From 9ecd69ebc88fb5d82a693e51eef0475c1a6b282e Mon Sep 17 00:00:00 2001 From: Andrew Stitcher Date: Mon, 2 Apr 2007 11:40:48 +0000 Subject: Fix for the most disruptive items in QPID-243. * All #include lines now use '""' rather than '<>' where appropriate. * #include lines within the qpid project use relative includes so that the same path will work in /usr/include when installed as part of the client libraries. * All the source code has now been rearranged to be under src in a directory analogous to the namespace of the classes in it. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@524769 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/cpp/Makefile.am | 2 +- qpid/cpp/bootstrap | 4 +- qpid/cpp/configure.ac | 12 +- qpid/cpp/gen/Makefile.am | 37 -- qpid/cpp/gen/make-gen-src-mk.sh | 30 -- .../templ.cpp/AMQP_ClientOperations.h.tmpl | 2 +- .../gentools/templ.cpp/AMQP_ClientProxy.cpp.tmpl | 4 +- .../cpp/gentools/templ.cpp/AMQP_ClientProxy.h.tmpl | 2 +- .../gentools/templ.cpp/AMQP_HighestVersion.h.tmpl | 2 +- .../templ.cpp/AMQP_MethodVersionMap.cpp.tmpl | 2 +- .../templ.cpp/AMQP_MethodVersionMap.h.tmpl | 2 +- .../templ.cpp/AMQP_ServerOperations.h.tmpl | 2 +- .../gentools/templ.cpp/AMQP_ServerProxy.cpp.tmpl | 4 +- .../cpp/gentools/templ.cpp/AMQP_ServerProxy.h.tmpl | 2 +- qpid/cpp/gentools/templ.cpp/MethodBodyClass.h.tmpl | 10 +- qpid/cpp/lib/Makefile.am | 1 - qpid/cpp/lib/broker/AccumulatedAck.cpp | 57 --- qpid/cpp/lib/broker/AccumulatedAck.h | 57 --- qpid/cpp/lib/broker/AutoDelete.cpp | 86 ----- qpid/cpp/lib/broker/AutoDelete.h | 55 --- qpid/cpp/lib/broker/Broker.cpp | 121 ------- qpid/cpp/lib/broker/Broker.h | 108 ------ qpid/cpp/lib/broker/BrokerAdapter.cpp | 388 -------------------- qpid/cpp/lib/broker/BrokerAdapter.h | 222 ------------ qpid/cpp/lib/broker/BrokerChannel.cpp | 346 ------------------ qpid/cpp/lib/broker/BrokerChannel.h | 159 --------- qpid/cpp/lib/broker/BrokerExchange.h | 51 --- qpid/cpp/lib/broker/BrokerMessage.cpp | 244 ------------- qpid/cpp/lib/broker/BrokerMessage.h | 137 ------- qpid/cpp/lib/broker/BrokerMessageBase.h | 182 ---------- qpid/cpp/lib/broker/BrokerMessageMessage.cpp | 305 ---------------- qpid/cpp/lib/broker/BrokerMessageMessage.h | 99 ------ qpid/cpp/lib/broker/BrokerQueue.cpp | 282 --------------- qpid/cpp/lib/broker/BrokerQueue.h | 151 -------- qpid/cpp/lib/broker/BrokerSingleton.cpp | 36 -- qpid/cpp/lib/broker/BrokerSingleton.h | 52 --- qpid/cpp/lib/broker/CompletionHandler.h | 39 -- qpid/cpp/lib/broker/Configuration.cpp | 252 ------------- qpid/cpp/lib/broker/Configuration.h | 171 --------- qpid/cpp/lib/broker/Connection.cpp | 128 ------- qpid/cpp/lib/broker/Connection.h | 108 ------ qpid/cpp/lib/broker/ConnectionFactory.cpp | 43 --- qpid/cpp/lib/broker/ConnectionFactory.h | 47 --- qpid/cpp/lib/broker/ConnectionToken.h | 38 -- qpid/cpp/lib/broker/Consumer.h | 37 -- qpid/cpp/lib/broker/Content.h | 64 ---- qpid/cpp/lib/broker/DeletingTxOp.cpp | 45 --- qpid/cpp/lib/broker/DeletingTxOp.h | 45 --- qpid/cpp/lib/broker/Deliverable.h | 37 -- qpid/cpp/lib/broker/DeliverableMessage.cpp | 33 -- qpid/cpp/lib/broker/DeliverableMessage.h | 41 --- qpid/cpp/lib/broker/DeliveryRecord.cpp | 87 ----- qpid/cpp/lib/broker/DeliveryRecord.h | 63 ---- qpid/cpp/lib/broker/DirectExchange.cpp | 71 ---- qpid/cpp/lib/broker/DirectExchange.h | 57 --- qpid/cpp/lib/broker/ExchangeRegistry.cpp | 76 ---- qpid/cpp/lib/broker/ExchangeRegistry.h | 47 --- qpid/cpp/lib/broker/FanOutExchange.cpp | 56 --- qpid/cpp/lib/broker/FanOutExchange.h | 60 ---- qpid/cpp/lib/broker/HandlerImpl.h | 71 ---- qpid/cpp/lib/broker/HeadersExchange.cpp | 119 ------- qpid/cpp/lib/broker/HeadersExchange.h | 65 ---- qpid/cpp/lib/broker/InMemoryContent.cpp | 72 ---- qpid/cpp/lib/broker/InMemoryContent.h | 45 --- qpid/cpp/lib/broker/LazyLoadedContent.cpp | 68 ---- qpid/cpp/lib/broker/LazyLoadedContent.h | 50 --- qpid/cpp/lib/broker/Makefile.am | 101 ------ qpid/cpp/lib/broker/MessageBuilder.cpp | 74 ---- qpid/cpp/lib/broker/MessageBuilder.h | 57 --- qpid/cpp/lib/broker/MessageHandlerImpl.cpp | 243 ------------- qpid/cpp/lib/broker/MessageHandlerImpl.h | 130 ------- qpid/cpp/lib/broker/MessageStore.h | 129 ------- qpid/cpp/lib/broker/MessageStoreModule.cpp | 109 ------ qpid/cpp/lib/broker/MessageStoreModule.h | 67 ---- qpid/cpp/lib/broker/NameGenerator.cpp | 32 -- qpid/cpp/lib/broker/NameGenerator.h | 39 -- qpid/cpp/lib/broker/NullMessageStore.cpp | 105 ------ qpid/cpp/lib/broker/NullMessageStore.h | 64 ---- qpid/cpp/lib/broker/Persistable.h | 62 ---- qpid/cpp/lib/broker/PersistableExchange.h | 44 --- qpid/cpp/lib/broker/PersistableMessage.h | 53 --- qpid/cpp/lib/broker/PersistableQueue.h | 45 --- qpid/cpp/lib/broker/Prefetch.h | 42 --- qpid/cpp/lib/broker/QueuePolicy.cpp | 69 ---- qpid/cpp/lib/broker/QueuePolicy.h | 54 --- qpid/cpp/lib/broker/QueueRegistry.cpp | 78 ---- qpid/cpp/lib/broker/QueueRegistry.h | 96 ----- qpid/cpp/lib/broker/RecoverableMessage.h | 57 --- qpid/cpp/lib/broker/RecoverableQueue.h | 49 --- qpid/cpp/lib/broker/RecoveryManager.h | 45 --- qpid/cpp/lib/broker/RecoveryManagerImpl.cpp | 131 ------- qpid/cpp/lib/broker/RecoveryManagerImpl.h | 55 --- qpid/cpp/lib/broker/Reference.cpp | 52 --- qpid/cpp/lib/broker/Reference.h | 114 ------ qpid/cpp/lib/broker/TopicExchange.cpp | 154 -------- qpid/cpp/lib/broker/TopicExchange.h | 100 ------ qpid/cpp/lib/broker/TransactionalStore.h | 57 --- qpid/cpp/lib/broker/TxAck.cpp | 54 --- qpid/cpp/lib/broker/TxAck.h | 57 --- qpid/cpp/lib/broker/TxBuffer.cpp | 55 --- qpid/cpp/lib/broker/TxBuffer.h | 107 ------ qpid/cpp/lib/broker/TxOp.h | 39 -- qpid/cpp/lib/broker/TxPublish.cpp | 60 ---- qpid/cpp/lib/broker/TxPublish.h | 78 ---- qpid/cpp/lib/client/AckMode.h | 102 ------ qpid/cpp/lib/client/BasicMessageChannel.cpp | 395 --------------------- qpid/cpp/lib/client/BasicMessageChannel.h | 91 ----- qpid/cpp/lib/client/ClientAdapter.cpp | 70 ---- qpid/cpp/lib/client/ClientAdapter.h | 66 ---- qpid/cpp/lib/client/ClientChannel.cpp | 340 ------------------ qpid/cpp/lib/client/ClientChannel.h | 352 ------------------ qpid/cpp/lib/client/ClientExchange.cpp | 34 -- qpid/cpp/lib/client/ClientExchange.h | 106 ------ qpid/cpp/lib/client/ClientMessage.h | 62 ---- qpid/cpp/lib/client/ClientQueue.cpp | 58 --- qpid/cpp/lib/client/ClientQueue.h | 103 ------ qpid/cpp/lib/client/Connection.cpp | 156 -------- qpid/cpp/lib/client/Connection.h | 179 ---------- qpid/cpp/lib/client/Connector.cpp | 188 ---------- qpid/cpp/lib/client/Connector.h | 98 ----- qpid/cpp/lib/client/IncomingMessage.cpp | 130 ------- qpid/cpp/lib/client/IncomingMessage.h | 114 ------ qpid/cpp/lib/client/Makefile.am | 37 -- qpid/cpp/lib/client/MessageChannel.h | 94 ----- qpid/cpp/lib/client/MessageListener.cpp | 24 -- qpid/cpp/lib/client/MessageListener.h | 49 --- qpid/cpp/lib/client/MethodBodyInstances.h | 100 ------ qpid/cpp/lib/client/ResponseHandler.cpp | 79 ----- qpid/cpp/lib/client/ResponseHandler.h | 75 ---- qpid/cpp/lib/client/ReturnedMessageHandler.cpp | 24 -- qpid/cpp/lib/client/ReturnedMessageHandler.h | 49 --- qpid/cpp/lib/common/Exception.cpp | 46 --- qpid/cpp/lib/common/Exception.h | 97 ----- qpid/cpp/lib/common/ExceptionHolder.cpp | 32 -- qpid/cpp/lib/common/ExceptionHolder.h | 67 ---- qpid/cpp/lib/common/Makefile.am | 143 -------- qpid/cpp/lib/common/QpidError.cpp | 42 --- qpid/cpp/lib/common/QpidError.h | 78 ---- qpid/cpp/lib/common/SharedObject.h | 55 --- qpid/cpp/lib/common/doxygen_mainpage.h | 45 --- qpid/cpp/lib/common/framing/AMQBody.cpp | 33 -- qpid/cpp/lib/common/framing/AMQBody.h | 59 --- qpid/cpp/lib/common/framing/AMQContentBody.cpp | 43 --- qpid/cpp/lib/common/framing/AMQContentBody.h | 53 --- qpid/cpp/lib/common/framing/AMQDataBlock.h | 42 --- qpid/cpp/lib/common/framing/AMQFrame.cpp | 139 -------- qpid/cpp/lib/common/framing/AMQFrame.h | 78 ---- qpid/cpp/lib/common/framing/AMQHeaderBody.cpp | 75 ---- qpid/cpp/lib/common/framing/AMQHeaderBody.h | 60 ---- qpid/cpp/lib/common/framing/AMQHeartbeatBody.cpp | 29 -- qpid/cpp/lib/common/framing/AMQHeartbeatBody.h | 47 --- qpid/cpp/lib/common/framing/AMQMethodBody.cpp | 59 --- qpid/cpp/lib/common/framing/AMQMethodBody.h | 84 ----- qpid/cpp/lib/common/framing/AMQRequestBody.cpp | 66 ---- qpid/cpp/lib/common/framing/AMQRequestBody.h | 78 ---- qpid/cpp/lib/common/framing/AMQResponseBody.cpp | 65 ---- qpid/cpp/lib/common/framing/AMQResponseBody.h | 85 ----- .../lib/common/framing/BasicHeaderProperties.cpp | 103 ------ .../cpp/lib/common/framing/BasicHeaderProperties.h | 115 ------ qpid/cpp/lib/common/framing/BodyHandler.cpp | 60 ---- qpid/cpp/lib/common/framing/BodyHandler.h | 61 ---- qpid/cpp/lib/common/framing/Buffer.cpp | 183 ---------- qpid/cpp/lib/common/framing/Buffer.h | 86 ----- qpid/cpp/lib/common/framing/ChannelAdapter.cpp | 99 ------ qpid/cpp/lib/common/framing/ChannelAdapter.h | 105 ------ qpid/cpp/lib/common/framing/FieldTable.cpp | 150 -------- qpid/cpp/lib/common/framing/FieldTable.h | 90 ----- qpid/cpp/lib/common/framing/FramingContent.cpp | 75 ---- qpid/cpp/lib/common/framing/FramingContent.h | 41 --- qpid/cpp/lib/common/framing/HeaderProperties.h | 46 --- qpid/cpp/lib/common/framing/InitiationHandler.cpp | 24 -- qpid/cpp/lib/common/framing/InitiationHandler.h | 41 --- qpid/cpp/lib/common/framing/InputHandler.h | 39 -- qpid/cpp/lib/common/framing/MethodContext.cpp | 31 -- qpid/cpp/lib/common/framing/MethodContext.h | 75 ---- qpid/cpp/lib/common/framing/OutputHandler.h | 39 -- qpid/cpp/lib/common/framing/ProtocolInitiation.cpp | 63 ---- qpid/cpp/lib/common/framing/ProtocolInitiation.h | 54 --- qpid/cpp/lib/common/framing/ProtocolVersion.cpp | 44 --- qpid/cpp/lib/common/framing/ProtocolVersion.h | 57 --- .../common/framing/ProtocolVersionException.cpp | 33 -- .../lib/common/framing/ProtocolVersionException.h | 56 --- qpid/cpp/lib/common/framing/Proxy.cpp | 32 -- qpid/cpp/lib/common/framing/Proxy.h | 51 --- qpid/cpp/lib/common/framing/Requester.cpp | 40 --- qpid/cpp/lib/common/framing/Requester.h | 67 ---- qpid/cpp/lib/common/framing/Responder.cpp | 43 --- qpid/cpp/lib/common/framing/Responder.h | 61 ---- qpid/cpp/lib/common/framing/Value.cpp | 122 ------- qpid/cpp/lib/common/framing/Value.h | 171 --------- qpid/cpp/lib/common/framing/amqp_framing.h | 36 -- qpid/cpp/lib/common/framing/amqp_types.h | 57 --- qpid/cpp/lib/common/framing/amqp_types_full.h | 36 -- qpid/cpp/lib/common/shared_ptr.h | 36 -- qpid/cpp/lib/common/sys/Acceptor.h | 47 --- qpid/cpp/lib/common/sys/AtomicCount.h | 53 --- qpid/cpp/lib/common/sys/Condition.h | 128 ------- qpid/cpp/lib/common/sys/ConnectionInputHandler.h | 45 --- .../lib/common/sys/ConnectionInputHandlerFactory.h | 46 --- qpid/cpp/lib/common/sys/ConnectionOutputHandler.h | 41 --- qpid/cpp/lib/common/sys/Module.h | 161 --------- qpid/cpp/lib/common/sys/Monitor.h | 55 --- qpid/cpp/lib/common/sys/Mutex.h | 165 --------- qpid/cpp/lib/common/sys/ProducerConsumer.cpp | 141 -------- qpid/cpp/lib/common/sys/ProducerConsumer.h | 165 --------- qpid/cpp/lib/common/sys/Runnable.cpp | 32 -- qpid/cpp/lib/common/sys/Runnable.h | 50 --- qpid/cpp/lib/common/sys/ScopedIncrement.h | 59 --- qpid/cpp/lib/common/sys/ShutdownHandler.h | 37 -- qpid/cpp/lib/common/sys/Socket.h | 88 ----- qpid/cpp/lib/common/sys/Thread.h | 142 -------- qpid/cpp/lib/common/sys/ThreadSafeQueue.h | 98 ----- qpid/cpp/lib/common/sys/Time.cpp | 60 ---- qpid/cpp/lib/common/sys/Time.h | 58 --- qpid/cpp/lib/common/sys/TimeoutHandler.h | 39 -- qpid/cpp/lib/common/sys/apr/APRAcceptor.cpp | 120 ------- qpid/cpp/lib/common/sys/apr/APRBase.cpp | 90 ----- qpid/cpp/lib/common/sys/apr/APRBase.h | 78 ---- qpid/cpp/lib/common/sys/apr/APRPool.cpp | 41 --- qpid/cpp/lib/common/sys/apr/APRPool.h | 50 --- qpid/cpp/lib/common/sys/apr/APRSocket.cpp | 78 ---- qpid/cpp/lib/common/sys/apr/APRSocket.h | 48 --- qpid/cpp/lib/common/sys/apr/LFProcessor.cpp | 179 ---------- qpid/cpp/lib/common/sys/apr/LFProcessor.h | 121 ------- qpid/cpp/lib/common/sys/apr/LFSessionContext.cpp | 179 ---------- qpid/cpp/lib/common/sys/apr/LFSessionContext.h | 90 ----- qpid/cpp/lib/common/sys/apr/Socket.cpp | 86 ----- qpid/cpp/lib/common/sys/apr/Thread.cpp | 33 -- qpid/cpp/lib/common/sys/posix/EventChannel.cpp | 325 ----------------- qpid/cpp/lib/common/sys/posix/EventChannel.h | 176 --------- .../lib/common/sys/posix/EventChannelAcceptor.cpp | 149 -------- .../common/sys/posix/EventChannelConnection.cpp | 229 ------------ .../lib/common/sys/posix/EventChannelConnection.h | 102 ------ .../lib/common/sys/posix/EventChannelThreads.cpp | 119 ------- .../cpp/lib/common/sys/posix/EventChannelThreads.h | 92 ----- qpid/cpp/lib/common/sys/posix/PosixAcceptor.cpp | 48 --- qpid/cpp/lib/common/sys/posix/Socket.cpp | 118 ------ qpid/cpp/lib/common/sys/posix/Thread.cpp | 28 -- qpid/cpp/lib/common/sys/posix/check.cpp | 39 -- qpid/cpp/lib/common/sys/posix/check.h | 62 ---- qpid/cpp/src/Exception.cpp | 46 +++ qpid/cpp/src/Exception.h | 97 +++++ qpid/cpp/src/ExceptionHolder.cpp | 32 ++ qpid/cpp/src/ExceptionHolder.h | 67 ++++ qpid/cpp/src/Makefile.am | 155 +++++++- qpid/cpp/src/QpidError.cpp | 42 +++ qpid/cpp/src/QpidError.h | 78 ++++ qpid/cpp/src/SharedObject.h | 55 +++ qpid/cpp/src/broker/AccumulatedAck.cpp | 57 +++ qpid/cpp/src/broker/AccumulatedAck.h | 57 +++ qpid/cpp/src/broker/AutoDelete.cpp | 86 +++++ qpid/cpp/src/broker/AutoDelete.h | 55 +++ qpid/cpp/src/broker/Broker.cpp | 121 +++++++ qpid/cpp/src/broker/Broker.h | 108 ++++++ qpid/cpp/src/broker/BrokerAdapter.cpp | 388 ++++++++++++++++++++ qpid/cpp/src/broker/BrokerAdapter.h | 222 ++++++++++++ qpid/cpp/src/broker/BrokerChannel.cpp | 346 ++++++++++++++++++ qpid/cpp/src/broker/BrokerChannel.h | 159 +++++++++ qpid/cpp/src/broker/BrokerExchange.h | 51 +++ qpid/cpp/src/broker/BrokerMessage.cpp | 244 +++++++++++++ qpid/cpp/src/broker/BrokerMessage.h | 137 +++++++ qpid/cpp/src/broker/BrokerMessageBase.h | 182 ++++++++++ qpid/cpp/src/broker/BrokerMessageMessage.cpp | 305 ++++++++++++++++ qpid/cpp/src/broker/BrokerMessageMessage.h | 99 ++++++ qpid/cpp/src/broker/BrokerQueue.cpp | 282 +++++++++++++++ qpid/cpp/src/broker/BrokerQueue.h | 151 ++++++++ qpid/cpp/src/broker/BrokerSingleton.cpp | 36 ++ qpid/cpp/src/broker/BrokerSingleton.h | 52 +++ qpid/cpp/src/broker/CompletionHandler.h | 39 ++ qpid/cpp/src/broker/Configuration.cpp | 252 +++++++++++++ qpid/cpp/src/broker/Configuration.h | 171 +++++++++ qpid/cpp/src/broker/Connection.cpp | 128 +++++++ qpid/cpp/src/broker/Connection.h | 108 ++++++ qpid/cpp/src/broker/ConnectionFactory.cpp | 43 +++ qpid/cpp/src/broker/ConnectionFactory.h | 47 +++ qpid/cpp/src/broker/ConnectionToken.h | 38 ++ qpid/cpp/src/broker/Consumer.h | 37 ++ qpid/cpp/src/broker/Content.h | 64 ++++ qpid/cpp/src/broker/DeletingTxOp.cpp | 45 +++ qpid/cpp/src/broker/DeletingTxOp.h | 45 +++ qpid/cpp/src/broker/Deliverable.h | 37 ++ qpid/cpp/src/broker/DeliverableMessage.cpp | 33 ++ qpid/cpp/src/broker/DeliverableMessage.h | 41 +++ qpid/cpp/src/broker/DeliveryRecord.cpp | 87 +++++ qpid/cpp/src/broker/DeliveryRecord.h | 63 ++++ qpid/cpp/src/broker/DirectExchange.cpp | 71 ++++ qpid/cpp/src/broker/DirectExchange.h | 57 +++ qpid/cpp/src/broker/ExchangeRegistry.cpp | 76 ++++ qpid/cpp/src/broker/ExchangeRegistry.h | 47 +++ qpid/cpp/src/broker/FanOutExchange.cpp | 56 +++ qpid/cpp/src/broker/FanOutExchange.h | 60 ++++ qpid/cpp/src/broker/HandlerImpl.h | 71 ++++ qpid/cpp/src/broker/HeadersExchange.cpp | 119 +++++++ qpid/cpp/src/broker/HeadersExchange.h | 65 ++++ qpid/cpp/src/broker/InMemoryContent.cpp | 72 ++++ qpid/cpp/src/broker/InMemoryContent.h | 45 +++ qpid/cpp/src/broker/LazyLoadedContent.cpp | 68 ++++ qpid/cpp/src/broker/LazyLoadedContent.h | 50 +++ qpid/cpp/src/broker/Makefile.am | 97 +++++ qpid/cpp/src/broker/MessageBuilder.cpp | 74 ++++ qpid/cpp/src/broker/MessageBuilder.h | 57 +++ qpid/cpp/src/broker/MessageHandlerImpl.cpp | 243 +++++++++++++ qpid/cpp/src/broker/MessageHandlerImpl.h | 130 +++++++ qpid/cpp/src/broker/MessageStore.h | 129 +++++++ qpid/cpp/src/broker/MessageStoreModule.cpp | 109 ++++++ qpid/cpp/src/broker/MessageStoreModule.h | 67 ++++ qpid/cpp/src/broker/NameGenerator.cpp | 32 ++ qpid/cpp/src/broker/NameGenerator.h | 39 ++ qpid/cpp/src/broker/NullMessageStore.cpp | 105 ++++++ qpid/cpp/src/broker/NullMessageStore.h | 64 ++++ qpid/cpp/src/broker/Persistable.h | 62 ++++ qpid/cpp/src/broker/PersistableExchange.h | 44 +++ qpid/cpp/src/broker/PersistableMessage.h | 53 +++ qpid/cpp/src/broker/PersistableQueue.h | 45 +++ qpid/cpp/src/broker/Prefetch.h | 42 +++ qpid/cpp/src/broker/QueuePolicy.cpp | 69 ++++ qpid/cpp/src/broker/QueuePolicy.h | 54 +++ qpid/cpp/src/broker/QueueRegistry.cpp | 78 ++++ qpid/cpp/src/broker/QueueRegistry.h | 96 +++++ qpid/cpp/src/broker/RecoverableMessage.h | 57 +++ qpid/cpp/src/broker/RecoverableQueue.h | 49 +++ qpid/cpp/src/broker/RecoveryManager.h | 45 +++ qpid/cpp/src/broker/RecoveryManagerImpl.cpp | 131 +++++++ qpid/cpp/src/broker/RecoveryManagerImpl.h | 55 +++ qpid/cpp/src/broker/Reference.cpp | 52 +++ qpid/cpp/src/broker/Reference.h | 114 ++++++ qpid/cpp/src/broker/TopicExchange.cpp | 154 ++++++++ qpid/cpp/src/broker/TopicExchange.h | 100 ++++++ qpid/cpp/src/broker/TransactionalStore.h | 57 +++ qpid/cpp/src/broker/TxAck.cpp | 54 +++ qpid/cpp/src/broker/TxAck.h | 57 +++ qpid/cpp/src/broker/TxBuffer.cpp | 55 +++ qpid/cpp/src/broker/TxBuffer.h | 107 ++++++ qpid/cpp/src/broker/TxOp.h | 39 ++ qpid/cpp/src/broker/TxPublish.cpp | 60 ++++ qpid/cpp/src/broker/TxPublish.h | 78 ++++ qpid/cpp/src/client/AckMode.h | 102 ++++++ qpid/cpp/src/client/BasicMessageChannel.cpp | 395 +++++++++++++++++++++ qpid/cpp/src/client/BasicMessageChannel.h | 91 +++++ qpid/cpp/src/client/ClientAdapter.cpp | 70 ++++ qpid/cpp/src/client/ClientAdapter.h | 66 ++++ qpid/cpp/src/client/ClientChannel.cpp | 340 ++++++++++++++++++ qpid/cpp/src/client/ClientChannel.h | 352 ++++++++++++++++++ qpid/cpp/src/client/ClientExchange.cpp | 34 ++ qpid/cpp/src/client/ClientExchange.h | 106 ++++++ qpid/cpp/src/client/ClientMessage.h | 62 ++++ qpid/cpp/src/client/ClientQueue.cpp | 58 +++ qpid/cpp/src/client/ClientQueue.h | 103 ++++++ qpid/cpp/src/client/Connection.cpp | 156 ++++++++ qpid/cpp/src/client/Connection.h | 179 ++++++++++ qpid/cpp/src/client/Connector.cpp | 188 ++++++++++ qpid/cpp/src/client/Connector.h | 98 +++++ qpid/cpp/src/client/IncomingMessage.cpp | 130 +++++++ qpid/cpp/src/client/IncomingMessage.h | 114 ++++++ qpid/cpp/src/client/Makefile.am | 34 ++ qpid/cpp/src/client/MessageChannel.h | 94 +++++ qpid/cpp/src/client/MessageListener.cpp | 24 ++ qpid/cpp/src/client/MessageListener.h | 49 +++ qpid/cpp/src/client/MethodBodyInstances.h | 100 ++++++ qpid/cpp/src/client/ResponseHandler.cpp | 79 +++++ qpid/cpp/src/client/ResponseHandler.h | 75 ++++ qpid/cpp/src/client/ReturnedMessageHandler.cpp | 24 ++ qpid/cpp/src/client/ReturnedMessageHandler.h | 49 +++ qpid/cpp/src/doxygen_mainpage.h | 45 +++ qpid/cpp/src/framing/AMQBody.cpp | 33 ++ qpid/cpp/src/framing/AMQBody.h | 59 +++ qpid/cpp/src/framing/AMQContentBody.cpp | 43 +++ qpid/cpp/src/framing/AMQContentBody.h | 53 +++ qpid/cpp/src/framing/AMQDataBlock.h | 42 +++ qpid/cpp/src/framing/AMQFrame.cpp | 139 ++++++++ qpid/cpp/src/framing/AMQFrame.h | 78 ++++ qpid/cpp/src/framing/AMQHeaderBody.cpp | 75 ++++ qpid/cpp/src/framing/AMQHeaderBody.h | 60 ++++ qpid/cpp/src/framing/AMQHeartbeatBody.cpp | 29 ++ qpid/cpp/src/framing/AMQHeartbeatBody.h | 47 +++ qpid/cpp/src/framing/AMQMethodBody.cpp | 59 +++ qpid/cpp/src/framing/AMQMethodBody.h | 84 +++++ qpid/cpp/src/framing/AMQRequestBody.cpp | 66 ++++ qpid/cpp/src/framing/AMQRequestBody.h | 78 ++++ qpid/cpp/src/framing/AMQResponseBody.cpp | 65 ++++ qpid/cpp/src/framing/AMQResponseBody.h | 85 +++++ qpid/cpp/src/framing/BasicHeaderProperties.cpp | 103 ++++++ qpid/cpp/src/framing/BasicHeaderProperties.h | 115 ++++++ qpid/cpp/src/framing/BodyHandler.cpp | 60 ++++ qpid/cpp/src/framing/BodyHandler.h | 61 ++++ qpid/cpp/src/framing/Buffer.cpp | 183 ++++++++++ qpid/cpp/src/framing/Buffer.h | 86 +++++ qpid/cpp/src/framing/ChannelAdapter.cpp | 99 ++++++ qpid/cpp/src/framing/ChannelAdapter.h | 105 ++++++ qpid/cpp/src/framing/FieldTable.cpp | 150 ++++++++ qpid/cpp/src/framing/FieldTable.h | 90 +++++ qpid/cpp/src/framing/FramingContent.cpp | 75 ++++ qpid/cpp/src/framing/FramingContent.h | 41 +++ qpid/cpp/src/framing/HeaderProperties.h | 46 +++ qpid/cpp/src/framing/InitiationHandler.cpp | 24 ++ qpid/cpp/src/framing/InitiationHandler.h | 41 +++ qpid/cpp/src/framing/InputHandler.h | 39 ++ qpid/cpp/src/framing/MethodContext.cpp | 31 ++ qpid/cpp/src/framing/MethodContext.h | 75 ++++ qpid/cpp/src/framing/OutputHandler.h | 39 ++ qpid/cpp/src/framing/ProtocolInitiation.cpp | 63 ++++ qpid/cpp/src/framing/ProtocolInitiation.h | 54 +++ qpid/cpp/src/framing/ProtocolVersion.cpp | 44 +++ qpid/cpp/src/framing/ProtocolVersion.h | 57 +++ qpid/cpp/src/framing/ProtocolVersionException.cpp | 33 ++ qpid/cpp/src/framing/ProtocolVersionException.h | 56 +++ qpid/cpp/src/framing/Proxy.cpp | 32 ++ qpid/cpp/src/framing/Proxy.h | 51 +++ qpid/cpp/src/framing/Requester.cpp | 40 +++ qpid/cpp/src/framing/Requester.h | 67 ++++ qpid/cpp/src/framing/Responder.cpp | 43 +++ qpid/cpp/src/framing/Responder.h | 61 ++++ qpid/cpp/src/framing/Value.cpp | 122 +++++++ qpid/cpp/src/framing/Value.h | 171 +++++++++ qpid/cpp/src/framing/amqp_framing.h | 36 ++ qpid/cpp/src/framing/amqp_types.h | 57 +++ qpid/cpp/src/framing/amqp_types_full.h | 36 ++ qpid/cpp/src/gen/Makefile.am | 37 ++ qpid/cpp/src/gen/make-gen-src-mk.sh | 30 ++ qpid/cpp/src/qpidd.cpp | 6 +- qpid/cpp/src/shared_ptr.h | 36 ++ qpid/cpp/src/sys/Acceptor.h | 47 +++ qpid/cpp/src/sys/AtomicCount.h | 53 +++ qpid/cpp/src/sys/Condition.h | 128 +++++++ qpid/cpp/src/sys/ConnectionInputHandler.h | 45 +++ qpid/cpp/src/sys/ConnectionInputHandlerFactory.h | 46 +++ qpid/cpp/src/sys/ConnectionOutputHandler.h | 41 +++ qpid/cpp/src/sys/Module.h | 161 +++++++++ qpid/cpp/src/sys/Monitor.h | 55 +++ qpid/cpp/src/sys/Mutex.h | 165 +++++++++ qpid/cpp/src/sys/ProducerConsumer.cpp | 141 ++++++++ qpid/cpp/src/sys/ProducerConsumer.h | 165 +++++++++ qpid/cpp/src/sys/Runnable.cpp | 32 ++ qpid/cpp/src/sys/Runnable.h | 50 +++ qpid/cpp/src/sys/ScopedIncrement.h | 59 +++ qpid/cpp/src/sys/ShutdownHandler.h | 37 ++ qpid/cpp/src/sys/Socket.h | 88 +++++ qpid/cpp/src/sys/Thread.h | 142 ++++++++ qpid/cpp/src/sys/ThreadSafeQueue.h | 98 +++++ qpid/cpp/src/sys/Time.cpp | 60 ++++ qpid/cpp/src/sys/Time.h | 58 +++ qpid/cpp/src/sys/TimeoutHandler.h | 39 ++ qpid/cpp/src/sys/apr/APRAcceptor.cpp | 120 +++++++ qpid/cpp/src/sys/apr/APRBase.cpp | 90 +++++ qpid/cpp/src/sys/apr/APRBase.h | 78 ++++ qpid/cpp/src/sys/apr/APRPool.cpp | 41 +++ qpid/cpp/src/sys/apr/APRPool.h | 50 +++ qpid/cpp/src/sys/apr/APRSocket.cpp | 78 ++++ qpid/cpp/src/sys/apr/APRSocket.h | 48 +++ qpid/cpp/src/sys/apr/LFProcessor.cpp | 179 ++++++++++ qpid/cpp/src/sys/apr/LFProcessor.h | 121 +++++++ qpid/cpp/src/sys/apr/LFSessionContext.cpp | 179 ++++++++++ qpid/cpp/src/sys/apr/LFSessionContext.h | 90 +++++ qpid/cpp/src/sys/apr/Socket.cpp | 86 +++++ qpid/cpp/src/sys/apr/Thread.cpp | 33 ++ qpid/cpp/src/sys/posix/EventChannel.cpp | 325 +++++++++++++++++ qpid/cpp/src/sys/posix/EventChannel.h | 176 +++++++++ qpid/cpp/src/sys/posix/EventChannelAcceptor.cpp | 149 ++++++++ qpid/cpp/src/sys/posix/EventChannelConnection.cpp | 229 ++++++++++++ qpid/cpp/src/sys/posix/EventChannelConnection.h | 102 ++++++ qpid/cpp/src/sys/posix/EventChannelThreads.cpp | 119 +++++++ qpid/cpp/src/sys/posix/EventChannelThreads.h | 92 +++++ qpid/cpp/src/sys/posix/PosixAcceptor.cpp | 48 +++ qpid/cpp/src/sys/posix/Socket.cpp | 118 ++++++ qpid/cpp/src/sys/posix/Thread.cpp | 28 ++ qpid/cpp/src/sys/posix/check.cpp | 39 ++ qpid/cpp/src/sys/posix/check.h | 62 ++++ qpid/cpp/src/tests/.vg-supp | 18 + qpid/cpp/src/tests/APRBaseTest.cpp | 47 +++ qpid/cpp/src/tests/AccumulatedAckTest.cpp | 107 ++++++ qpid/cpp/src/tests/BrokerChannelTest.cpp | 357 +++++++++++++++++++ qpid/cpp/src/tests/ClientChannelTest.cpp | 193 ++++++++++ qpid/cpp/src/tests/ConfigurationTest.cpp | 98 +++++ qpid/cpp/src/tests/EventChannelConnectionTest.cpp | 109 ++++++ qpid/cpp/src/tests/EventChannelTest.cpp | 187 ++++++++++ qpid/cpp/src/tests/EventChannelThreadsTest.cpp | 247 +++++++++++++ qpid/cpp/src/tests/ExchangeTest.cpp | 73 ++++ qpid/cpp/src/tests/FieldTableTest.cpp | 55 +++ qpid/cpp/src/tests/FramingTest.cpp | 381 ++++++++++++++++++++ qpid/cpp/src/tests/HeaderTest.cpp | 141 ++++++++ qpid/cpp/src/tests/HeadersExchangeTest.cpp | 115 ++++++ qpid/cpp/src/tests/InMemoryContentTest.cpp | 92 +++++ qpid/cpp/src/tests/InProcessBroker.h | 163 +++++++++ qpid/cpp/src/tests/LazyLoadedContentTest.cpp | 112 ++++++ qpid/cpp/src/tests/Makefile.am | 117 ++++++ qpid/cpp/src/tests/MessageBuilderTest.cpp | 225 ++++++++++++ qpid/cpp/src/tests/MessageHandlerTest.cpp | 57 +++ qpid/cpp/src/tests/MessageTest.cpp | 88 +++++ qpid/cpp/src/tests/MockChannel.h | 70 ++++ qpid/cpp/src/tests/MockConnectionInputHandler.h | 113 ++++++ qpid/cpp/src/tests/ProducerConsumerTest.cpp | 284 +++++++++++++++ qpid/cpp/src/tests/QueuePolicyTest.cpp | 89 +++++ qpid/cpp/src/tests/QueueRegistryTest.cpp | 95 +++++ qpid/cpp/src/tests/QueueTest.cpp | 149 ++++++++ qpid/cpp/src/tests/ReferenceTest.cpp | 102 ++++++ qpid/cpp/src/tests/TopicExchangeTest.cpp | 200 +++++++++++ qpid/cpp/src/tests/TxAckTest.cpp | 113 ++++++ qpid/cpp/src/tests/TxBufferTest.cpp | 269 ++++++++++++++ qpid/cpp/src/tests/TxPublishTest.cpp | 108 ++++++ qpid/cpp/src/tests/ValueTest.cpp | 102 ++++++ qpid/cpp/src/tests/client_test.cpp | 138 +++++++ qpid/cpp/src/tests/dlclose_noop.c | 30 ++ qpid/cpp/src/tests/echo_service.cpp | 230 ++++++++++++ qpid/cpp/src/tests/examples.Makefile | 66 ++++ qpid/cpp/src/tests/examples.README | 18 + qpid/cpp/src/tests/kill_broker | 3 + qpid/cpp/src/tests/python_tests | 8 + qpid/cpp/src/tests/qpid_test_plugin.h | 43 +++ qpid/cpp/src/tests/quick_topictest | 7 + qpid/cpp/src/tests/run-python-tests | 0 qpid/cpp/src/tests/run-unit-tests | 37 ++ qpid/cpp/src/tests/setup | 81 +++++ qpid/cpp/src/tests/start_broker | 14 + qpid/cpp/src/tests/topic_listener.cpp | 217 +++++++++++ qpid/cpp/src/tests/topic_publisher.cpp | 287 +++++++++++++++ qpid/cpp/src/tests/topictest | 39 ++ qpid/cpp/tests/.vg-supp | 18 - qpid/cpp/tests/APRBaseTest.cpp | 47 --- qpid/cpp/tests/AccumulatedAckTest.cpp | 107 ------ qpid/cpp/tests/BrokerChannelTest.cpp | 357 ------------------- qpid/cpp/tests/ClientChannelTest.cpp | 193 ---------- qpid/cpp/tests/ConfigurationTest.cpp | 98 ----- qpid/cpp/tests/EventChannelConnectionTest.cpp | 109 ------ qpid/cpp/tests/EventChannelTest.cpp | 187 ---------- qpid/cpp/tests/EventChannelThreadsTest.cpp | 247 ------------- qpid/cpp/tests/ExchangeTest.cpp | 73 ---- qpid/cpp/tests/FieldTableTest.cpp | 55 --- qpid/cpp/tests/FramingTest.cpp | 381 -------------------- qpid/cpp/tests/HeaderTest.cpp | 141 -------- qpid/cpp/tests/HeadersExchangeTest.cpp | 115 ------ qpid/cpp/tests/InMemoryContentTest.cpp | 92 ----- qpid/cpp/tests/InProcessBroker.h | 163 --------- qpid/cpp/tests/LazyLoadedContentTest.cpp | 112 ------ qpid/cpp/tests/Makefile.am | 123 ------- qpid/cpp/tests/MessageBuilderTest.cpp | 225 ------------ qpid/cpp/tests/MessageHandlerTest.cpp | 57 --- qpid/cpp/tests/MessageTest.cpp | 88 ----- qpid/cpp/tests/MockChannel.h | 70 ---- qpid/cpp/tests/MockConnectionInputHandler.h | 113 ------ qpid/cpp/tests/ProducerConsumerTest.cpp | 284 --------------- qpid/cpp/tests/QueuePolicyTest.cpp | 89 ----- qpid/cpp/tests/QueueRegistryTest.cpp | 95 ----- qpid/cpp/tests/QueueTest.cpp | 149 -------- qpid/cpp/tests/ReferenceTest.cpp | 102 ------ qpid/cpp/tests/TopicExchangeTest.cpp | 200 ----------- qpid/cpp/tests/TxAckTest.cpp | 113 ------ qpid/cpp/tests/TxBufferTest.cpp | 269 -------------- qpid/cpp/tests/TxPublishTest.cpp | 108 ------ qpid/cpp/tests/ValueTest.cpp | 102 ------ qpid/cpp/tests/client_test.cpp | 138 ------- qpid/cpp/tests/dlclose_noop.c | 30 -- qpid/cpp/tests/echo_service.cpp | 230 ------------ qpid/cpp/tests/examples.Makefile | 66 ---- qpid/cpp/tests/examples.README | 18 - qpid/cpp/tests/kill_broker | 3 - qpid/cpp/tests/python_tests | 8 - qpid/cpp/tests/qpid_test_plugin.h | 43 --- qpid/cpp/tests/quick_topictest | 7 - qpid/cpp/tests/run-python-tests | 0 qpid/cpp/tests/run-unit-tests | 37 -- qpid/cpp/tests/setup | 81 ----- qpid/cpp/tests/start_broker | 14 - qpid/cpp/tests/topic_listener.cpp | 217 ----------- qpid/cpp/tests/topic_publisher.cpp | 287 --------------- qpid/cpp/tests/topictest | 39 -- 565 files changed, 25999 insertions(+), 26025 deletions(-) delete mode 100644 qpid/cpp/gen/Makefile.am delete mode 100755 qpid/cpp/gen/make-gen-src-mk.sh delete mode 100644 qpid/cpp/lib/Makefile.am delete mode 100644 qpid/cpp/lib/broker/AccumulatedAck.cpp delete mode 100644 qpid/cpp/lib/broker/AccumulatedAck.h delete mode 100644 qpid/cpp/lib/broker/AutoDelete.cpp delete mode 100644 qpid/cpp/lib/broker/AutoDelete.h delete mode 100644 qpid/cpp/lib/broker/Broker.cpp delete mode 100644 qpid/cpp/lib/broker/Broker.h delete mode 100644 qpid/cpp/lib/broker/BrokerAdapter.cpp delete mode 100644 qpid/cpp/lib/broker/BrokerAdapter.h delete mode 100644 qpid/cpp/lib/broker/BrokerChannel.cpp delete mode 100644 qpid/cpp/lib/broker/BrokerChannel.h delete mode 100644 qpid/cpp/lib/broker/BrokerExchange.h delete mode 100644 qpid/cpp/lib/broker/BrokerMessage.cpp delete mode 100644 qpid/cpp/lib/broker/BrokerMessage.h delete mode 100644 qpid/cpp/lib/broker/BrokerMessageBase.h delete mode 100644 qpid/cpp/lib/broker/BrokerMessageMessage.cpp delete mode 100644 qpid/cpp/lib/broker/BrokerMessageMessage.h delete mode 100644 qpid/cpp/lib/broker/BrokerQueue.cpp delete mode 100644 qpid/cpp/lib/broker/BrokerQueue.h delete mode 100644 qpid/cpp/lib/broker/BrokerSingleton.cpp delete mode 100644 qpid/cpp/lib/broker/BrokerSingleton.h delete mode 100644 qpid/cpp/lib/broker/CompletionHandler.h delete mode 100644 qpid/cpp/lib/broker/Configuration.cpp delete mode 100644 qpid/cpp/lib/broker/Configuration.h delete mode 100644 qpid/cpp/lib/broker/Connection.cpp delete mode 100644 qpid/cpp/lib/broker/Connection.h delete mode 100644 qpid/cpp/lib/broker/ConnectionFactory.cpp delete mode 100644 qpid/cpp/lib/broker/ConnectionFactory.h delete mode 100644 qpid/cpp/lib/broker/ConnectionToken.h delete mode 100644 qpid/cpp/lib/broker/Consumer.h delete mode 100644 qpid/cpp/lib/broker/Content.h delete mode 100644 qpid/cpp/lib/broker/DeletingTxOp.cpp delete mode 100644 qpid/cpp/lib/broker/DeletingTxOp.h delete mode 100644 qpid/cpp/lib/broker/Deliverable.h delete mode 100644 qpid/cpp/lib/broker/DeliverableMessage.cpp delete mode 100644 qpid/cpp/lib/broker/DeliverableMessage.h delete mode 100644 qpid/cpp/lib/broker/DeliveryRecord.cpp delete mode 100644 qpid/cpp/lib/broker/DeliveryRecord.h delete mode 100644 qpid/cpp/lib/broker/DirectExchange.cpp delete mode 100644 qpid/cpp/lib/broker/DirectExchange.h delete mode 100644 qpid/cpp/lib/broker/ExchangeRegistry.cpp delete mode 100644 qpid/cpp/lib/broker/ExchangeRegistry.h delete mode 100644 qpid/cpp/lib/broker/FanOutExchange.cpp delete mode 100644 qpid/cpp/lib/broker/FanOutExchange.h delete mode 100644 qpid/cpp/lib/broker/HandlerImpl.h delete mode 100644 qpid/cpp/lib/broker/HeadersExchange.cpp delete mode 100644 qpid/cpp/lib/broker/HeadersExchange.h delete mode 100644 qpid/cpp/lib/broker/InMemoryContent.cpp delete mode 100644 qpid/cpp/lib/broker/InMemoryContent.h delete mode 100644 qpid/cpp/lib/broker/LazyLoadedContent.cpp delete mode 100644 qpid/cpp/lib/broker/LazyLoadedContent.h delete mode 100644 qpid/cpp/lib/broker/Makefile.am delete mode 100644 qpid/cpp/lib/broker/MessageBuilder.cpp delete mode 100644 qpid/cpp/lib/broker/MessageBuilder.h delete mode 100644 qpid/cpp/lib/broker/MessageHandlerImpl.cpp delete mode 100644 qpid/cpp/lib/broker/MessageHandlerImpl.h delete mode 100644 qpid/cpp/lib/broker/MessageStore.h delete mode 100644 qpid/cpp/lib/broker/MessageStoreModule.cpp delete mode 100644 qpid/cpp/lib/broker/MessageStoreModule.h delete mode 100644 qpid/cpp/lib/broker/NameGenerator.cpp delete mode 100644 qpid/cpp/lib/broker/NameGenerator.h delete mode 100644 qpid/cpp/lib/broker/NullMessageStore.cpp delete mode 100644 qpid/cpp/lib/broker/NullMessageStore.h delete mode 100644 qpid/cpp/lib/broker/Persistable.h delete mode 100644 qpid/cpp/lib/broker/PersistableExchange.h delete mode 100644 qpid/cpp/lib/broker/PersistableMessage.h delete mode 100644 qpid/cpp/lib/broker/PersistableQueue.h delete mode 100644 qpid/cpp/lib/broker/Prefetch.h delete mode 100644 qpid/cpp/lib/broker/QueuePolicy.cpp delete mode 100644 qpid/cpp/lib/broker/QueuePolicy.h delete mode 100644 qpid/cpp/lib/broker/QueueRegistry.cpp delete mode 100644 qpid/cpp/lib/broker/QueueRegistry.h delete mode 100644 qpid/cpp/lib/broker/RecoverableMessage.h delete mode 100644 qpid/cpp/lib/broker/RecoverableQueue.h delete mode 100644 qpid/cpp/lib/broker/RecoveryManager.h delete mode 100644 qpid/cpp/lib/broker/RecoveryManagerImpl.cpp delete mode 100644 qpid/cpp/lib/broker/RecoveryManagerImpl.h delete mode 100644 qpid/cpp/lib/broker/Reference.cpp delete mode 100644 qpid/cpp/lib/broker/Reference.h delete mode 100644 qpid/cpp/lib/broker/TopicExchange.cpp delete mode 100644 qpid/cpp/lib/broker/TopicExchange.h delete mode 100644 qpid/cpp/lib/broker/TransactionalStore.h delete mode 100644 qpid/cpp/lib/broker/TxAck.cpp delete mode 100644 qpid/cpp/lib/broker/TxAck.h delete mode 100644 qpid/cpp/lib/broker/TxBuffer.cpp delete mode 100644 qpid/cpp/lib/broker/TxBuffer.h delete mode 100644 qpid/cpp/lib/broker/TxOp.h delete mode 100644 qpid/cpp/lib/broker/TxPublish.cpp delete mode 100644 qpid/cpp/lib/broker/TxPublish.h delete mode 100644 qpid/cpp/lib/client/AckMode.h delete mode 100644 qpid/cpp/lib/client/BasicMessageChannel.cpp delete mode 100644 qpid/cpp/lib/client/BasicMessageChannel.h delete mode 100644 qpid/cpp/lib/client/ClientAdapter.cpp delete mode 100644 qpid/cpp/lib/client/ClientAdapter.h delete mode 100644 qpid/cpp/lib/client/ClientChannel.cpp delete mode 100644 qpid/cpp/lib/client/ClientChannel.h delete mode 100644 qpid/cpp/lib/client/ClientExchange.cpp delete mode 100644 qpid/cpp/lib/client/ClientExchange.h delete mode 100644 qpid/cpp/lib/client/ClientMessage.h delete mode 100644 qpid/cpp/lib/client/ClientQueue.cpp delete mode 100644 qpid/cpp/lib/client/ClientQueue.h delete mode 100644 qpid/cpp/lib/client/Connection.cpp delete mode 100644 qpid/cpp/lib/client/Connection.h delete mode 100644 qpid/cpp/lib/client/Connector.cpp delete mode 100644 qpid/cpp/lib/client/Connector.h delete mode 100644 qpid/cpp/lib/client/IncomingMessage.cpp delete mode 100644 qpid/cpp/lib/client/IncomingMessage.h delete mode 100644 qpid/cpp/lib/client/Makefile.am delete mode 100644 qpid/cpp/lib/client/MessageChannel.h delete mode 100644 qpid/cpp/lib/client/MessageListener.cpp delete mode 100644 qpid/cpp/lib/client/MessageListener.h delete mode 100644 qpid/cpp/lib/client/MethodBodyInstances.h delete mode 100644 qpid/cpp/lib/client/ResponseHandler.cpp delete mode 100644 qpid/cpp/lib/client/ResponseHandler.h delete mode 100644 qpid/cpp/lib/client/ReturnedMessageHandler.cpp delete mode 100644 qpid/cpp/lib/client/ReturnedMessageHandler.h delete mode 100644 qpid/cpp/lib/common/Exception.cpp delete mode 100644 qpid/cpp/lib/common/Exception.h delete mode 100644 qpid/cpp/lib/common/ExceptionHolder.cpp delete mode 100644 qpid/cpp/lib/common/ExceptionHolder.h delete mode 100644 qpid/cpp/lib/common/Makefile.am delete mode 100644 qpid/cpp/lib/common/QpidError.cpp delete mode 100644 qpid/cpp/lib/common/QpidError.h delete mode 100644 qpid/cpp/lib/common/SharedObject.h delete mode 100644 qpid/cpp/lib/common/doxygen_mainpage.h delete mode 100644 qpid/cpp/lib/common/framing/AMQBody.cpp delete mode 100644 qpid/cpp/lib/common/framing/AMQBody.h delete mode 100644 qpid/cpp/lib/common/framing/AMQContentBody.cpp delete mode 100644 qpid/cpp/lib/common/framing/AMQContentBody.h delete mode 100644 qpid/cpp/lib/common/framing/AMQDataBlock.h delete mode 100644 qpid/cpp/lib/common/framing/AMQFrame.cpp delete mode 100644 qpid/cpp/lib/common/framing/AMQFrame.h delete mode 100644 qpid/cpp/lib/common/framing/AMQHeaderBody.cpp delete mode 100644 qpid/cpp/lib/common/framing/AMQHeaderBody.h delete mode 100644 qpid/cpp/lib/common/framing/AMQHeartbeatBody.cpp delete mode 100644 qpid/cpp/lib/common/framing/AMQHeartbeatBody.h delete mode 100644 qpid/cpp/lib/common/framing/AMQMethodBody.cpp delete mode 100644 qpid/cpp/lib/common/framing/AMQMethodBody.h delete mode 100644 qpid/cpp/lib/common/framing/AMQRequestBody.cpp delete mode 100644 qpid/cpp/lib/common/framing/AMQRequestBody.h delete mode 100644 qpid/cpp/lib/common/framing/AMQResponseBody.cpp delete mode 100644 qpid/cpp/lib/common/framing/AMQResponseBody.h delete mode 100644 qpid/cpp/lib/common/framing/BasicHeaderProperties.cpp delete mode 100644 qpid/cpp/lib/common/framing/BasicHeaderProperties.h delete mode 100644 qpid/cpp/lib/common/framing/BodyHandler.cpp delete mode 100644 qpid/cpp/lib/common/framing/BodyHandler.h delete mode 100644 qpid/cpp/lib/common/framing/Buffer.cpp delete mode 100644 qpid/cpp/lib/common/framing/Buffer.h delete mode 100644 qpid/cpp/lib/common/framing/ChannelAdapter.cpp delete mode 100644 qpid/cpp/lib/common/framing/ChannelAdapter.h delete mode 100644 qpid/cpp/lib/common/framing/FieldTable.cpp delete mode 100644 qpid/cpp/lib/common/framing/FieldTable.h delete mode 100644 qpid/cpp/lib/common/framing/FramingContent.cpp delete mode 100644 qpid/cpp/lib/common/framing/FramingContent.h delete mode 100644 qpid/cpp/lib/common/framing/HeaderProperties.h delete mode 100644 qpid/cpp/lib/common/framing/InitiationHandler.cpp delete mode 100644 qpid/cpp/lib/common/framing/InitiationHandler.h delete mode 100644 qpid/cpp/lib/common/framing/InputHandler.h delete mode 100644 qpid/cpp/lib/common/framing/MethodContext.cpp delete mode 100644 qpid/cpp/lib/common/framing/MethodContext.h delete mode 100644 qpid/cpp/lib/common/framing/OutputHandler.h delete mode 100644 qpid/cpp/lib/common/framing/ProtocolInitiation.cpp delete mode 100644 qpid/cpp/lib/common/framing/ProtocolInitiation.h delete mode 100644 qpid/cpp/lib/common/framing/ProtocolVersion.cpp delete mode 100644 qpid/cpp/lib/common/framing/ProtocolVersion.h delete mode 100644 qpid/cpp/lib/common/framing/ProtocolVersionException.cpp delete mode 100644 qpid/cpp/lib/common/framing/ProtocolVersionException.h delete mode 100644 qpid/cpp/lib/common/framing/Proxy.cpp delete mode 100644 qpid/cpp/lib/common/framing/Proxy.h delete mode 100644 qpid/cpp/lib/common/framing/Requester.cpp delete mode 100644 qpid/cpp/lib/common/framing/Requester.h delete mode 100644 qpid/cpp/lib/common/framing/Responder.cpp delete mode 100644 qpid/cpp/lib/common/framing/Responder.h delete mode 100644 qpid/cpp/lib/common/framing/Value.cpp delete mode 100644 qpid/cpp/lib/common/framing/Value.h delete mode 100644 qpid/cpp/lib/common/framing/amqp_framing.h delete mode 100644 qpid/cpp/lib/common/framing/amqp_types.h delete mode 100644 qpid/cpp/lib/common/framing/amqp_types_full.h delete mode 100644 qpid/cpp/lib/common/shared_ptr.h delete mode 100644 qpid/cpp/lib/common/sys/Acceptor.h delete mode 100644 qpid/cpp/lib/common/sys/AtomicCount.h delete mode 100644 qpid/cpp/lib/common/sys/Condition.h delete mode 100644 qpid/cpp/lib/common/sys/ConnectionInputHandler.h delete mode 100644 qpid/cpp/lib/common/sys/ConnectionInputHandlerFactory.h delete mode 100644 qpid/cpp/lib/common/sys/ConnectionOutputHandler.h delete mode 100644 qpid/cpp/lib/common/sys/Module.h delete mode 100644 qpid/cpp/lib/common/sys/Monitor.h delete mode 100644 qpid/cpp/lib/common/sys/Mutex.h delete mode 100644 qpid/cpp/lib/common/sys/ProducerConsumer.cpp delete mode 100644 qpid/cpp/lib/common/sys/ProducerConsumer.h delete mode 100644 qpid/cpp/lib/common/sys/Runnable.cpp delete mode 100644 qpid/cpp/lib/common/sys/Runnable.h delete mode 100644 qpid/cpp/lib/common/sys/ScopedIncrement.h delete mode 100644 qpid/cpp/lib/common/sys/ShutdownHandler.h delete mode 100644 qpid/cpp/lib/common/sys/Socket.h delete mode 100644 qpid/cpp/lib/common/sys/Thread.h delete mode 100644 qpid/cpp/lib/common/sys/ThreadSafeQueue.h delete mode 100644 qpid/cpp/lib/common/sys/Time.cpp delete mode 100644 qpid/cpp/lib/common/sys/Time.h delete mode 100644 qpid/cpp/lib/common/sys/TimeoutHandler.h delete mode 100644 qpid/cpp/lib/common/sys/apr/APRAcceptor.cpp delete mode 100644 qpid/cpp/lib/common/sys/apr/APRBase.cpp delete mode 100644 qpid/cpp/lib/common/sys/apr/APRBase.h delete mode 100644 qpid/cpp/lib/common/sys/apr/APRPool.cpp delete mode 100644 qpid/cpp/lib/common/sys/apr/APRPool.h delete mode 100644 qpid/cpp/lib/common/sys/apr/APRSocket.cpp delete mode 100644 qpid/cpp/lib/common/sys/apr/APRSocket.h delete mode 100644 qpid/cpp/lib/common/sys/apr/LFProcessor.cpp delete mode 100644 qpid/cpp/lib/common/sys/apr/LFProcessor.h delete mode 100644 qpid/cpp/lib/common/sys/apr/LFSessionContext.cpp delete mode 100644 qpid/cpp/lib/common/sys/apr/LFSessionContext.h delete mode 100644 qpid/cpp/lib/common/sys/apr/Socket.cpp delete mode 100644 qpid/cpp/lib/common/sys/apr/Thread.cpp delete mode 100644 qpid/cpp/lib/common/sys/posix/EventChannel.cpp delete mode 100644 qpid/cpp/lib/common/sys/posix/EventChannel.h delete mode 100644 qpid/cpp/lib/common/sys/posix/EventChannelAcceptor.cpp delete mode 100644 qpid/cpp/lib/common/sys/posix/EventChannelConnection.cpp delete mode 100644 qpid/cpp/lib/common/sys/posix/EventChannelConnection.h delete mode 100644 qpid/cpp/lib/common/sys/posix/EventChannelThreads.cpp delete mode 100644 qpid/cpp/lib/common/sys/posix/EventChannelThreads.h delete mode 100644 qpid/cpp/lib/common/sys/posix/PosixAcceptor.cpp delete mode 100644 qpid/cpp/lib/common/sys/posix/Socket.cpp delete mode 100644 qpid/cpp/lib/common/sys/posix/Thread.cpp delete mode 100644 qpid/cpp/lib/common/sys/posix/check.cpp delete mode 100644 qpid/cpp/lib/common/sys/posix/check.h create mode 100644 qpid/cpp/src/Exception.cpp create mode 100644 qpid/cpp/src/Exception.h create mode 100644 qpid/cpp/src/ExceptionHolder.cpp create mode 100644 qpid/cpp/src/ExceptionHolder.h create mode 100644 qpid/cpp/src/QpidError.cpp create mode 100644 qpid/cpp/src/QpidError.h create mode 100644 qpid/cpp/src/SharedObject.h create mode 100644 qpid/cpp/src/broker/AccumulatedAck.cpp create mode 100644 qpid/cpp/src/broker/AccumulatedAck.h create mode 100644 qpid/cpp/src/broker/AutoDelete.cpp create mode 100644 qpid/cpp/src/broker/AutoDelete.h create mode 100644 qpid/cpp/src/broker/Broker.cpp create mode 100644 qpid/cpp/src/broker/Broker.h create mode 100644 qpid/cpp/src/broker/BrokerAdapter.cpp create mode 100644 qpid/cpp/src/broker/BrokerAdapter.h create mode 100644 qpid/cpp/src/broker/BrokerChannel.cpp create mode 100644 qpid/cpp/src/broker/BrokerChannel.h create mode 100644 qpid/cpp/src/broker/BrokerExchange.h create mode 100644 qpid/cpp/src/broker/BrokerMessage.cpp create mode 100644 qpid/cpp/src/broker/BrokerMessage.h create mode 100644 qpid/cpp/src/broker/BrokerMessageBase.h create mode 100644 qpid/cpp/src/broker/BrokerMessageMessage.cpp create mode 100644 qpid/cpp/src/broker/BrokerMessageMessage.h create mode 100644 qpid/cpp/src/broker/BrokerQueue.cpp create mode 100644 qpid/cpp/src/broker/BrokerQueue.h create mode 100644 qpid/cpp/src/broker/BrokerSingleton.cpp create mode 100644 qpid/cpp/src/broker/BrokerSingleton.h create mode 100644 qpid/cpp/src/broker/CompletionHandler.h create mode 100644 qpid/cpp/src/broker/Configuration.cpp create mode 100644 qpid/cpp/src/broker/Configuration.h create mode 100644 qpid/cpp/src/broker/Connection.cpp create mode 100644 qpid/cpp/src/broker/Connection.h create mode 100644 qpid/cpp/src/broker/ConnectionFactory.cpp create mode 100644 qpid/cpp/src/broker/ConnectionFactory.h create mode 100644 qpid/cpp/src/broker/ConnectionToken.h create mode 100644 qpid/cpp/src/broker/Consumer.h create mode 100644 qpid/cpp/src/broker/Content.h create mode 100644 qpid/cpp/src/broker/DeletingTxOp.cpp create mode 100644 qpid/cpp/src/broker/DeletingTxOp.h create mode 100644 qpid/cpp/src/broker/Deliverable.h create mode 100644 qpid/cpp/src/broker/DeliverableMessage.cpp create mode 100644 qpid/cpp/src/broker/DeliverableMessage.h create mode 100644 qpid/cpp/src/broker/DeliveryRecord.cpp create mode 100644 qpid/cpp/src/broker/DeliveryRecord.h create mode 100644 qpid/cpp/src/broker/DirectExchange.cpp create mode 100644 qpid/cpp/src/broker/DirectExchange.h create mode 100644 qpid/cpp/src/broker/ExchangeRegistry.cpp create mode 100644 qpid/cpp/src/broker/ExchangeRegistry.h create mode 100644 qpid/cpp/src/broker/FanOutExchange.cpp create mode 100644 qpid/cpp/src/broker/FanOutExchange.h create mode 100644 qpid/cpp/src/broker/HandlerImpl.h create mode 100644 qpid/cpp/src/broker/HeadersExchange.cpp create mode 100644 qpid/cpp/src/broker/HeadersExchange.h create mode 100644 qpid/cpp/src/broker/InMemoryContent.cpp create mode 100644 qpid/cpp/src/broker/InMemoryContent.h create mode 100644 qpid/cpp/src/broker/LazyLoadedContent.cpp create mode 100644 qpid/cpp/src/broker/LazyLoadedContent.h create mode 100644 qpid/cpp/src/broker/Makefile.am create mode 100644 qpid/cpp/src/broker/MessageBuilder.cpp create mode 100644 qpid/cpp/src/broker/MessageBuilder.h create mode 100644 qpid/cpp/src/broker/MessageHandlerImpl.cpp create mode 100644 qpid/cpp/src/broker/MessageHandlerImpl.h create mode 100644 qpid/cpp/src/broker/MessageStore.h create mode 100644 qpid/cpp/src/broker/MessageStoreModule.cpp create mode 100644 qpid/cpp/src/broker/MessageStoreModule.h create mode 100644 qpid/cpp/src/broker/NameGenerator.cpp create mode 100644 qpid/cpp/src/broker/NameGenerator.h create mode 100644 qpid/cpp/src/broker/NullMessageStore.cpp create mode 100644 qpid/cpp/src/broker/NullMessageStore.h create mode 100644 qpid/cpp/src/broker/Persistable.h create mode 100644 qpid/cpp/src/broker/PersistableExchange.h create mode 100644 qpid/cpp/src/broker/PersistableMessage.h create mode 100644 qpid/cpp/src/broker/PersistableQueue.h create mode 100644 qpid/cpp/src/broker/Prefetch.h create mode 100644 qpid/cpp/src/broker/QueuePolicy.cpp create mode 100644 qpid/cpp/src/broker/QueuePolicy.h create mode 100644 qpid/cpp/src/broker/QueueRegistry.cpp create mode 100644 qpid/cpp/src/broker/QueueRegistry.h create mode 100644 qpid/cpp/src/broker/RecoverableMessage.h create mode 100644 qpid/cpp/src/broker/RecoverableQueue.h create mode 100644 qpid/cpp/src/broker/RecoveryManager.h create mode 100644 qpid/cpp/src/broker/RecoveryManagerImpl.cpp create mode 100644 qpid/cpp/src/broker/RecoveryManagerImpl.h create mode 100644 qpid/cpp/src/broker/Reference.cpp create mode 100644 qpid/cpp/src/broker/Reference.h create mode 100644 qpid/cpp/src/broker/TopicExchange.cpp create mode 100644 qpid/cpp/src/broker/TopicExchange.h create mode 100644 qpid/cpp/src/broker/TransactionalStore.h create mode 100644 qpid/cpp/src/broker/TxAck.cpp create mode 100644 qpid/cpp/src/broker/TxAck.h create mode 100644 qpid/cpp/src/broker/TxBuffer.cpp create mode 100644 qpid/cpp/src/broker/TxBuffer.h create mode 100644 qpid/cpp/src/broker/TxOp.h create mode 100644 qpid/cpp/src/broker/TxPublish.cpp create mode 100644 qpid/cpp/src/broker/TxPublish.h create mode 100644 qpid/cpp/src/client/AckMode.h create mode 100644 qpid/cpp/src/client/BasicMessageChannel.cpp create mode 100644 qpid/cpp/src/client/BasicMessageChannel.h create mode 100644 qpid/cpp/src/client/ClientAdapter.cpp create mode 100644 qpid/cpp/src/client/ClientAdapter.h create mode 100644 qpid/cpp/src/client/ClientChannel.cpp create mode 100644 qpid/cpp/src/client/ClientChannel.h create mode 100644 qpid/cpp/src/client/ClientExchange.cpp create mode 100644 qpid/cpp/src/client/ClientExchange.h create mode 100644 qpid/cpp/src/client/ClientMessage.h create mode 100644 qpid/cpp/src/client/ClientQueue.cpp create mode 100644 qpid/cpp/src/client/ClientQueue.h create mode 100644 qpid/cpp/src/client/Connection.cpp create mode 100644 qpid/cpp/src/client/Connection.h create mode 100644 qpid/cpp/src/client/Connector.cpp create mode 100644 qpid/cpp/src/client/Connector.h create mode 100644 qpid/cpp/src/client/IncomingMessage.cpp create mode 100644 qpid/cpp/src/client/IncomingMessage.h create mode 100644 qpid/cpp/src/client/Makefile.am create mode 100644 qpid/cpp/src/client/MessageChannel.h create mode 100644 qpid/cpp/src/client/MessageListener.cpp create mode 100644 qpid/cpp/src/client/MessageListener.h create mode 100644 qpid/cpp/src/client/MethodBodyInstances.h create mode 100644 qpid/cpp/src/client/ResponseHandler.cpp create mode 100644 qpid/cpp/src/client/ResponseHandler.h create mode 100644 qpid/cpp/src/client/ReturnedMessageHandler.cpp create mode 100644 qpid/cpp/src/client/ReturnedMessageHandler.h create mode 100644 qpid/cpp/src/doxygen_mainpage.h create mode 100644 qpid/cpp/src/framing/AMQBody.cpp create mode 100644 qpid/cpp/src/framing/AMQBody.h create mode 100644 qpid/cpp/src/framing/AMQContentBody.cpp create mode 100644 qpid/cpp/src/framing/AMQContentBody.h create mode 100644 qpid/cpp/src/framing/AMQDataBlock.h create mode 100644 qpid/cpp/src/framing/AMQFrame.cpp create mode 100644 qpid/cpp/src/framing/AMQFrame.h create mode 100644 qpid/cpp/src/framing/AMQHeaderBody.cpp create mode 100644 qpid/cpp/src/framing/AMQHeaderBody.h create mode 100644 qpid/cpp/src/framing/AMQHeartbeatBody.cpp create mode 100644 qpid/cpp/src/framing/AMQHeartbeatBody.h create mode 100644 qpid/cpp/src/framing/AMQMethodBody.cpp create mode 100644 qpid/cpp/src/framing/AMQMethodBody.h create mode 100644 qpid/cpp/src/framing/AMQRequestBody.cpp create mode 100644 qpid/cpp/src/framing/AMQRequestBody.h create mode 100644 qpid/cpp/src/framing/AMQResponseBody.cpp create mode 100644 qpid/cpp/src/framing/AMQResponseBody.h create mode 100644 qpid/cpp/src/framing/BasicHeaderProperties.cpp create mode 100644 qpid/cpp/src/framing/BasicHeaderProperties.h create mode 100644 qpid/cpp/src/framing/BodyHandler.cpp create mode 100644 qpid/cpp/src/framing/BodyHandler.h create mode 100644 qpid/cpp/src/framing/Buffer.cpp create mode 100644 qpid/cpp/src/framing/Buffer.h create mode 100644 qpid/cpp/src/framing/ChannelAdapter.cpp create mode 100644 qpid/cpp/src/framing/ChannelAdapter.h create mode 100644 qpid/cpp/src/framing/FieldTable.cpp create mode 100644 qpid/cpp/src/framing/FieldTable.h create mode 100644 qpid/cpp/src/framing/FramingContent.cpp create mode 100644 qpid/cpp/src/framing/FramingContent.h create mode 100644 qpid/cpp/src/framing/HeaderProperties.h create mode 100644 qpid/cpp/src/framing/InitiationHandler.cpp create mode 100644 qpid/cpp/src/framing/InitiationHandler.h create mode 100644 qpid/cpp/src/framing/InputHandler.h create mode 100644 qpid/cpp/src/framing/MethodContext.cpp create mode 100644 qpid/cpp/src/framing/MethodContext.h create mode 100644 qpid/cpp/src/framing/OutputHandler.h create mode 100644 qpid/cpp/src/framing/ProtocolInitiation.cpp create mode 100644 qpid/cpp/src/framing/ProtocolInitiation.h create mode 100644 qpid/cpp/src/framing/ProtocolVersion.cpp create mode 100644 qpid/cpp/src/framing/ProtocolVersion.h create mode 100644 qpid/cpp/src/framing/ProtocolVersionException.cpp create mode 100644 qpid/cpp/src/framing/ProtocolVersionException.h create mode 100644 qpid/cpp/src/framing/Proxy.cpp create mode 100644 qpid/cpp/src/framing/Proxy.h create mode 100644 qpid/cpp/src/framing/Requester.cpp create mode 100644 qpid/cpp/src/framing/Requester.h create mode 100644 qpid/cpp/src/framing/Responder.cpp create mode 100644 qpid/cpp/src/framing/Responder.h create mode 100644 qpid/cpp/src/framing/Value.cpp create mode 100644 qpid/cpp/src/framing/Value.h create mode 100644 qpid/cpp/src/framing/amqp_framing.h create mode 100644 qpid/cpp/src/framing/amqp_types.h create mode 100644 qpid/cpp/src/framing/amqp_types_full.h create mode 100644 qpid/cpp/src/gen/Makefile.am create mode 100755 qpid/cpp/src/gen/make-gen-src-mk.sh create mode 100644 qpid/cpp/src/shared_ptr.h create mode 100644 qpid/cpp/src/sys/Acceptor.h create mode 100644 qpid/cpp/src/sys/AtomicCount.h create mode 100644 qpid/cpp/src/sys/Condition.h create mode 100644 qpid/cpp/src/sys/ConnectionInputHandler.h create mode 100644 qpid/cpp/src/sys/ConnectionInputHandlerFactory.h create mode 100644 qpid/cpp/src/sys/ConnectionOutputHandler.h create mode 100644 qpid/cpp/src/sys/Module.h create mode 100644 qpid/cpp/src/sys/Monitor.h create mode 100644 qpid/cpp/src/sys/Mutex.h create mode 100644 qpid/cpp/src/sys/ProducerConsumer.cpp create mode 100644 qpid/cpp/src/sys/ProducerConsumer.h create mode 100644 qpid/cpp/src/sys/Runnable.cpp create mode 100644 qpid/cpp/src/sys/Runnable.h create mode 100644 qpid/cpp/src/sys/ScopedIncrement.h create mode 100644 qpid/cpp/src/sys/ShutdownHandler.h create mode 100644 qpid/cpp/src/sys/Socket.h create mode 100644 qpid/cpp/src/sys/Thread.h create mode 100644 qpid/cpp/src/sys/ThreadSafeQueue.h create mode 100644 qpid/cpp/src/sys/Time.cpp create mode 100644 qpid/cpp/src/sys/Time.h create mode 100644 qpid/cpp/src/sys/TimeoutHandler.h create mode 100644 qpid/cpp/src/sys/apr/APRAcceptor.cpp create mode 100644 qpid/cpp/src/sys/apr/APRBase.cpp create mode 100644 qpid/cpp/src/sys/apr/APRBase.h create mode 100644 qpid/cpp/src/sys/apr/APRPool.cpp create mode 100644 qpid/cpp/src/sys/apr/APRPool.h create mode 100644 qpid/cpp/src/sys/apr/APRSocket.cpp create mode 100644 qpid/cpp/src/sys/apr/APRSocket.h create mode 100644 qpid/cpp/src/sys/apr/LFProcessor.cpp create mode 100644 qpid/cpp/src/sys/apr/LFProcessor.h create mode 100644 qpid/cpp/src/sys/apr/LFSessionContext.cpp create mode 100644 qpid/cpp/src/sys/apr/LFSessionContext.h create mode 100644 qpid/cpp/src/sys/apr/Socket.cpp create mode 100644 qpid/cpp/src/sys/apr/Thread.cpp create mode 100644 qpid/cpp/src/sys/posix/EventChannel.cpp create mode 100644 qpid/cpp/src/sys/posix/EventChannel.h create mode 100644 qpid/cpp/src/sys/posix/EventChannelAcceptor.cpp create mode 100644 qpid/cpp/src/sys/posix/EventChannelConnection.cpp create mode 100644 qpid/cpp/src/sys/posix/EventChannelConnection.h create mode 100644 qpid/cpp/src/sys/posix/EventChannelThreads.cpp create mode 100644 qpid/cpp/src/sys/posix/EventChannelThreads.h create mode 100644 qpid/cpp/src/sys/posix/PosixAcceptor.cpp create mode 100644 qpid/cpp/src/sys/posix/Socket.cpp create mode 100644 qpid/cpp/src/sys/posix/Thread.cpp create mode 100644 qpid/cpp/src/sys/posix/check.cpp create mode 100644 qpid/cpp/src/sys/posix/check.h create mode 100644 qpid/cpp/src/tests/.vg-supp create mode 100644 qpid/cpp/src/tests/APRBaseTest.cpp create mode 100644 qpid/cpp/src/tests/AccumulatedAckTest.cpp create mode 100644 qpid/cpp/src/tests/BrokerChannelTest.cpp create mode 100644 qpid/cpp/src/tests/ClientChannelTest.cpp create mode 100644 qpid/cpp/src/tests/ConfigurationTest.cpp create mode 100644 qpid/cpp/src/tests/EventChannelConnectionTest.cpp create mode 100644 qpid/cpp/src/tests/EventChannelTest.cpp create mode 100644 qpid/cpp/src/tests/EventChannelThreadsTest.cpp create mode 100644 qpid/cpp/src/tests/ExchangeTest.cpp create mode 100644 qpid/cpp/src/tests/FieldTableTest.cpp create mode 100644 qpid/cpp/src/tests/FramingTest.cpp create mode 100644 qpid/cpp/src/tests/HeaderTest.cpp create mode 100644 qpid/cpp/src/tests/HeadersExchangeTest.cpp create mode 100644 qpid/cpp/src/tests/InMemoryContentTest.cpp create mode 100644 qpid/cpp/src/tests/InProcessBroker.h create mode 100644 qpid/cpp/src/tests/LazyLoadedContentTest.cpp create mode 100644 qpid/cpp/src/tests/Makefile.am create mode 100644 qpid/cpp/src/tests/MessageBuilderTest.cpp create mode 100644 qpid/cpp/src/tests/MessageHandlerTest.cpp create mode 100644 qpid/cpp/src/tests/MessageTest.cpp create mode 100644 qpid/cpp/src/tests/MockChannel.h create mode 100644 qpid/cpp/src/tests/MockConnectionInputHandler.h create mode 100644 qpid/cpp/src/tests/ProducerConsumerTest.cpp create mode 100644 qpid/cpp/src/tests/QueuePolicyTest.cpp create mode 100644 qpid/cpp/src/tests/QueueRegistryTest.cpp create mode 100644 qpid/cpp/src/tests/QueueTest.cpp create mode 100644 qpid/cpp/src/tests/ReferenceTest.cpp create mode 100644 qpid/cpp/src/tests/TopicExchangeTest.cpp create mode 100644 qpid/cpp/src/tests/TxAckTest.cpp create mode 100644 qpid/cpp/src/tests/TxBufferTest.cpp create mode 100644 qpid/cpp/src/tests/TxPublishTest.cpp create mode 100644 qpid/cpp/src/tests/ValueTest.cpp create mode 100644 qpid/cpp/src/tests/client_test.cpp create mode 100644 qpid/cpp/src/tests/dlclose_noop.c create mode 100644 qpid/cpp/src/tests/echo_service.cpp create mode 100644 qpid/cpp/src/tests/examples.Makefile create mode 100644 qpid/cpp/src/tests/examples.README create mode 100755 qpid/cpp/src/tests/kill_broker create mode 100755 qpid/cpp/src/tests/python_tests create mode 100644 qpid/cpp/src/tests/qpid_test_plugin.h create mode 100755 qpid/cpp/src/tests/quick_topictest create mode 100755 qpid/cpp/src/tests/run-python-tests create mode 100755 qpid/cpp/src/tests/run-unit-tests create mode 100644 qpid/cpp/src/tests/setup create mode 100755 qpid/cpp/src/tests/start_broker create mode 100644 qpid/cpp/src/tests/topic_listener.cpp create mode 100644 qpid/cpp/src/tests/topic_publisher.cpp create mode 100755 qpid/cpp/src/tests/topictest delete mode 100644 qpid/cpp/tests/.vg-supp delete mode 100644 qpid/cpp/tests/APRBaseTest.cpp delete mode 100644 qpid/cpp/tests/AccumulatedAckTest.cpp delete mode 100644 qpid/cpp/tests/BrokerChannelTest.cpp delete mode 100644 qpid/cpp/tests/ClientChannelTest.cpp delete mode 100644 qpid/cpp/tests/ConfigurationTest.cpp delete mode 100644 qpid/cpp/tests/EventChannelConnectionTest.cpp delete mode 100644 qpid/cpp/tests/EventChannelTest.cpp delete mode 100644 qpid/cpp/tests/EventChannelThreadsTest.cpp delete mode 100644 qpid/cpp/tests/ExchangeTest.cpp delete mode 100644 qpid/cpp/tests/FieldTableTest.cpp delete mode 100644 qpid/cpp/tests/FramingTest.cpp delete mode 100644 qpid/cpp/tests/HeaderTest.cpp delete mode 100644 qpid/cpp/tests/HeadersExchangeTest.cpp delete mode 100644 qpid/cpp/tests/InMemoryContentTest.cpp delete mode 100644 qpid/cpp/tests/InProcessBroker.h delete mode 100644 qpid/cpp/tests/LazyLoadedContentTest.cpp delete mode 100644 qpid/cpp/tests/Makefile.am delete mode 100644 qpid/cpp/tests/MessageBuilderTest.cpp delete mode 100644 qpid/cpp/tests/MessageHandlerTest.cpp delete mode 100644 qpid/cpp/tests/MessageTest.cpp delete mode 100644 qpid/cpp/tests/MockChannel.h delete mode 100644 qpid/cpp/tests/MockConnectionInputHandler.h delete mode 100644 qpid/cpp/tests/ProducerConsumerTest.cpp delete mode 100644 qpid/cpp/tests/QueuePolicyTest.cpp delete mode 100644 qpid/cpp/tests/QueueRegistryTest.cpp delete mode 100644 qpid/cpp/tests/QueueTest.cpp delete mode 100644 qpid/cpp/tests/ReferenceTest.cpp delete mode 100644 qpid/cpp/tests/TopicExchangeTest.cpp delete mode 100644 qpid/cpp/tests/TxAckTest.cpp delete mode 100644 qpid/cpp/tests/TxBufferTest.cpp delete mode 100644 qpid/cpp/tests/TxPublishTest.cpp delete mode 100644 qpid/cpp/tests/ValueTest.cpp delete mode 100644 qpid/cpp/tests/client_test.cpp delete mode 100644 qpid/cpp/tests/dlclose_noop.c delete mode 100644 qpid/cpp/tests/echo_service.cpp delete mode 100644 qpid/cpp/tests/examples.Makefile delete mode 100644 qpid/cpp/tests/examples.README delete mode 100755 qpid/cpp/tests/kill_broker delete mode 100755 qpid/cpp/tests/python_tests delete mode 100644 qpid/cpp/tests/qpid_test_plugin.h delete mode 100755 qpid/cpp/tests/quick_topictest delete mode 100755 qpid/cpp/tests/run-python-tests delete mode 100755 qpid/cpp/tests/run-unit-tests delete mode 100644 qpid/cpp/tests/setup delete mode 100755 qpid/cpp/tests/start_broker delete mode 100644 qpid/cpp/tests/topic_listener.cpp delete mode 100644 qpid/cpp/tests/topic_publisher.cpp delete mode 100755 qpid/cpp/tests/topictest (limited to 'qpid/cpp') diff --git a/qpid/cpp/Makefile.am b/qpid/cpp/Makefile.am index 112cd5dd59..2ae53a7181 100644 --- a/qpid/cpp/Makefile.am +++ b/qpid/cpp/Makefile.am @@ -7,7 +7,7 @@ EXTRA_DIST = \ $(PACKAGE).spec \ $(PACKAGE).spec.in -SUBDIRS = gen lib src docs/api docs/man rpm tests +SUBDIRS = src docs/api docs/man rpm # Update libtool, if needed. libtool: $(LIBTOOL_DEPS) diff --git a/qpid/cpp/bootstrap b/qpid/cpp/bootstrap index 4fbce77e3f..b956edf70f 100755 --- a/qpid/cpp/bootstrap +++ b/qpid/cpp/bootstrap @@ -17,13 +17,13 @@ if test -d ../specs; then # contents of the sole automake-else clause (the warning), then # use the result to run the rules that create gen-src.mk, a file # that must be created before we run automake. - (cd gen && rm -f gen-src.mk + (cd src/gen && rm -f gen-src.mk perl -ne '/warning:|^(if|else|endif|include)\b/ or print' Makefile.am \ | make -f - srcdir=. gen-src.mk > /dev/null ) fi # Generate (for automake) lots of repetitive parts of tests/Makefile.am. -(cd tests && rm -f gen.mk +(cd src/tests && rm -f gen.mk perl -ne '/^include / or print' Makefile.am \ | make -f - abs_srcdir=`dirname $(pwd)` gen.mk > /dev/null ) diff --git a/qpid/cpp/configure.ac b/qpid/cpp/configure.ac index f4dcf32c28..14bc41deaf 100644 --- a/qpid/cpp/configure.ac +++ b/qpid/cpp/configure.ac @@ -16,7 +16,7 @@ AM_INIT_AUTOMAKE([dist-bzip2]) AC_PREREQ(2.59) AC_CONFIG_HEADERS([config.h:config.in]) -AC_CONFIG_SRCDIR([lib/broker/Broker.cpp]) +AC_CONFIG_SRCDIR([src/broker/Broker.cpp]) AC_PROG_CC_STDC AM_PROG_CC_C_O @@ -138,13 +138,11 @@ test "$enable_VALGRIND" = no && VALGRIND= AC_CONFIG_FILES([ Makefile - gen/Makefile - lib/Makefile - lib/common/Makefile - lib/client/Makefile - lib/broker/Makefile + src/gen/Makefile + src/client/Makefile + src/broker/Makefile src/Makefile - tests/Makefile + src/tests/Makefile docs/man/Makefile docs/api/Makefile rpm/Makefile diff --git a/qpid/cpp/gen/Makefile.am b/qpid/cpp/gen/Makefile.am deleted file mode 100644 index e16923fcc2..0000000000 --- a/qpid/cpp/gen/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -include gen-src.mk - -BUILT_SOURCES = $(generated_sources) $(generated_headers) -pkginclude_HEADERS=$(generated_headers) - -# Distribute the generated sources, at least for now, since -# the generator code is in java. -EXTRA_DIST = $(BUILT_SOURCES) -DISTCLEANFILES = $(BUILT_SOURCES) timestamp gen-src.mk - -# Don't attempt to run the code generator unless configure has set -# CAN_GENERATE_CODE, indicating that the amqp.xml and tools needed -# to run the code generator are available. -# -if CAN_GENERATE_CODE - -gentools_dir = $(srcdir)/../gentools -spec_dir = $(srcdir)/../../specs - -# FIXME aconway 2007-01-04: Enabling Basic class until -# new messaging class is ready to replace it. -# spec = $(spec_dir)/amqp.0-9.xml $(spec_dir)/amqp-errata.0-9.xml $(spec_dir)/amqp-nogen.0-9.xml -spec = $(spec_dir)/amqp.0-9.xml $(spec_dir)/amqp-errata.0-9.xml - -gentools_srcdir = $(gentools_dir)/src/org/apache/qpid/gentools - -$(BUILT_SOURCES) timestamp: $(spec) $(java_sources) $(cxx_templates) Makefile.am - rm -f $(generated_sources) - cd $(gentools_srcdir) && rm -f *.class && $(JAVAC) *.java - $(JAVA) -cp $(gentools_dir)/src org.apache.qpid.gentools.Main \ - -c -o . -t $(gentools_dir)/templ.cpp $(spec) - touch timestamp - -gen-src.mk: timestamp - ./make-gen-src-mk.sh $(gentools_dir) $(gentools_srcdir) > $@-t - mv $@-t $@ -endif diff --git a/qpid/cpp/gen/make-gen-src-mk.sh b/qpid/cpp/gen/make-gen-src-mk.sh deleted file mode 100755 index 08eb8ea134..0000000000 --- a/qpid/cpp/gen/make-gen-src-mk.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -# Generate the gen-src.mk makefile fragment, to stdout. -# Usage: - -gentools_dir=$1 -gentools_srcdir=$2 - -wildcard() { echo `ls $* 2>/dev/null` ; } - -cat < -#include "../lib/common/framing/ProtocolVersion.h" +#include "../framing/ProtocolVersion.h" namespace qpid { namespace framing { diff --git a/qpid/cpp/gentools/templ.cpp/AMQP_ClientProxy.cpp.tmpl b/qpid/cpp/gentools/templ.cpp/AMQP_ClientProxy.cpp.tmpl index e3602e20b7..a1613c77f0 100644 --- a/qpid/cpp/gentools/templ.cpp/AMQP_ClientProxy.cpp.tmpl +++ b/qpid/cpp/gentools/templ.cpp/AMQP_ClientProxy.cpp.tmpl @@ -27,8 +27,8 @@ */ #include #include "AMQP_ClientProxy.h" -#include "../lib/common/framing/ChannelAdapter.h" -#include "../lib/common/framing/amqp_types_full.h" +#include "../framing/ChannelAdapter.h" +#include "../framing/amqp_types_full.h" %{MLIST} ${cpc_method_body_include} diff --git a/qpid/cpp/gentools/templ.cpp/AMQP_ClientProxy.h.tmpl b/qpid/cpp/gentools/templ.cpp/AMQP_ClientProxy.h.tmpl index 05ff2aa5b1..04f1f1020a 100644 --- a/qpid/cpp/gentools/templ.cpp/AMQP_ClientProxy.h.tmpl +++ b/qpid/cpp/gentools/templ.cpp/AMQP_ClientProxy.h.tmpl @@ -29,7 +29,7 @@ #ifndef qpid_framing_AMQP_ClientProxy__ #define qpid_framing_AMQP_ClientProxy__ -#include "../lib/common/framing/Proxy.h" +#include "../framing/Proxy.h" namespace qpid { namespace framing { diff --git a/qpid/cpp/gentools/templ.cpp/AMQP_HighestVersion.h.tmpl b/qpid/cpp/gentools/templ.cpp/AMQP_HighestVersion.h.tmpl index 3d5dacf4dc..fdbeb077d3 100644 --- a/qpid/cpp/gentools/templ.cpp/AMQP_HighestVersion.h.tmpl +++ b/qpid/cpp/gentools/templ.cpp/AMQP_HighestVersion.h.tmpl @@ -28,7 +28,7 @@ #ifndef qpid_framing_highestProtocolVersion__ #define qpid_framing_highestProtocolVersion__ -#include "../lib/common/framing/ProtocolVersion.h" +#include "../framing/ProtocolVersion.h" namespace qpid { diff --git a/qpid/cpp/gentools/templ.cpp/AMQP_MethodVersionMap.cpp.tmpl b/qpid/cpp/gentools/templ.cpp/AMQP_MethodVersionMap.cpp.tmpl index bfb9ce1307..ea61c1c91d 100644 --- a/qpid/cpp/gentools/templ.cpp/AMQP_MethodVersionMap.cpp.tmpl +++ b/qpid/cpp/gentools/templ.cpp/AMQP_MethodVersionMap.cpp.tmpl @@ -27,7 +27,7 @@ */ #include -#include "../lib/common/framing/ProtocolVersionException.h" +#include "../framing/ProtocolVersionException.h" #include "AMQP_MethodVersionMap.h" namespace qpid diff --git a/qpid/cpp/gentools/templ.cpp/AMQP_MethodVersionMap.h.tmpl b/qpid/cpp/gentools/templ.cpp/AMQP_MethodVersionMap.h.tmpl index 530f76f599..2bfadc80dd 100644 --- a/qpid/cpp/gentools/templ.cpp/AMQP_MethodVersionMap.h.tmpl +++ b/qpid/cpp/gentools/templ.cpp/AMQP_MethodVersionMap.h.tmpl @@ -30,7 +30,7 @@ #define qpid_framing_AMQP_MethodVersionMap__ #include -#include "../lib/common/framing/AMQMethodBody.h" +#include "../framing/AMQMethodBody.h" %{MLIST} ${mc_method_body_include} diff --git a/qpid/cpp/gentools/templ.cpp/AMQP_ServerOperations.h.tmpl b/qpid/cpp/gentools/templ.cpp/AMQP_ServerOperations.h.tmpl index 1508815144..5b260f1882 100644 --- a/qpid/cpp/gentools/templ.cpp/AMQP_ServerOperations.h.tmpl +++ b/qpid/cpp/gentools/templ.cpp/AMQP_ServerOperations.h.tmpl @@ -29,7 +29,7 @@ #ifndef qpid_framing_AMQP_ServerOperations__ #define qpid_framing_AMQP_ServerOperations__ -#include "../lib/common/framing/ProtocolVersion.h" +#include "../framing/ProtocolVersion.h" namespace qpid { namespace framing { diff --git a/qpid/cpp/gentools/templ.cpp/AMQP_ServerProxy.cpp.tmpl b/qpid/cpp/gentools/templ.cpp/AMQP_ServerProxy.cpp.tmpl index c45af6a996..9877047d26 100644 --- a/qpid/cpp/gentools/templ.cpp/AMQP_ServerProxy.cpp.tmpl +++ b/qpid/cpp/gentools/templ.cpp/AMQP_ServerProxy.cpp.tmpl @@ -28,8 +28,8 @@ #include #include "AMQP_ServerProxy.h" -#include "../lib/common/framing/ChannelAdapter.h" -#include "../lib/common/framing/amqp_types_full.h" +#include "../framing/ChannelAdapter.h" +#include "../framing/amqp_types_full.h" %{MLIST} ${spc_method_body_include} diff --git a/qpid/cpp/gentools/templ.cpp/AMQP_ServerProxy.h.tmpl b/qpid/cpp/gentools/templ.cpp/AMQP_ServerProxy.h.tmpl index 5e9ced4375..e07a1fcf9c 100644 --- a/qpid/cpp/gentools/templ.cpp/AMQP_ServerProxy.h.tmpl +++ b/qpid/cpp/gentools/templ.cpp/AMQP_ServerProxy.h.tmpl @@ -29,7 +29,7 @@ #ifndef qpid_framing_AMQP_ServerProxy__ #define qpid_framing_AMQP_ServerProxy__ -#include "../lib/common/framing/Proxy.h" +#include "../framing/Proxy.h" namespace qpid { namespace framing { diff --git a/qpid/cpp/gentools/templ.cpp/MethodBodyClass.h.tmpl b/qpid/cpp/gentools/templ.cpp/MethodBodyClass.h.tmpl index 2b5b6a541c..68f3e92a45 100644 --- a/qpid/cpp/gentools/templ.cpp/MethodBodyClass.h.tmpl +++ b/qpid/cpp/gentools/templ.cpp/MethodBodyClass.h.tmpl @@ -32,11 +32,11 @@ #include #include -#include "../lib/common/framing/amqp_types.h" -#include "${mb_base_class}.h" -#include "../lib/common/framing/Buffer.h" -#include "../lib/common/framing/FieldTable.h" -#include "../lib/common/framing/FramingContent.h" +#include "../framing/amqp_types.h" +#include "../framing/${mb_base_class}.h" +#include "../framing/Buffer.h" +#include "../framing/FieldTable.h" +#include "../framing/FramingContent.h" namespace qpid { diff --git a/qpid/cpp/lib/Makefile.am b/qpid/cpp/lib/Makefile.am deleted file mode 100644 index 09a689bc76..0000000000 --- a/qpid/cpp/lib/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = common broker client diff --git a/qpid/cpp/lib/broker/AccumulatedAck.cpp b/qpid/cpp/lib/broker/AccumulatedAck.cpp deleted file mode 100644 index ff471b0287..0000000000 --- a/qpid/cpp/lib/broker/AccumulatedAck.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 "AccumulatedAck.h" - -#include - -using std::less_equal; -using std::bind2nd; -using namespace qpid::broker; - -void AccumulatedAck::update(uint64_t firstTag, uint64_t lastTag){ - assert(firstTag<=lastTag); - if (firstTag <= range + 1) { - if (lastTag > range) range = lastTag; - } else { - for (uint64_t tag = firstTag; tag<=lastTag; tag++) - individual.push_back(tag); - } -} - -void AccumulatedAck::consolidate(){ - individual.sort(); - //remove any individual tags that are covered by range - individual.remove_if(bind2nd(less_equal(), range)); - //update range if possible (using <= allows for duplicates from overlapping ranges) - while (individual.front() <= range + 1) { - range = individual.front(); - individual.pop_front(); - } -} - -void AccumulatedAck::clear(){ - range = 0; - individual.clear(); -} - -bool AccumulatedAck::covers(uint64_t tag) const{ - return tag <= range || find(individual.begin(), individual.end(), tag) != individual.end(); -} diff --git a/qpid/cpp/lib/broker/AccumulatedAck.h b/qpid/cpp/lib/broker/AccumulatedAck.h deleted file mode 100644 index c4a6e3b79b..0000000000 --- a/qpid/cpp/lib/broker/AccumulatedAck.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 _AccumulatedAck_ -#define _AccumulatedAck_ - -#include -#include -#include - -namespace qpid { - namespace broker { - /** - * Keeps an accumulated record of acked messages (by delivery - * tag). - */ - class AccumulatedAck { - public: - /** - * If not zero, then everything up to this value has been - * acked. - */ - uint64_t range; - /** - * List of individually acked messages that are not - * included in the range marked by 'range'. - */ - std::list individual; - - AccumulatedAck(uint64_t r) : range(r) {} - void update(uint64_t firstTag, uint64_t lastTag); - void consolidate(); - void clear(); - bool covers(uint64_t tag) const; - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/AutoDelete.cpp b/qpid/cpp/lib/broker/AutoDelete.cpp deleted file mode 100644 index 2037a9c71c..0000000000 --- a/qpid/cpp/lib/broker/AutoDelete.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 - -using namespace qpid::broker; -using namespace qpid::sys; - -AutoDelete::AutoDelete(QueueRegistry* const _registry, uint32_t _period) - : registry(_registry), period(_period), stopped(true) { } - -void AutoDelete::add(Queue::shared_ptr const queue){ - Mutex::ScopedLock l(lock); - queues.push(queue); -} - -Queue::shared_ptr const AutoDelete::pop(){ - Queue::shared_ptr next; - Mutex::ScopedLock l(lock); - if(!queues.empty()){ - next = queues.front(); - queues.pop(); - } - return next; -} - -void AutoDelete::process(){ - Queue::shared_ptr seen; - for(Queue::shared_ptr q = pop(); q; q = pop()){ - if(seen == q){ - add(q); - break; - }else if(q->canAutoDelete()){ - std::string name(q->getName()); - registry->destroy(name); - std::cout << "INFO: Auto-deleted queue named " << name << std::endl; - }else{ - add(q); - if(!seen) seen = q; - } - } -} - -void AutoDelete::run(){ - Monitor::ScopedLock l(monitor); - while(!stopped){ - process(); - monitor.wait(period*TIME_MSEC); - } -} - -void AutoDelete::start(){ - Monitor::ScopedLock l(monitor); - if(stopped){ - stopped = false; - runner = Thread(this); - } -} - -void AutoDelete::stop(){ - { - Monitor::ScopedLock l(monitor); - if(stopped) return; - stopped = true; - } - monitor.notify(); - runner.join(); -} diff --git a/qpid/cpp/lib/broker/AutoDelete.h b/qpid/cpp/lib/broker/AutoDelete.h deleted file mode 100644 index 9034de1730..0000000000 --- a/qpid/cpp/lib/broker/AutoDelete.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _AutoDelete_ -#define _AutoDelete_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 - -namespace qpid { - namespace broker{ - class AutoDelete : private qpid::sys::Runnable { - qpid::sys::Mutex lock; - qpid::sys::Monitor monitor; - std::queue queues; - QueueRegistry* const registry; - uint32_t period; - volatile bool stopped; - qpid::sys::Thread runner; - - Queue::shared_ptr const pop(); - void process(); - virtual void run(); - - public: - AutoDelete(QueueRegistry* const registry, uint32_t period); - void add(Queue::shared_ptr const); - void start(); - void stop(); - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/Broker.cpp b/qpid/cpp/lib/broker/Broker.cpp deleted file mode 100644 index fa80867b69..0000000000 --- a/qpid/cpp/lib/broker/Broker.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 -#include - -#include "AMQFrame.h" -#include "DirectExchange.h" -#include "TopicExchange.h" -#include "FanOutExchange.h" -#include "HeadersExchange.h" -#include "MessageStoreModule.h" -#include "NullMessageStore.h" -#include "ProtocolInitiation.h" -#include "RecoveryManagerImpl.h" -#include "Connection.h" -#include "sys/ConnectionInputHandler.h" -#include "sys/ConnectionInputHandlerFactory.h" -#include "sys/TimeoutHandler.h" - -#include "Broker.h" - -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"); - -Broker::Broker(const Configuration& conf) : - config(conf), - store(createStore(conf)), - queues(store.get()), - timeout(30000), - stagingThreshold(0), - cleaner(&queues, timeout/10), - factory(*this) -{ - exchanges.declare(empty, DirectExchange::typeName); // Default exchange. - exchanges.declare(amq_direct, DirectExchange::typeName); - exchanges.declare(amq_topic, TopicExchange::typeName); - exchanges.declare(amq_fanout, FanOutExchange::typeName); - exchanges.declare(amq_match, HeadersExchange::typeName); - - if(store.get()) { - RecoveryManagerImpl recoverer(queues, exchanges, conf.getStagingThreshold()); - store->recover(recoverer); - } - - cleaner.start(); -} - - -Broker::shared_ptr Broker::create(int16_t port) -{ - Configuration config; - config.setPort(port); - return create(config); -} - -Broker::shared_ptr Broker::create(const Configuration& config) { - return Broker::shared_ptr(new Broker(config)); -} - -MessageStore* Broker::createStore(const Configuration& config) { - if (config.getStore().empty()) - return new NullMessageStore(config.isTrace()); - else - return new MessageStoreModule(config.getStore()); -} - -void Broker::run() { - getAcceptor().run(&factory); -} - -void Broker::shutdown() { - if (acceptor) - acceptor->shutdown(); -} - -Broker::~Broker() { - shutdown(); -} - -int16_t Broker::getPort() const { return getAcceptor().getPort(); } - -Acceptor& Broker::getAcceptor() const { - if (!acceptor) - const_cast(acceptor) = - Acceptor::create(config.getPort(), - config.getConnectionBacklog(), - config.getWorkerThreads(), - config.isTrace()); - return *acceptor; -} - - -const int16_t Broker::DEFAULT_PORT(5672); - - -}} // namespace qpid::broker - diff --git a/qpid/cpp/lib/broker/Broker.h b/qpid/cpp/lib/broker/Broker.h deleted file mode 100644 index 68c04336d8..0000000000 --- a/qpid/cpp/lib/broker/Broker.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef _Broker_ -#define _Broker_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 - -namespace qpid { -namespace broker { -/** - * A broker instance. - */ -class Broker : public sys::Runnable, - public SharedObject -{ - public: - static const int16_t DEFAULT_PORT; - - virtual ~Broker(); - - /** - * Create a broker. - * @param port Port to listen on or 0 to pick a port dynamically. - */ - static shared_ptr create(int16_t port = DEFAULT_PORT); - - /** - * Create a broker using a Configuration. - */ - static shared_ptr create(const Configuration& config); - - /** - * 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. - */ - virtual int16_t getPort() const; - - /** - * Run the broker. Implements Runnable::run() so the broker - * can be run in a separate thread. - */ - virtual void run(); - - /** Shut down the broker */ - virtual void shutdown(); - - MessageStore& getStore() { return *store; } - QueueRegistry& getQueues() { return queues; } - ExchangeRegistry& getExchanges() { return exchanges; } - uint32_t getTimeout() { return timeout; } - uint64_t getStagingThreshold() { return stagingThreshold; } - AutoDelete& getCleaner() { return cleaner; } - - private: - Broker(const Configuration& config); - sys::Acceptor& getAcceptor() const; - - Configuration config; - sys::Acceptor::shared_ptr acceptor; - const std::auto_ptr store; - QueueRegistry queues; - ExchangeRegistry exchanges; - uint32_t timeout; - uint64_t stagingThreshold; - AutoDelete cleaner; - ConnectionFactory factory; - - static MessageStore* createStore(const Configuration& config); -}; - -}} - - - -#endif /*!_Broker_*/ diff --git a/qpid/cpp/lib/broker/BrokerAdapter.cpp b/qpid/cpp/lib/broker/BrokerAdapter.cpp deleted file mode 100644 index 981801c40e..0000000000 --- a/qpid/cpp/lib/broker/BrokerAdapter.cpp +++ /dev/null @@ -1,388 +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 "BrokerAdapter.h" -#include "BrokerChannel.h" -#include "Connection.h" -#include "AMQMethodBody.h" -#include "Exception.h" - -namespace qpid { -namespace broker { - -using boost::format; -using namespace qpid; -using namespace qpid::framing; - -typedef std::vector QueueVector; - - -BrokerAdapter::BrokerAdapter(Channel& ch, Connection& c, Broker& b) : - CoreRefs(ch, c, b), - connection(c), - basicHandler(*this), - channelHandler(*this), - connectionHandler(*this), - exchangeHandler(*this), - messageHandler(*this), - queueHandler(*this), - txHandler(*this) -{} - - -ProtocolVersion BrokerAdapter::getVersion() const { - return connection.getVersion(); -} - -void BrokerAdapter::ConnectionHandlerImpl::startOk( - const MethodContext&, const FieldTable& /*clientProperties*/, - const string& /*mechanism*/, - const string& /*response*/, const string& /*locale*/) -{ - client.tune( - 100, connection.getFrameMax(), connection.getHeartbeat()); -} - -void BrokerAdapter::ConnectionHandlerImpl::secureOk( - const MethodContext&, const string& /*response*/){} - -void BrokerAdapter::ConnectionHandlerImpl::tuneOk( - const MethodContext&, uint16_t /*channelmax*/, - uint32_t framemax, uint16_t heartbeat) -{ - connection.setFrameMax(framemax); - connection.setHeartbeat(heartbeat); -} - -void BrokerAdapter::ConnectionHandlerImpl::open( - const MethodContext& context, const string& /*virtualHost*/, - const string& /*capabilities*/, bool /*insist*/) -{ - string knownhosts; - client.openOk( - knownhosts, context.getRequestId()); -} - -void BrokerAdapter::ConnectionHandlerImpl::close( - const MethodContext& context, uint16_t /*replyCode*/, const string& /*replyText*/, - uint16_t /*classId*/, uint16_t /*methodId*/) -{ - client.closeOk(context.getRequestId()); - connection.getOutput().close(); -} - -void BrokerAdapter::ConnectionHandlerImpl::closeOk(const MethodContext&){ - connection.getOutput().close(); -} - -void BrokerAdapter::ChannelHandlerImpl::open( - const MethodContext& context, const string& /*outOfBand*/){ - channel.open(); - // FIXME aconway 2007-01-04: provide valid ID as per ampq 0-9 - client.openOk( - std::string()/* ID */, context.getRequestId()); -} - -void BrokerAdapter::ChannelHandlerImpl::flow(const MethodContext&, bool /*active*/){} -void BrokerAdapter::ChannelHandlerImpl::flowOk(const MethodContext&, bool /*active*/){} - -void BrokerAdapter::ChannelHandlerImpl::close( - const MethodContext& context, uint16_t /*replyCode*/, - const string& /*replyText*/, - uint16_t /*classId*/, uint16_t /*methodId*/) -{ - client.closeOk(context.getRequestId()); - // FIXME aconway 2007-01-18: Following line will "delete this". Ugly. - connection.closeChannel(channel.getId()); -} - -void BrokerAdapter::ChannelHandlerImpl::closeOk(const MethodContext&){} - - - -void BrokerAdapter::ExchangeHandlerImpl::declare(const MethodContext& context, uint16_t /*ticket*/, const string& exchange, const string& type, - bool passive, bool /*durable*/, bool /*autoDelete*/, bool /*internal*/, bool nowait, - const FieldTable& /*arguments*/){ - - if(passive){ - if(!broker.getExchanges().get(exchange)) { - throw ChannelException(404, "Exchange not found: " + exchange); - } - }else{ - try{ - std::pair response = broker.getExchanges().declare(exchange, type); - if(!response.second && response.first->getType() != type){ - throw ConnectionException( - 530, - "Exchange already declared to be of type " - + response.first->getType() + ", requested " + type); - } - }catch(UnknownExchangeTypeException& e){ - throw ConnectionException( - 503, "Exchange type not implemented: " + type); - } - } - if(!nowait){ - client.declareOk(context.getRequestId()); - } -} - -void BrokerAdapter::ExchangeHandlerImpl::delete_(const MethodContext& context, uint16_t /*ticket*/, - const string& exchange, bool /*ifUnused*/, bool nowait){ - - //TODO: implement unused - broker.getExchanges().destroy(exchange); - if(!nowait) client.deleteOk(context.getRequestId()); -} - -void BrokerAdapter::QueueHandlerImpl::declare(const MethodContext& context, uint16_t /*ticket*/, const string& name, - bool passive, bool durable, bool exclusive, - bool autoDelete, bool nowait, const qpid::framing::FieldTable& arguments){ - Queue::shared_ptr queue; - if (passive && !name.empty()) { - queue = connection.getQueue(name, channel.getId()); - } else { - std::pair queue_created = - broker.getQueues().declare( - name, durable, - autoDelete ? connection.getTimeout() : 0, - exclusive ? &connection : 0); - queue = queue_created.first; - assert(queue); - if (queue_created.second) { // This is a new queue - channel.setDefaultQueue(queue); - - //apply settings & create persistent record if required - queue_created.first->create(arguments); - - //add default binding: - broker.getExchanges().getDefault()->bind(queue, name, 0); - if (exclusive) { - connection.exclusiveQueues.push_back(queue); - } else if(autoDelete){ - broker.getCleaner().add(queue); - } - } - } - if (exclusive && !queue->isExclusiveOwner(&connection)) - throw ChannelException( - 405, - format("Cannot grant exclusive access to queue '%s'") - % queue->getName()); - if (!nowait) { - string queueName = queue->getName(); - client.declareOk( - queueName, queue->getMessageCount(), queue->getConsumerCount(), - context.getRequestId()); - } -} - -void BrokerAdapter::QueueHandlerImpl::bind(const MethodContext& context, uint16_t /*ticket*/, const string& queueName, - const string& exchangeName, const string& routingKey, bool nowait, - const FieldTable& arguments){ - - Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); - Exchange::shared_ptr exchange = broker.getExchanges().get(exchangeName); - if(exchange){ - string exchangeRoutingKey = routingKey.empty() && queueName.empty() ? queue->getName() : routingKey; - exchange->bind(queue, exchangeRoutingKey, &arguments); - if(!nowait) client.bindOk(context.getRequestId()); - }else{ - throw ChannelException( - 404, "Bind failed. No such exchange: " + exchangeName); - } -} - -void -BrokerAdapter::QueueHandlerImpl::unbind( - const MethodContext& context, - uint16_t /*ticket*/, - const string& queueName, - const string& exchangeName, - const string& routingKey, - const qpid::framing::FieldTable& arguments ) -{ - Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); - if (!queue.get()) throw ChannelException(404, "Unbind failed. No such exchange: " + exchangeName); - - Exchange::shared_ptr exchange = broker.getExchanges().get(exchangeName); - if (!exchange.get()) throw ChannelException(404, "Unbind failed. No such exchange: " + exchangeName); - - exchange->unbind(queue, routingKey, &arguments); - - client.unbindOk(context.getRequestId()); -} - -void BrokerAdapter::QueueHandlerImpl::purge(const MethodContext& context, uint16_t /*ticket*/, const string& queueName, bool nowait){ - - Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); - int count = queue->purge(); - if(!nowait) client.purgeOk( count, context.getRequestId()); -} - -void BrokerAdapter::QueueHandlerImpl::delete_(const MethodContext& context, uint16_t /*ticket*/, const string& queue, - bool ifUnused, bool ifEmpty, bool nowait){ - ChannelException error(0, ""); - int count(0); - Queue::shared_ptr q = connection.getQueue(queue, channel.getId()); - if(ifEmpty && q->getMessageCount() > 0){ - throw ChannelException(406, "Queue not empty."); - }else if(ifUnused && q->getConsumerCount() > 0){ - throw ChannelException(406, "Queue in use."); - }else{ - //remove the queue from the list of exclusive queues if necessary - if(q->isExclusiveOwner(&connection)){ - QueueVector::iterator i = find(connection.exclusiveQueues.begin(), connection.exclusiveQueues.end(), q); - if(i < connection.exclusiveQueues.end()) connection.exclusiveQueues.erase(i); - } - count = q->getMessageCount(); - q->destroy(); - broker.getQueues().destroy(queue); - } - - if(!nowait) - client.deleteOk(count, context.getRequestId()); -} - - - - -void BrokerAdapter::BasicHandlerImpl::qos(const MethodContext& context, uint32_t prefetchSize, uint16_t prefetchCount, bool /*global*/){ - //TODO: handle global - channel.setPrefetchSize(prefetchSize); - channel.setPrefetchCount(prefetchCount); - client.qosOk(context.getRequestId()); -} - -void BrokerAdapter::BasicHandlerImpl::consume( - const MethodContext& context, uint16_t /*ticket*/, - const string& queueName, const string& consumerTag, - bool noLocal, bool noAck, bool exclusive, - bool nowait, const FieldTable& fields) -{ - - Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); - if(!consumerTag.empty() && channel.exists(consumerTag)){ - throw ConnectionException(530, "Consumer tags must be unique"); - } - - string newTag = consumerTag; - channel.consume( - newTag, queue, !noAck, exclusive, noLocal ? &connection : 0, &fields); - - if(!nowait) client.consumeOk(newTag, context.getRequestId()); - - //allow messages to be dispatched if required as there is now a consumer: - queue->dispatch(); -} - -void BrokerAdapter::BasicHandlerImpl::cancel(const MethodContext& context, const string& consumerTag, bool nowait){ - channel.cancel(consumerTag); - - if(!nowait) client.cancelOk(consumerTag, context.getRequestId()); -} - -void BrokerAdapter::BasicHandlerImpl::publish( - const MethodContext& context, uint16_t /*ticket*/, - const string& exchangeName, const string& routingKey, - bool mandatory, bool immediate) -{ - - Exchange::shared_ptr exchange = exchangeName.empty() ? broker.getExchanges().getDefault() : broker.getExchanges().get(exchangeName); - if(exchange){ - BasicMessage* msg = new BasicMessage( - &connection, exchangeName, routingKey, mandatory, immediate, - context.methodBody); - channel.handlePublish(msg); - }else{ - throw ChannelException( - 404, "Exchange not found '" + exchangeName + "'"); - } -} - -void BrokerAdapter::BasicHandlerImpl::get(const MethodContext& context, uint16_t /*ticket*/, const string& queueName, bool noAck){ - Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); - if(!connection.getChannel(channel.getId()).get(queue, "", !noAck)){ - string clusterId;//not used, part of an imatix hack - - client.getEmpty(clusterId, context.getRequestId()); - } -} - -void BrokerAdapter::BasicHandlerImpl::ack(const MethodContext&, uint64_t deliveryTag, bool multiple){ - channel.ack(deliveryTag, multiple); -} - -void BrokerAdapter::BasicHandlerImpl::reject(const MethodContext&, uint64_t /*deliveryTag*/, bool /*requeue*/){} - -void BrokerAdapter::BasicHandlerImpl::recover(const MethodContext&, bool requeue){ - channel.recover(requeue); -} - -void BrokerAdapter::TxHandlerImpl::select(const MethodContext& context){ - channel.begin(); - client.selectOk(context.getRequestId()); -} - -void BrokerAdapter::TxHandlerImpl::commit(const MethodContext& context){ - channel.commit(); - client.commitOk(context.getRequestId()); -} - -void BrokerAdapter::TxHandlerImpl::rollback(const MethodContext& context){ - - channel.rollback(); - client.rollbackOk(context.getRequestId()); - channel.recover(false); -} - -void -BrokerAdapter::ChannelHandlerImpl::ok( const MethodContext& ) -{ - //no specific action required, generic response handling should be sufficient -} - - -// -// Message class method handlers -// -void -BrokerAdapter::ChannelHandlerImpl::ping( const MethodContext& context) -{ - client.ok(context.getRequestId()); - client.pong(); -} - - -void -BrokerAdapter::ChannelHandlerImpl::pong( const MethodContext& context) -{ - client.ok(context.getRequestId()); -} - -void -BrokerAdapter::ChannelHandlerImpl::resume( - const MethodContext&, - const string& /*channel*/ ) -{ - assert(0); // FIXME aconway 2007-01-04: 0-9 feature -} - -}} // namespace qpid::broker - diff --git a/qpid/cpp/lib/broker/BrokerAdapter.h b/qpid/cpp/lib/broker/BrokerAdapter.h deleted file mode 100644 index 2fafbcc180..0000000000 --- a/qpid/cpp/lib/broker/BrokerAdapter.h +++ /dev/null @@ -1,222 +0,0 @@ -#ifndef _broker_BrokerAdapter_h -#define _broker_BrokerAdapter_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 "AMQP_ServerOperations.h" -#include "HandlerImpl.h" -#include "MessageHandlerImpl.h" -#include "Exception.h" - -namespace qpid { -namespace broker { - -class Channel; -class Connection; -class Broker; -class ChannelHandler; -class ConnectionHandler; -class BasicHandler; -class ExchangeHandler; -class QueueHandler; -class TxHandler; -class MessageHandler; -class AccessHandler; -class FileHandler; -class StreamHandler; -class DtxHandler; -class TunnelHandler; -class MessageHandlerImpl; - -/** - * Per-channel protocol adapter. - * - * A container for a collection of AMQP-class adapters that translate - * AMQP method bodies into calls on the core Channel, Connection and - * Broker objects. Each adapter class also provides a client proxy - * to send methods to the peer. - * - */ -class BrokerAdapter : public CoreRefs, public framing::AMQP_ServerOperations -{ - public: - BrokerAdapter(Channel& ch, Connection& c, Broker& b); - - framing::ProtocolVersion getVersion() const; - ChannelHandler* getChannelHandler() { return &channelHandler; } - ConnectionHandler* getConnectionHandler() { return &connectionHandler; } - BasicHandler* getBasicHandler() { return &basicHandler; } - ExchangeHandler* getExchangeHandler() { return &exchangeHandler; } - QueueHandler* getQueueHandler() { return &queueHandler; } - TxHandler* getTxHandler() { return &txHandler; } - MessageHandler* getMessageHandler() { return &messageHandler; } - AccessHandler* getAccessHandler() { - throw ConnectionException(540, "Access class not implemented"); } - FileHandler* getFileHandler() { - throw ConnectionException(540, "File class not implemented"); } - StreamHandler* getStreamHandler() { - throw ConnectionException(540, "Stream class not implemented"); } - DtxHandler* getDtxHandler() { - throw ConnectionException(540, "Dtx class not implemented"); } - TunnelHandler* getTunnelHandler() { - throw ConnectionException(540, "Tunnel class not implemented"); } - - framing::AMQP_ClientProxy& getProxy() { return proxy; } - - private: - - class ConnectionHandlerImpl : - public ConnectionHandler, - public HandlerImpl - { - public: - ConnectionHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} - - void startOk(const framing::MethodContext& context, - const qpid::framing::FieldTable& clientProperties, - const std::string& mechanism, const std::string& response, - const std::string& locale); - void secureOk(const framing::MethodContext& context, - const std::string& response); - void tuneOk(const framing::MethodContext& context, - uint16_t channelMax, - uint32_t frameMax, uint16_t heartbeat); - void open(const framing::MethodContext& context, - const std::string& virtualHost, - const std::string& capabilities, bool insist); - void close(const framing::MethodContext& context, uint16_t replyCode, - const std::string& replyText, - uint16_t classId, uint16_t methodId); - void closeOk(const framing::MethodContext& context); - }; - - class ChannelHandlerImpl : - public ChannelHandler, - public HandlerImpl - { - public: - ChannelHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} - - void open(const framing::MethodContext& context, const std::string& outOfBand); - void flow(const framing::MethodContext& context, bool active); - void flowOk(const framing::MethodContext& context, bool active); - void ok( const framing::MethodContext& context ); - void ping( const framing::MethodContext& context ); - void pong( const framing::MethodContext& context ); - void resume( const framing::MethodContext& context, const std::string& channelId ); - void close(const framing::MethodContext& context, uint16_t replyCode, const - std::string& replyText, uint16_t classId, uint16_t methodId); - void closeOk(const framing::MethodContext& context); - }; - - class ExchangeHandlerImpl : - public ExchangeHandler, - public HandlerImpl - { - public: - ExchangeHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} - - void declare(const framing::MethodContext& context, uint16_t ticket, - const std::string& exchange, const std::string& type, - bool passive, bool durable, bool autoDelete, - bool internal, bool nowait, - const qpid::framing::FieldTable& arguments); - void delete_(const framing::MethodContext& context, uint16_t ticket, - const std::string& exchange, bool ifUnused, bool nowait); - }; - - class QueueHandlerImpl : - public QueueHandler, - public HandlerImpl - { - public: - QueueHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} - - void declare(const framing::MethodContext& context, uint16_t ticket, const std::string& queue, - bool passive, bool durable, bool exclusive, - bool autoDelete, bool nowait, - const qpid::framing::FieldTable& arguments); - void bind(const framing::MethodContext& context, uint16_t ticket, const std::string& queue, - const std::string& exchange, const std::string& routingKey, - bool nowait, const qpid::framing::FieldTable& arguments); - void unbind(const framing::MethodContext& context, - uint16_t ticket, - const std::string& queue, - const std::string& exchange, - const std::string& routingKey, - const qpid::framing::FieldTable& arguments ); - void purge(const framing::MethodContext& context, uint16_t ticket, const std::string& queue, - bool nowait); - void delete_(const framing::MethodContext& context, uint16_t ticket, const std::string& queue, - bool ifUnused, bool ifEmpty, - bool nowait); - }; - - class BasicHandlerImpl : - public BasicHandler, - public HandlerImpl - { - public: - BasicHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} - - void qos(const framing::MethodContext& context, uint32_t prefetchSize, - uint16_t prefetchCount, bool global); - void consume( - const framing::MethodContext& context, uint16_t ticket, const std::string& queue, - const std::string& consumerTag, bool noLocal, bool noAck, - bool exclusive, bool nowait, - const qpid::framing::FieldTable& fields); - void cancel(const framing::MethodContext& context, const std::string& consumerTag, - bool nowait); - void publish(const framing::MethodContext& context, uint16_t ticket, - const std::string& exchange, const std::string& routingKey, - bool mandatory, bool immediate); - void get(const framing::MethodContext& context, uint16_t ticket, const std::string& queue, - bool noAck); - void ack(const framing::MethodContext& context, uint64_t deliveryTag, bool multiple); - void reject(const framing::MethodContext& context, uint64_t deliveryTag, bool requeue); - void recover(const framing::MethodContext& context, bool requeue); - }; - - class TxHandlerImpl : - public TxHandler, - public HandlerImpl - { - public: - TxHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} - - void select(const framing::MethodContext& context); - void commit(const framing::MethodContext& context); - void rollback(const framing::MethodContext& context); - }; - - Connection& connection; - BasicHandlerImpl basicHandler; - ChannelHandlerImpl channelHandler; - ConnectionHandlerImpl connectionHandler; - ExchangeHandlerImpl exchangeHandler; - MessageHandlerImpl messageHandler; - QueueHandlerImpl queueHandler; - TxHandlerImpl txHandler; - -}; -}} // namespace qpid::broker - - - -#endif /*!_broker_BrokerAdapter_h*/ diff --git a/qpid/cpp/lib/broker/BrokerChannel.cpp b/qpid/cpp/lib/broker/BrokerChannel.cpp deleted file mode 100644 index 5897914f26..0000000000 --- a/qpid/cpp/lib/broker/BrokerChannel.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 - -#include -#include -#include -#include - -#include - -#include "BrokerChannel.h" -#include "DeletingTxOp.h" -#include "framing/ChannelAdapter.h" -#include -#include -#include -#include -#include -#include -#include -#include "BrokerAdapter.h" -#include "Connection.h" - -using std::mem_fun_ref; -using std::bind2nd; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - - -Channel::Channel( - Connection& con, ChannelId id, - uint32_t _framesize, MessageStore* const _store, - uint64_t _stagingThreshold -) : - ChannelAdapter(id, &con.getOutput(), con.getVersion()), - connection(con), - currentDeliveryTag(1), - transactional(false), - prefetchSize(0), - prefetchCount(0), - framesize(_framesize), - tagGenerator("sgen"), - accumulatedAck(0), - store(_store), - messageBuilder(this, _store, _stagingThreshold), - opened(id == 0),//channel 0 is automatically open, other must be explicitly opened - adapter(new BrokerAdapter(*this, con, con.broker)) -{ - outstanding.reset(); -} - -Channel::~Channel(){ - close(); -} - -bool Channel::exists(const string& consumerTag){ - return consumers.find(consumerTag) != consumers.end(); -} - -// TODO aconway 2007-02-12: Why is connection token passed in instead -// of using the channel's parent connection? -void Channel::consume(string& tagInOut, Queue::shared_ptr queue, bool acks, - bool exclusive, ConnectionToken* const connection, - const FieldTable*) -{ - if(tagInOut.empty()) - tagInOut = tagGenerator.generate(); - std::auto_ptr c( - new ConsumerImpl(this, tagInOut, queue, connection, acks)); - queue->consume(c.get(), exclusive);//may throw exception - consumers.insert(tagInOut, c.release()); -} - -void Channel::cancel(const string& tag){ - // consumers is a ptr_map so erase will delete the consumer - // which will call cancel. - ConsumerImplMap::iterator i = consumers.find(tag); - if (i != consumers.end()) - consumers.erase(i); -} - -void Channel::close(){ - opened = false; - consumers.clear(); - recover(true); -} - -void Channel::begin(){ - transactional = true; -} - -void Channel::commit(){ - TxAck txAck(accumulatedAck, unacked); - txBuffer.enlist(&txAck); - if(txBuffer.prepare(store)){ - txBuffer.commit(); - } - accumulatedAck.clear(); -} - -void Channel::rollback(){ - txBuffer.rollback(); - accumulatedAck.clear(); -} - -void Channel::deliver( - Message::shared_ptr& msg, const string& consumerTag, - Queue::shared_ptr& queue, bool ackExpected) -{ - Mutex::ScopedLock locker(deliveryLock); - - // Key the delivered messages to the id of the request in which they're sent - uint64_t deliveryTag = getNextSendRequestId(); - - if(ackExpected){ - unacked.push_back(DeliveryRecord(msg, queue, consumerTag, deliveryTag)); - outstanding.size += msg->contentSize(); - outstanding.count++; - } - //send deliver method, header and content(s) - msg->deliver(*this, consumerTag, deliveryTag, framesize); -} - -bool Channel::checkPrefetch(Message::shared_ptr& msg){ - Mutex::ScopedLock locker(deliveryLock); - bool countOk = !prefetchCount || prefetchCount > unacked.size(); - bool sizeOk = !prefetchSize || prefetchSize > msg->contentSize() + outstanding.size || unacked.empty(); - return countOk && sizeOk; -} - -Channel::ConsumerImpl::ConsumerImpl(Channel* _parent, const string& _tag, - Queue::shared_ptr _queue, - ConnectionToken* const _connection, bool ack -) : parent(_parent), tag(_tag), queue(_queue), connection(_connection), - ackExpected(ack), blocked(false) {} - -bool Channel::ConsumerImpl::deliver(Message::shared_ptr& msg){ - if(!connection || connection != msg->getPublisher()){//check for no_local - if(ackExpected && !parent->checkPrefetch(msg)){ - blocked = true; - }else{ - blocked = false; - parent->deliver(msg, tag, queue, ackExpected); - return true; - } - } - return false; -} - -Channel::ConsumerImpl::~ConsumerImpl() { - cancel(); -} - -void Channel::ConsumerImpl::cancel(){ - if(queue) - queue->cancel(this); -} - -void Channel::ConsumerImpl::requestDispatch(){ - if(blocked) - queue->dispatch(); -} - -void Channel::handleInlineTransfer(Message::shared_ptr msg) -{ - Exchange::shared_ptr exchange = - connection.broker.getExchanges().get(msg->getExchange()); - if(transactional){ - TxPublish* deliverable = new TxPublish(msg); - exchange->route( - *deliverable, msg->getRoutingKey(), - &(msg->getApplicationHeaders())); - txBuffer.enlist(new DeletingTxOp(deliverable)); - }else{ - DeliverableMessage deliverable(msg); - exchange->route( - deliverable, msg->getRoutingKey(), - &(msg->getApplicationHeaders())); - } -} - -void Channel::handlePublish(Message* _message){ - Message::shared_ptr message(_message); - messageBuilder.initialise(message); -} - -void Channel::handleHeader(AMQHeaderBody::shared_ptr header){ - messageBuilder.setHeader(header); - //at this point, decide based on the size of the message whether we want - //to stage it by saving content directly to disk as it arrives -} - -void Channel::handleContent(AMQContentBody::shared_ptr content){ - messageBuilder.addContent(content); -} - -void Channel::handleHeartbeat(boost::shared_ptr) { - // TODO aconway 2007-01-17: Implement heartbeating. -} - -void Channel::complete(Message::shared_ptr msg) { - Exchange::shared_ptr exchange = - connection.broker.getExchanges().get(msg->getExchange()); - assert(exchange.get()); - if(transactional) { - std::auto_ptr deliverable(new TxPublish(msg)); - exchange->route(*deliverable, msg->getRoutingKey(), - &(msg->getApplicationHeaders())); - txBuffer.enlist(new DeletingTxOp(deliverable.release())); - } else { - DeliverableMessage deliverable(msg); - exchange->route(deliverable, msg->getRoutingKey(), - &(msg->getApplicationHeaders())); - } -} - -void Channel::ack(){ - ack(getFirstAckRequest(), getLastAckRequest()); -} - -// Used by Basic -void Channel::ack(uint64_t deliveryTag, bool multiple){ - if (multiple) - ack(0, deliveryTag); - else - ack(deliveryTag, deliveryTag); -} - -void Channel::ack(uint64_t firstTag, uint64_t lastTag){ - if(transactional){ - accumulatedAck.update(firstTag, lastTag); - - //TODO: I think the outstanding prefetch size & count should be updated at this point... - //TODO: ...this may then necessitate dispatching to consumers - }else{ - Mutex::ScopedLock locker(deliveryLock);//need to synchronize with possible concurrent delivery - - ack_iterator i = find_if(unacked.begin(), unacked.end(), bind2nd(mem_fun_ref(&DeliveryRecord::matches), lastTag)); - ack_iterator j = (firstTag == 0) ? - unacked.begin() : - find_if(unacked.begin(), unacked.end(), bind2nd(mem_fun_ref(&DeliveryRecord::matches), firstTag)); - - if(i == unacked.end()){ - throw ConnectionException(530, "Received ack for unrecognised delivery tag"); - }else if(i!=j){ - ack_iterator end = ++i; - for_each(j, end, bind2nd(mem_fun_ref(&DeliveryRecord::discard), 0)); - unacked.erase(unacked.begin(), end); - - //recalculate the prefetch: - outstanding.reset(); - for_each(unacked.begin(), unacked.end(), bind2nd(mem_fun_ref(&DeliveryRecord::addTo), &outstanding)); - }else{ - i->discard(); - i->subtractFrom(&outstanding); - unacked.erase(i); - } - - //if the prefetch limit had previously been reached, there may - //be messages that can be now be delivered - std::for_each(consumers.begin(), consumers.end(), - boost::bind(&ConsumerImpl::requestDispatch, _1)); - } -} - -void Channel::recover(bool requeue){ - Mutex::ScopedLock locker(deliveryLock);//need to synchronize with possible concurrent delivery - - if(requeue){ - outstanding.reset(); - std::list copy = unacked; - unacked.clear(); - for_each(copy.begin(), copy.end(), mem_fun_ref(&DeliveryRecord::requeue)); - }else{ - for_each(unacked.begin(), unacked.end(), bind2nd(mem_fun_ref(&DeliveryRecord::redeliver), this)); - } -} - -bool Channel::get(Queue::shared_ptr queue, const string& destination, bool ackExpected){ - Message::shared_ptr msg = queue->dequeue(); - if(msg){ - Mutex::ScopedLock locker(deliveryLock); - uint64_t myDeliveryTag = getNextSendRequestId(); - msg->sendGetOk(MethodContext(this, msg->getRespondTo()), - destination, - queue->getMessageCount() + 1, myDeliveryTag, - framesize); - if(ackExpected){ - unacked.push_back(DeliveryRecord(msg, queue, myDeliveryTag)); - } - return true; - }else{ - return false; - } -} - -void Channel::deliver(Message::shared_ptr& msg, const string& consumerTag, - uint64_t deliveryTag) -{ - msg->deliver(*this, consumerTag, deliveryTag, framesize); -} - -void Channel::handleMethodInContext( - boost::shared_ptr method, - const MethodContext& context -) -{ - try{ - if(getId() != 0 && !method->isA() && !isOpen()) { - std::stringstream out; - out << "Attempt to use unopened channel: " << getId(); - throw ConnectionException(504, out.str()); - } else { - method->invoke(*adapter, context); - } - }catch(ChannelException& e){ - adapter->getProxy().getChannel().close( - e.code, e.toString(), - method->amqpClassId(), method->amqpMethodId()); - connection.closeChannel(getId()); - }catch(ConnectionException& e){ - connection.close(e.code, e.toString(), method->amqpClassId(), method->amqpMethodId()); - }catch(std::exception& e){ - connection.close(541/*internal error*/, e.what(), method->amqpClassId(), method->amqpMethodId()); - } -} diff --git a/qpid/cpp/lib/broker/BrokerChannel.h b/qpid/cpp/lib/broker/BrokerChannel.h deleted file mode 100644 index 5085783685..0000000000 --- a/qpid/cpp/lib/broker/BrokerChannel.h +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef _broker_BrokerChannel_h -#define _broker_BrokerChannel_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "framing/ChannelAdapter.h" -#include "ChannelOpenBody.h" -#include "CompletionHandler.h" - -namespace qpid { -namespace broker { - -class ConnectionToken; -class Connection; -class Queue; -class BrokerAdapter; - -using framing::string; - -/** - * Maintains state for an AMQP channel. Handles incoming and - * outgoing messages for that channel. - */ -class Channel : public framing::ChannelAdapter, - public CompletionHandler -{ - class ConsumerImpl : public Consumer - { - Channel* parent; - const string tag; - Queue::shared_ptr queue; - ConnectionToken* const connection; - const bool ackExpected; - bool blocked; - - public: - ConsumerImpl(Channel* parent, const string& tag, - Queue::shared_ptr queue, - ConnectionToken* const connection, bool ack); - ~ConsumerImpl(); - virtual bool deliver(Message::shared_ptr& msg); - void cancel(); - void requestDispatch(); - }; - - typedef boost::ptr_map ConsumerImplMap; - - Connection& connection; - uint64_t currentDeliveryTag; - Queue::shared_ptr defaultQueue; - bool transactional; - ConsumerImplMap consumers; - uint32_t prefetchSize; - uint16_t prefetchCount; - Prefetch outstanding; - uint32_t framesize; - NameGenerator tagGenerator; - std::list unacked; - sys::Mutex deliveryLock; - TxBuffer txBuffer; - AccumulatedAck accumulatedAck; - MessageStore* const store; - MessageBuilder messageBuilder;//builder for in-progress message - bool opened; - boost::scoped_ptr adapter; - - // completion handler for MessageBuilder - void complete(Message::shared_ptr msg); - - void deliver(Message::shared_ptr& msg, const string& tag, - Queue::shared_ptr& queue, bool ackExpected); - bool checkPrefetch(Message::shared_ptr& msg); - - public: - Channel(Connection& parent, - framing::ChannelId id, - uint32_t framesize, - MessageStore* const _store = 0, - uint64_t stagingThreshold = 0); - - ~Channel(); - - bool isOpen() const { return opened; } - BrokerAdapter& getAdatper() { return *adapter; } - - void open() { opened = true; } - void setDefaultQueue(Queue::shared_ptr queue){ defaultQueue = queue; } - Queue::shared_ptr getDefaultQueue() const { return defaultQueue; } - uint32_t setPrefetchSize(uint32_t size){ return prefetchSize = size; } - uint16_t setPrefetchCount(uint16_t n){ return prefetchCount = n; } - - bool exists(const string& consumerTag); - - /** - *@param tagInOut - if empty it is updated with the generated token. - */ - void consume(string& tagInOut, Queue::shared_ptr queue, bool acks, - bool exclusive, ConnectionToken* const connection = 0, - const framing::FieldTable* = 0); - void cancel(const string& tag); - bool get(Queue::shared_ptr queue, const std::string& destination, bool ackExpected); - void begin(); - void close(); - void commit(); - void rollback(); - void ack(); - void ack(uint64_t deliveryTag, bool multiple); - void ack(uint64_t deliveryTag, uint64_t endTag); - void recover(bool requeue); - void deliver(Message::shared_ptr& msg, const string& consumerTag, uint64_t deliveryTag); - void handlePublish(Message* msg); - void handleHeader(boost::shared_ptr); - void handleContent(boost::shared_ptr); - void handleHeartbeat(boost::shared_ptr); - - void handleInlineTransfer(Message::shared_ptr msg); - - // For ChannelAdapter - void handleMethodInContext( - boost::shared_ptr method, - const framing::MethodContext& context); -}; - -}} // namespace broker - - -#endif /*!_broker_BrokerChannel_h*/ diff --git a/qpid/cpp/lib/broker/BrokerExchange.h b/qpid/cpp/lib/broker/BrokerExchange.h deleted file mode 100644 index 6f4e9e6671..0000000000 --- a/qpid/cpp/lib/broker/BrokerExchange.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _broker_BrokerExchange_h -#define _broker_BrokerExchange_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 broker { - using std::string; - - class Exchange{ - const string name; - public: - typedef boost::shared_ptr shared_ptr; - - explicit Exchange(const string& _name) : name(_name){} - virtual ~Exchange(){} - string getName() { return name; } - virtual string getType() = 0; - virtual void bind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args) = 0; - virtual void unbind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args) = 0; - virtual void route(Deliverable& msg, const string& routingKey, const qpid::framing::FieldTable* args) = 0; - }; - } -} - - -#endif /*!_broker_BrokerExchange_h*/ diff --git a/qpid/cpp/lib/broker/BrokerMessage.cpp b/qpid/cpp/lib/broker/BrokerMessage.cpp deleted file mode 100644 index b14efb966e..0000000000 --- a/qpid/cpp/lib/broker/BrokerMessage.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "AMQMethodBody.h" -#include "AMQFrame.h" -#include "framing/ChannelAdapter.h" -#include "RecoveryManagerImpl.h" - -using namespace boost; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -BasicMessage::BasicMessage( - const ConnectionToken* const _publisher, - const string& _exchange, const string& _routingKey, - bool _mandatory, bool _immediate, framing::AMQMethodBody::shared_ptr respondTo -) : - Message(_publisher, _exchange, _routingKey, _mandatory, - _immediate, respondTo), - size(0) -{} - -// For tests only. -BasicMessage::BasicMessage() : size(0) -{} - -BasicMessage::~BasicMessage(){} - -void BasicMessage::setHeader(AMQHeaderBody::shared_ptr _header){ - this->header = _header; -} - -void BasicMessage::addContent(AMQContentBody::shared_ptr data){ - if (!content.get()) { - content = std::auto_ptr(new InMemoryContent()); - } - content->add(data); - size += data->size(); -} - -bool BasicMessage::isComplete(){ - return header.get() && (header->getContentSize() == contentSize()); -} - -void BasicMessage::deliver(ChannelAdapter& channel, - const string& consumerTag, uint64_t deliveryTag, - uint32_t framesize) -{ - // CCT -- TODO - Update code generator to take pointer/ not - // instance to avoid extra contruction - channel.send( - new BasicDeliverBody( - channel.getVersion(), consumerTag, deliveryTag, - getRedelivered(), getExchange(), getRoutingKey())); - sendContent(channel, framesize); -} - -void BasicMessage::sendGetOk(const MethodContext& context, - const std::string& /*destination*/, - uint32_t messageCount, - uint64_t deliveryTag, - uint32_t framesize) -{ - // CCT -- TODO - Update code generator to take pointer/ not - // instance to avoid extra contruction - context.channel->send( - new BasicGetOkBody( - context.channel->getVersion(), - context.methodBody->getRequestId(), - deliveryTag, getRedelivered(), getExchange(), - getRoutingKey(), messageCount)); - sendContent(*context.channel, framesize); -} - -void BasicMessage::sendContent( - ChannelAdapter& channel, uint32_t framesize) -{ - channel.send(header); - Mutex::ScopedLock locker(contentLock); - if (content.get()) - content->send(channel, framesize); -} - -BasicHeaderProperties* BasicMessage::getHeaderProperties(){ - return boost::polymorphic_downcast( - header->getProperties()); -} - -const FieldTable& BasicMessage::getApplicationHeaders(){ - return getHeaderProperties()->getHeaders(); -} - -bool BasicMessage::isPersistent() -{ - if(!header) return false; - BasicHeaderProperties* props = getHeaderProperties(); - return props && props->getDeliveryMode() == PERSISTENT; -} - -void BasicMessage::decode(Buffer& buffer, bool headersOnly, uint32_t contentChunkSize) -{ - decodeHeader(buffer); - if (!headersOnly) decodeContent(buffer, contentChunkSize); -} - -void BasicMessage::decodeHeader(Buffer& buffer) -{ - //don't care about the type here, but want encode/decode to be symmetric - RecoveryManagerImpl::decodeMessageType(buffer); - - string exchange; - string routingKey; - - buffer.getShortString(exchange); - buffer.getShortString(routingKey); - setRouting(exchange, routingKey); - - uint32_t headerSize = buffer.getLong(); - AMQHeaderBody::shared_ptr headerBody(new AMQHeaderBody()); - headerBody->decode(buffer, headerSize); - setHeader(headerBody); -} - -void BasicMessage::decodeContent(Buffer& buffer, uint32_t chunkSize) -{ - uint64_t expected = expectedContentSize(); - if (expected != buffer.available()) { - std::cout << "WARN: Expected " << expectedContentSize() << " bytes, got " << buffer.available() << std::endl; - throw Exception("Cannot decode content, buffer not large enough."); - } - - if (!chunkSize || chunkSize > expected) { - chunkSize = expected; - } - - uint64_t total = 0; - while (total < expectedContentSize()) { - uint64_t remaining = expected - total; - AMQContentBody::shared_ptr contentBody(new AMQContentBody()); - contentBody->decode(buffer, remaining < chunkSize ? remaining : chunkSize); - addContent(contentBody); - total += chunkSize; - } -} - -void BasicMessage::encode(Buffer& buffer) const -{ - encodeHeader(buffer); - encodeContent(buffer); -} - -void BasicMessage::encodeHeader(Buffer& buffer) const -{ - RecoveryManagerImpl::encodeMessageType(*this, buffer); - buffer.putShortString(getExchange()); - buffer.putShortString(getRoutingKey()); - buffer.putLong(header->size()); - header->encode(buffer); -} - -void BasicMessage::encodeContent(Buffer& buffer) const -{ - Mutex::ScopedLock locker(contentLock); - if (content.get()) content->encode(buffer); -} - -uint32_t BasicMessage::encodedSize() const -{ - return encodedHeaderSize() + encodedContentSize(); -} - -uint32_t BasicMessage::encodedContentSize() const -{ - Mutex::ScopedLock locker(contentLock); - return content.get() ? content->size() : 0; -} - -uint32_t BasicMessage::encodedHeaderSize() const -{ - return RecoveryManagerImpl::encodedMessageTypeSize() - +getExchange().size() + 1 - + getRoutingKey().size() + 1 - + header->size() + 4;//4 extra bytes for size -} - -uint64_t BasicMessage::expectedContentSize() -{ - return header.get() ? header->getContentSize() : 0; -} - -void BasicMessage::releaseContent(MessageStore* store) -{ - Mutex::ScopedLock locker(contentLock); - if (!isPersistent() && getPersistenceId() == 0) { - store->stage(*this); - } - if (!content.get() || content->size() > 0) { - //set content to lazy loading mode (but only if there is - //stored content): - - //Note: the LazyLoadedContent instance contains a raw pointer - //to the message, however it is then set as a member of that - //message so its lifetime is guaranteed to be no longer than - //that of the message itself - content = std::auto_ptr( - new LazyLoadedContent(store, this, expectedContentSize())); - } -} - -void BasicMessage::setContent(std::auto_ptr& _content) -{ - Mutex::ScopedLock locker(contentLock); - content = _content; -} diff --git a/qpid/cpp/lib/broker/BrokerMessage.h b/qpid/cpp/lib/broker/BrokerMessage.h deleted file mode 100644 index 8b408ae669..0000000000 --- a/qpid/cpp/lib/broker/BrokerMessage.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef _broker_BrokerMessage_h -#define _broker_BrokerMessage_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 - -namespace qpid { - -namespace framing { -class MethodContext; -class ChannelAdapter; -class AMQHeaderBody; -} - -namespace broker { - -class MessageStore; -using framing::string; - -/** - * Represents an AMQP message, i.e. a header body, a list of - * content bodies and some details about the publication - * request. - */ -class BasicMessage : public Message { - boost::shared_ptr header; - std::auto_ptr content; - mutable sys::Mutex contentLock; - uint64_t size; - - void sendContent(framing::ChannelAdapter&, uint32_t framesize); - - public: - typedef boost::shared_ptr shared_ptr; - - BasicMessage(const ConnectionToken* const publisher, - const string& exchange, const string& routingKey, - bool mandatory, bool immediate, - boost::shared_ptr respondTo); - BasicMessage(); - ~BasicMessage(); - void setHeader(boost::shared_ptr header); - void addContent(framing::AMQContentBody::shared_ptr data); - bool isComplete(); - - void deliver(framing::ChannelAdapter&, - const string& consumerTag, - uint64_t deliveryTag, - uint32_t framesize); - - void sendGetOk(const framing::MethodContext&, - const std::string& destination, - uint32_t messageCount, - uint64_t deliveryTag, - uint32_t framesize); - - framing::BasicHeaderProperties* getHeaderProperties(); - const framing::FieldTable& getApplicationHeaders(); - bool isPersistent(); - uint64_t contentSize() const { return size; } - - void decode(framing::Buffer& buffer, bool headersOnly = false, - uint32_t contentChunkSize = 0); - void decodeHeader(framing::Buffer& buffer); - void decodeContent(framing::Buffer& buffer, uint32_t contentChunkSize = 0); - - void encode(framing::Buffer& buffer) const; - void encodeHeader(framing::Buffer& buffer) const; - void encodeContent(framing::Buffer& buffer) const; - /** - * @returns the size of the buffer needed to encode this - * message in its entirety - */ - 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; - /** - * @returns the size of the buffer needed to encode the - * (possibly partial) content held by this message - */ - uint32_t encodedContentSize() const; - /** - * Releases the in-memory content data held by this - * message. Must pass in a store from which the data can - * be reloaded. - */ - void releaseContent(MessageStore* store); - /** - * If headers have been received, returns the expected - * content size else returns 0. - */ - uint64_t expectedContentSize(); - /** - * Sets the 'content' implementation of this message (the - * message controls the lifecycle of the content instance - * it uses). - */ - void setContent(std::auto_ptr& content); -}; - -} -} - - -#endif /*!_broker_BrokerMessage_h*/ diff --git a/qpid/cpp/lib/broker/BrokerMessageBase.h b/qpid/cpp/lib/broker/BrokerMessageBase.h deleted file mode 100644 index da0cc57756..0000000000 --- a/qpid/cpp/lib/broker/BrokerMessageBase.h +++ /dev/null @@ -1,182 +0,0 @@ -#ifndef _broker_BrokerMessageBase_h -#define _broker_BrokerMessageBase_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "Content.h" -#include "PersistableMessage.h" -#include "framing/amqp_types.h" - -namespace qpid { - -namespace framing { -class MethodContext; -class ChannelAdapter; -class BasicHeaderProperties; -class FieldTable; -class AMQMethodBody; -class AMQContentBody; -class AMQHeaderBody; -} - - -namespace broker { -class ConnectionToken; -class MessageStore; - -/** - * Base class for all types of internal broker messages - * abstracting away the operations - * TODO; AMS: for the moment this is mostly a placeholder - */ -class Message : public PersistableMessage{ - public: - typedef boost::shared_ptr shared_ptr; - typedef boost::shared_ptr AMQMethodBodyPtr; - - - Message(const ConnectionToken* publisher_, - const std::string& _exchange, - const std::string& _routingKey, - bool _mandatory, bool _immediate, - AMQMethodBodyPtr respondTo_) : - publisher(publisher_), - exchange(_exchange), - routingKey(_routingKey), - mandatory(_mandatory), - immediate(_immediate), - persistenceId(0), - redelivered(false), - respondTo(respondTo_) - {} - - Message() : - mandatory(false), - immediate(false), - persistenceId(0), - redelivered(false) - {} - - virtual ~Message() {}; - - // Accessors - const std::string& getRoutingKey() const { return routingKey; } - const std::string& getExchange() const { return exchange; } - uint64_t getPersistenceId() const { return persistenceId; } - bool getRedelivered() const { return redelivered; } - AMQMethodBodyPtr getRespondTo() const { return respondTo; } - - void setRouting(const std::string& _exchange, const std::string& _routingKey) - { exchange = _exchange; routingKey = _routingKey; } - void setPersistenceId(uint64_t _persistenceId) { persistenceId = _persistenceId; } // XXXX: Only used in tests? - void redeliver() { redelivered = true; } - - /** - * Used to deliver the message from the queue - */ - virtual void deliver(framing::ChannelAdapter& channel, - const std::string& consumerTag, - uint64_t deliveryTag, - uint32_t framesize) = 0; - /** - * Used to return a message in response to a get from a queue - */ - virtual void sendGetOk(const framing::MethodContext& context, - const std::string& destination, - uint32_t messageCount, - uint64_t deliveryTag, - uint32_t framesize) = 0; - - virtual bool isComplete() = 0; - - virtual uint64_t contentSize() const = 0; - virtual framing::BasicHeaderProperties* getHeaderProperties() = 0; - virtual const framing::FieldTable& getApplicationHeaders() = 0; - virtual bool isPersistent() = 0; - virtual const ConnectionToken* getPublisher() const { - return publisher; - } - - virtual void encode(framing::Buffer& buffer) const = 0; - virtual void encodeHeader(framing::Buffer& buffer) const = 0; - - /** - * @returns the size of the buffer needed to encode this - * message in its entirety - */ - virtual uint32_t encodedSize() const = 0; - /** - * @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) - */ - virtual uint32_t encodedHeaderSize() const = 0; - /** - * @returns the size of the buffer needed to encode the - * (possibly partial) content held by this message - */ - virtual uint32_t encodedContentSize() const = 0; - /** - * If headers have been received, returns the expected - * content size else returns 0. - */ - virtual uint64_t expectedContentSize() = 0; - - virtual void decodeHeader(framing::Buffer& buffer) = 0; - virtual void decodeContent(framing::Buffer& buffer, uint32_t contentChunkSize = 0) = 0; - - static shared_ptr decode(framing::Buffer& buffer); - - // TODO: AMS 29/1/2007 Don't think these are really part of base class - - /** - * Sets the 'content' implementation of this message (the - * message controls the lifecycle of the content instance - * it uses). - */ - virtual void setContent(std::auto_ptr& /*content*/) {}; - virtual void setHeader(boost::shared_ptr) {}; - virtual void addContent(boost::shared_ptr) {}; - /** - * Releases the in-memory content data held by this - * message. Must pass in a store from which the data can - * be reloaded. - */ - virtual void releaseContent(MessageStore* /*store*/) {}; - - private: - const ConnectionToken* publisher; - std::string exchange; - std::string routingKey; - const bool mandatory; - const bool immediate; - uint64_t persistenceId; - bool redelivered; - AMQMethodBodyPtr respondTo; -}; - -}} - - -#endif /*!_broker_BrokerMessage_h*/ diff --git a/qpid/cpp/lib/broker/BrokerMessageMessage.cpp b/qpid/cpp/lib/broker/BrokerMessageMessage.cpp deleted file mode 100644 index 73ad961938..0000000000 --- a/qpid/cpp/lib/broker/BrokerMessageMessage.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 "QpidError.h" -#include "BrokerMessageMessage.h" -#include "ChannelAdapter.h" -#include "MessageTransferBody.h" -#include "MessageOpenBody.h" -#include "MessageCloseBody.h" -#include "MessageAppendBody.h" -#include "Reference.h" -#include "framing/AMQFrame.h" -#include "framing/FieldTable.h" -#include "framing/BasicHeaderProperties.h" -#include "RecoveryManagerImpl.h" - -#include - -using namespace std; -using namespace qpid::framing; - -namespace qpid { -namespace broker { - -MessageMessage::MessageMessage( - ConnectionToken* publisher, RequestId requestId_, TransferPtr transfer_ -) : Message(publisher, transfer_->getDestination(), - transfer_->getRoutingKey(), - transfer_->getMandatory(), - transfer_->getImmediate(), - transfer_), - requestId(requestId_), - transfer(transfer_) -{} - -MessageMessage::MessageMessage( - ConnectionToken* publisher, RequestId requestId_, TransferPtr transfer_, - ReferencePtr reference_ -) : Message(publisher, transfer_->getDestination(), - transfer_->getRoutingKey(), - transfer_->getMandatory(), - transfer_->getImmediate(), - transfer_), - requestId(requestId_), - transfer(transfer_), - reference(reference_) -{} - -/** - * Currently used by message store impls to recover messages - */ -MessageMessage::MessageMessage() : transfer(new MessageTransferBody(qpid::framing::highestProtocolVersion)) {} - -// TODO: astitcher 1-Mar-2007: This code desperately needs better factoring -void MessageMessage::transferMessage( - framing::ChannelAdapter& channel, - const std::string& consumerTag, - uint32_t framesize) -{ - const framing::Content& body = transfer->getBody(); - - // Send any reference data - if (!body.isInline()){ - // Open - channel.send(new MessageOpenBody(channel.getVersion(), reference->getId())); - // Appends - for(Reference::Appends::const_iterator a = reference->getAppends().begin(); - a != reference->getAppends().end(); - ++a) { - uint32_t sizeleft = (*a)->size(); - const string& content = (*a)->getBytes(); - // Calculate overhead bytes - // Assume that the overhead is constant as the reference name doesn't change - uint32_t overhead = sizeleft - content.size(); - string::size_type contentStart = 0; - while (sizeleft) { - string::size_type contentSize = sizeleft <= framesize ? sizeleft : framesize-overhead; - channel.send(new MessageAppendBody(channel.getVersion(), reference->getId(), - string(content, contentStart, contentSize))); - sizeleft -= contentSize; - contentStart += contentSize; - } - } - } - - // The transfer - if ( transfer->size()<=framesize ) { - channel.send( - new MessageTransferBody(channel.getVersion(), - transfer->getTicket(), - consumerTag, - getRedelivered(), - transfer->getImmediate(), - transfer->getTtl(), - transfer->getPriority(), - transfer->getTimestamp(), - transfer->getDeliveryMode(), - transfer->getExpiration(), - getExchange(), - getRoutingKey(), - transfer->getMessageId(), - transfer->getCorrelationId(), - transfer->getReplyTo(), - transfer->getContentType(), - transfer->getContentEncoding(), - transfer->getUserId(), - transfer->getAppId(), - transfer->getTransactionId(), - transfer->getSecurityToken(), - transfer->getApplicationHeaders(), - body, - transfer->getMandatory())); - } else { - // Thing to do here is to construct a simple reference message then deliver that instead - // fragmentation will be taken care of in the delivery if necessary; - string content = body.getValue(); - string refname = "dummy"; - TransferPtr newTransfer( - new MessageTransferBody(channel.getVersion(), - transfer->getTicket(), - consumerTag, - getRedelivered(), - transfer->getImmediate(), - transfer->getTtl(), - transfer->getPriority(), - transfer->getTimestamp(), - transfer->getDeliveryMode(), - transfer->getExpiration(), - getExchange(), - getRoutingKey(), - transfer->getMessageId(), - transfer->getCorrelationId(), - transfer->getReplyTo(), - transfer->getContentType(), - transfer->getContentEncoding(), - transfer->getUserId(), - transfer->getAppId(), - transfer->getTransactionId(), - transfer->getSecurityToken(), - transfer->getApplicationHeaders(), - framing::Content(REFERENCE, refname), - transfer->getMandatory())); - ReferencePtr newRef(new Reference(refname)); - Reference::AppendPtr newAppend(new MessageAppendBody(channel.getVersion(), refname, content)); - newRef->append(newAppend); - MessageMessage newMsg(const_cast(getPublisher()), 0, newTransfer, newRef); - newMsg.transferMessage(channel, consumerTag, framesize); - return; - } - // Close any reference data - if (!body.isInline()){ - // Close - channel.send(new MessageCloseBody(channel.getVersion(), reference->getId())); - } -} - -void MessageMessage::deliver( - framing::ChannelAdapter& channel, - const std::string& consumerTag, - uint64_t /*deliveryTag*/, - uint32_t framesize) -{ - transferMessage(channel, consumerTag, framesize); -} - -void MessageMessage::sendGetOk( - const framing::MethodContext& context, - const std::string& destination, - uint32_t /*messageCount*/, - uint64_t /*deliveryTag*/, - uint32_t framesize) -{ - framing::ChannelAdapter* channel = context.channel; - transferMessage(*channel, destination, framesize); -} - -bool MessageMessage::isComplete() -{ - return true; -} - -uint64_t MessageMessage::contentSize() const -{ - if (transfer->getBody().isInline()) - return transfer->getBody().getValue().size(); - else - return reference->getSize(); -} - -qpid::framing::BasicHeaderProperties* MessageMessage::getHeaderProperties() -{ - return 0; // FIXME aconway 2007-02-05: -} - -const FieldTable& MessageMessage::getApplicationHeaders() -{ - return transfer->getApplicationHeaders(); -} -bool MessageMessage::isPersistent() -{ - return transfer->getDeliveryMode() == PERSISTENT; -} - -uint32_t MessageMessage::encodedSize() const -{ - return encodedHeaderSize() + encodedContentSize(); -} - -uint32_t MessageMessage::encodedHeaderSize() const -{ - return RecoveryManagerImpl::encodedMessageTypeSize() + transfer->size() - transfer->baseSize(); -} - -uint32_t MessageMessage::encodedContentSize() const -{ - return 0; -} - -uint64_t MessageMessage::expectedContentSize() -{ - return 0; -} - -void MessageMessage::encode(Buffer& buffer) const -{ - encodeHeader(buffer); -} - -void MessageMessage::encodeHeader(Buffer& buffer) const -{ - RecoveryManagerImpl::encodeMessageType(*this, buffer); - if (transfer->getBody().isInline()) { - transfer->encodeContent(buffer); - } else { - string data; - for(Reference::Appends::const_iterator a = reference->getAppends().begin(); a != reference->getAppends().end(); ++a) { - data += (*a)->getBytes(); - } - framing::Content body(INLINE, data); - std::auto_ptr copy(copyTransfer(transfer->version, transfer->getDestination(), body)); - copy->encodeContent(buffer); - } -} - -void MessageMessage::decodeHeader(Buffer& buffer) -{ - //don't care about the type here, but want encode/decode to be symmetric - RecoveryManagerImpl::decodeMessageType(buffer); - - transfer->decodeContent(buffer); -} - -void MessageMessage::decodeContent(Buffer& /*buffer*/, uint32_t /*chunkSize*/) -{ -} - - -MessageTransferBody* MessageMessage::copyTransfer(const ProtocolVersion& version, - const string& destination, - const framing::Content& body) const -{ - return new MessageTransferBody(version, - transfer->getTicket(), - destination, - getRedelivered(), - transfer->getImmediate(), - transfer->getTtl(), - transfer->getPriority(), - transfer->getTimestamp(), - transfer->getDeliveryMode(), - transfer->getExpiration(), - getExchange(), - getRoutingKey(), - transfer->getMessageId(), - transfer->getCorrelationId(), - transfer->getReplyTo(), - transfer->getContentType(), - transfer->getContentEncoding(), - transfer->getUserId(), - transfer->getAppId(), - transfer->getTransactionId(), - transfer->getSecurityToken(), - transfer->getApplicationHeaders(), - body, - transfer->getMandatory()); - -} -}} // namespace qpid::broker diff --git a/qpid/cpp/lib/broker/BrokerMessageMessage.h b/qpid/cpp/lib/broker/BrokerMessageMessage.h deleted file mode 100644 index 1da171fba8..0000000000 --- a/qpid/cpp/lib/broker/BrokerMessageMessage.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef _broker_BrokerMessageMessage_h -#define _broker_BrokerMessageMessage_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "BrokerMessageBase.h" -#include "MessageTransferBody.h" -#include "amqp_types.h" - -#include - -namespace qpid { - -namespace framing { -class MessageTransferBody; -} - -namespace broker { -class ConnectionToken; -class Reference; - -class MessageMessage: public Message{ - public: - typedef boost::shared_ptr shared_ptr; - typedef boost::shared_ptr TransferPtr; - typedef boost::shared_ptr ReferencePtr; - - MessageMessage(ConnectionToken* publisher, framing::RequestId, TransferPtr transfer); - MessageMessage(ConnectionToken* publisher, framing::RequestId, TransferPtr transfer, ReferencePtr reference); - MessageMessage(); - - // Default destructor okay - - framing::RequestId getRequestId() {return requestId; } - TransferPtr getTransfer() { return transfer; } - ReferencePtr getReference() { return reference; } - - void deliver(framing::ChannelAdapter& channel, - const std::string& consumerTag, - uint64_t deliveryTag, - uint32_t framesize); - - void sendGetOk(const framing::MethodContext& context, - const std::string& destination, - uint32_t messageCount, - uint64_t deliveryTag, - uint32_t framesize); - - bool isComplete(); - - uint64_t contentSize() const; - framing::BasicHeaderProperties* getHeaderProperties(); - const framing::FieldTable& getApplicationHeaders(); - bool isPersistent(); - - void encode(framing::Buffer& buffer) const; - void encodeHeader(framing::Buffer& buffer) const; - uint32_t encodedSize() const; - uint32_t encodedHeaderSize() const; - uint32_t encodedContentSize() const; - uint64_t expectedContentSize(); - void decodeHeader(framing::Buffer& buffer); - void decodeContent(framing::Buffer& buffer, uint32_t contentChunkSize = 0); - - private: - void transferMessage(framing::ChannelAdapter& channel, - const std::string& consumerTag, - uint32_t framesize); - framing::MessageTransferBody* copyTransfer(const framing::ProtocolVersion& version, - const std::string& destination, - const framing::Content& body) const; - - framing::RequestId requestId; - const TransferPtr transfer; - const ReferencePtr reference; -}; - -}} - - -#endif /*!_broker_BrokerMessage_h*/ diff --git a/qpid/cpp/lib/broker/BrokerQueue.cpp b/qpid/cpp/lib/broker/BrokerQueue.cpp deleted file mode 100644 index e2b59aa766..0000000000 --- a/qpid/cpp/lib/broker/BrokerQueue.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "QueueRegistry.h" - -using namespace qpid::broker; -using namespace qpid::sys; -using namespace qpid::framing; -using boost::format; - -Queue::Queue(const string& _name, uint32_t _autodelete, - MessageStore* const _store, - const ConnectionToken* const _owner) : - - name(_name), - autodelete(_autodelete), - store(_store), - owner(_owner), - queueing(false), - dispatching(false), - next(0), - lastUsed(0), - exclusive(0), - persistenceId(0) -{ - if(autodelete) lastUsed = now()/TIME_MSEC; -} - -Queue::~Queue(){} - -void Queue::deliver(Message::shared_ptr& msg){ - enqueue(0, msg); - process(msg); -} - -void Queue::recover(Message::shared_ptr& msg){ - push(msg); - if (store && msg->expectedContentSize() != msg->encodedContentSize()) { - //content has not been loaded, need to ensure that lazy loading mode is set: - //TODO: find a nicer way to do this - msg->releaseContent(store); - } -} - -void Queue::process(Message::shared_ptr& msg){ - Mutex::ScopedLock locker(lock); - if(queueing || !dispatch(msg)){ - push(msg); - } -} - -bool Queue::dispatch(Message::shared_ptr& msg){ - if(consumers.empty()){ - return false; - }else if(exclusive){ - if(!exclusive->deliver(msg)){ - std::cout << "WARNING: Dropping undeliverable message from queue with exclusive consumer." << std::endl; - } - return true; - }else{ - //deliver to next consumer - next = next % consumers.size(); - Consumer* c = consumers[next]; - int start = next; - while(c){ - next++; - if(c->deliver(msg)) return true; - - next = next % consumers.size(); - c = next == start ? 0 : consumers[next]; - } - return false; - } -} - -bool Queue::startDispatching(){ - Mutex::ScopedLock locker(lock); - if(queueing && !dispatching){ - dispatching = true; - return true; - }else{ - return false; - } -} - -void Queue::dispatch(){ - bool proceed = startDispatching(); - while(proceed){ - Mutex::ScopedLock locker(lock); - if(!messages.empty() && dispatch(messages.front())){ - pop(); - }else{ - dispatching = false; - proceed = false; - queueing = !messages.empty(); - } - } -} - -void Queue::consume(Consumer* c, bool requestExclusive){ - Mutex::ScopedLock locker(lock); - if(exclusive) - throw ChannelException( - 403, format("Queue '%s' has an exclusive consumer." - " No more consumers allowed.") % getName()); - if(requestExclusive) { - if(!consumers.empty()) - throw ChannelException( - 403, format("Queue '%s' already has conumers." - "Exclusive access denied.") %getName()); - exclusive = c; - } - if(autodelete && consumers.empty()) lastUsed = 0; - consumers.push_back(c); -} - -void Queue::cancel(Consumer* c){ - Mutex::ScopedLock locker(lock); - Consumers::iterator i = std::find(consumers.begin(), consumers.end(), c); - if (i != consumers.end()) - consumers.erase(i); - if(autodelete && consumers.empty()) lastUsed = now()*TIME_MSEC; - if(exclusive == c) exclusive = 0; -} - -Message::shared_ptr Queue::dequeue(){ - Mutex::ScopedLock locker(lock); - Message::shared_ptr msg; - if(!messages.empty()){ - msg = messages.front(); - pop(); - } - return msg; -} - -uint32_t Queue::purge(){ - Mutex::ScopedLock locker(lock); - int count = messages.size(); - while(!messages.empty()) pop(); - return count; -} - -void Queue::pop(){ - if (policy.get()) policy->dequeued(messages.front()->contentSize()); - messages.pop(); -} - -void Queue::push(Message::shared_ptr& msg){ - queueing = true; - messages.push(msg); - if (policy.get()) { - policy->enqueued(msg->contentSize()); - if (policy->limitExceeded()) { - msg->releaseContent(store); - } - } -} - -uint32_t Queue::getMessageCount() const{ - Mutex::ScopedLock locker(lock); - return messages.size(); -} - -uint32_t Queue::getConsumerCount() const{ - Mutex::ScopedLock locker(lock); - return consumers.size(); -} - -bool Queue::canAutoDelete() const{ - Mutex::ScopedLock locker(lock); - return lastUsed && (now()*TIME_MSEC - lastUsed > autodelete); -} - -void Queue::enqueue(TransactionContext* ctxt, Message::shared_ptr& msg) -{ - if (msg->isPersistent() && store) { - store->enqueue(ctxt, *msg.get(), *this); - } -} - -void Queue::dequeue(TransactionContext* ctxt, Message::shared_ptr& msg) -{ - if (msg->isPersistent() && store) { - store->dequeue(ctxt, *msg.get(), *this); - } -} - -namespace -{ - const std::string qpidMaxSize("qpid.max_size"); - const std::string qpidMaxCount("qpid.max_count"); -} - -void Queue::create(const FieldTable& settings) -{ - //TODO: hold onto settings and persist them as part of encode - // in fact settings should be passed in on construction - if (store) { - store->create(*this); - } - configure(settings); -} - -void Queue::configure(const FieldTable& settings) -{ - std::auto_ptr _policy(new QueuePolicy(settings)); - if (_policy->getMaxCount() || _policy->getMaxSize()) - setPolicy(_policy); -} - -void Queue::destroy() -{ - if (store) { - store->destroy(*this); - } -} - -void Queue::setPolicy(std::auto_ptr _policy) -{ - policy = _policy; -} - -const QueuePolicy* const Queue::getPolicy() -{ - return policy.get(); -} - -uint64_t Queue::getPersistenceId() const -{ - return persistenceId; -} - -void Queue::setPersistenceId(uint64_t _persistenceId) -{ - persistenceId = _persistenceId; -} - -void Queue::encode(framing::Buffer& buffer) const -{ - buffer.putShortString(name); - //TODO store all required properties -} - -uint32_t Queue::encodedSize() const -{ - //TODO, revise when storing full set of queue properties - return name.size() + 1/*short string size octet*/; -} - -Queue::shared_ptr Queue::decode(QueueRegistry& queues, framing::Buffer& buffer) -{ - string name; - buffer.getShortString(name); - std::pair result = queues.declare(name, true); - return result.first; -} - diff --git a/qpid/cpp/lib/broker/BrokerQueue.h b/qpid/cpp/lib/broker/BrokerQueue.h deleted file mode 100644 index 20d81e4e87..0000000000 --- a/qpid/cpp/lib/broker/BrokerQueue.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef _broker_BrokerQueue_h -#define _broker_BrokerQueue_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "PersistableQueue.h" -#include - -// TODO aconway 2007-02-06: Use auto_ptr and boost::ptr_vector to -// enforce ownership of Consumers. - -namespace qpid { - namespace broker { - class MessageStore; - class QueueRegistry; - - /** - * Thrown when exclusive access would be violated. - */ - using std::string; - - /** - * 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 PersistableQueue{ - typedef std::vector Consumers; - typedef std::queue Messages; - - const string name; - const uint32_t autodelete; - MessageStore* const store; - const ConnectionToken* const owner; - Consumers consumers; - Messages messages; - bool queueing; - bool dispatching; - int next; - mutable qpid::sys::Mutex lock; - int64_t lastUsed; - Consumer* exclusive; - mutable uint64_t persistenceId; - std::auto_ptr policy; - - void pop(); - void push(Message::shared_ptr& msg); - bool startDispatching(); - bool dispatch(Message::shared_ptr& msg); - void setPolicy(std::auto_ptr policy); - - public: - - typedef boost::shared_ptr shared_ptr; - - typedef std::vector vector; - - Queue(const string& name, uint32_t autodelete = 0, - MessageStore* const store = 0, - const ConnectionToken* const owner = 0); - ~Queue(); - - void create(const qpid::framing::FieldTable& settings); - void configure(const qpid::framing::FieldTable& settings); - void destroy(); - /** - * Delivers a message to the queue. Will record it as - * enqueued if persistent then process it. - */ - void deliver(Message::shared_ptr& msg); - /** - * Dispatches the messages immediately to a consumer if - * one is available or stores it for later if not. - */ - void process(Message::shared_ptr& msg); - /** - * Used during recovery to add stored messages back to the queue - */ - void recover(Message::shared_ptr& msg); - /** - * Dispatch any queued messages providing there are - * consumers for them. Only one thread can be dispatching - * at any time, but this method (rather than the caller) - * is responsible for ensuring that. - */ - void dispatch(); - void consume(Consumer* c, bool exclusive = false); - void cancel(Consumer* c); - uint32_t purge(); - uint32_t getMessageCount() const; - uint32_t getConsumerCount() const; - inline const string& getName() const { return name; } - inline const bool isExclusiveOwner(const ConnectionToken* const o) const { return o == owner; } - inline bool hasExclusiveConsumer() const { return exclusive; } - - bool canAutoDelete() const; - - void enqueue(TransactionContext* ctxt, Message::shared_ptr& msg); - /** - * dequeue from store (only done once messages is acknowledged) - */ - void dequeue(TransactionContext* ctxt, Message::shared_ptr& msg); - /** - * dequeues from memory only - */ - Message::shared_ptr dequeue(); - - const QueuePolicy* const getPolicy(); - - //PersistableQueue support: - uint64_t getPersistenceId() const; - void setPersistenceId(uint64_t persistenceId); - void encode(framing::Buffer& buffer) const; - uint32_t encodedSize() const; - - static Queue::shared_ptr decode(QueueRegistry& queues, framing::Buffer& buffer); - }; - } -} - - -#endif /*!_broker_BrokerQueue_h*/ diff --git a/qpid/cpp/lib/broker/BrokerSingleton.cpp b/qpid/cpp/lib/broker/BrokerSingleton.cpp deleted file mode 100644 index 4571764850..0000000000 --- a/qpid/cpp/lib/broker/BrokerSingleton.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 "BrokerSingleton.h" - -namespace qpid { -namespace broker { - -BrokerSingleton::BrokerSingleton() { - if (broker.get() == 0) - broker = Broker::create(); - Broker::shared_ptr::operator=(broker); -} - -BrokerSingleton::~BrokerSingleton() { - broker->shutdown(); -} - -Broker::shared_ptr BrokerSingleton::broker; - -}} // namespace qpid::broker diff --git a/qpid/cpp/lib/broker/BrokerSingleton.h b/qpid/cpp/lib/broker/BrokerSingleton.h deleted file mode 100644 index 139e02a5fd..0000000000 --- a/qpid/cpp/lib/broker/BrokerSingleton.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _broker_BrokerSingleton_h -#define _broker_BrokerSingleton_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 "Broker.h" - -namespace qpid { -namespace broker { - -/** - * BrokerSingleton is a smart pointer to a process-wide singleton broker - * started on an os-chosen port. The broker starts the first time - * an instance of BrokerSingleton is created and runs untill the process exits. - * - * Useful for unit tests that want to share a broker between multiple - * tests to reduce overhead of starting/stopping a broker for every test. - * - * Tests that need a new broker can call Broker::create directly. - * - * THREAD UNSAFE. - */ -class BrokerSingleton : public Broker::shared_ptr -{ - public: - BrokerSingleton(); - ~BrokerSingleton(); - private: - static Broker::shared_ptr broker; -}; - -}} // namespace qpid::broker - - - -#endif /*!_broker_BrokerSingleton_h*/ diff --git a/qpid/cpp/lib/broker/CompletionHandler.h b/qpid/cpp/lib/broker/CompletionHandler.h deleted file mode 100644 index 9d51656282..0000000000 --- a/qpid/cpp/lib/broker/CompletionHandler.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _broker_CompletionHandler_h -#define _broker_CompletionHandler_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 broker { - -/** - * Callback interface to handle completion of a message. - */ -class CompletionHandler -{ - public: - virtual ~CompletionHandler(){} - virtual void complete(Message::shared_ptr) = 0; -}; - -}} // namespace qpid::broker - - - -#endif /*!_broker_CompletionHandler_h*/ diff --git a/qpid/cpp/lib/broker/Configuration.cpp b/qpid/cpp/lib/broker/Configuration.cpp deleted file mode 100644 index e83c359f2d..0000000000 --- a/qpid/cpp/lib/broker/Configuration.cpp +++ /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. - * - */ -#include -#include -#include - -using namespace qpid::broker; -using namespace std; - -Configuration::Configuration() : - daemon('d', "daemon", "Run as system daemon, detached from terminal.", false), - trace('t', "trace", "Print incoming & outgoing frames to the console", false), - port('p', "port", "Set the port to listen on (default=5672)", 5672), - workerThreads("worker-threads", "Set the number of worker threads to use (default=5).", 5), - maxConnections("max-connections", "Set the maximum number of connections the broker can accept (default=500).", 500), - connectionBacklog("connection-backlog", "Set the connection backlog for the servers socket (default=10)", 10), - store('s', "store", "Set the message store module to use (default='' which implies no store)", ""), - stagingThreshold("staging-threshold", "Set the message size threshold above which messages will be written to disk as they arrive (default=5,000,000)", 5000000), - help("help", "Print usage information", false), - version("version", "Print version information", false) -{ - options.push_back(&daemon); - options.push_back(&trace); - options.push_back(&port); - options.push_back(&workerThreads); - options.push_back(&maxConnections); - options.push_back(&connectionBacklog); - options.push_back(&store); - options.push_back(&stagingThreshold); - options.push_back(&help); - options.push_back(&version); -} - -Configuration::~Configuration(){} - -void Configuration::parse(char const *progName, int argc, char** argv){ - programName = progName; - int position = 1; - while(position < argc){ - bool matched(false); - for(op_iterator i = options.begin(); i < options.end() && !matched; i++){ - matched = (*i)->parse(position, argv, argc); - } - if(!matched) { - throw BadOptionException( - std::string("Unrecognised option: ")+argv[position]); - } - } -} - -void Configuration::usage(){ - std::cout << "Usage: " << programName << " [OPTION]..." << std::endl - << "Start the Qpid AMQP broker daemon." << std::endl << std::endl - << "Options:" << std::endl; - for(op_iterator i = options.begin(); i < options.end(); i++){ - (*i)->print(std::cout); - } - - std::cout << std::endl << "Report bugs to <" << PACKAGE_BUGREPORT << ">." - << std::endl; -} - -bool Configuration::isHelp() const { - return help.getValue(); -} - -bool Configuration::isVersion() const { - return version.getValue(); -} - -bool Configuration::isDaemon() const { - return daemon.getValue(); -} - -bool Configuration::isTrace() const { - return trace.getValue(); -} - -int Configuration::getPort() const { - return port.getValue(); -} - -int Configuration::getWorkerThreads() const { - return workerThreads.getValue(); -} - -int Configuration::getMaxConnections() const { - return maxConnections.getValue(); -} - -int Configuration::getConnectionBacklog() const { - return connectionBacklog.getValue(); -} - -const std::string& Configuration::getStore() const { - return store.getValue(); -} - -long Configuration::getStagingThreshold() const { - return stagingThreshold.getValue(); -} - - -Configuration::Option::Option(const char _flag, const string& _name, const string& _desc) : - flag(string("-") + _flag), name("--" +_name), desc(_desc) {} - -Configuration::Option::Option(const string& _name, const string& _desc) : - flag(""), name("--" + _name), desc(_desc) {} - -Configuration::Option::~Option(){} - -bool Configuration::Option::match(const string& arg){ - return flag == arg || name == arg; -} - -bool Configuration::Option::parse(int& i, char** argv, int argc){ - const string arg(argv[i]); - if(match(arg)){ - if(needsValue()){ - if(++i < argc) setValue(argv[i]); - else throw ParseException("Argument " + arg + " requires a value!"); - }else{ - setValue(""); - } - i++; - return true; - }else{ - return false; - } -} - -void Configuration::Option::print(ostream& out) const { - out << " "; - if(flag.length() > 0){ - out << flag << ", "; - } else { - out << " "; - } - out << name; - if(needsValue()) out << " "; - out << std::endl; - out << " " << desc << std::endl; -} - - -// String Option: - -Configuration::StringOption::StringOption(const char _flag, const string& _name, const string& _desc, const string _value) : - Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::StringOption::StringOption(const string& _name, const string& _desc, const string _value) : - Option(_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::StringOption::~StringOption(){} - -const string& Configuration::StringOption::getValue() const { - return value; -} - -bool Configuration::StringOption::needsValue() const { - return true; -} - -void Configuration::StringOption::setValue(const std::string& _value){ - value = _value; -} - -// Int Option: - -Configuration::IntOption::IntOption(const char _flag, const string& _name, const string& _desc, const int _value) : - Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::IntOption::IntOption(const string& _name, const string& _desc, const int _value) : - Option(_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::IntOption::~IntOption(){} - -int Configuration::IntOption::getValue() const { - return value; -} - -bool Configuration::IntOption::needsValue() const { - return true; -} - -void Configuration::IntOption::setValue(const std::string& _value){ - value = atoi(_value.c_str()); -} - -// Long Option: - -Configuration::LongOption::LongOption(const char _flag, const string& _name, const string& _desc, const long _value) : - Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::LongOption::LongOption(const string& _name, const string& _desc, const long _value) : - Option(_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::LongOption::~LongOption(){} - -long Configuration::LongOption::getValue() const { - return value; -} - -bool Configuration::LongOption::needsValue() const { - return true; -} - -void Configuration::LongOption::setValue(const std::string& _value){ - value = atol(_value.c_str()); -} - -// Bool Option: - -Configuration::BoolOption::BoolOption(const char _flag, const string& _name, const string& _desc, const bool _value) : - Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::BoolOption::BoolOption(const string& _name, const string& _desc, const bool _value) : - Option(_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::BoolOption::~BoolOption(){} - -bool Configuration::BoolOption::getValue() const { - return value; -} - -bool Configuration::BoolOption::needsValue() const { - return false; -} - -void Configuration::BoolOption::setValue(const std::string& /*not required*/){ - //BoolOptions have no value. The fact that the option is specified - //implies the value is true. - value = true; -} diff --git a/qpid/cpp/lib/broker/Configuration.h b/qpid/cpp/lib/broker/Configuration.h deleted file mode 100644 index 27c743c8f0..0000000000 --- a/qpid/cpp/lib/broker/Configuration.h +++ /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. - * - */ -#ifndef _Configuration_ -#define _Configuration_ - -#include -#include -#include -#include - -namespace qpid { -namespace broker { -class Configuration{ - - class Option { - const std::string flag; - const std::string name; - const std::string desc; - - bool match(const std::string& arg); - - protected: - virtual bool needsValue() const = 0; - virtual void setValue(const std::string& value) = 0; - - public: - Option(const char flag, const std::string& name, const std::string& desc); - Option(const std::string& name, const std::string& desc); - virtual ~Option(); - - bool parse(int& i, char** argv, int argc); - void print(std::ostream& out) const; - }; - - class IntOption : public Option{ - const int defaultValue; - int value; - public: - IntOption(char flag, const std::string& name, const std::string& desc, const int value = 0); - IntOption(const std::string& name, const std::string& desc, const int value = 0); - virtual ~IntOption(); - - int getValue() const; - virtual bool needsValue() const; - virtual void setValue(const std::string& value); - virtual void setValue(int _value) { value = _value; } - }; - - class LongOption : public Option{ - const long defaultValue; - int value; - public: - LongOption(char flag, const std::string& name, const std::string& desc, const long value = 0); - LongOption(const std::string& name, const std::string& desc, const long value = 0); - virtual ~LongOption(); - - long getValue() const; - virtual bool needsValue() const; - virtual void setValue(const std::string& value); - virtual void setValue(int _value) { value = _value; } - }; - - class StringOption : public Option{ - const std::string defaultValue; - std::string value; - public: - StringOption(char flag, const std::string& name, const std::string& desc, const std::string value = ""); - StringOption(const std::string& name, const std::string& desc, const std::string value = ""); - virtual ~StringOption(); - - const std::string& getValue() const; - virtual bool needsValue() const; - virtual void setValue(const std::string& value); - }; - - class BoolOption : public Option{ - const bool defaultValue; - bool value; - public: - BoolOption(char flag, const std::string& name, const std::string& desc, const bool value = 0); - BoolOption(const std::string& name, const std::string& desc, const bool value = 0); - virtual ~BoolOption(); - - bool getValue() const; - virtual bool needsValue() const; - virtual void setValue(const std::string& value); - virtual void setValue(bool _value) { value = _value; } - }; - - BoolOption daemon; - BoolOption trace; - IntOption port; - IntOption workerThreads; - IntOption maxConnections; - IntOption connectionBacklog; - StringOption store; - LongOption stagingThreshold; - BoolOption help; - BoolOption version; - char const *programName; - - typedef std::vector::iterator op_iterator; - std::vector options; - - public: - - struct BadOptionException : public Exception { - template - BadOptionException(const T& msg) : Exception(msg) {} - }; - - - class ParseException : public Exception { - public: - template - ParseException(const T& msg) : Exception(msg) {} - }; - - - Configuration(); - ~Configuration(); - - void parse(char const*, int argc, char** argv); - - bool isHelp() const; - bool isVersion() const; - bool isDaemon() const; - bool isTrace() const; - int getPort() const; - int getWorkerThreads() const; - int getMaxConnections() const; - int getConnectionBacklog() const; - const std::string& getStore() const; - long getStagingThreshold() const; - - void setHelp(bool b) { help.setValue(b); } - void setVersion(bool b) { version.setValue(b); } - void setDaemon(bool b) { daemon.setValue(b); } - void setTrace(bool b) { trace.setValue(b); } - void setPort(int i) { port.setValue(i); } - void setWorkerThreads(int i) { workerThreads.setValue(i); } - void setMaxConnections(int i) { maxConnections.setValue(i); } - void setConnectionBacklog(int i) { connectionBacklog.setValue(i); } - void setStore(const std::string& s) { store.setValue(s); } - void setStagingThreshold(long l) { stagingThreshold.setValue(l); } - - void usage(); -}; -} -} - - -#endif diff --git a/qpid/cpp/lib/broker/Connection.cpp b/qpid/cpp/lib/broker/Connection.cpp deleted file mode 100644 index dbc8149cb5..0000000000 --- a/qpid/cpp/lib/broker/Connection.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 "Connection.h" -#include "BrokerChannel.h" -#include "AMQP_ClientProxy.h" -#include "BrokerAdapter.h" - -using namespace boost; -using namespace qpid::sys; -using namespace qpid::framing; -using namespace qpid::sys; - -namespace qpid { -namespace broker { - -Connection::Connection(ConnectionOutputHandler* out_, Broker& broker_) : - broker(broker_), - out(out_), - framemax(65536), - heartbeat(0), - client(0), - timeout(broker.getTimeout()), - stagingThreshold(broker.getStagingThreshold()) -{} - - -Queue::shared_ptr Connection::getQueue(const string& name, uint16_t channel){ - Queue::shared_ptr queue; - if (name.empty()) { - queue = getChannel(channel).getDefaultQueue(); - if (!queue) throw ConnectionException( 530, "Queue must be specified or previously declared" ); - } else { - queue = broker.getQueues().find(name); - if (queue == 0) { - throw ChannelException( 404, "Queue not found: " + name); - } - } - return queue; -} - - -Exchange::shared_ptr Connection::findExchange(const string& name){ - return broker.getExchanges().get(name); -} - - -void Connection::received(framing::AMQFrame* frame){ - getChannel(frame->getChannel()).handleBody(frame->getBody()); -} - -void Connection::close( - ReplyCode code, const string& text, ClassId classId, MethodId methodId) -{ - client->close(code, text, classId, methodId); - getOutput().close(); -} - -void Connection::initiated(const framing::ProtocolInitiation& header) { - version = ProtocolVersion(header.getMajor(), header.getMinor()); - FieldTable properties; - string mechanisms("PLAIN"); - string locales("en_US"); - getChannel(0).init(0, *out, getVersion()); - client = &getChannel(0).getAdatper().getProxy().getConnection(); - client->start( - header.getMajor(), header.getMinor(), - properties, mechanisms, locales); -} - -void Connection::idleOut(){} - -void Connection::idleIn(){} - -void Connection::closed(){ - try { - while (!exclusiveQueues.empty()) { - broker.getQueues().destroy(exclusiveQueues.front()->getName()); - exclusiveQueues.erase(exclusiveQueues.begin()); - } - } catch(std::exception& e) { - std::cout << "Caught unhandled exception while closing session: " << - e.what() << std::endl; - assert(0); - } -} - -void Connection::closeChannel(uint16_t id) { - ChannelMap::iterator i = channels.find(id); - if (i != channels.end()) - i->close(); -} - - -Channel& Connection::getChannel(ChannelId id) { - ChannelMap::iterator i = channels.find(id); - if (i == channels.end()) { - i = channels.insert( - id, new Channel( - *this, id, framemax, broker.getQueues().getStore(), - broker.getStagingThreshold())).first; - } - return *i; -} - - -}} - diff --git a/qpid/cpp/lib/broker/Connection.h b/qpid/cpp/lib/broker/Connection.h deleted file mode 100644 index 5c6f40ca54..0000000000 --- a/qpid/cpp/lib/broker/Connection.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 _Connection_ -#define _Connection_ - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include "framing/ProtocolVersion.h" -#include "Broker.h" -#include "Exception.h" -#include "BrokerChannel.h" - -namespace qpid { -namespace broker { - -class Channel; - -class Connection : public sys::ConnectionInputHandler, - public ConnectionToken -{ - public: - Connection(sys::ConnectionOutputHandler* out, Broker& broker); - - /** Get a channel. Create if it does not already exist */ - Channel& getChannel(framing::ChannelId channel); - - /** Close a channel */ - void closeChannel(framing::ChannelId channel); - - /** Close the connection */ - void close(framing::ReplyCode code, const string& text, framing::ClassId classId, framing::MethodId methodId); - - sys::ConnectionOutputHandler& getOutput() const { return *out; } - framing::ProtocolVersion getVersion() const { return version; } - - uint32_t getFrameMax() const { return framemax; } - uint16_t getHeartbeat() const { return heartbeat; } - uint32_t getTimeout() const { return timeout; } - uint64_t getStagingThreshold() const { return stagingThreshold; } - - void setFrameMax(uint32_t fm) { framemax = fm; } - void setHeartbeat(uint16_t hb) { heartbeat = hb; } - - /** - * Get named queue, never returns 0. - * @return: named queue or default queue for channel if name="" - * @exception: ChannelException if no queue of that name is found. - * @exception: ConnectionException if name="" and channel has no default. - */ - Queue::shared_ptr getQueue(const string& name, uint16_t channel); - - Broker& broker; - std::vector exclusiveQueues; - - // ConnectionInputHandler methods - void received(framing::AMQFrame* frame); - void initiated(const framing::ProtocolInitiation& header); - void idleOut(); - void idleIn(); - void closed(); - - private: - typedef boost::ptr_map ChannelMap; - - typedef std::vector::iterator queue_iterator; - Exchange::shared_ptr findExchange(const string& name); - - framing::ProtocolVersion version; - ChannelMap channels; - sys::ConnectionOutputHandler* out; - uint32_t framemax; - uint16_t heartbeat; - framing::AMQP_ClientProxy::Connection* client; - const uint32_t timeout; //timeout for auto-deleted queues (in ms) - const uint64_t stagingThreshold; - -}; - -}} - -#endif diff --git a/qpid/cpp/lib/broker/ConnectionFactory.cpp b/qpid/cpp/lib/broker/ConnectionFactory.cpp deleted file mode 100644 index 0208e32b4d..0000000000 --- a/qpid/cpp/lib/broker/ConnectionFactory.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 -#include "Connection.h" - -namespace qpid { -namespace broker { - - -ConnectionFactory::ConnectionFactory(Broker& b) : broker(b) -{} - - -ConnectionFactory::~ConnectionFactory() -{ - broker.getCleaner().stop(); -} - -qpid::sys::ConnectionInputHandler* -ConnectionFactory::create(qpid::sys::ConnectionOutputHandler* out) -{ - return new Connection(out, broker); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/lib/broker/ConnectionFactory.h b/qpid/cpp/lib/broker/ConnectionFactory.h deleted file mode 100644 index 9147384b2a..0000000000 --- a/qpid/cpp/lib/broker/ConnectionFactory.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 _ConnectionFactory_ -#define _ConnectionFactory_ - -#include "ConnectionInputHandlerFactory.h" - -namespace qpid { -namespace broker { -class Broker; - -class ConnectionFactory : public qpid::sys::ConnectionInputHandlerFactory -{ - public: - ConnectionFactory(Broker& b); - - virtual qpid::sys::ConnectionInputHandler* create( - qpid::sys::ConnectionOutputHandler* ctxt); - - virtual ~ConnectionFactory(); - - private: - Broker& broker; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/broker/ConnectionToken.h b/qpid/cpp/lib/broker/ConnectionToken.h deleted file mode 100644 index 7e7f813d0e..0000000000 --- a/qpid/cpp/lib/broker/ConnectionToken.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 _ConnectionToken_ -#define _ConnectionToken_ - -namespace qpid { - namespace broker { - /** - * An empty interface allowing opaque implementations of some - * form of token to identify a connection. - */ - class ConnectionToken{ - public: - virtual ~ConnectionToken(){} - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/Consumer.h b/qpid/cpp/lib/broker/Consumer.h deleted file mode 100644 index 26deef4a26..0000000000 --- a/qpid/cpp/lib/broker/Consumer.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 _Consumer_ -#define _Consumer_ - -#include - -namespace qpid { - namespace broker { - class Consumer{ - public: - virtual bool deliver(Message::shared_ptr& msg) = 0; - virtual ~Consumer(){} - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/Content.h b/qpid/cpp/lib/broker/Content.h deleted file mode 100644 index b65a454778..0000000000 --- a/qpid/cpp/lib/broker/Content.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 _Content_ -#define _Content_ - -#include - -#include -#include -#include - -namespace qpid { - -namespace framing { -class ChannelAdapter; -} - -namespace broker { -class Content{ - public: - typedef std::string DataBlock; - typedef boost::function1 SendFn; - - virtual ~Content(){} - - /** Add a block of data to the content */ - virtual void add(framing::AMQContentBody::shared_ptr data) = 0; - - /** Total size of content in bytes */ - virtual uint32_t size() = 0; - - /** - * Iterate over the content calling SendFn for each block. - * Subdivide blocks if necessary to ensure each block is - * <= framesize bytes long. - */ - virtual void send(framing::ChannelAdapter& channel, uint32_t framesize) = 0; - - //FIXME aconway 2007-02-07: This is inconsistently implemented - //find out what is needed. - virtual void encode(qpid::framing::Buffer& buffer) = 0; -}; -}} - - -#endif diff --git a/qpid/cpp/lib/broker/DeletingTxOp.cpp b/qpid/cpp/lib/broker/DeletingTxOp.cpp deleted file mode 100644 index 25fe9c98db..0000000000 --- a/qpid/cpp/lib/broker/DeletingTxOp.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 - -using namespace qpid::broker; - -DeletingTxOp::DeletingTxOp(TxOp* const _delegate) : delegate(_delegate){} - -bool DeletingTxOp::prepare(TransactionContext* ctxt) throw(){ - return delegate && delegate->prepare(ctxt); -} - -void DeletingTxOp::commit() throw(){ - if(delegate){ - delegate->commit(); - delete delegate; - delegate = 0; - } -} - -void DeletingTxOp::rollback() throw(){ - if(delegate){ - delegate->rollback(); - delete delegate; - delegate = 0; - } -} diff --git a/qpid/cpp/lib/broker/DeletingTxOp.h b/qpid/cpp/lib/broker/DeletingTxOp.h deleted file mode 100644 index 3e026cd4ca..0000000000 --- a/qpid/cpp/lib/broker/DeletingTxOp.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 _DeletingTxOp_ -#define _DeletingTxOp_ - -#include - -namespace qpid { - namespace broker { - /** - * TxOp wrapper that will delegate calls & delete the object - * to which it delegates after completion of the transaction. - */ - class DeletingTxOp : public virtual TxOp{ - TxOp* delegate; - public: - DeletingTxOp(TxOp* const delegate); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - virtual ~DeletingTxOp(){} - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/Deliverable.h b/qpid/cpp/lib/broker/Deliverable.h deleted file mode 100644 index e33443555d..0000000000 --- a/qpid/cpp/lib/broker/Deliverable.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 _Deliverable_ -#define _Deliverable_ - -#include - -namespace qpid { - namespace broker { - class Deliverable{ - public: - virtual void deliverTo(Queue::shared_ptr& queue) = 0; - virtual ~Deliverable(){} - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/DeliverableMessage.cpp b/qpid/cpp/lib/broker/DeliverableMessage.cpp deleted file mode 100644 index b9c89da690..0000000000 --- a/qpid/cpp/lib/broker/DeliverableMessage.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 - -using namespace qpid::broker; - -DeliverableMessage::DeliverableMessage(Message::shared_ptr& _msg) : msg(_msg) -{ -} - -void DeliverableMessage::deliverTo(Queue::shared_ptr& queue) -{ - queue->deliver(msg); -} - diff --git a/qpid/cpp/lib/broker/DeliverableMessage.h b/qpid/cpp/lib/broker/DeliverableMessage.h deleted file mode 100644 index 962f0da640..0000000000 --- a/qpid/cpp/lib/broker/DeliverableMessage.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 _DeliverableMessage_ -#define _DeliverableMessage_ - -#include -#include -#include - -namespace qpid { - namespace broker { - class DeliverableMessage : public Deliverable{ - Message::shared_ptr msg; - public: - DeliverableMessage(Message::shared_ptr& msg); - virtual void deliverTo(Queue::shared_ptr& queue); - virtual ~DeliverableMessage(){} - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/DeliveryRecord.cpp b/qpid/cpp/lib/broker/DeliveryRecord.cpp deleted file mode 100644 index e0b5bcfeb1..0000000000 --- a/qpid/cpp/lib/broker/DeliveryRecord.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 -#include - -using namespace qpid::broker; -using std::string; - -DeliveryRecord::DeliveryRecord(Message::shared_ptr _msg, - Queue::shared_ptr _queue, - const string _consumerTag, - const uint64_t _deliveryTag) : msg(_msg), - queue(_queue), - consumerTag(_consumerTag), - deliveryTag(_deliveryTag), - pull(false){} - -DeliveryRecord::DeliveryRecord(Message::shared_ptr _msg, - Queue::shared_ptr _queue, - const uint64_t _deliveryTag) : msg(_msg), - queue(_queue), - consumerTag(""), - deliveryTag(_deliveryTag), - pull(true){} - - -void DeliveryRecord::discard(TransactionContext* ctxt) const{ - queue->dequeue(ctxt, msg); -} - -bool DeliveryRecord::matches(uint64_t tag) const{ - return deliveryTag == tag; -} - -bool DeliveryRecord::coveredBy(const AccumulatedAck* const range) const{ - return range->covers(deliveryTag); -} - -void DeliveryRecord::redeliver(Channel* const channel) const{ - if(pull){ - //if message was originally sent as response to get, we must requeue it - requeue(); - }else{ - channel->deliver(msg, consumerTag, deliveryTag); - } -} - -void DeliveryRecord::requeue() const{ - msg->redeliver(); - queue->process(msg); -} - -void DeliveryRecord::addTo(Prefetch* const prefetch) const{ - if(!pull){ - //ignore 'pulled' messages (i.e. those that were sent in - //response to get) when calculating prefetch - prefetch->size += msg->contentSize(); - prefetch->count++; - } -} - -void DeliveryRecord::subtractFrom(Prefetch* const prefetch) const{ - if(!pull){ - //ignore 'pulled' messages (i.e. those that were sent in - //response to get) when calculating prefetch - prefetch->size -= msg->contentSize(); - prefetch->count--; - } -} diff --git a/qpid/cpp/lib/broker/DeliveryRecord.h b/qpid/cpp/lib/broker/DeliveryRecord.h deleted file mode 100644 index 9423dd2062..0000000000 --- a/qpid/cpp/lib/broker/DeliveryRecord.h +++ /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. - * - */ -#ifndef _DeliveryRecord_ -#define _DeliveryRecord_ - -#include -#include -#include -#include -#include -#include - -namespace qpid { - namespace broker { - class Channel; - - /** - * Record of a delivery for which an ack is outstanding. - */ - class DeliveryRecord{ - mutable Message::shared_ptr msg; - mutable Queue::shared_ptr queue; - std::string consumerTag; - uint64_t deliveryTag; - bool pull; - - public: - DeliveryRecord(Message::shared_ptr msg, Queue::shared_ptr queue, const std::string consumerTag, const uint64_t deliveryTag); - DeliveryRecord(Message::shared_ptr msg, Queue::shared_ptr queue, const uint64_t deliveryTag); - - void discard(TransactionContext* ctxt = 0) const; - bool matches(uint64_t tag) const; - bool coveredBy(const AccumulatedAck* const range) const; - void requeue() const; - void redeliver(Channel* const) const; - void addTo(Prefetch* const prefetch) const; - void subtractFrom(Prefetch* const prefetch) const; - }; - - typedef std::list::iterator ack_iterator; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/DirectExchange.cpp b/qpid/cpp/lib/broker/DirectExchange.cpp deleted file mode 100644 index 0661e8c365..0000000000 --- a/qpid/cpp/lib/broker/DirectExchange.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 - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -DirectExchange::DirectExchange(const string& _name) : Exchange(_name) { - -} - -void DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable*){ - Mutex::ScopedLock l(lock); - std::vector& queues(bindings[routingKey]); - std::vector::iterator i = find(queues.begin(), queues.end(), queue); - if(i == queues.end()){ - bindings[routingKey].push_back(queue); - } -} - -void DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* /*args*/){ - Mutex::ScopedLock l(lock); - std::vector& queues(bindings[routingKey]); - - std::vector::iterator i = find(queues.begin(), queues.end(), queue); - if(i < queues.end()){ - queues.erase(i); - if(queues.empty()){ - bindings.erase(routingKey); - } - } -} - -void DirectExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/){ - Mutex::ScopedLock l(lock); - std::vector& queues(bindings[routingKey]); - int count(0); - for(std::vector::iterator i = queues.begin(); i != queues.end(); i++, count++){ - msg.deliverTo(*i); - } - if(!count){ - std::cout << "WARNING: DirectExchange " << getName() << " could not route message with key " << routingKey << std::endl; - } -} - -DirectExchange::~DirectExchange(){ - -} - - -const std::string DirectExchange::typeName("direct"); diff --git a/qpid/cpp/lib/broker/DirectExchange.h b/qpid/cpp/lib/broker/DirectExchange.h deleted file mode 100644 index a7ef5aca9e..0000000000 --- a/qpid/cpp/lib/broker/DirectExchange.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 _DirectExchange_ -#define _DirectExchange_ - -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace broker { - class DirectExchange : public virtual Exchange{ - std::map > bindings; - qpid::sys::Mutex lock; - - public: - static const std::string typeName; - - DirectExchange(const std::string& name); - - virtual std::string getType(){ return typeName; } - - virtual void bind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual void unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual void route(Deliverable& msg, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual ~DirectExchange(); - }; -} -} - - -#endif diff --git a/qpid/cpp/lib/broker/ExchangeRegistry.cpp b/qpid/cpp/lib/broker/ExchangeRegistry.cpp deleted file mode 100644 index 3e5ed89b54..0000000000 --- a/qpid/cpp/lib/broker/ExchangeRegistry.cpp +++ /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. - * - */ -#include -#include -#include -#include -#include - -using namespace qpid::broker; -using namespace qpid::sys; -using std::pair; - -pair ExchangeRegistry::declare(const string& name, const string& type) throw(UnknownExchangeTypeException){ - Mutex::ScopedLock locker(lock); - ExchangeMap::iterator i = exchanges.find(name); - if (i == exchanges.end()) { - Exchange::shared_ptr exchange; - - if(type == TopicExchange::typeName){ - exchange = Exchange::shared_ptr(new TopicExchange(name)); - }else if(type == DirectExchange::typeName){ - exchange = Exchange::shared_ptr(new DirectExchange(name)); - }else if(type == FanOutExchange::typeName){ - exchange = Exchange::shared_ptr(new FanOutExchange(name)); - }else if (type == HeadersExchange::typeName) { - exchange = Exchange::shared_ptr(new HeadersExchange(name)); - }else{ - throw UnknownExchangeTypeException(); - } - exchanges[name] = exchange; - return std::pair(exchange, true); - } else { - return std::pair(i->second, false); - } -} - -void ExchangeRegistry::destroy(const string& name){ - Mutex::ScopedLock locker(lock); - exchanges.erase(name); -} - -Exchange::shared_ptr ExchangeRegistry::get(const string& name){ - Mutex::ScopedLock locker(lock); - Exchange::shared_ptr exchange =exchanges[name]; - if (!exchange) - throw ChannelException(404, "Exchange not found:" + name); - return exchange; -} - -namespace -{ -const std::string empty; -} - -Exchange::shared_ptr ExchangeRegistry::getDefault() -{ - return get(empty); -} diff --git a/qpid/cpp/lib/broker/ExchangeRegistry.h b/qpid/cpp/lib/broker/ExchangeRegistry.h deleted file mode 100644 index aeb32753df..0000000000 --- a/qpid/cpp/lib/broker/ExchangeRegistry.h +++ /dev/null @@ -1,47 +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 -#include -#include - -namespace qpid { -namespace broker { - struct UnknownExchangeTypeException{}; - - class ExchangeRegistry{ - typedef std::map ExchangeMap; - ExchangeMap exchanges; - qpid::sys::Mutex lock; - public: - std::pair declare(const std::string& name, const std::string& type) throw(UnknownExchangeTypeException); - void destroy(const std::string& name); - Exchange::shared_ptr get(const std::string& name); - Exchange::shared_ptr getDefault(); - }; -} -} - - -#endif /*!_broker_ExchangeRegistry_h*/ diff --git a/qpid/cpp/lib/broker/FanOutExchange.cpp b/qpid/cpp/lib/broker/FanOutExchange.cpp deleted file mode 100644 index b487593efd..0000000000 --- a/qpid/cpp/lib/broker/FanOutExchange.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 - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -FanOutExchange::FanOutExchange(const std::string& _name) : Exchange(_name) {} - -void FanOutExchange::bind(Queue::shared_ptr queue, const string& /*routingKey*/, const FieldTable* /*args*/){ - Mutex::ScopedLock locker(lock); - // Add if not already present. - Queue::vector::iterator i = std::find(bindings.begin(), bindings.end(), queue); - if (i == bindings.end()) { - bindings.push_back(queue); - } -} - -void FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*routingKey*/, const FieldTable* /*args*/){ - Mutex::ScopedLock locker(lock); - Queue::vector::iterator i = std::find(bindings.begin(), bindings.end(), queue); - if (i != bindings.end()) { - bindings.erase(i); - } -} - -void FanOutExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* /*args*/){ - Mutex::ScopedLock locker(lock); - for(Queue::vector::iterator i = bindings.begin(); i != bindings.end(); ++i){ - msg.deliverTo(*i); - } -} - -FanOutExchange::~FanOutExchange() {} - -const std::string FanOutExchange::typeName("fanout"); diff --git a/qpid/cpp/lib/broker/FanOutExchange.h b/qpid/cpp/lib/broker/FanOutExchange.h deleted file mode 100644 index 6dc70e69bb..0000000000 --- a/qpid/cpp/lib/broker/FanOutExchange.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 _FanOutExchange_ -#define _FanOutExchange_ - -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace broker { - -class FanOutExchange : public virtual Exchange { - std::vector bindings; - qpid::sys::Mutex lock; - - public: - static const std::string typeName; - - FanOutExchange(const std::string& name); - - virtual std::string getType(){ return typeName; } - - virtual void bind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual void unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual void route(Deliverable& msg, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual ~FanOutExchange(); -}; - -} -} - - - -#endif diff --git a/qpid/cpp/lib/broker/HandlerImpl.h b/qpid/cpp/lib/broker/HandlerImpl.h deleted file mode 100644 index c55a36da45..0000000000 --- a/qpid/cpp/lib/broker/HandlerImpl.h +++ /dev/null @@ -1,71 +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 "BrokerChannel.h" -#include "AMQP_ClientProxy.h" - -namespace qpid { - -namespace framing { -class AMQP_ClientProxy; -} - -namespace broker { - -class Broker; -class Channel; -class Connection; - -/** - * A collection of references to the core objects required by an adapter, - * and a client proxy. - */ -struct CoreRefs -{ - CoreRefs(Channel& ch, Connection& c, Broker& b) - : channel(ch), connection(c), broker(b), proxy(ch) {} - - Channel& channel; - Connection& connection; - Broker& broker; - framing::AMQP_ClientProxy proxy; -}; - - -/** - * Base template for protocol handler implementations. - * Provides the core references and appropriate AMQP class proxy. - */ -template -struct HandlerImpl : public CoreRefs { - typedef HandlerImpl HandlerImplType; - HandlerImpl(CoreRefs& parent) - : CoreRefs(parent), client(ProxyType::get(proxy)) {} - ProxyType client; -}; - - - -}} // namespace qpid::broker - - - -#endif /*!_broker_HandlerImpl_h*/ diff --git a/qpid/cpp/lib/broker/HeadersExchange.cpp b/qpid/cpp/lib/broker/HeadersExchange.cpp deleted file mode 100644 index 3ef0cc0446..0000000000 --- a/qpid/cpp/lib/broker/HeadersExchange.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. - * - */ -#include -#include -#include -#include - - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -// 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 all("all"); - const std::string any("any"); - const std::string x_match("x-match"); -} - -HeadersExchange::HeadersExchange(const string& _name) : Exchange(_name) { } - -void HeadersExchange::bind(Queue::shared_ptr queue, const string& /*routingKey*/, const FieldTable* args){ - Mutex::ScopedLock locker(lock); - std::string what = args->getString("x-match"); - if (what != all && what != any) { - THROW_QPID_ERROR(PROTOCOL_ERROR, "Invalid x-match value binding to headers exchange."); - } - bindings.push_back(Binding(*args, queue)); -} - -void HeadersExchange::unbind(Queue::shared_ptr queue, const string& /*routingKey*/, const FieldTable* args){ - Mutex::ScopedLock locker(lock); - Bindings::iterator i = - std::find(bindings.begin(),bindings.end(), Binding(*args, queue)); - if (i != bindings.end()) bindings.erase(i); -} - - -void HeadersExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* args){ - Mutex::ScopedLock locker(lock);; - for (Bindings::iterator i = bindings.begin(); i != bindings.end(); ++i) { - if (match(i->first, *args)) msg.deliverTo(i->second); - } -} - -HeadersExchange::~HeadersExchange() {} - -const std::string HeadersExchange::typeName("headers"); - -namespace -{ - - bool match_values(const Value& bind, const Value& msg) { - return dynamic_cast(&bind) || bind == msg; - } - -} - - -bool HeadersExchange::match(const FieldTable& bind, const FieldTable& msg) { - typedef FieldTable::ValueMap Map; - std::string what = bind.getString(x_match); - if (what == all) { - for (Map::const_iterator i = bind.getMap().begin(); - i != bind.getMap().end(); - ++i) - { - if (i->first != x_match) - { - Map::const_iterator j = msg.getMap().find(i->first); - if (j == msg.getMap().end()) return false; - if (!match_values(*(i->second), *(j->second))) return false; - } - } - return true; - } else if (what == any) { - for (Map::const_iterator i = bind.getMap().begin(); - i != bind.getMap().end(); - ++i) - { - if (i->first != x_match) - { - Map::const_iterator j = msg.getMap().find(i->first); - if (j != msg.getMap().end()) { - if (match_values(*(i->second), *(j->second))) return true; - } - } - } - return false; - } else { - return false; - } -} - - - diff --git a/qpid/cpp/lib/broker/HeadersExchange.h b/qpid/cpp/lib/broker/HeadersExchange.h deleted file mode 100644 index 5e8da5ad85..0000000000 --- a/qpid/cpp/lib/broker/HeadersExchange.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 _HeadersExchange_ -#define _HeadersExchange_ - -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace broker { - - -class HeadersExchange : public virtual Exchange { - typedef std::pair Binding; - typedef std::vector Bindings; - - Bindings bindings; - qpid::sys::Mutex lock; - - public: - static const std::string typeName; - - HeadersExchange(const string& name); - - virtual std::string getType(){ return typeName; } - - virtual void bind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args); - - virtual void unbind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args); - - virtual void route(Deliverable& msg, const string& routingKey, const qpid::framing::FieldTable* args); - - virtual ~HeadersExchange(); - - static bool match(const qpid::framing::FieldTable& bindArgs, const qpid::framing::FieldTable& msgArgs); -}; - - - -} -} - -#endif diff --git a/qpid/cpp/lib/broker/InMemoryContent.cpp b/qpid/cpp/lib/broker/InMemoryContent.cpp deleted file mode 100644 index 237375e860..0000000000 --- a/qpid/cpp/lib/broker/InMemoryContent.cpp +++ /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 "AMQFrame.h" -#include "framing/ChannelAdapter.h" - -using namespace qpid::broker; -using namespace qpid::framing; -using boost::static_pointer_cast; - -void InMemoryContent::add(AMQContentBody::shared_ptr data) -{ - content.push_back(data); -} - -uint32_t InMemoryContent::size() -{ - int sum(0); - for (content_iterator i = content.begin(); i != content.end(); i++) { - sum += (*i)->size(); - } - return sum; -} - -void InMemoryContent::send(ChannelAdapter& channel, uint32_t framesize) -{ - for (content_iterator i = content.begin(); i != content.end(); i++) { - if ((*i)->size() > framesize) { - uint32_t offset = 0; - for (int chunk = (*i)->size() / framesize; chunk > 0; chunk--) { - string data = (*i)->getData().substr(offset, framesize); - channel.send(new AMQContentBody(data)); - offset += framesize; - } - uint32_t remainder = (*i)->size() % framesize; - if (remainder) { - string data = (*i)->getData().substr(offset, remainder); - channel.send(new AMQContentBody(data)); - } - } else { - AMQBody::shared_ptr contentBody = - static_pointer_cast(*i); - channel.send(contentBody); - } - } -} - -void InMemoryContent::encode(Buffer& buffer) -{ - for (content_iterator i = content.begin(); i != content.end(); i++) { - (*i)->encode(buffer); - } -} - diff --git a/qpid/cpp/lib/broker/InMemoryContent.h b/qpid/cpp/lib/broker/InMemoryContent.h deleted file mode 100644 index 7a58ace3a7..0000000000 --- a/qpid/cpp/lib/broker/InMemoryContent.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 _InMemoryContent_ -#define _InMemoryContent_ - -#include -#include - - -namespace qpid { - namespace broker { - class InMemoryContent : public Content{ - typedef std::vector content_list; - typedef content_list::iterator content_iterator; - - content_list content; - public: - void add(qpid::framing::AMQContentBody::shared_ptr data); - uint32_t size(); - void send(framing::ChannelAdapter&, uint32_t framesize); - void encode(qpid::framing::Buffer& buffer); - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/LazyLoadedContent.cpp b/qpid/cpp/lib/broker/LazyLoadedContent.cpp deleted file mode 100644 index 9810ee671c..0000000000 --- a/qpid/cpp/lib/broker/LazyLoadedContent.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 -#include "AMQFrame.h" -#include "framing/ChannelAdapter.h" - -using namespace qpid::broker; -using namespace qpid::framing; - -LazyLoadedContent::~LazyLoadedContent() -{ - store->destroy(*msg); -} - -LazyLoadedContent::LazyLoadedContent(MessageStore* const _store, Message* const _msg, uint64_t _expectedSize) : - store(_store), msg(_msg), expectedSize(_expectedSize) {} - -void LazyLoadedContent::add(AMQContentBody::shared_ptr data) -{ - store->appendContent(*msg, data->getData()); -} - -uint32_t LazyLoadedContent::size() -{ - return 0;//all content is written as soon as it is added -} - -void LazyLoadedContent::send(ChannelAdapter& channel, uint32_t framesize) -{ - if (expectedSize > framesize) { - for (uint64_t offset = 0; offset < expectedSize; offset += framesize) - { - uint64_t remaining = expectedSize - offset; - string data; - store->loadContent(*msg, data, offset, - remaining > framesize ? framesize : remaining); - channel.send(new AMQContentBody(data)); - } - } else { - string data; - store->loadContent(*msg, data, 0, expectedSize); - channel.send(new AMQContentBody(data)); - } -} - -void LazyLoadedContent::encode(Buffer&) -{ - //do nothing as all content is written as soon as it is added -} - diff --git a/qpid/cpp/lib/broker/LazyLoadedContent.h b/qpid/cpp/lib/broker/LazyLoadedContent.h deleted file mode 100644 index 3306f6e3ba..0000000000 --- a/qpid/cpp/lib/broker/LazyLoadedContent.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 _LazyLoadedContent_ -#define _LazyLoadedContent_ - -#include -#include -#include "BrokerMessageBase.h" - -namespace qpid { - namespace broker { - class LazyLoadedContent : public Content{ - MessageStore* const store; - Message* const msg; - const uint64_t expectedSize; - public: - LazyLoadedContent( - MessageStore* const store, Message* const msg, - uint64_t expectedSize); - ~LazyLoadedContent(); - void add(qpid::framing::AMQContentBody::shared_ptr data); - uint32_t size(); - void send( - framing::ChannelAdapter&, - uint32_t framesize); - void encode(qpid::framing::Buffer& buffer); - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/Makefile.am b/qpid/cpp/lib/broker/Makefile.am deleted file mode 100644 index 29cfb0f347..0000000000 --- a/qpid/cpp/lib/broker/Makefile.am +++ /dev/null @@ -1,101 +0,0 @@ -AM_CXXFLAGS = $(WARNING_CFLAGS) -INCLUDES = \ - -I$(top_srcdir)/gen \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/common/sys \ - -I$(top_srcdir)/lib/common/framing \ - $(APR_CXXFLAGS) - -lib_LTLIBRARIES = libqpidbroker.la -libqpidbroker_la_LIBADD = ../common/libqpidcommon.la -libqpidbroker_la_LDFLAGS = -version-info $(LIBTOOL_VERSION_INFO_ARG) -libqpidbroker_la_SOURCES = \ - AccumulatedAck.cpp \ - AccumulatedAck.h \ - AutoDelete.cpp \ - AutoDelete.h \ - Binding.h \ - Broker.cpp \ - Broker.h \ - BrokerSingleton.cpp \ - BrokerSingleton.h \ - BrokerChannel.cpp \ - BrokerChannel.h \ - BrokerExchange.h \ - BrokerMessage.cpp \ - BrokerMessage.h \ - BrokerMessageMessage.cpp \ - BrokerMessageMessage.h \ - BrokerQueue.cpp \ - BrokerQueue.h \ - Configuration.cpp \ - Configuration.h \ - ConnectionToken.h \ - Consumer.h \ - Content.h \ - DeletingTxOp.cpp \ - DeletingTxOp.h \ - Deliverable.h \ - DeliverableMessage.cpp \ - DeliverableMessage.h \ - DeliveryRecord.cpp \ - DeliveryRecord.h \ - DirectExchange.cpp \ - DirectExchange.h \ - ExchangeRegistry.cpp \ - ExchangeRegistry.h \ - FanOutExchange.cpp \ - FanOutExchange.h \ - HeadersExchange.cpp \ - HeadersExchange.h \ - InMemoryContent.cpp \ - InMemoryContent.h \ - LazyLoadedContent.cpp \ - LazyLoadedContent.h \ - MessageBuilder.cpp \ - MessageBuilder.h \ - MessageStore.h \ - MessageStoreModule.cpp \ - MessageStoreModule.h \ - NameGenerator.cpp \ - NameGenerator.h \ - NullMessageStore.cpp \ - NullMessageStore.h \ - Persistable.h \ - PersistableExchange.h \ - PersistableMessage.h \ - PersistableQueue.h \ - Prefetch.h \ - QueuePolicy.cpp \ - QueuePolicy.h \ - QueueRegistry.cpp \ - QueueRegistry.h \ - RecoverableMessage.h \ - RecoverableQueue.h \ - RecoveryManager.h \ - RecoveryManagerImpl.cpp \ - RecoveryManagerImpl.h \ - Reference.cpp \ - Reference.h \ - ConnectionFactory.cpp \ - ConnectionFactory.h \ - Connection.cpp \ - Connection.h \ - BrokerAdapter.cpp \ - BrokerAdapter.h \ - MessageHandlerImpl.cpp \ - MessageHandlerImpl.h \ - TopicExchange.cpp \ - TopicExchange.h \ - TransactionalStore.h \ - TxAck.cpp \ - TxAck.h \ - TxBuffer.cpp \ - TxBuffer.h \ - TxOp.h \ - TxPublish.cpp \ - TxPublish.h - - -# Force build during dist phase so help2man will work. -dist-hook: $(lib_LTLIBRARIES) diff --git a/qpid/cpp/lib/broker/MessageBuilder.cpp b/qpid/cpp/lib/broker/MessageBuilder.cpp deleted file mode 100644 index e99dcad7d6..0000000000 --- a/qpid/cpp/lib/broker/MessageBuilder.cpp +++ /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. - * - */ -#include - -#include -#include - -using namespace qpid::broker; -using namespace qpid::framing; -using std::auto_ptr; - -MessageBuilder::MessageBuilder(CompletionHandler* _handler, - MessageStore* const _store, - uint64_t _stagingThreshold -) : - handler(_handler), - store(_store), - stagingThreshold(_stagingThreshold) -{} - -void MessageBuilder::route(){ - if (message->isComplete()) { - if (handler) handler->complete(message); - message.reset(); - } -} - -void MessageBuilder::initialise(Message::shared_ptr& msg){ - if(message.get()){ - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got publish before previous content was completed."); - } - message = msg; -} - -void MessageBuilder::setHeader(AMQHeaderBody::shared_ptr& header){ - if(!message.get()){ - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got header before publish."); - } - message->setHeader(header); - if (stagingThreshold && header->getContentSize() >= stagingThreshold) { - store->stage(*message); - message->releaseContent(store); - } else { - auto_ptr content(new InMemoryContent()); - message->setContent(content); - } - route(); -} - -void MessageBuilder::addContent(AMQContentBody::shared_ptr& content){ - if(!message.get()){ - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got content before publish."); - } - message->addContent(content); - route(); -} diff --git a/qpid/cpp/lib/broker/MessageBuilder.h b/qpid/cpp/lib/broker/MessageBuilder.h deleted file mode 100644 index 30834e1075..0000000000 --- a/qpid/cpp/lib/broker/MessageBuilder.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 _MessageBuilder_ -#define _MessageBuilder_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "CompletionHandler.h" - -namespace qpid { - namespace broker { - class MessageBuilder{ - public: - MessageBuilder(CompletionHandler* _handler, - MessageStore* const store = 0, - uint64_t stagingThreshold = 0); - void initialise(Message::shared_ptr& msg); - void setHeader(framing::AMQHeaderBody::shared_ptr& header); - void addContent(framing::AMQContentBody::shared_ptr& content); - Message::shared_ptr getMessage() { return message; } - private: - Message::shared_ptr message; - CompletionHandler* handler; - MessageStore* const store; - const uint64_t stagingThreshold; - - void route(); - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/MessageHandlerImpl.cpp b/qpid/cpp/lib/broker/MessageHandlerImpl.cpp deleted file mode 100644 index fa7c10f26c..0000000000 --- a/qpid/cpp/lib/broker/MessageHandlerImpl.cpp +++ /dev/null @@ -1,243 +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 "QpidError.h" -#include "MessageHandlerImpl.h" -#include "BrokerChannel.h" -#include "FramingContent.h" -#include "Connection.h" -#include "Broker.h" -#include "BrokerMessageMessage.h" -#include "MessageAppendBody.h" -#include "MessageTransferBody.h" -#include "BrokerAdapter.h" - -namespace qpid { -namespace broker { - -using namespace framing; - -MessageHandlerImpl::MessageHandlerImpl(CoreRefs& parent) - : HandlerImplType(parent) {} - -// -// Message class method handlers -// - -void -MessageHandlerImpl::cancel(const MethodContext& context, - const string& destination ) -{ - channel.cancel(destination); - client.ok(context.getRequestId()); -} - -void -MessageHandlerImpl::open(const MethodContext& context, - const string& reference) -{ - references.open(reference); - client.ok(context.getRequestId()); -} - -void -MessageHandlerImpl::append(const MethodContext& context, - const string& reference, - const string& /*bytes*/ ) -{ - references.get(reference)->append( - boost::shared_polymorphic_downcast( - context.methodBody)); - client.ok(context.getRequestId()); -} - -void -MessageHandlerImpl::close(const MethodContext& context, - const string& reference) -{ - Reference::shared_ptr ref = references.get(reference); - client.ok(context.getRequestId()); - - // Send any transfer messages to their correct exchanges and okay them - const Reference::Messages& msgs = ref->getMessages(); - for (Reference::Messages::const_iterator m = msgs.begin(); m != msgs.end(); ++m) { - channel.handleInlineTransfer(*m); - client.ok((*m)->getRequestId()); - } - ref->close(); -} - -void -MessageHandlerImpl::checkpoint(const MethodContext& context, - const string& /*reference*/, - const string& /*identifier*/ ) -{ - // Initial implementation (which is conforming) is to do nothing here - // and return offset zero for the resume - client.ok(context.getRequestId()); -} - -void -MessageHandlerImpl::resume(const MethodContext& context, - const string& reference, - const string& /*identifier*/ ) -{ - // Initial (null) implementation - // open reference and return 0 offset - references.open(reference); - client.offset(0, context.getRequestId()); -} - -void -MessageHandlerImpl::offset(const MethodContext&, - uint64_t /*value*/ ) -{ - // Shouldn't ever receive this as it is reponse to resume - // which is never sent - // TODO astitcher 2007-02-16 What is the correct exception to throw here? - THROW_QPID_ERROR(INTERNAL_ERROR, "impossible"); -} - -void -MessageHandlerImpl::consume(const MethodContext& context, - uint16_t /*ticket*/, - const string& queueName, - const string& destination, - bool noLocal, - bool noAck, - bool exclusive, - const framing::FieldTable& filter ) -{ - Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); - if(!destination.empty() && channel.exists(destination)) - throw ConnectionException(530, "Consumer tags must be unique"); - string tag = destination; - channel.consume( - tag, queue, !noAck, exclusive, - noLocal ? &connection : 0, &filter); - client.ok(context.getRequestId()); - // Dispatch messages as there is now a consumer. - queue->dispatch(); -} - -void -MessageHandlerImpl::get( const MethodContext& context, - uint16_t /*ticket*/, - const string& queueName, - const string& destination, - bool noAck ) -{ - Queue::shared_ptr queue = - connection.getQueue(queueName, context.channel->getId()); - - if(channel.get(queue, destination, !noAck)) - client.ok(context.getRequestId()); - else - client.empty(context.getRequestId()); -} - -void -MessageHandlerImpl::empty( const MethodContext& ) -{ - // Shouldn't ever receive this as it is a response to get - // which is never sent - // TODO astitcher 2007-02-09 What is the correct exception to throw here? - THROW_QPID_ERROR(INTERNAL_ERROR, "Impossible"); -} - -void -MessageHandlerImpl::ok(const MethodContext& /*context*/) -{ - channel.ack(); -} - -void -MessageHandlerImpl::qos(const MethodContext& context, - uint32_t prefetchSize, - uint16_t prefetchCount, - bool /*global*/ ) -{ - //TODO: handle global - channel.setPrefetchSize(prefetchSize); - channel.setPrefetchCount(prefetchCount); - client.ok(context.getRequestId()); -} - -void -MessageHandlerImpl::recover(const MethodContext& context, - bool requeue) -{ - channel.recover(requeue); - client.ok(context.getRequestId()); -} - -void -MessageHandlerImpl::reject(const MethodContext& /*context*/, - uint16_t /*code*/, - const string& /*text*/ ) -{ - channel.ack(); - // channel.requeue(); -} - -void -MessageHandlerImpl::transfer(const MethodContext& context, - uint16_t /*ticket*/, - const string& /* destination */, - bool /*redelivered*/, - bool /*immediate*/, - uint64_t /*ttl*/, - uint8_t /*priority*/, - uint64_t /*timestamp*/, - uint8_t /*deliveryMode*/, - uint64_t /*expiration*/, - const string& /*exchangeName*/, - const string& /*routingKey*/, - const string& /*messageId*/, - const string& /*correlationId*/, - const string& /*replyTo*/, - const string& /*contentType*/, - const string& /*contentEncoding*/, - const string& /*userId*/, - const string& /*appId*/, - const string& /*transactionId*/, - const string& /*securityToken*/, - const framing::FieldTable& /*applicationHeaders*/, - const framing::Content& body, - bool /*mandatory*/) -{ - MessageTransferBody::shared_ptr transfer( - boost::shared_polymorphic_downcast( - context.methodBody)); - RequestId requestId = context.getRequestId(); - - if (body.isInline()) { - MessageMessage::shared_ptr message( - new MessageMessage(&connection, requestId, transfer)); - channel.handleInlineTransfer(message); - client.ok(requestId); - } else { - Reference::shared_ptr ref(references.get(body.getValue())); - MessageMessage::shared_ptr message( - new MessageMessage(&connection, requestId, transfer, ref)); - ref->addMessage(message); - } -} - - -}} // namespace qpid::broker diff --git a/qpid/cpp/lib/broker/MessageHandlerImpl.h b/qpid/cpp/lib/broker/MessageHandlerImpl.h deleted file mode 100644 index 872d429d5c..0000000000 --- a/qpid/cpp/lib/broker/MessageHandlerImpl.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef _broker_MessageHandlerImpl_h -#define _broker_MessageHandlerImpl_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 "AMQP_ServerOperations.h" -#include "AMQP_ClientProxy.h" -#include "Reference.h" -#include "HandlerImpl.h" - -namespace qpid { -namespace broker { - -class Connection; -class Broker; -class MessageMessage; - -class MessageHandlerImpl : - public framing::AMQP_ServerOperations::MessageHandler, - public HandlerImpl -{ - public: - MessageHandlerImpl(CoreRefs& parent); - - void append(const framing::MethodContext&, - const std::string& reference, - const std::string& bytes ); - - void cancel(const framing::MethodContext&, - const std::string& destination ); - - void checkpoint(const framing::MethodContext&, - const std::string& reference, - const std::string& identifier ); - - void close(const framing::MethodContext&, - const std::string& reference ); - - void consume(const framing::MethodContext&, - uint16_t ticket, - const std::string& queue, - const std::string& destination, - bool noLocal, - bool noAck, - bool exclusive, - const framing::FieldTable& filter ); - - void empty( const framing::MethodContext& ); - - void get(const framing::MethodContext&, - uint16_t ticket, - const std::string& queue, - const std::string& destination, - bool noAck ); - - void offset(const framing::MethodContext&, - uint64_t value ); - - void ok( const framing::MethodContext& ); - - void open(const framing::MethodContext&, - const std::string& reference ); - - void qos(const framing::MethodContext&, - uint32_t prefetchSize, - uint16_t prefetchCount, - bool global ); - - void recover(const framing::MethodContext&, - bool requeue ); - - void reject(const framing::MethodContext&, - uint16_t code, - const std::string& text ); - - void resume(const framing::MethodContext&, - const std::string& reference, - const std::string& identifier ); - - void transfer(const framing::MethodContext&, - uint16_t ticket, - const std::string& destination, - bool redelivered, - bool immediate, - uint64_t ttl, - uint8_t priority, - uint64_t timestamp, - uint8_t deliveryMode, - uint64_t expiration, - const std::string& exchange, - const std::string& routingKey, - const std::string& messageId, - const std::string& correlationId, - const std::string& replyTo, - const std::string& contentType, - const std::string& contentEncoding, - const std::string& userId, - const std::string& appId, - const std::string& transactionId, - const std::string& securityToken, - const framing::FieldTable& applicationHeaders, - const framing::Content& body, - bool mandatory ); - private: - ReferenceRegistry references; -}; - -}} // namespace qpid::broker - - - -#endif /*!_broker_MessageHandlerImpl_h*/ diff --git a/qpid/cpp/lib/broker/MessageStore.h b/qpid/cpp/lib/broker/MessageStore.h deleted file mode 100644 index 1d9ee86e48..0000000000 --- a/qpid/cpp/lib/broker/MessageStore.h +++ /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. - * - */ -#ifndef _MessageStore_ -#define _MessageStore_ - -#include "PersistableExchange.h" -#include "PersistableMessage.h" -#include "PersistableQueue.h" -#include "RecoveryManager.h" -#include "TransactionalStore.h" - -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: - /** - * Record the existence of a durable queue - */ - virtual void create(const PersistableQueue& queue) = 0; - /** - * Destroy a durable queue - */ - virtual void destroy(const PersistableQueue& queue) = 0; - - /** - * Record the existence of a durable exchange - */ - virtual void create(const PersistableExchange& exchange) = 0; - /** - * Destroy a durable exchange - */ - virtual void destroy(const PersistableExchange& exchange) = 0; - - /** - * Request recovery of queue and message state from store - */ - virtual void recover(RecoveryManager& queues) = 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(PersistableMessage& 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(PersistableMessage& 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(PersistableMessage& 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. - * - * @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, PersistableMessage& 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. - * - * @param msg the message to dequeue - * @param queue the name of th 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, PersistableMessage& msg, const PersistableQueue& queue) = 0; - - virtual ~MessageStore(){} -}; - -} -} - - -#endif diff --git a/qpid/cpp/lib/broker/MessageStoreModule.cpp b/qpid/cpp/lib/broker/MessageStoreModule.cpp deleted file mode 100644 index 9939440ecb..0000000000 --- a/qpid/cpp/lib/broker/MessageStoreModule.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 -#include - -using namespace qpid::broker; - -MessageStoreModule::MessageStoreModule(const std::string& name) : store(name) -{ -} - -void MessageStoreModule::create(const PersistableQueue& queue) -{ - store->create(queue); -} - -void MessageStoreModule::destroy(const PersistableQueue& queue) -{ - store->destroy(queue); -} - -void MessageStoreModule::create(const PersistableExchange& exchange) -{ - store->create(exchange); -} - -void MessageStoreModule::destroy(const PersistableExchange& exchange) -{ - store->destroy(exchange); -} - -void MessageStoreModule::recover(RecoveryManager& registry) -{ - store->recover(registry); -} - -void MessageStoreModule::stage(PersistableMessage& msg) -{ - store->stage(msg); -} - -void MessageStoreModule::destroy(PersistableMessage& msg) -{ - store->destroy(msg); -} - -void MessageStoreModule::appendContent(PersistableMessage& msg, const std::string& data) -{ - store->appendContent(msg, data); -} - -void MessageStoreModule::loadContent(PersistableMessage& msg, string& data, uint64_t offset, uint32_t length) -{ - store->loadContent(msg, data, offset, length); -} - -void MessageStoreModule::enqueue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue) -{ - store->enqueue(ctxt, msg, queue); -} - -void MessageStoreModule::dequeue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue) -{ - store->dequeue(ctxt, msg, queue); -} - -std::auto_ptr MessageStoreModule::begin() -{ - return store->begin(); -} - -std::auto_ptr MessageStoreModule::begin(const std::string& xid) -{ - return store->begin(xid); -} - -void MessageStoreModule::prepare(TPCTransactionContext& txn) -{ - store->prepare(txn); -} - -void MessageStoreModule::commit(TransactionContext& ctxt) -{ - store->commit(ctxt); -} - -void MessageStoreModule::abort(TransactionContext& ctxt) -{ - store->abort(ctxt); -} diff --git a/qpid/cpp/lib/broker/MessageStoreModule.h b/qpid/cpp/lib/broker/MessageStoreModule.h deleted file mode 100644 index 1787a4f361..0000000000 --- a/qpid/cpp/lib/broker/MessageStoreModule.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 _MessageStoreModule_ -#define _MessageStoreModule_ - -#include -#include -#include -#include -#include - -namespace qpid { -namespace broker { - -/** - * A null implementation of the MessageStore interface - */ -class MessageStoreModule : public MessageStore -{ - qpid::sys::Module store; -public: - MessageStoreModule(const std::string& name); - - 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 create(const PersistableQueue& queue); - void destroy(const PersistableQueue& queue); - void create(const PersistableExchange& exchange); - void destroy(const PersistableExchange& exchange); - void recover(RecoveryManager& queues); - void stage(PersistableMessage& msg); - void destroy(PersistableMessage& msg); - void appendContent(PersistableMessage& msg, const std::string& data); - void loadContent(PersistableMessage& msg, std::string& data, uint64_t offset, uint32_t length); - void enqueue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue); - void dequeue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue); - - ~MessageStoreModule(){} -}; - -} -} - - -#endif diff --git a/qpid/cpp/lib/broker/NameGenerator.cpp b/qpid/cpp/lib/broker/NameGenerator.cpp deleted file mode 100644 index 3f281859fa..0000000000 --- a/qpid/cpp/lib/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 -#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/lib/broker/NameGenerator.h b/qpid/cpp/lib/broker/NameGenerator.h deleted file mode 100644 index b2dbbdfb69..0000000000 --- a/qpid/cpp/lib/broker/NameGenerator.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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(); - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/NullMessageStore.cpp b/qpid/cpp/lib/broker/NullMessageStore.cpp deleted file mode 100644 index 0d53a31069..0000000000 --- a/qpid/cpp/lib/broker/NullMessageStore.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 - -#include - -#include - -using namespace qpid::broker; - -NullMessageStore::NullMessageStore(bool _warn) : warn(_warn){} - -void NullMessageStore::create(const PersistableQueue& queue) -{ - if (warn) std::cout << "WARNING: Can't create durable queue '" << queue.getName() << "'. Persistence not enabled." << std::endl; -} - -void NullMessageStore::destroy(const PersistableQueue& queue) -{ - if (warn) std::cout << "WARNING: Can't destroy durable queue '" << queue.getName() << "'. Persistence not enabled." << std::endl; -} - -void NullMessageStore::create(const PersistableExchange&) -{ -} - -void NullMessageStore::destroy(const PersistableExchange&) -{ -} - -void NullMessageStore::recover(RecoveryManager&) -{ - if (warn) std::cout << "WARNING: Persistence not enabled, no recovery of queues or messages." << std::endl; -} - -void NullMessageStore::stage(PersistableMessage&) -{ - if (warn) std::cout << "WARNING: Can't stage message. Persistence not enabled." << std::endl; -} - -void NullMessageStore::destroy(PersistableMessage&) -{ - if (warn) std::cout << "WARNING: No need to destroy staged message. Persistence not enabled." << std::endl; -} - -void NullMessageStore::appendContent(PersistableMessage&, const string&) -{ - if (warn) std::cout << "WARNING: Can't append content. Persistence not enabled." << std::endl; -} - -void NullMessageStore::loadContent(PersistableMessage&, string&, uint64_t, uint32_t) -{ - if (warn) std::cout << "WARNING: Can't load content. Persistence not enabled." << std::endl; -} - -void NullMessageStore::enqueue(TransactionContext*, PersistableMessage&, const PersistableQueue& queue) -{ - if (warn) std::cout << "WARNING: Can't enqueue message onto '" << queue.getName() << "'. Persistence not enabled." << std::endl; -} - -void NullMessageStore::dequeue(TransactionContext*, PersistableMessage&, const PersistableQueue& queue) -{ - if (warn) std::cout << "WARNING: Can't dequeue message from '" << queue.getName() << "'. Persistence not enabled." << std::endl; -} - -std::auto_ptr NullMessageStore::begin() -{ - return std::auto_ptr(); -} - -std::auto_ptr NullMessageStore::begin(const std::string&) -{ - return std::auto_ptr(); -} - -void NullMessageStore::prepare(TPCTransactionContext&) -{ -} - -void NullMessageStore::commit(TransactionContext&) -{ -} - -void NullMessageStore::abort(TransactionContext&) -{ -} diff --git a/qpid/cpp/lib/broker/NullMessageStore.h b/qpid/cpp/lib/broker/NullMessageStore.h deleted file mode 100644 index f1a321cff4..0000000000 --- a/qpid/cpp/lib/broker/NullMessageStore.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 _NullMessageStore_ -#define _NullMessageStore_ - -#include -#include -#include - -namespace qpid { -namespace broker { - -/** - * A null implementation of the MessageStore interface - */ -class NullMessageStore : public MessageStore -{ - const bool warn; -public: - NullMessageStore(bool warn = false); - - virtual std::auto_ptr begin(); - virtual std::auto_ptr begin(const std::string& xid); - virtual void prepare(TPCTransactionContext& txn); - virtual void commit(TransactionContext& txn); - virtual void abort(TransactionContext& txn); - - virtual void create(const PersistableQueue& queue); - virtual void destroy(const PersistableQueue& queue); - virtual void create(const PersistableExchange& exchange); - virtual void destroy(const PersistableExchange& exchange); - virtual void recover(RecoveryManager& queues); - virtual void stage(PersistableMessage& msg); - virtual void destroy(PersistableMessage& msg); - virtual void appendContent(PersistableMessage& msg, const std::string& data); - virtual void loadContent(PersistableMessage& msg, std::string& data, uint64_t offset, uint32_t length); - virtual void enqueue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue); - virtual void dequeue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue); - ~NullMessageStore(){} -}; - -} -} - - -#endif diff --git a/qpid/cpp/lib/broker/Persistable.h b/qpid/cpp/lib/broker/Persistable.h deleted file mode 100644 index 9f48643c9e..0000000000 --- a/qpid/cpp/lib/broker/Persistable.h +++ /dev/null @@ -1,62 +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 "framing/amqp_types.h" -#include "framing/Buffer.h" - -namespace qpid { -namespace broker { - -/** - * Base class for all persistable objects - */ -class Persistable -{ -public: - /** - * Allows the store to attach its own identifier to this object - */ - virtual void setPersistenceId(uint64_t id) = 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/lib/broker/PersistableExchange.h b/qpid/cpp/lib/broker/PersistableExchange.h deleted file mode 100644 index 9badf5f609..0000000000 --- a/qpid/cpp/lib/broker/PersistableExchange.h +++ /dev/null @@ -1,44 +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 "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 ~PersistableExchange() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/broker/PersistableMessage.h b/qpid/cpp/lib/broker/PersistableMessage.h deleted file mode 100644 index f598e48709..0000000000 --- a/qpid/cpp/lib/broker/PersistableMessage.h +++ /dev/null @@ -1,53 +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 "Persistable.h" -#include "framing/amqp_types.h" - -namespace qpid { -namespace broker { - -/** - * The interface messages must expose to the MessageStore in order to - * be persistable. - */ - class PersistableMessage : public Persistable -{ -public: - typedef boost::shared_ptr shared_ptr; - - /** - * @returns the size of the headers when encoded - */ - virtual uint32_t encodedHeaderSize() const = 0; - - virtual ~PersistableMessage() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/broker/PersistableQueue.h b/qpid/cpp/lib/broker/PersistableQueue.h deleted file mode 100644 index 5dd91dde9b..0000000000 --- a/qpid/cpp/lib/broker/PersistableQueue.h +++ /dev/null @@ -1,45 +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 "Persistable.h" - -namespace qpid { -namespace broker { - -/** - * 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() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/broker/Prefetch.h b/qpid/cpp/lib/broker/Prefetch.h deleted file mode 100644 index b6d4026c3f..0000000000 --- a/qpid/cpp/lib/broker/Prefetch.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 _Prefetch_ -#define _Prefetch_ - -#include - -namespace qpid { - namespace broker { - /** - * Count and total size of asynchronously delivered - * (i.e. pushed) messages that have acks outstanding. - */ - struct Prefetch{ - uint32_t size; - uint16_t count; - - void reset() { size = 0; count = 0; } - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/QueuePolicy.cpp b/qpid/cpp/lib/broker/QueuePolicy.cpp deleted file mode 100644 index 94b86f2bbb..0000000000 --- a/qpid/cpp/lib/broker/QueuePolicy.cpp +++ /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. - * - */ -#include - -using namespace qpid::broker; -using namespace qpid::framing; - -QueuePolicy::QueuePolicy(uint32_t _maxCount, uint64_t _maxSize) : - maxCount(_maxCount), maxSize(_maxSize), count(0), size(0) {} - -QueuePolicy::QueuePolicy(const FieldTable& settings) : - maxCount(getInt(settings, maxCountKey, 0)), - maxSize(getInt(settings, maxSizeKey, 0)), count(0), size(0) {} - -void QueuePolicy::enqueued(uint64_t _size) -{ - if (maxCount) count++; - if (maxSize) size += _size; -} - -void QueuePolicy::dequeued(uint64_t _size) -{ - if (maxCount) count--; - if (maxSize) size -= _size; -} - -bool QueuePolicy::limitExceeded() -{ - return (maxSize && size > maxSize) || (maxCount && count > maxCount); -} - -void QueuePolicy::update(FieldTable& settings) -{ - if (maxCount) settings.setInt(maxCountKey, maxCount); - if (maxSize) settings.setInt(maxSizeKey, maxSize); -} - - -int QueuePolicy::getInt(const FieldTable& settings, const std::string& key, int defaultValue) -{ - //Note: currently field table only contain signed 32 bit ints, which - // restricts the values that can be set on the queue policy. - try { - return settings.getInt(key); - } catch (FieldNotFoundException& ignore) { - return defaultValue; - } -} - -const std::string QueuePolicy::maxCountKey("qpid.max_count"); -const std::string QueuePolicy::maxSizeKey("qpid.max_size"); diff --git a/qpid/cpp/lib/broker/QueuePolicy.h b/qpid/cpp/lib/broker/QueuePolicy.h deleted file mode 100644 index e7688f3e67..0000000000 --- a/qpid/cpp/lib/broker/QueuePolicy.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 _QueuePolicy_ -#define _QueuePolicy_ - -#include - -namespace qpid { - namespace broker { - class QueuePolicy - { - static const std::string maxCountKey; - static const std::string maxSizeKey; - - const uint32_t maxCount; - const uint64_t maxSize; - uint32_t count; - uint64_t size; - - static int getInt(const qpid::framing::FieldTable& settings, const std::string& key, int defaultValue); - - public: - QueuePolicy(uint32_t maxCount, uint64_t maxSize); - QueuePolicy(const qpid::framing::FieldTable& settings); - void enqueued(uint64_t size); - void dequeued(uint64_t size); - void update(qpid::framing::FieldTable& settings); - bool limitExceeded(); - uint32_t getMaxCount() const { return maxCount; } - uint64_t getMaxSize() const { return maxSize; } - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/QueueRegistry.cpp b/qpid/cpp/lib/broker/QueueRegistry.cpp deleted file mode 100644 index d33cd09840..0000000000 --- a/qpid/cpp/lib/broker/QueueRegistry.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 -#include -#include - -using namespace qpid::broker; -using namespace qpid::sys; - -QueueRegistry::QueueRegistry(MessageStore* const _store) : counter(1), store(_store){} - -QueueRegistry::~QueueRegistry(){} - -std::pair -QueueRegistry::declare(const string& declareName, bool durable, - uint32_t autoDelete, const ConnectionToken* owner) -{ - Mutex::ScopedLock locker(lock); - string name = declareName.empty() ? generateName() : declareName; - assert(!name.empty()); - QueueMap::iterator i = queues.find(name); - if (i == queues.end()) { - Queue::shared_ptr queue(new Queue(name, autoDelete, durable ? store : 0, owner)); - queues[name] = queue; - return std::pair(queue, true); - } else { - return std::pair(i->second, false); - } -} - -void QueueRegistry::destroy(const string& name){ - Mutex::ScopedLock locker(lock); - queues.erase(name); -} - -Queue::shared_ptr QueueRegistry::find(const string& name){ - Mutex::ScopedLock locker(lock); - QueueMap::iterator i = queues.find(name); - if (i == queues.end()) { - return Queue::shared_ptr(); - } else { - return i->second; - } -} - -string QueueRegistry::generateName(){ - string name; - do { - std::stringstream ss; - ss << "tmp_" << counter++; - name = ss.str(); - // Thread safety: Private function, only called with lock held - // so this is OK. - } while(queues.find(name) != queues.end()); - return name; -} - -MessageStore* const QueueRegistry::getStore() const { - return store; -} diff --git a/qpid/cpp/lib/broker/QueueRegistry.h b/qpid/cpp/lib/broker/QueueRegistry.h deleted file mode 100644 index 079034359e..0000000000 --- a/qpid/cpp/lib/broker/QueueRegistry.h +++ /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. - * - */ -#ifndef _QueueRegistry_ -#define _QueueRegistry_ - -#include -#include -#include - -namespace qpid { -namespace broker { - -/** - * 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{ - - public: - QueueRegistry(MessageStore* const store = 0); - ~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. - */ - std::pair declare(const string& name, bool durable = false, uint32_t autodelete = 0, - const ConnectionToken* const owner = 0); - - /** - * 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. - * - */ - void destroy(const string& name); - - /** - * Find the named queue. Return 0 if not found. - */ - Queue::shared_ptr find(const string& name); - - /** - * Generate unique queue name. - */ - string generateName(); - - /** - * Return the message store used. - */ - MessageStore* const getStore() const; - - - private: - typedef std::map QueueMap; - QueueMap queues; - qpid::sys::Mutex lock; - int counter; - MessageStore* const store; -}; - - -} -} - - -#endif diff --git a/qpid/cpp/lib/broker/RecoverableMessage.h b/qpid/cpp/lib/broker/RecoverableMessage.h deleted file mode 100644 index 4bb0d2c4a1..0000000000 --- a/qpid/cpp/lib/broker/RecoverableMessage.h +++ /dev/null @@ -1,57 +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 "framing/amqp_types.h" -#include "framing/Buffer.h" - -namespace qpid { -namespace broker { - -/** - * The interface through which messages are reloaded on recovery. - */ -class RecoverableMessage -{ -public: - typedef boost::shared_ptr shared_ptr; - /** - * 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 ~RecoverableMessage() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/broker/RecoverableQueue.h b/qpid/cpp/lib/broker/RecoverableQueue.h deleted file mode 100644 index a5c564b947..0000000000 --- a/qpid/cpp/lib/broker/RecoverableQueue.h +++ /dev/null @@ -1,49 +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 "RecoverableMessage.h" -#include - -namespace qpid { -namespace broker { - -/** - * The interface through which messages are added back to queues on - * recovery. - */ -class RecoverableQueue -{ -public: - typedef boost::shared_ptr shared_ptr; - /** - * Used during recovery to add stored messages back to the queue - */ - virtual void recover(RecoverableMessage::shared_ptr msg) = 0; - virtual ~RecoverableQueue() {}; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/broker/RecoveryManager.h b/qpid/cpp/lib/broker/RecoveryManager.h deleted file mode 100644 index 700bbdcf80..0000000000 --- a/qpid/cpp/lib/broker/RecoveryManager.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 _RecoveryManager_ -#define _RecoveryManager_ - -#include "RecoverableQueue.h" -#include "RecoverableMessage.h" -#include "framing/Buffer.h" - -namespace qpid { -namespace broker { - - class RecoveryManager{ - public: - virtual ~RecoveryManager(){} - virtual void recoverExchange(framing::Buffer& buffer) = 0; - virtual RecoverableQueue::shared_ptr recoverQueue(framing::Buffer& buffer) = 0; - virtual RecoverableMessage::shared_ptr recoverMessage(framing::Buffer& buffer) = 0; - virtual void recoveryComplete() = 0; - }; - - -} -} - - -#endif diff --git a/qpid/cpp/lib/broker/RecoveryManagerImpl.cpp b/qpid/cpp/lib/broker/RecoveryManagerImpl.cpp deleted file mode 100644 index c14f9c52cc..0000000000 --- a/qpid/cpp/lib/broker/RecoveryManagerImpl.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 "BrokerMessage.h" -#include "BrokerMessageMessage.h" -#include "BrokerQueue.h" - -using namespace qpid; -using namespace qpid::broker; -using boost::dynamic_pointer_cast; - - -static const uint8_t BASIC = 1; -static const uint8_t MESSAGE = 2; - -RecoveryManagerImpl::RecoveryManagerImpl(QueueRegistry& _queues, ExchangeRegistry& _exchanges, uint64_t _stagingThreshold) - : queues(_queues), exchanges(_exchanges), stagingThreshold(_stagingThreshold) {} - -RecoveryManagerImpl::~RecoveryManagerImpl() {} - -class RecoverableMessageImpl : public RecoverableMessage -{ - Message::shared_ptr msg; - const uint64_t stagingThreshold; -public: - RecoverableMessageImpl(Message::shared_ptr& _msg, uint64_t _stagingThreshold) - : msg(_msg), stagingThreshold(_stagingThreshold) {} - ~RecoverableMessageImpl() {}; - bool loadContent(uint64_t available); - void decodeContent(framing::Buffer& buffer); - void recover(Queue::shared_ptr queue); -}; - -class RecoverableQueueImpl : public RecoverableQueue -{ - Queue::shared_ptr queue; -public: - RecoverableQueueImpl(Queue::shared_ptr& _queue) : queue(_queue) {} - ~RecoverableQueueImpl() {}; - void recover(RecoverableMessage::shared_ptr msg); -}; - -void RecoveryManagerImpl::recoverExchange(framing::Buffer&) -{ - //TODO -} - -RecoverableQueue::shared_ptr RecoveryManagerImpl::recoverQueue(framing::Buffer& buffer) -{ - Queue::shared_ptr queue = Queue::decode(queues, buffer); - try { - Exchange::shared_ptr exchange = exchanges.getDefault(); - if (exchange) { - exchange->bind(queue, queue->getName(), 0); - } - } catch (ChannelException& e) { - //assume no default exchange has been declared - } - return RecoverableQueue::shared_ptr(new RecoverableQueueImpl(queue)); -} - -RecoverableMessage::shared_ptr RecoveryManagerImpl::recoverMessage(framing::Buffer& buffer) -{ - buffer.record(); - //peek at type: - Message::shared_ptr message(decodeMessageType(buffer) == MESSAGE ? - ((Message*) new MessageMessage()) : - ((Message*) new BasicMessage())); - buffer.restore(); - message->decodeHeader(buffer); - return RecoverableMessage::shared_ptr(new RecoverableMessageImpl(message, stagingThreshold)); -} - -void RecoveryManagerImpl::recoveryComplete() -{ - //TODO (finalise binding setup etc) -} - -uint8_t RecoveryManagerImpl::decodeMessageType(framing::Buffer& buffer) -{ - return buffer.getOctet(); -} - -void RecoveryManagerImpl::encodeMessageType(const Message& msg, framing::Buffer& buffer) -{ - buffer.putOctet(dynamic_cast(&msg) ? MESSAGE : BASIC); -} - -uint32_t RecoveryManagerImpl::encodedMessageTypeSize() -{ - return 1; -} - -bool RecoverableMessageImpl::loadContent(uint64_t available) -{ - return !stagingThreshold || available < stagingThreshold; -} - -void RecoverableMessageImpl::decodeContent(framing::Buffer& buffer) -{ - msg->decodeContent(buffer); -} - -void RecoverableMessageImpl::recover(Queue::shared_ptr queue) -{ - queue->recover(msg); -} - -void RecoverableQueueImpl::recover(RecoverableMessage::shared_ptr msg) -{ - dynamic_pointer_cast(msg)->recover(queue); -} diff --git a/qpid/cpp/lib/broker/RecoveryManagerImpl.h b/qpid/cpp/lib/broker/RecoveryManagerImpl.h deleted file mode 100644 index c40de7895f..0000000000 --- a/qpid/cpp/lib/broker/RecoveryManagerImpl.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 _RecoveryManagerImpl_ -#define _RecoveryManagerImpl_ - -#include -#include "ExchangeRegistry.h" -#include "QueueRegistry.h" -#include "RecoveryManager.h" - -namespace qpid { -namespace broker { - - class RecoveryManagerImpl : public RecoveryManager{ - QueueRegistry& queues; - ExchangeRegistry& exchanges; - const uint64_t stagingThreshold; - public: - RecoveryManagerImpl(QueueRegistry& queues, ExchangeRegistry& exchanges, uint64_t stagingThreshold); - ~RecoveryManagerImpl(); - - void recoverExchange(framing::Buffer& buffer); - RecoverableQueue::shared_ptr recoverQueue(framing::Buffer& buffer); - RecoverableMessage::shared_ptr recoverMessage(framing::Buffer& buffer); - void recoveryComplete(); - - static uint8_t decodeMessageType(framing::Buffer& buffer); - static void encodeMessageType(const Message& msg, framing::Buffer& buffer); - static uint32_t encodedMessageTypeSize(); - }; - - -} -} - - -#endif diff --git a/qpid/cpp/lib/broker/Reference.cpp b/qpid/cpp/lib/broker/Reference.cpp deleted file mode 100644 index bd1bdcb007..0000000000 --- a/qpid/cpp/lib/broker/Reference.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 -#include "Reference.h" -#include "BrokerMessageMessage.h" -#include "QpidError.h" -#include "MessageAppendBody.h" -#include "CompletionHandler.h" - -namespace qpid { -namespace broker { - -Reference::shared_ptr ReferenceRegistry::open(const Reference::Id& id) { - ReferenceMap::iterator i = references.find(id); - if (i != references.end()) - throw ConnectionException(503, "Attempt to re-open reference " +id); - return references[id] = Reference::shared_ptr(new Reference(id, this)); -} - -Reference::shared_ptr ReferenceRegistry::get(const Reference::Id& id) { - ReferenceMap::iterator i = references.find(id); - if (i == references.end()) - throw ConnectionException(503, "Attempt to use non-existent reference "+id); - return i->second; -} - -void Reference::append(AppendPtr ptr) { - appends.push_back(ptr); - size += ptr->getBytes().length(); -} - -void Reference::close() { - registry->references.erase(getId()); -} - -}} // namespace qpid::broker diff --git a/qpid/cpp/lib/broker/Reference.h b/qpid/cpp/lib/broker/Reference.h deleted file mode 100644 index 277eb7b917..0000000000 --- a/qpid/cpp/lib/broker/Reference.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef _broker_Reference_h -#define _broker_Reference_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 -#include -#include -#include - -namespace qpid { - -namespace framing { -class MessageAppendBody; -} - -namespace broker { - -class MessageMessage; -class ReferenceRegistry; - -// FIXME aconway 2007-03-27: Merge with client::IncomingMessage -// to common reference handling code. - -/** - * A reference is an accumulation point for data in a multi-frame - * message. A reference can be used by multiple transfer commands to - * create multiple messages, so the reference tracks which commands - * are using it. When the reference is closed, all the associated - * transfers are completed. - * - * THREAD UNSAFE: per-channel resource, access to channels is - * serialized. - */ -class Reference -{ - public: - typedef std::string Id; - typedef boost::shared_ptr shared_ptr; - typedef boost::shared_ptr MessagePtr; - typedef std::vector Messages; - typedef boost::shared_ptr AppendPtr; - typedef std::vector Appends; - - Reference(const Id& id_=Id(), ReferenceRegistry* reg=0) - : id(id_), size(0), registry(reg) {} - - const std::string& getId() const { return id; } - uint64_t getSize() const { return size; } - - /** Add a message to be completed with this reference */ - void addMessage(MessagePtr message) { messages.push_back(message); } - - /** Append more data to the reference */ - void append(AppendPtr ptr); - - /** Close the reference, complete each associated message */ - void close(); - - const Appends& getAppends() const { return appends; } - const Messages& getMessages() const { return messages; } - - private: - Id id; - uint64_t size; - ReferenceRegistry* registry; - Messages messages; - Appends appends; -}; - - -/** - * A registry/factory for references. - * - * THREAD UNSAFE: per-channel resource, access to channels is - * serialized. - */ -class ReferenceRegistry { - public: - ReferenceRegistry() {}; - Reference::shared_ptr open(const Reference::Id& id); - Reference::shared_ptr get(const Reference::Id& id); - - private: - typedef std::map ReferenceMap; - ReferenceMap references; - - // Reference calls references.erase(). - friend class Reference; -}; - - -}} // namespace qpid::broker - - - -#endif /*!_broker_Reference_h*/ diff --git a/qpid/cpp/lib/broker/TopicExchange.cpp b/qpid/cpp/lib/broker/TopicExchange.cpp deleted file mode 100644 index 796d3cea02..0000000000 --- a/qpid/cpp/lib/broker/TopicExchange.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 -#include - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -// TODO aconway 2006-09-20: More efficient matching algorithm. -// Areas for improvement: -// - excessive string copying: should be 0 copy, match from original buffer. -// - match/lookup: use descision tree or other more efficient structure. - -Tokens& Tokens::operator=(const std::string& s) { - clear(); - if (s.empty()) return *this; - std::string::const_iterator i = s.begin(); - while (true) { - // Invariant: i is at the beginning of the next untokenized word. - std::string::const_iterator j = find(i, s.end(), '.'); - push_back(std::string(i, j)); - if (j == s.end()) return *this; - i = j + 1; - } - return *this; -} - -TopicPattern& TopicPattern::operator=(const Tokens& tokens) { - Tokens::operator=(tokens); - normalize(); - return *this; -} - -namespace { -const std::string hashmark("#"); -const std::string star("*"); -} - -void TopicPattern::normalize() { - std::string word; - Tokens::iterator i = begin(); - while (i != end()) { - if (*i == hashmark) { - ++i; - while (i != end()) { - // Invariant: *(i-1)==#, [begin()..i-1] is normalized. - if (*i == star) { // Move * before #. - std::swap(*i, *(i-1)); - ++i; - } else if (*i == hashmark) { - erase(i); // Remove extra # - } else { - break; - } - } - } else { - i ++; - } - } -} - - -namespace { -// TODO aconway 2006-09-20: Ineficient to convert every routingKey to a string. -// Need StringRef class that operates on a string in place witout copy. -// Should be applied everywhere strings are extracted from frames. -// -bool do_match(Tokens::const_iterator pattern_begin, Tokens::const_iterator pattern_end, Tokens::const_iterator target_begin, Tokens::const_iterator target_end) -{ - // Invariant: [pattern_begin..p) matches [target_begin..t) - Tokens::const_iterator p = pattern_begin; - Tokens::const_iterator t = target_begin; - while (p != pattern_end && t != target_end) - { - if (*p == star || *p == *t) { - ++p, ++t; - } else if (*p == hashmark) { - ++p; - if (do_match(p, pattern_end, t, target_end)) return true; - while (t != target_end) { - ++t; - if (do_match(p, pattern_end, t, target_end)) return true; - } - return false; - } else { - return false; - } - } - while (p != pattern_end && *p == hashmark) ++p; // Ignore trailing # - return t == target_end && p == pattern_end; -} -} - -bool TopicPattern::match(const Tokens& target) const -{ - return do_match(begin(), end(), target.begin(), target.end()); -} - -TopicExchange::TopicExchange(const string& _name) : Exchange(_name) { } - -void TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* /*args*/){ - Monitor::ScopedLock l(lock); - TopicPattern routingPattern(routingKey); - bindings[routingPattern].push_back(queue); -} - -void TopicExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* /*args*/){ - Monitor::ScopedLock l(lock); - BindingMap::iterator bi = bindings.find(TopicPattern(routingKey)); - Queue::vector& qv(bi->second); - if (bi == bindings.end()) return; - Queue::vector::iterator q = find(qv.begin(), qv.end(), queue); - if(q == qv.end()) return; - qv.erase(q); - if(qv.empty()) bindings.erase(bi); -} - - -void TopicExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/){ - Monitor::ScopedLock l(lock); - for (BindingMap::iterator i = bindings.begin(); i != bindings.end(); ++i) { - if (i->first.match(routingKey)) { - Queue::vector& qv(i->second); - for(Queue::vector::iterator j = qv.begin(); j != qv.end(); j++){ - msg.deliverTo(*j); - } - } - } -} - -TopicExchange::~TopicExchange() {} - -const std::string TopicExchange::typeName("topic"); - - diff --git a/qpid/cpp/lib/broker/TopicExchange.h b/qpid/cpp/lib/broker/TopicExchange.h deleted file mode 100644 index fa0c86863a..0000000000 --- a/qpid/cpp/lib/broker/TopicExchange.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 _TopicExchange_ -#define _TopicExchange_ - -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace broker { - -/** A vector of string tokens */ -class Tokens : public std::vector { - public: - Tokens() {}; - // Default copy, assign, dtor are sufficient. - - /** Tokenize s, provides automatic conversion of string to Tokens */ - Tokens(const std::string& s) { operator=(s); } - /** Tokenizing assignment operator s */ - Tokens & operator=(const std::string& s); - - private: - size_t hash; -}; - - -/** - * Tokens that have been normalized as a pattern and can be matched - * with topic Tokens. Normalized meands all sequences of mixed * and - * # are reduced to a series of * followed by at most one #. - */ -class TopicPattern : public Tokens -{ - public: - TopicPattern() {} - // Default copy, assign, dtor are sufficient. - TopicPattern(const Tokens& tokens) { operator=(tokens); } - TopicPattern(const std::string& str) { operator=(str); } - TopicPattern& operator=(const Tokens&); - TopicPattern& operator=(const std::string& str) { return operator=(Tokens(str)); } - - /** Match a topic */ - bool match(const std::string& topic) { return match(Tokens(topic)); } - bool match(const Tokens& topic) const; - - private: - void normalize(); -}; - -class TopicExchange : public virtual Exchange{ - typedef std::map BindingMap; - BindingMap bindings; - qpid::sys::Mutex lock; - - public: - static const std::string typeName; - - TopicExchange(const string& name); - - virtual std::string getType(){ return typeName; } - - virtual void bind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args); - - virtual void unbind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args); - - virtual void route(Deliverable& msg, const string& routingKey, const qpid::framing::FieldTable* args); - - virtual ~TopicExchange(); -}; - - - -} -} - -#endif diff --git a/qpid/cpp/lib/broker/TransactionalStore.h b/qpid/cpp/lib/broker/TransactionalStore.h deleted file mode 100644 index 9347edf0ad..0000000000 --- a/qpid/cpp/lib/broker/TransactionalStore.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 _TransactionalStore_ -#define _TransactionalStore_ - -#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 ~TransactionalStore(){} -}; - -} -} - - -#endif diff --git a/qpid/cpp/lib/broker/TxAck.cpp b/qpid/cpp/lib/broker/TxAck.cpp deleted file mode 100644 index a2f3283f91..0000000000 --- a/qpid/cpp/lib/broker/TxAck.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 - -using std::bind1st; -using std::bind2nd; -using std::mem_fun_ref; -using namespace qpid::broker; - -TxAck::TxAck(AccumulatedAck& _acked, std::list& _unacked) : - acked(_acked), unacked(_unacked){ - -} - -bool TxAck::prepare(TransactionContext* ctxt) throw(){ - try{ - //dequeue all acked messages from their queues - for (ack_iterator i = unacked.begin(); i != unacked.end(); i++) { - if (i->coveredBy(&acked)) { - i->discard(ctxt); - } - } - return true; - }catch(...){ - std::cout << "TxAck::prepare() - Failed to prepare" << std::endl; - return false; - } -} - -void TxAck::commit() throw(){ - //remove all acked records from the list - unacked.remove_if(bind2nd(mem_fun_ref(&DeliveryRecord::coveredBy), &acked)); -} - -void TxAck::rollback() throw(){ -} diff --git a/qpid/cpp/lib/broker/TxAck.h b/qpid/cpp/lib/broker/TxAck.h deleted file mode 100644 index d023cfae0d..0000000000 --- a/qpid/cpp/lib/broker/TxAck.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 _TxAck_ -#define _TxAck_ - -#include -#include -#include -#include -#include -#include - -namespace qpid { - namespace broker { - /** - * Defines the transactional behaviour for acks received by a - * transactional channel. - */ - class TxAck : public TxOp{ - AccumulatedAck& acked; - std::list& unacked; - - public: - /** - * @param acked a representation of the accumulation of - * acks received - * @param unacked the record of delivered messages - */ - TxAck(AccumulatedAck& acked, std::list& unacked); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - virtual ~TxAck(){} - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/TxBuffer.cpp b/qpid/cpp/lib/broker/TxBuffer.cpp deleted file mode 100644 index e5701c3d46..0000000000 --- a/qpid/cpp/lib/broker/TxBuffer.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 - -using std::mem_fun; -using namespace qpid::broker; - -bool TxBuffer::prepare(TransactionalStore* const store) -{ - std::auto_ptr ctxt; - if(store) ctxt = store->begin(); - for(op_iterator i = ops.begin(); i < ops.end(); i++){ - if(!(*i)->prepare(ctxt.get())){ - if(store) store->abort(*ctxt); - return false; - } - } - if(store) store->commit(*ctxt); - return true; -} - -void TxBuffer::commit() -{ - for_each(ops.begin(), ops.end(), mem_fun(&TxOp::commit)); - ops.clear(); -} - -void TxBuffer::rollback() -{ - for_each(ops.begin(), ops.end(), mem_fun(&TxOp::rollback)); - ops.clear(); -} - -void TxBuffer::enlist(TxOp* const op) -{ - ops.push_back(op); -} diff --git a/qpid/cpp/lib/broker/TxBuffer.h b/qpid/cpp/lib/broker/TxBuffer.h deleted file mode 100644 index 2d9a2a3679..0000000000 --- a/qpid/cpp/lib/broker/TxBuffer.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 _TxBuffer_ -#define _TxBuffer_ - -#include -#include -#include -#include -#include - -/** - * 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. - */ -namespace qpid { - namespace broker { - class TxBuffer{ - typedef std::vector::iterator op_iterator; - std::vector ops; - public: - /** - * Requests that all ops are prepared. This should - * primarily involve making sure that a persistent record - * of the operations is stored where necessary. - * - * All ops will be prepared under a transaction on the - * specified store. If any operation fails on prepare, - * this transaction will be rolled back. - * - * 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. - */ - bool prepare(TransactionalStore* const store); - /** - * Signals that the ops all prepared all completed - * 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. - */ - void commit(); - /** - * Rolls back all the operations. - * - * Should only be called either after a call to prepare() - * returns true (2pc) or instead of a prepare call - * ('server-local') - */ - void rollback(); - /** - * Adds an operation to the transaction. - */ - void enlist(TxOp* const op); - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/TxOp.h b/qpid/cpp/lib/broker/TxOp.h deleted file mode 100644 index abba84a8e8..0000000000 --- a/qpid/cpp/lib/broker/TxOp.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 - -namespace qpid { - namespace broker { - class TxOp{ - public: - virtual bool prepare(TransactionContext*) throw() = 0; - virtual void commit() throw() = 0; - virtual void rollback() throw() = 0; - virtual ~TxOp(){} - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/broker/TxPublish.cpp b/qpid/cpp/lib/broker/TxPublish.cpp deleted file mode 100644 index 57993782d0..0000000000 --- a/qpid/cpp/lib/broker/TxPublish.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 - -using namespace qpid::broker; - -TxPublish::TxPublish(Message::shared_ptr _msg) : msg(_msg) {} - -bool TxPublish::prepare(TransactionContext* ctxt) throw(){ - try{ - for_each(queues.begin(), queues.end(), Prepare(ctxt, msg)); - return true; - }catch(...){ - std::cout << "TxPublish::prepare() - Failed to prepare" << std::endl; - return false; - } -} - -void TxPublish::commit() throw(){ - for_each(queues.begin(), queues.end(), Commit(msg)); -} - -void TxPublish::rollback() throw(){ -} - -void TxPublish::deliverTo(Queue::shared_ptr& queue){ - queues.push_back(queue); -} - -TxPublish::Prepare::Prepare(TransactionContext* _ctxt, Message::shared_ptr& _msg) - : ctxt(_ctxt), msg(_msg){} - -void TxPublish::Prepare::operator()(Queue::shared_ptr& queue){ - queue->enqueue(ctxt, msg); -} - -TxPublish::Commit::Commit(Message::shared_ptr& _msg) : msg(_msg){} - -void TxPublish::Commit::operator()(Queue::shared_ptr& queue){ - queue->process(msg); -} - diff --git a/qpid/cpp/lib/broker/TxPublish.h b/qpid/cpp/lib/broker/TxPublish.h deleted file mode 100644 index 0c7596086a..0000000000 --- a/qpid/cpp/lib/broker/TxPublish.h +++ /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. - * - */ -#ifndef _TxPublish_ -#define _TxPublish_ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { - namespace broker { - /** - * Defines the behaviour for publish operations on a - * transactional channel. Messages are routed through - * exchanges when received but are not at that stage delivered - * to the matching queues, rather the queues are held in an - * instance of this class. On prepare() the message is marked - * enqueued to the relevant queues in the MessagesStore. On - * commit() the messages will be passed to the queue for - * dispatch or to be added to the in-memory queue. - */ - class TxPublish : public TxOp, public Deliverable{ - class Prepare{ - TransactionContext* ctxt; - Message::shared_ptr& msg; - public: - Prepare(TransactionContext* ctxt, Message::shared_ptr& msg); - void operator()(Queue::shared_ptr& queue); - }; - - class Commit{ - Message::shared_ptr& msg; - public: - Commit(Message::shared_ptr& msg); - void operator()(Queue::shared_ptr& queue); - }; - - Message::shared_ptr msg; - std::list queues; - - public: - TxPublish(Message::shared_ptr msg); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - - virtual void deliverTo(Queue::shared_ptr& queue); - - virtual ~TxPublish(){} - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/client/AckMode.h b/qpid/cpp/lib/client/AckMode.h deleted file mode 100644 index 9ad5ef925c..0000000000 --- a/qpid/cpp/lib/client/AckMode.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef _client_AckMode_h -#define _client_AckMode_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 client { - -/** - * The available acknowledgements modes. - * - * \ingroup clientapi - */ -enum AckMode { - /** No acknowledgement will be sent, broker can - discard messages as soon as they are delivered - to a consumer using this mode. **/ - NO_ACK = 0, - /** Each message will be automatically - acknowledged as soon as it is delivered to the - application **/ - AUTO_ACK = 1, - /** Acknowledgements will be sent automatically, - but not for each message. **/ - LAZY_ACK = 2, - /** The application is responsible for explicitly - acknowledging messages. **/ - CLIENT_ACK = 3 -}; - -}} // namespace qpid::client - - - -#endif /*!_client_AckMode_h*/ -#ifndef _client_AckMode_h -#define _client_AckMode_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 client { - -/** - * The available acknowledgements modes. - * - * \ingroup clientapi - */ -enum AckMode { - /** No acknowledgement will be sent, broker can - discard messages as soon as they are delivered - to a consumer using this mode. **/ - NO_ACK = 0, - /** Each message will be automatically - acknowledged as soon as it is delivered to the - application **/ - AUTO_ACK = 1, - /** Acknowledgements will be sent automatically, - but not for each message. **/ - LAZY_ACK = 2, - /** The application is responsible for explicitly - acknowledging messages. **/ - CLIENT_ACK = 3 -}; - -}} // namespace qpid::client - - - -#endif /*!_client_AckMode_h*/ diff --git a/qpid/cpp/lib/client/BasicMessageChannel.cpp b/qpid/cpp/lib/client/BasicMessageChannel.cpp deleted file mode 100644 index d6929965ee..0000000000 --- a/qpid/cpp/lib/client/BasicMessageChannel.cpp +++ /dev/null @@ -1,395 +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 "BasicMessageChannel.h" -#include "AMQMethodBody.h" -#include "ClientChannel.h" -#include "ReturnedMessageHandler.h" -#include "MessageListener.h" -#include "framing/FieldTable.h" -#include "Connection.h" -#include -#include -#include -#include - -namespace qpid { -namespace client { - -using namespace std; -using namespace sys; -using namespace framing; -using boost::format; - -namespace { - -// Destination name constants -const std::string BASIC_GET("__basic_get__"); -const std::string BASIC_RETURN("__basic_return__"); - -// Reference name constant -const std::string BASIC_REF("__basic_reference__"); -} - -class BasicMessageChannel::WaitableDestination : - public IncomingMessage::Destination -{ - public: - WaitableDestination() : shutdownFlag(false) {} - void message(const Message& msg) { - Mutex::ScopedLock l(monitor); - queue.push(msg); - monitor.notify(); - } - - void empty() { - Mutex::ScopedLock l(monitor); - queue.push(Empty()); - monitor.notify(); - } - - bool wait(Message& msgOut) { - Mutex::ScopedLock l(monitor); - while (queue.empty() && !shutdownFlag) - monitor.wait(); - if (shutdownFlag) - return false; - Message* msg = boost::get(&queue.front()); - bool success = msg; - if (success) - msgOut=*msg; - queue.pop(); - if (!queue.empty()) - monitor.notify(); // Wake another waiter. - return success; - } - - void shutdown() { - Mutex::ScopedLock l(monitor); - shutdownFlag = true; - monitor.notifyAll(); - } - - private: - struct Empty {}; - typedef boost::variant Item; - sys::Monitor monitor; - std::queue queue; - bool shutdownFlag; -}; - - -BasicMessageChannel::BasicMessageChannel(Channel& ch) - : channel(ch), returnsHandler(0), - destGet(new WaitableDestination()), - destDispatch(new WaitableDestination()) -{ - incoming.addDestination(BASIC_RETURN, *destDispatch); -} - -void BasicMessageChannel::consume( - Queue& queue, std::string& tag, MessageListener* listener, - AckMode ackMode, bool noLocal, bool synch, const FieldTable* fields) -{ - { - // Note we create a consumer even if tag="". In that case - // It will be renamed when we handle BasicConsumeOkBody. - // - Mutex::ScopedLock l(lock); - ConsumerMap::iterator i = consumers.find(tag); - if (i != consumers.end()) - THROW_QPID_ERROR(CLIENT_ERROR, - "Consumer already exists with tag="+tag); - Consumer& c = consumers[tag]; - c.listener = listener; - c.ackMode = ackMode; - c.lastDeliveryTag = 0; - } - - // FIXME aconway 2007-03-23: get processed in both. - - // BasicConsumeOkBody is really processed in handle(), here - // we just pick up the tag to return to the user. - // - // We can't process it here because messages for the consumer may - // already be arriving. - // - BasicConsumeOkBody::shared_ptr ok = - channel.sendAndReceiveSync( - synch, - new BasicConsumeBody( - channel.version, 0, queue.getName(), tag, noLocal, - ackMode == NO_ACK, false, !synch, - fields ? *fields : FieldTable())); - tag = ok->getConsumerTag(); -} - - -void BasicMessageChannel::cancel(const std::string& tag, bool synch) { - Consumer c; - { - Mutex::ScopedLock l(lock); - ConsumerMap::iterator i = consumers.find(tag); - if (i == consumers.end()) - return; - c = i->second; - consumers.erase(i); - } - if(c.ackMode == LAZY_ACK && c.lastDeliveryTag > 0) - channel.send(new BasicAckBody(channel.version, c.lastDeliveryTag, true)); - channel.sendAndReceiveSync( - synch, new BasicCancelBody(channel.version, tag, !synch)); -} - -void BasicMessageChannel::close(){ - ConsumerMap consumersCopy; - { - Mutex::ScopedLock l(lock); - consumersCopy = consumers; - consumers.clear(); - } - destGet->shutdown(); - destDispatch->shutdown(); - for (ConsumerMap::iterator i=consumersCopy.begin(); - i != consumersCopy.end(); ++i) - { - Consumer& c = i->second; - if ((c.ackMode == LAZY_ACK || c.ackMode == AUTO_ACK) - && c.lastDeliveryTag > 0) - { - channel.send(new BasicAckBody(channel.version, c.lastDeliveryTag, true)); - } - } -} - - -bool BasicMessageChannel::get( - Message& msg, const Queue& queue, AckMode ackMode) -{ - // Prepare for incoming response - incoming.addDestination(BASIC_GET, *destGet); - channel.send( - new BasicGetBody(channel.version, 0, queue.getName(), ackMode)); - bool got = destGet->wait(msg); - return got; -} - -void BasicMessageChannel::publish( - const Message& msg, const Exchange& exchange, - const std::string& routingKey, bool mandatory, bool immediate) -{ - const string e = exchange.getName(); - string key = routingKey; - - // Make a header for the message - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - BasicHeaderProperties::copy( - *static_cast(header->getProperties()), msg); - header->setContentSize(msg.getData().size()); - - channel.send( - new BasicPublishBody( - channel.version, 0, e, key, mandatory, immediate)); - channel.send(header); - string data = msg.getData(); - u_int64_t data_length = data.length(); - if(data_length > 0){ - //frame itself uses 8 bytes - u_int32_t frag_size = channel.connection->getMaxFrameSize() - 8; - if(data_length < frag_size){ - channel.send(new AMQContentBody(data)); - }else{ - u_int32_t offset = 0; - u_int32_t remaining = data_length - offset; - while (remaining > 0) { - u_int32_t length = remaining > frag_size ? frag_size : remaining; - string frag(data.substr(offset, length)); - channel.send(new AMQContentBody(frag)); - - offset += length; - remaining = data_length - offset; - } - } - } -} - -void BasicMessageChannel::handle(boost::shared_ptr method) { - assert(method->amqpClassId() ==BasicGetBody::CLASS_ID); - switch(method->amqpMethodId()) { - case BasicGetOkBody::METHOD_ID: { - incoming.openReference(BASIC_REF); - incoming.createMessage(BASIC_GET, BASIC_REF); - return; - } - case BasicGetEmptyBody::METHOD_ID: { - incoming.getDestination(BASIC_GET).empty(); - incoming.removeDestination(BASIC_GET); - return; - } - case BasicDeliverBody::METHOD_ID: { - BasicDeliverBody::shared_ptr deliver= - boost::shared_polymorphic_downcast(method); - incoming.openReference(BASIC_REF); - Message& msg = incoming.createMessage( - deliver->getConsumerTag(), BASIC_REF); - msg.setDestination(deliver->getConsumerTag()); - msg.setDeliveryTag(deliver->getDeliveryTag()); - msg.setRedelivered(deliver->getRedelivered()); - return; - } - case BasicReturnBody::METHOD_ID: { - incoming.openReference(BASIC_REF); - incoming.createMessage(BASIC_RETURN, BASIC_REF); - return; - } - case BasicConsumeOkBody::METHOD_ID: { - Mutex::ScopedLock l(lock); - BasicConsumeOkBody::shared_ptr consumeOk = - boost::shared_polymorphic_downcast(method); - std::string tag = consumeOk->getConsumerTag(); - ConsumerMap::iterator i = consumers.find(std::string()); - if (i != consumers.end()) { - // Need to rename the un-named consumer. - if (consumers.find(tag) == consumers.end()) { - consumers[tag] = i->second; - consumers.erase(i); - } - else // Tag already exists. - throw ChannelException(404, "Tag already exists: "+tag); - } - // FIXME aconway 2007-03-23: Integrate consumer & destination - // maps. - incoming.addDestination(tag, *destDispatch); - return; - } - } - throw Channel::UnknownMethod(); -} - -void BasicMessageChannel::handle(AMQHeaderBody::shared_ptr header) { - BasicHeaderProperties* props = - boost::polymorphic_downcast( - header->getProperties()); - IncomingMessage::Reference& ref = incoming.getReference(BASIC_REF); - assert (ref.messages.size() == 1); - ref.messages.front().BasicHeaderProperties::operator=(*props); - incoming_size = header->getContentSize(); - if (incoming_size==0) - incoming.closeReference(BASIC_REF); -} - -void BasicMessageChannel::handle(AMQContentBody::shared_ptr content){ - incoming.appendReference(BASIC_REF, content->getData()); - size_t size = incoming.getReference(BASIC_REF).data.size(); - if (size >= incoming_size) { - incoming.closeReference(BASIC_REF); - if (size > incoming_size) - throw ChannelException(502, "Content exceeded declared size"); - } -} - -void BasicMessageChannel::deliver(Consumer& consumer, Message& msg){ - //record delivery tag: - consumer.lastDeliveryTag = msg.getDeliveryTag(); - - //allow registered listener to handle the message - consumer.listener->received(msg); - - if(channel.isOpen()){ - bool multiple(false); - switch(consumer.ackMode){ - case LAZY_ACK: - multiple = true; - if(++(consumer.count) < channel.getPrefetch()) - break; - //else drop-through - case AUTO_ACK: - consumer.lastDeliveryTag = 0; - channel.send( - new BasicAckBody( - channel.version, - msg.getDeliveryTag(), - multiple)); - case NO_ACK: // Nothing to do - case CLIENT_ACK: // User code must ack. - break; - // TODO aconway 2007-02-22: Provide a way for user - // to ack! - } - } - - //as it stands, transactionality is entirely orthogonal to ack - //mode, though the acks will not be processed by the broker under - //a transaction until it commits. -} - - -void BasicMessageChannel::run() { - while(channel.isOpen()) { - try { - Message msg; - bool gotMessge = destDispatch->wait(msg); - if (gotMessge) { - if(msg.getDestination() == BASIC_RETURN) { - ReturnedMessageHandler* handler=0; - { - Mutex::ScopedLock l(lock); - handler=returnsHandler; - } - if(handler != 0) - handler->returned(msg); - } - else { - Consumer consumer; - { - Mutex::ScopedLock l(lock); - ConsumerMap::iterator i = consumers.find( - msg.getDestination()); - if(i == consumers.end()) - THROW_QPID_ERROR(PROTOCOL_ERROR+504, - "Unknown consumer tag=" + - msg.getDestination()); - consumer = i->second; - } - deliver(consumer, msg); - } - } - } - catch (const ShutdownException&) { - /* Orderly shutdown */ - } - catch (const Exception& e) { - // FIXME aconway 2007-02-20: Report exception to user. - cout << "client::BasicMessageChannel::run() terminated by: " - << e.toString() << endl; - } - } -} - -void BasicMessageChannel::setReturnedMessageHandler(ReturnedMessageHandler* handler){ - Mutex::ScopedLock l(lock); - returnsHandler = handler; -} - -void BasicMessageChannel::setQos(){ - channel.sendAndReceive( - new BasicQosBody(channel.version, 0, channel.getPrefetch(), false)); - if(channel.isTransactional()) - channel.sendAndReceive(new TxSelectBody(channel.version)); -} - -}} // namespace qpid::client diff --git a/qpid/cpp/lib/client/BasicMessageChannel.h b/qpid/cpp/lib/client/BasicMessageChannel.h deleted file mode 100644 index aaedfd6bf1..0000000000 --- a/qpid/cpp/lib/client/BasicMessageChannel.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef _client_BasicMessageChannel_h -#define _client_BasicMessageChannel_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 "MessageChannel.h" -#include "IncomingMessage.h" -#include - -namespace qpid { -namespace client { -/** - * Messaging implementation using AMQP 0-8 BasicMessageChannel class - * to send and receiving messages. - */ -class BasicMessageChannel : public MessageChannel -{ - public: - BasicMessageChannel(Channel& parent); - - void consume( - Queue& queue, std::string& tag, MessageListener* listener, - AckMode ackMode = NO_ACK, bool noLocal = false, bool synch = true, - const framing::FieldTable* fields = 0); - - void cancel(const std::string& tag, bool synch = true); - - bool get(Message& msg, const Queue& queue, AckMode ackMode = NO_ACK); - - void publish(const Message& msg, const Exchange& exchange, - const std::string& routingKey, - bool mandatory = false, bool immediate = false); - - void setReturnedMessageHandler(ReturnedMessageHandler* handler); - - void run(); - - void handle(boost::shared_ptr); - - void handle(shared_ptr); - - void handle(shared_ptr); - - void setQos(); - - void close(); - - private: - - class WaitableDestination; - struct Consumer{ - MessageListener* listener; - AckMode ackMode; - int count; - u_int64_t lastDeliveryTag; - }; - typedef std::map ConsumerMap; - - void deliver(Consumer& consumer, Message& msg); - - sys::Mutex lock; - Channel& channel; - IncomingMessage incoming; - uint64_t incoming_size; - ConsumerMap consumers ; - ReturnedMessageHandler* returnsHandler; - boost::scoped_ptr destGet; - boost::scoped_ptr destDispatch; -}; - -}} // namespace qpid::client - - - -#endif /*!_client_BasicMessageChannel_h*/ diff --git a/qpid/cpp/lib/client/ClientAdapter.cpp b/qpid/cpp/lib/client/ClientAdapter.cpp deleted file mode 100644 index c77f049c96..0000000000 --- a/qpid/cpp/lib/client/ClientAdapter.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 "AMQP_ClientOperations.h" -#include "ClientAdapter.h" -#include "Connection.h" -#include "Exception.h" -#include "AMQMethodBody.h" - -namespace qpid { -namespace client { - -using namespace qpid; -using namespace qpid::framing; - -typedef std::vector::iterator queue_iterator; - -void ClientAdapter::handleMethodInContext( - boost::shared_ptr method, - const MethodContext& context -) -{ - try{ - method->invoke(*clientOps, context); - }catch(ChannelException& e){ - connection.client->getChannel().close( - context, e.code, e.toString(), - method->amqpClassId(), method->amqpMethodId()); - connection.closeChannel(getId()); - }catch(ConnectionException& e){ - connection.client->getConnection().close( - context, e.code, e.toString(), - method->amqpClassId(), method->amqpMethodId()); - }catch(std::exception& e){ - connection.client->getConnection().close( - context, 541/*internal error*/, e.what(), - method->amqpClassId(), method->amqpMethodId()); - } -} - -void ClientAdapter::handleHeader(AMQHeaderBody::shared_ptr body) { - channel->handleHeader(body); -} - -void ClientAdapter::handleContent(AMQContentBody::shared_ptr body) { - channel->handleContent(body); -} - -void ClientAdapter::handleHeartbeat(AMQHeartbeatBody::shared_ptr) { - // TODO aconway 2007-01-17: Implement heartbeats. -} - - - -}} // namespace qpid::client - diff --git a/qpid/cpp/lib/client/ClientAdapter.h b/qpid/cpp/lib/client/ClientAdapter.h deleted file mode 100644 index d5e16fc6ad..0000000000 --- a/qpid/cpp/lib/client/ClientAdapter.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef _client_ClientAdapter_h -#define _client_ClientAdapter_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 "ChannelAdapter.h" -#include "ClientChannel.h" - -namespace qpid { -namespace client { - -class AMQMethodBody; -class Connection; - -/** - * Per-channel protocol adapter. - * - * Translates protocol bodies into calls on the core Channel, - * Connection and Client objects. - * - * Owns a channel, has references to Connection and Client. - */ -class ClientAdapter : public framing::ChannelAdapter -{ - public: - ClientAdapter(std::auto_ptr ch, Connection&, Client&); - Channel& getChannel() { return *channel; } - - void handleHeader(boost::shared_ptr); - void handleContent(boost::shared_ptr); - void handleHeartbeat(boost::shared_ptr); - - private: - void handleMethodInContext( - boost::shared_ptr method, - const framing::MethodContext& context); - - class ClientOps; - - std::auto_ptr channel; - Connection& connection; - Client& client; - boost::shared_ptr clientOps; -}; - -}} // namespace qpid::client - - - -#endif /*!_client_ClientAdapter_h*/ diff --git a/qpid/cpp/lib/client/ClientChannel.cpp b/qpid/cpp/lib/client/ClientChannel.cpp deleted file mode 100644 index 98feff9389..0000000000 --- a/qpid/cpp/lib/client/ClientChannel.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. - * - */ -#include -#include -#include -#include -#include -#include -#include "Connection.h" -#include "BasicMessageChannel.h" -// FIXME aconway 2007-03-21: -//#include "MessageMessageChannel.h" - -// FIXME aconway 2007-01-26: Evaluate all throws, ensure consistent -// handling of errors that should close the connection or the channel. -// Make sure the user thread receives a connection in each case. -// -using namespace std; -using namespace boost; -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; - -Channel::Channel(bool _transactional, u_int16_t _prefetch, - MessageChannel* impl) : - // FIXME aconway 2007-03-21: MessageMessageChannel - messaging(impl ? impl : new BasicMessageChannel(*this)), - connection(0), - prefetch(_prefetch), - transactional(_transactional) -{ } - -Channel::~Channel(){ - close(); -} - -void Channel::open(ChannelId id, Connection& con) -{ - if (isOpen()) - THROW_QPID_ERROR(INTERNAL_ERROR, "Attempt to re-open channel "+id); - connection = &con; - init(id, con, con.getVersion()); // ChannelAdapter initialization. - string oob; - if (id != 0) - sendAndReceive(new ChannelOpenBody(version, oob)); -} - -void Channel::protocolInit( - const std::string& uid, const std::string& pwd, const std::string& vhost) { - assert(connection); - responses.expect(); - connection->connector->init(); // Send ProtocolInit block. - ConnectionStartBody::shared_ptr connectionStart = - responses.receive(); - - FieldTable props; - string mechanism("PLAIN"); - string response = ((char)0) + uid + ((char)0) + pwd; - string locale("en_US"); - ConnectionTuneBody::shared_ptr proposal = - sendAndReceive( - new ConnectionStartOkBody( - version, connectionStart->getRequestId(), - props, mechanism, - response, locale)); - - /** - * Assume for now that further challenges will not be required - //receive connection.secure - responses.receive(connection_secure)); - //send connection.secure-ok - connection->send(new AMQFrame(0, new ConnectionSecureOkBody(response))); - **/ - - send(new ConnectionTuneOkBody( - version, proposal->getRequestId(), - proposal->getChannelMax(), connection->getMaxFrameSize(), - proposal->getHeartbeat())); - - uint16_t heartbeat = proposal->getHeartbeat(); - connection->connector->setReadTimeout(heartbeat * 2); - connection->connector->setWriteTimeout(heartbeat); - - // Send connection open. - std::string capabilities; - responses.expect(); - send(new ConnectionOpenBody(version, vhost, capabilities, true)); - //receive connection.open-ok (or redirect, but ignore that for now - //esp. as using force=true). - AMQMethodBody::shared_ptr openResponse = responses.receive(); - if(openResponse->isA()) { - //ok - }else if(openResponse->isA()){ - //ignore for now - ConnectionRedirectBody::shared_ptr redirect( - shared_polymorphic_downcast(openResponse)); - cout << "Received redirection to " << redirect->getHost() - << endl; - } else { - THROW_QPID_ERROR(PROTOCOL_ERROR, "Bad response to Connection.open"); - } -} - -bool Channel::isOpen() const { return connection; } - -void Channel::setQos() { - messaging->setQos(); -} - -void Channel::setPrefetch(uint16_t _prefetch){ - prefetch = _prefetch; - setQos(); -} - -void Channel::declareExchange(Exchange& exchange, bool synch){ - string name = exchange.getName(); - string type = exchange.getType(); - FieldTable args; - sendAndReceiveSync( - synch, - new ExchangeDeclareBody( - version, 0, name, type, false, false, false, false, !synch, args)); -} - -void Channel::deleteExchange(Exchange& exchange, bool synch){ - string name = exchange.getName(); - sendAndReceiveSync( - synch, - new ExchangeDeleteBody(version, 0, name, false, !synch)); -} - -void Channel::declareQueue(Queue& queue, bool synch){ - string name = queue.getName(); - FieldTable args; - QueueDeclareOkBody::shared_ptr response = - sendAndReceiveSync( - synch, - new QueueDeclareBody( - version, 0, name, false/*passive*/, queue.isDurable(), - queue.isExclusive(), queue.isAutoDelete(), !synch, args)); - if(synch) { - if(queue.getName().length() == 0) - queue.setName(response->getQueue()); - } -} - -void Channel::deleteQueue(Queue& queue, bool ifunused, bool ifempty, bool synch){ - //ticket, queue, ifunused, ifempty, nowait - string name = queue.getName(); - sendAndReceiveSync( - synch, - new QueueDeleteBody(version, 0, name, ifunused, ifempty, !synch)); -} - -void Channel::bind(const Exchange& exchange, const Queue& queue, const std::string& key, const FieldTable& args, bool synch){ - string e = exchange.getName(); - string q = queue.getName(); - sendAndReceiveSync( - synch, - new QueueBindBody(version, 0, q, e, key,!synch, args)); -} - -void Channel::commit(){ - sendAndReceive(new TxCommitBody(version)); -} - -void Channel::rollback(){ - sendAndReceive(new TxRollbackBody(version)); -} - -void Channel::handleMethodInContext( - AMQMethodBody::shared_ptr method, const MethodContext&) -{ - // TODO aconway 2007-03-23: Special case for consume OK as it - // is both an expected response and needs handling in this thread. - // Need to review & reationalize the client-side processing model. - if (method->isA()) { - messaging->handle(method); - responses.signalResponse(method); - return; - } - if(responses.isWaiting()) { - responses.signalResponse(method); - return; - } - try { - switch (method->amqpClassId()) { - case BasicDeliverBody::CLASS_ID: messaging->handle(method); break; - case ChannelCloseBody::CLASS_ID: handleChannel(method); break; - case ConnectionCloseBody::CLASS_ID: handleConnection(method); break; - default: throw UnknownMethod(); - } - } - catch (const UnknownMethod&) { - connection->close( - 504, "Unknown method", - method->amqpClassId(), method->amqpMethodId()); - } - } - -void Channel::handleChannel(AMQMethodBody::shared_ptr method) { - switch (method->amqpMethodId()) { - case ChannelCloseBody::METHOD_ID: - peerClose(shared_polymorphic_downcast(method)); - return; - case ChannelFlowBody::METHOD_ID: - // FIXME aconway 2007-02-22: Not yet implemented. - return; - } - throw UnknownMethod(); -} - -void Channel::handleConnection(AMQMethodBody::shared_ptr method) { - if (method->amqpMethodId() == ConnectionCloseBody::METHOD_ID) { - connection->close(); - return; - } - throw UnknownMethod(); -} - -void Channel::handleHeader(AMQHeaderBody::shared_ptr body){ - messaging->handle(body); -} - -void Channel::handleContent(AMQContentBody::shared_ptr body){ - messaging->handle(body); -} - -void Channel::handleHeartbeat(AMQHeartbeatBody::shared_ptr /*body*/){ - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Channel received heartbeat"); -} - -void Channel::start(){ - dispatcher = Thread(*messaging); -} - -// Close called by local application. -void Channel::close( - uint16_t code, const std::string& text, - ClassId classId, MethodId methodId) -{ - if (isOpen()) { - try { - if (getId() != 0) { - sendAndReceive( - new ChannelCloseBody( - version, code, text, classId, methodId)); - } - static_cast(connection)->erase(getId()); - closeInternal(); - } catch (...) { - static_cast(connection)->erase(getId()); - closeInternal(); - throw; - } - } -} - -// Channel closed by peer. -void Channel::peerClose(ChannelCloseBody::shared_ptr) { - assert(isOpen()); - closeInternal(); -} - -void Channel::closeInternal() { - if (isOpen()); - { - messaging->close(); - connection = 0; - // A 0 response means we are closed. - responses.signalResponse(AMQMethodBody::shared_ptr()); - } - dispatcher.join(); -} - -AMQMethodBody::shared_ptr Channel::sendAndReceive( - AMQMethodBody* toSend, ClassId c, MethodId m) -{ - responses.expect(); - send(toSend); - return responses.receive(c, m); -} - -AMQMethodBody::shared_ptr Channel::sendAndReceiveSync( - bool sync, AMQMethodBody* body, ClassId c, MethodId m) -{ - if(sync) - return sendAndReceive(body, c, m); - else { - send(body); - return AMQMethodBody::shared_ptr(); - } -} - -void Channel::consume( - Queue& queue, std::string& tag, MessageListener* listener, - AckMode ackMode, bool noLocal, bool synch, const FieldTable* fields) { - messaging->consume(queue, tag, listener, ackMode, noLocal, synch, fields); -} - -void Channel::cancel(const std::string& tag, bool synch) { - messaging->cancel(tag, synch); -} - -bool Channel::get(Message& msg, const Queue& queue, AckMode ackMode) { - return messaging->get(msg, queue, ackMode); -} - -void Channel::publish(const Message& msg, const Exchange& exchange, - const std::string& routingKey, - bool mandatory, bool immediate) { - messaging->publish(msg, exchange, routingKey, mandatory, immediate); -} - -void Channel::setReturnedMessageHandler(ReturnedMessageHandler* handler) { - messaging->setReturnedMessageHandler(handler); -} - -void Channel::run() { - messaging->run(); -} - diff --git a/qpid/cpp/lib/client/ClientChannel.h b/qpid/cpp/lib/client/ClientChannel.h deleted file mode 100644 index f6fe18da20..0000000000 --- a/qpid/cpp/lib/client/ClientChannel.h +++ /dev/null @@ -1,352 +0,0 @@ -#ifndef _client_ClientChannel_h -#define _client_ClientChannel_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "ChannelAdapter.h" -#include "Thread.h" -#include "AckMode.h" - -namespace qpid { - -namespace framing { -class ChannelCloseBody; -class AMQMethodBody; -} - -namespace client { - -class Connection; -class MessageChannel; -class MessageListener; -class ReturnedMessageHandler; - -/** - * Represents an AMQP channel, i.e. loosely a session of work. It - * is through a channel that most of the AMQP 'methods' are - * exposed. - * - * \ingroup clientapi - */ -class Channel : public framing::ChannelAdapter -{ - private: - struct UnknownMethod {}; - - sys::Mutex lock; - boost::scoped_ptr messaging; - Connection* connection; - sys::Thread dispatcher; - ResponseHandler responses; - - uint16_t prefetch; - const bool transactional; - framing::ProtocolVersion version; - - void handleHeader(framing::AMQHeaderBody::shared_ptr body); - void handleContent(framing::AMQContentBody::shared_ptr body); - void handleHeartbeat(framing::AMQHeartbeatBody::shared_ptr body); - void handleMethodInContext( - framing::AMQMethodBody::shared_ptr, const framing::MethodContext&); - void handleChannel(framing::AMQMethodBody::shared_ptr method); - void handleConnection(framing::AMQMethodBody::shared_ptr method); - - void setQos(); - - void protocolInit( - const std::string& uid, const std::string& pwd, - const std::string& vhost); - - framing::AMQMethodBody::shared_ptr sendAndReceive( - framing::AMQMethodBody*, framing::ClassId, framing::MethodId); - - framing::AMQMethodBody::shared_ptr sendAndReceiveSync( - bool sync, - framing::AMQMethodBody*, framing::ClassId, framing::MethodId); - - template - boost::shared_ptr sendAndReceive(framing::AMQMethodBody* body) { - return boost::shared_polymorphic_downcast( - sendAndReceive(body, BodyType::CLASS_ID, BodyType::METHOD_ID)); - } - - template - boost::shared_ptr sendAndReceiveSync( - bool sync, framing::AMQMethodBody* body) { - return boost::shared_polymorphic_downcast( - sendAndReceiveSync( - sync, body, BodyType::CLASS_ID, BodyType::METHOD_ID)); - } - - void open(framing::ChannelId, Connection&); - void closeInternal(); - void peerClose(boost::shared_ptr); - - // FIXME aconway 2007-02-23: Get rid of friendships. - friend class Connection; - friend class BasicMessageChannel; // for sendAndReceive. - friend class MessageMessageChannel; // for sendAndReceive. - - public: - - /** - * Creates a channel object. - * - * @param transactional if true, the publishing and acknowledgement - * of messages will be transactional and can be committed or - * aborted in atomic units (@see commit(), @see rollback()) - * - * @param prefetch specifies the number of unacknowledged - * messages the channel is willing to have sent to it - * asynchronously - * - * @param messageImpl Alternate messaging implementation class to - * allow alternate protocol implementations of messaging - * operations. Takes ownership. - */ - Channel( - bool transactional = false, u_int16_t prefetch = 500, - MessageChannel* messageImpl = 0); - - ~Channel(); - - /** - * Declares an exchange. - * - * In AMQP Exchanges are the destinations to which messages - * are published. They have Queues bound to them and route - * messages they receive to those queues. The routing rules - * depend on the type of the exchange. - * - * @param exchange an Exchange object representing the - * exchange to declare - * - * @param synch if true this call will block until a response - * is received from the broker - */ - void declareExchange(Exchange& exchange, bool synch = true); - /** - * Deletes an exchange - * - * @param exchange an Exchange object representing the exchange to delete - * - * @param synch if true this call will block until a response - * is received from the broker - */ - void deleteExchange(Exchange& exchange, bool synch = true); - /** - * Declares a Queue - * - * @param queue a Queue object representing the queue to declare - * - * @param synch if true this call will block until a response - * is received from the broker - */ - void declareQueue(Queue& queue, bool synch = true); - /** - * Deletes a Queue - * - * @param queue a Queue object representing the queue to delete - * - * @param synch if true this call will block until a response - * is received from the broker - */ - void deleteQueue(Queue& queue, bool ifunused = false, bool ifempty = false, bool synch = true); - /** - * Binds a queue to an exchange. The exact semantics of this - * (in particular how 'routing keys' and 'binding arguments' - * are used) depends on the type of the exchange. - * - * @param exchange an Exchange object representing the - * exchange to bind to - * - * @param queue a Queue object representing the queue to be - * bound - * - * @param key the 'routing key' for the binding - * - * @param args the 'binding arguments' for the binding - * - * @param synch if true this call will block until a response - * is received from the broker - */ - void bind(const Exchange& exchange, const Queue& queue, - const std::string& key, const framing::FieldTable& args, - bool synch = true); - - /** - * For a transactional channel this will commit all - * publications and acknowledgements since the last commit (or - * the channel was opened if there has been no previous - * commit). This will cause published messages to become - * available to consumers and acknowledged messages to be - * consumed and removed from the queues they were dispatched - * from. - * - * Transactionailty of a channel is specified when the channel - * object is created (@see Channel()). - */ - void commit(); - - /** - * For a transactional channel, this will rollback any - * publications or acknowledgements. It will be as if the - * ppblished messages were never sent and the acknowledged - * messages were never consumed. - */ - void rollback(); - - /** - * Change the prefetch in use. - */ - void setPrefetch(uint16_t prefetch); - - uint16_t getPrefetch() { return prefetch; } - - /** - * Start message dispatching on a new thread - */ - void start(); - - /** - * Close the channel with optional error information. - * Closing a channel that is not open has no effect. - */ - void close( - framing::ReplyCode = 200, const std::string& ="OK", - framing::ClassId = 0, framing::MethodId = 0); - - /** True if the channel is transactional */ - bool isTransactional() { return transactional; } - - /** True if the channel is open */ - bool isOpen() const; - - /** Get the connection associated with this channel */ - Connection& getConnection() { return *connection; } - - /** Return the protocol version */ - framing::ProtocolVersion getVersion() const { return version ; } - - /** - * Creates a 'consumer' for a queue. Messages in (or arriving - * at) that queue will be delivered to consumers - * asynchronously. - * - * @param queue a Queue instance representing the queue to - * consume from - * - * @param tag an identifier to associate with the consumer - * that can be used to cancel its subscription (if empty, this - * will be assigned by the broker) - * - * @param listener a pointer to an instance of an - * implementation of the MessageListener interface. Messages - * received from this queue for this consumer will result in - * invocation of the received() method on the listener, with - * the message itself passed in. - * - * @param ackMode the mode of acknowledgement that the broker - * should assume for this consumer. @see AckMode - * - * @param noLocal if true, this consumer will not be sent any - * message published by this connection - * - * @param synch if true this call will block until a response - * is received from the broker - */ - void consume( - Queue& queue, std::string& tag, MessageListener* listener, - AckMode ackMode = NO_ACK, bool noLocal = false, bool synch = true, - const framing::FieldTable* fields = 0); - - /** - * Cancels a subscription previously set up through a call to consume(). - * - * @param tag the identifier used (or assigned) in the consume - * request that set up the subscription to be cancelled. - * - * @param synch if true this call will block until a response - * is received from the broker - */ - void cancel(const std::string& tag, bool synch = true); - /** - * Synchronous pull of a message from a queue. - * - * @param msg a message object that will contain the message - * headers and content if the call completes. - * - * @param queue the queue to consume from - * - * @param ackMode the acknowledgement mode to use (@see - * AckMode) - * - * @return true if a message was succcessfully dequeued from - * the queue, false if the queue was empty. - */ - bool get(Message& msg, const Queue& queue, AckMode ackMode = NO_ACK); - - /** - * Publishes (i.e. sends a message to the broker). - * - * @param msg the message to publish - * - * @param exchange the exchange to publish the message to - * - * @param routingKey the routing key to publish with - * - * @param mandatory if true and the exchange to which this - * publish is directed has no matching bindings, the message - * will be returned (see setReturnedMessageHandler()). - * - * @param immediate if true and there is no consumer to - * receive this message on publication, the message will be - * returned (see setReturnedMessageHandler()). - */ - void publish(const Message& msg, const Exchange& exchange, - const std::string& routingKey, - bool mandatory = false, bool immediate = false); - - /** - * Set a handler for this channel that will process any - * returned messages - * - * @see publish() - */ - void setReturnedMessageHandler(ReturnedMessageHandler* handler); - - /** - * Deliver messages from the broker to the appropriate MessageListener. - */ - void run(); - - -}; - -}} - -#endif /*!_client_ClientChannel_h*/ diff --git a/qpid/cpp/lib/client/ClientExchange.cpp b/qpid/cpp/lib/client/ClientExchange.cpp deleted file mode 100644 index 5e5f3f14c6..0000000000 --- a/qpid/cpp/lib/client/ClientExchange.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::Exchange::Exchange(std::string _name, std::string _type) : name(_name), type(_type){} -const std::string& qpid::client::Exchange::getName() const { return name; } -const std::string& qpid::client::Exchange::getType() const { return type; } - -const std::string qpid::client::Exchange::DIRECT_EXCHANGE = "direct"; -const std::string qpid::client::Exchange::TOPIC_EXCHANGE = "topic"; -const std::string qpid::client::Exchange::HEADERS_EXCHANGE = "headers"; - -const qpid::client::Exchange qpid::client::Exchange::DEFAULT_EXCHANGE("", DIRECT_EXCHANGE); -const qpid::client::Exchange qpid::client::Exchange::STANDARD_DIRECT_EXCHANGE("amq.direct", DIRECT_EXCHANGE); -const qpid::client::Exchange qpid::client::Exchange::STANDARD_TOPIC_EXCHANGE("amq.topic", TOPIC_EXCHANGE); -const qpid::client::Exchange qpid::client::Exchange::STANDARD_HEADERS_EXCHANGE("amq.headers", HEADERS_EXCHANGE); diff --git a/qpid/cpp/lib/client/ClientExchange.h b/qpid/cpp/lib/client/ClientExchange.h deleted file mode 100644 index a8ac21fa9b..0000000000 --- a/qpid/cpp/lib/client/ClientExchange.h +++ /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 - -#ifndef _Exchange_ -#define _Exchange_ - -namespace qpid { -namespace client { - - /** - * A 'handle' used to represent an AMQP exchange in the Channel - * methods. Exchanges are the destinations to which messages are - * published. - * - * There are different types of exchange (the standard types are - * available as static constants, see DIRECT_EXCHANGE, - * TOPIC_EXCHANGE and HEADERS_EXCHANGE). A Queue can be bound to - * an exchange using Channel::bind() and messages published to - * that exchange are then routed to the queue based on the details - * of the binding and the type of exchange. - * - * There are some standard exchange instances that are predeclared - * on all AMQP brokers. These are defined as static members - * STANDARD_DIRECT_EXCHANGE, STANDARD_TOPIC_EXCHANGE and - * STANDARD_HEADERS_EXCHANGE. There is also the 'default' exchange - * (member DEFAULT_EXCHANGE) which is nameless and of type - * 'direct' and has every declared queue bound to it by queue - * name. - * - * \ingroup clientapi - */ - class Exchange{ - const std::string name; - const std::string type; - - public: - /** - * A direct exchange routes messages published with routing - * key X to any queue bound with key X (i.e. an exact match is - * used). - */ - static const std::string DIRECT_EXCHANGE; - /** - * A topic exchange treat the key with which a queue is bound - * as a pattern and routes all messages whose routing keys - * match that pattern to the bound queue. The routing key for - * a message must consist of zero or more alpha-numeric words - * delimited by dots. The pattern is of a similar form but * - * can be used to match excatly one word and # can be used to - * match zero or more words. - */ - static const std::string TOPIC_EXCHANGE; - /** - * The headers exchange routes messages based on whether their - * headers match the binding arguments specified when - * binding. (see the AMQP spec for more details). - */ - static const std::string HEADERS_EXCHANGE; - - /** - * The 'default' exchange, nameless and of type 'direct'. Has - * every declared queue bound to it by name. - */ - static const Exchange DEFAULT_EXCHANGE; - /** - * The standard direct exchange, named amq.direct. - */ - static const Exchange STANDARD_DIRECT_EXCHANGE; - /** - * The standard topic exchange, named amq.topic. - */ - static const Exchange STANDARD_TOPIC_EXCHANGE; - /** - * The standard headers exchange, named amq.header. - */ - static const Exchange STANDARD_HEADERS_EXCHANGE; - - Exchange(std::string name, std::string type = DIRECT_EXCHANGE); - const std::string& getName() const; - const std::string& getType() const; - }; - -} -} - - -#endif diff --git a/qpid/cpp/lib/client/ClientMessage.h b/qpid/cpp/lib/client/ClientMessage.h deleted file mode 100644 index a326c24aed..0000000000 --- a/qpid/cpp/lib/client/ClientMessage.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _client_ClientMessage_h -#define _client_ClientMessage_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "framing/BasicHeaderProperties.h" - -namespace qpid { -namespace client { - -/** - * A representation of messages for sent or recived through the - * client api. - * - * \ingroup clientapi - */ -class Message : public framing::BasicHeaderProperties { - public: - Message(const std::string& data_=std::string()) : data(data_) {} - - std::string getData() const { return data; } - void setData(const std::string& _data) { data = _data; } - - std::string getDestination() const { return destination; } - void setDestination(const std::string& dest) { destination = dest; } - - // TODO aconway 2007-03-22: only needed for Basic.deliver support. - uint64_t getDeliveryTag() const { return deliveryTag; } - void setDeliveryTag(uint64_t dt) { deliveryTag = dt; } - - bool isRedelivered() const { return redelivered; } - void setRedelivered(bool _redelivered){ redelivered = _redelivered; } - - private: - std::string data; - std::string destination; - bool redelivered; - uint64_t deliveryTag; -}; - -}} - -#endif /*!_client_ClientMessage_h*/ diff --git a/qpid/cpp/lib/client/ClientQueue.cpp b/qpid/cpp/lib/client/ClientQueue.cpp deleted file mode 100644 index 773be504d8..0000000000 --- a/qpid/cpp/lib/client/ClientQueue.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::Queue::Queue() : name(""), autodelete(true), exclusive(true), durable(false){} - -qpid::client::Queue::Queue(std::string _name) : name(_name), autodelete(false), exclusive(false), durable(false){} - -qpid::client::Queue::Queue(std::string _name, bool temp) : name(_name), autodelete(temp), exclusive(temp), durable(false){} - -qpid::client::Queue::Queue(std::string _name, bool _autodelete, bool _exclusive, bool _durable) - : name(_name), autodelete(_autodelete), exclusive(_exclusive), durable(_durable){} - -const std::string& qpid::client::Queue::getName() const{ - return name; -} - -void qpid::client::Queue::setName(const std::string& _name){ - name = _name; -} - -bool qpid::client::Queue::isAutoDelete() const{ - return autodelete; -} - -bool qpid::client::Queue::isExclusive() const{ - return exclusive; -} - -bool qpid::client::Queue::isDurable() const{ - return durable; -} - -void qpid::client::Queue::setDurable(bool _durable){ - durable = _durable; -} - - - - diff --git a/qpid/cpp/lib/client/ClientQueue.h b/qpid/cpp/lib/client/ClientQueue.h deleted file mode 100644 index b37a44b004..0000000000 --- a/qpid/cpp/lib/client/ClientQueue.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef _client_ClientQueue_h -#define _client_ClientQueue_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 { - - /** - * A 'handle' used to represent an AMQP queue in the Channel - * methods. Creating an instance of this class does not cause the - * queue to be created on the broker. Rather, an instance of this - * class should be passed to Channel::declareQueue() to ensure - * that the queue exists or is created. - * - * Queues hold messages and allow clients to consume - * (see Channel::consume()) or get (see Channel::get()) those messags. A - * queue receives messages by being bound to one or more Exchange; - * messages published to that exchange may then be routed to the - * queue based on the details of the binding and the type of the - * exchange (see Channel::bind()). - * - * Queues are identified by a name. They can be exclusive (in which - * case they can only be used in the context of the connection - * over which they were declared, and are deleted when then - * connection closes), or they can be shared. Shared queues can be - * auto deleted when they have no consumers. - * - * We use the term 'temporary queue' to refer to an exclusive - * queue. - * - * \ingroup clientapi - */ - class Queue{ - std::string name; - const bool autodelete; - const bool exclusive; - bool durable; - - public: - - /** - * Creates an unnamed, non-durable, temporary queue. A name - * will be assigned to this queue instance by a call to - * Channel::declareQueue(). - */ - Queue(); - /** - * Creates a shared, non-durable, queue with a given name, - * that will not be autodeleted. - * - * @param name the name of the queue - */ - Queue(std::string name); - /** - * Creates a non-durable queue with a given name. - * - * @param name the name of the queue - * - * @param temp if true the queue will be a temporary queue, if - * false it will be shared and not autodeleted. - */ - Queue(std::string name, bool temp); - /** - * This constructor allows the autodelete, exclusive and - * durable propeties to be explictly set. Note however that if - * exclusive is true, autodelete has no meaning as exclusive - * queues are always destroyed when the connection that - * created them is closed. - */ - Queue(std::string name, bool autodelete, bool exclusive, bool durable); - const std::string& getName() const; - void setName(const std::string&); - bool isAutoDelete() const; - bool isExclusive() const; - bool isDurable() const; - void setDurable(bool durable); - }; - -} -} - -#endif /*!_client_ClientQueue_h*/ diff --git a/qpid/cpp/lib/client/Connection.cpp b/qpid/cpp/lib/client/Connection.cpp deleted file mode 100644 index 618f3cbc92..0000000000 --- a/qpid/cpp/lib/client/Connection.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 -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace qpid::framing; -using namespace qpid::sys; - - -namespace qpid { -namespace client { - -const std::string Connection::OK("OK"); - -Connection::Connection( - bool _debug, uint32_t _max_frame_size, - framing::ProtocolVersion _version -) : channelIdCounter(0), version(_version), max_frame_size(_max_frame_size), - defaultConnector(version, _debug, _max_frame_size), - isOpen(false), debug(_debug) -{ - setConnector(defaultConnector); -} - -Connection::~Connection(){} - -void Connection::setConnector(Connector& con) -{ - connector = &con; - connector->setInputHandler(this); - connector->setTimeoutHandler(this); - connector->setShutdownHandler(this); - out = connector->getOutputHandler(); -} - -void Connection::open( - const std::string& host, int port, - const std::string& uid, const std::string& pwd, const std::string& vhost) -{ - if (isOpen) - THROW_QPID_ERROR(INTERNAL_ERROR, "Channel object is already open"); - connector->connect(host, port); - channels[0] = &channel0; - channel0.open(0, *this); - channel0.protocolInit(uid, pwd, vhost); - isOpen = true; -} - -void Connection::shutdown() { - close(); -} - -void Connection::close( - ReplyCode code, const string& msg, ClassId classId, MethodId methodId -) -{ - if(isOpen) { - // TODO aconway 2007-01-29: Exception handling - could end up - // partly closed with threads left unjoined. - isOpen = false; - channel0.sendAndReceive( - new ConnectionCloseBody( - getVersion(), code, msg, classId, methodId)); - - using boost::bind; - for_each(channels.begin(), channels.end(), - bind(&Channel::closeInternal, - bind(&ChannelMap::value_type::second, _1))); - channels.clear(); - connector->close(); - } -} - -void Connection::openChannel(Channel& channel) { - ChannelId id = ++channelIdCounter; - assert (channels.find(id) == channels.end()); - assert(out); - channels[id] = &channel; - channel.open(id, *this); -} - -void Connection::erase(ChannelId id) { - channels.erase(id); -} - -void Connection::received(AMQFrame* frame){ - // FIXME aconway 2007-01-25: Mutex - ChannelId id = frame->getChannel(); - Channel* channel = channels[id]; - // FIXME aconway 2007-01-26: Exception thrown here is hanging the - // client. Need to review use of exceptions. - if (channel == 0) - THROW_QPID_ERROR( - PROTOCOL_ERROR+504, - (boost::format("Invalid channel number %g") % id).str()); - try{ - channel->handleBody(frame->getBody()); - }catch(const qpid::QpidError& e){ - channelException( - *channel, dynamic_cast(frame->getBody().get()), e); - } -} - -void Connection::send(AMQFrame* frame) { - out->send(frame); -} - -void Connection::channelException( - Channel& channel, AMQMethodBody* method, const QpidError& e) -{ - int code = (e.code >= PROTOCOL_ERROR) ? e.code - PROTOCOL_ERROR : 500; - string msg = e.msg; - if(method == 0) - channel.close(code, msg); - else - channel.close( - code, msg, method->amqpClassId(), method->amqpMethodId()); -} - -void Connection::idleIn(){ - connector->close(); -} - -void Connection::idleOut(){ - out->send(new AMQFrame(version, 0, new AMQHeartbeatBody())); -} - -}} // namespace qpid::client diff --git a/qpid/cpp/lib/client/Connection.h b/qpid/cpp/lib/client/Connection.h deleted file mode 100644 index 627266e580..0000000000 --- a/qpid/cpp/lib/client/Connection.h +++ /dev/null @@ -1,179 +0,0 @@ -#ifndef _client_Connection_ -#define _client_Connection_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "QpidError.h" -#include "ClientChannel.h" -#include "Connector.h" -#include "sys/ShutdownHandler.h" -#include "sys/TimeoutHandler.h" - - -namespace qpid { - -/** - * The client namespace contains all classes that make up a client - * implementation of the AMQP protocol. The key classes that form - * the basis of the client API to be used by applications are - * Connection and Channel. - */ -namespace client { - -/** - * \internal provide access to selected private channel functions - * for the Connection without making it a friend of the entire channel. - */ -class ConnectionForChannel : - public framing::InputHandler, - public framing::OutputHandler, - public sys::TimeoutHandler, - public sys::ShutdownHandler - -{ - private: - friend class Channel; - virtual void erase(framing::ChannelId) = 0; -}; - - -/** - * \defgroup clientapi Application API for an AMQP client - */ - -/** - * Represents a connection to an AMQP broker. All communication is - * initiated by establishing a connection, then opening one or - * more Channels over that connection. - * - * \ingroup clientapi - */ -class Connection : public ConnectionForChannel -{ - typedef std::map ChannelMap; - - framing::ChannelId channelIdCounter; - static const std::string OK; - - framing::ProtocolVersion version; - const uint32_t max_frame_size; - ChannelMap channels; - Connector defaultConnector; - Connector* connector; - framing::OutputHandler* out; - volatile bool isOpen; - Channel channel0; - bool debug; - - void erase(framing::ChannelId); - void channelException( - Channel&, framing::AMQMethodBody*, const QpidError&); - - // TODO aconway 2007-01-26: too many friendships, untagle these classes. - friend class Channel; - - public: - /** - * Creates a connection object, but does not open the - * connection. - * - * @param _version the version of the protocol to connect with - * - * @param debug turns on tracing for the connection - * (i.e. prints details of the frames sent and received to std - * out). Optional and defaults to false. - * - * @param max_frame_size the maximum frame size that the - * client will accept. Optional and defaults to 65536. - */ - Connection(bool debug = false, uint32_t max_frame_size = 65536, - framing::ProtocolVersion=framing::highestProtocolVersion); - ~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). - */ - void open(const std::string& host, int port = 5672, - const std::string& uid = "guest", - const std::string& pwd = "guest", - const std::string& virtualhost = "/"); - - /** - * Close the connection with optional error information for the peer. - * - * Any further use of this connection (without reopening it) will - * not succeed. - */ - void close(framing::ReplyCode=200, const std::string& msg=OK, - framing::ClassId = 0, framing::MethodId = 0); - - /** - * Associate a Channel with this connection and open it for use. - * - * In AMQP channels are like multi-plexed 'sessions' of work over - * a connection. Almost all the interaction with AMQP is done over - * a channel. - * - * @param connection the connection object to be associated with - * the channel. Call Channel::close() to close the channel. - */ - void openChannel(Channel&); - - - // TODO aconway 2007-01-26: can these be private? - void send(framing::AMQFrame*); - void received(framing::AMQFrame*); - void idleOut(); - void idleIn(); - void shutdown(); - - /**\internal used for testing */ - void setConnector(Connector& connector); - - /** - * @return the maximum frame size in use on this connection - */ - inline uint32_t getMaxFrameSize(){ return max_frame_size; } - - /** @return protocol version in use on this connection. */ - framing::ProtocolVersion getVersion() const { return version; } -}; - -}} // namespace qpid::client - - -#endif diff --git a/qpid/cpp/lib/client/Connector.cpp b/qpid/cpp/lib/client/Connector.cpp deleted file mode 100644 index 7b73cc016a..0000000000 --- a/qpid/cpp/lib/client/Connector.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 -#include -#include -#include "Connector.h" - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::framing; -using qpid::QpidError; - -Connector::Connector( - ProtocolVersion ver, bool _debug, uint32_t buffer_size -) : debug(_debug), - receive_buffer_size(buffer_size), - send_buffer_size(buffer_size), - version(ver), - closed(true), - lastIn(0), lastOut(0), - timeout(0), - idleIn(0), idleOut(0), - timeoutHandler(0), - shutdownHandler(0), - inbuf(receive_buffer_size), - outbuf(send_buffer_size) -{ } - -Connector::~Connector(){ } - -void Connector::connect(const std::string& host, int port){ - socket = Socket::createTcp(); - socket.connect(host, port); - closed = false; - receiver = Thread(this); -} - -void Connector::init(){ - ProtocolInitiation init(version); - writeBlock(&init); -} - -void Connector::close(){ - closed = true; - socket.close(); - receiver.join(); -} - -void Connector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void Connector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -OutputHandler* Connector::getOutputHandler(){ - return this; -} - -void Connector::send(AMQFrame* f){ - std::auto_ptr frame(f); - AMQBody::shared_ptr body = frame->getBody(); - writeBlock(frame.get()); - if(debug) std::cout << "SENT: " << *frame << std::endl; -} - -void Connector::writeBlock(AMQDataBlock* data){ - Mutex::ScopedLock l(writeLock); - data->encode(outbuf); - //transfer data to wire - outbuf.flip(); - writeToSocket(outbuf.start(), outbuf.available()); - outbuf.clear(); -} - -void Connector::writeToSocket(char* data, size_t available){ - size_t written = 0; - while(written < available && !closed){ - ssize_t sent = socket.send(data + written, available-written); - if(sent > 0) { - lastOut = now() * TIME_MSEC; - written += sent; - } - } -} - -void Connector::handleClosed(){ - closed = true; - socket.close(); - if(shutdownHandler) shutdownHandler->shutdown(); -} - -void Connector::checkIdle(ssize_t status){ - if(timeoutHandler){ - Time t = now() * TIME_MSEC; - if(status == Socket::SOCKET_TIMEOUT) { - if(idleIn && (t - lastIn > idleIn)){ - timeoutHandler->idleIn(); - } - } - else if(status == 0 || status == Socket::SOCKET_EOF) { - handleClosed(); - } - else { - lastIn = t; - } - if(idleOut && (t - lastOut > idleOut)){ - timeoutHandler->idleOut(); - } - } -} - -void Connector::setReadTimeout(uint16_t t){ - idleIn = t * 1000;//t is in secs - if(idleIn && (!timeout || idleIn < timeout)){ - timeout = idleIn; - setSocketTimeout(); - } - -} - -void Connector::setWriteTimeout(uint16_t t){ - idleOut = t * 1000;//t is in secs - if(idleOut && (!timeout || idleOut < timeout)){ - timeout = idleOut; - setSocketTimeout(); - } -} - -void Connector::setSocketTimeout(){ - socket.setTimeout(timeout*TIME_MSEC); -} - -void Connector::setTimeoutHandler(TimeoutHandler* handler){ - timeoutHandler = handler; -} - -void Connector::run(){ - try{ - while(!closed){ - ssize_t available = inbuf.available(); - if(available < 1){ - THROW_QPID_ERROR(INTERNAL_ERROR, "Frame exceeds buffer size."); - } - ssize_t received = socket.recv(inbuf.start(), available); - checkIdle(received); - - if(!closed && received > 0){ - inbuf.move(received); - inbuf.flip();//position = 0, limit = total data read - - AMQFrame frame(version); - while(frame.decode(inbuf)){ - if(debug) std::cout << "RECV: " << frame << std::endl; - input->received(&frame); - } - //need to compact buffer to preserve any 'extra' data - inbuf.compact(); - } - } - } catch (const std::exception& e) { - std::cout << e.what() << std::endl; - handleClosed(); - } -} - -}} // namespace qpid::client diff --git a/qpid/cpp/lib/client/Connector.h b/qpid/cpp/lib/client/Connector.h deleted file mode 100644 index 91234d2321..0000000000 --- a/qpid/cpp/lib/client/Connector.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 _Connector_ -#define _Connector_ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { - -namespace client { - -class Connector : public framing::OutputHandler, - private sys::Runnable -{ - const bool debug; - const int receive_buffer_size; - const int send_buffer_size; - framing::ProtocolVersion version; - - bool closed; - - int64_t lastIn; - int64_t lastOut; - int64_t timeout; - uint32_t idleIn; - uint32_t idleOut; - - sys::TimeoutHandler* timeoutHandler; - sys::ShutdownHandler* shutdownHandler; - framing::InputHandler* input; - framing::InitiationHandler* initialiser; - framing::OutputHandler* output; - - framing::Buffer inbuf; - framing::Buffer outbuf; - - sys::Mutex writeLock; - sys::Thread receiver; - - sys::Socket socket; - - void checkIdle(ssize_t status); - void writeBlock(framing::AMQDataBlock* data); - void writeToSocket(char* data, size_t available); - void setSocketTimeout(); - - void run(); - void handleClosed(); - - friend class Channel; - public: - Connector(framing::ProtocolVersion pVersion, - bool debug = false, uint32_t buffer_size = 1024); - virtual ~Connector(); - virtual void connect(const std::string& host, int port); - virtual void init(); - virtual void close(); - virtual void setInputHandler(framing::InputHandler* handler); - virtual void setTimeoutHandler(sys::TimeoutHandler* handler); - virtual void setShutdownHandler(sys::ShutdownHandler* handler); - virtual framing::OutputHandler* getOutputHandler(); - virtual void send(framing::AMQFrame* frame); - virtual void setReadTimeout(uint16_t timeout); - virtual void setWriteTimeout(uint16_t timeout); -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/client/IncomingMessage.cpp b/qpid/cpp/lib/client/IncomingMessage.cpp deleted file mode 100644 index fb9640b61b..0000000000 --- a/qpid/cpp/lib/client/IncomingMessage.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 "IncomingMessage.h" -#include "Exception.h" -#include "ClientMessage.h" -#include - -namespace qpid { -namespace client { - -using boost::format; -using sys::Mutex; - -IncomingMessage::Destination::~Destination() {} - -void IncomingMessage::openReference(const std::string& name) { - Mutex::ScopedLock l(lock); - if (references.find(name) != references.end()) - throw ConnectionException( - 503, format("Attempt to open existing reference %s.") % name); - references[name]; - return; -} - -void IncomingMessage::appendReference( - const std::string& name, const std::string& data) -{ - Mutex::ScopedLock l(lock); - getRefUnlocked(name).data += data; -} - -Message& IncomingMessage::createMessage( - const std::string& destination, const std::string& reference) -{ - Mutex::ScopedLock l(lock); - getDestUnlocked(destination); // Verify destination. - Reference& ref = getRefUnlocked(reference); - ref.messages.resize(ref.messages.size() +1); - ref.messages.back().setDestination(destination); - return ref.messages.back(); -} - -void IncomingMessage::closeReference(const std::string& name) { - Reference refCopy; - { - Mutex::ScopedLock l(lock); - refCopy = getRefUnlocked(name); - references.erase(name); - } - for (std::vector::iterator i = refCopy.messages.begin(); - i != refCopy.messages.end(); - ++i) - { - i->setData(refCopy.data); - // TODO aconway 2007-03-23: Thread safety, - // can a destination be removed while we're doing this? - getDestination(i->getDestination()).message(*i); - } -} - - -void IncomingMessage::addDestination(std::string name, Destination& dest) { - Mutex::ScopedLock l(lock); - DestinationMap::iterator i = destinations.find(name); - if (i == destinations.end()) - destinations[name]=&dest; - else if (i->second != &dest) - throw ConnectionException( - 503, format("Destination already exists: %s.") % name); -} - -void IncomingMessage::removeDestination(std::string name) { - Mutex::ScopedLock l(lock); - DestinationMap::iterator i = destinations.find(name); - if (i == destinations.end()) - throw ConnectionException( - 503, format("No such destination: %s.") % name); - destinations.erase(i); -} - -IncomingMessage::Destination& IncomingMessage::getDestination( - const std::string& name) { - return getDestUnlocked(name); -} - -IncomingMessage::Reference& IncomingMessage::getReference( - const std::string& name) { - return getRefUnlocked(name); -} - -IncomingMessage::Reference& IncomingMessage::getRefUnlocked( - const std::string& name) { - Mutex::ScopedLock l(lock); - ReferenceMap::iterator i = references.find(name); - if (i == references.end()) - throw ConnectionException( - 503, format("No such reference: %s.") % name); - return i->second; -} - -IncomingMessage::Destination& IncomingMessage::getDestUnlocked( - const std::string& name) { - Mutex::ScopedLock l(lock); - DestinationMap::iterator i = destinations.find(name); - if (i == destinations.end()) - throw ConnectionException( - 503, format("No such destination: %s.") % name); - return *i->second; -} - -}} // namespace qpid::client diff --git a/qpid/cpp/lib/client/IncomingMessage.h b/qpid/cpp/lib/client/IncomingMessage.h deleted file mode 100644 index d78a90327d..0000000000 --- a/qpid/cpp/lib/client/IncomingMessage.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef _IncomingMessage_ -#define _IncomingMessage_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "sys/Mutex.h" -#include -#include - - -namespace qpid { -namespace client { - -class Message; - -/** - * Manage incoming messages. - * - * Uses reference and destination concepts from 0-9 Messsage class. - * - * Basic messages use special destination and reference names to indicate - * get-ok, return etc. messages. - * - */ -class IncomingMessage { - public: - /** Accumulate data associated with a set of messages. */ - struct Reference { - std::string data; - std::vector messages; - }; - - /** Interface to a destination for messages. */ - class Destination { - public: - virtual ~Destination(); - - /** Pass a message to the destination */ - virtual void message(const Message&) = 0; - - /** Notify destination of queue-empty contition */ - virtual void empty() = 0; - }; - - - /** Add a reference. Throws if already open. */ - void openReference(const std::string& name); - - /** Get a reference. Throws if not already open. */ - void appendReference(const std::string& name, - const std::string& data); - - /** Create a message to destination associated with reference - *@exception if destination or reference non-existent. - */ - Message& createMessage(const std::string& destination, - const std::string& reference); - - /** Get a reference. - *@exception if non-existent. - */ - Reference& getReference(const std::string& name); - - /** Close a reference and deliver all its messages. - * Throws if not open or a message has an invalid destination. - */ - void closeReference(const std::string& name); - - /** Add a destination. - *@exception if a different Destination is already registered - * under name. - */ - void addDestination(std::string name, Destination&); - - /** Remove a destination. Throws if does not exist */ - void removeDestination(std::string name); - - /** Get a destination. Throws if does not exist */ - Destination& getDestination(const std::string& name); - private: - - typedef std::map ReferenceMap; - typedef std::map DestinationMap; - - Reference& getRefUnlocked(const std::string& name); - Destination& getDestUnlocked(const std::string& name); - - mutable sys::Mutex lock; - ReferenceMap references; - DestinationMap destinations; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/client/Makefile.am b/qpid/cpp/lib/client/Makefile.am deleted file mode 100644 index 6dbe195232..0000000000 --- a/qpid/cpp/lib/client/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -AM_CXXFLAGS = $(WARNING_CFLAGS) -INCLUDES = \ - -I$(top_srcdir)/gen \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/common/sys \ - -I$(top_srcdir)/lib/common/framing \ - $(APR_CXXFLAGS) - -lib_LTLIBRARIES = libqpidclient.la -libqpidclient_la_LIBADD = ../common/libqpidcommon.la -libqpidclient_la_LDFLAGS = -version-info $(LIBTOOL_VERSION_INFO_ARG) -libqpidclient_la_SOURCES = \ - ClientChannel.cpp \ - ClientExchange.cpp \ - ClientQueue.cpp \ - BasicMessageChannel.cpp \ - Connection.cpp \ - Connector.cpp \ - IncomingMessage.cpp \ - MessageListener.cpp \ - ResponseHandler.cpp \ - ReturnedMessageHandler.cpp -pkginclude_HEADERS = \ - AckMode.h \ - ClientChannel.h \ - ClientExchange.h \ - ClientMessage.h \ - ClientQueue.h \ - Connection.h \ - Connector.h \ - IncomingMessage.h \ - MessageChannel.h \ - BasicMessageChannel.h \ - MessageListener.h \ - MethodBodyInstances.h \ - ResponseHandler.h \ - ReturnedMessageHandler.h diff --git a/qpid/cpp/lib/client/MessageChannel.h b/qpid/cpp/lib/client/MessageChannel.h deleted file mode 100644 index 028a19a949..0000000000 --- a/qpid/cpp/lib/client/MessageChannel.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef _client_MessageChannel_h -#define _client_MessageChannel_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 "shared_ptr.h" -#include "sys/Runnable.h" -#include "AckMode.h" - -namespace qpid { - -namespace framing { -class AMQMethodBody; -class AMQHeaderBody; -class AMQContentBody; -class FieldTable; -} - -namespace client { - -class Channel; -class Message; -class Queue; -class Exchange; -class MessageListener; -class ReturnedMessageHandler; - -/** - * Abstract interface for messaging implementation for a channel. - * - *@see Channel for documentation. - */ -class MessageChannel : public sys::Runnable -{ - public: - /**@see Channel::consume */ - virtual void consume( - Queue& queue, std::string& tag, MessageListener* listener, - AckMode ackMode = NO_ACK, bool noLocal = false, bool synch = true, - const framing::FieldTable* fields = 0) = 0; - - /**@see Channel::cancel */ - virtual void cancel(const std::string& tag, bool synch = true) = 0; - - /**@see Channel::get */ - virtual bool get( - Message& msg, const Queue& queue, AckMode ackMode = NO_ACK) = 0; - - /**@see Channel::get */ - virtual void publish(const Message& msg, const Exchange& exchange, - const std::string& routingKey, - bool mandatory = false, bool immediate = false) = 0; - - /**@see Channel::setReturnedMessageHandler */ - virtual void setReturnedMessageHandler( - ReturnedMessageHandler* handler) = 0; - - /** Handle an incoming method. */ - virtual void handle(shared_ptr) = 0; - - /** Handle an incoming header */ - virtual void handle(shared_ptr) = 0; - - /** Handle an incoming content */ - virtual void handle(shared_ptr) = 0; - - /** Send channel's QOS settings */ - virtual void setQos() = 0; - - /** Channel is closing */ - virtual void close() = 0; -}; - -}} // namespace qpid::client - - - -#endif /*!_client_MessageChannel_h*/ diff --git a/qpid/cpp/lib/client/MessageListener.cpp b/qpid/cpp/lib/client/MessageListener.cpp deleted file mode 100644 index 70d44e7040..0000000000 --- a/qpid/cpp/lib/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::~MessageListener() {} diff --git a/qpid/cpp/lib/client/MessageListener.h b/qpid/cpp/lib/client/MessageListener.h deleted file mode 100644 index cfb917b4f8..0000000000 --- a/qpid/cpp/lib/client/MessageListener.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. - * - */ -#include - -#ifndef _MessageListener_ -#define _MessageListener_ - -#include - -namespace qpid { -namespace client { - - /** - * An interface through which asynchronously delivered messages - * can be received by an application. - * - * @see Channel::consume() - * - * \ingroup clientapi - */ - class MessageListener{ - public: - virtual ~MessageListener(); - virtual void received(Message& msg) = 0; - }; - -} -} - - -#endif diff --git a/qpid/cpp/lib/client/MethodBodyInstances.h b/qpid/cpp/lib/client/MethodBodyInstances.h deleted file mode 100644 index acbeeb1158..0000000000 --- a/qpid/cpp/lib/client/MethodBodyInstances.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. - * - */ -#include - -#ifndef _MethodBodyInstances_h_ -#define _MethodBodyInstances_h_ - -namespace qpid { -namespace client { - -/** - * A list of method body instances that can be used to compare against - * incoming bodies. - */ -class MethodBodyInstances -{ -private: - qpid::framing::ProtocolVersion version; -public: - const qpid::framing::BasicCancelOkBody basic_cancel_ok; - const qpid::framing::BasicConsumeOkBody basic_consume_ok; - const qpid::framing::BasicDeliverBody basic_deliver; - const qpid::framing::BasicGetEmptyBody basic_get_empty; - const qpid::framing::BasicGetOkBody basic_get_ok; - const qpid::framing::BasicQosOkBody basic_qos_ok; - const qpid::framing::BasicReturnBody basic_return; - const qpid::framing::ChannelCloseBody channel_close; - const qpid::framing::ChannelCloseOkBody channel_close_ok; - const qpid::framing::ChannelFlowBody channel_flow; - const qpid::framing::ChannelOpenOkBody channel_open_ok; - const qpid::framing::ConnectionCloseBody connection_close; - const qpid::framing::ConnectionCloseOkBody connection_close_ok; - const qpid::framing::ConnectionOpenOkBody connection_open_ok; - const qpid::framing::ConnectionRedirectBody connection_redirect; - const qpid::framing::ConnectionStartBody connection_start; - const qpid::framing::ConnectionTuneBody connection_tune; - const qpid::framing::ExchangeDeclareOkBody exchange_declare_ok; - const qpid::framing::ExchangeDeleteOkBody exchange_delete_ok; - const qpid::framing::QueueDeclareOkBody queue_declare_ok; - const qpid::framing::QueueDeleteOkBody queue_delete_ok; - const qpid::framing::QueueBindOkBody queue_bind_ok; - const qpid::framing::TxCommitOkBody tx_commit_ok; - const qpid::framing::TxRollbackOkBody tx_rollback_ok; - const qpid::framing::TxSelectOkBody tx_select_ok; - - MethodBodyInstances(uint8_t major, uint8_t minor) : - version(major, minor), - basic_cancel_ok(version), - basic_consume_ok(version), - basic_deliver(version), - basic_get_empty(version), - basic_get_ok(version), - basic_qos_ok(version), - basic_return(version), - channel_close(version), - channel_close_ok(version), - channel_flow(version), - channel_open_ok(version), - connection_close(version), - connection_close_ok(version), - connection_open_ok(version), - connection_redirect(version), - connection_start(version), - connection_tune(version), - exchange_declare_ok(version), - exchange_delete_ok(version), - queue_declare_ok(version), - queue_delete_ok(version), - queue_bind_ok(version), - tx_commit_ok(version), - tx_rollback_ok(version), - tx_select_ok(version) - {} - -}; - -static MethodBodyInstances method_bodies(8, 0); - -} // namespace client -} // namespace qpid - -#endif diff --git a/qpid/cpp/lib/client/ResponseHandler.cpp b/qpid/cpp/lib/client/ResponseHandler.cpp deleted file mode 100644 index 926a9ce336..0000000000 --- a/qpid/cpp/lib/client/ResponseHandler.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include -#include -#include "ResponseHandler.h" -#include "AMQMethodBody.h" - -using namespace qpid::sys; -using namespace qpid::framing; - -namespace qpid { -namespace client { - -ResponseHandler::ResponseHandler() : waiting(false), shutdownFlag(false) {} - -ResponseHandler::~ResponseHandler(){} - -bool ResponseHandler::isWaiting() { - Monitor::ScopedLock l(monitor); - return waiting; -} - -void ResponseHandler::expect(){ - Monitor::ScopedLock l(monitor); - waiting = true; -} - -void ResponseHandler::signalResponse(MethodPtr _response) -{ - Monitor::ScopedLock l(monitor); - response = _response; - if (!response) - shutdownFlag=true; - waiting = false; - monitor.notify(); -} - -ResponseHandler::MethodPtr ResponseHandler::receive() { - Monitor::ScopedLock l(monitor); - while (!response && !shutdownFlag) - monitor.wait(); - if (shutdownFlag) - THROW_QPID_ERROR( - PROTOCOL_ERROR, "Channel closed unexpectedly."); - MethodPtr result = response; - response.reset(); - return result; -} - -ResponseHandler::MethodPtr ResponseHandler::receive(ClassId c, MethodId m) { - MethodPtr response = receive(); - if(c != response->amqpClassId() || m != response->amqpMethodId()) { - THROW_QPID_ERROR( - PROTOCOL_ERROR, - boost::format("Expected class:method %d:%d, got %d:%d") - % c % m % response->amqpClassId() % response->amqpMethodId()); - } - return response; -} - -}} // namespace qpid::client diff --git a/qpid/cpp/lib/client/ResponseHandler.h b/qpid/cpp/lib/client/ResponseHandler.h deleted file mode 100644 index 500166144d..0000000000 --- a/qpid/cpp/lib/client/ResponseHandler.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. - * - */ -#include "shared_ptr.h" -#include - -#ifndef _ResponseHandler_ -#define _ResponseHandler_ - -namespace qpid { - -namespace framing { -class AMQMethodBody; -} - -namespace client { - -/** - * Holds a response from the broker peer for the client. - */ -class ResponseHandler{ - typedef shared_ptr MethodPtr; - bool waiting; - bool shutdownFlag; - MethodPtr response; - sys::Monitor monitor; - - public: - ResponseHandler(); - ~ResponseHandler(); - - /** Is a response expected? */ - bool isWaiting(); - - /** Provide a response to the waiting thread */ - void signalResponse(MethodPtr response); - - /** Indicate a message is expected. */ - void expect(); - - /** Wait for a response. */ - MethodPtr receive(); - - /** Wait for a specific response. */ - MethodPtr receive(framing::ClassId, framing::MethodId); - - /** Template version of receive returns typed pointer. */ - template - shared_ptr receive() { - return shared_polymorphic_downcast( - receive(BodyType::CLASS_ID, BodyType::METHOD_ID)); - } -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/client/ReturnedMessageHandler.cpp b/qpid/cpp/lib/client/ReturnedMessageHandler.cpp deleted file mode 100644 index ee9f7462ef..0000000000 --- a/qpid/cpp/lib/client/ReturnedMessageHandler.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::ReturnedMessageHandler::~ReturnedMessageHandler() {} diff --git a/qpid/cpp/lib/client/ReturnedMessageHandler.h b/qpid/cpp/lib/client/ReturnedMessageHandler.h deleted file mode 100644 index 137f0b2e17..0000000000 --- a/qpid/cpp/lib/client/ReturnedMessageHandler.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. - * - */ -#include - -#ifndef _ReturnedMessageHandler_ -#define _ReturnedMessageHandler_ - -#include - -namespace qpid { -namespace client { - - /** - * An interface through which returned messages can be received by - * an application. - * - * @see Channel::setReturnedMessageHandler() - * - * \ingroup clientapi - */ - class ReturnedMessageHandler{ - public: - virtual ~ReturnedMessageHandler(); - virtual void returned(Message& msg) = 0; - }; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/Exception.cpp b/qpid/cpp/lib/common/Exception.cpp deleted file mode 100644 index f7d91498e0..0000000000 --- a/qpid/cpp/lib/common/Exception.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 - -namespace qpid { - -Exception::Exception() throw() {} - -Exception::Exception(const std::string& str) throw() : whatStr(str) {} - -Exception::Exception(const char* str) throw() : whatStr(str) {} - -Exception::~Exception() throw() {} - -const char* Exception::what() const throw() { return whatStr.c_str(); } - -std::string Exception::toString() const throw() { return whatStr; } - -Exception* Exception::clone() const throw() { return new Exception(*this); } - -void Exception::throwSelf() const { throw *this; } - -ShutdownException::ShutdownException() : Exception("Shut down.") {} - -EmptyException::EmptyException() : Exception("Empty.") {} - -} // namespace qpid diff --git a/qpid/cpp/lib/common/Exception.h b/qpid/cpp/lib/common/Exception.h deleted file mode 100644 index b8cd68cf8c..0000000000 --- a/qpid/cpp/lib/common/Exception.h +++ /dev/null @@ -1,97 +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 -#include -#include -#include -#include - -#include "amqp_types.h" - -namespace qpid -{ -/** - * Exception base class for all Qpid exceptions. - */ -class Exception : public std::exception -{ - protected: - std::string whatStr; - - public: - Exception() throw(); - Exception(const std::string& str) throw(); - Exception(const char* str) throw(); - Exception(const std::exception&) throw(); - - /** Allow any type that has ostream operator<< to act as message */ - template - Exception(const T& message) - : whatStr(boost::lexical_cast(message)) {} - - virtual ~Exception() throw(); - - virtual const char* what() const throw(); - virtual std::string toString() const throw(); - - virtual Exception* clone() const throw(); - virtual void throwSelf() const; - - typedef boost::shared_ptr shared_ptr; -}; - -struct ChannelException : public Exception { - framing::ReplyCode code; - template - ChannelException(framing::ReplyCode code_, const T& message) - : Exception(message), code(code_) {} - void throwSelf() const { throw *this; } -}; - -struct ConnectionException : public Exception { - framing::ReplyCode code; - template - ConnectionException(framing::ReplyCode code_, const T& message) - : Exception(message), code(code_) {} - void throwSelf() const { throw *this; } -}; - -/** - * Exception used to indicate that a thread should shut down. - * Does not indicate an error that should be signalled to the user. - */ -struct ShutdownException : public Exception { - ShutdownException(); - void throwSelf() const { throw *this; } -}; - -/** Exception to indicate empty queue or other empty state */ -struct EmptyException : public Exception { - EmptyException(); - void throwSelf() const { throw *this; } -}; - -} - -#endif /*!_Exception_*/ diff --git a/qpid/cpp/lib/common/ExceptionHolder.cpp b/qpid/cpp/lib/common/ExceptionHolder.cpp deleted file mode 100644 index de8d7b2487..0000000000 --- a/qpid/cpp/lib/common/ExceptionHolder.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 "ExceptionHolder.h" - -namespace qpid { - -ExceptionHolder::ExceptionHolder(const std::exception& e) { - const Exception* ex = dynamic_cast(&e); - if (ex) { - reset(ex->clone()); - } else { - reset(new Exception(e.what())); - } -} - -} diff --git a/qpid/cpp/lib/common/ExceptionHolder.h b/qpid/cpp/lib/common/ExceptionHolder.h deleted file mode 100644 index 2769455aba..0000000000 --- a/qpid/cpp/lib/common/ExceptionHolder.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _qpid_ExceptionHolder_h -#define _qpid_ExceptionHolder_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 -#include - -namespace qpid { - -// FIXME aconway 2007-02-20: Not necessary, a simple -// Exception::shared_ptr will do the job. Remove -// -/** - * Holder for a heap-allocated exc eption that can be stack allocated - * and thrown safely. - * - * Basically this is a shared_ptr with the Exception functions added - * so the catcher need not be aware that it is a pointer rather than a - * reference. - * - * shared_ptr is chosen over auto_ptr because it has normal - * copy semantics. - */ -class ExceptionHolder : public Exception, public boost::shared_ptr -{ - public: - typedef boost::shared_ptr shared_ptr; - - ExceptionHolder() throw() {} - ExceptionHolder(Exception* p) throw() : shared_ptr(p) {} - ExceptionHolder(shared_ptr p) throw() : shared_ptr(p) {} - - ExceptionHolder(const Exception& e) throw() : shared_ptr(e.clone()) {} - ExceptionHolder(const std::exception& e); - - ~ExceptionHolder() throw() {} - - const char* what() const throw() { return get()->what(); } - std::string toString() const throw() { return get()->toString(); } - Exception* clone() const throw() { return get()->clone(); } - void throwIf() const { if (get()) get()->throwSelf(); } - void throwSelf() const { assert(get()); get()->throwSelf(); } -}; - -} // namespace qpid - - - -#endif /*!_qpid_ExceptionHolder_h*/ diff --git a/qpid/cpp/lib/common/Makefile.am b/qpid/cpp/lib/common/Makefile.am deleted file mode 100644 index 355f764b6e..0000000000 --- a/qpid/cpp/lib/common/Makefile.am +++ /dev/null @@ -1,143 +0,0 @@ -AM_CXXFLAGS = $(WARNING_CFLAGS) - -INCLUDES = \ - -I$(top_srcdir)/gen \ - -I$(top_srcdir)/lib/common/sys \ - -I$(top_srcdir)/lib/common/framing \ - $(APR_CXXFLAGS) - -apr = sys/apr -apr_src = \ - $(apr)/APRAcceptor.cpp \ - $(apr)/APRBase.cpp \ - $(apr)/APRPool.cpp \ - $(apr)/APRSocket.cpp \ - $(apr)/LFProcessor.cpp \ - $(apr)/LFSessionContext.cpp \ - $(apr)/Socket.cpp \ - $(apr)/Thread.cpp -apr_hdr = \ - $(apr)/APRBase.h \ - $(apr)/APRPool.h \ - $(apr)/APRSocket.h \ - $(apr)/LFProcessor.h \ - $(apr)/LFSessionContext.h - -posix = sys/posix -posix_src = \ - $(posix)/PosixAcceptor.cpp \ - $(posix)/Socket.cpp \ - $(posix)/Thread.cpp \ - $(posix)/check.cpp \ - $(posix)/EventChannel.cpp \ - $(posix)/EventChannelThreads.cpp -posix_hdr = \ - $(posix)/check.h \ - $(posix)/EventChannel.h \ - $(posix)/EventChannelThreads.h - -EXTRA_DIST=$(posix_src) $(posix_hdr) -platform_src = $(apr_src) -platform_hdr = $(apr_hdr) - -framing = framing -gen = $(srcdir)/../../gen - -lib_LTLIBRARIES = libqpidcommon.la -libqpidcommon_la_LIBADD = \ - $(APR_LIBS) \ - $(LIB_DLOPEN) \ - $(LIB_CLOCK_GETTIME) - -libqpidcommon_la_LDFLAGS = \ - -version-info \ - $(LIBTOOL_VERSION_INFO_ARG) - -libqpidcommon_la_SOURCES = \ - $(platform_src) \ - $(framing)/AMQBody.cpp \ - $(framing)/AMQRequestBody.cpp \ - $(framing)/AMQResponseBody.cpp \ - $(framing)/AMQContentBody.cpp \ - $(framing)/AMQFrame.cpp \ - $(framing)/AMQHeaderBody.cpp \ - $(framing)/AMQHeartbeatBody.cpp \ - $(framing)/AMQMethodBody.cpp \ - $(framing)/MethodContext.cpp \ - $(framing)/BasicHeaderProperties.cpp \ - $(framing)/BodyHandler.cpp \ - $(framing)/ChannelAdapter.cpp \ - $(framing)/Buffer.cpp \ - $(framing)/FieldTable.cpp \ - $(framing)/FramingContent.cpp \ - $(framing)/InitiationHandler.cpp \ - $(framing)/ProtocolInitiation.cpp \ - $(framing)/ProtocolVersion.cpp \ - $(framing)/ProtocolVersionException.cpp \ - $(framing)/Requester.cpp \ - $(framing)/Responder.cpp \ - $(framing)/Value.cpp \ - $(framing)/Proxy.cpp \ - $(gen)/AMQP_ClientProxy.cpp \ - $(gen)/AMQP_HighestVersion.h \ - $(gen)/AMQP_MethodVersionMap.cpp \ - $(gen)/AMQP_ServerProxy.cpp \ - Exception.cpp \ - ExceptionHolder.cpp \ - QpidError.cpp \ - sys/Runnable.cpp \ - sys/Time.cpp \ - sys/ProducerConsumer.cpp - -nobase_pkginclude_HEADERS = \ - $(gen)/AMQP_HighestVersion.h \ - $(platform_hdr) \ - $(framing)/AMQBody.h \ - $(framing)/AMQContentBody.h \ - $(framing)/AMQDataBlock.h \ - $(framing)/AMQFrame.h \ - $(framing)/AMQHeaderBody.h \ - $(framing)/AMQHeartbeatBody.h \ - $(framing)/AMQMethodBody.h \ - $(framing)/MethodContext.h \ - $(framing)/BasicHeaderProperties.h \ - $(framing)/BodyHandler.h \ - $(framing)/ChannelAdapter.h \ - $(framing)/Buffer.h \ - $(framing)/FieldTable.h \ - $(framing)/FramingContent.h \ - $(framing)/HeaderProperties.h \ - $(framing)/InitiationHandler.h \ - $(framing)/InputHandler.h \ - $(framing)/OutputHandler.h \ - $(framing)/ProtocolInitiation.h \ - $(framing)/ProtocolVersion.h \ - $(framing)/ProtocolVersionException.h \ - $(framing)/Value.h \ - $(framing)/amqp_framing.h \ - $(framing)/amqp_types.h \ - $(framing)/Proxy.h \ - shared_ptr.h \ - Exception.h \ - ExceptionHolder.h \ - QpidError.h \ - SharedObject.h \ - sys/Acceptor.h \ - sys/AtomicCount.h \ - sys/Module.h \ - sys/Monitor.h \ - sys/Mutex.h \ - sys/Runnable.h \ - sys/ConnectionOutputHandler.h \ - sys/ConnectionInputHandler.h \ - sys/ConnectionInputHandlerFactory.h \ - sys/ShutdownHandler.h \ - sys/Socket.h \ - sys/Thread.h \ - sys/Time.h \ - sys/TimeoutHandler.h \ - sys/ProducerConsumer.h - - -# Force build during dist phase so help2man will work. -dist-hook: $(lib_LTLIBRARIES) diff --git a/qpid/cpp/lib/common/QpidError.cpp b/qpid/cpp/lib/common/QpidError.cpp deleted file mode 100644 index 9cd3051d1e..0000000000 --- a/qpid/cpp/lib/common/QpidError.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 - -#include -#include - -using namespace qpid; - -QpidError::QpidError() : code(0) {} - -QpidError::~QpidError() throw() {} - -Exception* QpidError::clone() const throw() { return new QpidError(*this); } - -void QpidError::throwSelf() const { throw *this; } - -void QpidError::init() { - whatStr = boost::str(boost::format("Error [%d] %s (%s:%d)") - % code % msg % loc.file % loc.line); -} - - diff --git a/qpid/cpp/lib/common/QpidError.h b/qpid/cpp/lib/common/QpidError.h deleted file mode 100644 index 2a0395ab79..0000000000 --- a/qpid/cpp/lib/common/QpidError.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef __QpidError__ -#define __QpidError__ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 { - -struct SrcLine { - public: - SrcLine(const std::string& file_="", int line_=0) : - file(file_), line(line_) {} - - std::string file; - int line; -}; - -class QpidError : public Exception -{ - public: - const int code; - SrcLine loc; - std::string msg; - - QpidError(); - - template - QpidError(int code_, const T& msg_, const SrcLine& loc_) throw() - : code(code_), loc(loc_), msg(boost::lexical_cast(msg_)) - { init(); } - - ~QpidError() throw(); - Exception* clone() const throw(); - void throwSelf() const; - - private: - - void init(); -}; - - -} // namespace qpid - -#define SRCLINE ::qpid::SrcLine(__FILE__, __LINE__) - -#define QPID_ERROR(CODE, MESSAGE) ::qpid::QpidError((CODE), (MESSAGE), SRCLINE) - -#define THROW_QPID_ERROR(CODE, MESSAGE) throw QPID_ERROR(CODE,MESSAGE) - -const int PROTOCOL_ERROR = 10000; -const int APR_ERROR = 20000; -const int FRAMING_ERROR = 30000; -const int CLIENT_ERROR = 40000; -const int INTERNAL_ERROR = 50000; - -#endif diff --git a/qpid/cpp/lib/common/SharedObject.h b/qpid/cpp/lib/common/SharedObject.h deleted file mode 100644 index 852a036ab9..0000000000 --- a/qpid/cpp/lib/common/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/lib/common/doxygen_mainpage.h b/qpid/cpp/lib/common/doxygen_mainpage.h deleted file mode 100644 index b354238cd0..0000000000 --- a/qpid/cpp/lib/common/doxygen_mainpage.h +++ /dev/null @@ -1,45 +0,0 @@ -// This header file is just for doxygen documentation purposes. - -/*!\mainpage Qpid C++ Developer Kit. - * - *\section intro_sec Introduction - * - * The Qpid project provides implementations of the AMQP messaging specification in several programming language. - * - * Qpidc provides APIs and libraries to implement AMQP - * clients in C++. Qpidc clients can interact with any compliant AMQP - * message broker. The Qpid project also provides an AMQP broker - * daemon called qpidd that you can use with your qpidc clients. - * - *\section install_sec Installation - * - * If you are installing from the source distribution -
-   > ./configure && make
-   > make install  
- * This will build and install the client development kit and the broker - * in standard places. Use - * ./configure --help for more options. - * - * You can also install from RPMs with the rpm -i command. - * You will need - * - qpidc for core libraries. - * - qpidc-devel for header files and developer documentation. - * - qpidd for the broker daemon. - * - *\section getstart_sec Getting Started - * - * If you have installed in the standard places you should use - * these compile flags: - * - * -I/usr/include/qpidc -I/usr/include/qpidc/framing -I/usr/include/qpidc/sys - * - * and these link flags: - * - * -lqpidcommon -lqpidclient - * - * If you have installed somewhere else you should modify the flags - * appropriately. - * - * See the \ref clientapi "client API module" for more on the client API. - */ diff --git a/qpid/cpp/lib/common/framing/AMQBody.cpp b/qpid/cpp/lib/common/framing/AMQBody.cpp deleted file mode 100644 index c7c253beda..0000000000 --- a/qpid/cpp/lib/common/framing/AMQBody.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 -#include - -std::ostream& qpid::framing::operator<<(std::ostream& out, const qpid::framing::AMQBody& body) -{ - body.print(out); - return out; -} - -qpid::framing::AMQBody::~AMQBody() {} - - diff --git a/qpid/cpp/lib/common/framing/AMQBody.h b/qpid/cpp/lib/common/framing/AMQBody.h deleted file mode 100644 index 26076956ca..0000000000 --- a/qpid/cpp/lib/common/framing/AMQBody.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. - * - */ -#include -#include -#include - -#ifndef _AMQBody_ -#define _AMQBody_ - -namespace qpid { - namespace framing { - - class AMQBody - { - public: - typedef boost::shared_ptr shared_ptr; - - virtual ~AMQBody(); - virtual uint32_t size() const = 0; - virtual uint8_t type() const = 0; - virtual void encode(Buffer& buffer) const = 0; - virtual void decode(Buffer& buffer, uint32_t size) = 0; - - virtual void print(std::ostream& out) const = 0; - }; - - std::ostream& operator<<(std::ostream& out, const AMQBody& body) ; - - enum BodyTypes { - METHOD_BODY = 1, - HEADER_BODY = 2, - CONTENT_BODY = 3, - HEARTBEAT_BODY = 8, - REQUEST_BODY = 9, - RESPONSE_BODY = 10 - }; - } -} - - -#endif diff --git a/qpid/cpp/lib/common/framing/AMQContentBody.cpp b/qpid/cpp/lib/common/framing/AMQContentBody.cpp deleted file mode 100644 index 573c17dade..0000000000 --- a/qpid/cpp/lib/common/framing/AMQContentBody.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 -#include - -qpid::framing::AMQContentBody::AMQContentBody(){ -} - -qpid::framing::AMQContentBody::AMQContentBody(const string& _data) : data(_data){ -} - -uint32_t qpid::framing::AMQContentBody::size() 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 (" << size() << " bytes)"; -} diff --git a/qpid/cpp/lib/common/framing/AMQContentBody.h b/qpid/cpp/lib/common/framing/AMQContentBody.h deleted file mode 100644 index c9fa7cde5c..0000000000 --- a/qpid/cpp/lib/common/framing/AMQContentBody.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. - * - */ -#include -#include -#include - -#ifndef _AMQContentBody_ -#define _AMQContentBody_ - -namespace qpid { -namespace framing { - -class AMQContentBody : public AMQBody -{ - string data; - -public: - typedef boost::shared_ptr shared_ptr; - - AMQContentBody(); - AMQContentBody(const string& data); - inline virtual ~AMQContentBody(){} - inline uint8_t type() const { return CONTENT_BODY; }; - inline string& getData(){ return data; } - uint32_t size() const; - void encode(Buffer& buffer) const; - void decode(Buffer& buffer, uint32_t size); - void print(std::ostream& out) const; -}; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/framing/AMQDataBlock.h b/qpid/cpp/lib/common/framing/AMQDataBlock.h deleted file mode 100644 index 2a6f843f1e..0000000000 --- a/qpid/cpp/lib/common/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 - -#ifndef _AMQDataBlock_ -#define _AMQDataBlock_ - -namespace qpid { -namespace framing { - -class AMQDataBlock -{ -public: - virtual ~AMQDataBlock() {} - virtual void encode(Buffer& buffer) = 0; - virtual bool decode(Buffer& buffer) = 0; - virtual uint32_t size() const = 0; -}; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/framing/AMQFrame.cpp b/qpid/cpp/lib/common/framing/AMQFrame.cpp deleted file mode 100644 index bc9061b169..0000000000 --- a/qpid/cpp/lib/common/framing/AMQFrame.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. - * - */ -#include - -#include -#include -#include "AMQRequestBody.h" -#include "AMQResponseBody.h" - - -namespace qpid { -namespace framing { - - -AMQP_MethodVersionMap AMQFrame::versionMap; - -AMQFrame::AMQFrame(ProtocolVersion _version): -version(_version) - { - assert(version != ProtocolVersion(0,0)); - } - -AMQFrame::AMQFrame(ProtocolVersion _version, uint16_t _channel, AMQBody* _body) : -version(_version), channel(_channel), body(_body) -{} - -AMQFrame::AMQFrame(ProtocolVersion _version, uint16_t _channel, const AMQBody::shared_ptr& _body) : -version(_version), channel(_channel), body(_body) -{} - -AMQFrame::~AMQFrame() {} - -uint16_t AMQFrame::getChannel(){ - return channel; -} - -AMQBody::shared_ptr AMQFrame::getBody(){ - return body; -} - -void AMQFrame::encode(Buffer& buffer) -{ - buffer.putOctet(body->type()); - buffer.putShort(channel); - buffer.putLong(body->size()); - body->encode(buffer); - buffer.putOctet(0xCE); -} - -uint32_t AMQFrame::size() const{ - assert(body.get()); - return 1/*type*/ + 2/*channel*/ + 4/*body size*/ + body->size() - + 1/*0xCE*/; -} - -bool AMQFrame::decode(Buffer& buffer) -{ - if(buffer.available() < 7) - return false; - buffer.record(); - uint32_t frameSize = decodeHead(buffer); - if(buffer.available() < frameSize + 1){ - buffer.restore(); - return false; - } - decodeBody(buffer, frameSize); - uint8_t end = buffer.getOctet(); - if(end != 0xCE) THROW_QPID_ERROR(FRAMING_ERROR, "Frame end not found"); - return true; -} - -uint32_t AMQFrame::decodeHead(Buffer& buffer){ - type = buffer.getOctet(); - channel = buffer.getShort(); - return buffer.getLong(); -} - -void AMQFrame::decodeBody(Buffer& buffer, uint32_t size) -{ - switch(type) - { - case METHOD_BODY: - body = AMQMethodBody::create(versionMap, version, buffer); - break; - case REQUEST_BODY: - body = AMQRequestBody::create(versionMap, version, buffer); - break; - case RESPONSE_BODY: - body = AMQResponseBody::create(versionMap, version, buffer); - break; - case HEADER_BODY: - body = AMQBody::shared_ptr(new AMQHeaderBody()); - break; - case CONTENT_BODY: - body = AMQBody::shared_ptr(new AMQContentBody()); - break; - case HEARTBEAT_BODY: - body = AMQBody::shared_ptr(new AMQHeartbeatBody()); - break; - default: - THROW_QPID_ERROR( - FRAMING_ERROR, - boost::format("Unknown frame type %d") % type); - } - body->decode(buffer, size); -} - -std::ostream& operator<<(std::ostream& out, const AMQFrame& t) -{ - out << "Frame[channel=" << t.channel << "; "; - if (t.body.get() == 0) - out << "empty"; - else - out << *t.body; - out << "]"; - return out; -} - - -}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/AMQFrame.h b/qpid/cpp/lib/common/framing/AMQFrame.h deleted file mode 100644 index 0c18e0c2a5..0000000000 --- a/qpid/cpp/lib/common/framing/AMQFrame.h +++ /dev/null @@ -1,78 +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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace framing { - - -class AMQFrame : public AMQDataBlock -{ - public: - AMQFrame(ProtocolVersion _version = highestProtocolVersion); - AMQFrame(ProtocolVersion _version, uint16_t channel, AMQBody* body); - AMQFrame(ProtocolVersion _version, uint16_t channel, const AMQBody::shared_ptr& body); - virtual ~AMQFrame(); - virtual void encode(Buffer& buffer); - virtual bool decode(Buffer& buffer); - virtual uint32_t size() const; - uint16_t getChannel(); - AMQBody::shared_ptr getBody(); - - /** Convenience template to cast the body to an expected type */ - template boost::shared_ptr castBody() { - assert(dynamic_cast(getBody().get())); - boost::static_pointer_cast(getBody()); - } - - uint32_t decodeHead(Buffer& buffer); - void decodeBody(Buffer& buffer, uint32_t size); - - private: - static AMQP_MethodVersionMap versionMap; - ProtocolVersion version; - - uint16_t channel; - uint8_t type; - AMQBody::shared_ptr body; - - - friend std::ostream& operator<<(std::ostream& out, const AMQFrame& body); -}; - -}} // namespace qpid::framing - - -#endif diff --git a/qpid/cpp/lib/common/framing/AMQHeaderBody.cpp b/qpid/cpp/lib/common/framing/AMQHeaderBody.cpp deleted file mode 100644 index 3ddae4eebf..0000000000 --- a/qpid/cpp/lib/common/framing/AMQHeaderBody.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 -#include -#include - -qpid::framing::AMQHeaderBody::AMQHeaderBody(int classId) : weight(0), contentSize(0){ - createProperties(classId); -} - -qpid::framing::AMQHeaderBody::AMQHeaderBody() : properties(0), weight(0), contentSize(0){ -} - -qpid::framing::AMQHeaderBody::~AMQHeaderBody(){ - delete properties; -} - -uint32_t qpid::framing::AMQHeaderBody::size() const{ - return 12 + properties->size(); -} - -void qpid::framing::AMQHeaderBody::encode(Buffer& buffer) const { - buffer.putShort(properties->classId()); - buffer.putShort(weight); - buffer.putLongLong(contentSize); - properties->encode(buffer); -} - -void qpid::framing::AMQHeaderBody::decode(Buffer& buffer, uint32_t bufSize){ - uint16_t classId = buffer.getShort(); - weight = buffer.getShort(); - contentSize = buffer.getLongLong(); - createProperties(classId); - properties->decode(buffer, bufSize - 12); -} - -void qpid::framing::AMQHeaderBody::createProperties(int classId){ - switch(classId){ - case BASIC: - properties = new qpid::framing::BasicHeaderProperties(); - break; - default: - THROW_QPID_ERROR(FRAMING_ERROR, "Unknown header class"); - } -} - -void qpid::framing::AMQHeaderBody::print(std::ostream& out) const -{ - out << "header (" << size() << " bytes)" << " content_size=" << getContentSize(); - const BasicHeaderProperties* props = - dynamic_cast(getProperties()); - if (props) { - out << ", message_id=" << props->getMessageId(); - out << ", delivery_mode=" << (int) props->getDeliveryMode(); - out << ", headers=" << const_cast(props)->getHeaders(); - } -} diff --git a/qpid/cpp/lib/common/framing/AMQHeaderBody.h b/qpid/cpp/lib/common/framing/AMQHeaderBody.h deleted file mode 100644 index d57f93aacd..0000000000 --- a/qpid/cpp/lib/common/framing/AMQHeaderBody.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 -#include -#include -#include - -#ifndef _AMQHeaderBody_ -#define _AMQHeaderBody_ - -namespace qpid { -namespace framing { - -class AMQHeaderBody : public AMQBody -{ - HeaderProperties* properties; - uint16_t weight; - uint64_t contentSize; - - void createProperties(int classId); -public: - typedef boost::shared_ptr shared_ptr; - - AMQHeaderBody(int classId); - AMQHeaderBody(); - inline uint8_t type() const { return HEADER_BODY; } - HeaderProperties* getProperties(){ return properties; } - const HeaderProperties* getProperties() const { return properties; } - inline uint64_t getContentSize() const { return contentSize; } - inline void setContentSize(uint64_t _size) { contentSize = _size; } - virtual ~AMQHeaderBody(); - virtual uint32_t size() const; - virtual void encode(Buffer& buffer) const; - virtual void decode(Buffer& buffer, uint32_t size); - virtual void print(std::ostream& out) const; -}; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/framing/AMQHeartbeatBody.cpp b/qpid/cpp/lib/common/framing/AMQHeartbeatBody.cpp deleted file mode 100644 index 63f83a3d29..0000000000 --- a/qpid/cpp/lib/common/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 -#include - -qpid::framing::AMQHeartbeatBody::~AMQHeartbeatBody() {} - -void qpid::framing::AMQHeartbeatBody::print(std::ostream& out) const { - out << "heartbeat"; -} diff --git a/qpid/cpp/lib/common/framing/AMQHeartbeatBody.h b/qpid/cpp/lib/common/framing/AMQHeartbeatBody.h deleted file mode 100644 index a3e9d823f1..0000000000 --- a/qpid/cpp/lib/common/framing/AMQHeartbeatBody.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. - * - */ -#include -#include -#include - -#ifndef _AMQHeartbeatBody_ -#define _AMQHeartbeatBody_ - -namespace qpid { -namespace framing { - -class AMQHeartbeatBody : public AMQBody -{ -public: - typedef boost::shared_ptr shared_ptr; - - virtual ~AMQHeartbeatBody(); - inline uint32_t size() const { return 0; } - inline uint8_t type() const { return HEARTBEAT_BODY; } - inline void encode(Buffer& ) const {} - inline void decode(Buffer& , uint32_t /*size*/) {} - virtual void print(std::ostream& out) const; -}; - -} -} - -#endif diff --git a/qpid/cpp/lib/common/framing/AMQMethodBody.cpp b/qpid/cpp/lib/common/framing/AMQMethodBody.cpp deleted file mode 100644 index 23502068f5..0000000000 --- a/qpid/cpp/lib/common/framing/AMQMethodBody.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 -#include -#include "AMQP_MethodVersionMap.h" - -namespace qpid { -namespace framing { - -void AMQMethodBody::encodeId(Buffer& buffer) const{ - buffer.putShort(amqpClassId()); - buffer.putShort(amqpMethodId()); -} - -void AMQMethodBody::invoke(AMQP_ServerOperations&, const MethodContext&){ - assert(0); - THROW_QPID_ERROR(PROTOCOL_ERROR, "Method not supported by AMQP Server."); -} - -AMQMethodBody::shared_ptr AMQMethodBody::create( - AMQP_MethodVersionMap& versionMap, ProtocolVersion version, - Buffer& buffer) -{ - ClassMethodId id; - id.decode(buffer); - return AMQMethodBody::shared_ptr( - versionMap.createMethodBody( - id.classId, id.methodId, version.getMajor(), version.getMinor())); -} - -void AMQMethodBody::ClassMethodId::decode(Buffer& buffer) { - classId = buffer.getShort(); - methodId = buffer.getShort(); -} - -void AMQMethodBody::decode(Buffer& buffer, uint32_t /*size*/) { - decodeContent(buffer); -} - -}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/AMQMethodBody.h b/qpid/cpp/lib/common/framing/AMQMethodBody.h deleted file mode 100644 index c2b00c2169..0000000000 --- a/qpid/cpp/lib/common/framing/AMQMethodBody.h +++ /dev/null @@ -1,84 +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 -#include -#include -#include -#include -#include - -namespace qpid { -namespace framing { - -class AMQP_MethodVersionMap; - -class AMQMethodBody : public AMQBody -{ - public: - typedef boost::shared_ptr shared_ptr; - - static shared_ptr create( - AMQP_MethodVersionMap& map, ProtocolVersion version, Buffer& buf); - - ProtocolVersion version; - uint8_t type() const { return METHOD_BODY; } - AMQMethodBody(uint8_t major, uint8_t minor) : version(major, minor) {} - AMQMethodBody(ProtocolVersion ver) : version(ver) {} - virtual ~AMQMethodBody() {} - void decode(Buffer&, uint32_t); - - virtual MethodId amqpMethodId() const = 0; - virtual ClassId amqpClassId() const = 0; - - virtual void invoke(AMQP_ServerOperations&, const MethodContext&); - - template bool isA() { - return amqpClassId()==T::CLASS_ID && amqpMethodId()==T::METHOD_ID; - } - - /** Return request ID or response correlationID */ - virtual RequestId getRequestId() const { return 0; } - - virtual bool isRequest() const { return false; } - virtual bool isResponse() const { return false; } - - protected: - static uint32_t baseSize() { return 4; } - - struct ClassMethodId { - uint16_t classId; - uint16_t methodId; - void decode(Buffer& b); - }; - - void encodeId(Buffer& buffer) const; - virtual void encodeContent(Buffer& buffer) const = 0; - virtual void decodeContent(Buffer& buffer) = 0; -}; - - -}} // namespace qpid::framing - - -#endif diff --git a/qpid/cpp/lib/common/framing/AMQRequestBody.cpp b/qpid/cpp/lib/common/framing/AMQRequestBody.cpp deleted file mode 100644 index 54e1c11863..0000000000 --- a/qpid/cpp/lib/common/framing/AMQRequestBody.cpp +++ /dev/null @@ -1,66 +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 "AMQRequestBody.h" -#include "AMQP_MethodVersionMap.h" - -namespace qpid { -namespace framing { - -void AMQRequestBody::Data::encode(Buffer& buffer) const { - buffer.putLongLong(requestId); - buffer.putLongLong(responseMark); - buffer.putLong(0); // Reserved long in spec. -} - -void AMQRequestBody::Data::decode(Buffer& buffer) { - requestId = buffer.getLongLong(); - responseMark = buffer.getLongLong(); - buffer.getLong(); // Ignore reserved long. -} - -void AMQRequestBody::encode(Buffer& buffer) const { - data.encode(buffer); - encodeId(buffer); - encodeContent(buffer); -} - -AMQRequestBody::shared_ptr -AMQRequestBody::create( - AMQP_MethodVersionMap& versionMap, ProtocolVersion version, - Buffer& buffer) -{ - ClassMethodId id; - Data data; - data.decode(buffer); - id.decode(buffer); - AMQRequestBody* body = dynamic_cast( - versionMap.createMethodBody( - id.classId, id.methodId, version.getMajor(), version.getMinor())); - assert(body); - body->data = data; - return AMQRequestBody::shared_ptr(body); -} - -void AMQRequestBody::printPrefix(std::ostream& out) const { - out << "request(id=" << data.requestId << ",mark=" - << data.responseMark << "): "; -} - -}} // namespace qpid::framing - diff --git a/qpid/cpp/lib/common/framing/AMQRequestBody.h b/qpid/cpp/lib/common/framing/AMQRequestBody.h deleted file mode 100644 index f21659a57a..0000000000 --- a/qpid/cpp/lib/common/framing/AMQRequestBody.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _framing_AMQRequestBody_h -#define _framing_AMQRequestBody_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 "AMQMethodBody.h" - -namespace qpid { -namespace framing { - -/** - * Body of a request method frame. - */ -class AMQRequestBody : public AMQMethodBody -{ - public: - typedef boost::shared_ptr shared_ptr; - - struct Data { - Data(RequestId id=0, ResponseId mark=0) - : requestId(id), responseMark(mark) {} - void encode(Buffer&) const; - void decode(Buffer&); - - RequestId requestId; - ResponseId responseMark; - }; - - static Data& getData(const AMQBody::shared_ptr& body) { - return boost::dynamic_pointer_cast(body)->getData(); - } - - static shared_ptr create( - AMQP_MethodVersionMap& versionMap, ProtocolVersion version, - Buffer& buffer); - - AMQRequestBody(ProtocolVersion v, RequestId id=0, ResponseId mark=0) - : AMQMethodBody(v), data(id, mark) {} - - uint8_t type() const { return REQUEST_BODY; } - void encode(Buffer& buffer) const; - - Data& getData() { return data; } - RequestId getRequestId() const { return data.requestId; } - ResponseId getResponseMark() const { return data.responseMark; } - void setRequestId(RequestId id) { data.requestId=id; } - void setResponseMark(ResponseId mark) { data.responseMark=mark; } - - bool isRequest()const { return true; } - static const uint32_t baseSize() { return AMQMethodBody::baseSize()+20; } - protected: - void printPrefix(std::ostream& out) const; - - private: - Data data; -}; - -}} // namespace qpid::framing - - - -#endif /*!_framing_AMQRequestBody_h*/ diff --git a/qpid/cpp/lib/common/framing/AMQResponseBody.cpp b/qpid/cpp/lib/common/framing/AMQResponseBody.cpp deleted file mode 100644 index 7da71a5d25..0000000000 --- a/qpid/cpp/lib/common/framing/AMQResponseBody.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 "AMQFrame.h" -#include "AMQResponseBody.h" -#include "AMQP_MethodVersionMap.h" - -namespace qpid { -namespace framing { - -void AMQResponseBody::Data::encode(Buffer& buffer) const { - buffer.putLongLong(responseId); - buffer.putLongLong(requestId); - buffer.putLong(batchOffset); -} - -void AMQResponseBody::Data::decode(Buffer& buffer) { - responseId = buffer.getLongLong(); - requestId = buffer.getLongLong(); - batchOffset = buffer.getLong(); -} - -void AMQResponseBody::encode(Buffer& buffer) const { - data.encode(buffer); - encodeId(buffer); - encodeContent(buffer); -} - -AMQResponseBody::shared_ptr AMQResponseBody::create( - AMQP_MethodVersionMap& versionMap, ProtocolVersion version, - Buffer& buffer) -{ - ClassMethodId id; - Data data; - data.decode(buffer); - id.decode(buffer); - AMQResponseBody* body = dynamic_cast( - versionMap.createMethodBody( - id.classId, id.methodId, version.getMajor(), version.getMinor())); - assert(body); - body->data = data; - return AMQResponseBody::shared_ptr(body); -} - -void AMQResponseBody::printPrefix(std::ostream& out) const { - out << "response(id=" << data.responseId << ",request=" << data.requestId - << ",batch=" << data.batchOffset << "): "; -} - -}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/AMQResponseBody.h b/qpid/cpp/lib/common/framing/AMQResponseBody.h deleted file mode 100644 index fa381baddd..0000000000 --- a/qpid/cpp/lib/common/framing/AMQResponseBody.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef _framing_AMQResponseBody_h -#define _framing_AMQResponseBody_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 "AMQMethodBody.h" - -namespace qpid { -namespace framing { - -class AMQP_MethodVersionMap; - -/** - * Body of a response method frame. - */ -class AMQResponseBody : public AMQMethodBody -{ - - public: - typedef boost::shared_ptr shared_ptr; - - struct Data { - Data(ResponseId id=0, RequestId req=0, BatchOffset off=0) - : responseId(id), requestId(req), batchOffset(off) {} - void encode(Buffer&) const; - void decode(Buffer&); - - uint64_t responseId; - uint64_t requestId; - uint32_t batchOffset; - }; - - static Data& getData(const AMQBody::shared_ptr& body) { - return boost::dynamic_pointer_cast(body)->getData(); - } - - static shared_ptr create( - AMQP_MethodVersionMap& versionMap, ProtocolVersion version, - Buffer& buffer); - - AMQResponseBody( - ProtocolVersion v, ResponseId id=0, RequestId req=0, BatchOffset off=0) - : AMQMethodBody(v), data(id, req, off) {} - - uint8_t type() const { return RESPONSE_BODY; } - void encode(Buffer& buffer) const; - - Data& getData() { return data; } - ResponseId getResponseId() const { return data.responseId; } - RequestId getRequestId() const { return data.requestId; } - BatchOffset getBatchOffset() const { return data.batchOffset; } - void setResponseId(ResponseId id) { data.responseId = id; } - void setRequestId(RequestId id) { data.requestId = id; } - void setBatchOffset(BatchOffset id) { data.batchOffset = id; } - - bool isResponse() const { return true; } - protected: - static const uint32_t baseSize() { return AMQMethodBody::baseSize()+20; } - void printPrefix(std::ostream& out) const; - - private: - Data data; -}; - -}} // namespace qpid::framing - - - -#endif /*!_framing_AMQResponseBody_h*/ diff --git a/qpid/cpp/lib/common/framing/BasicHeaderProperties.cpp b/qpid/cpp/lib/common/framing/BasicHeaderProperties.cpp deleted file mode 100644 index d815d1e62f..0000000000 --- a/qpid/cpp/lib/common/framing/BasicHeaderProperties.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 - -//TODO: This could be easily generated from the spec - -qpid::framing::BasicHeaderProperties::BasicHeaderProperties() : deliveryMode(DeliveryMode(0)), priority(0), timestamp(0){} -qpid::framing::BasicHeaderProperties::~BasicHeaderProperties(){} - -uint32_t qpid::framing::BasicHeaderProperties::size() const{ - uint32_t bytes = 2;//flags - if(contentType.length() > 0) bytes += contentType.length() + 1; - if(contentEncoding.length() > 0) bytes += contentEncoding.length() + 1; - if(headers.count() > 0) bytes += headers.size(); - if(deliveryMode != 0) bytes += 1; - if(priority != 0) bytes += 1; - if(correlationId.length() > 0) bytes += correlationId.length() + 1; - if(replyTo.length() > 0) bytes += replyTo.length() + 1; - if(expiration.length() > 0) bytes += expiration.length() + 1; - if(messageId.length() > 0) bytes += messageId.length() + 1; - if(timestamp != 0) bytes += 8; - if(type.length() > 0) bytes += type.length() + 1; - if(userId.length() > 0) bytes += userId.length() + 1; - if(appId.length() > 0) bytes += appId.length() + 1; - if(clusterId.length() > 0) bytes += clusterId.length() + 1; - - return bytes; -} - -void qpid::framing::BasicHeaderProperties::encode(qpid::framing::Buffer& buffer) const{ - uint16_t flags = getFlags(); - buffer.putShort(flags); - - if(contentType.length() > 0) buffer.putShortString(contentType); - if(contentEncoding.length() > 0) buffer.putShortString(contentEncoding); - if(headers.count() > 0) buffer.putFieldTable(headers); - if(deliveryMode != 0) buffer.putOctet(deliveryMode); - if(priority != 0) buffer.putOctet(priority); - if(correlationId.length() > 0) buffer.putShortString(correlationId); - if(replyTo.length() > 0) buffer.putShortString(replyTo); - if(expiration.length() > 0) buffer.putShortString(expiration); - if(messageId.length() > 0) buffer.putShortString(messageId); - if(timestamp != 0) buffer.putLongLong(timestamp);; - if(type.length() > 0) buffer.putShortString(type); - if(userId.length() > 0) buffer.putShortString(userId); - if(appId.length() > 0) buffer.putShortString(appId); - if(clusterId.length() > 0) buffer.putShortString(clusterId); -} - -void qpid::framing::BasicHeaderProperties::decode(qpid::framing::Buffer& buffer, uint32_t /*size*/){ - uint16_t flags = buffer.getShort(); - if(flags & (1 << 15)) buffer.getShortString(contentType); - if(flags & (1 << 14)) buffer.getShortString(contentEncoding); - if(flags & (1 << 13)) buffer.getFieldTable(headers); - if(flags & (1 << 12)) deliveryMode = DeliveryMode(buffer.getOctet()); - if(flags & (1 << 11)) priority = buffer.getOctet(); - if(flags & (1 << 10)) buffer.getShortString(correlationId); - if(flags & (1 << 9)) buffer.getShortString(replyTo); - if(flags & (1 << 8)) buffer.getShortString(expiration); - if(flags & (1 << 7)) buffer.getShortString(messageId); - if(flags & (1 << 6)) timestamp = buffer.getLongLong(); - if(flags & (1 << 5)) buffer.getShortString(type); - if(flags & (1 << 4)) buffer.getShortString(userId); - if(flags & (1 << 3)) buffer.getShortString(appId); - if(flags & (1 << 2)) buffer.getShortString(clusterId); -} - -uint16_t qpid::framing::BasicHeaderProperties::getFlags() const{ - uint16_t flags(0); - if(contentType.length() > 0) flags |= (1 << 15); - if(contentEncoding.length() > 0) flags |= (1 << 14); - if(headers.count() > 0) flags |= (1 << 13); - if(deliveryMode != 0) flags |= (1 << 12); - if(priority != 0) flags |= (1 << 11); - if(correlationId.length() > 0) flags |= (1 << 10); - if(replyTo.length() > 0) flags |= (1 << 9); - if(expiration.length() > 0) flags |= (1 << 8); - if(messageId.length() > 0) flags |= (1 << 7); - if(timestamp != 0) flags |= (1 << 6); - if(type.length() > 0) flags |= (1 << 5); - if(userId.length() > 0) flags |= (1 << 4); - if(appId.length() > 0) flags |= (1 << 3); - if(clusterId.length() > 0) flags |= (1 << 2); - return flags; -} diff --git a/qpid/cpp/lib/common/framing/BasicHeaderProperties.h b/qpid/cpp/lib/common/framing/BasicHeaderProperties.h deleted file mode 100644 index 248014aefb..0000000000 --- a/qpid/cpp/lib/common/framing/BasicHeaderProperties.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. - * - */ -#include -#include -#include -#include - -#ifndef _BasicHeaderProperties_ -#define _BasicHeaderProperties_ - -namespace qpid { -namespace framing { - -enum DeliveryMode { TRANSIENT = 1, PERSISTENT = 2}; - -class BasicHeaderProperties : public HeaderProperties -{ - string contentType; - string contentEncoding; - FieldTable headers; - DeliveryMode deliveryMode; - uint8_t priority; - string correlationId; - string replyTo; - string expiration; - string messageId; - uint64_t timestamp; - string type; - string userId; - string appId; - string clusterId; - - uint16_t getFlags() const; - - public: - BasicHeaderProperties(); - virtual ~BasicHeaderProperties(); - virtual uint32_t size() const; - virtual void encode(Buffer& buffer) const; - virtual void decode(Buffer& buffer, uint32_t size); - - virtual uint8_t classId() { return BASIC; } - - string getContentType() const { return contentType; } - string getContentEncoding() const { return contentEncoding; } - FieldTable& getHeaders() { return headers; } - const FieldTable& getHeaders() const { return headers; } - DeliveryMode getDeliveryMode() const { return deliveryMode; } - uint8_t getPriority() const { return priority; } - string getCorrelationId() const {return correlationId; } - string getReplyTo() const { return replyTo; } - string getExpiration() const { return expiration; } - string getMessageId() const {return messageId; } - uint64_t getTimestamp() const { return timestamp; } - string getType() const { return type; } - string getUserId() const { return userId; } - string getAppId() const { return appId; } - string getClusterId() const { return clusterId; } - - void setContentType(const string& _type){ contentType = _type; } - void setContentEncoding(const string& encoding){ contentEncoding = encoding; } - void setHeaders(const FieldTable& _headers){ headers = _headers; } - void setDeliveryMode(DeliveryMode mode){ deliveryMode = mode; } - void setPriority(uint8_t _priority){ priority = _priority; } - void setCorrelationId(const string& _correlationId){ correlationId = _correlationId; } - void setReplyTo(const string& _replyTo){ replyTo = _replyTo;} - void setExpiration(const string& _expiration){ expiration = _expiration; } - void setMessageId(const string& _messageId){ messageId = _messageId; } - void setTimestamp(uint64_t _timestamp){ timestamp = _timestamp; } - void setType(const string& _type){ type = _type; } - void setUserId(const string& _userId){ userId = _userId; } - void setAppId(const string& _appId){appId = _appId; } - void setClusterId(const string& _clusterId){ clusterId = _clusterId; } - - /** \internal - * Template to copy between types like BasicHeaderProperties. - */ - template - static void copy(T& to, const U& from) { - to.setContentType(from.getContentType()); - to.setContentEncoding(from.getContentEncoding()); - to.setHeaders(from.getHeaders()); - to.setDeliveryMode(from.getDeliveryMode()); - to.setPriority(from.getPriority()); - to.setCorrelationId(from.getCorrelationId()); - to.setReplyTo(from.getReplyTo()); - to.setExpiration(from.getExpiration()); - to.setMessageId(from.getMessageId()); - to.setTimestamp(from.getTimestamp()); - to.setType(from.getType()); - to.setUserId(from.getUserId()); - to.setAppId(from.getAppId()); - to.setClusterId(from.getClusterId()); - } -}; -}} -#endif diff --git a/qpid/cpp/lib/common/framing/BodyHandler.cpp b/qpid/cpp/lib/common/framing/BodyHandler.cpp deleted file mode 100644 index 5dd0c0c23d..0000000000 --- a/qpid/cpp/lib/common/framing/BodyHandler.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 "QpidError.h" -#include "BodyHandler.h" -#include -#include -#include -#include -#include -#include - -using namespace qpid::framing; -using namespace boost; - -BodyHandler::~BodyHandler() {} - -void BodyHandler::handleBody(shared_ptr body) { - switch(body->type()) - { - case REQUEST_BODY: - handleRequest(shared_polymorphic_cast(body)); - break; - case RESPONSE_BODY: - handleResponse(shared_polymorphic_cast(body)); - break; - case METHOD_BODY: - handleMethod(shared_polymorphic_cast(body)); - break; - case HEADER_BODY: - handleHeader(shared_polymorphic_cast(body)); - break; - case CONTENT_BODY: - handleContent(shared_polymorphic_cast(body)); - break; - case HEARTBEAT_BODY: - handleHeartbeat(shared_polymorphic_cast(body)); - break; - default: - QPID_ERROR(PROTOCOL_ERROR, "Unknown frame type "+body->type()); - } -} - diff --git a/qpid/cpp/lib/common/framing/BodyHandler.h b/qpid/cpp/lib/common/framing/BodyHandler.h deleted file mode 100644 index cb3f0997b0..0000000000 --- a/qpid/cpp/lib/common/framing/BodyHandler.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _BodyHandler_ -#define _BodyHandler_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "Requester.h" -#include "Responder.h" - -namespace qpid { -namespace framing { - -class AMQRequestBody; -class AMQResponseBody; -class AMQMethodBody; -class AMQHeaderBody; -class AMQContentBody; -class AMQHeartbeatBody; - -/** - * Interface to handle incoming frame bodies. - * Derived classes provide logic for each frame type. - */ -class BodyHandler { - public: - virtual ~BodyHandler(); - virtual void handleBody(boost::shared_ptr body); - - protected: - virtual void handleRequest(boost::shared_ptr) = 0; - virtual void handleResponse(boost::shared_ptr) = 0; - virtual void handleMethod(boost::shared_ptr) = 0; - virtual void handleHeader(boost::shared_ptr) = 0; - virtual void handleContent(boost::shared_ptr) = 0; - virtual void handleHeartbeat(boost::shared_ptr) = 0; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/common/framing/Buffer.cpp b/qpid/cpp/lib/common/framing/Buffer.cpp deleted file mode 100644 index 52c9a42d55..0000000000 --- a/qpid/cpp/lib/common/framing/Buffer.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 -#include -#include - -qpid::framing::Buffer::Buffer(uint32_t _size) : size(_size), owner(true), position(0), limit(_size){ - data = new char[size]; -} - -qpid::framing::Buffer::Buffer(char* _data, uint32_t _size) : size(_size), owner(false), data(_data), position(0), limit(_size){ -} - -qpid::framing::Buffer::~Buffer(){ - if(owner) delete[] data; -} - -void qpid::framing::Buffer::flip(){ - limit = position; - position = 0; -} - -void qpid::framing::Buffer::clear(){ - limit = size; - position = 0; -} - -void qpid::framing::Buffer::compact(){ - uint32_t p = limit - position; - //copy p chars from position to 0 - memmove(data, data + position, p); - limit = size; - position = p; -} - -void qpid::framing::Buffer::record(){ - r_position = position; - r_limit = limit; -} - -void qpid::framing::Buffer::restore(){ - position = r_position; - limit = r_limit; -} - -uint32_t qpid::framing::Buffer::available(){ - return limit - position; -} - -char* qpid::framing::Buffer::start(){ - return data + position; -} - -void qpid::framing::Buffer::move(uint32_t bytes){ - position += bytes; -} - -void qpid::framing::Buffer::putOctet(uint8_t i){ - data[position++] = i; -} - -void qpid::framing::Buffer::putShort(uint16_t i){ - uint16_t b = i; - data[position++] = (uint8_t) (0xFF & (b >> 8)); - data[position++] = (uint8_t) (0xFF & b); -} - -void qpid::framing::Buffer::putLong(uint32_t i){ - 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 qpid::framing::Buffer::putLongLong(uint64_t i){ - uint32_t hi = i >> 32; - uint32_t lo = i; - putLong(hi); - putLong(lo); -} - -uint8_t qpid::framing::Buffer::getOctet(){ - return (uint8_t) data[position++]; -} - -uint16_t qpid::framing::Buffer::getShort(){ - uint16_t hi = (unsigned char) data[position++]; - hi = hi << 8; - hi |= (unsigned char) data[position++]; - return hi; -} - -uint32_t qpid::framing::Buffer::getLong(){ - 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 qpid::framing::Buffer::getLongLong(){ - uint64_t hi = getLong(); - uint64_t lo = getLong(); - hi = hi << 32; - return hi | lo; -} - - -void qpid::framing::Buffer::putShortString(const string& s){ - uint8_t len = s.length(); - putOctet(len); - s.copy(data + position, len); - position += len; -} - -void qpid::framing::Buffer::putLongString(const string& s){ - uint32_t len = s.length(); - putLong(len); - s.copy(data + position, len); - position += len; -} - -void qpid::framing::Buffer::getShortString(string& s){ - uint8_t len = getOctet(); - s.assign(data + position, len); - position += len; -} - -void qpid::framing::Buffer::getLongString(string& s){ - uint32_t len = getLong(); - s.assign(data + position, len); - position += len; -} - -void qpid::framing::Buffer::putFieldTable(const FieldTable& t){ - t.encode(*this); -} - -void qpid::framing::Buffer::getFieldTable(FieldTable& t){ - t.decode(*this); -} - -void qpid::framing::Buffer::putContent(const Content& c){ - c.encode(*this); -} - -void qpid::framing::Buffer::getContent(Content& c){ - c.decode(*this); -} - -void qpid::framing::Buffer::putRawData(const string& s){ - uint32_t len = s.length(); - s.copy(data + position, len); - position += len; -} - -void qpid::framing::Buffer::getRawData(string& s, uint32_t len){ - s.assign(data + position, len); - position += len; -} diff --git a/qpid/cpp/lib/common/framing/Buffer.h b/qpid/cpp/lib/common/framing/Buffer.h deleted file mode 100644 index 63a15c7c3d..0000000000 --- a/qpid/cpp/lib/common/framing/Buffer.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. - * - */ -#include - -#ifndef _Buffer_ -#define _Buffer_ - -namespace qpid { -namespace framing { - -class Content; -class FieldTable; - -class Buffer -{ - const uint32_t size; - const bool owner;//indicates whether the data is owned by this instance - char* data; - uint32_t position; - uint32_t limit; - uint32_t r_position; - uint32_t r_limit; - -public: - - Buffer(uint32_t size); - Buffer(char* data, uint32_t size); - ~Buffer(); - - void flip(); - void clear(); - void compact(); - void record(); - void restore(); - uint32_t available(); - char* start(); - void move(uint32_t bytes); - - void putOctet(uint8_t i); - void putShort(uint16_t i); - void putLong(uint32_t i); - void putLongLong(uint64_t i); - - uint8_t getOctet(); - uint16_t getShort(); - uint32_t getLong(); - uint64_t getLongLong(); - - void putShortString(const string& s); - void putLongString(const string& s); - void getShortString(string& s); - void getLongString(string& s); - - void putFieldTable(const FieldTable& t); - void getFieldTable(FieldTable& t); - - void putContent(const Content& c); - void getContent(Content& c); - - void putRawData(const string& s); - void getRawData(string& s, uint32_t size); - -}; - -}} // namespace qpid::framing - - -#endif diff --git a/qpid/cpp/lib/common/framing/ChannelAdapter.cpp b/qpid/cpp/lib/common/framing/ChannelAdapter.cpp deleted file mode 100644 index 8a1ff39ee5..0000000000 --- a/qpid/cpp/lib/common/framing/ChannelAdapter.cpp +++ /dev/null @@ -1,99 +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 "ChannelAdapter.h" -#include "AMQFrame.h" -#include "Exception.h" - -using boost::format; - -namespace qpid { -namespace framing { - -void ChannelAdapter::init( - ChannelId i, OutputHandler& o, ProtocolVersion v) -{ - assertChannelNotOpen(); - id = i; - out = &o; - version = v; -} - -RequestId ChannelAdapter::send(AMQBody::shared_ptr body) { - RequestId result = 0; - assertChannelOpen(); - switch (body->type()) { - case REQUEST_BODY: { - AMQRequestBody::shared_ptr request = - boost::shared_polymorphic_downcast(body); - requester.sending(request->getData()); - result = request->getData().requestId; - break; - } - case RESPONSE_BODY: { - AMQResponseBody::shared_ptr response = - boost::shared_polymorphic_downcast(body); - responder.sending(response->getData()); - break; - } - } - out->send(new AMQFrame(getVersion(), getId(), body)); - return result; -} - -void ChannelAdapter::handleRequest(AMQRequestBody::shared_ptr request) { - assertMethodOk(*request); - AMQRequestBody::Data& requestData = request->getData(); - responder.received(requestData); - handleMethodInContext(request, MethodContext(this, request)); -} - -void ChannelAdapter::handleResponse(AMQResponseBody::shared_ptr response) { - assertMethodOk(*response); - // TODO aconway 2007-01-30: Consider a response handled on receipt. - // Review - any cases where this is not the case? - AMQResponseBody::Data& responseData = response->getData(); - requester.processed(responseData); - handleMethod(response); -} - -void ChannelAdapter::handleMethod(AMQMethodBody::shared_ptr method) { - assertMethodOk(*method); - handleMethodInContext(method, MethodContext(this, method)); -} - -void ChannelAdapter::assertMethodOk(AMQMethodBody& method) const { - if (getId() != 0 && method.amqpClassId() == ConnectionOpenBody::CLASS_ID) - throw ConnectionException( - 504, format("Connection method on non-0 channel %d.")%getId()); -} - -void ChannelAdapter::assertChannelOpen() const { - if (getId() != 0 && !isOpen()) - throw ConnectionException( - 504, format("Channel %d is not open.")%getId()); -} - -void ChannelAdapter::assertChannelNotOpen() const { - if (getId() != 0 && isOpen()) - throw ConnectionException( - 504, format("Channel %d is already open.") % getId()); -} - -}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/ChannelAdapter.h b/qpid/cpp/lib/common/framing/ChannelAdapter.h deleted file mode 100644 index f6e3986eed..0000000000 --- a/qpid/cpp/lib/common/framing/ChannelAdapter.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef _ChannelAdapter_ -#define _ChannelAdapter_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "BodyHandler.h" -#include "Requester.h" -#include "Responder.h" -#include "framing/amqp_types.h" - -namespace qpid { -namespace framing { - -class MethodContext; - -// FIXME aconway 2007-02-20: Rename as ChannelBase or just Channel. - -/** - * Base class for client and broker channels. - * - * - receives frame bodies from the network. - * - Updates request/response data. - * - Dispatches requests with a MethodContext for responses. - * - * send() - * - Updates request/resposne ID data. - * - Forwards frame to the peer. - * - * Thread safety: OBJECT UNSAFE. Instances must not be called - * concurrently. AMQP defines channels to be serialized. - */ -class ChannelAdapter : public BodyHandler { - public: - /** - *@param output Processed frames are forwarded to this handler. - */ - ChannelAdapter(ChannelId id_=0, OutputHandler* out_=0, - ProtocolVersion ver=ProtocolVersion()) - : id(id_), out(out_), version(ver) {} - - /** Initialize the channel adapter. */ - void init(ChannelId, OutputHandler&, ProtocolVersion); - - ChannelId getId() const { return id; } - ProtocolVersion getVersion() const { return version; } - - /** - * Wrap body in a frame and send the frame. - * Takes ownership of body. - */ - RequestId send(AMQBody::shared_ptr body); - RequestId send(AMQBody* body) { return send(AMQBody::shared_ptr(body)); } - - void handleMethod(boost::shared_ptr); - void handleRequest(boost::shared_ptr); - void handleResponse(boost::shared_ptr); - - virtual bool isOpen() const = 0; - - protected: - void assertMethodOk(AMQMethodBody& method) const; - void assertChannelOpen() const; - void assertChannelNotOpen() const; - - virtual void handleMethodInContext( - boost::shared_ptr method, - const MethodContext& context) = 0; - - RequestId getFirstAckRequest() { return requester.getFirstAckRequest(); } - RequestId getLastAckRequest() { return requester.getLastAckRequest(); } - RequestId getNextSendRequestId() { return requester.getNextId(); } - - private: - ChannelId id; - OutputHandler* out; - ProtocolVersion version; - Requester requester; - Responder responder; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/common/framing/FieldTable.cpp b/qpid/cpp/lib/common/framing/FieldTable.cpp deleted file mode 100644 index 5bbc4651d3..0000000000 --- a/qpid/cpp/lib/common/framing/FieldTable.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 -#include -#include -#include -#include - -namespace qpid { -namespace framing { - -FieldTable::~FieldTable() {} - -uint32_t FieldTable::size() const { - uint32_t len(4); - for(ValueMap::const_iterator i = values.begin(); i != values.end(); ++i) { - // 2 = shortstr_len_byyte + type_char_byte - len += 2 + (i->first).size() + (i->second)->size(); - } - 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) { - out << "{"; - FieldTable::ValueMap::const_iterator i = t.getMap().begin(); - if (i != t.getMap().end()) out << *i++; - while (i != t.getMap().end()) - { - out << "," << *i++; - } - return out << "}"; -} - -void FieldTable::setString(const std::string& name, const std::string& value){ - values[name] = ValuePtr(new StringValue(value)); -} - -void FieldTable::setInt(const std::string& name, int value){ - values[name] = ValuePtr(new IntegerValue(value)); -} - -void FieldTable::setTimestamp(const std::string& name, uint64_t value){ - values[name] = ValuePtr(new TimeValue(value)); -} - -void FieldTable::setTable(const std::string& name, const FieldTable& value){ - values[name] = ValuePtr(new FieldTableValue(value)); -} - -namespace { -template T default_value() { return T(); } -template <> int default_value() { return 0; } -template <> uint64_t default_value() { return 0; } -} - -template -T FieldTable::getValue(const std::string& name) const -{ - ValueMap::const_iterator i = values.find(name); - if (i == values.end()) return default_value(); - const ValueOps *vt = dynamic_cast*>(i->second.get()); - return vt->getValue(); -} - -std::string FieldTable::getString(const std::string& name) const { - return getValue(name); -} - -int FieldTable::getInt(const std::string& name) const { - return getValue(name); -} - -uint64_t FieldTable::getTimestamp(const std::string& name) const { - return getValue(name); -} - -void FieldTable::getTable(const std::string& name, FieldTable& value) const { - value = getValue(name); -} - -void FieldTable::encode(Buffer& buffer) const{ - buffer.putLong(size() - 4); - for (ValueMap::const_iterator i = values.begin(); i!=values.end(); ++i) { - buffer.putShortString(i->first); - buffer.putOctet(i->second->getType()); - i->second->encode(buffer); - } -} - -void FieldTable::decode(Buffer& buffer){ - uint32_t len = buffer.getLong(); - uint32_t available = buffer.available(); - if (available < len) - THROW_QPID_ERROR(FRAMING_ERROR, "Not enough data for field table."); - uint32_t leftover = available - len; - while(buffer.available() > leftover){ - std::string name; - buffer.getShortString(name); - std::auto_ptr value(Value::decode_value(buffer)); - values[name] = ValuePtr(value.release()); - } -} - - -bool FieldTable::operator==(const FieldTable& x) const { - 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) -{ - values.erase(values.find(name)); -} - -} -} diff --git a/qpid/cpp/lib/common/framing/FieldTable.h b/qpid/cpp/lib/common/framing/FieldTable.h deleted file mode 100644 index e25a7d3f8c..0000000000 --- a/qpid/cpp/lib/common/framing/FieldTable.h +++ /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 -#include -#include -#include -#include - -#ifndef _FieldTable_ -#define _FieldTable_ - -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 Value; -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; - - ~FieldTable(); - uint32_t size() const; - int count() const; - void setString(const std::string& name, const std::string& value); - void setInt(const std::string& name, int value); - void setTimestamp(const std::string& name, uint64_t value); - void setTable(const std::string& name, const FieldTable& value); - //void setDecimal(string& name, xxx& value); - std::string getString(const std::string& name) const; - int getInt(const std::string& name) const; - uint64_t getTimestamp(const std::string& name) const; - void getTable(const std::string& name, FieldTable& value) const; - //void getDecimal(string& name, xxx& value); - void erase(const std::string& name); - - void encode(Buffer& buffer) const; - void decode(Buffer& buffer); - - bool operator==(const FieldTable& other) const; - - // TODO aconway 2006-09-26: Yeuch! Rework FieldTable to have - // a map-like interface. - const ValueMap& getMap() const { return values; } - ValueMap& getMap() { return values; } - - private: - friend std::ostream& operator<<(std::ostream& out, const FieldTable& body); - ValueMap values; - template T getValue(const std::string& name) const; -}; - -class FieldNotFoundException{}; -class UnknownFieldName : public FieldNotFoundException{}; -class IncorrectFieldType : public FieldNotFoundException{}; -} -} - - -#endif diff --git a/qpid/cpp/lib/common/framing/FramingContent.cpp b/qpid/cpp/lib/common/framing/FramingContent.cpp deleted file mode 100644 index 24efa38dcb..0000000000 --- a/qpid/cpp/lib/common/framing/FramingContent.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 - -#include "Buffer.h" -#include "FramingContent.h" -#include -#include - -namespace qpid { -namespace framing { - -Content::Content() : discriminator(0) {} - -Content::Content(uint8_t _discriminator, const string& _value): discriminator(_discriminator), value(_value) { - validate(); -} - -void Content::validate() { - if (discriminator == REFERENCE) { - if(value.empty()) { - THROW_QPID_ERROR(FRAMING_ERROR, "Reference cannot be empty"); - } - }else if (discriminator != INLINE) { - std::stringstream out; - out << "Invalid discriminator: " << (int) discriminator; - THROW_QPID_ERROR(FRAMING_ERROR, out.str()); - } -} - -Content::~Content() {} - -void Content::encode(Buffer& buffer) const { - buffer.putOctet(discriminator); - buffer.putLongString(value); -} - -void Content::decode(Buffer& buffer) { - discriminator = buffer.getOctet(); - buffer.getLongString(value); - validate(); -} - -size_t Content::size() const { - return 1/*discriminator*/ + 4/*for recording size of long string*/ + value.size(); -} - -std::ostream& operator<<(std::ostream& out, const Content& content) { - if (content.discriminator == REFERENCE) { - out << "{REF:" << content.value << "}"; - } else if (content.discriminator == INLINE) { - out << "{INLINE:" << content.value.size() << " bytes}"; - } - return out; -} - -}} // namespace framing::qpid diff --git a/qpid/cpp/lib/common/framing/FramingContent.h b/qpid/cpp/lib/common/framing/FramingContent.h deleted file mode 100644 index 876e90c905..0000000000 --- a/qpid/cpp/lib/common/framing/FramingContent.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _framing_FramingContent_h -#define _framing_FramingContent_h - -#include - -namespace qpid { -namespace framing { - -enum discriminator_types { INLINE = 0, REFERENCE = 1 }; - -/** - * A representation of the AMQP 'content' data type (used for message - * bodies) which can hold inline data or a reference. - */ -class Content -{ - uint8_t discriminator; - string value; - - void validate(); - - public: - Content(); - Content(uint8_t _discriminator, const string& _value); - ~Content(); - - void encode(Buffer& buffer) const; - void decode(Buffer& buffer); - size_t size() const; - bool isInline() const { return discriminator == INLINE; } - bool isReference() const { return discriminator == REFERENCE; } - const string& getValue() const { return value; } - void setValue(const string& newValue) { value = newValue; } - - friend std::ostream& operator<<(std::ostream&, const Content&); -}; - -}} // namespace qpid::framing - - -#endif /*!_framing_FramingContent_h*/ diff --git a/qpid/cpp/lib/common/framing/HeaderProperties.h b/qpid/cpp/lib/common/framing/HeaderProperties.h deleted file mode 100644 index 1ec4840309..0000000000 --- a/qpid/cpp/lib/common/framing/HeaderProperties.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. - * - */ -#include -#include - -#ifndef _HeaderProperties_ -#define _HeaderProperties_ - -namespace qpid { -namespace framing { - - enum header_classes{BASIC = 60}; - - class HeaderProperties - { - - public: - inline virtual ~HeaderProperties(){} - virtual uint8_t classId() = 0; - virtual uint32_t size() const = 0; - virtual void encode(Buffer& buffer) const = 0; - virtual void decode(Buffer& buffer, uint32_t size) = 0; - }; -} -} - - -#endif diff --git a/qpid/cpp/lib/common/framing/InitiationHandler.cpp b/qpid/cpp/lib/common/framing/InitiationHandler.cpp deleted file mode 100644 index dd92c9859b..0000000000 --- a/qpid/cpp/lib/common/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::~InitiationHandler() {} diff --git a/qpid/cpp/lib/common/framing/InitiationHandler.h b/qpid/cpp/lib/common/framing/InitiationHandler.h deleted file mode 100644 index 7f44323f09..0000000000 --- a/qpid/cpp/lib/common/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 - -namespace qpid { -namespace framing { - - class InitiationHandler{ - public: - virtual ~InitiationHandler(); - virtual void initiated(const ProtocolInitiation&) = 0; - }; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/framing/InputHandler.h b/qpid/cpp/lib/common/framing/InputHandler.h deleted file mode 100644 index 4e2d4bcc9b..0000000000 --- a/qpid/cpp/lib/common/framing/InputHandler.h +++ /dev/null @@ -1,39 +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 -#include - -namespace qpid { -namespace framing { - -class InputHandler : private boost::noncopyable { - public: - virtual ~InputHandler() {} - virtual void received(AMQFrame* frame) = 0; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/common/framing/MethodContext.cpp b/qpid/cpp/lib/common/framing/MethodContext.cpp deleted file mode 100644 index 73af73f8e5..0000000000 --- a/qpid/cpp/lib/common/framing/MethodContext.cpp +++ /dev/null @@ -1,31 +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 "MethodContext.h" -#include "amqp_types.h" -#include "AMQRequestBody.h" - -namespace qpid { -namespace framing { - -RequestId MethodContext::getRequestId() const { - return boost::shared_polymorphic_downcast(methodBody) - ->getRequestId(); -} - -}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/MethodContext.h b/qpid/cpp/lib/common/framing/MethodContext.h deleted file mode 100644 index 80e4c55d7e..0000000000 --- a/qpid/cpp/lib/common/framing/MethodContext.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _framing_MethodContext_h -#define _framing_MethodContext_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 "OutputHandler.h" -#include "ProtocolVersion.h" - -namespace qpid { -namespace framing { - -class BodyHandler; -class AMQMethodBody; -class ChannelAdapter; - -/** - * Invocation context for an AMQP method. - * - * It provides the method being processed and the channel on which - * it arrived. - * - * All Handler functions take a MethodContext as the last parameter. - */ -struct MethodContext -{ - typedef boost::shared_ptr BodyPtr; - - MethodContext(ChannelAdapter* ch=0, BodyPtr method=BodyPtr()) - : channel(ch), methodBody(method) {} - - /** - * Channel on which the method being processed arrived. - * 0 if the method was constructed by the caller - * rather than received from a channel. - */ - ChannelAdapter* channel; - - /** - * Body of the method being processed. - * It's useful for passing around instead of unpacking all its parameters. - * It's also provides the request ID when constructing a response. - */ - BodyPtr methodBody; - - /** - * Return methodBody's request ID. - * It is an error to call this if methodBody is not a request. - */ - RequestId getRequestId() const; -}; - - -}} // namespace qpid::framing - - - -#endif /*!_framing_MethodContext_h*/ diff --git a/qpid/cpp/lib/common/framing/OutputHandler.h b/qpid/cpp/lib/common/framing/OutputHandler.h deleted file mode 100644 index 9ffd4227d8..0000000000 --- a/qpid/cpp/lib/common/framing/OutputHandler.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _OutputHandler_ -#define _OutputHandler_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 { -class AMQFrame; - -class OutputHandler : private boost::noncopyable { - public: - virtual ~OutputHandler() {} - virtual void send(AMQFrame* frame) = 0; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/common/framing/ProtocolInitiation.cpp b/qpid/cpp/lib/common/framing/ProtocolInitiation.cpp deleted file mode 100644 index de53488f7b..0000000000 --- a/qpid/cpp/lib/common/framing/ProtocolInitiation.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 - -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){ - buffer.putOctet('A'); - buffer.putOctet('M'); - buffer.putOctet('Q'); - buffer.putOctet('P'); - 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 - buffer.getOctet();//class - buffer.getOctet();//instance - version.setMajor(buffer.getOctet()); - version.setMinor(buffer.getOctet()); - return true; - }else{ - return false; - } -} - -//TODO: this should prbably be generated from the spec at some point to keep the version numbers up to date - -}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/ProtocolInitiation.h b/qpid/cpp/lib/common/framing/ProtocolInitiation.h deleted file mode 100644 index ed7b59e94e..0000000000 --- a/qpid/cpp/lib/common/framing/ProtocolInitiation.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. - * - */ -#include -#include -#include -#include - -#ifndef _ProtocolInitiation_ -#define _ProtocolInitiation_ - -namespace qpid { -namespace framing { - -class ProtocolInitiation : public AMQDataBlock -{ -private: - ProtocolVersion version; - -public: - ProtocolInitiation(); - ProtocolInitiation(uint8_t major, uint8_t minor); - ProtocolInitiation(ProtocolVersion p); - virtual ~ProtocolInitiation(); - virtual void encode(Buffer& buffer); - virtual bool decode(Buffer& buffer); - inline virtual uint32_t size() 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; } -}; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/framing/ProtocolVersion.cpp b/qpid/cpp/lib/common/framing/ProtocolVersion.cpp deleted file mode 100644 index fd4b1a645f..0000000000 --- a/qpid/cpp/lib/common/framing/ProtocolVersion.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 -#include - -using namespace qpid::framing; - -const std::string ProtocolVersion::toString() const -{ - std::stringstream ss; - ss << major_ << "-" << minor_; - 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_; -} - diff --git a/qpid/cpp/lib/common/framing/ProtocolVersion.h b/qpid/cpp/lib/common/framing/ProtocolVersion.h deleted file mode 100644 index 5e1429c1ea..0000000000 --- a/qpid/cpp/lib/common/framing/ProtocolVersion.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 _ProtocolVersion_ -#define _ProtocolVersion_ - -#include - -namespace qpid -{ -namespace framing -{ - -class ProtocolVersion -{ -private: - uint8_t major_; - uint8_t minor_; - -public: - ProtocolVersion(uint8_t _major=0, uint8_t _minor=0) - : major_(_major), minor_(_minor) {} - - uint8_t getMajor() const { return major_; } - void setMajor(uint8_t major) { major_ = major; } - uint8_t getMinor() const { return minor_; } - void setMinor(uint8_t minor) { minor_ = minor; } - const std::string toString() const; - - ProtocolVersion& operator=(ProtocolVersion p); - - bool operator==(ProtocolVersion p) const; - bool operator!=(ProtocolVersion p) const { return ! (*this == p); } -}; - -} // namespace framing -} // namespace qpid - - -#endif // ifndef _ProtocolVersion_ diff --git a/qpid/cpp/lib/common/framing/ProtocolVersionException.cpp b/qpid/cpp/lib/common/framing/ProtocolVersionException.cpp deleted file mode 100644 index 9088422f6f..0000000000 --- a/qpid/cpp/lib/common/framing/ProtocolVersionException.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 -#include - - -using namespace qpid::framing; - -void ProtocolVersionException::init(const std::string& msg) -{ - whatStr = boost::str( - boost::format("ProtocolVersionException: %s found: %s") - % versionFound.toString() % msg); -} - diff --git a/qpid/cpp/lib/common/framing/ProtocolVersionException.h b/qpid/cpp/lib/common/framing/ProtocolVersionException.h deleted file mode 100644 index 8e2de8b843..0000000000 --- a/qpid/cpp/lib/common/framing/ProtocolVersionException.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 _ProtocolVersionException_ -#define _ProtocolVersionException_ - -#include -#include -#include -#include - -namespace qpid { -namespace framing { - -class ProtocolVersionException : public qpid::Exception -{ -protected: - ProtocolVersion versionFound; - -public: - ~ProtocolVersionException() throw() {} - - template - ProtocolVersionException( - ProtocolVersion ver, const T& msg) throw () : versionFound(ver) - { init(boost::lexical_cast(msg)); } - - template - ProtocolVersionException(const T& msg) throw () - { init(boost::lexical_cast(msg)); } - - private: - void init(const std::string& msg); -}; - -}} // namespace qpid::framing - -#endif //ifndef _ProtocolVersionException_ diff --git a/qpid/cpp/lib/common/framing/Proxy.cpp b/qpid/cpp/lib/common/framing/Proxy.cpp deleted file mode 100644 index 0b2a882a49..0000000000 --- a/qpid/cpp/lib/common/framing/Proxy.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 "Proxy.h" -#include "ChannelAdapter.h" -#include "ProtocolVersion.h" - -namespace qpid { -namespace framing { - -Proxy::~Proxy() {} - -ProtocolVersion Proxy::getProtocolVersion() const { - return channel.getVersion(); -} - -}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/Proxy.h b/qpid/cpp/lib/common/framing/Proxy.h deleted file mode 100644 index 8ed46ed748..0000000000 --- a/qpid/cpp/lib/common/framing/Proxy.h +++ /dev/null @@ -1,51 +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 "ProtocolVersion.h" - -namespace qpid { -namespace framing { - -class ChannelAdapter; -class FieldTable; -class Content; - -/** - * Base class for proxies. - */ -class Proxy -{ - - public: - Proxy(ChannelAdapter& ch) : channel(ch) {} - virtual ~Proxy(); - - ProtocolVersion getProtocolVersion() const; - - protected: - ChannelAdapter& channel; -}; - -}} // namespace qpid::framing - - - -#endif /*!_framing_Proxy_h*/ diff --git a/qpid/cpp/lib/common/framing/Requester.cpp b/qpid/cpp/lib/common/framing/Requester.cpp deleted file mode 100644 index 9ee809e2ee..0000000000 --- a/qpid/cpp/lib/common/framing/Requester.cpp +++ /dev/null @@ -1,40 +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 "Requester.h" -#include "QpidError.h" - -namespace qpid { -namespace framing { - -Requester::Requester() : lastId(0), responseMark(0) {} - -void Requester::sending(AMQRequestBody::Data& request) { - request.requestId = ++lastId; - request.responseMark = responseMark; -} - -void Requester::processed(const AMQResponseBody::Data& response) { - responseMark = response.responseId; - firstAckRequest = response.requestId; - lastAckRequest = firstAckRequest + response.batchOffset; -} - -}} // namespace qpid::framing diff --git a/qpid/cpp/lib/common/framing/Requester.h b/qpid/cpp/lib/common/framing/Requester.h deleted file mode 100644 index dcc4460041..0000000000 --- a/qpid/cpp/lib/common/framing/Requester.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _framing_Requester_h -#define _framing_Requester_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 "AMQRequestBody.h" -#include "AMQResponseBody.h" - -namespace qpid { -namespace framing { - -class AMQRequestBody; -class AMQResponseBody; - -/** - * Manage request IDs and the response mark for locally initiated requests. - * - * THREAD UNSAFE: This class is called as frames are sent or received - * sequentially on a connection, so it does not need to be thread safe. - */ -class Requester -{ - public: - Requester(); - - /** Called before sending a request to set request data. */ - void sending(AMQRequestBody::Data&); - - /** Called after processing a response. */ - void processed(const AMQResponseBody::Data&); - - /** Get the next request id to be used. */ - RequestId getNextId() { return lastId + 1; } - /** Get the first request acked by this response */ - RequestId getFirstAckRequest() { return firstAckRequest; } - /** Get the last request acked by this response */ - RequestId getLastAckRequest() { return lastAckRequest; } - - private: - RequestId lastId; - ResponseId responseMark; - ResponseId firstAckRequest; - ResponseId lastAckRequest; -}; - -}} // namespace qpid::framing - - - -#endif /*!_framing_Requester_h*/ diff --git a/qpid/cpp/lib/common/framing/Responder.cpp b/qpid/cpp/lib/common/framing/Responder.cpp deleted file mode 100644 index c8c5ce8dcc..0000000000 --- a/qpid/cpp/lib/common/framing/Responder.cpp +++ /dev/null @@ -1,43 +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 "Responder.h" -#include "QpidError.h" - -namespace qpid { -namespace framing { - -Responder::Responder() : lastId(0), responseMark(0) {} - -void Responder::received(const AMQRequestBody::Data& request) { - if (request.responseMark < responseMark || request.responseMark > lastId) - THROW_QPID_ERROR( - PROTOCOL_ERROR, boost::format("Invalid response mark %d.") - %request.responseMark); - responseMark = request.responseMark; -} - -void Responder::sending(AMQResponseBody::Data& response) { - response.responseId = ++lastId; - assert(response.requestId); // Should be already set. - response.batchOffset = 0; -} - -}} // namespace qpid::framing - diff --git a/qpid/cpp/lib/common/framing/Responder.h b/qpid/cpp/lib/common/framing/Responder.h deleted file mode 100644 index 0e1785256b..0000000000 --- a/qpid/cpp/lib/common/framing/Responder.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _framing_Responder_h -#define _framing_Responder_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 "AMQRequestBody.h" -#include "AMQResponseBody.h" - -namespace qpid { -namespace framing { - -/** - * Manage response ids and response mark remotely initianted requests. - * - * THREAD UNSAFE: This class is called as frames are sent or received - * sequentially on a connection, so it does not need to be thread safe. - */ -class Responder -{ - public: - Responder(); - - /** Called after receiving a request. */ - void received(const AMQRequestBody::Data& request); - - /** Called before sending a response to set respose data. */ - void sending(AMQResponseBody::Data& response); - - /** Get the ID of the highest response acknowledged by the peer. */ - ResponseId getResponseMark() { return responseMark; } - - // TODO aconway 2007-01-14: Batching support - store unsent - // Response for equality comparison with subsequent responses. - // - - private: - ResponseId lastId; - ResponseId responseMark; -}; - -}} // namespace qpid::framing - - - -#endif /*!_framing_Responder_h*/ diff --git a/qpid/cpp/lib/common/framing/Value.cpp b/qpid/cpp/lib/common/framing/Value.cpp deleted file mode 100644 index 03e005e384..0000000000 --- a/qpid/cpp/lib/common/framing/Value.cpp +++ /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 -#include -#include -#include -#include - -namespace qpid { -namespace framing { - -Value::~Value() {} - -void StringValue::encode(Buffer& buffer){ - buffer.putLongString(value); -} -void StringValue::decode(Buffer& buffer){ - buffer.getLongString(value); -} - -void IntegerValue::encode(Buffer& buffer){ - buffer.putLong((uint32_t) value); -} -void IntegerValue::decode(Buffer& buffer){ - value = buffer.getLong(); -} - -void TimeValue::encode(Buffer& buffer){ - buffer.putLongLong(value); -} -void TimeValue::decode(Buffer& buffer){ - value = buffer.getLongLong(); -} - -void DecimalValue::encode(Buffer& buffer){ - buffer.putOctet(value.decimals); - buffer.putLong(value.value); -} -void DecimalValue::decode(Buffer& buffer){ - value = Decimal(buffer.getLong(), buffer.getOctet()); -} - -void FieldTableValue::encode(Buffer& buffer){ - buffer.putFieldTable(value); -} -void FieldTableValue::decode(Buffer& buffer){ - buffer.getFieldTable(value); -} - -std::auto_ptr Value::decode_value(Buffer& buffer) -{ - std::auto_ptr value; - uint8_t type = buffer.getOctet(); - switch(type){ - case 'S': - value.reset(new StringValue()); - break; - case 'I': - value.reset(new IntegerValue()); - break; - case 'D': - value.reset(new DecimalValue()); - break; - case 'T': - value.reset(new TimeValue()); - break; - case 'F': - value.reset(new FieldTableValue()); - break; - - //non-standard types, introduced in java client for JMS compliance - case 'x': - value.reset(new BinaryValue()); - break; - default: - std::stringstream out; - out << "Unknown field table value type: " << type; - THROW_QPID_ERROR(FRAMING_ERROR, out.str()); - } - value->decode(buffer); - return value; -} - -EmptyValue::~EmptyValue() {} - -void EmptyValue::print(std::ostream& out) const -{ - out << ""; -} - -std::ostream& operator<<(std::ostream& out, const Value& v) { - v.print(out); - return out; -} - -std::ostream& operator<<(std::ostream& out, const Decimal& d) -{ - return out << "Decimal(" << d.value << "," << d.decimals << ")"; -} - -}} - - - diff --git a/qpid/cpp/lib/common/framing/Value.h b/qpid/cpp/lib/common/framing/Value.h deleted file mode 100644 index 8752b02f40..0000000000 --- a/qpid/cpp/lib/common/framing/Value.h +++ /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 -#include -#include -#include - -#ifndef _Value_ -#define _Value_ - -namespace qpid { -namespace framing { - -class Buffer; - -/** - * Represents a decimal value. - * No arithmetic functionality for now, we only care about encoding/decoding. - */ -struct Decimal { - uint32_t value; - uint8_t decimals; - - Decimal(uint32_t value_=0, uint8_t decimals_=0) : value(value_), decimals(decimals_) {} - bool operator==(const Decimal& d) const { - return decimals == d.decimals && value == d.value; - } - bool operator!=(const Decimal& d) const { return !(*this == d); } -}; - -std::ostream& operator<<(std::ostream& out, const Decimal& d); - -/** - * Polymorpic base class for values. - */ -class Value { - public: - virtual ~Value(); - virtual uint32_t size() const = 0; - virtual char getType() const = 0; - virtual void encode(Buffer& buffer) = 0; - virtual void decode(Buffer& buffer) = 0; - virtual bool operator==(const Value&) const = 0; - bool operator!=(const Value& v) const { return !(*this == v); } - virtual void print(std::ostream& out) const = 0; - - /** Create a new value by decoding from the buffer */ - static std::auto_ptr decode_value(Buffer& buffer); -}; - -std::ostream& operator<<(std::ostream& out, const Value& d); - - -/** - * Template for common operations on Value sub-classes. - */ -template -class ValueOps : public Value -{ - protected: - T value; - public: - ValueOps() {} - ValueOps(const T& v) : value(v) {} - const T& getValue() const { return value; } - T& getValue() { return value; } - - virtual bool operator==(const Value& v) const { - const ValueOps* vo = dynamic_cast*>(&v); - if (vo == 0) return false; - else return value == vo->value; - } - - void print(std::ostream& out) const { out << value; } -}; - - -class StringValue : public ValueOps { - public: - StringValue(const std::string& v) : ValueOps(v) {} - StringValue() {} - virtual uint32_t size() const { return 4 + value.length(); } - virtual char getType() const { return 'S'; } - virtual void encode(Buffer& buffer); - virtual void decode(Buffer& buffer); -}; - -class IntegerValue : public ValueOps { - public: - IntegerValue(int v) : ValueOps(v) {} - IntegerValue(){} - virtual uint32_t size() const { return 4; } - virtual char getType() const { return 'I'; } - virtual void encode(Buffer& buffer); - virtual void decode(Buffer& buffer); -}; - -class TimeValue : public ValueOps { - public: - TimeValue(uint64_t v) : ValueOps(v){} - TimeValue(){} - virtual uint32_t size() const { return 8; } - virtual char getType() const { return 'T'; } - virtual void encode(Buffer& buffer); - virtual void decode(Buffer& buffer); -}; - -class DecimalValue : public ValueOps { - public: - DecimalValue(const Decimal& d) : ValueOps(d) {} - DecimalValue(uint32_t value_=0, uint8_t decimals_=0) : - ValueOps(Decimal(value_, decimals_)){} - virtual uint32_t size() const { return 5; } - virtual char getType() const { return 'D'; } - virtual void encode(Buffer& buffer); - virtual void decode(Buffer& buffer); -}; - - -class FieldTableValue : public ValueOps { - public: - FieldTableValue(const FieldTable& v) : ValueOps(v){} - FieldTableValue(){} - virtual uint32_t size() const { return 4 + value.size(); } - virtual char getType() const { return 'F'; } - virtual void encode(Buffer& buffer); - virtual void decode(Buffer& buffer); -}; - -class EmptyValue : public Value { - public: - ~EmptyValue(); - virtual uint32_t size() const { return 0; } - virtual char getType() const { return 0; } - virtual void encode(Buffer& ) {} - virtual void decode(Buffer& ) {} - virtual bool operator==(const Value& v) const { - return dynamic_cast(&v); - } - virtual void print(std::ostream& out) const; -}; - -//non-standard types, introduced in java client for JMS compliance -class BinaryValue : public StringValue { - public: - BinaryValue(const std::string& v) : StringValue(v) {} - BinaryValue() {} - virtual char getType() const { return 'x'; } -}; - -}} // qpid::framing - -#endif diff --git a/qpid/cpp/lib/common/framing/amqp_framing.h b/qpid/cpp/lib/common/framing/amqp_framing.h deleted file mode 100644 index 62f87352f8..0000000000 --- a/qpid/cpp/lib/common/framing/amqp_framing.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. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include diff --git a/qpid/cpp/lib/common/framing/amqp_types.h b/qpid/cpp/lib/common/framing/amqp_types.h deleted file mode 100644 index 49963bd570..0000000000 --- a/qpid/cpp/lib/common/framing/amqp_types.h +++ /dev/null @@ -1,57 +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 - * Type definitions and forward declarations of all types used to - * in AMQP messages. - */ - -#include -#ifdef _WINDOWS -#include "windows.h" -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned __int64 uint64_t; -#endif -#ifndef _WINDOWS -#include "stdint.h" -#endif - -namespace qpid { -namespace framing { - -using std::string; -typedef uint16_t ChannelId; -typedef uint64_t RequestId; -typedef uint64_t ResponseId; -typedef uint32_t BatchOffset; -typedef uint16_t ClassId; -typedef uint16_t MethodId; -typedef uint16_t ReplyCode; - -// Types represented by classes. -class Content; -class FieldTable; -}} // namespace qpid::framing -#endif diff --git a/qpid/cpp/lib/common/framing/amqp_types_full.h b/qpid/cpp/lib/common/framing/amqp_types_full.h deleted file mode 100644 index 6a24a99d38..0000000000 --- a/qpid/cpp/lib/common/framing/amqp_types_full.h +++ /dev/null @@ -1,36 +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 - * Type definitions and full declarations of all types used to - * in AMQP messages. - * - * Its 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 do increases compile - * times. - */ - -#include "amqp_types.h" -#include "FramingContent.h" -#include "FieldTable.h" - -#endif /*!_framing_amqp_types_decl_h*/ diff --git a/qpid/cpp/lib/common/shared_ptr.h b/qpid/cpp/lib/common/shared_ptr.h deleted file mode 100644 index c4d547e5bb..0000000000 --- a/qpid/cpp/lib/common/shared_ptr.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _common_shared_ptr_h -#define _common_shared_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 -#include - -namespace qpid { -/// Import shared_ptr definitions into qpid namespace. -using boost::shared_ptr; -using boost::dynamic_pointer_cast; -using boost::static_pointer_cast; -using boost::const_pointer_cast; -using boost::shared_polymorphic_downcast; -} // namespace qpid - - - -#endif /*!_common_shared_ptr_h*/ diff --git a/qpid/cpp/lib/common/sys/Acceptor.h b/qpid/cpp/lib/common/sys/Acceptor.h deleted file mode 100644 index cd4932d92e..0000000000 --- a/qpid/cpp/lib/common/sys/Acceptor.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _sys_Acceptor_h -#define _sys_Acceptor_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 ConnectionInputHandlerFactory; - -class Acceptor : public qpid::SharedObject -{ - public: - static Acceptor::shared_ptr create(int16_t port, int backlog, int threads, bool trace = false); - virtual ~Acceptor() = 0; - virtual uint16_t getPort() const = 0; - virtual void run(qpid::sys::ConnectionInputHandlerFactory* factory) = 0; - virtual void shutdown() = 0; -}; - -}} - - - -#endif /*!_sys_Acceptor_h*/ diff --git a/qpid/cpp/lib/common/sys/AtomicCount.h b/qpid/cpp/lib/common/sys/AtomicCount.h deleted file mode 100644 index 63670cbf00..0000000000 --- a/qpid/cpp/lib/common/sys/AtomicCount.h +++ /dev/null @@ -1,53 +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 "ScopedIncrement.h" - -namespace qpid { -namespace sys { - -/** - * Atomic counter. - */ -class AtomicCount : boost::noncopyable { - public: - typedef ScopedDecrement ScopedDecrement; - typedef 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/lib/common/sys/Condition.h b/qpid/cpp/lib/common/sys/Condition.h deleted file mode 100644 index 9d70af5b84..0000000000 --- a/qpid/cpp/lib/common/sys/Condition.h +++ /dev/null @@ -1,128 +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. - * - */ - -#include -#include -#include -#include - -#ifdef USE_APR -# include -#endif - -namespace qpid { -namespace sys { - -/** - * A condition variable for thread synchronization. - */ -class Condition -{ - public: - inline Condition(); - inline ~Condition(); - inline void wait(Mutex&); - inline bool wait(Mutex&, const Time& absoluteTime); - inline void notify(); - inline void notifyAll(); - - private: -#ifdef USE_APR - apr_thread_cond_t* condition; -#else - pthread_cond_t condition; -#endif -}; - - -// APR ================================================================ -#ifdef USE_APR - -Condition::Condition() { - CHECK_APR_SUCCESS(apr_thread_cond_create(&condition, APRPool::get())); -} - -Condition::~Condition() { - CHECK_APR_SUCCESS(apr_thread_cond_destroy(condition)); -} - -void Condition::wait(Mutex& mutex) { - CHECK_APR_SUCCESS(apr_thread_cond_wait(condition, mutex.mutex)); -} - -bool Condition::wait(Mutex& mutex, const Time& absoluteTime){ - // APR uses microseconds. - apr_status_t status = - apr_thread_cond_timedwait( - condition, mutex.mutex, absoluteTime/TIME_USEC); - if(status != APR_TIMEUP) CHECK_APR_SUCCESS(status); - return status == 0; -} - -void Condition::notify(){ - CHECK_APR_SUCCESS(apr_thread_cond_signal(condition)); -} - -void Condition::notifyAll(){ - CHECK_APR_SUCCESS(apr_thread_cond_broadcast(condition)); -} - -#else -// POSIX ================================================================ - -Condition::Condition() { - QPID_POSIX_THROW_IF(pthread_cond_init(&condition, 0)); -} - -Condition::~Condition() { - QPID_POSIX_THROW_IF(pthread_cond_destroy(&condition)); -} - -void Condition::wait(Mutex& mutex) { - QPID_POSIX_THROW_IF(pthread_cond_wait(&condition, &mutex.mutex)); -} - -bool Condition::wait(Mutex& mutex, const Time& 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; -} - -void Condition::notify(){ - QPID_POSIX_THROW_IF(pthread_cond_signal(&condition)); -} - -void Condition::notifyAll(){ - QPID_POSIX_THROW_IF(pthread_cond_broadcast(&condition)); -} -#endif /*USE_APR*/ - - -}} -#endif /*!_sys_Condition_h*/ diff --git a/qpid/cpp/lib/common/sys/ConnectionInputHandler.h b/qpid/cpp/lib/common/sys/ConnectionInputHandler.h deleted file mode 100644 index fa70dfaf48..0000000000 --- a/qpid/cpp/lib/common/sys/ConnectionInputHandler.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 _ConnectionInputHandler_ -#define _ConnectionInputHandler_ - -#include -#include -#include -#include - -namespace qpid { -namespace sys { - - class ConnectionInputHandler : - public qpid::framing::InitiationHandler, - public qpid::framing::InputHandler, - public TimeoutHandler - { - public: - virtual void closed() = 0; - }; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/sys/ConnectionInputHandlerFactory.h b/qpid/cpp/lib/common/sys/ConnectionInputHandlerFactory.h deleted file mode 100644 index af7d411928..0000000000 --- a/qpid/cpp/lib/common/sys/ConnectionInputHandlerFactory.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 _ConnectionInputHandlerFactory_ -#define _ConnectionInputHandlerFactory_ - -#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: - virtual ConnectionInputHandler* create(ConnectionOutputHandler* ctxt) = 0; - virtual ~ConnectionInputHandlerFactory(){} -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/common/sys/ConnectionOutputHandler.h b/qpid/cpp/lib/common/sys/ConnectionOutputHandler.h deleted file mode 100644 index 91849e1dfb..0000000000 --- a/qpid/cpp/lib/common/sys/ConnectionOutputHandler.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 _ConnectionOutputHandler_ -#define _ConnectionOutputHandler_ - -#include - -namespace qpid { -namespace sys { - -/** - * Provides the output handler associated with a connection. - */ -class ConnectionOutputHandler : public virtual qpid::framing::OutputHandler -{ - public: - virtual void close() = 0; -}; - -}} - - -#endif diff --git a/qpid/cpp/lib/common/sys/Module.h b/qpid/cpp/lib/common/sys/Module.h deleted file mode 100644 index 9bf5d6e1fc..0000000000 --- a/qpid/cpp/lib/common/sys/Module.h +++ /dev/null @@ -1,161 +0,0 @@ -#ifndef _sys_Module_h -#define _sys_Module_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 { -#if USE_APR -#include - typedef apr_dso_handle_t* dso_handle_t; -#else - typedef void* dso_handle_t; -#endif - - template class Module : private boost::noncopyable - { - typedef T* create_t(); - typedef void destroy_t(T*); - - dso_handle_t handle; - destroy_t* destroy; - T* ptr; - - void load(const std::string& name); - void unload(); - void* getSymbol(const std::string& name); - - public: - Module(const std::string& name); - T* operator->(); - T* get(); - ~Module() throw(); - }; - -} -} - -using namespace qpid::sys; - -template Module::Module(const std::string& module) : destroy(0), ptr(0) -{ - load(module); - //TODO: need a better strategy for symbol names to allow multiple - //modules to be loaded without clashes... - - //Note: need the double cast to avoid errors in casting from void* to function pointer with -pedantic - create_t* create = reinterpret_cast(reinterpret_cast(getSymbol("create"))); - destroy = reinterpret_cast(reinterpret_cast(getSymbol("destroy"))); - ptr = create(); -} - -template T* Module::operator->() -{ - return ptr; -} - -template T* Module::get() -{ - return ptr; -} - -template Module::~Module() throw() -{ - try { - if (handle && ptr) { - destroy(ptr); - } - if (handle) unload(); - } catch (std::exception& e) { - std::cout << "Error while destroying module: " << e.what() << std::endl; - } - destroy = 0; - handle = 0; - ptr = 0; -} - -// APR ================================================================ -#if USE_APR - -#include -#include - -template void Module::load(const std::string& name) -{ - CHECK_APR_SUCCESS(apr_dso_load(&handle, name.c_str(), APRPool::get())); -} - -template void Module::unload() -{ - CHECK_APR_SUCCESS(apr_dso_unload(handle)); -} - -template void* Module::getSymbol(const std::string& name) -{ - apr_dso_handle_sym_t symbol; - CHECK_APR_SUCCESS(apr_dso_sym(&symbol, handle, name.c_str())); - return (void*) symbol; -} - -// POSIX================================================================ -#else - -#include - -template void Module::load(const std::string& name) -{ - dlerror(); - handle = dlopen(name.c_str(), RTLD_NOW); - const char* error = dlerror(); - if (error) { - THROW_QPID_ERROR(INTERNAL_ERROR, error); - } -} - -template void Module::unload() -{ - dlerror(); - dlclose(handle); - const char* error = dlerror(); - if (error) { - THROW_QPID_ERROR(INTERNAL_ERROR, error); - } -} - -template void* Module::getSymbol(const std::string& name) -{ - dlerror(); - void* sym = dlsym(handle, name.c_str()); - const char* error = dlerror(); - if (error) { - THROW_QPID_ERROR(INTERNAL_ERROR, error); - } - return sym; -} - -#endif //if USE_APR - -#endif //ifndef _sys_Module_h - diff --git a/qpid/cpp/lib/common/sys/Monitor.h b/qpid/cpp/lib/common/sys/Monitor.h deleted file mode 100644 index a3bbd3c5aa..0000000000 --- a/qpid/cpp/lib/common/sys/Monitor.h +++ /dev/null @@ -1,55 +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 -#include - -#ifdef USE_APR -# include -#endif - -namespace qpid { -namespace sys { - -/** - * A monitor is a condition variable and a mutex - */ -class Monitor : public Mutex, public Condition { - public: - using Condition::wait; - inline void wait(); - inline bool wait(const Time& absoluteTime); -}; - - -void Monitor::wait() { - Condition::wait(*this); -} - -bool Monitor::wait(const Time& absoluteTime) { - return Condition::wait(*this, absoluteTime); -} - -}} -#endif /*!_sys_Monitor_h*/ diff --git a/qpid/cpp/lib/common/sys/Mutex.h b/qpid/cpp/lib/common/sys/Mutex.h deleted file mode 100644 index 9db9be0981..0000000000 --- a/qpid/cpp/lib/common/sys/Mutex.h +++ /dev/null @@ -1,165 +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. - * - */ - -#ifdef USE_APR -# include -# include -# include -#else -# include -# include -#endif -#include - -namespace qpid { -namespace sys { - -class Condition; - -/** - * 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) { l.lock(); } - ~ScopedLock() { mutex.unlock(); } - private: - L& mutex; -}; - -template -class ScopedUnlock -{ - public: - ScopedUnlock(L& l) : mutex(l) { l.unlock(); } - ~ScopedUnlock() { mutex.lock(); } - private: - L& mutex; -}; - -/** - * Mutex lock. - */ -class Mutex : private boost::noncopyable { - public: - typedef ScopedLock ScopedLock; - typedef ScopedUnlock ScopedUnlock; - - inline Mutex(); - inline ~Mutex(); - inline void lock(); - inline void unlock(); - inline void trylock(); - - protected: -#ifdef USE_APR - apr_thread_mutex_t* mutex; -#else - pthread_mutex_t mutex; -#endif - friend class Condition; -}; - -#ifdef USE_APR -// APR ================================================================ - -Mutex::Mutex() { - CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, APRPool::get())); -} - -Mutex::~Mutex(){ - CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); -} - -void Mutex::lock() { - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); -} -void Mutex::unlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); -} - -void Mutex::trylock() { - CHECK_APR_SUCCESS(apr_thread_mutex_trylock(mutex)); -} - -#else -// POSIX ================================================================ - -/** - * PODMutex is a POD, can be static-initialized with - * PODMutex m = QPID_PODMUTEX_INITIALIZER - */ -struct PODMutex -{ - typedef ScopedLock ScopedLock; - - inline void lock(); - inline void unlock(); - inline void trylock(); - - // Must be public to be a POD: - pthread_mutex_t mutex; -}; - -#define QPID_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } - - -void PODMutex::lock() { - QPID_POSIX_THROW_IF(pthread_mutex_lock(&mutex)); -} -void PODMutex::unlock() { - QPID_POSIX_THROW_IF(pthread_mutex_unlock(&mutex)); -} - -void PODMutex::trylock() { - QPID_POSIX_THROW_IF(pthread_mutex_trylock(&mutex)); -} - - -Mutex::Mutex() { - QPID_POSIX_THROW_IF(pthread_mutex_init(&mutex, 0)); -} - -Mutex::~Mutex(){ - QPID_POSIX_THROW_IF(pthread_mutex_destroy(&mutex)); -} - -void Mutex::lock() { - QPID_POSIX_THROW_IF(pthread_mutex_lock(&mutex)); -} -void Mutex::unlock() { - QPID_POSIX_THROW_IF(pthread_mutex_unlock(&mutex)); -} - -void Mutex::trylock() { - QPID_POSIX_THROW_IF(pthread_mutex_trylock(&mutex)); -} - -#endif // USE_APR - -}} - - - -#endif /*!_sys_Mutex_h*/ diff --git a/qpid/cpp/lib/common/sys/ProducerConsumer.cpp b/qpid/cpp/lib/common/sys/ProducerConsumer.cpp deleted file mode 100644 index 7a0249f666..0000000000 --- a/qpid/cpp/lib/common/sys/ProducerConsumer.cpp +++ /dev/null @@ -1,141 +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 "QpidError.h" -#include "ScopedIncrement.h" -#include "ProducerConsumer.h" - -namespace qpid { -namespace sys { - -// // ================ ProducerConsumer - -ProducerConsumer::ProducerConsumer(size_t init_items) - : items(init_items), waiters(0), shutdownFlag(false) -{} - -void ProducerConsumer::shutdown() { - Mutex::ScopedLock l(monitor); - shutdownFlag = true; - monitor.notifyAll(); - // Wait for waiting consumers to wake up. - while (waiters > 0) - monitor.wait(); -} - -size_t ProducerConsumer::available() const { - Mutex::ScopedLock l(monitor); - return items; -} - -size_t ProducerConsumer::consumers() const { - Mutex::ScopedLock l(monitor); - return waiters; -} - -// ================ Lock - -ProducerConsumer::Lock::Lock(ProducerConsumer& p) - : pc(p), lock(p.monitor), status(INCOMPLETE) {} - -bool ProducerConsumer::Lock::isOk() const { - return !pc.isShutdown() && status==INCOMPLETE; -} - -void ProducerConsumer::Lock::checkOk() const { - assert(!pc.isShutdown()); - assert(status == INCOMPLETE); -} - -ProducerConsumer::Lock::~Lock() { - assert(status != INCOMPLETE || pc.isShutdown()); -} - -void ProducerConsumer::Lock::confirm() { - checkOk(); - status = CONFIRMED; -} - -void ProducerConsumer::Lock::cancel() { - checkOk(); - status = CANCELLED; -} - -// ================ ProducerLock - -ProducerConsumer::ProducerLock::ProducerLock(ProducerConsumer& p) : Lock(p) -{} - - -ProducerConsumer::ProducerLock::~ProducerLock() { - if (status == CONFIRMED) { - pc.items++; - pc.monitor.notify(); // Notify a consumer. - } -} - -// ================ ConsumerLock - -ProducerConsumer::ConsumerLock::ConsumerLock(ProducerConsumer& p) : Lock(p) -{ - if (isOk()) { - ScopedIncrement inc(pc.waiters); - while (pc.items == 0 && !pc.shutdownFlag) { - pc.monitor.wait(); - } - } -} - -ProducerConsumer::ConsumerLock::ConsumerLock( - ProducerConsumer& p, const Time& timeout) : Lock(p) -{ - if (isOk()) { - // Don't wait if timeout==0 - if (timeout == 0) { - if (pc.items == 0) - status = TIMEOUT; - return; - } - else { - Time deadline = now() + timeout; - ScopedIncrement inc(pc.waiters); - while (pc.items == 0 && !pc.shutdownFlag) { - if (!pc.monitor.wait(deadline)) { - status = TIMEOUT; - return; - } - } - } - } -} - -ProducerConsumer::ConsumerLock::~ConsumerLock() { - if (pc.isShutdown()) { - if (pc.waiters == 0) - pc.monitor.notifyAll(); // Notify shutdown thread(s) - } - else if (status==CONFIRMED) { - pc.items--; - if (pc.items > 0) - pc.monitor.notify(); // Notify another consumer. - } -} - - -}} // namespace qpid::sys diff --git a/qpid/cpp/lib/common/sys/ProducerConsumer.h b/qpid/cpp/lib/common/sys/ProducerConsumer.h deleted file mode 100644 index c7f42f266d..0000000000 --- a/qpid/cpp/lib/common/sys/ProducerConsumer.h +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef _sys_ProducerConsumer_h -#define _sys_ProducerConsumer_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 "Exception.h" -#include "sys/Monitor.h" - -namespace qpid { -namespace sys { - -/** - * Producer-consumer synchronisation. - * - * Producers increase the number of available items, consumers reduce it. - * Consumers wait till an item is available. Waiting threads can be - * woken for shutdown using shutdown(). - * - * Note: Currently implements unbounded producer-consumer, i.e. no limit - * to available items, producers never block. Can be extended to support - * bounded PC if required. - * - // TODO aconway 2007-02-13: example, from tests. -*/ -class ProducerConsumer -{ - public: - ProducerConsumer(size_t init_items=0); - - ~ProducerConsumer() { shutdown(); } - - /** - * Wake any threads waiting for ProducerLock or ConsumerLock. - *@post No threads are waiting in Producer or Consumer locks. - */ - void shutdown(); - - /** True if queue is shutdown */ - bool isShutdown() { return shutdownFlag; } - - /** Number of items available for consumers */ - size_t available() const; - - /** Number of consumers waiting for items */ - size_t consumers() const; - - /** True if available == 0 */ - bool empty() const { return available() == 0; } - - /** - * Base class for producer and consumer locks. - */ - class Lock : private boost::noncopyable { - public: - - /** - * You must call isOk() after creating a lock to verify its state. - * - *@return true means the lock succeeded. You MUST call either - *confirm() or cancel() before the lock goes out of scope. - * - * false means the lock failed - timed out or the - * ProducerConsumer is shutdown. You should not do anything in - * the scope of the lock. - */ - bool isOk() const; - - /** - * Confirm that an item was produced/consumed. - *@pre isOk() - */ - void confirm(); - - /** - * Cancel the lock to indicate nothing was produced/consumed. - * Note that locks are not actually released until destroyed. - * - *@pre isOk() - */ - void cancel(); - - /** True if this lock experienced a timeout */ - bool isTimedOut() const { return status == TIMEOUT; } - - /** True if we have been shutdown */ - bool isShutdown() const { return pc.isShutdown(); } - - ProducerConsumer& pc; - - protected: - /** Lock status */ - enum Status { INCOMPLETE, CONFIRMED, CANCELLED, TIMEOUT }; - - Lock(ProducerConsumer& p); - ~Lock(); - void checkOk() const; - Mutex::ScopedLock lock; - Status status; - }; - - /** Lock for code that produces items. */ - struct ProducerLock : public Lock { - /** - * Acquire locks to produce an item. - *@post If isOk() the calling thread has exclusive access - * to produce an item. - */ - ProducerLock(ProducerConsumer& p); - - /** Release locks, signal waiting consumers if confirm() was called. */ - ~ProducerLock(); - }; - - /** Lock for code that consumes items */ - struct ConsumerLock : public Lock { - /** - * Wait for an item to consume and acquire locks. - * - *@post If isOk() there is at least one item available and the - *calling thread has exclusive access to consume it. - */ - ConsumerLock(ProducerConsumer& p); - - /** - * Wait up to timeout to acquire lock. - *@post If isOk() caller has a producer lock. - * If isTimedOut() there was a timeout. - * If neither then we were shutdown. - */ - ConsumerLock(ProducerConsumer& p, const Time& timeout); - - /** Release locks */ - ~ConsumerLock(); - }; - - private: - mutable Monitor monitor; - size_t items; - size_t waiters; - bool shutdownFlag; - - friend class Lock; - friend class ProducerLock; - friend class ConsumerLock; -}; - -}} // namespace qpid::sys - -#endif /*!_sys_ProducerConsumer_h*/ diff --git a/qpid/cpp/lib/common/sys/Runnable.cpp b/qpid/cpp/lib/common/sys/Runnable.cpp deleted file mode 100644 index 30122c682f..0000000000 --- a/qpid/cpp/lib/common/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 "Runnable.h" -#include - -namespace qpid { -namespace sys { - -Runnable::~Runnable() {} - -Runnable::Functor Runnable::functor() -{ - return boost::bind(&Runnable::run, this); -} - -}} diff --git a/qpid/cpp/lib/common/sys/Runnable.h b/qpid/cpp/lib/common/sys/Runnable.h deleted file mode 100644 index fb3927c612..0000000000 --- a/qpid/cpp/lib/common/sys/Runnable.h +++ /dev/null @@ -1,50 +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 - -namespace qpid { -namespace sys { - -/** - * Interface for objects that can be run, e.g. in a thread. - */ -class Runnable -{ - public: - /** Type to represent a runnable as a Functor */ - typedef boost::function0 Functor; - - 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/lib/common/sys/ScopedIncrement.h b/qpid/cpp/lib/common/sys/ScopedIncrement.h deleted file mode 100644 index f14461ddaf..0000000000 --- a/qpid/cpp/lib/common/sys/ScopedIncrement.h +++ /dev/null @@ -1,59 +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 - -namespace qpid { -namespace sys { - -/** Increment counter in constructor and decrement in destructor. */ -template -class ScopedIncrement : boost::noncopyable -{ - public: - ScopedIncrement(T& c) : count(c) { ++count; } - ~ScopedIncrement() { --count; } - private: - T& count; -}; - - -/** 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/lib/common/sys/ShutdownHandler.h b/qpid/cpp/lib/common/sys/ShutdownHandler.h deleted file mode 100644 index 88baecb5b6..0000000000 --- a/qpid/cpp/lib/common/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/lib/common/sys/Socket.h b/qpid/cpp/lib/common/sys/Socket.h deleted file mode 100644 index d793a240c6..0000000000 --- a/qpid/cpp/lib/common/sys/Socket.h +++ /dev/null @@ -1,88 +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 -#include - -#ifdef USE_APR -# include -#endif - -namespace qpid { -namespace sys { - -class Socket -{ - public: - /** Create an initialized TCP socket */ - static Socket createTcp(); - - /** Create a socket wrapper for descriptor. */ -#ifdef USE_APR - Socket(apr_socket_t* descriptor = 0); -#else - Socket(int descriptor = 0); -#endif - - /** Set timeout for read and write */ - void setTimeout(Time interval); - - void connect(const std::string& host, int port); - - void close(); - - enum { SOCKET_TIMEOUT=-2, SOCKET_EOF=-3 } ErrorCode; - - /** Returns bytes sent or an ErrorCode value < 0. */ - ssize_t send(const void* data, size_t size); - - /** - * Returns bytes received, an ErrorCode value < 0 or 0 - * if the connection closed in an orderly manner. - */ - ssize_t recv(void* data, size_t size); - - /** 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. - */ - int listen(int port = 0, int backlog = 10); - - /** Get file descriptor */ - int fd(); - - private: -#ifdef USE_APR - apr_socket_t* socket; -#else - void init() const; - mutable int socket; // Initialized on demand. -#endif -}; - -}} - - -#endif /*!_sys_Socket_h*/ diff --git a/qpid/cpp/lib/common/sys/Thread.h b/qpid/cpp/lib/common/sys/Thread.h deleted file mode 100644 index 47b95b6234..0000000000 --- a/qpid/cpp/lib/common/sys/Thread.h +++ /dev/null @@ -1,142 +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 - -#ifdef USE_APR -# include -# include -# include -# include -#else -# include -# include -#endif - -namespace qpid { -namespace sys { - -class Thread -{ - public: - inline static Thread current(); - inline static void yield(); - - inline Thread(); - inline explicit Thread(qpid::sys::Runnable*); - inline explicit Thread(qpid::sys::Runnable&); - - inline void join(); - - inline long id(); - - private: -#ifdef USE_APR - static void* APR_THREAD_FUNC runRunnable(apr_thread_t* thread, void *data); - inline Thread(apr_thread_t* t); - apr_thread_t* thread; -#else - static void* runRunnable(void* runnable); - inline Thread(pthread_t); - pthread_t thread; -#endif -}; - - -Thread::Thread() : thread(0) {} - -// APR ================================================================ -#ifdef USE_APR - -Thread::Thread(Runnable* runnable) { - CHECK_APR_SUCCESS( - apr_thread_create(&thread, 0, runRunnable, runnable, APRPool::get())); -} - -Thread::Thread(Runnable& runnable) { - CHECK_APR_SUCCESS( - apr_thread_create(&thread, 0, runRunnable, &runnable, APRPool::get())); -} - -void Thread::join(){ - apr_status_t status; - if (thread != 0) - CHECK_APR_SUCCESS(apr_thread_join(&status, thread)); -} - -long Thread::id() { - return long(thread); -} - -Thread::Thread(apr_thread_t* t) : thread(t) {} - -Thread Thread::current(){ - apr_thread_t* thr; - apr_os_thread_t osthr = apr_os_thread_current(); - CHECK_APR_SUCCESS(apr_os_thread_put(&thr, &osthr, APRPool::get())); - return Thread(thr); -} - -void Thread::yield() -{ - apr_thread_yield(); -} - - -// POSIX ================================================================ -#else - -Thread::Thread(Runnable* runnable) { - QPID_POSIX_THROW_IF(pthread_create(&thread, NULL, runRunnable, runnable)); -} - -Thread::Thread(Runnable& runnable) { - QPID_POSIX_THROW_IF(pthread_create(&thread, NULL, runRunnable, &runnable)); -} - -void Thread::join(){ - QPID_POSIX_THROW_IF(pthread_join(thread, 0)); -} - -long Thread::id() { - return long(thread); -} - -Thread::Thread(pthread_t thr) : thread(thr) {} - -Thread Thread::current() { - return Thread(pthread_self()); -} - -void Thread::yield() -{ - QPID_POSIX_THROW_IF(pthread_yield()); -} - - -#endif - -}} - -#endif /*!_sys_Thread_h*/ diff --git a/qpid/cpp/lib/common/sys/ThreadSafeQueue.h b/qpid/cpp/lib/common/sys/ThreadSafeQueue.h deleted file mode 100644 index 80ea92da0e..0000000000 --- a/qpid/cpp/lib/common/sys/ThreadSafeQueue.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _sys_ThreadSafeQueue_h -#define _sys_ThreadSafeQueue_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 "ProducerConsumer.h" -#include "Exception.h" - -namespace qpid { -namespace sys { - -/** - * A thread safe queue template. - */ -template > -class ThreadSafeQueue -{ - public: - - ThreadSafeQueue() {} - - /** Push a value onto the back of the queue */ - void push(const T& value) { - ProducerConsumer::ProducerLock producer(pc); - if (producer.isOk()) { - producer.confirm(); - container.push_back(value); - } - } - - /** Pop a value from the front of the queue. Waits till value is available. - *@throw ShutdownException if queue is shutdown while waiting. - */ - T pop() { - ProducerConsumer::ConsumerLock consumer(pc); - if (consumer.isOk()) { - consumer.confirm(); - T value(container.front()); - container.pop_front(); - return value; - } - throw ShutdownException(); - } - - /** - * If a value becomes available within the timeout, set outValue - * and return true. Otherwise return false; - */ - bool pop(T& outValue, const Time& timeout) { - ProducerConsumer::ConsumerLock consumer(pc, timeout); - if (consumer.isOk()) { - consumer.confirm(); - outValue = container.front(); - container.pop_front(); - return true; - } - return false; - } - - /** Interrupt threads waiting in pop() */ - void shutdown() { pc.shutdown(); } - - /** True if queue is shutdown */ - bool isShutdown() { return pc.isShutdown(); } - - /** Size of the queue */ - size_t size() { ProducerConsumer::Lock l(pc); return container.size(); } - - /** True if queue is empty */ - bool empty() { ProducerConsumer::Lock l(pc); return container.empty(); } - - private: - ProducerConsumer pc; - ContainerType container; -}; - -}} // namespace qpid::sys - - - -#endif /*!_sys_ThreadSafeQueue_h*/ diff --git a/qpid/cpp/lib/common/sys/Time.cpp b/qpid/cpp/lib/common/sys/Time.cpp deleted file mode 100644 index ad6185b966..0000000000 --- a/qpid/cpp/lib/common/sys/Time.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 "Time.h" - -namespace qpid { -namespace sys { - -// APR ================================================================ -#if USE_APR - -Time now() { return apr_time_now() * TIME_USEC; } - -// POSIX================================================================ -#else - -Time now() { - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - return toTime(ts); -} - -struct timespec toTimespec(const Time& t) { - struct timespec ts; - toTimespec(ts, t); - return ts; -} - -struct timespec& toTimespec(struct timespec& ts, const Time& t) { - ts.tv_sec = t / TIME_SEC; - ts.tv_nsec = t % TIME_SEC; - return ts; -} - -Time toTime(const struct timespec& ts) { - return ts.tv_sec*TIME_SEC + ts.tv_nsec; -} - - -#endif -}} - diff --git a/qpid/cpp/lib/common/sys/Time.h b/qpid/cpp/lib/common/sys/Time.h deleted file mode 100644 index 3dd46741d8..0000000000 --- a/qpid/cpp/lib/common/sys/Time.h +++ /dev/null @@ -1,58 +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 - -#ifdef USE_APR -# include -#else -# include -#endif - -namespace qpid { -namespace sys { - -/** Time in nanoseconds */ -typedef int64_t Time; - -Time now(); - -/** Nanoseconds per second. */ -const Time TIME_SEC = 1000*1000*1000; -/** Nanoseconds per millisecond */ -const Time TIME_MSEC = 1000*1000; -/** Nanoseconds per microseconds. */ -const Time TIME_USEC = 1000; -/** Nanoseconds per nanosecond. */ -const Time TIME_NSEC = 1; - -#ifndef USE_APR -struct timespec toTimespec(const Time& t); -struct timespec& toTimespec(struct timespec& ts, const Time& t); -Time toTime(const struct timespec& ts); -#endif - -}} - -#endif /*!_sys_Time_h*/ diff --git a/qpid/cpp/lib/common/sys/TimeoutHandler.h b/qpid/cpp/lib/common/sys/TimeoutHandler.h deleted file mode 100644 index 0c10709bbf..0000000000 --- a/qpid/cpp/lib/common/sys/TimeoutHandler.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 _TimeoutHandler_ -#define _TimeoutHandler_ - -namespace qpid { -namespace sys { - - class TimeoutHandler - { - public: - virtual void idleOut() = 0; - virtual void idleIn() = 0; - virtual ~TimeoutHandler(){} - }; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/sys/apr/APRAcceptor.cpp b/qpid/cpp/lib/common/sys/apr/APRAcceptor.cpp deleted file mode 100644 index 604fb9f5ca..0000000000 --- a/qpid/cpp/lib/common/sys/apr/APRAcceptor.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 -#include -#include "LFProcessor.h" -#include "LFSessionContext.h" -#include "APRBase.h" -#include "APRPool.h" - -namespace qpid { -namespace sys { - -class APRAcceptor : public Acceptor -{ - public: - APRAcceptor(int16_t port, int backlog, int threads, bool trace); - virtual uint16_t getPort() const; - virtual void run(qpid::sys::ConnectionInputHandlerFactory* factory); - virtual void shutdown(); - - private: - void shutdownImpl(); - - private: - int16_t port; - bool trace; - LFProcessor processor; - apr_socket_t* socket; - volatile bool running; - Mutex shutdownLock; -}; - -// Define generic Acceptor::create() to return APRAcceptor. -Acceptor::shared_ptr Acceptor::create(int16_t port, int backlog, int threads, bool trace) -{ - return Acceptor::shared_ptr(new APRAcceptor(port, backlog, threads, trace)); -} -// Must define Acceptor virtual dtor. -Acceptor::~Acceptor() {} - -APRAcceptor::APRAcceptor(int16_t port_, int backlog, int threads, bool trace_) : - port(port_), - trace(trace_), - processor(APRPool::get(), threads, 1000, 5000000), - running(false) -{ - apr_sockaddr_t* address; - CHECK_APR_SUCCESS(apr_sockaddr_info_get(&address, APR_ANYADDR, APR_UNSPEC, port, APR_IPV4_ADDR_OK, APRPool::get())); - CHECK_APR_SUCCESS(apr_socket_create(&socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, APRPool::get())); - CHECK_APR_SUCCESS(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1)); - CHECK_APR_SUCCESS(apr_socket_bind(socket, address)); - CHECK_APR_SUCCESS(apr_socket_listen(socket, backlog)); -} - -uint16_t APRAcceptor::getPort() const { - apr_sockaddr_t* address; - CHECK_APR_SUCCESS(apr_socket_addr_get(&address, APR_LOCAL, socket)); - return address->port; -} - -void APRAcceptor::run(ConnectionInputHandlerFactory* factory) { - running = true; - processor.start(); - std::cout << "Listening on port " << getPort() << "..." << std::endl; - while(running) { - apr_socket_t* client; - apr_status_t status = apr_socket_accept(&client, socket, APRPool::get()); - if(status == APR_SUCCESS){ - //make this socket non-blocking: - CHECK_APR_SUCCESS(apr_socket_timeout_set(client, 0)); - CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_SO_NONBLOCK, 1)); - CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_TCP_NODELAY, 1)); - CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_SO_SNDBUF, 32768)); - CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_SO_RCVBUF, 32768)); - LFSessionContext* session = new LFSessionContext(APRPool::get(), client, &processor, trace); - session->init(factory->create(session)); - }else{ - Mutex::ScopedLock locker(shutdownLock); - if(running) { - if(status != APR_EINTR){ - std::cout << "ERROR: " << get_desc(status) << std::endl; - } - shutdownImpl(); - } - } - } -} - -void APRAcceptor::shutdown() { - Mutex::ScopedLock locker(shutdownLock); - if (running) - shutdownImpl(); -} - -void APRAcceptor::shutdownImpl() { - running = false; - processor.stop(); - CHECK_APR_SUCCESS(apr_socket_close(socket)); -} - - -}} diff --git a/qpid/cpp/lib/common/sys/apr/APRBase.cpp b/qpid/cpp/lib/common/sys/apr/APRBase.cpp deleted file mode 100644 index 861071499f..0000000000 --- a/qpid/cpp/lib/common/sys/apr/APRBase.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 -#include -#include "APRBase.h" - -using namespace qpid::sys; - -APRBase* APRBase::instance = 0; - -APRBase* APRBase::getInstance(){ - if(instance == 0){ - instance = new APRBase(); - } - return instance; -} - - -APRBase::APRBase() : count(0){ - apr_initialize(); - CHECK_APR_SUCCESS(apr_pool_create(&pool, 0)); - CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, pool)); -} - -APRBase::~APRBase(){ - CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); - apr_pool_destroy(pool); - apr_terminate(); -} - -bool APRBase::_increment(){ - bool deleted(false); - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); - if(this == instance){ - count++; - }else{ - deleted = true; - } - CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); - return !deleted; -} - -void APRBase::_decrement(){ - APRBase* copy = 0; - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); - if(--count == 0){ - copy = instance; - instance = 0; - } - CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); - if(copy != 0){ - delete copy; - } -} - -void APRBase::increment(){ - int count = 0; - while(count++ < 2 && !getInstance()->_increment()){ - std::cout << "WARNING: APR initialization triggered concurrently with termination." << std::endl; - } -} - -void APRBase::decrement(){ - getInstance()->_decrement(); -} - -std::string qpid::sys::get_desc(apr_status_t status){ - const int size = 50; - char tmp[size]; - return std::string(apr_strerror(status, tmp, size)); -} - diff --git a/qpid/cpp/lib/common/sys/apr/APRBase.h b/qpid/cpp/lib/common/sys/apr/APRBase.h deleted file mode 100644 index 6a866a554a..0000000000 --- a/qpid/cpp/lib/common/sys/apr/APRBase.h +++ /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. - * - */ -#ifndef _APRBase_ -#define _APRBase_ - -#include -#include -#include -#include - -namespace qpid { -namespace sys { - - /** - * Use of APR libraries necessitates explicit init and terminate - * calls. Any class using APR libs should obtain the reference to - * this singleton and increment on construction, decrement on - * destruction. This class can then correctly initialise apr - * before the first use and terminate after the last use. - */ - class APRBase{ - static APRBase* instance; - apr_pool_t* pool; - apr_thread_mutex_t* mutex; - int count; - - APRBase(); - ~APRBase(); - static APRBase* getInstance(); - bool _increment(); - void _decrement(); - public: - static void increment(); - static void decrement(); - }; - - //this is also a convenient place for a helper function for error checking: - void check(apr_status_t status, const char* file, const int line); - std::string get_desc(apr_status_t status); - -#define CHECK_APR_SUCCESS(A) qpid::sys::check(A, __FILE__, __LINE__); - -} -} - -// Inlined as it is called *a lot* -void inline qpid::sys::check(apr_status_t status, const char* file, const int line){ - if (status != APR_SUCCESS){ - const int size = 50; - char tmp[size]; - std::string msg(apr_strerror(status, tmp, size)); - throw qpid::QpidError(APR_ERROR + ((int) status), msg, - qpid::SrcLine(file, line)); - } -} - - - - -#endif diff --git a/qpid/cpp/lib/common/sys/apr/APRPool.cpp b/qpid/cpp/lib/common/sys/apr/APRPool.cpp deleted file mode 100644 index e8b71f6e8a..0000000000 --- a/qpid/cpp/lib/common/sys/apr/APRPool.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 "APRPool.h" -#include "APRBase.h" -#include - -using namespace qpid::sys; - -APRPool::APRPool(){ - APRBase::increment(); - CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); -} - -APRPool::~APRPool(){ - apr_pool_destroy(pool); - APRBase::decrement(); -} - -apr_pool_t* APRPool::get() { - return boost::details::pool::singleton_default::instance().pool; -} - diff --git a/qpid/cpp/lib/common/sys/apr/APRPool.h b/qpid/cpp/lib/common/sys/apr/APRPool.h deleted file mode 100644 index da7661fcfa..0000000000 --- a/qpid/cpp/lib/common/sys/apr/APRPool.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _APRPool_ -#define _APRPool_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 { -/** - * Singleton APR memory pool. - */ -class APRPool : private boost::noncopyable { - public: - APRPool(); - ~APRPool(); - - /** Get singleton instance */ - static apr_pool_t* get(); - - private: - apr_pool_t* pool; -}; - -}} - - - - - -#endif /*!_APRPool_*/ diff --git a/qpid/cpp/lib/common/sys/apr/APRSocket.cpp b/qpid/cpp/lib/common/sys/apr/APRSocket.cpp deleted file mode 100644 index 96dbd132a1..0000000000 --- a/qpid/cpp/lib/common/sys/apr/APRSocket.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 "APRBase.h" -#include "APRSocket.h" -#include -#include - -using namespace qpid::sys; -using namespace qpid::framing; - -APRSocket::APRSocket(apr_socket_t* _socket) : socket(_socket), closed(false){ - -} - -void APRSocket::read(qpid::framing::Buffer& buffer){ - apr_size_t bytes; - bytes = buffer.available(); - apr_status_t s = apr_socket_recv(socket, buffer.start(), &bytes); - buffer.move(bytes); - if(APR_STATUS_IS_TIMEUP(s)){ - //timed out - }else if(APR_STATUS_IS_EOF(s)){ - close(); - } -} - -void APRSocket::write(qpid::framing::Buffer& buffer){ - apr_size_t bytes; - do{ - bytes = buffer.available(); - apr_socket_send(socket, buffer.start(), &bytes); - buffer.move(bytes); - }while(bytes > 0); -} - -void APRSocket::close(){ - if(!closed){ - std::cout << "Closing socket " << socket << "@" << this << std::endl; - CHECK_APR_SUCCESS(apr_socket_close(socket)); - closed = true; - } -} - -bool APRSocket::isOpen() const { - return !closed; -} - -uint8_t APRSocket::read(){ - char data[1]; - apr_size_t bytes = 1; - apr_status_t s = apr_socket_recv(socket, data, &bytes); - if(APR_STATUS_IS_EOF(s) || bytes == 0){ - return 0; - }else{ - return *data; - } -} - -APRSocket::~APRSocket(){ -} diff --git a/qpid/cpp/lib/common/sys/apr/APRSocket.h b/qpid/cpp/lib/common/sys/apr/APRSocket.h deleted file mode 100644 index a55dfc06b0..0000000000 --- a/qpid/cpp/lib/common/sys/apr/APRSocket.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. - * - */ -#ifndef _APRSocket_ -#define _APRSocket_ - -#include -#include - -namespace qpid { -namespace sys { - - class APRSocket - { - apr_socket_t* const socket; - volatile bool closed; - public: - APRSocket(apr_socket_t* socket); - void read(qpid::framing::Buffer& b); - void write(qpid::framing::Buffer& b); - void close(); - bool isOpen() const; - uint8_t read(); - ~APRSocket(); - }; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/sys/apr/LFProcessor.cpp b/qpid/cpp/lib/common/sys/apr/LFProcessor.cpp deleted file mode 100644 index 2b6fc92623..0000000000 --- a/qpid/cpp/lib/common/sys/apr/LFProcessor.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 -#include -#include "LFProcessor.h" -#include "APRBase.h" -#include "LFSessionContext.h" - -using namespace qpid::sys; -using qpid::QpidError; - -// TODO aconway 2006-10-12: stopped is read outside locks. -// - -LFProcessor::LFProcessor(apr_pool_t* pool, int _workers, int _size, int _timeout) : - size(_size), - timeout(_timeout), - signalledCount(0), - current(0), - count(0), - workerCount(_workers), - hasLeader(false), - workers(new Thread[_workers]), - stopped(false) -{ - - CHECK_APR_SUCCESS(apr_pollset_create(&pollset, size, pool, APR_POLLSET_THREADSAFE)); -} - - -LFProcessor::~LFProcessor(){ - if (!stopped) stop(); - delete[] workers; - CHECK_APR_SUCCESS(apr_pollset_destroy(pollset)); -} - -void LFProcessor::start(){ - for(int i = 0; i < workerCount; i++){ - workers[i] = Thread(this); - } -} - -void LFProcessor::add(const apr_pollfd_t* const fd){ - CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd)); - Monitor::ScopedLock l(countLock); - sessions.push_back(reinterpret_cast(fd->client_data)); - count++; -} - -void LFProcessor::remove(const apr_pollfd_t* const fd){ - CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd)); - Monitor::ScopedLock l(countLock); - sessions.erase(find(sessions.begin(), sessions.end(), reinterpret_cast(fd->client_data))); - count--; -} - -void LFProcessor::reactivate(const apr_pollfd_t* const fd){ - CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd)); -} - -void LFProcessor::deactivate(const apr_pollfd_t* const fd){ - CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd)); -} - -void LFProcessor::update(const apr_pollfd_t* const fd){ - CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd)); - CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd)); -} - -bool LFProcessor::full(){ - Mutex::ScopedLock locker(countLock); - return count == size; -} - -bool LFProcessor::empty(){ - Mutex::ScopedLock locker(countLock); - return count == 0; -} - -void LFProcessor::poll() { - apr_status_t status = APR_EGENERAL; - do{ - current = 0; - if(!stopped){ - status = apr_pollset_poll(pollset, timeout, &signalledCount, &signalledFDs); - } - }while(status != APR_SUCCESS && !stopped); -} - -void LFProcessor::run(){ - try{ - while(!stopped){ - const apr_pollfd_t* event = 0; - LFSessionContext* session = 0; - { - Monitor::ScopedLock l(leadLock); - waitToLead(); - event = getNextEvent(); - if(!event) return; - session = reinterpret_cast( - event->client_data); - session->startProcessing(); - relinquishLead(); - } - - //process event: - if(event->rtnevents & APR_POLLIN) session->read(); - if(event->rtnevents & APR_POLLOUT) session->write(); - - if(session->isClosed()){ - session->handleClose(); - Monitor::ScopedLock l(countLock); - sessions.erase(find(sessions.begin(),sessions.end(), session)); - count--; - }else{ - session->stopProcessing(); - } - } - }catch(std::exception e){ - std::cout << e.what() << std::endl; - } -} - -void LFProcessor::waitToLead(){ - while(hasLeader && !stopped) leadLock.wait(); - hasLeader = !stopped; -} - -void LFProcessor::relinquishLead(){ - hasLeader = false; - leadLock.notify(); -} - -const apr_pollfd_t* LFProcessor::getNextEvent(){ - while(true){ - if(stopped){ - return 0; - }else if(current < signalledCount){ - //use result of previous poll if one is available - return signalledFDs + (current++); - }else{ - //else poll to get new events - poll(); - } - } -} - -void LFProcessor::stop(){ - stopped = true; - { - Monitor::ScopedLock l(leadLock); - leadLock.notifyAll(); - } - for(int i = 0; i < workerCount; i++){ - workers[i].join(); - } - for(iterator i = sessions.begin(); i < sessions.end(); i++){ - (*i)->shutdown(); - } -} - diff --git a/qpid/cpp/lib/common/sys/apr/LFProcessor.h b/qpid/cpp/lib/common/sys/apr/LFProcessor.h deleted file mode 100644 index de90199472..0000000000 --- a/qpid/cpp/lib/common/sys/apr/LFProcessor.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 _LFProcessor_ -#define _LFProcessor_ - -#include -#include -#include -#include -#include -#include - -namespace qpid { -namespace sys { - - class LFSessionContext; - - /** - * This class processes a poll set using the leaders-followers - * pattern for thread synchronization: the leader will poll and on - * the poll returning, it will remove a session, promote a - * follower to leadership, then process the session. - */ - class LFProcessor : private virtual qpid::sys::Runnable - { - typedef std::vector::iterator iterator; - - const int size; - const apr_interval_time_t timeout; - apr_pollset_t* pollset; - int signalledCount; - int current; - const apr_pollfd_t* signalledFDs; - int count; - const int workerCount; - bool hasLeader; - qpid::sys::Thread* workers; - qpid::sys::Monitor leadLock; - qpid::sys::Mutex countLock; - std::vector sessions; - volatile bool stopped; - - const apr_pollfd_t* getNextEvent(); - void waitToLead(); - void relinquishLead(); - void poll(); - virtual void run(); - - public: - LFProcessor(apr_pool_t* pool, int workers, int size, int timeout); - /** - * Add the fd to the poll set. Relies on the client_data being - * an instance of LFSessionContext. - */ - void add(const apr_pollfd_t* const fd); - /** - * Remove the fd from the poll set. - */ - void remove(const apr_pollfd_t* const fd); - /** - * Signal that the fd passed in, already part of the pollset, - * has had its flags altered. - */ - void update(const apr_pollfd_t* const fd); - /** - * Add an fd back to the poll set after deactivation. - */ - void reactivate(const apr_pollfd_t* const fd); - /** - * Temporarily remove the fd from the poll set. Called when processing - * is about to begin. - */ - void deactivate(const apr_pollfd_t* const fd); - /** - * Indicates whether the capacity of this processor has been - * reached (or whether it can still handle further fd's). - */ - bool full(); - /** - * Indicates whether there are any fd's registered. - */ - bool empty(); - /** - * Stop processing. - */ - void stop(); - /** - * Start processing. - */ - void start(); - /** - * Is processing stopped? - */ - bool isStopped(); - - ~LFProcessor(); - }; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/sys/apr/LFSessionContext.cpp b/qpid/cpp/lib/common/sys/apr/LFSessionContext.cpp deleted file mode 100644 index 5edb72baee..0000000000 --- a/qpid/cpp/lib/common/sys/apr/LFSessionContext.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 "LFSessionContext.h" -#include "APRBase.h" -#include -#include - -using namespace qpid::sys; -using namespace qpid::sys; -using namespace qpid::framing; - -LFSessionContext::LFSessionContext(apr_pool_t* _pool, apr_socket_t* _socket, - LFProcessor* const _processor, - bool _debug) : - debug(_debug), - socket(_socket), - initiated(false), - in(65536), - out(65536), - processor(_processor), - processing(false), - closing(false) -{ - - fd.p = _pool; - fd.desc_type = APR_POLL_SOCKET; - fd.reqevents = APR_POLLIN; - fd.client_data = this; - fd.desc.s = _socket; - - out.flip(); -} - -LFSessionContext::~LFSessionContext(){ - -} - -void LFSessionContext::read(){ - socket.read(in); - in.flip(); - if(initiated){ - AMQFrame frame; - try{ - while(frame.decode(in)){ - if(debug) log("RECV", &frame); - handler->received(&frame); - } - }catch(QpidError error){ - std::cout << "Error [" << error.code << "] " << error.msg - << " (" << error.loc.file << ":" << error.loc.line - << ")" << std::endl; - } - }else{ - ProtocolInitiation protocolInit; - if(protocolInit.decode(in)){ - handler->initiated(protocolInit); - initiated = true; - if(debug) std::cout << "INIT [" << &socket << "]" << std::endl; - } - } - in.compact(); -} - -void LFSessionContext::write(){ - bool done = isClosed(); - while(!done){ - if(out.available() > 0){ - socket.write(out); - if(out.available() > 0){ - - //incomplete write, leave flags to receive notification of readiness to write - done = true;//finished processing for now, but write is still in progress - } - }else{ - //do we have any frames to write? - Mutex::ScopedLock l(writeLock); - if(!framesToWrite.empty()){ - out.clear(); - bool encoded(false); - AMQFrame* frame = framesToWrite.front(); - while(frame && out.available() >= frame->size()){ - encoded = true; - frame->encode(out); - if(debug) log("SENT", frame); - delete frame; - framesToWrite.pop(); - frame = framesToWrite.empty() ? 0 : framesToWrite.front(); - } - if(!encoded) THROW_QPID_ERROR(FRAMING_ERROR, "Could not write frame, too large for buffer."); - out.flip(); - }else{ - //reset flags, don't care about writability anymore - fd.reqevents = APR_POLLIN; - done = true; - - if(closing){ - socket.close(); - } - } - } - } -} - -void LFSessionContext::send(AMQFrame* frame){ - Mutex::ScopedLock l(writeLock); - if(!closing){ - framesToWrite.push(frame); - if(!(fd.reqevents & APR_POLLOUT)){ - fd.reqevents |= APR_POLLOUT; - if(!processing){ - processor->update(&fd); - } - } - } -} - -void LFSessionContext::startProcessing(){ - Mutex::ScopedLock l(writeLock); - processing = true; - processor->deactivate(&fd); -} - -void LFSessionContext::stopProcessing(){ - Mutex::ScopedLock l(writeLock); - processor->reactivate(&fd); - processing = false; -} - -void LFSessionContext::close(){ - Mutex::ScopedLock l(writeLock); - closing = true; - if(!processing){ - //allow pending frames to be written to socket - fd.reqevents = APR_POLLOUT; - processor->update(&fd); - } -} - -void LFSessionContext::handleClose(){ - handler->closed(); - std::cout << "Session closed [" << &socket << "]" << std::endl; - delete handler; - delete this; -} - -void LFSessionContext::shutdown(){ - socket.close(); - handleClose(); -} - -void LFSessionContext::init(ConnectionInputHandler* _handler){ - handler = _handler; - processor->add(&fd); -} - -void LFSessionContext::log(const std::string& desc, AMQFrame* const frame){ - Mutex::ScopedLock l(logLock); - std::cout << desc << " [" << &socket << "]: " << *frame << std::endl; -} - -Mutex LFSessionContext::logLock; diff --git a/qpid/cpp/lib/common/sys/apr/LFSessionContext.h b/qpid/cpp/lib/common/sys/apr/LFSessionContext.h deleted file mode 100644 index 81cfc0efda..0000000000 --- a/qpid/cpp/lib/common/sys/apr/LFSessionContext.h +++ /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. - * - */ -#ifndef _LFSessionContext_ -#define _LFSessionContext_ - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "APRSocket.h" -#include "LFProcessor.h" - -namespace qpid { -namespace sys { - - -class LFSessionContext : public virtual qpid::sys::ConnectionOutputHandler -{ - const bool debug; - APRSocket socket; - bool initiated; - - qpid::framing::Buffer in; - qpid::framing::Buffer out; - - qpid::sys::ConnectionInputHandler* handler; - LFProcessor* const processor; - - apr_pollfd_t fd; - - std::queue framesToWrite; - qpid::sys::Mutex writeLock; - - bool processing; - bool closing; - - static qpid::sys::Mutex logLock; - void log(const std::string& desc, - qpid::framing::AMQFrame* const frame); - - - public: - LFSessionContext(apr_pool_t* pool, apr_socket_t* socket, - LFProcessor* const processor, - bool debug = false); - virtual ~LFSessionContext(); - virtual void send(qpid::framing::AMQFrame* frame); - virtual void close(); - void read(); - void write(); - void init(qpid::sys::ConnectionInputHandler* handler); - void startProcessing(); - void stopProcessing(); - void handleClose(); - void shutdown(); - inline apr_pollfd_t* const getFd(){ return &fd; } - inline bool isClosed(){ return !socket.isOpen(); } -}; - -} -} - - -#endif diff --git a/qpid/cpp/lib/common/sys/apr/Socket.cpp b/qpid/cpp/lib/common/sys/apr/Socket.cpp deleted file mode 100644 index bca4da6c96..0000000000 --- a/qpid/cpp/lib/common/sys/apr/Socket.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 - - -using namespace qpid::sys; - -Socket Socket::createTcp() { - Socket s; - CHECK_APR_SUCCESS( - apr_socket_create( - &s.socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, - APRPool::get())); - return s; -} - -Socket::Socket(apr_socket_t* s) { - socket = s; -} - -void Socket::setTimeout(Time interval) { - apr_socket_timeout_set(socket, interval/TIME_USEC); -} - -void Socket::connect(const std::string& host, int port) { - apr_sockaddr_t* address; - CHECK_APR_SUCCESS( - apr_sockaddr_info_get( - &address, host.c_str(), APR_UNSPEC, port, APR_IPV4_ADDR_OK, - APRPool::get())); - CHECK_APR_SUCCESS(apr_socket_connect(socket, address)); -} - -void Socket::close() { - if (socket == 0) return; - CHECK_APR_SUCCESS(apr_socket_close(socket)); - socket = 0; -} - -ssize_t Socket::send(const void* data, size_t size) -{ - apr_size_t sent = size; - apr_status_t status = - apr_socket_send(socket, reinterpret_cast(data), &sent); - if (APR_STATUS_IS_TIMEUP(status)) return SOCKET_TIMEOUT; - if (APR_STATUS_IS_EOF(status)) return SOCKET_EOF; - CHECK_APR_SUCCESS(status); - return sent; -} - -ssize_t Socket::recv(void* data, size_t size) -{ - apr_size_t received = size; - apr_status_t status = - apr_socket_recv(socket, reinterpret_cast(data), &received); - if (APR_STATUS_IS_TIMEUP(status)) - return SOCKET_TIMEOUT; - if (APR_STATUS_IS_EOF(status)) - return SOCKET_EOF; - CHECK_APR_SUCCESS(status); - return received; -} - - diff --git a/qpid/cpp/lib/common/sys/apr/Thread.cpp b/qpid/cpp/lib/common/sys/apr/Thread.cpp deleted file mode 100644 index 5c4799aa96..0000000000 --- a/qpid/cpp/lib/common/sys/apr/Thread.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 - -using namespace qpid::sys; -using qpid::sys::Runnable; - -void* APR_THREAD_FUNC Thread::runRunnable(apr_thread_t* thread, void *data) { - reinterpret_cast(data)->run(); - CHECK_APR_SUCCESS(apr_thread_exit(thread, APR_SUCCESS)); - return NULL; -} - - diff --git a/qpid/cpp/lib/common/sys/posix/EventChannel.cpp b/qpid/cpp/lib/common/sys/posix/EventChannel.cpp deleted file mode 100644 index 16c7ec9c3f..0000000000 --- a/qpid/cpp/lib/common/sys/posix/EventChannel.cpp +++ /dev/null @@ -1,325 +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 - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include "check.h" -#include "EventChannel.h" - -using namespace std; - - -// Convenience template to zero out a struct. -template struct ZeroStruct : public S { - ZeroStruct() { memset(this, 0, sizeof(*this)); } -}; - -namespace qpid { -namespace sys { - - -/** - * EventHandler wraps an epoll file descriptor. Acts as private - * interface between EventChannel and subclasses. - * - * Also implements Event interface for events that are not associated - * with a file descriptor and are passed via the message queue. - */ -class EventHandler : public Event, private Monitor -{ - public: - EventHandler(int epollSize = 256); - ~EventHandler(); - - int getEpollFd() { return epollFd; } - void epollAdd(int fd, uint32_t epollEvents, Event* event); - void epollMod(int fd, uint32_t epollEvents, Event* event); - void epollDel(int fd); - - void mqPut(Event* event); - Event* mqGet(); - - protected: - // Should never be called, only complete. - void prepare(EventHandler&) { assert(0); } - Event* complete(EventHandler& eh); - - private: - int epollFd; - std::string mqName; - int mqFd; - std::queue mqEvents; -}; - -EventHandler::EventHandler(int epollSize) -{ - epollFd = epoll_create(epollSize); - if (epollFd < 0) throw QPID_POSIX_ERROR(errno); - - // Create a POSIX message queue for non-fd events. - // We write one byte and never read it is always ready for read - // when we add it to epoll. - // - ZeroStruct attr; - attr.mq_maxmsg = 1; - attr.mq_msgsize = 1; - do { - char tmpnam[L_tmpnam]; - tmpnam_r(tmpnam); - mqName = tmpnam + 4; // Skip "tmp/" - mqFd = mq_open( - mqName.c_str(), O_CREAT|O_EXCL|O_RDWR|O_NONBLOCK, S_IRWXU, &attr); - if (mqFd < 0) throw QPID_POSIX_ERROR(errno); - } while (mqFd == EEXIST); // Name already taken, try again. - - static char zero = '\0'; - mq_send(mqFd, &zero, 1, 0); - epollAdd(mqFd, 0, this); -} - -EventHandler::~EventHandler() { - mq_close(mqFd); - mq_unlink(mqName.c_str()); -} - -void EventHandler::mqPut(Event* event) { - ScopedLock l(*this); - assert(event != 0); - mqEvents.push(event); - epollMod(mqFd, EPOLLIN|EPOLLONESHOT, this); -} - -Event* EventHandler::mqGet() { - ScopedLock l(*this); - if (mqEvents.empty()) - return 0; - Event* event = mqEvents.front(); - mqEvents.pop(); - if(!mqEvents.empty()) - epollMod(mqFd, EPOLLIN|EPOLLONESHOT, this); - return event; -} - -void EventHandler::epollAdd(int fd, uint32_t epollEvents, Event* event) -{ - ZeroStruct ee; - ee.data.ptr = event; - ee.events = epollEvents; - if (epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &ee) < 0) - throw QPID_POSIX_ERROR(errno); -} - -void EventHandler::epollMod(int fd, uint32_t epollEvents, Event* event) -{ - ZeroStruct ee; - ee.data.ptr = event; - ee.events = epollEvents; - if (epoll_ctl(epollFd, EPOLL_CTL_MOD, fd, &ee) < 0) - throw QPID_POSIX_ERROR(errno); -} - -void EventHandler::epollDel(int fd) { - if (epoll_ctl(epollFd, EPOLL_CTL_DEL, fd, 0) < 0) - throw QPID_POSIX_ERROR(errno); -} - -Event* EventHandler::complete(EventHandler& eh) -{ - assert(&eh == this); - Event* event = mqGet(); - return event==0 ? 0 : event->complete(eh); -} - -// ================================================================ -// EventChannel - -EventChannel::shared_ptr EventChannel::create() { - return shared_ptr(new EventChannel()); -} - -EventChannel::EventChannel() : handler(new EventHandler()) {} - -EventChannel::~EventChannel() {} - -void EventChannel::postEvent(Event& e) -{ - e.prepare(*handler); -} - -Event* EventChannel::getEvent() -{ - static const int infiniteTimeout = -1; - ZeroStruct epollEvent; - - // Loop until we can complete the event. Some events may re-post - // themselves and return 0 from complete, e.g. partial reads. // - Event* event = 0; - while (event == 0) { - int eventCount = epoll_wait(handler->getEpollFd(), - &epollEvent, 1, infiniteTimeout); - if (eventCount < 0) { - if (errno != EINTR) { - // TODO aconway 2006-11-28: Proper handling/logging of errors. - cerr << BOOST_CURRENT_FUNCTION << " ignoring error " - << PosixError::getMessage(errno) << endl; - assert(0); - } - } - else if (eventCount == 1) { - event = reinterpret_cast(epollEvent.data.ptr); - assert(event != 0); - try { - event = event->complete(*handler); - } - catch (const Exception& e) { - if (event) - event->setError(e); - } - catch (const std::exception& e) { - if (event) - event->setError(e); - } - } - } - return event; -} - -Event::~Event() {} - -void Event::prepare(EventHandler& handler) -{ - handler.mqPut(this); -} - -bool Event::hasError() const { - return error; -} - -void Event::throwIfError() throw (Exception) { - if (hasError()) - error.throwSelf(); -} - -Event* Event::complete(EventHandler&) -{ - return this; -} - -void Event::dispatch() -{ - try { - if (!callback.empty()) - callback(); - } catch (const std::exception&) { - throw; - } catch (...) { - throw QPID_ERROR(INTERNAL_ERROR, "Unknown exception."); - } -} - -void Event::setError(const ExceptionHolder& e) { - error = e; -} - -void ReadEvent::prepare(EventHandler& handler) -{ - handler.epollAdd(descriptor, EPOLLIN | EPOLLONESHOT, this); -} - -ssize_t ReadEvent::doRead() { - ssize_t n = ::read(descriptor, static_cast(buffer) + received, - size - received); - if (n > 0) received += n; - return n; -} - -Event* ReadEvent::complete(EventHandler& handler) -{ - // Read as much as possible without blocking. - ssize_t n = doRead(); - while (n > 0 && received < size) doRead(); - - if (received == size) { - handler.epollDel(descriptor); - received = 0; // Reset for re-use. - return this; - } - else if (n <0 && (errno == EAGAIN)) { - // Keep polling for more. - handler.epollMod(descriptor, EPOLLIN | EPOLLONESHOT, this); - return 0; - } - else { - // Unexpected EOF or error. Throw ENODATA for EOF. - handler.epollDel(descriptor); - received = 0; // Reset for re-use. - throw QPID_POSIX_ERROR((n < 0) ? errno : ENODATA); - } -} - -void WriteEvent::prepare(EventHandler& handler) -{ - handler.epollAdd(descriptor, EPOLLOUT | EPOLLONESHOT, this); -} - -Event* WriteEvent::complete(EventHandler& handler) -{ - ssize_t n = write(descriptor, static_cast(buffer) + written, - size - written); - if (n < 0) throw QPID_POSIX_ERROR(errno); - written += n; - if(written < size) { - // Keep polling. - handler.epollMod(descriptor, EPOLLOUT | EPOLLONESHOT, this); - return 0; - } - written = 0; // Reset for re-use. - handler.epollDel(descriptor); - return this; -} - -void AcceptEvent::prepare(EventHandler& handler) -{ - handler.epollAdd(descriptor, EPOLLIN | EPOLLONESHOT, this); -} - -Event* AcceptEvent::complete(EventHandler& handler) -{ - handler.epollDel(descriptor); - accepted = ::accept(descriptor, 0, 0); - if (accepted < 0) throw QPID_POSIX_ERROR(errno); - return this; -} - -}} diff --git a/qpid/cpp/lib/common/sys/posix/EventChannel.h b/qpid/cpp/lib/common/sys/posix/EventChannel.h deleted file mode 100644 index 49c7fce740..0000000000 --- a/qpid/cpp/lib/common/sys/posix/EventChannel.h +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef _sys_EventChannel_h -#define _sys_EventChannel_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 -#include -#include - -namespace qpid { -namespace sys { - -class Event; -class EventHandler; -class EventChannel; - -/** - * Base class for all Events. - */ -class Event -{ - public: - /** Type for callback when event is dispatched */ - typedef boost::function0 Callback; - - /** - * Create an event with optional callback. - * Instances of Event are sent directly through the channel. - * Derived classes define additional waiting behaviour. - *@param cb A callback functor that is invoked when dispatch() is called. - */ - Event(Callback cb = 0) : callback(cb) {} - - virtual ~Event(); - - /** Call the callback provided to the constructor, if any. */ - void dispatch(); - - /** True if there was an error processing this event */ - bool hasError() const; - - /** If hasError() throw the corresponding exception. */ - void throwIfError() throw(Exception); - - protected: - virtual void prepare(EventHandler&); - virtual Event* complete(EventHandler&); - void setError(const ExceptionHolder& e); - - Callback callback; - ExceptionHolder error; - - friend class EventChannel; - friend class EventHandler; -}; - -template -class IOEvent : public Event { - public: - void getDescriptor() const { return descriptor; } - size_t getSize() const { return size; } - BufT getBuffer() const { return buffer; } - - protected: - IOEvent(int fd, Callback cb, size_t sz, BufT buf) : - Event(cb), descriptor(fd), buffer(buf), size(sz) {} - - int descriptor; - BufT buffer; - size_t size; -}; - -/** Asynchronous read event */ -class ReadEvent : public IOEvent -{ - public: - explicit ReadEvent(int fd=-1, void* buf=0, size_t sz=0, Callback cb=0) : - IOEvent(fd, cb, sz, buf), received(0) {} - - private: - void prepare(EventHandler&); - Event* complete(EventHandler&); - ssize_t doRead(); - - size_t received; -}; - -/** Asynchronous write event */ -class WriteEvent : public IOEvent -{ - public: - explicit WriteEvent(int fd=-1, const void* buf=0, size_t sz=0, - Callback cb=0) : - IOEvent(fd, cb, sz, buf), written(0) {} - - protected: - void prepare(EventHandler&); - Event* complete(EventHandler&); - - private: - ssize_t doWrite(); - size_t written; -}; - -/** Asynchronous socket accept event */ -class AcceptEvent : public Event -{ - public: - /** Accept a connection on fd. */ - explicit AcceptEvent(int fd=-1, Callback cb=0) : - Event(cb), descriptor(fd), accepted(0) {} - - /** Get descriptor for server socket */ - int getAcceptedDesscriptor() const { return accepted; } - - private: - void prepare(EventHandler&); - Event* complete(EventHandler&); - - int descriptor; - int accepted; -}; - - -class QueueSet; - -/** - * Channel to post and wait for events. - */ -class EventChannel : public qpid::SharedObject -{ - public: - static shared_ptr create(); - - ~EventChannel(); - - /** Post an event to the channel. */ - void postEvent(Event& event); - - /** Post an event to the channel. Must not be 0. */ - void postEvent(Event* event) { postEvent(*event); } - - /** - * Wait for the next complete event. - *@return Pointer to event. Will never return 0. - */ - Event* getEvent(); - - private: - EventChannel(); - boost::shared_ptr handler; -}; - - -}} - - - -#endif /*!_sys_EventChannel_h*/ diff --git a/qpid/cpp/lib/common/sys/posix/EventChannelAcceptor.cpp b/qpid/cpp/lib/common/sys/posix/EventChannelAcceptor.cpp deleted file mode 100644 index 548fbd1881..0000000000 --- a/qpid/cpp/lib/common/sys/posix/EventChannelAcceptor.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 - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "EventChannelConnection.h" - -namespace qpid { -namespace sys { - -using namespace qpid::framing; -using namespace std; - -class EventChannelAcceptor : public Acceptor { - public: - - - EventChannelAcceptor( - int16_t port_, int backlog, int nThreads, bool trace_ - ); - - int getPort() const; - - void run(ConnectionInputHandlerFactory& factory); - - void shutdown(); - - private: - - void accept(); - - Mutex lock; - Socket listener; - const int port; - const bool isTrace; - bool isRunning; - boost::ptr_vector connections; - AcceptEvent acceptEvent; - ConnectionInputHandlerFactory* factory; - bool isShutdown; - EventChannelThreads::shared_ptr threads; -}; - -Acceptor::shared_ptr Acceptor::create( - int16_t port, int backlog, int threads, bool trace) -{ - return Acceptor::shared_ptr( - new EventChannelAcceptor(port, backlog, threads, trace)); -} - -// Must define Acceptor virtual dtor. -Acceptor::~Acceptor() {} - -EventChannelAcceptor::EventChannelAcceptor( - int16_t port_, int backlog, int nThreads, bool trace_ -) : listener(Socket::createTcp()), - port(listener.listen(int(port_), backlog)), - isTrace(trace_), - isRunning(false), - acceptEvent(listener.fd(), - boost::bind(&EventChannelAcceptor::accept, this)), - factory(0), - isShutdown(false), - threads(EventChannelThreads::create(EventChannel::create(), nThreads)) -{ } - -int EventChannelAcceptor::getPort() const { - return port; // Immutable no need for lock. -} - -void EventChannelAcceptor::run(ConnectionInputHandlerFactory& f) { - { - Mutex::ScopedLock l(lock); - if (!isRunning && !isShutdown) { - isRunning = true; - factory = &f; - threads->post(acceptEvent); - } - } - threads->join(); // Wait for shutdown. -} - -void EventChannelAcceptor::shutdown() { - bool doShutdown = false; - { - Mutex::ScopedLock l(lock); - doShutdown = !isShutdown; // I'm the shutdown thread. - isShutdown = true; - } - if (doShutdown) { - ::close(acceptEvent.getDescriptor()); - threads->shutdown(); - for_each(connections.begin(), connections.end(), - boost::bind(&EventChannelConnection::close, _1)); - } - threads->join(); -} - -void EventChannelAcceptor::accept() -{ - // No lock, we only post one accept event at a time. - if (isShutdown) - return; - if (acceptEvent.getException()) { - Exception::log(*acceptEvent.getException(), - "EventChannelAcceptor::accept"); - shutdown(); - return; - } - // TODO aconway 2006-11-29: Need to reap closed connections also. - int fd = acceptEvent.getAcceptedDesscriptor(); - connections.push_back( - new EventChannelConnection(threads, *factory, fd, fd, isTrace)); - threads->post(acceptEvent); // Keep accepting. -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/lib/common/sys/posix/EventChannelConnection.cpp b/qpid/cpp/lib/common/sys/posix/EventChannelConnection.cpp deleted file mode 100644 index 4449dc3035..0000000000 --- a/qpid/cpp/lib/common/sys/posix/EventChannelConnection.cpp +++ /dev/null @@ -1,229 +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 - -#include "EventChannelConnection.h" -#include "sys/ConnectionInputHandlerFactory.h" -#include "QpidError.h" - -using namespace std; -using namespace qpid; -using namespace qpid::framing; - -namespace qpid { -namespace sys { - -const size_t EventChannelConnection::bufferSize = 65536; - -EventChannelConnection::EventChannelConnection( - EventChannelThreads::shared_ptr threads_, - ConnectionInputHandlerFactory& factory_, - int rfd, - int wfd, - bool isTrace_ -) : - readFd(rfd), - writeFd(wfd ? wfd : rfd), - readCallback(boost::bind(&EventChannelConnection::closeOnException, - this, &EventChannelConnection::endInitRead)), - - isWriting(false), - isClosed(false), - threads(threads_), - handler(factory_.create(this)), - in(bufferSize), - out(bufferSize), - isTrace(isTrace_) -{ - BOOST_ASSERT(readFd > 0); - BOOST_ASSERT(writeFd > 0); - closeOnException(&EventChannelConnection::startRead); -} - - -void EventChannelConnection::send(std::auto_ptr frame) { - { - Monitor::ScopedLock lock(monitor); - assert(frame.get()); - writeFrames.push_back(frame.release()); - } - closeOnException(&EventChannelConnection::startWrite); -} - -void EventChannelConnection::close() { - { - Monitor::ScopedLock lock(monitor); - if (isClosed) - return; - isClosed = true; - } - ::close(readFd); - ::close(writeFd); - { - Monitor::ScopedLock lock(monitor); - while (busyThreads > 0) - monitor.wait(); - } - handler->closed(); -} - -void EventChannelConnection::closeNoThrow() { - Exception::tryCatchLog( - boost::bind(&EventChannelConnection::close, this), - false, - "Exception closing channel" - ); -} - -/** - * Call f in a try/catch block and close the connection if - * an exception is thrown. - */ -void EventChannelConnection::closeOnException(MemberFnPtr f) -{ - try { - Exception::tryCatchLog( - boost::bind(f, this), - "Closing connection due to exception" - ); - return; - } catch (...) { - // Exception was already logged by tryCatchLog - closeNoThrow(); - } -} - -// Post the write event. -// Always called inside closeOnException. -// Called by endWrite and send, but only one thread writes at a time. -// -void EventChannelConnection::startWrite() { - FrameQueue::auto_type frame; - { - Monitor::ScopedLock lock(monitor); - // Stop if closed or a write event is already in progress. - if (isClosed || isWriting) - return; - if (writeFrames.empty()) { - isWriting = false; - return; - } - isWriting = true; - frame = writeFrames.pop_front(); - } - // No need to lock here - only one thread can be writing at a time. - out.clear(); - if (isTrace) - cout << "Send on socket " << writeFd << ": " << *frame << endl; - frame->encode(out); - out.flip(); - writeEvent = WriteEvent( - writeFd, out.start(), out.available(), - boost::bind(&EventChannelConnection::closeOnException, - this, &EventChannelConnection::endWrite)); - threads->post(writeEvent); -} - -// ScopedBusy ctor increments busyThreads. -// dtor decrements and calls monitor.notifyAll if it reaches 0. -// -struct EventChannelConnection::ScopedBusy : public AtomicCount::ScopedIncrement -{ - ScopedBusy(EventChannelConnection& ecc) - : AtomicCount::ScopedIncrement( - ecc.busyThreads, boost::bind(&Monitor::notifyAll, &ecc.monitor)) - {} -}; - -// Write event completed. -// Always called by a channel thread inside closeOnException. -// -void EventChannelConnection::endWrite() { - ScopedBusy(*this); - { - Monitor::ScopedLock lock(monitor); - isWriting = false; - if (isClosed) - return; - writeEvent.throwIfException(); - } - // Check if there's more in to write in the write queue. - startWrite(); -} - - -// Post the read event. -// Always called inside closeOnException. -// Called from ctor and end[Init]Read, so only one call at a time -// is possible since we only post one read event at a time. -// -void EventChannelConnection::startRead() { - // Non blocking read, as much as we can swallow. - readEvent = ReadEvent( - readFd, in.start(), in.available(), readCallback,true); - threads->post(readEvent); -} - -// Completion of initial read, expect protocolInit. -// Always called inside closeOnException in channel thread. -// Only called by one thread at a time. -void EventChannelConnection::endInitRead() { - ScopedBusy(*this); - if (!isClosed) { - readEvent.throwIfException(); - in.move(readEvent.getBytesRead()); - in.flip(); - ProtocolInitiation protocolInit; - if(protocolInit.decode(in)){ - handler->initiated(&protocolInit); - readCallback = boost::bind( - &EventChannelConnection::closeOnException, - this, &EventChannelConnection::endRead); - } - in.compact(); - // Continue reading. - startRead(); - } -} - -// Normal reads, expect a frame. -// Always called inside closeOnException in channel thread. -void EventChannelConnection::endRead() { - ScopedBusy(*this); - if (!isClosed) { - readEvent.throwIfException(); - in.move(readEvent.getBytesRead()); - in.flip(); - AMQFrame frame; - while (frame.decode(in)) { - // TODO aconway 2006-11-30: received should take Frame& - if (isTrace) - cout << "Received on socket " << readFd - << ": " << frame << endl; - handler->received(&frame); - } - in.compact(); - startRead(); - } -} - -}} // namespace qpid::sys diff --git a/qpid/cpp/lib/common/sys/posix/EventChannelConnection.h b/qpid/cpp/lib/common/sys/posix/EventChannelConnection.h deleted file mode 100644 index da7b6dca27..0000000000 --- a/qpid/cpp/lib/common/sys/posix/EventChannelConnection.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef _posix_EventChannelConnection_h -#define _posix_EventChannelConnection_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 "EventChannelThreads.h" -#include "sys/Monitor.h" -#include "sys/ConnectionOutputHandler.h" -#include "sys/ConnectionInputHandler.h" -#include "sys/AtomicCount.h" -#include "framing/AMQFrame.h" - -namespace qpid { -namespace sys { - -class ConnectionInputHandlerFactory; - -/** - * Implements ConnectionOutputHandler and delegates to a ConnectionInputHandler - * for a connection via the EventChannel. - *@param readDescriptor file descriptor for reading. - *@param writeDescriptor file descriptor for writing, - * by default same as readDescriptor - */ -class EventChannelConnection : public ConnectionOutputHandler { - public: - EventChannelConnection( - EventChannelThreads::shared_ptr threads, - ConnectionInputHandlerFactory& factory, - int readDescriptor, - int writeDescriptor = 0, - bool isTrace = false - ); - - // TODO aconway 2006-11-30: ConnectionOutputHandler::send should take auto_ptr - virtual void send(qpid::framing::AMQFrame* frame) { - send(std::auto_ptr(frame)); - } - - virtual void send(std::auto_ptr frame); - - virtual void close(); - - private: - typedef boost::ptr_deque FrameQueue; - typedef void (EventChannelConnection::*MemberFnPtr)(); - struct ScopedBusy; - - void startWrite(); - void endWrite(); - void startRead(); - void endInitRead(); - void endRead(); - void closeNoThrow(); - void closeOnException(MemberFnPtr); - bool shouldContinue(bool& flag); - - static const size_t bufferSize; - - Monitor monitor; - - int readFd, writeFd; - ReadEvent readEvent; - WriteEvent writeEvent; - Event::Callback readCallback; - bool isWriting; - bool isClosed; - AtomicCount busyThreads; - - EventChannelThreads::shared_ptr threads; - std::auto_ptr handler; - qpid::framing::Buffer in, out; - FrameQueue writeFrames; - bool isTrace; - - friend struct ScopedBusy; -}; - - -}} // namespace qpid::sys - - - -#endif /*!_posix_EventChannelConnection_h*/ diff --git a/qpid/cpp/lib/common/sys/posix/EventChannelThreads.cpp b/qpid/cpp/lib/common/sys/posix/EventChannelThreads.cpp deleted file mode 100644 index 95e699e0b0..0000000000 --- a/qpid/cpp/lib/common/sys/posix/EventChannelThreads.cpp +++ /dev/null @@ -1,119 +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 "EventChannelThreads.h" -#include -#include -using namespace std; -#include - -namespace qpid { -namespace sys { - -EventChannelThreads::shared_ptr EventChannelThreads::create( - EventChannel::shared_ptr ec) -{ - return EventChannelThreads::shared_ptr(new EventChannelThreads(ec)); -} - -EventChannelThreads::EventChannelThreads(EventChannel::shared_ptr ec) : - channel(ec), nWaiting(0), state(RUNNING) -{ - // TODO aconway 2006-11-15: Estimate initial threads based on CPUs. - addThread(); -} - -EventChannelThreads::~EventChannelThreads() { - shutdown(); - join(); -} - -void EventChannelThreads::shutdown() -{ - ScopedLock lock(*this); - if (state != RUNNING) // Already shutting down. - return; - for (size_t i = 0; i < workers.size(); ++i) { - channel->postEvent(terminate); - } - state = TERMINATE_SENT; - notify(); // Wake up one join() thread. -} - -void EventChannelThreads::join() -{ - { - ScopedLock lock(*this); - while (state == RUNNING) // Wait for shutdown to start. - wait(); - if (state == SHUTDOWN) // Shutdown is complete - return; - if (state == JOINING) { - // Someone else is doing the join. - while (state != SHUTDOWN) - wait(); - return; - } - // I'm the joining thread - assert(state == TERMINATE_SENT); - state = JOINING; - } // Drop the lock. - - for (size_t i = 0; i < workers.size(); ++i) { - assert(state == JOINING); // Only this thread can change JOINING. - workers[i].join(); - } - state = SHUTDOWN; - notifyAll(); // Notify other join() threaeds. -} - -void EventChannelThreads::addThread() { - ScopedLock l(*this); - workers.push_back(Thread(*this)); -} - -void EventChannelThreads::run() -{ - // Start life waiting. Decrement on exit. - AtomicCount::ScopedIncrement inc(nWaiting); - try { - while (true) { - Event* e = channel->getEvent(); - assert(e != 0); - if (e == &terminate) { - return; - } - AtomicCount::ScopedDecrement dec(nWaiting); - // I'm no longer waiting, make sure someone is. - if (dec == 0) - addThread(); - e->dispatch(); - } - } - catch (const std::exception& e) { - // TODO aconway 2006-11-15: need better logging across the board. - std::cerr << "EventChannelThreads::run() caught: " << e.what() - << std::endl; - } - catch (...) { - std::cerr << "EventChannelThreads::run() caught unknown exception." - << std::endl; - } -} - -}} diff --git a/qpid/cpp/lib/common/sys/posix/EventChannelThreads.h b/qpid/cpp/lib/common/sys/posix/EventChannelThreads.h deleted file mode 100644 index 98403c0869..0000000000 --- a/qpid/cpp/lib/common/sys/posix/EventChannelThreads.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef _posix_EventChannelThreads_h -#define _sys_EventChannelThreads_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 -#include -#include -#include -#include -#include "EventChannel.h" - -namespace qpid { -namespace sys { - -/** - Dynamic thread pool serving an EventChannel. - - Threads run a loop { e = getEvent(); e->dispatch(); } - The size of the thread pool is automatically adjusted to optimal size. -*/ -class EventChannelThreads : - public qpid::SharedObject, - public sys::Monitor, private sys::Runnable -{ - public: - /** Create the thread pool and start initial threads. */ - static EventChannelThreads::shared_ptr create( - EventChannel::shared_ptr channel - ); - - ~EventChannelThreads(); - - /** Post event to the underlying channel */ - void postEvent(Event& event) { channel->postEvent(event); } - - /** Post event to the underlying channel Must not be 0. */ - void postEvent(Event* event) { channel->postEvent(event); } - - /** - * Terminate all threads. - * - * Returns immediately, use join() to wait till all threads are - * shut down. - */ - void shutdown(); - - /** Wait for all threads to terminate. */ - void join(); - - private: - typedef std::vector Threads; - typedef enum { - RUNNING, TERMINATE_SENT, JOINING, SHUTDOWN - } State; - - EventChannelThreads(EventChannel::shared_ptr underlyingChannel); - void addThread(); - - void run(); - bool keepRunning(); - void adjustThreads(); - - EventChannel::shared_ptr channel; - Threads workers; - sys::AtomicCount nWaiting; - State state; - Event terminate; -}; - - -}} - - -#endif /*!_sys_EventChannelThreads_h*/ diff --git a/qpid/cpp/lib/common/sys/posix/PosixAcceptor.cpp b/qpid/cpp/lib/common/sys/posix/PosixAcceptor.cpp deleted file mode 100644 index a80a6c61f7..0000000000 --- a/qpid/cpp/lib/common/sys/posix/PosixAcceptor.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 -#include - -namespace qpid { -namespace sys { - -namespace { -void fail() { throw qpid::Exception("PosixAcceptor not implemented"); } -} - -class PosixAcceptor : public Acceptor { - public: - virtual int16_t getPort() const { fail(); return 0; } - virtual void run(qpid::sys::ConnectionInputHandlerFactory* ) { fail(); } - virtual void shutdown() { fail(); } -}; - -// Define generic Acceptor::create() to return APRAcceptor. - Acceptor::shared_ptr Acceptor::create(int16_t , int, int, bool) -{ - return Acceptor::shared_ptr(new PosixAcceptor()); -} - -// Must define Acceptor virtual dtor. -Acceptor::~Acceptor() {} - -}} diff --git a/qpid/cpp/lib/common/sys/posix/Socket.cpp b/qpid/cpp/lib/common/sys/posix/Socket.cpp deleted file mode 100644 index 5bd13742f6..0000000000 --- a/qpid/cpp/lib/common/sys/posix/Socket.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 -#include -#include -#include - -#include - -#include -#include -#include - -using namespace qpid::sys; - -Socket Socket::createTcp() -{ - int s = ::socket (PF_INET, SOCK_STREAM, 0); - if (s < 0) throw QPID_POSIX_ERROR(errno); - return s; -} - -Socket::Socket(int descriptor) : socket(descriptor) {} - -void Socket::setTimeout(Time interval) -{ - struct timeval tv; - tv.tv_sec = interval/TIME_SEC; - tv.tv_usec = (interval%TIME_SEC)/TIME_USEC; - setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); -} - -void Socket::connect(const std::string& host, int port) -{ - struct sockaddr_in name; - name.sin_family = AF_INET; - name.sin_port = htons(port); - struct hostent* hp = gethostbyname ( host.c_str() ); - if (hp == 0) throw QPID_POSIX_ERROR(errno); - memcpy(&name.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length); - if (::connect(socket, (struct sockaddr*)(&name), sizeof(name)) < 0) - throw QPID_POSIX_ERROR(errno); -} - -void -Socket::close() -{ - if (socket == 0) return; - if (::close(socket) < 0) throw QPID_POSIX_ERROR(errno); - socket = 0; -} - -ssize_t -Socket::send(const void* data, size_t size) -{ - ssize_t sent = ::send(socket, data, size, 0); - if (sent < 0) { - if (errno == ECONNRESET) return SOCKET_EOF; - if (errno == ETIMEDOUT) return SOCKET_TIMEOUT; - throw QPID_POSIX_ERROR(errno); - } - return sent; -} - -ssize_t -Socket::recv(void* data, size_t size) -{ - ssize_t received = ::recv(socket, data, size, 0); - if (received < 0) { - if (errno == ETIMEDOUT) return SOCKET_TIMEOUT; - throw QPID_POSIX_ERROR(errno); - } - return received; -} - -int Socket::listen(int port, int backlog) -{ - struct sockaddr_in name; - name.sin_family = AF_INET; - name.sin_port = htons(port); - name.sin_addr.s_addr = 0; - if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) < 0) - throw QPID_POSIX_ERROR(errno); - if (::listen(socket, backlog) < 0) - throw QPID_POSIX_ERROR(errno); - - socklen_t namelen = sizeof(name); - if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0) - throw QPID_POSIX_ERROR(errno); - - return ntohs(name.sin_port); -} - - -int Socket::fd() -{ - return socket; -} diff --git a/qpid/cpp/lib/common/sys/posix/Thread.cpp b/qpid/cpp/lib/common/sys/posix/Thread.cpp deleted file mode 100644 index f524799556..0000000000 --- a/qpid/cpp/lib/common/sys/posix/Thread.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 - -void* qpid::sys::Thread::runRunnable(void* p) -{ - static_cast(p)->run(); - return 0; -} diff --git a/qpid/cpp/lib/common/sys/posix/check.cpp b/qpid/cpp/lib/common/sys/posix/check.cpp deleted file mode 100644 index 408679caa8..0000000000 --- a/qpid/cpp/lib/common/sys/posix/check.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "check.h" - -namespace qpid { -namespace sys { - -std::string -PosixError::getMessage(int errNo) -{ - char buf[512]; - return std::string(strerror_r(errNo, buf, sizeof(buf))); -} - -PosixError::PosixError(int errNo, const qpid::SrcLine& loc) throw() - : qpid::QpidError(INTERNAL_ERROR + errNo, getMessage(errNo), loc) -{ } - -}} diff --git a/qpid/cpp/lib/common/sys/posix/check.h b/qpid/cpp/lib/common/sys/posix/check.h deleted file mode 100644 index 57b5a5757c..0000000000 --- a/qpid/cpp/lib/common/sys/posix/check.h +++ /dev/null @@ -1,62 +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 -#include -#include - -namespace qpid { -namespace sys { - -/** - * Exception with message from errno. - */ -class PosixError : public qpid::QpidError -{ - public: - static std::string getMessage(int errNo); - - PosixError(int errNo, const qpid::SrcLine& location) throw(); - - ~PosixError() throw() {} - - int getErrNo() { return errNo; } - - Exception* clone() const throw() { return new PosixError(*this); } - - void throwSelf() const { throw *this; } - - private: - int errNo; -}; - -}} - -/** Create a PosixError for the current file/line and errno. */ -#define QPID_POSIX_ERROR(errNo) ::qpid::sys::PosixError(errNo, SRCLINE) - -/** Throw a posix error if errNo is non-zero */ -#define QPID_POSIX_THROW_IF(ERRNO) \ - if ((ERRNO) != 0) throw QPID_POSIX_ERROR((ERRNO)) -#endif /*!_posix_check_h*/ diff --git a/qpid/cpp/src/Exception.cpp b/qpid/cpp/src/Exception.cpp new file mode 100644 index 0000000000..1bbf89e99f --- /dev/null +++ b/qpid/cpp/src/Exception.cpp @@ -0,0 +1,46 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "Exception.h" + +namespace qpid { + +Exception::Exception() throw() {} + +Exception::Exception(const std::string& str) throw() : whatStr(str) {} + +Exception::Exception(const char* str) throw() : whatStr(str) {} + +Exception::~Exception() throw() {} + +const char* Exception::what() const throw() { return whatStr.c_str(); } + +std::string Exception::toString() const throw() { return whatStr; } + +Exception* Exception::clone() const throw() { return new Exception(*this); } + +void Exception::throwSelf() const { throw *this; } + +ShutdownException::ShutdownException() : Exception("Shut down.") {} + +EmptyException::EmptyException() : Exception("Empty.") {} + +} // namespace qpid diff --git a/qpid/cpp/src/Exception.h b/qpid/cpp/src/Exception.h new file mode 100644 index 0000000000..4fbad7efaa --- /dev/null +++ b/qpid/cpp/src/Exception.h @@ -0,0 +1,97 @@ +#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 +#include +#include +#include +#include + +#include "framing/amqp_types.h" + +namespace qpid +{ +/** + * Exception base class for all Qpid exceptions. + */ +class Exception : public std::exception +{ + protected: + std::string whatStr; + + public: + Exception() throw(); + Exception(const std::string& str) throw(); + Exception(const char* str) throw(); + Exception(const std::exception&) throw(); + + /** Allow any type that has ostream operator<< to act as message */ + template + Exception(const T& message) + : whatStr(boost::lexical_cast(message)) {} + + virtual ~Exception() throw(); + + virtual const char* what() const throw(); + virtual std::string toString() const throw(); + + virtual Exception* clone() const throw(); + virtual void throwSelf() const; + + typedef boost::shared_ptr shared_ptr; +}; + +struct ChannelException : public Exception { + framing::ReplyCode code; + template + ChannelException(framing::ReplyCode code_, const T& message) + : Exception(message), code(code_) {} + void throwSelf() const { throw *this; } +}; + +struct ConnectionException : public Exception { + framing::ReplyCode code; + template + ConnectionException(framing::ReplyCode code_, const T& message) + : Exception(message), code(code_) {} + void throwSelf() const { throw *this; } +}; + +/** + * Exception used to indicate that a thread should shut down. + * Does not indicate an error that should be signalled to the user. + */ +struct ShutdownException : public Exception { + ShutdownException(); + void throwSelf() const { throw *this; } +}; + +/** Exception to indicate empty queue or other empty state */ +struct EmptyException : public Exception { + EmptyException(); + void throwSelf() const { throw *this; } +}; + +} + +#endif /*!_Exception_*/ diff --git a/qpid/cpp/src/ExceptionHolder.cpp b/qpid/cpp/src/ExceptionHolder.cpp new file mode 100644 index 0000000000..de8d7b2487 --- /dev/null +++ b/qpid/cpp/src/ExceptionHolder.cpp @@ -0,0 +1,32 @@ +/* + * + * 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 "ExceptionHolder.h" + +namespace qpid { + +ExceptionHolder::ExceptionHolder(const std::exception& e) { + const Exception* ex = dynamic_cast(&e); + if (ex) { + reset(ex->clone()); + } else { + reset(new Exception(e.what())); + } +} + +} diff --git a/qpid/cpp/src/ExceptionHolder.h b/qpid/cpp/src/ExceptionHolder.h new file mode 100644 index 0000000000..723dac4b2d --- /dev/null +++ b/qpid/cpp/src/ExceptionHolder.h @@ -0,0 +1,67 @@ +#ifndef _qpid_ExceptionHolder_h +#define _qpid_ExceptionHolder_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 "Exception.h" +#include + +namespace qpid { + +// FIXME aconway 2007-02-20: Not necessary, a simple +// Exception::shared_ptr will do the job. Remove +// +/** + * Holder for a heap-allocated exc eption that can be stack allocated + * and thrown safely. + * + * Basically this is a shared_ptr with the Exception functions added + * so the catcher need not be aware that it is a pointer rather than a + * reference. + * + * shared_ptr is chosen over auto_ptr because it has normal + * copy semantics. + */ +class ExceptionHolder : public Exception, public boost::shared_ptr +{ + public: + typedef boost::shared_ptr shared_ptr; + + ExceptionHolder() throw() {} + ExceptionHolder(Exception* p) throw() : shared_ptr(p) {} + ExceptionHolder(shared_ptr p) throw() : shared_ptr(p) {} + + ExceptionHolder(const Exception& e) throw() : shared_ptr(e.clone()) {} + ExceptionHolder(const std::exception& e); + + ~ExceptionHolder() throw() {} + + const char* what() const throw() { return get()->what(); } + std::string toString() const throw() { return get()->toString(); } + Exception* clone() const throw() { return get()->clone(); } + void throwIf() const { if (get()) get()->throwSelf(); } + void throwSelf() const { assert(get()); get()->throwSelf(); } +}; + +} // namespace qpid + + + +#endif /*!_qpid_ExceptionHolder_h*/ diff --git a/qpid/cpp/src/Makefile.am b/qpid/cpp/src/Makefile.am index 40398eb2c9..22bcd5c554 100644 --- a/qpid/cpp/src/Makefile.am +++ b/qpid/cpp/src/Makefile.am @@ -1,17 +1,150 @@ +SUBDIRS = broker . client tests gen + AM_CXXFLAGS = $(WARNING_CFLAGS) -INCLUDES = \ - -I$(top_srcdir)/gen \ - -I$(top_srcdir)/lib/broker \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/common/framing \ - -I$(top_srcdir)/lib/common/sys -LDADD = \ - ../lib/broker/libqpidbroker.la \ - ../lib/common/libqpidcommon.la +INCLUDES = \ + -I$(srcdir)/gen \ + $(APR_CXXFLAGS) + +qpidd_LDADD = \ + broker/libqpidbroker.la \ + libqpidcommon.la sbin_PROGRAMS = qpidd qpidd_SOURCES = qpidd.cpp -# Force build of qpidd during dist phase so help2man will work. -dist-hook: $(sbin_PROGRAMS) +apr = sys/apr +apr_src = \ + $(apr)/APRAcceptor.cpp \ + $(apr)/APRBase.cpp \ + $(apr)/APRPool.cpp \ + $(apr)/APRSocket.cpp \ + $(apr)/LFProcessor.cpp \ + $(apr)/LFSessionContext.cpp \ + $(apr)/Socket.cpp \ + $(apr)/Thread.cpp +apr_hdr = \ + $(apr)/APRBase.h \ + $(apr)/APRPool.h \ + $(apr)/APRSocket.h \ + $(apr)/LFProcessor.h \ + $(apr)/LFSessionContext.h + +posix = sys/posix +posix_src = \ + $(posix)/PosixAcceptor.cpp \ + $(posix)/Socket.cpp \ + $(posix)/Thread.cpp \ + $(posix)/check.cpp \ + $(posix)/EventChannel.cpp \ + $(posix)/EventChannelThreads.cpp +posix_hdr = \ + $(posix)/check.h \ + $(posix)/EventChannel.h \ + $(posix)/EventChannelThreads.h + +EXTRA_DIST=$(posix_src) $(posix_hdr) +platform_src = $(apr_src) +platform_hdr = $(apr_hdr) + +framing = framing +gen = gen + +lib_LTLIBRARIES = libqpidcommon.la +libqpidcommon_la_LIBADD = \ + $(APR_LIBS) \ + $(LIB_DLOPEN) \ + $(LIB_CLOCK_GETTIME) + +libqpidcommon_la_LDFLAGS = \ + -version-info \ + $(LIBTOOL_VERSION_INFO_ARG) + +libqpidcommon_la_SOURCES = \ + $(platform_src) \ + $(framing)/AMQBody.cpp \ + $(framing)/AMQRequestBody.cpp \ + $(framing)/AMQResponseBody.cpp \ + $(framing)/AMQContentBody.cpp \ + $(framing)/AMQFrame.cpp \ + $(framing)/AMQHeaderBody.cpp \ + $(framing)/AMQHeartbeatBody.cpp \ + $(framing)/AMQMethodBody.cpp \ + $(framing)/MethodContext.cpp \ + $(framing)/BasicHeaderProperties.cpp \ + $(framing)/BodyHandler.cpp \ + $(framing)/ChannelAdapter.cpp \ + $(framing)/Buffer.cpp \ + $(framing)/FieldTable.cpp \ + $(framing)/FramingContent.cpp \ + $(framing)/InitiationHandler.cpp \ + $(framing)/ProtocolInitiation.cpp \ + $(framing)/ProtocolVersion.cpp \ + $(framing)/ProtocolVersionException.cpp \ + $(framing)/Requester.cpp \ + $(framing)/Responder.cpp \ + $(framing)/Value.cpp \ + $(framing)/Proxy.cpp \ + $(gen)/AMQP_ClientProxy.cpp \ + $(gen)/AMQP_HighestVersion.h \ + $(gen)/AMQP_MethodVersionMap.cpp \ + $(gen)/AMQP_ServerProxy.cpp \ + Exception.cpp \ + ExceptionHolder.cpp \ + QpidError.cpp \ + sys/Runnable.cpp \ + sys/Time.cpp \ + sys/ProducerConsumer.cpp + +nobase_pkginclude_HEADERS = \ + $(gen)/AMQP_HighestVersion.h \ + $(platform_hdr) \ + $(framing)/AMQBody.h \ + $(framing)/AMQContentBody.h \ + $(framing)/AMQDataBlock.h \ + $(framing)/AMQFrame.h \ + $(framing)/AMQHeaderBody.h \ + $(framing)/AMQHeartbeatBody.h \ + $(framing)/AMQMethodBody.h \ + $(framing)/MethodContext.h \ + $(framing)/BasicHeaderProperties.h \ + $(framing)/BodyHandler.h \ + $(framing)/ChannelAdapter.h \ + $(framing)/Buffer.h \ + $(framing)/FieldTable.h \ + $(framing)/FramingContent.h \ + $(framing)/HeaderProperties.h \ + $(framing)/InitiationHandler.h \ + $(framing)/InputHandler.h \ + $(framing)/OutputHandler.h \ + $(framing)/ProtocolInitiation.h \ + $(framing)/ProtocolVersion.h \ + $(framing)/ProtocolVersionException.h \ + $(framing)/Value.h \ + $(framing)/amqp_framing.h \ + $(framing)/amqp_types.h \ + $(framing)/Proxy.h \ + shared_ptr.h \ + Exception.h \ + ExceptionHolder.h \ + QpidError.h \ + SharedObject.h \ + sys/Acceptor.h \ + sys/AtomicCount.h \ + sys/Module.h \ + sys/Monitor.h \ + sys/Mutex.h \ + sys/Runnable.h \ + sys/ConnectionOutputHandler.h \ + sys/ConnectionInputHandler.h \ + sys/ConnectionInputHandlerFactory.h \ + sys/ShutdownHandler.h \ + sys/Socket.h \ + sys/Thread.h \ + sys/Time.h \ + sys/TimeoutHandler.h \ + sys/ProducerConsumer.h + + +# Force build during dist phase so help2man will work. +dist-hook: $(lib_LTLIBRARIES) $(sbin_PROGRAMS) diff --git a/qpid/cpp/src/QpidError.cpp b/qpid/cpp/src/QpidError.cpp new file mode 100644 index 0000000000..365c84ea1d --- /dev/null +++ b/qpid/cpp/src/QpidError.cpp @@ -0,0 +1,42 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "QpidError.h" +#include + +using namespace qpid; + +QpidError::QpidError() : code(0) {} + +QpidError::~QpidError() throw() {} + +Exception* QpidError::clone() const throw() { return new QpidError(*this); } + +void QpidError::throwSelf() const { throw *this; } + +void QpidError::init() { + whatStr = boost::str(boost::format("Error [%d] %s (%s:%d)") + % code % msg % loc.file % loc.line); +} + + diff --git a/qpid/cpp/src/QpidError.h b/qpid/cpp/src/QpidError.h new file mode 100644 index 0000000000..12e80c9bd9 --- /dev/null +++ b/qpid/cpp/src/QpidError.h @@ -0,0 +1,78 @@ +#ifndef __QpidError__ +#define __QpidError__ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "Exception.h" + +namespace qpid { + +struct SrcLine { + public: + SrcLine(const std::string& file_="", int line_=0) : + file(file_), line(line_) {} + + std::string file; + int line; +}; + +class QpidError : public Exception +{ + public: + const int code; + SrcLine loc; + std::string msg; + + QpidError(); + + template + QpidError(int code_, const T& msg_, const SrcLine& loc_) throw() + : code(code_), loc(loc_), msg(boost::lexical_cast(msg_)) + { init(); } + + ~QpidError() throw(); + Exception* clone() const throw(); + void throwSelf() const; + + private: + + void init(); +}; + + +} // namespace qpid + +#define SRCLINE ::qpid::SrcLine(__FILE__, __LINE__) + +#define QPID_ERROR(CODE, MESSAGE) ::qpid::QpidError((CODE), (MESSAGE), SRCLINE) + +#define THROW_QPID_ERROR(CODE, MESSAGE) throw QPID_ERROR(CODE,MESSAGE) + +const int PROTOCOL_ERROR = 10000; +const int APR_ERROR = 20000; +const int FRAMING_ERROR = 30000; +const int CLIENT_ERROR = 40000; +const int INTERNAL_ERROR = 50000; + +#endif diff --git a/qpid/cpp/src/SharedObject.h b/qpid/cpp/src/SharedObject.h new file mode 100644 index 0000000000..852a036ab9 --- /dev/null +++ b/qpid/cpp/src/SharedObject.h @@ -0,0 +1,55 @@ +#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/broker/AccumulatedAck.cpp b/qpid/cpp/src/broker/AccumulatedAck.cpp new file mode 100644 index 0000000000..ff471b0287 --- /dev/null +++ b/qpid/cpp/src/broker/AccumulatedAck.cpp @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "AccumulatedAck.h" + +#include + +using std::less_equal; +using std::bind2nd; +using namespace qpid::broker; + +void AccumulatedAck::update(uint64_t firstTag, uint64_t lastTag){ + assert(firstTag<=lastTag); + if (firstTag <= range + 1) { + if (lastTag > range) range = lastTag; + } else { + for (uint64_t tag = firstTag; tag<=lastTag; tag++) + individual.push_back(tag); + } +} + +void AccumulatedAck::consolidate(){ + individual.sort(); + //remove any individual tags that are covered by range + individual.remove_if(bind2nd(less_equal(), range)); + //update range if possible (using <= allows for duplicates from overlapping ranges) + while (individual.front() <= range + 1) { + range = individual.front(); + individual.pop_front(); + } +} + +void AccumulatedAck::clear(){ + range = 0; + individual.clear(); +} + +bool AccumulatedAck::covers(uint64_t tag) const{ + return tag <= range || find(individual.begin(), individual.end(), tag) != individual.end(); +} diff --git a/qpid/cpp/src/broker/AccumulatedAck.h b/qpid/cpp/src/broker/AccumulatedAck.h new file mode 100644 index 0000000000..c4a6e3b79b --- /dev/null +++ b/qpid/cpp/src/broker/AccumulatedAck.h @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _AccumulatedAck_ +#define _AccumulatedAck_ + +#include +#include +#include + +namespace qpid { + namespace broker { + /** + * Keeps an accumulated record of acked messages (by delivery + * tag). + */ + class AccumulatedAck { + public: + /** + * If not zero, then everything up to this value has been + * acked. + */ + uint64_t range; + /** + * List of individually acked messages that are not + * included in the range marked by 'range'. + */ + std::list individual; + + AccumulatedAck(uint64_t r) : range(r) {} + void update(uint64_t firstTag, uint64_t lastTag); + void consolidate(); + void clear(); + bool covers(uint64_t tag) const; + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/AutoDelete.cpp b/qpid/cpp/src/broker/AutoDelete.cpp new file mode 100644 index 0000000000..dee8a0ec78 --- /dev/null +++ b/qpid/cpp/src/broker/AutoDelete.cpp @@ -0,0 +1,86 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "AutoDelete.h" +#include "../sys/Time.h" + +using namespace qpid::broker; +using namespace qpid::sys; + +AutoDelete::AutoDelete(QueueRegistry* const _registry, uint32_t _period) + : registry(_registry), period(_period), stopped(true) { } + +void AutoDelete::add(Queue::shared_ptr const queue){ + Mutex::ScopedLock l(lock); + queues.push(queue); +} + +Queue::shared_ptr const AutoDelete::pop(){ + Queue::shared_ptr next; + Mutex::ScopedLock l(lock); + if(!queues.empty()){ + next = queues.front(); + queues.pop(); + } + return next; +} + +void AutoDelete::process(){ + Queue::shared_ptr seen; + for(Queue::shared_ptr q = pop(); q; q = pop()){ + if(seen == q){ + add(q); + break; + }else if(q->canAutoDelete()){ + std::string name(q->getName()); + registry->destroy(name); + std::cout << "INFO: Auto-deleted queue named " << name << std::endl; + }else{ + add(q); + if(!seen) seen = q; + } + } +} + +void AutoDelete::run(){ + Monitor::ScopedLock l(monitor); + while(!stopped){ + process(); + monitor.wait(period*TIME_MSEC); + } +} + +void AutoDelete::start(){ + Monitor::ScopedLock l(monitor); + if(stopped){ + stopped = false; + runner = Thread(this); + } +} + +void AutoDelete::stop(){ + { + Monitor::ScopedLock l(monitor); + if(stopped) return; + stopped = true; + } + monitor.notify(); + runner.join(); +} diff --git a/qpid/cpp/src/broker/AutoDelete.h b/qpid/cpp/src/broker/AutoDelete.h new file mode 100644 index 0000000000..8cfd37325f --- /dev/null +++ b/qpid/cpp/src/broker/AutoDelete.h @@ -0,0 +1,55 @@ +#ifndef _AutoDelete_ +#define _AutoDelete_ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../sys/Monitor.h" +#include "BrokerQueue.h" +#include "QueueRegistry.h" +#include "../sys/Thread.h" + +namespace qpid { + namespace broker{ + class AutoDelete : private qpid::sys::Runnable { + qpid::sys::Mutex lock; + qpid::sys::Monitor monitor; + std::queue queues; + QueueRegistry* const registry; + uint32_t period; + volatile bool stopped; + qpid::sys::Thread runner; + + Queue::shared_ptr const pop(); + void process(); + virtual void run(); + + public: + AutoDelete(QueueRegistry* const registry, uint32_t period); + void add(Queue::shared_ptr const); + void start(); + void stop(); + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/Broker.cpp b/qpid/cpp/src/broker/Broker.cpp new file mode 100644 index 0000000000..13da64915d --- /dev/null +++ b/qpid/cpp/src/broker/Broker.cpp @@ -0,0 +1,121 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../framing/AMQFrame.h" +#include "DirectExchange.h" +#include "TopicExchange.h" +#include "FanOutExchange.h" +#include "HeadersExchange.h" +#include "MessageStoreModule.h" +#include "NullMessageStore.h" +#include "../framing/ProtocolInitiation.h" +#include "RecoveryManagerImpl.h" +#include "Connection.h" +#include "../sys/ConnectionInputHandler.h" +#include "../sys/ConnectionInputHandlerFactory.h" +#include "../sys/TimeoutHandler.h" + +#include "Broker.h" + +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"); + +Broker::Broker(const Configuration& conf) : + config(conf), + store(createStore(conf)), + queues(store.get()), + timeout(30000), + stagingThreshold(0), + cleaner(&queues, timeout/10), + factory(*this) +{ + exchanges.declare(empty, DirectExchange::typeName); // Default exchange. + exchanges.declare(amq_direct, DirectExchange::typeName); + exchanges.declare(amq_topic, TopicExchange::typeName); + exchanges.declare(amq_fanout, FanOutExchange::typeName); + exchanges.declare(amq_match, HeadersExchange::typeName); + + if(store.get()) { + RecoveryManagerImpl recoverer(queues, exchanges, conf.getStagingThreshold()); + store->recover(recoverer); + } + + cleaner.start(); +} + + +Broker::shared_ptr Broker::create(int16_t port) +{ + Configuration config; + config.setPort(port); + return create(config); +} + +Broker::shared_ptr Broker::create(const Configuration& config) { + return Broker::shared_ptr(new Broker(config)); +} + +MessageStore* Broker::createStore(const Configuration& config) { + if (config.getStore().empty()) + return new NullMessageStore(config.isTrace()); + else + return new MessageStoreModule(config.getStore()); +} + +void Broker::run() { + getAcceptor().run(&factory); +} + +void Broker::shutdown() { + if (acceptor) + acceptor->shutdown(); +} + +Broker::~Broker() { + shutdown(); +} + +int16_t Broker::getPort() const { return getAcceptor().getPort(); } + +Acceptor& Broker::getAcceptor() const { + if (!acceptor) + const_cast(acceptor) = + Acceptor::create(config.getPort(), + config.getConnectionBacklog(), + config.getWorkerThreads(), + config.isTrace()); + return *acceptor; +} + + +const int16_t Broker::DEFAULT_PORT(5672); + + +}} // namespace qpid::broker + diff --git a/qpid/cpp/src/broker/Broker.h b/qpid/cpp/src/broker/Broker.h new file mode 100644 index 0000000000..f713f0955b --- /dev/null +++ b/qpid/cpp/src/broker/Broker.h @@ -0,0 +1,108 @@ +#ifndef _Broker_ +#define _Broker_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "Configuration.h" +#include "ConnectionFactory.h" +#include "../sys/Runnable.h" +#include "../sys/Acceptor.h" +#include "../SharedObject.h" +#include "MessageStore.h" +#include "AutoDelete.h" +#include "ExchangeRegistry.h" +#include "ConnectionToken.h" +#include "DirectExchange.h" +#include "../framing/OutputHandler.h" +#include "../framing/ProtocolInitiation.h" +#include "QueueRegistry.h" + +namespace qpid { +namespace broker { +/** + * A broker instance. + */ +class Broker : public sys::Runnable, + public SharedObject +{ + public: + static const int16_t DEFAULT_PORT; + + virtual ~Broker(); + + /** + * Create a broker. + * @param port Port to listen on or 0 to pick a port dynamically. + */ + static shared_ptr create(int16_t port = DEFAULT_PORT); + + /** + * Create a broker using a Configuration. + */ + static shared_ptr create(const Configuration& config); + + /** + * 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. + */ + virtual int16_t getPort() const; + + /** + * Run the broker. Implements Runnable::run() so the broker + * can be run in a separate thread. + */ + virtual void run(); + + /** Shut down the broker */ + virtual void shutdown(); + + MessageStore& getStore() { return *store; } + QueueRegistry& getQueues() { return queues; } + ExchangeRegistry& getExchanges() { return exchanges; } + uint32_t getTimeout() { return timeout; } + uint64_t getStagingThreshold() { return stagingThreshold; } + AutoDelete& getCleaner() { return cleaner; } + + private: + Broker(const Configuration& config); + sys::Acceptor& getAcceptor() const; + + Configuration config; + sys::Acceptor::shared_ptr acceptor; + const std::auto_ptr store; + QueueRegistry queues; + ExchangeRegistry exchanges; + uint32_t timeout; + uint64_t stagingThreshold; + AutoDelete cleaner; + ConnectionFactory factory; + + static MessageStore* createStore(const Configuration& config); +}; + +}} + + + +#endif /*!_Broker_*/ diff --git a/qpid/cpp/src/broker/BrokerAdapter.cpp b/qpid/cpp/src/broker/BrokerAdapter.cpp new file mode 100644 index 0000000000..d04610c877 --- /dev/null +++ b/qpid/cpp/src/broker/BrokerAdapter.cpp @@ -0,0 +1,388 @@ +/* + * + * 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 "BrokerAdapter.h" +#include "BrokerChannel.h" +#include "Connection.h" +#include "../framing/AMQMethodBody.h" +#include "../Exception.h" + +namespace qpid { +namespace broker { + +using boost::format; +using namespace qpid; +using namespace qpid::framing; + +typedef std::vector QueueVector; + + +BrokerAdapter::BrokerAdapter(Channel& ch, Connection& c, Broker& b) : + CoreRefs(ch, c, b), + connection(c), + basicHandler(*this), + channelHandler(*this), + connectionHandler(*this), + exchangeHandler(*this), + messageHandler(*this), + queueHandler(*this), + txHandler(*this) +{} + + +ProtocolVersion BrokerAdapter::getVersion() const { + return connection.getVersion(); +} + +void BrokerAdapter::ConnectionHandlerImpl::startOk( + const MethodContext&, const FieldTable& /*clientProperties*/, + const string& /*mechanism*/, + const string& /*response*/, const string& /*locale*/) +{ + client.tune( + 100, connection.getFrameMax(), connection.getHeartbeat()); +} + +void BrokerAdapter::ConnectionHandlerImpl::secureOk( + const MethodContext&, const string& /*response*/){} + +void BrokerAdapter::ConnectionHandlerImpl::tuneOk( + const MethodContext&, uint16_t /*channelmax*/, + uint32_t framemax, uint16_t heartbeat) +{ + connection.setFrameMax(framemax); + connection.setHeartbeat(heartbeat); +} + +void BrokerAdapter::ConnectionHandlerImpl::open( + const MethodContext& context, const string& /*virtualHost*/, + const string& /*capabilities*/, bool /*insist*/) +{ + string knownhosts; + client.openOk( + knownhosts, context.getRequestId()); +} + +void BrokerAdapter::ConnectionHandlerImpl::close( + const MethodContext& context, uint16_t /*replyCode*/, const string& /*replyText*/, + uint16_t /*classId*/, uint16_t /*methodId*/) +{ + client.closeOk(context.getRequestId()); + connection.getOutput().close(); +} + +void BrokerAdapter::ConnectionHandlerImpl::closeOk(const MethodContext&){ + connection.getOutput().close(); +} + +void BrokerAdapter::ChannelHandlerImpl::open( + const MethodContext& context, const string& /*outOfBand*/){ + channel.open(); + // FIXME aconway 2007-01-04: provide valid ID as per ampq 0-9 + client.openOk( + std::string()/* ID */, context.getRequestId()); +} + +void BrokerAdapter::ChannelHandlerImpl::flow(const MethodContext&, bool /*active*/){} +void BrokerAdapter::ChannelHandlerImpl::flowOk(const MethodContext&, bool /*active*/){} + +void BrokerAdapter::ChannelHandlerImpl::close( + const MethodContext& context, uint16_t /*replyCode*/, + const string& /*replyText*/, + uint16_t /*classId*/, uint16_t /*methodId*/) +{ + client.closeOk(context.getRequestId()); + // FIXME aconway 2007-01-18: Following line will "delete this". Ugly. + connection.closeChannel(channel.getId()); +} + +void BrokerAdapter::ChannelHandlerImpl::closeOk(const MethodContext&){} + + + +void BrokerAdapter::ExchangeHandlerImpl::declare(const MethodContext& context, uint16_t /*ticket*/, const string& exchange, const string& type, + bool passive, bool /*durable*/, bool /*autoDelete*/, bool /*internal*/, bool nowait, + const FieldTable& /*arguments*/){ + + if(passive){ + if(!broker.getExchanges().get(exchange)) { + throw ChannelException(404, "Exchange not found: " + exchange); + } + }else{ + try{ + std::pair response = broker.getExchanges().declare(exchange, type); + if(!response.second && response.first->getType() != type){ + throw ConnectionException( + 530, + "Exchange already declared to be of type " + + response.first->getType() + ", requested " + type); + } + }catch(UnknownExchangeTypeException& e){ + throw ConnectionException( + 503, "Exchange type not implemented: " + type); + } + } + if(!nowait){ + client.declareOk(context.getRequestId()); + } +} + +void BrokerAdapter::ExchangeHandlerImpl::delete_(const MethodContext& context, uint16_t /*ticket*/, + const string& exchange, bool /*ifUnused*/, bool nowait){ + + //TODO: implement unused + broker.getExchanges().destroy(exchange); + if(!nowait) client.deleteOk(context.getRequestId()); +} + +void BrokerAdapter::QueueHandlerImpl::declare(const MethodContext& context, uint16_t /*ticket*/, const string& name, + bool passive, bool durable, bool exclusive, + bool autoDelete, bool nowait, const qpid::framing::FieldTable& arguments){ + Queue::shared_ptr queue; + if (passive && !name.empty()) { + queue = connection.getQueue(name, channel.getId()); + } else { + std::pair queue_created = + broker.getQueues().declare( + name, durable, + autoDelete ? connection.getTimeout() : 0, + exclusive ? &connection : 0); + queue = queue_created.first; + assert(queue); + if (queue_created.second) { // This is a new queue + channel.setDefaultQueue(queue); + + //apply settings & create persistent record if required + queue_created.first->create(arguments); + + //add default binding: + broker.getExchanges().getDefault()->bind(queue, name, 0); + if (exclusive) { + connection.exclusiveQueues.push_back(queue); + } else if(autoDelete){ + broker.getCleaner().add(queue); + } + } + } + if (exclusive && !queue->isExclusiveOwner(&connection)) + throw ChannelException( + 405, + format("Cannot grant exclusive access to queue '%s'") + % queue->getName()); + if (!nowait) { + string queueName = queue->getName(); + client.declareOk( + queueName, queue->getMessageCount(), queue->getConsumerCount(), + context.getRequestId()); + } +} + +void BrokerAdapter::QueueHandlerImpl::bind(const MethodContext& context, uint16_t /*ticket*/, const string& queueName, + const string& exchangeName, const string& routingKey, bool nowait, + const FieldTable& arguments){ + + Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); + Exchange::shared_ptr exchange = broker.getExchanges().get(exchangeName); + if(exchange){ + string exchangeRoutingKey = routingKey.empty() && queueName.empty() ? queue->getName() : routingKey; + exchange->bind(queue, exchangeRoutingKey, &arguments); + if(!nowait) client.bindOk(context.getRequestId()); + }else{ + throw ChannelException( + 404, "Bind failed. No such exchange: " + exchangeName); + } +} + +void +BrokerAdapter::QueueHandlerImpl::unbind( + const MethodContext& context, + uint16_t /*ticket*/, + const string& queueName, + const string& exchangeName, + const string& routingKey, + const qpid::framing::FieldTable& arguments ) +{ + Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); + if (!queue.get()) throw ChannelException(404, "Unbind failed. No such exchange: " + exchangeName); + + Exchange::shared_ptr exchange = broker.getExchanges().get(exchangeName); + if (!exchange.get()) throw ChannelException(404, "Unbind failed. No such exchange: " + exchangeName); + + exchange->unbind(queue, routingKey, &arguments); + + client.unbindOk(context.getRequestId()); +} + +void BrokerAdapter::QueueHandlerImpl::purge(const MethodContext& context, uint16_t /*ticket*/, const string& queueName, bool nowait){ + + Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); + int count = queue->purge(); + if(!nowait) client.purgeOk( count, context.getRequestId()); +} + +void BrokerAdapter::QueueHandlerImpl::delete_(const MethodContext& context, uint16_t /*ticket*/, const string& queue, + bool ifUnused, bool ifEmpty, bool nowait){ + ChannelException error(0, ""); + int count(0); + Queue::shared_ptr q = connection.getQueue(queue, channel.getId()); + if(ifEmpty && q->getMessageCount() > 0){ + throw ChannelException(406, "Queue not empty."); + }else if(ifUnused && q->getConsumerCount() > 0){ + throw ChannelException(406, "Queue in use."); + }else{ + //remove the queue from the list of exclusive queues if necessary + if(q->isExclusiveOwner(&connection)){ + QueueVector::iterator i = find(connection.exclusiveQueues.begin(), connection.exclusiveQueues.end(), q); + if(i < connection.exclusiveQueues.end()) connection.exclusiveQueues.erase(i); + } + count = q->getMessageCount(); + q->destroy(); + broker.getQueues().destroy(queue); + } + + if(!nowait) + client.deleteOk(count, context.getRequestId()); +} + + + + +void BrokerAdapter::BasicHandlerImpl::qos(const MethodContext& context, uint32_t prefetchSize, uint16_t prefetchCount, bool /*global*/){ + //TODO: handle global + channel.setPrefetchSize(prefetchSize); + channel.setPrefetchCount(prefetchCount); + client.qosOk(context.getRequestId()); +} + +void BrokerAdapter::BasicHandlerImpl::consume( + const MethodContext& context, uint16_t /*ticket*/, + const string& queueName, const string& consumerTag, + bool noLocal, bool noAck, bool exclusive, + bool nowait, const FieldTable& fields) +{ + + Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); + if(!consumerTag.empty() && channel.exists(consumerTag)){ + throw ConnectionException(530, "Consumer tags must be unique"); + } + + string newTag = consumerTag; + channel.consume( + newTag, queue, !noAck, exclusive, noLocal ? &connection : 0, &fields); + + if(!nowait) client.consumeOk(newTag, context.getRequestId()); + + //allow messages to be dispatched if required as there is now a consumer: + queue->dispatch(); +} + +void BrokerAdapter::BasicHandlerImpl::cancel(const MethodContext& context, const string& consumerTag, bool nowait){ + channel.cancel(consumerTag); + + if(!nowait) client.cancelOk(consumerTag, context.getRequestId()); +} + +void BrokerAdapter::BasicHandlerImpl::publish( + const MethodContext& context, uint16_t /*ticket*/, + const string& exchangeName, const string& routingKey, + bool mandatory, bool immediate) +{ + + Exchange::shared_ptr exchange = exchangeName.empty() ? broker.getExchanges().getDefault() : broker.getExchanges().get(exchangeName); + if(exchange){ + BasicMessage* msg = new BasicMessage( + &connection, exchangeName, routingKey, mandatory, immediate, + context.methodBody); + channel.handlePublish(msg); + }else{ + throw ChannelException( + 404, "Exchange not found '" + exchangeName + "'"); + } +} + +void BrokerAdapter::BasicHandlerImpl::get(const MethodContext& context, uint16_t /*ticket*/, const string& queueName, bool noAck){ + Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); + if(!connection.getChannel(channel.getId()).get(queue, "", !noAck)){ + string clusterId;//not used, part of an imatix hack + + client.getEmpty(clusterId, context.getRequestId()); + } +} + +void BrokerAdapter::BasicHandlerImpl::ack(const MethodContext&, uint64_t deliveryTag, bool multiple){ + channel.ack(deliveryTag, multiple); +} + +void BrokerAdapter::BasicHandlerImpl::reject(const MethodContext&, uint64_t /*deliveryTag*/, bool /*requeue*/){} + +void BrokerAdapter::BasicHandlerImpl::recover(const MethodContext&, bool requeue){ + channel.recover(requeue); +} + +void BrokerAdapter::TxHandlerImpl::select(const MethodContext& context){ + channel.begin(); + client.selectOk(context.getRequestId()); +} + +void BrokerAdapter::TxHandlerImpl::commit(const MethodContext& context){ + channel.commit(); + client.commitOk(context.getRequestId()); +} + +void BrokerAdapter::TxHandlerImpl::rollback(const MethodContext& context){ + + channel.rollback(); + client.rollbackOk(context.getRequestId()); + channel.recover(false); +} + +void +BrokerAdapter::ChannelHandlerImpl::ok( const MethodContext& ) +{ + //no specific action required, generic response handling should be sufficient +} + + +// +// Message class method handlers +// +void +BrokerAdapter::ChannelHandlerImpl::ping( const MethodContext& context) +{ + client.ok(context.getRequestId()); + client.pong(); +} + + +void +BrokerAdapter::ChannelHandlerImpl::pong( const MethodContext& context) +{ + client.ok(context.getRequestId()); +} + +void +BrokerAdapter::ChannelHandlerImpl::resume( + const MethodContext&, + const string& /*channel*/ ) +{ + assert(0); // FIXME aconway 2007-01-04: 0-9 feature +} + +}} // namespace qpid::broker + diff --git a/qpid/cpp/src/broker/BrokerAdapter.h b/qpid/cpp/src/broker/BrokerAdapter.h new file mode 100644 index 0000000000..4af45162f0 --- /dev/null +++ b/qpid/cpp/src/broker/BrokerAdapter.h @@ -0,0 +1,222 @@ +#ifndef _broker_BrokerAdapter_h +#define _broker_BrokerAdapter_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 "AMQP_ServerOperations.h" +#include "HandlerImpl.h" +#include "MessageHandlerImpl.h" +#include "../Exception.h" + +namespace qpid { +namespace broker { + +class Channel; +class Connection; +class Broker; +class ChannelHandler; +class ConnectionHandler; +class BasicHandler; +class ExchangeHandler; +class QueueHandler; +class TxHandler; +class MessageHandler; +class AccessHandler; +class FileHandler; +class StreamHandler; +class DtxHandler; +class TunnelHandler; +class MessageHandlerImpl; + +/** + * Per-channel protocol adapter. + * + * A container for a collection of AMQP-class adapters that translate + * AMQP method bodies into calls on the core Channel, Connection and + * Broker objects. Each adapter class also provides a client proxy + * to send methods to the peer. + * + */ +class BrokerAdapter : public CoreRefs, public framing::AMQP_ServerOperations +{ + public: + BrokerAdapter(Channel& ch, Connection& c, Broker& b); + + framing::ProtocolVersion getVersion() const; + ChannelHandler* getChannelHandler() { return &channelHandler; } + ConnectionHandler* getConnectionHandler() { return &connectionHandler; } + BasicHandler* getBasicHandler() { return &basicHandler; } + ExchangeHandler* getExchangeHandler() { return &exchangeHandler; } + QueueHandler* getQueueHandler() { return &queueHandler; } + TxHandler* getTxHandler() { return &txHandler; } + MessageHandler* getMessageHandler() { return &messageHandler; } + AccessHandler* getAccessHandler() { + throw ConnectionException(540, "Access class not implemented"); } + FileHandler* getFileHandler() { + throw ConnectionException(540, "File class not implemented"); } + StreamHandler* getStreamHandler() { + throw ConnectionException(540, "Stream class not implemented"); } + DtxHandler* getDtxHandler() { + throw ConnectionException(540, "Dtx class not implemented"); } + TunnelHandler* getTunnelHandler() { + throw ConnectionException(540, "Tunnel class not implemented"); } + + framing::AMQP_ClientProxy& getProxy() { return proxy; } + + private: + + class ConnectionHandlerImpl : + public ConnectionHandler, + public HandlerImpl + { + public: + ConnectionHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} + + void startOk(const framing::MethodContext& context, + const qpid::framing::FieldTable& clientProperties, + const std::string& mechanism, const std::string& response, + const std::string& locale); + void secureOk(const framing::MethodContext& context, + const std::string& response); + void tuneOk(const framing::MethodContext& context, + uint16_t channelMax, + uint32_t frameMax, uint16_t heartbeat); + void open(const framing::MethodContext& context, + const std::string& virtualHost, + const std::string& capabilities, bool insist); + void close(const framing::MethodContext& context, uint16_t replyCode, + const std::string& replyText, + uint16_t classId, uint16_t methodId); + void closeOk(const framing::MethodContext& context); + }; + + class ChannelHandlerImpl : + public ChannelHandler, + public HandlerImpl + { + public: + ChannelHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} + + void open(const framing::MethodContext& context, const std::string& outOfBand); + void flow(const framing::MethodContext& context, bool active); + void flowOk(const framing::MethodContext& context, bool active); + void ok( const framing::MethodContext& context ); + void ping( const framing::MethodContext& context ); + void pong( const framing::MethodContext& context ); + void resume( const framing::MethodContext& context, const std::string& channelId ); + void close(const framing::MethodContext& context, uint16_t replyCode, const + std::string& replyText, uint16_t classId, uint16_t methodId); + void closeOk(const framing::MethodContext& context); + }; + + class ExchangeHandlerImpl : + public ExchangeHandler, + public HandlerImpl + { + public: + ExchangeHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} + + void declare(const framing::MethodContext& context, uint16_t ticket, + const std::string& exchange, const std::string& type, + bool passive, bool durable, bool autoDelete, + bool internal, bool nowait, + const qpid::framing::FieldTable& arguments); + void delete_(const framing::MethodContext& context, uint16_t ticket, + const std::string& exchange, bool ifUnused, bool nowait); + }; + + class QueueHandlerImpl : + public QueueHandler, + public HandlerImpl + { + public: + QueueHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} + + void declare(const framing::MethodContext& context, uint16_t ticket, const std::string& queue, + bool passive, bool durable, bool exclusive, + bool autoDelete, bool nowait, + const qpid::framing::FieldTable& arguments); + void bind(const framing::MethodContext& context, uint16_t ticket, const std::string& queue, + const std::string& exchange, const std::string& routingKey, + bool nowait, const qpid::framing::FieldTable& arguments); + void unbind(const framing::MethodContext& context, + uint16_t ticket, + const std::string& queue, + const std::string& exchange, + const std::string& routingKey, + const qpid::framing::FieldTable& arguments ); + void purge(const framing::MethodContext& context, uint16_t ticket, const std::string& queue, + bool nowait); + void delete_(const framing::MethodContext& context, uint16_t ticket, const std::string& queue, + bool ifUnused, bool ifEmpty, + bool nowait); + }; + + class BasicHandlerImpl : + public BasicHandler, + public HandlerImpl + { + public: + BasicHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} + + void qos(const framing::MethodContext& context, uint32_t prefetchSize, + uint16_t prefetchCount, bool global); + void consume( + const framing::MethodContext& context, uint16_t ticket, const std::string& queue, + const std::string& consumerTag, bool noLocal, bool noAck, + bool exclusive, bool nowait, + const qpid::framing::FieldTable& fields); + void cancel(const framing::MethodContext& context, const std::string& consumerTag, + bool nowait); + void publish(const framing::MethodContext& context, uint16_t ticket, + const std::string& exchange, const std::string& routingKey, + bool mandatory, bool immediate); + void get(const framing::MethodContext& context, uint16_t ticket, const std::string& queue, + bool noAck); + void ack(const framing::MethodContext& context, uint64_t deliveryTag, bool multiple); + void reject(const framing::MethodContext& context, uint64_t deliveryTag, bool requeue); + void recover(const framing::MethodContext& context, bool requeue); + }; + + class TxHandlerImpl : + public TxHandler, + public HandlerImpl + { + public: + TxHandlerImpl(BrokerAdapter& parent) : HandlerImplType(parent) {} + + void select(const framing::MethodContext& context); + void commit(const framing::MethodContext& context); + void rollback(const framing::MethodContext& context); + }; + + Connection& connection; + BasicHandlerImpl basicHandler; + ChannelHandlerImpl channelHandler; + ConnectionHandlerImpl connectionHandler; + ExchangeHandlerImpl exchangeHandler; + MessageHandlerImpl messageHandler; + QueueHandlerImpl queueHandler; + TxHandlerImpl txHandler; + +}; +}} // namespace qpid::broker + + + +#endif /*!_broker_BrokerAdapter_h*/ diff --git a/qpid/cpp/src/broker/BrokerChannel.cpp b/qpid/cpp/src/broker/BrokerChannel.cpp new file mode 100644 index 0000000000..5f35f36da6 --- /dev/null +++ b/qpid/cpp/src/broker/BrokerChannel.cpp @@ -0,0 +1,346 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "BrokerChannel.h" +#include "DeletingTxOp.h" +#include "../framing/ChannelAdapter.h" +#include "../QpidError.h" +#include "DeliverableMessage.h" +#include "BrokerQueue.h" +#include "BrokerMessage.h" +#include "MessageStore.h" +#include "TxAck.h" +#include "TxPublish.h" +#include "BrokerAdapter.h" +#include "Connection.h" + +using std::mem_fun_ref; +using std::bind2nd; +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::sys; + + +Channel::Channel( + Connection& con, ChannelId id, + uint32_t _framesize, MessageStore* const _store, + uint64_t _stagingThreshold +) : + ChannelAdapter(id, &con.getOutput(), con.getVersion()), + connection(con), + currentDeliveryTag(1), + transactional(false), + prefetchSize(0), + prefetchCount(0), + framesize(_framesize), + tagGenerator("sgen"), + accumulatedAck(0), + store(_store), + messageBuilder(this, _store, _stagingThreshold), + opened(id == 0),//channel 0 is automatically open, other must be explicitly opened + adapter(new BrokerAdapter(*this, con, con.broker)) +{ + outstanding.reset(); +} + +Channel::~Channel(){ + close(); +} + +bool Channel::exists(const string& consumerTag){ + return consumers.find(consumerTag) != consumers.end(); +} + +// TODO aconway 2007-02-12: Why is connection token passed in instead +// of using the channel's parent connection? +void Channel::consume(string& tagInOut, Queue::shared_ptr queue, bool acks, + bool exclusive, ConnectionToken* const connection, + const FieldTable*) +{ + if(tagInOut.empty()) + tagInOut = tagGenerator.generate(); + std::auto_ptr c( + new ConsumerImpl(this, tagInOut, queue, connection, acks)); + queue->consume(c.get(), exclusive);//may throw exception + consumers.insert(tagInOut, c.release()); +} + +void Channel::cancel(const string& tag){ + // consumers is a ptr_map so erase will delete the consumer + // which will call cancel. + ConsumerImplMap::iterator i = consumers.find(tag); + if (i != consumers.end()) + consumers.erase(i); +} + +void Channel::close(){ + opened = false; + consumers.clear(); + recover(true); +} + +void Channel::begin(){ + transactional = true; +} + +void Channel::commit(){ + TxAck txAck(accumulatedAck, unacked); + txBuffer.enlist(&txAck); + if(txBuffer.prepare(store)){ + txBuffer.commit(); + } + accumulatedAck.clear(); +} + +void Channel::rollback(){ + txBuffer.rollback(); + accumulatedAck.clear(); +} + +void Channel::deliver( + Message::shared_ptr& msg, const string& consumerTag, + Queue::shared_ptr& queue, bool ackExpected) +{ + Mutex::ScopedLock locker(deliveryLock); + + // Key the delivered messages to the id of the request in which they're sent + uint64_t deliveryTag = getNextSendRequestId(); + + if(ackExpected){ + unacked.push_back(DeliveryRecord(msg, queue, consumerTag, deliveryTag)); + outstanding.size += msg->contentSize(); + outstanding.count++; + } + //send deliver method, header and content(s) + msg->deliver(*this, consumerTag, deliveryTag, framesize); +} + +bool Channel::checkPrefetch(Message::shared_ptr& msg){ + Mutex::ScopedLock locker(deliveryLock); + bool countOk = !prefetchCount || prefetchCount > unacked.size(); + bool sizeOk = !prefetchSize || prefetchSize > msg->contentSize() + outstanding.size || unacked.empty(); + return countOk && sizeOk; +} + +Channel::ConsumerImpl::ConsumerImpl(Channel* _parent, const string& _tag, + Queue::shared_ptr _queue, + ConnectionToken* const _connection, bool ack +) : parent(_parent), tag(_tag), queue(_queue), connection(_connection), + ackExpected(ack), blocked(false) {} + +bool Channel::ConsumerImpl::deliver(Message::shared_ptr& msg){ + if(!connection || connection != msg->getPublisher()){//check for no_local + if(ackExpected && !parent->checkPrefetch(msg)){ + blocked = true; + }else{ + blocked = false; + parent->deliver(msg, tag, queue, ackExpected); + return true; + } + } + return false; +} + +Channel::ConsumerImpl::~ConsumerImpl() { + cancel(); +} + +void Channel::ConsumerImpl::cancel(){ + if(queue) + queue->cancel(this); +} + +void Channel::ConsumerImpl::requestDispatch(){ + if(blocked) + queue->dispatch(); +} + +void Channel::handleInlineTransfer(Message::shared_ptr msg) +{ + Exchange::shared_ptr exchange = + connection.broker.getExchanges().get(msg->getExchange()); + if(transactional){ + TxPublish* deliverable = new TxPublish(msg); + exchange->route( + *deliverable, msg->getRoutingKey(), + &(msg->getApplicationHeaders())); + txBuffer.enlist(new DeletingTxOp(deliverable)); + }else{ + DeliverableMessage deliverable(msg); + exchange->route( + deliverable, msg->getRoutingKey(), + &(msg->getApplicationHeaders())); + } +} + +void Channel::handlePublish(Message* _message){ + Message::shared_ptr message(_message); + messageBuilder.initialise(message); +} + +void Channel::handleHeader(AMQHeaderBody::shared_ptr header){ + messageBuilder.setHeader(header); + //at this point, decide based on the size of the message whether we want + //to stage it by saving content directly to disk as it arrives +} + +void Channel::handleContent(AMQContentBody::shared_ptr content){ + messageBuilder.addContent(content); +} + +void Channel::handleHeartbeat(boost::shared_ptr) { + // TODO aconway 2007-01-17: Implement heartbeating. +} + +void Channel::complete(Message::shared_ptr msg) { + Exchange::shared_ptr exchange = + connection.broker.getExchanges().get(msg->getExchange()); + assert(exchange.get()); + if(transactional) { + std::auto_ptr deliverable(new TxPublish(msg)); + exchange->route(*deliverable, msg->getRoutingKey(), + &(msg->getApplicationHeaders())); + txBuffer.enlist(new DeletingTxOp(deliverable.release())); + } else { + DeliverableMessage deliverable(msg); + exchange->route(deliverable, msg->getRoutingKey(), + &(msg->getApplicationHeaders())); + } +} + +void Channel::ack(){ + ack(getFirstAckRequest(), getLastAckRequest()); +} + +// Used by Basic +void Channel::ack(uint64_t deliveryTag, bool multiple){ + if (multiple) + ack(0, deliveryTag); + else + ack(deliveryTag, deliveryTag); +} + +void Channel::ack(uint64_t firstTag, uint64_t lastTag){ + if(transactional){ + accumulatedAck.update(firstTag, lastTag); + + //TODO: I think the outstanding prefetch size & count should be updated at this point... + //TODO: ...this may then necessitate dispatching to consumers + }else{ + Mutex::ScopedLock locker(deliveryLock);//need to synchronize with possible concurrent delivery + + ack_iterator i = find_if(unacked.begin(), unacked.end(), bind2nd(mem_fun_ref(&DeliveryRecord::matches), lastTag)); + ack_iterator j = (firstTag == 0) ? + unacked.begin() : + find_if(unacked.begin(), unacked.end(), bind2nd(mem_fun_ref(&DeliveryRecord::matches), firstTag)); + + if(i == unacked.end()){ + throw ConnectionException(530, "Received ack for unrecognised delivery tag"); + }else if(i!=j){ + ack_iterator end = ++i; + for_each(j, end, bind2nd(mem_fun_ref(&DeliveryRecord::discard), 0)); + unacked.erase(unacked.begin(), end); + + //recalculate the prefetch: + outstanding.reset(); + for_each(unacked.begin(), unacked.end(), bind2nd(mem_fun_ref(&DeliveryRecord::addTo), &outstanding)); + }else{ + i->discard(); + i->subtractFrom(&outstanding); + unacked.erase(i); + } + + //if the prefetch limit had previously been reached, there may + //be messages that can be now be delivered + std::for_each(consumers.begin(), consumers.end(), + boost::bind(&ConsumerImpl::requestDispatch, _1)); + } +} + +void Channel::recover(bool requeue){ + Mutex::ScopedLock locker(deliveryLock);//need to synchronize with possible concurrent delivery + + if(requeue){ + outstanding.reset(); + std::list copy = unacked; + unacked.clear(); + for_each(copy.begin(), copy.end(), mem_fun_ref(&DeliveryRecord::requeue)); + }else{ + for_each(unacked.begin(), unacked.end(), bind2nd(mem_fun_ref(&DeliveryRecord::redeliver), this)); + } +} + +bool Channel::get(Queue::shared_ptr queue, const string& destination, bool ackExpected){ + Message::shared_ptr msg = queue->dequeue(); + if(msg){ + Mutex::ScopedLock locker(deliveryLock); + uint64_t myDeliveryTag = getNextSendRequestId(); + msg->sendGetOk(MethodContext(this, msg->getRespondTo()), + destination, + queue->getMessageCount() + 1, myDeliveryTag, + framesize); + if(ackExpected){ + unacked.push_back(DeliveryRecord(msg, queue, myDeliveryTag)); + } + return true; + }else{ + return false; + } +} + +void Channel::deliver(Message::shared_ptr& msg, const string& consumerTag, + uint64_t deliveryTag) +{ + msg->deliver(*this, consumerTag, deliveryTag, framesize); +} + +void Channel::handleMethodInContext( + boost::shared_ptr method, + const MethodContext& context +) +{ + try{ + if(getId() != 0 && !method->isA() && !isOpen()) { + std::stringstream out; + out << "Attempt to use unopened channel: " << getId(); + throw ConnectionException(504, out.str()); + } else { + method->invoke(*adapter, context); + } + }catch(ChannelException& e){ + adapter->getProxy().getChannel().close( + e.code, e.toString(), + method->amqpClassId(), method->amqpMethodId()); + connection.closeChannel(getId()); + }catch(ConnectionException& e){ + connection.close(e.code, e.toString(), method->amqpClassId(), method->amqpMethodId()); + }catch(std::exception& e){ + connection.close(541/*internal error*/, e.what(), method->amqpClassId(), method->amqpMethodId()); + } +} diff --git a/qpid/cpp/src/broker/BrokerChannel.h b/qpid/cpp/src/broker/BrokerChannel.h new file mode 100644 index 0000000000..e2a96aa467 --- /dev/null +++ b/qpid/cpp/src/broker/BrokerChannel.h @@ -0,0 +1,159 @@ +#ifndef _broker_BrokerChannel_h +#define _broker_BrokerChannel_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "AccumulatedAck.h" +#include "Consumer.h" +#include "DeliveryRecord.h" +#include "MessageBuilder.h" +#include "NameGenerator.h" +#include "Prefetch.h" +#include "TxBuffer.h" +#include "../framing/ChannelAdapter.h" +#include "ChannelOpenBody.h" +#include "CompletionHandler.h" + +namespace qpid { +namespace broker { + +class ConnectionToken; +class Connection; +class Queue; +class BrokerAdapter; + +using framing::string; + +/** + * Maintains state for an AMQP channel. Handles incoming and + * outgoing messages for that channel. + */ +class Channel : public framing::ChannelAdapter, + public CompletionHandler +{ + class ConsumerImpl : public Consumer + { + Channel* parent; + const string tag; + Queue::shared_ptr queue; + ConnectionToken* const connection; + const bool ackExpected; + bool blocked; + + public: + ConsumerImpl(Channel* parent, const string& tag, + Queue::shared_ptr queue, + ConnectionToken* const connection, bool ack); + ~ConsumerImpl(); + virtual bool deliver(Message::shared_ptr& msg); + void cancel(); + void requestDispatch(); + }; + + typedef boost::ptr_map ConsumerImplMap; + + Connection& connection; + uint64_t currentDeliveryTag; + Queue::shared_ptr defaultQueue; + bool transactional; + ConsumerImplMap consumers; + uint32_t prefetchSize; + uint16_t prefetchCount; + Prefetch outstanding; + uint32_t framesize; + NameGenerator tagGenerator; + std::list unacked; + sys::Mutex deliveryLock; + TxBuffer txBuffer; + AccumulatedAck accumulatedAck; + MessageStore* const store; + MessageBuilder messageBuilder;//builder for in-progress message + bool opened; + boost::scoped_ptr adapter; + + // completion handler for MessageBuilder + void complete(Message::shared_ptr msg); + + void deliver(Message::shared_ptr& msg, const string& tag, + Queue::shared_ptr& queue, bool ackExpected); + bool checkPrefetch(Message::shared_ptr& msg); + + public: + Channel(Connection& parent, + framing::ChannelId id, + uint32_t framesize, + MessageStore* const _store = 0, + uint64_t stagingThreshold = 0); + + ~Channel(); + + bool isOpen() const { return opened; } + BrokerAdapter& getAdatper() { return *adapter; } + + void open() { opened = true; } + void setDefaultQueue(Queue::shared_ptr queue){ defaultQueue = queue; } + Queue::shared_ptr getDefaultQueue() const { return defaultQueue; } + uint32_t setPrefetchSize(uint32_t size){ return prefetchSize = size; } + uint16_t setPrefetchCount(uint16_t n){ return prefetchCount = n; } + + bool exists(const string& consumerTag); + + /** + *@param tagInOut - if empty it is updated with the generated token. + */ + void consume(string& tagInOut, Queue::shared_ptr queue, bool acks, + bool exclusive, ConnectionToken* const connection = 0, + const framing::FieldTable* = 0); + void cancel(const string& tag); + bool get(Queue::shared_ptr queue, const std::string& destination, bool ackExpected); + void begin(); + void close(); + void commit(); + void rollback(); + void ack(); + void ack(uint64_t deliveryTag, bool multiple); + void ack(uint64_t deliveryTag, uint64_t endTag); + void recover(bool requeue); + void deliver(Message::shared_ptr& msg, const string& consumerTag, uint64_t deliveryTag); + void handlePublish(Message* msg); + void handleHeader(boost::shared_ptr); + void handleContent(boost::shared_ptr); + void handleHeartbeat(boost::shared_ptr); + + void handleInlineTransfer(Message::shared_ptr msg); + + // For ChannelAdapter + void handleMethodInContext( + boost::shared_ptr method, + const framing::MethodContext& context); +}; + +}} // namespace broker + + +#endif /*!_broker_BrokerChannel_h*/ diff --git a/qpid/cpp/src/broker/BrokerExchange.h b/qpid/cpp/src/broker/BrokerExchange.h new file mode 100644 index 0000000000..07a411335a --- /dev/null +++ b/qpid/cpp/src/broker/BrokerExchange.h @@ -0,0 +1,51 @@ +#ifndef _broker_BrokerExchange_h +#define _broker_BrokerExchange_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "Deliverable.h" +#include "BrokerQueue.h" +#include "../framing/FieldTable.h" + +namespace qpid { + namespace broker { + using std::string; + + class Exchange{ + const string name; + public: + typedef boost::shared_ptr shared_ptr; + + explicit Exchange(const string& _name) : name(_name){} + virtual ~Exchange(){} + string getName() { return name; } + virtual string getType() = 0; + virtual void bind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args) = 0; + virtual void unbind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args) = 0; + virtual void route(Deliverable& msg, const string& routingKey, const qpid::framing::FieldTable* args) = 0; + }; + } +} + + +#endif /*!_broker_BrokerExchange_h*/ diff --git a/qpid/cpp/src/broker/BrokerMessage.cpp b/qpid/cpp/src/broker/BrokerMessage.cpp new file mode 100644 index 0000000000..06765bcaa9 --- /dev/null +++ b/qpid/cpp/src/broker/BrokerMessage.cpp @@ -0,0 +1,244 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "BrokerMessage.h" +#include + +#include "InMemoryContent.h" +#include "LazyLoadedContent.h" +#include "MessageStore.h" +#include "BasicDeliverBody.h" +#include "BasicGetOkBody.h" +#include "../framing/AMQContentBody.h" +#include "../framing/AMQHeaderBody.h" +#include "../framing/AMQMethodBody.h" +#include "../framing/AMQFrame.h" +#include "../framing/ChannelAdapter.h" +#include "RecoveryManagerImpl.h" + +using namespace boost; +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::sys; + +BasicMessage::BasicMessage( + const ConnectionToken* const _publisher, + const string& _exchange, const string& _routingKey, + bool _mandatory, bool _immediate, framing::AMQMethodBody::shared_ptr respondTo +) : + Message(_publisher, _exchange, _routingKey, _mandatory, + _immediate, respondTo), + size(0) +{} + +// For tests only. +BasicMessage::BasicMessage() : size(0) +{} + +BasicMessage::~BasicMessage(){} + +void BasicMessage::setHeader(AMQHeaderBody::shared_ptr _header){ + this->header = _header; +} + +void BasicMessage::addContent(AMQContentBody::shared_ptr data){ + if (!content.get()) { + content = std::auto_ptr(new InMemoryContent()); + } + content->add(data); + size += data->size(); +} + +bool BasicMessage::isComplete(){ + return header.get() && (header->getContentSize() == contentSize()); +} + +void BasicMessage::deliver(ChannelAdapter& channel, + const string& consumerTag, uint64_t deliveryTag, + uint32_t framesize) +{ + // CCT -- TODO - Update code generator to take pointer/ not + // instance to avoid extra contruction + channel.send( + new BasicDeliverBody( + channel.getVersion(), consumerTag, deliveryTag, + getRedelivered(), getExchange(), getRoutingKey())); + sendContent(channel, framesize); +} + +void BasicMessage::sendGetOk(const MethodContext& context, + const std::string& /*destination*/, + uint32_t messageCount, + uint64_t deliveryTag, + uint32_t framesize) +{ + // CCT -- TODO - Update code generator to take pointer/ not + // instance to avoid extra contruction + context.channel->send( + new BasicGetOkBody( + context.channel->getVersion(), + context.methodBody->getRequestId(), + deliveryTag, getRedelivered(), getExchange(), + getRoutingKey(), messageCount)); + sendContent(*context.channel, framesize); +} + +void BasicMessage::sendContent( + ChannelAdapter& channel, uint32_t framesize) +{ + channel.send(header); + Mutex::ScopedLock locker(contentLock); + if (content.get()) + content->send(channel, framesize); +} + +BasicHeaderProperties* BasicMessage::getHeaderProperties(){ + return boost::polymorphic_downcast( + header->getProperties()); +} + +const FieldTable& BasicMessage::getApplicationHeaders(){ + return getHeaderProperties()->getHeaders(); +} + +bool BasicMessage::isPersistent() +{ + if(!header) return false; + BasicHeaderProperties* props = getHeaderProperties(); + return props && props->getDeliveryMode() == PERSISTENT; +} + +void BasicMessage::decode(Buffer& buffer, bool headersOnly, uint32_t contentChunkSize) +{ + decodeHeader(buffer); + if (!headersOnly) decodeContent(buffer, contentChunkSize); +} + +void BasicMessage::decodeHeader(Buffer& buffer) +{ + //don't care about the type here, but want encode/decode to be symmetric + RecoveryManagerImpl::decodeMessageType(buffer); + + string exchange; + string routingKey; + + buffer.getShortString(exchange); + buffer.getShortString(routingKey); + setRouting(exchange, routingKey); + + uint32_t headerSize = buffer.getLong(); + AMQHeaderBody::shared_ptr headerBody(new AMQHeaderBody()); + headerBody->decode(buffer, headerSize); + setHeader(headerBody); +} + +void BasicMessage::decodeContent(Buffer& buffer, uint32_t chunkSize) +{ + uint64_t expected = expectedContentSize(); + if (expected != buffer.available()) { + std::cout << "WARN: Expected " << expectedContentSize() << " bytes, got " << buffer.available() << std::endl; + throw Exception("Cannot decode content, buffer not large enough."); + } + + if (!chunkSize || chunkSize > expected) { + chunkSize = expected; + } + + uint64_t total = 0; + while (total < expectedContentSize()) { + uint64_t remaining = expected - total; + AMQContentBody::shared_ptr contentBody(new AMQContentBody()); + contentBody->decode(buffer, remaining < chunkSize ? remaining : chunkSize); + addContent(contentBody); + total += chunkSize; + } +} + +void BasicMessage::encode(Buffer& buffer) const +{ + encodeHeader(buffer); + encodeContent(buffer); +} + +void BasicMessage::encodeHeader(Buffer& buffer) const +{ + RecoveryManagerImpl::encodeMessageType(*this, buffer); + buffer.putShortString(getExchange()); + buffer.putShortString(getRoutingKey()); + buffer.putLong(header->size()); + header->encode(buffer); +} + +void BasicMessage::encodeContent(Buffer& buffer) const +{ + Mutex::ScopedLock locker(contentLock); + if (content.get()) content->encode(buffer); +} + +uint32_t BasicMessage::encodedSize() const +{ + return encodedHeaderSize() + encodedContentSize(); +} + +uint32_t BasicMessage::encodedContentSize() const +{ + Mutex::ScopedLock locker(contentLock); + return content.get() ? content->size() : 0; +} + +uint32_t BasicMessage::encodedHeaderSize() const +{ + return RecoveryManagerImpl::encodedMessageTypeSize() + +getExchange().size() + 1 + + getRoutingKey().size() + 1 + + header->size() + 4;//4 extra bytes for size +} + +uint64_t BasicMessage::expectedContentSize() +{ + return header.get() ? header->getContentSize() : 0; +} + +void BasicMessage::releaseContent(MessageStore* store) +{ + Mutex::ScopedLock locker(contentLock); + if (!isPersistent() && getPersistenceId() == 0) { + store->stage(*this); + } + if (!content.get() || content->size() > 0) { + //set content to lazy loading mode (but only if there is + //stored content): + + //Note: the LazyLoadedContent instance contains a raw pointer + //to the message, however it is then set as a member of that + //message so its lifetime is guaranteed to be no longer than + //that of the message itself + content = std::auto_ptr( + new LazyLoadedContent(store, this, expectedContentSize())); + } +} + +void BasicMessage::setContent(std::auto_ptr& _content) +{ + Mutex::ScopedLock locker(contentLock); + content = _content; +} diff --git a/qpid/cpp/src/broker/BrokerMessage.h b/qpid/cpp/src/broker/BrokerMessage.h new file mode 100644 index 0000000000..1d13183f43 --- /dev/null +++ b/qpid/cpp/src/broker/BrokerMessage.h @@ -0,0 +1,137 @@ +#ifndef _broker_BrokerMessage_h +#define _broker_BrokerMessage_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "BrokerMessageBase.h" +#include "../framing/BasicHeaderProperties.h" +#include "ConnectionToken.h" +#include "Content.h" +#include "../sys/Mutex.h" +#include "TxBuffer.h" + +namespace qpid { + +namespace framing { +class MethodContext; +class ChannelAdapter; +class AMQHeaderBody; +} + +namespace broker { + +class MessageStore; +using framing::string; + +/** + * Represents an AMQP message, i.e. a header body, a list of + * content bodies and some details about the publication + * request. + */ +class BasicMessage : public Message { + boost::shared_ptr header; + std::auto_ptr content; + mutable sys::Mutex contentLock; + uint64_t size; + + void sendContent(framing::ChannelAdapter&, uint32_t framesize); + + public: + typedef boost::shared_ptr shared_ptr; + + BasicMessage(const ConnectionToken* const publisher, + const string& exchange, const string& routingKey, + bool mandatory, bool immediate, + boost::shared_ptr respondTo); + BasicMessage(); + ~BasicMessage(); + void setHeader(boost::shared_ptr header); + void addContent(framing::AMQContentBody::shared_ptr data); + bool isComplete(); + + void deliver(framing::ChannelAdapter&, + const string& consumerTag, + uint64_t deliveryTag, + uint32_t framesize); + + void sendGetOk(const framing::MethodContext&, + const std::string& destination, + uint32_t messageCount, + uint64_t deliveryTag, + uint32_t framesize); + + framing::BasicHeaderProperties* getHeaderProperties(); + const framing::FieldTable& getApplicationHeaders(); + bool isPersistent(); + uint64_t contentSize() const { return size; } + + void decode(framing::Buffer& buffer, bool headersOnly = false, + uint32_t contentChunkSize = 0); + void decodeHeader(framing::Buffer& buffer); + void decodeContent(framing::Buffer& buffer, uint32_t contentChunkSize = 0); + + void encode(framing::Buffer& buffer) const; + void encodeHeader(framing::Buffer& buffer) const; + void encodeContent(framing::Buffer& buffer) const; + /** + * @returns the size of the buffer needed to encode this + * message in its entirety + */ + 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; + /** + * @returns the size of the buffer needed to encode the + * (possibly partial) content held by this message + */ + uint32_t encodedContentSize() const; + /** + * Releases the in-memory content data held by this + * message. Must pass in a store from which the data can + * be reloaded. + */ + void releaseContent(MessageStore* store); + /** + * If headers have been received, returns the expected + * content size else returns 0. + */ + uint64_t expectedContentSize(); + /** + * Sets the 'content' implementation of this message (the + * message controls the lifecycle of the content instance + * it uses). + */ + void setContent(std::auto_ptr& content); +}; + +} +} + + +#endif /*!_broker_BrokerMessage_h*/ diff --git a/qpid/cpp/src/broker/BrokerMessageBase.h b/qpid/cpp/src/broker/BrokerMessageBase.h new file mode 100644 index 0000000000..93178774dd --- /dev/null +++ b/qpid/cpp/src/broker/BrokerMessageBase.h @@ -0,0 +1,182 @@ +#ifndef _broker_BrokerMessageBase_h +#define _broker_BrokerMessageBase_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "Content.h" +#include "PersistableMessage.h" +#include "../framing/amqp_types.h" + +namespace qpid { + +namespace framing { +class MethodContext; +class ChannelAdapter; +class BasicHeaderProperties; +class FieldTable; +class AMQMethodBody; +class AMQContentBody; +class AMQHeaderBody; +} + + +namespace broker { +class ConnectionToken; +class MessageStore; + +/** + * Base class for all types of internal broker messages + * abstracting away the operations + * TODO; AMS: for the moment this is mostly a placeholder + */ +class Message : public PersistableMessage{ + public: + typedef boost::shared_ptr shared_ptr; + typedef boost::shared_ptr AMQMethodBodyPtr; + + + Message(const ConnectionToken* publisher_, + const std::string& _exchange, + const std::string& _routingKey, + bool _mandatory, bool _immediate, + AMQMethodBodyPtr respondTo_) : + publisher(publisher_), + exchange(_exchange), + routingKey(_routingKey), + mandatory(_mandatory), + immediate(_immediate), + persistenceId(0), + redelivered(false), + respondTo(respondTo_) + {} + + Message() : + mandatory(false), + immediate(false), + persistenceId(0), + redelivered(false) + {} + + virtual ~Message() {}; + + // Accessors + const std::string& getRoutingKey() const { return routingKey; } + const std::string& getExchange() const { return exchange; } + uint64_t getPersistenceId() const { return persistenceId; } + bool getRedelivered() const { return redelivered; } + AMQMethodBodyPtr getRespondTo() const { return respondTo; } + + void setRouting(const std::string& _exchange, const std::string& _routingKey) + { exchange = _exchange; routingKey = _routingKey; } + void setPersistenceId(uint64_t _persistenceId) { persistenceId = _persistenceId; } // XXXX: Only used in tests? + void redeliver() { redelivered = true; } + + /** + * Used to deliver the message from the queue + */ + virtual void deliver(framing::ChannelAdapter& channel, + const std::string& consumerTag, + uint64_t deliveryTag, + uint32_t framesize) = 0; + /** + * Used to return a message in response to a get from a queue + */ + virtual void sendGetOk(const framing::MethodContext& context, + const std::string& destination, + uint32_t messageCount, + uint64_t deliveryTag, + uint32_t framesize) = 0; + + virtual bool isComplete() = 0; + + virtual uint64_t contentSize() const = 0; + virtual framing::BasicHeaderProperties* getHeaderProperties() = 0; + virtual const framing::FieldTable& getApplicationHeaders() = 0; + virtual bool isPersistent() = 0; + virtual const ConnectionToken* getPublisher() const { + return publisher; + } + + virtual void encode(framing::Buffer& buffer) const = 0; + virtual void encodeHeader(framing::Buffer& buffer) const = 0; + + /** + * @returns the size of the buffer needed to encode this + * message in its entirety + */ + virtual uint32_t encodedSize() const = 0; + /** + * @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) + */ + virtual uint32_t encodedHeaderSize() const = 0; + /** + * @returns the size of the buffer needed to encode the + * (possibly partial) content held by this message + */ + virtual uint32_t encodedContentSize() const = 0; + /** + * If headers have been received, returns the expected + * content size else returns 0. + */ + virtual uint64_t expectedContentSize() = 0; + + virtual void decodeHeader(framing::Buffer& buffer) = 0; + virtual void decodeContent(framing::Buffer& buffer, uint32_t contentChunkSize = 0) = 0; + + static shared_ptr decode(framing::Buffer& buffer); + + // TODO: AMS 29/1/2007 Don't think these are really part of base class + + /** + * Sets the 'content' implementation of this message (the + * message controls the lifecycle of the content instance + * it uses). + */ + virtual void setContent(std::auto_ptr& /*content*/) {}; + virtual void setHeader(boost::shared_ptr) {}; + virtual void addContent(boost::shared_ptr) {}; + /** + * Releases the in-memory content data held by this + * message. Must pass in a store from which the data can + * be reloaded. + */ + virtual void releaseContent(MessageStore* /*store*/) {}; + + private: + const ConnectionToken* publisher; + std::string exchange; + std::string routingKey; + const bool mandatory; + const bool immediate; + uint64_t persistenceId; + bool redelivered; + AMQMethodBodyPtr respondTo; +}; + +}} + + +#endif /*!_broker_BrokerMessage_h*/ diff --git a/qpid/cpp/src/broker/BrokerMessageMessage.cpp b/qpid/cpp/src/broker/BrokerMessageMessage.cpp new file mode 100644 index 0000000000..f320a0915e --- /dev/null +++ b/qpid/cpp/src/broker/BrokerMessageMessage.cpp @@ -0,0 +1,305 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../QpidError.h" +#include "BrokerMessageMessage.h" +#include "../framing/ChannelAdapter.h" +#include "MessageTransferBody.h" +#include "MessageOpenBody.h" +#include "MessageCloseBody.h" +#include "MessageAppendBody.h" +#include "Reference.h" +#include "../framing/AMQFrame.h" +#include "../framing/FieldTable.h" +#include "../framing/BasicHeaderProperties.h" +#include "RecoveryManagerImpl.h" + +#include + +using namespace std; +using namespace qpid::framing; + +namespace qpid { +namespace broker { + +MessageMessage::MessageMessage( + ConnectionToken* publisher, RequestId requestId_, TransferPtr transfer_ +) : Message(publisher, transfer_->getDestination(), + transfer_->getRoutingKey(), + transfer_->getMandatory(), + transfer_->getImmediate(), + transfer_), + requestId(requestId_), + transfer(transfer_) +{} + +MessageMessage::MessageMessage( + ConnectionToken* publisher, RequestId requestId_, TransferPtr transfer_, + ReferencePtr reference_ +) : Message(publisher, transfer_->getDestination(), + transfer_->getRoutingKey(), + transfer_->getMandatory(), + transfer_->getImmediate(), + transfer_), + requestId(requestId_), + transfer(transfer_), + reference(reference_) +{} + +/** + * Currently used by message store impls to recover messages + */ +MessageMessage::MessageMessage() : transfer(new MessageTransferBody(qpid::framing::highestProtocolVersion)) {} + +// TODO: astitcher 1-Mar-2007: This code desperately needs better factoring +void MessageMessage::transferMessage( + framing::ChannelAdapter& channel, + const std::string& consumerTag, + uint32_t framesize) +{ + const framing::Content& body = transfer->getBody(); + + // Send any reference data + if (!body.isInline()){ + // Open + channel.send(new MessageOpenBody(channel.getVersion(), reference->getId())); + // Appends + for(Reference::Appends::const_iterator a = reference->getAppends().begin(); + a != reference->getAppends().end(); + ++a) { + uint32_t sizeleft = (*a)->size(); + const string& content = (*a)->getBytes(); + // Calculate overhead bytes + // Assume that the overhead is constant as the reference name doesn't change + uint32_t overhead = sizeleft - content.size(); + string::size_type contentStart = 0; + while (sizeleft) { + string::size_type contentSize = sizeleft <= framesize ? sizeleft : framesize-overhead; + channel.send(new MessageAppendBody(channel.getVersion(), reference->getId(), + string(content, contentStart, contentSize))); + sizeleft -= contentSize; + contentStart += contentSize; + } + } + } + + // The transfer + if ( transfer->size()<=framesize ) { + channel.send( + new MessageTransferBody(channel.getVersion(), + transfer->getTicket(), + consumerTag, + getRedelivered(), + transfer->getImmediate(), + transfer->getTtl(), + transfer->getPriority(), + transfer->getTimestamp(), + transfer->getDeliveryMode(), + transfer->getExpiration(), + getExchange(), + getRoutingKey(), + transfer->getMessageId(), + transfer->getCorrelationId(), + transfer->getReplyTo(), + transfer->getContentType(), + transfer->getContentEncoding(), + transfer->getUserId(), + transfer->getAppId(), + transfer->getTransactionId(), + transfer->getSecurityToken(), + transfer->getApplicationHeaders(), + body, + transfer->getMandatory())); + } else { + // Thing to do here is to construct a simple reference message then deliver that instead + // fragmentation will be taken care of in the delivery if necessary; + string content = body.getValue(); + string refname = "dummy"; + TransferPtr newTransfer( + new MessageTransferBody(channel.getVersion(), + transfer->getTicket(), + consumerTag, + getRedelivered(), + transfer->getImmediate(), + transfer->getTtl(), + transfer->getPriority(), + transfer->getTimestamp(), + transfer->getDeliveryMode(), + transfer->getExpiration(), + getExchange(), + getRoutingKey(), + transfer->getMessageId(), + transfer->getCorrelationId(), + transfer->getReplyTo(), + transfer->getContentType(), + transfer->getContentEncoding(), + transfer->getUserId(), + transfer->getAppId(), + transfer->getTransactionId(), + transfer->getSecurityToken(), + transfer->getApplicationHeaders(), + framing::Content(REFERENCE, refname), + transfer->getMandatory())); + ReferencePtr newRef(new Reference(refname)); + Reference::AppendPtr newAppend(new MessageAppendBody(channel.getVersion(), refname, content)); + newRef->append(newAppend); + MessageMessage newMsg(const_cast(getPublisher()), 0, newTransfer, newRef); + newMsg.transferMessage(channel, consumerTag, framesize); + return; + } + // Close any reference data + if (!body.isInline()){ + // Close + channel.send(new MessageCloseBody(channel.getVersion(), reference->getId())); + } +} + +void MessageMessage::deliver( + framing::ChannelAdapter& channel, + const std::string& consumerTag, + uint64_t /*deliveryTag*/, + uint32_t framesize) +{ + transferMessage(channel, consumerTag, framesize); +} + +void MessageMessage::sendGetOk( + const framing::MethodContext& context, + const std::string& destination, + uint32_t /*messageCount*/, + uint64_t /*deliveryTag*/, + uint32_t framesize) +{ + framing::ChannelAdapter* channel = context.channel; + transferMessage(*channel, destination, framesize); +} + +bool MessageMessage::isComplete() +{ + return true; +} + +uint64_t MessageMessage::contentSize() const +{ + if (transfer->getBody().isInline()) + return transfer->getBody().getValue().size(); + else + return reference->getSize(); +} + +qpid::framing::BasicHeaderProperties* MessageMessage::getHeaderProperties() +{ + return 0; // FIXME aconway 2007-02-05: +} + +const FieldTable& MessageMessage::getApplicationHeaders() +{ + return transfer->getApplicationHeaders(); +} +bool MessageMessage::isPersistent() +{ + return transfer->getDeliveryMode() == PERSISTENT; +} + +uint32_t MessageMessage::encodedSize() const +{ + return encodedHeaderSize() + encodedContentSize(); +} + +uint32_t MessageMessage::encodedHeaderSize() const +{ + return RecoveryManagerImpl::encodedMessageTypeSize() + transfer->size() - transfer->baseSize(); +} + +uint32_t MessageMessage::encodedContentSize() const +{ + return 0; +} + +uint64_t MessageMessage::expectedContentSize() +{ + return 0; +} + +void MessageMessage::encode(Buffer& buffer) const +{ + encodeHeader(buffer); +} + +void MessageMessage::encodeHeader(Buffer& buffer) const +{ + RecoveryManagerImpl::encodeMessageType(*this, buffer); + if (transfer->getBody().isInline()) { + transfer->encodeContent(buffer); + } else { + string data; + for(Reference::Appends::const_iterator a = reference->getAppends().begin(); a != reference->getAppends().end(); ++a) { + data += (*a)->getBytes(); + } + framing::Content body(INLINE, data); + std::auto_ptr copy(copyTransfer(transfer->version, transfer->getDestination(), body)); + copy->encodeContent(buffer); + } +} + +void MessageMessage::decodeHeader(Buffer& buffer) +{ + //don't care about the type here, but want encode/decode to be symmetric + RecoveryManagerImpl::decodeMessageType(buffer); + + transfer->decodeContent(buffer); +} + +void MessageMessage::decodeContent(Buffer& /*buffer*/, uint32_t /*chunkSize*/) +{ +} + + +MessageTransferBody* MessageMessage::copyTransfer(const ProtocolVersion& version, + const string& destination, + const framing::Content& body) const +{ + return new MessageTransferBody(version, + transfer->getTicket(), + destination, + getRedelivered(), + transfer->getImmediate(), + transfer->getTtl(), + transfer->getPriority(), + transfer->getTimestamp(), + transfer->getDeliveryMode(), + transfer->getExpiration(), + getExchange(), + getRoutingKey(), + transfer->getMessageId(), + transfer->getCorrelationId(), + transfer->getReplyTo(), + transfer->getContentType(), + transfer->getContentEncoding(), + transfer->getUserId(), + transfer->getAppId(), + transfer->getTransactionId(), + transfer->getSecurityToken(), + transfer->getApplicationHeaders(), + body, + transfer->getMandatory()); + +} +}} // namespace qpid::broker diff --git a/qpid/cpp/src/broker/BrokerMessageMessage.h b/qpid/cpp/src/broker/BrokerMessageMessage.h new file mode 100644 index 0000000000..88ac07ecc3 --- /dev/null +++ b/qpid/cpp/src/broker/BrokerMessageMessage.h @@ -0,0 +1,99 @@ +#ifndef _broker_BrokerMessageMessage_h +#define _broker_BrokerMessageMessage_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "BrokerMessageBase.h" +#include "MessageTransferBody.h" +#include "../framing/amqp_types.h" + +#include + +namespace qpid { + +namespace framing { +class MessageTransferBody; +} + +namespace broker { +class ConnectionToken; +class Reference; + +class MessageMessage: public Message{ + public: + typedef boost::shared_ptr shared_ptr; + typedef boost::shared_ptr TransferPtr; + typedef boost::shared_ptr ReferencePtr; + + MessageMessage(ConnectionToken* publisher, framing::RequestId, TransferPtr transfer); + MessageMessage(ConnectionToken* publisher, framing::RequestId, TransferPtr transfer, ReferencePtr reference); + MessageMessage(); + + // Default destructor okay + + framing::RequestId getRequestId() {return requestId; } + TransferPtr getTransfer() { return transfer; } + ReferencePtr getReference() { return reference; } + + void deliver(framing::ChannelAdapter& channel, + const std::string& consumerTag, + uint64_t deliveryTag, + uint32_t framesize); + + void sendGetOk(const framing::MethodContext& context, + const std::string& destination, + uint32_t messageCount, + uint64_t deliveryTag, + uint32_t framesize); + + bool isComplete(); + + uint64_t contentSize() const; + framing::BasicHeaderProperties* getHeaderProperties(); + const framing::FieldTable& getApplicationHeaders(); + bool isPersistent(); + + void encode(framing::Buffer& buffer) const; + void encodeHeader(framing::Buffer& buffer) const; + uint32_t encodedSize() const; + uint32_t encodedHeaderSize() const; + uint32_t encodedContentSize() const; + uint64_t expectedContentSize(); + void decodeHeader(framing::Buffer& buffer); + void decodeContent(framing::Buffer& buffer, uint32_t contentChunkSize = 0); + + private: + void transferMessage(framing::ChannelAdapter& channel, + const std::string& consumerTag, + uint32_t framesize); + framing::MessageTransferBody* copyTransfer(const framing::ProtocolVersion& version, + const std::string& destination, + const framing::Content& body) const; + + framing::RequestId requestId; + const TransferPtr transfer; + const ReferencePtr reference; +}; + +}} + + +#endif /*!_broker_BrokerMessage_h*/ diff --git a/qpid/cpp/src/broker/BrokerQueue.cpp b/qpid/cpp/src/broker/BrokerQueue.cpp new file mode 100644 index 0000000000..08288a9dbd --- /dev/null +++ b/qpid/cpp/src/broker/BrokerQueue.cpp @@ -0,0 +1,282 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "BrokerQueue.h" +#include "MessageStore.h" +#include "../sys/Monitor.h" +#include "../sys/Time.h" +#include +#include "QueueRegistry.h" + +using namespace qpid::broker; +using namespace qpid::sys; +using namespace qpid::framing; +using boost::format; + +Queue::Queue(const string& _name, uint32_t _autodelete, + MessageStore* const _store, + const ConnectionToken* const _owner) : + + name(_name), + autodelete(_autodelete), + store(_store), + owner(_owner), + queueing(false), + dispatching(false), + next(0), + lastUsed(0), + exclusive(0), + persistenceId(0) +{ + if(autodelete) lastUsed = now()/TIME_MSEC; +} + +Queue::~Queue(){} + +void Queue::deliver(Message::shared_ptr& msg){ + enqueue(0, msg); + process(msg); +} + +void Queue::recover(Message::shared_ptr& msg){ + push(msg); + if (store && msg->expectedContentSize() != msg->encodedContentSize()) { + //content has not been loaded, need to ensure that lazy loading mode is set: + //TODO: find a nicer way to do this + msg->releaseContent(store); + } +} + +void Queue::process(Message::shared_ptr& msg){ + Mutex::ScopedLock locker(lock); + if(queueing || !dispatch(msg)){ + push(msg); + } +} + +bool Queue::dispatch(Message::shared_ptr& msg){ + if(consumers.empty()){ + return false; + }else if(exclusive){ + if(!exclusive->deliver(msg)){ + std::cout << "WARNING: Dropping undeliverable message from queue with exclusive consumer." << std::endl; + } + return true; + }else{ + //deliver to next consumer + next = next % consumers.size(); + Consumer* c = consumers[next]; + int start = next; + while(c){ + next++; + if(c->deliver(msg)) return true; + + next = next % consumers.size(); + c = next == start ? 0 : consumers[next]; + } + return false; + } +} + +bool Queue::startDispatching(){ + Mutex::ScopedLock locker(lock); + if(queueing && !dispatching){ + dispatching = true; + return true; + }else{ + return false; + } +} + +void Queue::dispatch(){ + bool proceed = startDispatching(); + while(proceed){ + Mutex::ScopedLock locker(lock); + if(!messages.empty() && dispatch(messages.front())){ + pop(); + }else{ + dispatching = false; + proceed = false; + queueing = !messages.empty(); + } + } +} + +void Queue::consume(Consumer* c, bool requestExclusive){ + Mutex::ScopedLock locker(lock); + if(exclusive) + throw ChannelException( + 403, format("Queue '%s' has an exclusive consumer." + " No more consumers allowed.") % getName()); + if(requestExclusive) { + if(!consumers.empty()) + throw ChannelException( + 403, format("Queue '%s' already has conumers." + "Exclusive access denied.") %getName()); + exclusive = c; + } + if(autodelete && consumers.empty()) lastUsed = 0; + consumers.push_back(c); +} + +void Queue::cancel(Consumer* c){ + Mutex::ScopedLock locker(lock); + Consumers::iterator i = std::find(consumers.begin(), consumers.end(), c); + if (i != consumers.end()) + consumers.erase(i); + if(autodelete && consumers.empty()) lastUsed = now()*TIME_MSEC; + if(exclusive == c) exclusive = 0; +} + +Message::shared_ptr Queue::dequeue(){ + Mutex::ScopedLock locker(lock); + Message::shared_ptr msg; + if(!messages.empty()){ + msg = messages.front(); + pop(); + } + return msg; +} + +uint32_t Queue::purge(){ + Mutex::ScopedLock locker(lock); + int count = messages.size(); + while(!messages.empty()) pop(); + return count; +} + +void Queue::pop(){ + if (policy.get()) policy->dequeued(messages.front()->contentSize()); + messages.pop(); +} + +void Queue::push(Message::shared_ptr& msg){ + queueing = true; + messages.push(msg); + if (policy.get()) { + policy->enqueued(msg->contentSize()); + if (policy->limitExceeded()) { + msg->releaseContent(store); + } + } +} + +uint32_t Queue::getMessageCount() const{ + Mutex::ScopedLock locker(lock); + return messages.size(); +} + +uint32_t Queue::getConsumerCount() const{ + Mutex::ScopedLock locker(lock); + return consumers.size(); +} + +bool Queue::canAutoDelete() const{ + Mutex::ScopedLock locker(lock); + return lastUsed && (now()*TIME_MSEC - lastUsed > autodelete); +} + +void Queue::enqueue(TransactionContext* ctxt, Message::shared_ptr& msg) +{ + if (msg->isPersistent() && store) { + store->enqueue(ctxt, *msg.get(), *this); + } +} + +void Queue::dequeue(TransactionContext* ctxt, Message::shared_ptr& msg) +{ + if (msg->isPersistent() && store) { + store->dequeue(ctxt, *msg.get(), *this); + } +} + +namespace +{ + const std::string qpidMaxSize("qpid.max_size"); + const std::string qpidMaxCount("qpid.max_count"); +} + +void Queue::create(const FieldTable& settings) +{ + //TODO: hold onto settings and persist them as part of encode + // in fact settings should be passed in on construction + if (store) { + store->create(*this); + } + configure(settings); +} + +void Queue::configure(const FieldTable& settings) +{ + std::auto_ptr _policy(new QueuePolicy(settings)); + if (_policy->getMaxCount() || _policy->getMaxSize()) + setPolicy(_policy); +} + +void Queue::destroy() +{ + if (store) { + store->destroy(*this); + } +} + +void Queue::setPolicy(std::auto_ptr _policy) +{ + policy = _policy; +} + +const QueuePolicy* const Queue::getPolicy() +{ + return policy.get(); +} + +uint64_t Queue::getPersistenceId() const +{ + return persistenceId; +} + +void Queue::setPersistenceId(uint64_t _persistenceId) +{ + persistenceId = _persistenceId; +} + +void Queue::encode(framing::Buffer& buffer) const +{ + buffer.putShortString(name); + //TODO store all required properties +} + +uint32_t Queue::encodedSize() const +{ + //TODO, revise when storing full set of queue properties + return name.size() + 1/*short string size octet*/; +} + +Queue::shared_ptr Queue::decode(QueueRegistry& queues, framing::Buffer& buffer) +{ + string name; + buffer.getShortString(name); + std::pair result = queues.declare(name, true); + return result.first; +} + diff --git a/qpid/cpp/src/broker/BrokerQueue.h b/qpid/cpp/src/broker/BrokerQueue.h new file mode 100644 index 0000000000..009f95b384 --- /dev/null +++ b/qpid/cpp/src/broker/BrokerQueue.h @@ -0,0 +1,151 @@ +#ifndef _broker_BrokerQueue_h +#define _broker_BrokerQueue_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../framing/amqp_types.h" +#include "ConnectionToken.h" +#include "Consumer.h" +#include "BrokerMessage.h" +#include "../framing/FieldTable.h" +#include "../sys/Monitor.h" +#include "PersistableQueue.h" +#include "QueuePolicy.h" + +// TODO aconway 2007-02-06: Use auto_ptr and boost::ptr_vector to +// enforce ownership of Consumers. + +namespace qpid { + namespace broker { + class MessageStore; + class QueueRegistry; + + /** + * Thrown when exclusive access would be violated. + */ + using std::string; + + /** + * 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 PersistableQueue{ + typedef std::vector Consumers; + typedef std::queue Messages; + + const string name; + const uint32_t autodelete; + MessageStore* const store; + const ConnectionToken* const owner; + Consumers consumers; + Messages messages; + bool queueing; + bool dispatching; + int next; + mutable qpid::sys::Mutex lock; + int64_t lastUsed; + Consumer* exclusive; + mutable uint64_t persistenceId; + std::auto_ptr policy; + + void pop(); + void push(Message::shared_ptr& msg); + bool startDispatching(); + bool dispatch(Message::shared_ptr& msg); + void setPolicy(std::auto_ptr policy); + + public: + + typedef boost::shared_ptr shared_ptr; + + typedef std::vector vector; + + Queue(const string& name, uint32_t autodelete = 0, + MessageStore* const store = 0, + const ConnectionToken* const owner = 0); + ~Queue(); + + void create(const qpid::framing::FieldTable& settings); + void configure(const qpid::framing::FieldTable& settings); + void destroy(); + /** + * Delivers a message to the queue. Will record it as + * enqueued if persistent then process it. + */ + void deliver(Message::shared_ptr& msg); + /** + * Dispatches the messages immediately to a consumer if + * one is available or stores it for later if not. + */ + void process(Message::shared_ptr& msg); + /** + * Used during recovery to add stored messages back to the queue + */ + void recover(Message::shared_ptr& msg); + /** + * Dispatch any queued messages providing there are + * consumers for them. Only one thread can be dispatching + * at any time, but this method (rather than the caller) + * is responsible for ensuring that. + */ + void dispatch(); + void consume(Consumer* c, bool exclusive = false); + void cancel(Consumer* c); + uint32_t purge(); + uint32_t getMessageCount() const; + uint32_t getConsumerCount() const; + inline const string& getName() const { return name; } + inline const bool isExclusiveOwner(const ConnectionToken* const o) const { return o == owner; } + inline bool hasExclusiveConsumer() const { return exclusive; } + + bool canAutoDelete() const; + + void enqueue(TransactionContext* ctxt, Message::shared_ptr& msg); + /** + * dequeue from store (only done once messages is acknowledged) + */ + void dequeue(TransactionContext* ctxt, Message::shared_ptr& msg); + /** + * dequeues from memory only + */ + Message::shared_ptr dequeue(); + + const QueuePolicy* const getPolicy(); + + //PersistableQueue support: + uint64_t getPersistenceId() const; + void setPersistenceId(uint64_t persistenceId); + void encode(framing::Buffer& buffer) const; + uint32_t encodedSize() const; + + static Queue::shared_ptr decode(QueueRegistry& queues, framing::Buffer& buffer); + }; + } +} + + +#endif /*!_broker_BrokerQueue_h*/ diff --git a/qpid/cpp/src/broker/BrokerSingleton.cpp b/qpid/cpp/src/broker/BrokerSingleton.cpp new file mode 100644 index 0000000000..4571764850 --- /dev/null +++ b/qpid/cpp/src/broker/BrokerSingleton.cpp @@ -0,0 +1,36 @@ +/* + * + * 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 "BrokerSingleton.h" + +namespace qpid { +namespace broker { + +BrokerSingleton::BrokerSingleton() { + if (broker.get() == 0) + broker = Broker::create(); + Broker::shared_ptr::operator=(broker); +} + +BrokerSingleton::~BrokerSingleton() { + broker->shutdown(); +} + +Broker::shared_ptr BrokerSingleton::broker; + +}} // namespace qpid::broker diff --git a/qpid/cpp/src/broker/BrokerSingleton.h b/qpid/cpp/src/broker/BrokerSingleton.h new file mode 100644 index 0000000000..139e02a5fd --- /dev/null +++ b/qpid/cpp/src/broker/BrokerSingleton.h @@ -0,0 +1,52 @@ +#ifndef _broker_BrokerSingleton_h +#define _broker_BrokerSingleton_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 "Broker.h" + +namespace qpid { +namespace broker { + +/** + * BrokerSingleton is a smart pointer to a process-wide singleton broker + * started on an os-chosen port. The broker starts the first time + * an instance of BrokerSingleton is created and runs untill the process exits. + * + * Useful for unit tests that want to share a broker between multiple + * tests to reduce overhead of starting/stopping a broker for every test. + * + * Tests that need a new broker can call Broker::create directly. + * + * THREAD UNSAFE. + */ +class BrokerSingleton : public Broker::shared_ptr +{ + public: + BrokerSingleton(); + ~BrokerSingleton(); + private: + static Broker::shared_ptr broker; +}; + +}} // namespace qpid::broker + + + +#endif /*!_broker_BrokerSingleton_h*/ diff --git a/qpid/cpp/src/broker/CompletionHandler.h b/qpid/cpp/src/broker/CompletionHandler.h new file mode 100644 index 0000000000..9d51656282 --- /dev/null +++ b/qpid/cpp/src/broker/CompletionHandler.h @@ -0,0 +1,39 @@ +#ifndef _broker_CompletionHandler_h +#define _broker_CompletionHandler_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 broker { + +/** + * Callback interface to handle completion of a message. + */ +class CompletionHandler +{ + public: + virtual ~CompletionHandler(){} + virtual void complete(Message::shared_ptr) = 0; +}; + +}} // namespace qpid::broker + + + +#endif /*!_broker_CompletionHandler_h*/ diff --git a/qpid/cpp/src/broker/Configuration.cpp b/qpid/cpp/src/broker/Configuration.cpp new file mode 100644 index 0000000000..5050314679 --- /dev/null +++ b/qpid/cpp/src/broker/Configuration.cpp @@ -0,0 +1,252 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "Configuration.h" +#include +#include "../../config.h" + +using namespace qpid::broker; +using namespace std; + +Configuration::Configuration() : + daemon('d', "daemon", "Run as system daemon, detached from terminal.", false), + trace('t', "trace", "Print incoming & outgoing frames to the console", false), + port('p', "port", "Set the port to listen on (default=5672)", 5672), + workerThreads("worker-threads", "Set the number of worker threads to use (default=5).", 5), + maxConnections("max-connections", "Set the maximum number of connections the broker can accept (default=500).", 500), + connectionBacklog("connection-backlog", "Set the connection backlog for the servers socket (default=10)", 10), + store('s', "store", "Set the message store module to use (default='' which implies no store)", ""), + stagingThreshold("staging-threshold", "Set the message size threshold above which messages will be written to disk as they arrive (default=5,000,000)", 5000000), + help("help", "Print usage information", false), + version("version", "Print version information", false) +{ + options.push_back(&daemon); + options.push_back(&trace); + options.push_back(&port); + options.push_back(&workerThreads); + options.push_back(&maxConnections); + options.push_back(&connectionBacklog); + options.push_back(&store); + options.push_back(&stagingThreshold); + options.push_back(&help); + options.push_back(&version); +} + +Configuration::~Configuration(){} + +void Configuration::parse(char const *progName, int argc, char** argv){ + programName = progName; + int position = 1; + while(position < argc){ + bool matched(false); + for(op_iterator i = options.begin(); i < options.end() && !matched; i++){ + matched = (*i)->parse(position, argv, argc); + } + if(!matched) { + throw BadOptionException( + std::string("Unrecognised option: ")+argv[position]); + } + } +} + +void Configuration::usage(){ + std::cout << "Usage: " << programName << " [OPTION]..." << std::endl + << "Start the Qpid AMQP broker daemon." << std::endl << std::endl + << "Options:" << std::endl; + for(op_iterator i = options.begin(); i < options.end(); i++){ + (*i)->print(std::cout); + } + + std::cout << std::endl << "Report bugs to <" << PACKAGE_BUGREPORT << ">." + << std::endl; +} + +bool Configuration::isHelp() const { + return help.getValue(); +} + +bool Configuration::isVersion() const { + return version.getValue(); +} + +bool Configuration::isDaemon() const { + return daemon.getValue(); +} + +bool Configuration::isTrace() const { + return trace.getValue(); +} + +int Configuration::getPort() const { + return port.getValue(); +} + +int Configuration::getWorkerThreads() const { + return workerThreads.getValue(); +} + +int Configuration::getMaxConnections() const { + return maxConnections.getValue(); +} + +int Configuration::getConnectionBacklog() const { + return connectionBacklog.getValue(); +} + +const std::string& Configuration::getStore() const { + return store.getValue(); +} + +long Configuration::getStagingThreshold() const { + return stagingThreshold.getValue(); +} + + +Configuration::Option::Option(const char _flag, const string& _name, const string& _desc) : + flag(string("-") + _flag), name("--" +_name), desc(_desc) {} + +Configuration::Option::Option(const string& _name, const string& _desc) : + flag(""), name("--" + _name), desc(_desc) {} + +Configuration::Option::~Option(){} + +bool Configuration::Option::match(const string& arg){ + return flag == arg || name == arg; +} + +bool Configuration::Option::parse(int& i, char** argv, int argc){ + const string arg(argv[i]); + if(match(arg)){ + if(needsValue()){ + if(++i < argc) setValue(argv[i]); + else throw ParseException("Argument " + arg + " requires a value!"); + }else{ + setValue(""); + } + i++; + return true; + }else{ + return false; + } +} + +void Configuration::Option::print(ostream& out) const { + out << " "; + if(flag.length() > 0){ + out << flag << ", "; + } else { + out << " "; + } + out << name; + if(needsValue()) out << " "; + out << std::endl; + out << " " << desc << std::endl; +} + + +// String Option: + +Configuration::StringOption::StringOption(const char _flag, const string& _name, const string& _desc, const string _value) : + Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} + +Configuration::StringOption::StringOption(const string& _name, const string& _desc, const string _value) : + Option(_name,_desc), defaultValue(_value), value(_value) {} + +Configuration::StringOption::~StringOption(){} + +const string& Configuration::StringOption::getValue() const { + return value; +} + +bool Configuration::StringOption::needsValue() const { + return true; +} + +void Configuration::StringOption::setValue(const std::string& _value){ + value = _value; +} + +// Int Option: + +Configuration::IntOption::IntOption(const char _flag, const string& _name, const string& _desc, const int _value) : + Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} + +Configuration::IntOption::IntOption(const string& _name, const string& _desc, const int _value) : + Option(_name,_desc), defaultValue(_value), value(_value) {} + +Configuration::IntOption::~IntOption(){} + +int Configuration::IntOption::getValue() const { + return value; +} + +bool Configuration::IntOption::needsValue() const { + return true; +} + +void Configuration::IntOption::setValue(const std::string& _value){ + value = atoi(_value.c_str()); +} + +// Long Option: + +Configuration::LongOption::LongOption(const char _flag, const string& _name, const string& _desc, const long _value) : + Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} + +Configuration::LongOption::LongOption(const string& _name, const string& _desc, const long _value) : + Option(_name,_desc), defaultValue(_value), value(_value) {} + +Configuration::LongOption::~LongOption(){} + +long Configuration::LongOption::getValue() const { + return value; +} + +bool Configuration::LongOption::needsValue() const { + return true; +} + +void Configuration::LongOption::setValue(const std::string& _value){ + value = atol(_value.c_str()); +} + +// Bool Option: + +Configuration::BoolOption::BoolOption(const char _flag, const string& _name, const string& _desc, const bool _value) : + Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} + +Configuration::BoolOption::BoolOption(const string& _name, const string& _desc, const bool _value) : + Option(_name,_desc), defaultValue(_value), value(_value) {} + +Configuration::BoolOption::~BoolOption(){} + +bool Configuration::BoolOption::getValue() const { + return value; +} + +bool Configuration::BoolOption::needsValue() const { + return false; +} + +void Configuration::BoolOption::setValue(const std::string& /*not required*/){ + //BoolOptions have no value. The fact that the option is specified + //implies the value is true. + value = true; +} diff --git a/qpid/cpp/src/broker/Configuration.h b/qpid/cpp/src/broker/Configuration.h new file mode 100644 index 0000000000..d93bf5c45b --- /dev/null +++ b/qpid/cpp/src/broker/Configuration.h @@ -0,0 +1,171 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _Configuration_ +#define _Configuration_ + +#include +#include +#include +#include "../Exception.h" + +namespace qpid { +namespace broker { +class Configuration{ + + class Option { + const std::string flag; + const std::string name; + const std::string desc; + + bool match(const std::string& arg); + + protected: + virtual bool needsValue() const = 0; + virtual void setValue(const std::string& value) = 0; + + public: + Option(const char flag, const std::string& name, const std::string& desc); + Option(const std::string& name, const std::string& desc); + virtual ~Option(); + + bool parse(int& i, char** argv, int argc); + void print(std::ostream& out) const; + }; + + class IntOption : public Option{ + const int defaultValue; + int value; + public: + IntOption(char flag, const std::string& name, const std::string& desc, const int value = 0); + IntOption(const std::string& name, const std::string& desc, const int value = 0); + virtual ~IntOption(); + + int getValue() const; + virtual bool needsValue() const; + virtual void setValue(const std::string& value); + virtual void setValue(int _value) { value = _value; } + }; + + class LongOption : public Option{ + const long defaultValue; + int value; + public: + LongOption(char flag, const std::string& name, const std::string& desc, const long value = 0); + LongOption(const std::string& name, const std::string& desc, const long value = 0); + virtual ~LongOption(); + + long getValue() const; + virtual bool needsValue() const; + virtual void setValue(const std::string& value); + virtual void setValue(int _value) { value = _value; } + }; + + class StringOption : public Option{ + const std::string defaultValue; + std::string value; + public: + StringOption(char flag, const std::string& name, const std::string& desc, const std::string value = ""); + StringOption(const std::string& name, const std::string& desc, const std::string value = ""); + virtual ~StringOption(); + + const std::string& getValue() const; + virtual bool needsValue() const; + virtual void setValue(const std::string& value); + }; + + class BoolOption : public Option{ + const bool defaultValue; + bool value; + public: + BoolOption(char flag, const std::string& name, const std::string& desc, const bool value = 0); + BoolOption(const std::string& name, const std::string& desc, const bool value = 0); + virtual ~BoolOption(); + + bool getValue() const; + virtual bool needsValue() const; + virtual void setValue(const std::string& value); + virtual void setValue(bool _value) { value = _value; } + }; + + BoolOption daemon; + BoolOption trace; + IntOption port; + IntOption workerThreads; + IntOption maxConnections; + IntOption connectionBacklog; + StringOption store; + LongOption stagingThreshold; + BoolOption help; + BoolOption version; + char const *programName; + + typedef std::vector::iterator op_iterator; + std::vector options; + + public: + + struct BadOptionException : public Exception { + template + BadOptionException(const T& msg) : Exception(msg) {} + }; + + + class ParseException : public Exception { + public: + template + ParseException(const T& msg) : Exception(msg) {} + }; + + + Configuration(); + ~Configuration(); + + void parse(char const*, int argc, char** argv); + + bool isHelp() const; + bool isVersion() const; + bool isDaemon() const; + bool isTrace() const; + int getPort() const; + int getWorkerThreads() const; + int getMaxConnections() const; + int getConnectionBacklog() const; + const std::string& getStore() const; + long getStagingThreshold() const; + + void setHelp(bool b) { help.setValue(b); } + void setVersion(bool b) { version.setValue(b); } + void setDaemon(bool b) { daemon.setValue(b); } + void setTrace(bool b) { trace.setValue(b); } + void setPort(int i) { port.setValue(i); } + void setWorkerThreads(int i) { workerThreads.setValue(i); } + void setMaxConnections(int i) { maxConnections.setValue(i); } + void setConnectionBacklog(int i) { connectionBacklog.setValue(i); } + void setStore(const std::string& s) { store.setValue(s); } + void setStagingThreshold(long l) { stagingThreshold.setValue(l); } + + void usage(); +}; +} +} + + +#endif diff --git a/qpid/cpp/src/broker/Connection.cpp b/qpid/cpp/src/broker/Connection.cpp new file mode 100644 index 0000000000..dbc8149cb5 --- /dev/null +++ b/qpid/cpp/src/broker/Connection.cpp @@ -0,0 +1,128 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "Connection.h" +#include "BrokerChannel.h" +#include "AMQP_ClientProxy.h" +#include "BrokerAdapter.h" + +using namespace boost; +using namespace qpid::sys; +using namespace qpid::framing; +using namespace qpid::sys; + +namespace qpid { +namespace broker { + +Connection::Connection(ConnectionOutputHandler* out_, Broker& broker_) : + broker(broker_), + out(out_), + framemax(65536), + heartbeat(0), + client(0), + timeout(broker.getTimeout()), + stagingThreshold(broker.getStagingThreshold()) +{} + + +Queue::shared_ptr Connection::getQueue(const string& name, uint16_t channel){ + Queue::shared_ptr queue; + if (name.empty()) { + queue = getChannel(channel).getDefaultQueue(); + if (!queue) throw ConnectionException( 530, "Queue must be specified or previously declared" ); + } else { + queue = broker.getQueues().find(name); + if (queue == 0) { + throw ChannelException( 404, "Queue not found: " + name); + } + } + return queue; +} + + +Exchange::shared_ptr Connection::findExchange(const string& name){ + return broker.getExchanges().get(name); +} + + +void Connection::received(framing::AMQFrame* frame){ + getChannel(frame->getChannel()).handleBody(frame->getBody()); +} + +void Connection::close( + ReplyCode code, const string& text, ClassId classId, MethodId methodId) +{ + client->close(code, text, classId, methodId); + getOutput().close(); +} + +void Connection::initiated(const framing::ProtocolInitiation& header) { + version = ProtocolVersion(header.getMajor(), header.getMinor()); + FieldTable properties; + string mechanisms("PLAIN"); + string locales("en_US"); + getChannel(0).init(0, *out, getVersion()); + client = &getChannel(0).getAdatper().getProxy().getConnection(); + client->start( + header.getMajor(), header.getMinor(), + properties, mechanisms, locales); +} + +void Connection::idleOut(){} + +void Connection::idleIn(){} + +void Connection::closed(){ + try { + while (!exclusiveQueues.empty()) { + broker.getQueues().destroy(exclusiveQueues.front()->getName()); + exclusiveQueues.erase(exclusiveQueues.begin()); + } + } catch(std::exception& e) { + std::cout << "Caught unhandled exception while closing session: " << + e.what() << std::endl; + assert(0); + } +} + +void Connection::closeChannel(uint16_t id) { + ChannelMap::iterator i = channels.find(id); + if (i != channels.end()) + i->close(); +} + + +Channel& Connection::getChannel(ChannelId id) { + ChannelMap::iterator i = channels.find(id); + if (i == channels.end()) { + i = channels.insert( + id, new Channel( + *this, id, framemax, broker.getQueues().getStore(), + broker.getStagingThreshold())).first; + } + return *i; +} + + +}} + diff --git a/qpid/cpp/src/broker/Connection.h b/qpid/cpp/src/broker/Connection.h new file mode 100644 index 0000000000..a36f1aa6ee --- /dev/null +++ b/qpid/cpp/src/broker/Connection.h @@ -0,0 +1,108 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _Connection_ +#define _Connection_ + +#include +#include + +#include + +#include "../framing/AMQFrame.h" +#include "AMQP_ServerOperations.h" +#include "AMQP_ClientProxy.h" +#include "../sys/ConnectionOutputHandler.h" +#include "../sys/ConnectionInputHandler.h" +#include "../sys/TimeoutHandler.h" +#include "../framing/ProtocolVersion.h" +#include "Broker.h" +#include "../Exception.h" +#include "BrokerChannel.h" + +namespace qpid { +namespace broker { + +class Channel; + +class Connection : public sys::ConnectionInputHandler, + public ConnectionToken +{ + public: + Connection(sys::ConnectionOutputHandler* out, Broker& broker); + + /** Get a channel. Create if it does not already exist */ + Channel& getChannel(framing::ChannelId channel); + + /** Close a channel */ + void closeChannel(framing::ChannelId channel); + + /** Close the connection */ + void close(framing::ReplyCode code, const string& text, framing::ClassId classId, framing::MethodId methodId); + + sys::ConnectionOutputHandler& getOutput() const { return *out; } + framing::ProtocolVersion getVersion() const { return version; } + + uint32_t getFrameMax() const { return framemax; } + uint16_t getHeartbeat() const { return heartbeat; } + uint32_t getTimeout() const { return timeout; } + uint64_t getStagingThreshold() const { return stagingThreshold; } + + void setFrameMax(uint32_t fm) { framemax = fm; } + void setHeartbeat(uint16_t hb) { heartbeat = hb; } + + /** + * Get named queue, never returns 0. + * @return: named queue or default queue for channel if name="" + * @exception: ChannelException if no queue of that name is found. + * @exception: ConnectionException if name="" and channel has no default. + */ + Queue::shared_ptr getQueue(const string& name, uint16_t channel); + + Broker& broker; + std::vector exclusiveQueues; + + // ConnectionInputHandler methods + void received(framing::AMQFrame* frame); + void initiated(const framing::ProtocolInitiation& header); + void idleOut(); + void idleIn(); + void closed(); + + private: + typedef boost::ptr_map ChannelMap; + + typedef std::vector::iterator queue_iterator; + Exchange::shared_ptr findExchange(const string& name); + + framing::ProtocolVersion version; + ChannelMap channels; + sys::ConnectionOutputHandler* out; + uint32_t framemax; + uint16_t heartbeat; + framing::AMQP_ClientProxy::Connection* client; + const uint32_t timeout; //timeout for auto-deleted queues (in ms) + const uint64_t stagingThreshold; + +}; + +}} + +#endif diff --git a/qpid/cpp/src/broker/ConnectionFactory.cpp b/qpid/cpp/src/broker/ConnectionFactory.cpp new file mode 100644 index 0000000000..5372bfe377 --- /dev/null +++ b/qpid/cpp/src/broker/ConnectionFactory.cpp @@ -0,0 +1,43 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "ConnectionFactory.h" +#include "Connection.h" + +namespace qpid { +namespace broker { + + +ConnectionFactory::ConnectionFactory(Broker& b) : broker(b) +{} + + +ConnectionFactory::~ConnectionFactory() +{ + broker.getCleaner().stop(); +} + +qpid::sys::ConnectionInputHandler* +ConnectionFactory::create(qpid::sys::ConnectionOutputHandler* out) +{ + return new Connection(out, broker); +} + +}} // namespace qpid::broker diff --git a/qpid/cpp/src/broker/ConnectionFactory.h b/qpid/cpp/src/broker/ConnectionFactory.h new file mode 100644 index 0000000000..54fabb8089 --- /dev/null +++ b/qpid/cpp/src/broker/ConnectionFactory.h @@ -0,0 +1,47 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _ConnectionFactory_ +#define _ConnectionFactory_ + +#include "../sys/ConnectionInputHandlerFactory.h" + +namespace qpid { +namespace broker { +class Broker; + +class ConnectionFactory : public qpid::sys::ConnectionInputHandlerFactory +{ + public: + ConnectionFactory(Broker& b); + + virtual qpid::sys::ConnectionInputHandler* create( + qpid::sys::ConnectionOutputHandler* ctxt); + + virtual ~ConnectionFactory(); + + private: + Broker& broker; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/broker/ConnectionToken.h b/qpid/cpp/src/broker/ConnectionToken.h new file mode 100644 index 0000000000..7e7f813d0e --- /dev/null +++ b/qpid/cpp/src/broker/ConnectionToken.h @@ -0,0 +1,38 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _ConnectionToken_ +#define _ConnectionToken_ + +namespace qpid { + namespace broker { + /** + * An empty interface allowing opaque implementations of some + * form of token to identify a connection. + */ + class ConnectionToken{ + public: + virtual ~ConnectionToken(){} + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/Consumer.h b/qpid/cpp/src/broker/Consumer.h new file mode 100644 index 0000000000..d0c397d184 --- /dev/null +++ b/qpid/cpp/src/broker/Consumer.h @@ -0,0 +1,37 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _Consumer_ +#define _Consumer_ + +#include "BrokerMessage.h" + +namespace qpid { + namespace broker { + class Consumer{ + public: + virtual bool deliver(Message::shared_ptr& msg) = 0; + virtual ~Consumer(){} + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/Content.h b/qpid/cpp/src/broker/Content.h new file mode 100644 index 0000000000..dd895e2eb3 --- /dev/null +++ b/qpid/cpp/src/broker/Content.h @@ -0,0 +1,64 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _Content_ +#define _Content_ + +#include + +#include "../framing/AMQContentBody.h" +#include "../framing/Buffer.h" +#include "../framing/OutputHandler.h" + +namespace qpid { + +namespace framing { +class ChannelAdapter; +} + +namespace broker { +class Content{ + public: + typedef std::string DataBlock; + typedef boost::function1 SendFn; + + virtual ~Content(){} + + /** Add a block of data to the content */ + virtual void add(framing::AMQContentBody::shared_ptr data) = 0; + + /** Total size of content in bytes */ + virtual uint32_t size() = 0; + + /** + * Iterate over the content calling SendFn for each block. + * Subdivide blocks if necessary to ensure each block is + * <= framesize bytes long. + */ + virtual void send(framing::ChannelAdapter& channel, uint32_t framesize) = 0; + + //FIXME aconway 2007-02-07: This is inconsistently implemented + //find out what is needed. + virtual void encode(qpid::framing::Buffer& buffer) = 0; +}; +}} + + +#endif diff --git a/qpid/cpp/src/broker/DeletingTxOp.cpp b/qpid/cpp/src/broker/DeletingTxOp.cpp new file mode 100644 index 0000000000..ae6ac0f2e6 --- /dev/null +++ b/qpid/cpp/src/broker/DeletingTxOp.cpp @@ -0,0 +1,45 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "DeletingTxOp.h" + +using namespace qpid::broker; + +DeletingTxOp::DeletingTxOp(TxOp* const _delegate) : delegate(_delegate){} + +bool DeletingTxOp::prepare(TransactionContext* ctxt) throw(){ + return delegate && delegate->prepare(ctxt); +} + +void DeletingTxOp::commit() throw(){ + if(delegate){ + delegate->commit(); + delete delegate; + delegate = 0; + } +} + +void DeletingTxOp::rollback() throw(){ + if(delegate){ + delegate->rollback(); + delete delegate; + delegate = 0; + } +} diff --git a/qpid/cpp/src/broker/DeletingTxOp.h b/qpid/cpp/src/broker/DeletingTxOp.h new file mode 100644 index 0000000000..ddef1c77c0 --- /dev/null +++ b/qpid/cpp/src/broker/DeletingTxOp.h @@ -0,0 +1,45 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _DeletingTxOp_ +#define _DeletingTxOp_ + +#include "TxOp.h" + +namespace qpid { + namespace broker { + /** + * TxOp wrapper that will delegate calls & delete the object + * to which it delegates after completion of the transaction. + */ + class DeletingTxOp : public virtual TxOp{ + TxOp* delegate; + public: + DeletingTxOp(TxOp* const delegate); + virtual bool prepare(TransactionContext* ctxt) throw(); + virtual void commit() throw(); + virtual void rollback() throw(); + virtual ~DeletingTxOp(){} + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/Deliverable.h b/qpid/cpp/src/broker/Deliverable.h new file mode 100644 index 0000000000..1570917849 --- /dev/null +++ b/qpid/cpp/src/broker/Deliverable.h @@ -0,0 +1,37 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _Deliverable_ +#define _Deliverable_ + +#include "BrokerQueue.h" + +namespace qpid { + namespace broker { + class Deliverable{ + public: + virtual void deliverTo(Queue::shared_ptr& queue) = 0; + virtual ~Deliverable(){} + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/DeliverableMessage.cpp b/qpid/cpp/src/broker/DeliverableMessage.cpp new file mode 100644 index 0000000000..0c2e46ccce --- /dev/null +++ b/qpid/cpp/src/broker/DeliverableMessage.cpp @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "DeliverableMessage.h" + +using namespace qpid::broker; + +DeliverableMessage::DeliverableMessage(Message::shared_ptr& _msg) : msg(_msg) +{ +} + +void DeliverableMessage::deliverTo(Queue::shared_ptr& queue) +{ + queue->deliver(msg); +} + diff --git a/qpid/cpp/src/broker/DeliverableMessage.h b/qpid/cpp/src/broker/DeliverableMessage.h new file mode 100644 index 0000000000..43e738a96a --- /dev/null +++ b/qpid/cpp/src/broker/DeliverableMessage.h @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _DeliverableMessage_ +#define _DeliverableMessage_ + +#include "Deliverable.h" +#include "BrokerMessage.h" +#include "BrokerQueue.h" + +namespace qpid { + namespace broker { + class DeliverableMessage : public Deliverable{ + Message::shared_ptr msg; + public: + DeliverableMessage(Message::shared_ptr& msg); + virtual void deliverTo(Queue::shared_ptr& queue); + virtual ~DeliverableMessage(){} + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/DeliveryRecord.cpp b/qpid/cpp/src/broker/DeliveryRecord.cpp new file mode 100644 index 0000000000..95650b7b23 --- /dev/null +++ b/qpid/cpp/src/broker/DeliveryRecord.cpp @@ -0,0 +1,87 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "BrokerChannel.h" + +using namespace qpid::broker; +using std::string; + +DeliveryRecord::DeliveryRecord(Message::shared_ptr _msg, + Queue::shared_ptr _queue, + const string _consumerTag, + const uint64_t _deliveryTag) : msg(_msg), + queue(_queue), + consumerTag(_consumerTag), + deliveryTag(_deliveryTag), + pull(false){} + +DeliveryRecord::DeliveryRecord(Message::shared_ptr _msg, + Queue::shared_ptr _queue, + const uint64_t _deliveryTag) : msg(_msg), + queue(_queue), + consumerTag(""), + deliveryTag(_deliveryTag), + pull(true){} + + +void DeliveryRecord::discard(TransactionContext* ctxt) const{ + queue->dequeue(ctxt, msg); +} + +bool DeliveryRecord::matches(uint64_t tag) const{ + return deliveryTag == tag; +} + +bool DeliveryRecord::coveredBy(const AccumulatedAck* const range) const{ + return range->covers(deliveryTag); +} + +void DeliveryRecord::redeliver(Channel* const channel) const{ + if(pull){ + //if message was originally sent as response to get, we must requeue it + requeue(); + }else{ + channel->deliver(msg, consumerTag, deliveryTag); + } +} + +void DeliveryRecord::requeue() const{ + msg->redeliver(); + queue->process(msg); +} + +void DeliveryRecord::addTo(Prefetch* const prefetch) const{ + if(!pull){ + //ignore 'pulled' messages (i.e. those that were sent in + //response to get) when calculating prefetch + prefetch->size += msg->contentSize(); + prefetch->count++; + } +} + +void DeliveryRecord::subtractFrom(Prefetch* const prefetch) const{ + if(!pull){ + //ignore 'pulled' messages (i.e. those that were sent in + //response to get) when calculating prefetch + prefetch->size -= msg->contentSize(); + prefetch->count--; + } +} diff --git a/qpid/cpp/src/broker/DeliveryRecord.h b/qpid/cpp/src/broker/DeliveryRecord.h new file mode 100644 index 0000000000..15c207ce44 --- /dev/null +++ b/qpid/cpp/src/broker/DeliveryRecord.h @@ -0,0 +1,63 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _DeliveryRecord_ +#define _DeliveryRecord_ + +#include +#include +#include "AccumulatedAck.h" +#include "BrokerMessage.h" +#include "Prefetch.h" +#include "BrokerQueue.h" + +namespace qpid { + namespace broker { + class Channel; + + /** + * Record of a delivery for which an ack is outstanding. + */ + class DeliveryRecord{ + mutable Message::shared_ptr msg; + mutable Queue::shared_ptr queue; + std::string consumerTag; + uint64_t deliveryTag; + bool pull; + + public: + DeliveryRecord(Message::shared_ptr msg, Queue::shared_ptr queue, const std::string consumerTag, const uint64_t deliveryTag); + DeliveryRecord(Message::shared_ptr msg, Queue::shared_ptr queue, const uint64_t deliveryTag); + + void discard(TransactionContext* ctxt = 0) const; + bool matches(uint64_t tag) const; + bool coveredBy(const AccumulatedAck* const range) const; + void requeue() const; + void redeliver(Channel* const) const; + void addTo(Prefetch* const prefetch) const; + void subtractFrom(Prefetch* const prefetch) const; + }; + + typedef std::list::iterator ack_iterator; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/DirectExchange.cpp b/qpid/cpp/src/broker/DirectExchange.cpp new file mode 100644 index 0000000000..7d15410374 --- /dev/null +++ b/qpid/cpp/src/broker/DirectExchange.cpp @@ -0,0 +1,71 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "DirectExchange.h" +#include + +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::sys; + +DirectExchange::DirectExchange(const string& _name) : Exchange(_name) { + +} + +void DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable*){ + Mutex::ScopedLock l(lock); + std::vector& queues(bindings[routingKey]); + std::vector::iterator i = find(queues.begin(), queues.end(), queue); + if(i == queues.end()){ + bindings[routingKey].push_back(queue); + } +} + +void DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* /*args*/){ + Mutex::ScopedLock l(lock); + std::vector& queues(bindings[routingKey]); + + std::vector::iterator i = find(queues.begin(), queues.end(), queue); + if(i < queues.end()){ + queues.erase(i); + if(queues.empty()){ + bindings.erase(routingKey); + } + } +} + +void DirectExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/){ + Mutex::ScopedLock l(lock); + std::vector& queues(bindings[routingKey]); + int count(0); + for(std::vector::iterator i = queues.begin(); i != queues.end(); i++, count++){ + msg.deliverTo(*i); + } + if(!count){ + std::cout << "WARNING: DirectExchange " << getName() << " could not route message with key " << routingKey << std::endl; + } +} + +DirectExchange::~DirectExchange(){ + +} + + +const std::string DirectExchange::typeName("direct"); diff --git a/qpid/cpp/src/broker/DirectExchange.h b/qpid/cpp/src/broker/DirectExchange.h new file mode 100644 index 0000000000..94b064327d --- /dev/null +++ b/qpid/cpp/src/broker/DirectExchange.h @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _DirectExchange_ +#define _DirectExchange_ + +#include +#include +#include "BrokerExchange.h" +#include "../framing/FieldTable.h" +#include "BrokerMessage.h" +#include "../sys/Monitor.h" +#include "BrokerQueue.h" + +namespace qpid { +namespace broker { + class DirectExchange : public virtual Exchange{ + std::map > bindings; + qpid::sys::Mutex lock; + + public: + static const std::string typeName; + + DirectExchange(const std::string& name); + + virtual std::string getType(){ return typeName; } + + virtual void bind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); + + virtual void unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); + + virtual void route(Deliverable& msg, const std::string& routingKey, const qpid::framing::FieldTable* args); + + virtual ~DirectExchange(); + }; +} +} + + +#endif diff --git a/qpid/cpp/src/broker/ExchangeRegistry.cpp b/qpid/cpp/src/broker/ExchangeRegistry.cpp new file mode 100644 index 0000000000..03863673df --- /dev/null +++ b/qpid/cpp/src/broker/ExchangeRegistry.cpp @@ -0,0 +1,76 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "ExchangeRegistry.h" +#include "DirectExchange.h" +#include "FanOutExchange.h" +#include "HeadersExchange.h" +#include "TopicExchange.h" + +using namespace qpid::broker; +using namespace qpid::sys; +using std::pair; + +pair ExchangeRegistry::declare(const string& name, const string& type) throw(UnknownExchangeTypeException){ + Mutex::ScopedLock locker(lock); + ExchangeMap::iterator i = exchanges.find(name); + if (i == exchanges.end()) { + Exchange::shared_ptr exchange; + + if(type == TopicExchange::typeName){ + exchange = Exchange::shared_ptr(new TopicExchange(name)); + }else if(type == DirectExchange::typeName){ + exchange = Exchange::shared_ptr(new DirectExchange(name)); + }else if(type == FanOutExchange::typeName){ + exchange = Exchange::shared_ptr(new FanOutExchange(name)); + }else if (type == HeadersExchange::typeName) { + exchange = Exchange::shared_ptr(new HeadersExchange(name)); + }else{ + throw UnknownExchangeTypeException(); + } + exchanges[name] = exchange; + return std::pair(exchange, true); + } else { + return std::pair(i->second, false); + } +} + +void ExchangeRegistry::destroy(const string& name){ + Mutex::ScopedLock locker(lock); + exchanges.erase(name); +} + +Exchange::shared_ptr ExchangeRegistry::get(const string& name){ + Mutex::ScopedLock locker(lock); + Exchange::shared_ptr exchange =exchanges[name]; + if (!exchange) + throw ChannelException(404, "Exchange not found:" + name); + return exchange; +} + +namespace +{ +const std::string empty; +} + +Exchange::shared_ptr ExchangeRegistry::getDefault() +{ + return get(empty); +} diff --git a/qpid/cpp/src/broker/ExchangeRegistry.h b/qpid/cpp/src/broker/ExchangeRegistry.h new file mode 100644 index 0000000000..1c81cb6021 --- /dev/null +++ b/qpid/cpp/src/broker/ExchangeRegistry.h @@ -0,0 +1,47 @@ +#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 +#include "BrokerExchange.h" +#include "../sys/Monitor.h" + +namespace qpid { +namespace broker { + struct UnknownExchangeTypeException{}; + + class ExchangeRegistry{ + typedef std::map ExchangeMap; + ExchangeMap exchanges; + qpid::sys::Mutex lock; + public: + std::pair declare(const std::string& name, const std::string& type) throw(UnknownExchangeTypeException); + void destroy(const std::string& name); + Exchange::shared_ptr get(const std::string& name); + Exchange::shared_ptr getDefault(); + }; +} +} + + +#endif /*!_broker_ExchangeRegistry_h*/ diff --git a/qpid/cpp/src/broker/FanOutExchange.cpp b/qpid/cpp/src/broker/FanOutExchange.cpp new file mode 100644 index 0000000000..1ac92c89e2 --- /dev/null +++ b/qpid/cpp/src/broker/FanOutExchange.cpp @@ -0,0 +1,56 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "FanOutExchange.h" +#include + +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::sys; + +FanOutExchange::FanOutExchange(const std::string& _name) : Exchange(_name) {} + +void FanOutExchange::bind(Queue::shared_ptr queue, const string& /*routingKey*/, const FieldTable* /*args*/){ + Mutex::ScopedLock locker(lock); + // Add if not already present. + Queue::vector::iterator i = std::find(bindings.begin(), bindings.end(), queue); + if (i == bindings.end()) { + bindings.push_back(queue); + } +} + +void FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*routingKey*/, const FieldTable* /*args*/){ + Mutex::ScopedLock locker(lock); + Queue::vector::iterator i = std::find(bindings.begin(), bindings.end(), queue); + if (i != bindings.end()) { + bindings.erase(i); + } +} + +void FanOutExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* /*args*/){ + Mutex::ScopedLock locker(lock); + for(Queue::vector::iterator i = bindings.begin(); i != bindings.end(); ++i){ + msg.deliverTo(*i); + } +} + +FanOutExchange::~FanOutExchange() {} + +const std::string FanOutExchange::typeName("fanout"); diff --git a/qpid/cpp/src/broker/FanOutExchange.h b/qpid/cpp/src/broker/FanOutExchange.h new file mode 100644 index 0000000000..147383ba1a --- /dev/null +++ b/qpid/cpp/src/broker/FanOutExchange.h @@ -0,0 +1,60 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _FanOutExchange_ +#define _FanOutExchange_ + +#include +#include +#include "BrokerExchange.h" +#include "../framing/FieldTable.h" +#include "BrokerMessage.h" +#include "../sys/Monitor.h" +#include "BrokerQueue.h" + +namespace qpid { +namespace broker { + +class FanOutExchange : public virtual Exchange { + std::vector bindings; + qpid::sys::Mutex lock; + + public: + static const std::string typeName; + + FanOutExchange(const std::string& name); + + virtual std::string getType(){ return typeName; } + + virtual void bind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); + + virtual void unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); + + virtual void route(Deliverable& msg, const std::string& routingKey, const qpid::framing::FieldTable* args); + + virtual ~FanOutExchange(); +}; + +} +} + + + +#endif diff --git a/qpid/cpp/src/broker/HandlerImpl.h b/qpid/cpp/src/broker/HandlerImpl.h new file mode 100644 index 0000000000..c55a36da45 --- /dev/null +++ b/qpid/cpp/src/broker/HandlerImpl.h @@ -0,0 +1,71 @@ +#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 "BrokerChannel.h" +#include "AMQP_ClientProxy.h" + +namespace qpid { + +namespace framing { +class AMQP_ClientProxy; +} + +namespace broker { + +class Broker; +class Channel; +class Connection; + +/** + * A collection of references to the core objects required by an adapter, + * and a client proxy. + */ +struct CoreRefs +{ + CoreRefs(Channel& ch, Connection& c, Broker& b) + : channel(ch), connection(c), broker(b), proxy(ch) {} + + Channel& channel; + Connection& connection; + Broker& broker; + framing::AMQP_ClientProxy proxy; +}; + + +/** + * Base template for protocol handler implementations. + * Provides the core references and appropriate AMQP class proxy. + */ +template +struct HandlerImpl : public CoreRefs { + typedef HandlerImpl HandlerImplType; + HandlerImpl(CoreRefs& parent) + : CoreRefs(parent), client(ProxyType::get(proxy)) {} + ProxyType client; +}; + + + +}} // namespace qpid::broker + + + +#endif /*!_broker_HandlerImpl_h*/ diff --git a/qpid/cpp/src/broker/HeadersExchange.cpp b/qpid/cpp/src/broker/HeadersExchange.cpp new file mode 100644 index 0000000000..21f23af00d --- /dev/null +++ b/qpid/cpp/src/broker/HeadersExchange.cpp @@ -0,0 +1,119 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "HeadersExchange.h" +#include "../framing/Value.h" +#include "../QpidError.h" +#include + + +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::sys; + +// 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 all("all"); + const std::string any("any"); + const std::string x_match("x-match"); +} + +HeadersExchange::HeadersExchange(const string& _name) : Exchange(_name) { } + +void HeadersExchange::bind(Queue::shared_ptr queue, const string& /*routingKey*/, const FieldTable* args){ + Mutex::ScopedLock locker(lock); + std::string what = args->getString("x-match"); + if (what != all && what != any) { + THROW_QPID_ERROR(PROTOCOL_ERROR, "Invalid x-match value binding to headers exchange."); + } + bindings.push_back(Binding(*args, queue)); +} + +void HeadersExchange::unbind(Queue::shared_ptr queue, const string& /*routingKey*/, const FieldTable* args){ + Mutex::ScopedLock locker(lock); + Bindings::iterator i = + std::find(bindings.begin(),bindings.end(), Binding(*args, queue)); + if (i != bindings.end()) bindings.erase(i); +} + + +void HeadersExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* args){ + Mutex::ScopedLock locker(lock);; + for (Bindings::iterator i = bindings.begin(); i != bindings.end(); ++i) { + if (match(i->first, *args)) msg.deliverTo(i->second); + } +} + +HeadersExchange::~HeadersExchange() {} + +const std::string HeadersExchange::typeName("headers"); + +namespace +{ + + bool match_values(const Value& bind, const Value& msg) { + return dynamic_cast(&bind) || bind == msg; + } + +} + + +bool HeadersExchange::match(const FieldTable& bind, const FieldTable& msg) { + typedef FieldTable::ValueMap Map; + std::string what = bind.getString(x_match); + if (what == all) { + for (Map::const_iterator i = bind.getMap().begin(); + i != bind.getMap().end(); + ++i) + { + if (i->first != x_match) + { + Map::const_iterator j = msg.getMap().find(i->first); + if (j == msg.getMap().end()) return false; + if (!match_values(*(i->second), *(j->second))) return false; + } + } + return true; + } else if (what == any) { + for (Map::const_iterator i = bind.getMap().begin(); + i != bind.getMap().end(); + ++i) + { + if (i->first != x_match) + { + Map::const_iterator j = msg.getMap().find(i->first); + if (j != msg.getMap().end()) { + if (match_values(*(i->second), *(j->second))) return true; + } + } + } + return false; + } else { + return false; + } +} + + + diff --git a/qpid/cpp/src/broker/HeadersExchange.h b/qpid/cpp/src/broker/HeadersExchange.h new file mode 100644 index 0000000000..4d26b95f50 --- /dev/null +++ b/qpid/cpp/src/broker/HeadersExchange.h @@ -0,0 +1,65 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _HeadersExchange_ +#define _HeadersExchange_ + +#include +#include "BrokerExchange.h" +#include "../framing/FieldTable.h" +#include "BrokerMessage.h" +#include "../sys/Monitor.h" +#include "BrokerQueue.h" + +namespace qpid { +namespace broker { + + +class HeadersExchange : public virtual Exchange { + typedef std::pair Binding; + typedef std::vector Bindings; + + Bindings bindings; + qpid::sys::Mutex lock; + + public: + static const std::string typeName; + + HeadersExchange(const string& name); + + virtual std::string getType(){ return typeName; } + + virtual void bind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args); + + virtual void unbind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args); + + virtual void route(Deliverable& msg, const string& routingKey, const qpid::framing::FieldTable* args); + + virtual ~HeadersExchange(); + + static bool match(const qpid::framing::FieldTable& bindArgs, const qpid::framing::FieldTable& msgArgs); +}; + + + +} +} + +#endif diff --git a/qpid/cpp/src/broker/InMemoryContent.cpp b/qpid/cpp/src/broker/InMemoryContent.cpp new file mode 100644 index 0000000000..d5f3479894 --- /dev/null +++ b/qpid/cpp/src/broker/InMemoryContent.cpp @@ -0,0 +1,72 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "InMemoryContent.h" +#include "../framing/AMQFrame.h" +#include "../framing/ChannelAdapter.h" + +using namespace qpid::broker; +using namespace qpid::framing; +using boost::static_pointer_cast; + +void InMemoryContent::add(AMQContentBody::shared_ptr data) +{ + content.push_back(data); +} + +uint32_t InMemoryContent::size() +{ + int sum(0); + for (content_iterator i = content.begin(); i != content.end(); i++) { + sum += (*i)->size(); + } + return sum; +} + +void InMemoryContent::send(ChannelAdapter& channel, uint32_t framesize) +{ + for (content_iterator i = content.begin(); i != content.end(); i++) { + if ((*i)->size() > framesize) { + uint32_t offset = 0; + for (int chunk = (*i)->size() / framesize; chunk > 0; chunk--) { + string data = (*i)->getData().substr(offset, framesize); + channel.send(new AMQContentBody(data)); + offset += framesize; + } + uint32_t remainder = (*i)->size() % framesize; + if (remainder) { + string data = (*i)->getData().substr(offset, remainder); + channel.send(new AMQContentBody(data)); + } + } else { + AMQBody::shared_ptr contentBody = + static_pointer_cast(*i); + channel.send(contentBody); + } + } +} + +void InMemoryContent::encode(Buffer& buffer) +{ + for (content_iterator i = content.begin(); i != content.end(); i++) { + (*i)->encode(buffer); + } +} + diff --git a/qpid/cpp/src/broker/InMemoryContent.h b/qpid/cpp/src/broker/InMemoryContent.h new file mode 100644 index 0000000000..425f0e4e26 --- /dev/null +++ b/qpid/cpp/src/broker/InMemoryContent.h @@ -0,0 +1,45 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _InMemoryContent_ +#define _InMemoryContent_ + +#include "Content.h" +#include + + +namespace qpid { + namespace broker { + class InMemoryContent : public Content{ + typedef std::vector content_list; + typedef content_list::iterator content_iterator; + + content_list content; + public: + void add(qpid::framing::AMQContentBody::shared_ptr data); + uint32_t size(); + void send(framing::ChannelAdapter&, uint32_t framesize); + void encode(qpid::framing::Buffer& buffer); + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/LazyLoadedContent.cpp b/qpid/cpp/src/broker/LazyLoadedContent.cpp new file mode 100644 index 0000000000..b5bead11a5 --- /dev/null +++ b/qpid/cpp/src/broker/LazyLoadedContent.cpp @@ -0,0 +1,68 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "LazyLoadedContent.h" +#include "../framing/AMQFrame.h" +#include "../framing/ChannelAdapter.h" + +using namespace qpid::broker; +using namespace qpid::framing; + +LazyLoadedContent::~LazyLoadedContent() +{ + store->destroy(*msg); +} + +LazyLoadedContent::LazyLoadedContent(MessageStore* const _store, Message* const _msg, uint64_t _expectedSize) : + store(_store), msg(_msg), expectedSize(_expectedSize) {} + +void LazyLoadedContent::add(AMQContentBody::shared_ptr data) +{ + store->appendContent(*msg, data->getData()); +} + +uint32_t LazyLoadedContent::size() +{ + return 0;//all content is written as soon as it is added +} + +void LazyLoadedContent::send(ChannelAdapter& channel, uint32_t framesize) +{ + if (expectedSize > framesize) { + for (uint64_t offset = 0; offset < expectedSize; offset += framesize) + { + uint64_t remaining = expectedSize - offset; + string data; + store->loadContent(*msg, data, offset, + remaining > framesize ? framesize : remaining); + channel.send(new AMQContentBody(data)); + } + } else { + string data; + store->loadContent(*msg, data, 0, expectedSize); + channel.send(new AMQContentBody(data)); + } +} + +void LazyLoadedContent::encode(Buffer&) +{ + //do nothing as all content is written as soon as it is added +} + diff --git a/qpid/cpp/src/broker/LazyLoadedContent.h b/qpid/cpp/src/broker/LazyLoadedContent.h new file mode 100644 index 0000000000..9dff6158a5 --- /dev/null +++ b/qpid/cpp/src/broker/LazyLoadedContent.h @@ -0,0 +1,50 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _LazyLoadedContent_ +#define _LazyLoadedContent_ + +#include "Content.h" +#include "MessageStore.h" +#include "BrokerMessageBase.h" + +namespace qpid { + namespace broker { + class LazyLoadedContent : public Content{ + MessageStore* const store; + Message* const msg; + const uint64_t expectedSize; + public: + LazyLoadedContent( + MessageStore* const store, Message* const msg, + uint64_t expectedSize); + ~LazyLoadedContent(); + void add(qpid::framing::AMQContentBody::shared_ptr data); + uint32_t size(); + void send( + framing::ChannelAdapter&, + uint32_t framesize); + void encode(qpid::framing::Buffer& buffer); + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/Makefile.am b/qpid/cpp/src/broker/Makefile.am new file mode 100644 index 0000000000..22f66dc3d9 --- /dev/null +++ b/qpid/cpp/src/broker/Makefile.am @@ -0,0 +1,97 @@ +AM_CXXFLAGS = $(WARNING_CFLAGS) +INCLUDES = \ + -I$(srcdir)/../gen \ + $(APR_CXXFLAGS) + +lib_LTLIBRARIES = libqpidbroker.la +libqpidbroker_la_LDFLAGS = -version-info $(LIBTOOL_VERSION_INFO_ARG) +libqpidbroker_la_SOURCES = \ + AccumulatedAck.cpp \ + AccumulatedAck.h \ + AutoDelete.cpp \ + AutoDelete.h \ + Binding.h \ + Broker.cpp \ + Broker.h \ + BrokerSingleton.cpp \ + BrokerSingleton.h \ + BrokerChannel.cpp \ + BrokerChannel.h \ + BrokerExchange.h \ + BrokerMessage.cpp \ + BrokerMessage.h \ + BrokerMessageMessage.cpp \ + BrokerMessageMessage.h \ + BrokerQueue.cpp \ + BrokerQueue.h \ + Configuration.cpp \ + Configuration.h \ + ConnectionToken.h \ + Consumer.h \ + Content.h \ + DeletingTxOp.cpp \ + DeletingTxOp.h \ + Deliverable.h \ + DeliverableMessage.cpp \ + DeliverableMessage.h \ + DeliveryRecord.cpp \ + DeliveryRecord.h \ + DirectExchange.cpp \ + DirectExchange.h \ + ExchangeRegistry.cpp \ + ExchangeRegistry.h \ + FanOutExchange.cpp \ + FanOutExchange.h \ + HeadersExchange.cpp \ + HeadersExchange.h \ + InMemoryContent.cpp \ + InMemoryContent.h \ + LazyLoadedContent.cpp \ + LazyLoadedContent.h \ + MessageBuilder.cpp \ + MessageBuilder.h \ + MessageStore.h \ + MessageStoreModule.cpp \ + MessageStoreModule.h \ + NameGenerator.cpp \ + NameGenerator.h \ + NullMessageStore.cpp \ + NullMessageStore.h \ + Persistable.h \ + PersistableExchange.h \ + PersistableMessage.h \ + PersistableQueue.h \ + Prefetch.h \ + QueuePolicy.cpp \ + QueuePolicy.h \ + QueueRegistry.cpp \ + QueueRegistry.h \ + RecoverableMessage.h \ + RecoverableQueue.h \ + RecoveryManager.h \ + RecoveryManagerImpl.cpp \ + RecoveryManagerImpl.h \ + Reference.cpp \ + Reference.h \ + ConnectionFactory.cpp \ + ConnectionFactory.h \ + Connection.cpp \ + Connection.h \ + BrokerAdapter.cpp \ + BrokerAdapter.h \ + MessageHandlerImpl.cpp \ + MessageHandlerImpl.h \ + TopicExchange.cpp \ + TopicExchange.h \ + TransactionalStore.h \ + TxAck.cpp \ + TxAck.h \ + TxBuffer.cpp \ + TxBuffer.h \ + TxOp.h \ + TxPublish.cpp \ + TxPublish.h + + +# Force build during dist phase so help2man will work. +dist-hook: $(lib_LTLIBRARIES) diff --git a/qpid/cpp/src/broker/MessageBuilder.cpp b/qpid/cpp/src/broker/MessageBuilder.cpp new file mode 100644 index 0000000000..6c33b38e72 --- /dev/null +++ b/qpid/cpp/src/broker/MessageBuilder.cpp @@ -0,0 +1,74 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "MessageBuilder.h" + +#include "InMemoryContent.h" +#include "LazyLoadedContent.h" + +using namespace qpid::broker; +using namespace qpid::framing; +using std::auto_ptr; + +MessageBuilder::MessageBuilder(CompletionHandler* _handler, + MessageStore* const _store, + uint64_t _stagingThreshold +) : + handler(_handler), + store(_store), + stagingThreshold(_stagingThreshold) +{} + +void MessageBuilder::route(){ + if (message->isComplete()) { + if (handler) handler->complete(message); + message.reset(); + } +} + +void MessageBuilder::initialise(Message::shared_ptr& msg){ + if(message.get()){ + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got publish before previous content was completed."); + } + message = msg; +} + +void MessageBuilder::setHeader(AMQHeaderBody::shared_ptr& header){ + if(!message.get()){ + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got header before publish."); + } + message->setHeader(header); + if (stagingThreshold && header->getContentSize() >= stagingThreshold) { + store->stage(*message); + message->releaseContent(store); + } else { + auto_ptr content(new InMemoryContent()); + message->setContent(content); + } + route(); +} + +void MessageBuilder::addContent(AMQContentBody::shared_ptr& content){ + if(!message.get()){ + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got content before publish."); + } + message->addContent(content); + route(); +} diff --git a/qpid/cpp/src/broker/MessageBuilder.h b/qpid/cpp/src/broker/MessageBuilder.h new file mode 100644 index 0000000000..ffac707f3b --- /dev/null +++ b/qpid/cpp/src/broker/MessageBuilder.h @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _MessageBuilder_ +#define _MessageBuilder_ + +#include +#include "../QpidError.h" +#include "BrokerExchange.h" +#include "BrokerMessage.h" +#include "MessageStore.h" +#include "../framing/AMQContentBody.h" +#include "../framing/AMQHeaderBody.h" +#include "BasicPublishBody.h" +#include "CompletionHandler.h" + +namespace qpid { + namespace broker { + class MessageBuilder{ + public: + MessageBuilder(CompletionHandler* _handler, + MessageStore* const store = 0, + uint64_t stagingThreshold = 0); + void initialise(Message::shared_ptr& msg); + void setHeader(framing::AMQHeaderBody::shared_ptr& header); + void addContent(framing::AMQContentBody::shared_ptr& content); + Message::shared_ptr getMessage() { return message; } + private: + Message::shared_ptr message; + CompletionHandler* handler; + MessageStore* const store; + const uint64_t stagingThreshold; + + void route(); + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/MessageHandlerImpl.cpp b/qpid/cpp/src/broker/MessageHandlerImpl.cpp new file mode 100644 index 0000000000..2378047054 --- /dev/null +++ b/qpid/cpp/src/broker/MessageHandlerImpl.cpp @@ -0,0 +1,243 @@ +/* + * + * 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 "../QpidError.h" +#include "MessageHandlerImpl.h" +#include "BrokerChannel.h" +#include "../framing/FramingContent.h" +#include "Connection.h" +#include "Broker.h" +#include "BrokerMessageMessage.h" +#include "MessageAppendBody.h" +#include "MessageTransferBody.h" +#include "BrokerAdapter.h" + +namespace qpid { +namespace broker { + +using namespace framing; + +MessageHandlerImpl::MessageHandlerImpl(CoreRefs& parent) + : HandlerImplType(parent) {} + +// +// Message class method handlers +// + +void +MessageHandlerImpl::cancel(const MethodContext& context, + const string& destination ) +{ + channel.cancel(destination); + client.ok(context.getRequestId()); +} + +void +MessageHandlerImpl::open(const MethodContext& context, + const string& reference) +{ + references.open(reference); + client.ok(context.getRequestId()); +} + +void +MessageHandlerImpl::append(const MethodContext& context, + const string& reference, + const string& /*bytes*/ ) +{ + references.get(reference)->append( + boost::shared_polymorphic_downcast( + context.methodBody)); + client.ok(context.getRequestId()); +} + +void +MessageHandlerImpl::close(const MethodContext& context, + const string& reference) +{ + Reference::shared_ptr ref = references.get(reference); + client.ok(context.getRequestId()); + + // Send any transfer messages to their correct exchanges and okay them + const Reference::Messages& msgs = ref->getMessages(); + for (Reference::Messages::const_iterator m = msgs.begin(); m != msgs.end(); ++m) { + channel.handleInlineTransfer(*m); + client.ok((*m)->getRequestId()); + } + ref->close(); +} + +void +MessageHandlerImpl::checkpoint(const MethodContext& context, + const string& /*reference*/, + const string& /*identifier*/ ) +{ + // Initial implementation (which is conforming) is to do nothing here + // and return offset zero for the resume + client.ok(context.getRequestId()); +} + +void +MessageHandlerImpl::resume(const MethodContext& context, + const string& reference, + const string& /*identifier*/ ) +{ + // Initial (null) implementation + // open reference and return 0 offset + references.open(reference); + client.offset(0, context.getRequestId()); +} + +void +MessageHandlerImpl::offset(const MethodContext&, + uint64_t /*value*/ ) +{ + // Shouldn't ever receive this as it is reponse to resume + // which is never sent + // TODO astitcher 2007-02-16 What is the correct exception to throw here? + THROW_QPID_ERROR(INTERNAL_ERROR, "impossible"); +} + +void +MessageHandlerImpl::consume(const MethodContext& context, + uint16_t /*ticket*/, + const string& queueName, + const string& destination, + bool noLocal, + bool noAck, + bool exclusive, + const framing::FieldTable& filter ) +{ + Queue::shared_ptr queue = connection.getQueue(queueName, channel.getId()); + if(!destination.empty() && channel.exists(destination)) + throw ConnectionException(530, "Consumer tags must be unique"); + string tag = destination; + channel.consume( + tag, queue, !noAck, exclusive, + noLocal ? &connection : 0, &filter); + client.ok(context.getRequestId()); + // Dispatch messages as there is now a consumer. + queue->dispatch(); +} + +void +MessageHandlerImpl::get( const MethodContext& context, + uint16_t /*ticket*/, + const string& queueName, + const string& destination, + bool noAck ) +{ + Queue::shared_ptr queue = + connection.getQueue(queueName, context.channel->getId()); + + if(channel.get(queue, destination, !noAck)) + client.ok(context.getRequestId()); + else + client.empty(context.getRequestId()); +} + +void +MessageHandlerImpl::empty( const MethodContext& ) +{ + // Shouldn't ever receive this as it is a response to get + // which is never sent + // TODO astitcher 2007-02-09 What is the correct exception to throw here? + THROW_QPID_ERROR(INTERNAL_ERROR, "Impossible"); +} + +void +MessageHandlerImpl::ok(const MethodContext& /*context*/) +{ + channel.ack(); +} + +void +MessageHandlerImpl::qos(const MethodContext& context, + uint32_t prefetchSize, + uint16_t prefetchCount, + bool /*global*/ ) +{ + //TODO: handle global + channel.setPrefetchSize(prefetchSize); + channel.setPrefetchCount(prefetchCount); + client.ok(context.getRequestId()); +} + +void +MessageHandlerImpl::recover(const MethodContext& context, + bool requeue) +{ + channel.recover(requeue); + client.ok(context.getRequestId()); +} + +void +MessageHandlerImpl::reject(const MethodContext& /*context*/, + uint16_t /*code*/, + const string& /*text*/ ) +{ + channel.ack(); + // channel.requeue(); +} + +void +MessageHandlerImpl::transfer(const MethodContext& context, + uint16_t /*ticket*/, + const string& /* destination */, + bool /*redelivered*/, + bool /*immediate*/, + uint64_t /*ttl*/, + uint8_t /*priority*/, + uint64_t /*timestamp*/, + uint8_t /*deliveryMode*/, + uint64_t /*expiration*/, + const string& /*exchangeName*/, + const string& /*routingKey*/, + const string& /*messageId*/, + const string& /*correlationId*/, + const string& /*replyTo*/, + const string& /*contentType*/, + const string& /*contentEncoding*/, + const string& /*userId*/, + const string& /*appId*/, + const string& /*transactionId*/, + const string& /*securityToken*/, + const framing::FieldTable& /*applicationHeaders*/, + const framing::Content& body, + bool /*mandatory*/) +{ + MessageTransferBody::shared_ptr transfer( + boost::shared_polymorphic_downcast( + context.methodBody)); + RequestId requestId = context.getRequestId(); + + if (body.isInline()) { + MessageMessage::shared_ptr message( + new MessageMessage(&connection, requestId, transfer)); + channel.handleInlineTransfer(message); + client.ok(requestId); + } else { + Reference::shared_ptr ref(references.get(body.getValue())); + MessageMessage::shared_ptr message( + new MessageMessage(&connection, requestId, transfer, ref)); + ref->addMessage(message); + } +} + + +}} // namespace qpid::broker diff --git a/qpid/cpp/src/broker/MessageHandlerImpl.h b/qpid/cpp/src/broker/MessageHandlerImpl.h new file mode 100644 index 0000000000..872d429d5c --- /dev/null +++ b/qpid/cpp/src/broker/MessageHandlerImpl.h @@ -0,0 +1,130 @@ +#ifndef _broker_MessageHandlerImpl_h +#define _broker_MessageHandlerImpl_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 "AMQP_ServerOperations.h" +#include "AMQP_ClientProxy.h" +#include "Reference.h" +#include "HandlerImpl.h" + +namespace qpid { +namespace broker { + +class Connection; +class Broker; +class MessageMessage; + +class MessageHandlerImpl : + public framing::AMQP_ServerOperations::MessageHandler, + public HandlerImpl +{ + public: + MessageHandlerImpl(CoreRefs& parent); + + void append(const framing::MethodContext&, + const std::string& reference, + const std::string& bytes ); + + void cancel(const framing::MethodContext&, + const std::string& destination ); + + void checkpoint(const framing::MethodContext&, + const std::string& reference, + const std::string& identifier ); + + void close(const framing::MethodContext&, + const std::string& reference ); + + void consume(const framing::MethodContext&, + uint16_t ticket, + const std::string& queue, + const std::string& destination, + bool noLocal, + bool noAck, + bool exclusive, + const framing::FieldTable& filter ); + + void empty( const framing::MethodContext& ); + + void get(const framing::MethodContext&, + uint16_t ticket, + const std::string& queue, + const std::string& destination, + bool noAck ); + + void offset(const framing::MethodContext&, + uint64_t value ); + + void ok( const framing::MethodContext& ); + + void open(const framing::MethodContext&, + const std::string& reference ); + + void qos(const framing::MethodContext&, + uint32_t prefetchSize, + uint16_t prefetchCount, + bool global ); + + void recover(const framing::MethodContext&, + bool requeue ); + + void reject(const framing::MethodContext&, + uint16_t code, + const std::string& text ); + + void resume(const framing::MethodContext&, + const std::string& reference, + const std::string& identifier ); + + void transfer(const framing::MethodContext&, + uint16_t ticket, + const std::string& destination, + bool redelivered, + bool immediate, + uint64_t ttl, + uint8_t priority, + uint64_t timestamp, + uint8_t deliveryMode, + uint64_t expiration, + const std::string& exchange, + const std::string& routingKey, + const std::string& messageId, + const std::string& correlationId, + const std::string& replyTo, + const std::string& contentType, + const std::string& contentEncoding, + const std::string& userId, + const std::string& appId, + const std::string& transactionId, + const std::string& securityToken, + const framing::FieldTable& applicationHeaders, + const framing::Content& body, + bool mandatory ); + private: + ReferenceRegistry references; +}; + +}} // namespace qpid::broker + + + +#endif /*!_broker_MessageHandlerImpl_h*/ diff --git a/qpid/cpp/src/broker/MessageStore.h b/qpid/cpp/src/broker/MessageStore.h new file mode 100644 index 0000000000..1d9ee86e48 --- /dev/null +++ b/qpid/cpp/src/broker/MessageStore.h @@ -0,0 +1,129 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _MessageStore_ +#define _MessageStore_ + +#include "PersistableExchange.h" +#include "PersistableMessage.h" +#include "PersistableQueue.h" +#include "RecoveryManager.h" +#include "TransactionalStore.h" + +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: + /** + * Record the existence of a durable queue + */ + virtual void create(const PersistableQueue& queue) = 0; + /** + * Destroy a durable queue + */ + virtual void destroy(const PersistableQueue& queue) = 0; + + /** + * Record the existence of a durable exchange + */ + virtual void create(const PersistableExchange& exchange) = 0; + /** + * Destroy a durable exchange + */ + virtual void destroy(const PersistableExchange& exchange) = 0; + + /** + * Request recovery of queue and message state from store + */ + virtual void recover(RecoveryManager& queues) = 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(PersistableMessage& 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(PersistableMessage& 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(PersistableMessage& 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. + * + * @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, PersistableMessage& 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. + * + * @param msg the message to dequeue + * @param queue the name of th 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, PersistableMessage& msg, const PersistableQueue& queue) = 0; + + virtual ~MessageStore(){} +}; + +} +} + + +#endif diff --git a/qpid/cpp/src/broker/MessageStoreModule.cpp b/qpid/cpp/src/broker/MessageStoreModule.cpp new file mode 100644 index 0000000000..cbda7182c1 --- /dev/null +++ b/qpid/cpp/src/broker/MessageStoreModule.cpp @@ -0,0 +1,109 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "MessageStoreModule.h" +#include + +using namespace qpid::broker; + +MessageStoreModule::MessageStoreModule(const std::string& name) : store(name) +{ +} + +void MessageStoreModule::create(const PersistableQueue& queue) +{ + store->create(queue); +} + +void MessageStoreModule::destroy(const PersistableQueue& queue) +{ + store->destroy(queue); +} + +void MessageStoreModule::create(const PersistableExchange& exchange) +{ + store->create(exchange); +} + +void MessageStoreModule::destroy(const PersistableExchange& exchange) +{ + store->destroy(exchange); +} + +void MessageStoreModule::recover(RecoveryManager& registry) +{ + store->recover(registry); +} + +void MessageStoreModule::stage(PersistableMessage& msg) +{ + store->stage(msg); +} + +void MessageStoreModule::destroy(PersistableMessage& msg) +{ + store->destroy(msg); +} + +void MessageStoreModule::appendContent(PersistableMessage& msg, const std::string& data) +{ + store->appendContent(msg, data); +} + +void MessageStoreModule::loadContent(PersistableMessage& msg, string& data, uint64_t offset, uint32_t length) +{ + store->loadContent(msg, data, offset, length); +} + +void MessageStoreModule::enqueue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue) +{ + store->enqueue(ctxt, msg, queue); +} + +void MessageStoreModule::dequeue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue) +{ + store->dequeue(ctxt, msg, queue); +} + +std::auto_ptr MessageStoreModule::begin() +{ + return store->begin(); +} + +std::auto_ptr MessageStoreModule::begin(const std::string& xid) +{ + return store->begin(xid); +} + +void MessageStoreModule::prepare(TPCTransactionContext& txn) +{ + store->prepare(txn); +} + +void MessageStoreModule::commit(TransactionContext& ctxt) +{ + store->commit(ctxt); +} + +void MessageStoreModule::abort(TransactionContext& ctxt) +{ + store->abort(ctxt); +} diff --git a/qpid/cpp/src/broker/MessageStoreModule.h b/qpid/cpp/src/broker/MessageStoreModule.h new file mode 100644 index 0000000000..b11f844948 --- /dev/null +++ b/qpid/cpp/src/broker/MessageStoreModule.h @@ -0,0 +1,67 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _MessageStoreModule_ +#define _MessageStoreModule_ + +#include "BrokerMessage.h" +#include "MessageStore.h" +#include "BrokerQueue.h" +#include "RecoveryManager.h" +#include "../sys/Module.h" + +namespace qpid { +namespace broker { + +/** + * A null implementation of the MessageStore interface + */ +class MessageStoreModule : public MessageStore +{ + qpid::sys::Module store; +public: + MessageStoreModule(const std::string& name); + + 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 create(const PersistableQueue& queue); + void destroy(const PersistableQueue& queue); + void create(const PersistableExchange& exchange); + void destroy(const PersistableExchange& exchange); + void recover(RecoveryManager& queues); + void stage(PersistableMessage& msg); + void destroy(PersistableMessage& msg); + void appendContent(PersistableMessage& msg, const std::string& data); + void loadContent(PersistableMessage& msg, std::string& data, uint64_t offset, uint32_t length); + void enqueue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue); + void dequeue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue); + + ~MessageStoreModule(){} +}; + +} +} + + +#endif diff --git a/qpid/cpp/src/broker/NameGenerator.cpp b/qpid/cpp/src/broker/NameGenerator.cpp new file mode 100644 index 0000000000..8484f921e9 --- /dev/null +++ b/qpid/cpp/src/broker/NameGenerator.cpp @@ -0,0 +1,32 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "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/broker/NameGenerator.h b/qpid/cpp/src/broker/NameGenerator.h new file mode 100644 index 0000000000..affcedba41 --- /dev/null +++ b/qpid/cpp/src/broker/NameGenerator.h @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _NameGenerator_ +#define _NameGenerator_ + +#include "BrokerMessage.h" + +namespace qpid { + namespace broker { + class NameGenerator{ + const std::string base; + unsigned int counter; + public: + NameGenerator(const std::string& base); + std::string generate(); + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/NullMessageStore.cpp b/qpid/cpp/src/broker/NullMessageStore.cpp new file mode 100644 index 0000000000..ac40987a44 --- /dev/null +++ b/qpid/cpp/src/broker/NullMessageStore.cpp @@ -0,0 +1,105 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "NullMessageStore.h" + +#include "RecoveryManager.h" + +#include + +using namespace qpid::broker; + +NullMessageStore::NullMessageStore(bool _warn) : warn(_warn){} + +void NullMessageStore::create(const PersistableQueue& queue) +{ + if (warn) std::cout << "WARNING: Can't create durable queue '" << queue.getName() << "'. Persistence not enabled." << std::endl; +} + +void NullMessageStore::destroy(const PersistableQueue& queue) +{ + if (warn) std::cout << "WARNING: Can't destroy durable queue '" << queue.getName() << "'. Persistence not enabled." << std::endl; +} + +void NullMessageStore::create(const PersistableExchange&) +{ +} + +void NullMessageStore::destroy(const PersistableExchange&) +{ +} + +void NullMessageStore::recover(RecoveryManager&) +{ + if (warn) std::cout << "WARNING: Persistence not enabled, no recovery of queues or messages." << std::endl; +} + +void NullMessageStore::stage(PersistableMessage&) +{ + if (warn) std::cout << "WARNING: Can't stage message. Persistence not enabled." << std::endl; +} + +void NullMessageStore::destroy(PersistableMessage&) +{ + if (warn) std::cout << "WARNING: No need to destroy staged message. Persistence not enabled." << std::endl; +} + +void NullMessageStore::appendContent(PersistableMessage&, const string&) +{ + if (warn) std::cout << "WARNING: Can't append content. Persistence not enabled." << std::endl; +} + +void NullMessageStore::loadContent(PersistableMessage&, string&, uint64_t, uint32_t) +{ + if (warn) std::cout << "WARNING: Can't load content. Persistence not enabled." << std::endl; +} + +void NullMessageStore::enqueue(TransactionContext*, PersistableMessage&, const PersistableQueue& queue) +{ + if (warn) std::cout << "WARNING: Can't enqueue message onto '" << queue.getName() << "'. Persistence not enabled." << std::endl; +} + +void NullMessageStore::dequeue(TransactionContext*, PersistableMessage&, const PersistableQueue& queue) +{ + if (warn) std::cout << "WARNING: Can't dequeue message from '" << queue.getName() << "'. Persistence not enabled." << std::endl; +} + +std::auto_ptr NullMessageStore::begin() +{ + return std::auto_ptr(); +} + +std::auto_ptr NullMessageStore::begin(const std::string&) +{ + return std::auto_ptr(); +} + +void NullMessageStore::prepare(TPCTransactionContext&) +{ +} + +void NullMessageStore::commit(TransactionContext&) +{ +} + +void NullMessageStore::abort(TransactionContext&) +{ +} diff --git a/qpid/cpp/src/broker/NullMessageStore.h b/qpid/cpp/src/broker/NullMessageStore.h new file mode 100644 index 0000000000..3d08e1a7a2 --- /dev/null +++ b/qpid/cpp/src/broker/NullMessageStore.h @@ -0,0 +1,64 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _NullMessageStore_ +#define _NullMessageStore_ + +#include "BrokerMessage.h" +#include "MessageStore.h" +#include "BrokerQueue.h" + +namespace qpid { +namespace broker { + +/** + * A null implementation of the MessageStore interface + */ +class NullMessageStore : public MessageStore +{ + const bool warn; +public: + NullMessageStore(bool warn = false); + + virtual std::auto_ptr begin(); + virtual std::auto_ptr begin(const std::string& xid); + virtual void prepare(TPCTransactionContext& txn); + virtual void commit(TransactionContext& txn); + virtual void abort(TransactionContext& txn); + + virtual void create(const PersistableQueue& queue); + virtual void destroy(const PersistableQueue& queue); + virtual void create(const PersistableExchange& exchange); + virtual void destroy(const PersistableExchange& exchange); + virtual void recover(RecoveryManager& queues); + virtual void stage(PersistableMessage& msg); + virtual void destroy(PersistableMessage& msg); + virtual void appendContent(PersistableMessage& msg, const std::string& data); + virtual void loadContent(PersistableMessage& msg, std::string& data, uint64_t offset, uint32_t length); + virtual void enqueue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue); + virtual void dequeue(TransactionContext* ctxt, PersistableMessage& msg, const PersistableQueue& queue); + ~NullMessageStore(){} +}; + +} +} + + +#endif diff --git a/qpid/cpp/src/broker/Persistable.h b/qpid/cpp/src/broker/Persistable.h new file mode 100644 index 0000000000..a53ea428ed --- /dev/null +++ b/qpid/cpp/src/broker/Persistable.h @@ -0,0 +1,62 @@ +#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 "../framing/amqp_types.h" +#include "../framing/Buffer.h" + +namespace qpid { +namespace broker { + +/** + * Base class for all persistable objects + */ +class Persistable +{ +public: + /** + * Allows the store to attach its own identifier to this object + */ + virtual void setPersistenceId(uint64_t id) = 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/broker/PersistableExchange.h b/qpid/cpp/src/broker/PersistableExchange.h new file mode 100644 index 0000000000..9badf5f609 --- /dev/null +++ b/qpid/cpp/src/broker/PersistableExchange.h @@ -0,0 +1,44 @@ +#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 "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 ~PersistableExchange() {}; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/broker/PersistableMessage.h b/qpid/cpp/src/broker/PersistableMessage.h new file mode 100644 index 0000000000..c10d16bc65 --- /dev/null +++ b/qpid/cpp/src/broker/PersistableMessage.h @@ -0,0 +1,53 @@ +#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 "Persistable.h" +#include "../framing/amqp_types.h" + +namespace qpid { +namespace broker { + +/** + * The interface messages must expose to the MessageStore in order to + * be persistable. + */ + class PersistableMessage : public Persistable +{ +public: + typedef boost::shared_ptr shared_ptr; + + /** + * @returns the size of the headers when encoded + */ + virtual uint32_t encodedHeaderSize() const = 0; + + virtual ~PersistableMessage() {}; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/broker/PersistableQueue.h b/qpid/cpp/src/broker/PersistableQueue.h new file mode 100644 index 0000000000..5dd91dde9b --- /dev/null +++ b/qpid/cpp/src/broker/PersistableQueue.h @@ -0,0 +1,45 @@ +#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 "Persistable.h" + +namespace qpid { +namespace broker { + +/** + * 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() {}; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/broker/Prefetch.h b/qpid/cpp/src/broker/Prefetch.h new file mode 100644 index 0000000000..448156c187 --- /dev/null +++ b/qpid/cpp/src/broker/Prefetch.h @@ -0,0 +1,42 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _Prefetch_ +#define _Prefetch_ + +#include "../framing/amqp_types.h" + +namespace qpid { + namespace broker { + /** + * Count and total size of asynchronously delivered + * (i.e. pushed) messages that have acks outstanding. + */ + struct Prefetch{ + uint32_t size; + uint16_t count; + + void reset() { size = 0; count = 0; } + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/QueuePolicy.cpp b/qpid/cpp/src/broker/QueuePolicy.cpp new file mode 100644 index 0000000000..620822cddc --- /dev/null +++ b/qpid/cpp/src/broker/QueuePolicy.cpp @@ -0,0 +1,69 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "QueuePolicy.h" + +using namespace qpid::broker; +using namespace qpid::framing; + +QueuePolicy::QueuePolicy(uint32_t _maxCount, uint64_t _maxSize) : + maxCount(_maxCount), maxSize(_maxSize), count(0), size(0) {} + +QueuePolicy::QueuePolicy(const FieldTable& settings) : + maxCount(getInt(settings, maxCountKey, 0)), + maxSize(getInt(settings, maxSizeKey, 0)), count(0), size(0) {} + +void QueuePolicy::enqueued(uint64_t _size) +{ + if (maxCount) count++; + if (maxSize) size += _size; +} + +void QueuePolicy::dequeued(uint64_t _size) +{ + if (maxCount) count--; + if (maxSize) size -= _size; +} + +bool QueuePolicy::limitExceeded() +{ + return (maxSize && size > maxSize) || (maxCount && count > maxCount); +} + +void QueuePolicy::update(FieldTable& settings) +{ + if (maxCount) settings.setInt(maxCountKey, maxCount); + if (maxSize) settings.setInt(maxSizeKey, maxSize); +} + + +int QueuePolicy::getInt(const FieldTable& settings, const std::string& key, int defaultValue) +{ + //Note: currently field table only contain signed 32 bit ints, which + // restricts the values that can be set on the queue policy. + try { + return settings.getInt(key); + } catch (FieldNotFoundException& ignore) { + return defaultValue; + } +} + +const std::string QueuePolicy::maxCountKey("qpid.max_count"); +const std::string QueuePolicy::maxSizeKey("qpid.max_size"); diff --git a/qpid/cpp/src/broker/QueuePolicy.h b/qpid/cpp/src/broker/QueuePolicy.h new file mode 100644 index 0000000000..28c3f81516 --- /dev/null +++ b/qpid/cpp/src/broker/QueuePolicy.h @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _QueuePolicy_ +#define _QueuePolicy_ + +#include "../framing/FieldTable.h" + +namespace qpid { + namespace broker { + class QueuePolicy + { + static const std::string maxCountKey; + static const std::string maxSizeKey; + + const uint32_t maxCount; + const uint64_t maxSize; + uint32_t count; + uint64_t size; + + static int getInt(const qpid::framing::FieldTable& settings, const std::string& key, int defaultValue); + + public: + QueuePolicy(uint32_t maxCount, uint64_t maxSize); + QueuePolicy(const qpid::framing::FieldTable& settings); + void enqueued(uint64_t size); + void dequeued(uint64_t size); + void update(qpid::framing::FieldTable& settings); + bool limitExceeded(); + uint32_t getMaxCount() const { return maxCount; } + uint64_t getMaxSize() const { return maxSize; } + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/QueueRegistry.cpp b/qpid/cpp/src/broker/QueueRegistry.cpp new file mode 100644 index 0000000000..dcaf7ec0f6 --- /dev/null +++ b/qpid/cpp/src/broker/QueueRegistry.cpp @@ -0,0 +1,78 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "QueueRegistry.h" +#include +#include + +using namespace qpid::broker; +using namespace qpid::sys; + +QueueRegistry::QueueRegistry(MessageStore* const _store) : counter(1), store(_store){} + +QueueRegistry::~QueueRegistry(){} + +std::pair +QueueRegistry::declare(const string& declareName, bool durable, + uint32_t autoDelete, const ConnectionToken* owner) +{ + Mutex::ScopedLock locker(lock); + string name = declareName.empty() ? generateName() : declareName; + assert(!name.empty()); + QueueMap::iterator i = queues.find(name); + if (i == queues.end()) { + Queue::shared_ptr queue(new Queue(name, autoDelete, durable ? store : 0, owner)); + queues[name] = queue; + return std::pair(queue, true); + } else { + return std::pair(i->second, false); + } +} + +void QueueRegistry::destroy(const string& name){ + Mutex::ScopedLock locker(lock); + queues.erase(name); +} + +Queue::shared_ptr QueueRegistry::find(const string& name){ + Mutex::ScopedLock locker(lock); + QueueMap::iterator i = queues.find(name); + if (i == queues.end()) { + return Queue::shared_ptr(); + } else { + return i->second; + } +} + +string QueueRegistry::generateName(){ + string name; + do { + std::stringstream ss; + ss << "tmp_" << counter++; + name = ss.str(); + // Thread safety: Private function, only called with lock held + // so this is OK. + } while(queues.find(name) != queues.end()); + return name; +} + +MessageStore* const QueueRegistry::getStore() const { + return store; +} diff --git a/qpid/cpp/src/broker/QueueRegistry.h b/qpid/cpp/src/broker/QueueRegistry.h new file mode 100644 index 0000000000..5798226c48 --- /dev/null +++ b/qpid/cpp/src/broker/QueueRegistry.h @@ -0,0 +1,96 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _QueueRegistry_ +#define _QueueRegistry_ + +#include +#include "../sys/Monitor.h" +#include "BrokerQueue.h" + +namespace qpid { +namespace broker { + +/** + * 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{ + + public: + QueueRegistry(MessageStore* const store = 0); + ~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. + */ + std::pair declare(const string& name, bool durable = false, uint32_t autodelete = 0, + const ConnectionToken* const owner = 0); + + /** + * 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. + * + */ + void destroy(const string& name); + + /** + * Find the named queue. Return 0 if not found. + */ + Queue::shared_ptr find(const string& name); + + /** + * Generate unique queue name. + */ + string generateName(); + + /** + * Return the message store used. + */ + MessageStore* const getStore() const; + + + private: + typedef std::map QueueMap; + QueueMap queues; + qpid::sys::Mutex lock; + int counter; + MessageStore* const store; +}; + + +} +} + + +#endif diff --git a/qpid/cpp/src/broker/RecoverableMessage.h b/qpid/cpp/src/broker/RecoverableMessage.h new file mode 100644 index 0000000000..c79a84081c --- /dev/null +++ b/qpid/cpp/src/broker/RecoverableMessage.h @@ -0,0 +1,57 @@ +#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 "../framing/amqp_types.h" +#include "../framing/Buffer.h" + +namespace qpid { +namespace broker { + +/** + * The interface through which messages are reloaded on recovery. + */ +class RecoverableMessage +{ +public: + typedef boost::shared_ptr shared_ptr; + /** + * 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 ~RecoverableMessage() {}; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/broker/RecoverableQueue.h b/qpid/cpp/src/broker/RecoverableQueue.h new file mode 100644 index 0000000000..a5c564b947 --- /dev/null +++ b/qpid/cpp/src/broker/RecoverableQueue.h @@ -0,0 +1,49 @@ +#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 "RecoverableMessage.h" +#include + +namespace qpid { +namespace broker { + +/** + * The interface through which messages are added back to queues on + * recovery. + */ +class RecoverableQueue +{ +public: + typedef boost::shared_ptr shared_ptr; + /** + * Used during recovery to add stored messages back to the queue + */ + virtual void recover(RecoverableMessage::shared_ptr msg) = 0; + virtual ~RecoverableQueue() {}; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/broker/RecoveryManager.h b/qpid/cpp/src/broker/RecoveryManager.h new file mode 100644 index 0000000000..3f351f6a2e --- /dev/null +++ b/qpid/cpp/src/broker/RecoveryManager.h @@ -0,0 +1,45 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _RecoveryManager_ +#define _RecoveryManager_ + +#include "RecoverableQueue.h" +#include "RecoverableMessage.h" +#include "../framing/Buffer.h" + +namespace qpid { +namespace broker { + + class RecoveryManager{ + public: + virtual ~RecoveryManager(){} + virtual void recoverExchange(framing::Buffer& buffer) = 0; + virtual RecoverableQueue::shared_ptr recoverQueue(framing::Buffer& buffer) = 0; + virtual RecoverableMessage::shared_ptr recoverMessage(framing::Buffer& buffer) = 0; + virtual void recoveryComplete() = 0; + }; + + +} +} + + +#endif diff --git a/qpid/cpp/src/broker/RecoveryManagerImpl.cpp b/qpid/cpp/src/broker/RecoveryManagerImpl.cpp new file mode 100644 index 0000000000..7c04ec9916 --- /dev/null +++ b/qpid/cpp/src/broker/RecoveryManagerImpl.cpp @@ -0,0 +1,131 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "RecoveryManagerImpl.h" + +#include "BrokerMessage.h" +#include "BrokerMessageMessage.h" +#include "BrokerQueue.h" + +using namespace qpid; +using namespace qpid::broker; +using boost::dynamic_pointer_cast; + + +static const uint8_t BASIC = 1; +static const uint8_t MESSAGE = 2; + +RecoveryManagerImpl::RecoveryManagerImpl(QueueRegistry& _queues, ExchangeRegistry& _exchanges, uint64_t _stagingThreshold) + : queues(_queues), exchanges(_exchanges), stagingThreshold(_stagingThreshold) {} + +RecoveryManagerImpl::~RecoveryManagerImpl() {} + +class RecoverableMessageImpl : public RecoverableMessage +{ + Message::shared_ptr msg; + const uint64_t stagingThreshold; +public: + RecoverableMessageImpl(Message::shared_ptr& _msg, uint64_t _stagingThreshold) + : msg(_msg), stagingThreshold(_stagingThreshold) {} + ~RecoverableMessageImpl() {}; + bool loadContent(uint64_t available); + void decodeContent(framing::Buffer& buffer); + void recover(Queue::shared_ptr queue); +}; + +class RecoverableQueueImpl : public RecoverableQueue +{ + Queue::shared_ptr queue; +public: + RecoverableQueueImpl(Queue::shared_ptr& _queue) : queue(_queue) {} + ~RecoverableQueueImpl() {}; + void recover(RecoverableMessage::shared_ptr msg); +}; + +void RecoveryManagerImpl::recoverExchange(framing::Buffer&) +{ + //TODO +} + +RecoverableQueue::shared_ptr RecoveryManagerImpl::recoverQueue(framing::Buffer& buffer) +{ + Queue::shared_ptr queue = Queue::decode(queues, buffer); + try { + Exchange::shared_ptr exchange = exchanges.getDefault(); + if (exchange) { + exchange->bind(queue, queue->getName(), 0); + } + } catch (ChannelException& e) { + //assume no default exchange has been declared + } + return RecoverableQueue::shared_ptr(new RecoverableQueueImpl(queue)); +} + +RecoverableMessage::shared_ptr RecoveryManagerImpl::recoverMessage(framing::Buffer& buffer) +{ + buffer.record(); + //peek at type: + Message::shared_ptr message(decodeMessageType(buffer) == MESSAGE ? + ((Message*) new MessageMessage()) : + ((Message*) new BasicMessage())); + buffer.restore(); + message->decodeHeader(buffer); + return RecoverableMessage::shared_ptr(new RecoverableMessageImpl(message, stagingThreshold)); +} + +void RecoveryManagerImpl::recoveryComplete() +{ + //TODO (finalise binding setup etc) +} + +uint8_t RecoveryManagerImpl::decodeMessageType(framing::Buffer& buffer) +{ + return buffer.getOctet(); +} + +void RecoveryManagerImpl::encodeMessageType(const Message& msg, framing::Buffer& buffer) +{ + buffer.putOctet(dynamic_cast(&msg) ? MESSAGE : BASIC); +} + +uint32_t RecoveryManagerImpl::encodedMessageTypeSize() +{ + return 1; +} + +bool RecoverableMessageImpl::loadContent(uint64_t available) +{ + return !stagingThreshold || available < stagingThreshold; +} + +void RecoverableMessageImpl::decodeContent(framing::Buffer& buffer) +{ + msg->decodeContent(buffer); +} + +void RecoverableMessageImpl::recover(Queue::shared_ptr queue) +{ + queue->recover(msg); +} + +void RecoverableQueueImpl::recover(RecoverableMessage::shared_ptr msg) +{ + dynamic_pointer_cast(msg)->recover(queue); +} diff --git a/qpid/cpp/src/broker/RecoveryManagerImpl.h b/qpid/cpp/src/broker/RecoveryManagerImpl.h new file mode 100644 index 0000000000..c40de7895f --- /dev/null +++ b/qpid/cpp/src/broker/RecoveryManagerImpl.h @@ -0,0 +1,55 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _RecoveryManagerImpl_ +#define _RecoveryManagerImpl_ + +#include +#include "ExchangeRegistry.h" +#include "QueueRegistry.h" +#include "RecoveryManager.h" + +namespace qpid { +namespace broker { + + class RecoveryManagerImpl : public RecoveryManager{ + QueueRegistry& queues; + ExchangeRegistry& exchanges; + const uint64_t stagingThreshold; + public: + RecoveryManagerImpl(QueueRegistry& queues, ExchangeRegistry& exchanges, uint64_t stagingThreshold); + ~RecoveryManagerImpl(); + + void recoverExchange(framing::Buffer& buffer); + RecoverableQueue::shared_ptr recoverQueue(framing::Buffer& buffer); + RecoverableMessage::shared_ptr recoverMessage(framing::Buffer& buffer); + void recoveryComplete(); + + static uint8_t decodeMessageType(framing::Buffer& buffer); + static void encodeMessageType(const Message& msg, framing::Buffer& buffer); + static uint32_t encodedMessageTypeSize(); + }; + + +} +} + + +#endif diff --git a/qpid/cpp/src/broker/Reference.cpp b/qpid/cpp/src/broker/Reference.cpp new file mode 100644 index 0000000000..ef55d3e6a2 --- /dev/null +++ b/qpid/cpp/src/broker/Reference.cpp @@ -0,0 +1,52 @@ +/* + * + * 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 "Reference.h" +#include "BrokerMessageMessage.h" +#include "../QpidError.h" +#include "MessageAppendBody.h" +#include "CompletionHandler.h" + +namespace qpid { +namespace broker { + +Reference::shared_ptr ReferenceRegistry::open(const Reference::Id& id) { + ReferenceMap::iterator i = references.find(id); + if (i != references.end()) + throw ConnectionException(503, "Attempt to re-open reference " +id); + return references[id] = Reference::shared_ptr(new Reference(id, this)); +} + +Reference::shared_ptr ReferenceRegistry::get(const Reference::Id& id) { + ReferenceMap::iterator i = references.find(id); + if (i == references.end()) + throw ConnectionException(503, "Attempt to use non-existent reference "+id); + return i->second; +} + +void Reference::append(AppendPtr ptr) { + appends.push_back(ptr); + size += ptr->getBytes().length(); +} + +void Reference::close() { + registry->references.erase(getId()); +} + +}} // namespace qpid::broker diff --git a/qpid/cpp/src/broker/Reference.h b/qpid/cpp/src/broker/Reference.h new file mode 100644 index 0000000000..277eb7b917 --- /dev/null +++ b/qpid/cpp/src/broker/Reference.h @@ -0,0 +1,114 @@ +#ifndef _broker_Reference_h +#define _broker_Reference_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 +#include +#include +#include + +namespace qpid { + +namespace framing { +class MessageAppendBody; +} + +namespace broker { + +class MessageMessage; +class ReferenceRegistry; + +// FIXME aconway 2007-03-27: Merge with client::IncomingMessage +// to common reference handling code. + +/** + * A reference is an accumulation point for data in a multi-frame + * message. A reference can be used by multiple transfer commands to + * create multiple messages, so the reference tracks which commands + * are using it. When the reference is closed, all the associated + * transfers are completed. + * + * THREAD UNSAFE: per-channel resource, access to channels is + * serialized. + */ +class Reference +{ + public: + typedef std::string Id; + typedef boost::shared_ptr shared_ptr; + typedef boost::shared_ptr MessagePtr; + typedef std::vector Messages; + typedef boost::shared_ptr AppendPtr; + typedef std::vector Appends; + + Reference(const Id& id_=Id(), ReferenceRegistry* reg=0) + : id(id_), size(0), registry(reg) {} + + const std::string& getId() const { return id; } + uint64_t getSize() const { return size; } + + /** Add a message to be completed with this reference */ + void addMessage(MessagePtr message) { messages.push_back(message); } + + /** Append more data to the reference */ + void append(AppendPtr ptr); + + /** Close the reference, complete each associated message */ + void close(); + + const Appends& getAppends() const { return appends; } + const Messages& getMessages() const { return messages; } + + private: + Id id; + uint64_t size; + ReferenceRegistry* registry; + Messages messages; + Appends appends; +}; + + +/** + * A registry/factory for references. + * + * THREAD UNSAFE: per-channel resource, access to channels is + * serialized. + */ +class ReferenceRegistry { + public: + ReferenceRegistry() {}; + Reference::shared_ptr open(const Reference::Id& id); + Reference::shared_ptr get(const Reference::Id& id); + + private: + typedef std::map ReferenceMap; + ReferenceMap references; + + // Reference calls references.erase(). + friend class Reference; +}; + + +}} // namespace qpid::broker + + + +#endif /*!_broker_Reference_h*/ diff --git a/qpid/cpp/src/broker/TopicExchange.cpp b/qpid/cpp/src/broker/TopicExchange.cpp new file mode 100644 index 0000000000..f29dfc38ba --- /dev/null +++ b/qpid/cpp/src/broker/TopicExchange.cpp @@ -0,0 +1,154 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "TopicExchange.h" +#include + +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::sys; + +// TODO aconway 2006-09-20: More efficient matching algorithm. +// Areas for improvement: +// - excessive string copying: should be 0 copy, match from original buffer. +// - match/lookup: use descision tree or other more efficient structure. + +Tokens& Tokens::operator=(const std::string& s) { + clear(); + if (s.empty()) return *this; + std::string::const_iterator i = s.begin(); + while (true) { + // Invariant: i is at the beginning of the next untokenized word. + std::string::const_iterator j = find(i, s.end(), '.'); + push_back(std::string(i, j)); + if (j == s.end()) return *this; + i = j + 1; + } + return *this; +} + +TopicPattern& TopicPattern::operator=(const Tokens& tokens) { + Tokens::operator=(tokens); + normalize(); + return *this; +} + +namespace { +const std::string hashmark("#"); +const std::string star("*"); +} + +void TopicPattern::normalize() { + std::string word; + Tokens::iterator i = begin(); + while (i != end()) { + if (*i == hashmark) { + ++i; + while (i != end()) { + // Invariant: *(i-1)==#, [begin()..i-1] is normalized. + if (*i == star) { // Move * before #. + std::swap(*i, *(i-1)); + ++i; + } else if (*i == hashmark) { + erase(i); // Remove extra # + } else { + break; + } + } + } else { + i ++; + } + } +} + + +namespace { +// TODO aconway 2006-09-20: Ineficient to convert every routingKey to a string. +// Need StringRef class that operates on a string in place witout copy. +// Should be applied everywhere strings are extracted from frames. +// +bool do_match(Tokens::const_iterator pattern_begin, Tokens::const_iterator pattern_end, Tokens::const_iterator target_begin, Tokens::const_iterator target_end) +{ + // Invariant: [pattern_begin..p) matches [target_begin..t) + Tokens::const_iterator p = pattern_begin; + Tokens::const_iterator t = target_begin; + while (p != pattern_end && t != target_end) + { + if (*p == star || *p == *t) { + ++p, ++t; + } else if (*p == hashmark) { + ++p; + if (do_match(p, pattern_end, t, target_end)) return true; + while (t != target_end) { + ++t; + if (do_match(p, pattern_end, t, target_end)) return true; + } + return false; + } else { + return false; + } + } + while (p != pattern_end && *p == hashmark) ++p; // Ignore trailing # + return t == target_end && p == pattern_end; +} +} + +bool TopicPattern::match(const Tokens& target) const +{ + return do_match(begin(), end(), target.begin(), target.end()); +} + +TopicExchange::TopicExchange(const string& _name) : Exchange(_name) { } + +void TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* /*args*/){ + Monitor::ScopedLock l(lock); + TopicPattern routingPattern(routingKey); + bindings[routingPattern].push_back(queue); +} + +void TopicExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* /*args*/){ + Monitor::ScopedLock l(lock); + BindingMap::iterator bi = bindings.find(TopicPattern(routingKey)); + Queue::vector& qv(bi->second); + if (bi == bindings.end()) return; + Queue::vector::iterator q = find(qv.begin(), qv.end(), queue); + if(q == qv.end()) return; + qv.erase(q); + if(qv.empty()) bindings.erase(bi); +} + + +void TopicExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/){ + Monitor::ScopedLock l(lock); + for (BindingMap::iterator i = bindings.begin(); i != bindings.end(); ++i) { + if (i->first.match(routingKey)) { + Queue::vector& qv(i->second); + for(Queue::vector::iterator j = qv.begin(); j != qv.end(); j++){ + msg.deliverTo(*j); + } + } + } +} + +TopicExchange::~TopicExchange() {} + +const std::string TopicExchange::typeName("topic"); + + diff --git a/qpid/cpp/src/broker/TopicExchange.h b/qpid/cpp/src/broker/TopicExchange.h new file mode 100644 index 0000000000..8aba0911c0 --- /dev/null +++ b/qpid/cpp/src/broker/TopicExchange.h @@ -0,0 +1,100 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _TopicExchange_ +#define _TopicExchange_ + +#include +#include +#include "BrokerExchange.h" +#include "../framing/FieldTable.h" +#include "BrokerMessage.h" +#include "../sys/Monitor.h" +#include "BrokerQueue.h" + +namespace qpid { +namespace broker { + +/** A vector of string tokens */ +class Tokens : public std::vector { + public: + Tokens() {}; + // Default copy, assign, dtor are sufficient. + + /** Tokenize s, provides automatic conversion of string to Tokens */ + Tokens(const std::string& s) { operator=(s); } + /** Tokenizing assignment operator s */ + Tokens & operator=(const std::string& s); + + private: + size_t hash; +}; + + +/** + * Tokens that have been normalized as a pattern and can be matched + * with topic Tokens. Normalized meands all sequences of mixed * and + * # are reduced to a series of * followed by at most one #. + */ +class TopicPattern : public Tokens +{ + public: + TopicPattern() {} + // Default copy, assign, dtor are sufficient. + TopicPattern(const Tokens& tokens) { operator=(tokens); } + TopicPattern(const std::string& str) { operator=(str); } + TopicPattern& operator=(const Tokens&); + TopicPattern& operator=(const std::string& str) { return operator=(Tokens(str)); } + + /** Match a topic */ + bool match(const std::string& topic) { return match(Tokens(topic)); } + bool match(const Tokens& topic) const; + + private: + void normalize(); +}; + +class TopicExchange : public virtual Exchange{ + typedef std::map BindingMap; + BindingMap bindings; + qpid::sys::Mutex lock; + + public: + static const std::string typeName; + + TopicExchange(const string& name); + + virtual std::string getType(){ return typeName; } + + virtual void bind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args); + + virtual void unbind(Queue::shared_ptr queue, const string& routingKey, const qpid::framing::FieldTable* args); + + virtual void route(Deliverable& msg, const string& routingKey, const qpid::framing::FieldTable* args); + + virtual ~TopicExchange(); +}; + + + +} +} + +#endif diff --git a/qpid/cpp/src/broker/TransactionalStore.h b/qpid/cpp/src/broker/TransactionalStore.h new file mode 100644 index 0000000000..9347edf0ad --- /dev/null +++ b/qpid/cpp/src/broker/TransactionalStore.h @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _TransactionalStore_ +#define _TransactionalStore_ + +#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 ~TransactionalStore(){} +}; + +} +} + + +#endif diff --git a/qpid/cpp/src/broker/TxAck.cpp b/qpid/cpp/src/broker/TxAck.cpp new file mode 100644 index 0000000000..60d8049102 --- /dev/null +++ b/qpid/cpp/src/broker/TxAck.cpp @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "TxAck.h" + +using std::bind1st; +using std::bind2nd; +using std::mem_fun_ref; +using namespace qpid::broker; + +TxAck::TxAck(AccumulatedAck& _acked, std::list& _unacked) : + acked(_acked), unacked(_unacked){ + +} + +bool TxAck::prepare(TransactionContext* ctxt) throw(){ + try{ + //dequeue all acked messages from their queues + for (ack_iterator i = unacked.begin(); i != unacked.end(); i++) { + if (i->coveredBy(&acked)) { + i->discard(ctxt); + } + } + return true; + }catch(...){ + std::cout << "TxAck::prepare() - Failed to prepare" << std::endl; + return false; + } +} + +void TxAck::commit() throw(){ + //remove all acked records from the list + unacked.remove_if(bind2nd(mem_fun_ref(&DeliveryRecord::coveredBy), &acked)); +} + +void TxAck::rollback() throw(){ +} diff --git a/qpid/cpp/src/broker/TxAck.h b/qpid/cpp/src/broker/TxAck.h new file mode 100644 index 0000000000..5e6d0a370c --- /dev/null +++ b/qpid/cpp/src/broker/TxAck.h @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _TxAck_ +#define _TxAck_ + +#include +#include +#include +#include "AccumulatedAck.h" +#include "DeliveryRecord.h" +#include "TxOp.h" + +namespace qpid { + namespace broker { + /** + * Defines the transactional behaviour for acks received by a + * transactional channel. + */ + class TxAck : public TxOp{ + AccumulatedAck& acked; + std::list& unacked; + + public: + /** + * @param acked a representation of the accumulation of + * acks received + * @param unacked the record of delivered messages + */ + TxAck(AccumulatedAck& acked, std::list& unacked); + virtual bool prepare(TransactionContext* ctxt) throw(); + virtual void commit() throw(); + virtual void rollback() throw(); + virtual ~TxAck(){} + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/TxBuffer.cpp b/qpid/cpp/src/broker/TxBuffer.cpp new file mode 100644 index 0000000000..47bc13b5c0 --- /dev/null +++ b/qpid/cpp/src/broker/TxBuffer.cpp @@ -0,0 +1,55 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "TxBuffer.h" + +using std::mem_fun; +using namespace qpid::broker; + +bool TxBuffer::prepare(TransactionalStore* const store) +{ + std::auto_ptr ctxt; + if(store) ctxt = store->begin(); + for(op_iterator i = ops.begin(); i < ops.end(); i++){ + if(!(*i)->prepare(ctxt.get())){ + if(store) store->abort(*ctxt); + return false; + } + } + if(store) store->commit(*ctxt); + return true; +} + +void TxBuffer::commit() +{ + for_each(ops.begin(), ops.end(), mem_fun(&TxOp::commit)); + ops.clear(); +} + +void TxBuffer::rollback() +{ + for_each(ops.begin(), ops.end(), mem_fun(&TxOp::rollback)); + ops.clear(); +} + +void TxBuffer::enlist(TxOp* const op) +{ + ops.push_back(op); +} diff --git a/qpid/cpp/src/broker/TxBuffer.h b/qpid/cpp/src/broker/TxBuffer.h new file mode 100644 index 0000000000..61c0820c7d --- /dev/null +++ b/qpid/cpp/src/broker/TxBuffer.h @@ -0,0 +1,107 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _TxBuffer_ +#define _TxBuffer_ + +#include +#include +#include +#include "TransactionalStore.h" +#include "TxOp.h" + +/** + * 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. + */ +namespace qpid { + namespace broker { + class TxBuffer{ + typedef std::vector::iterator op_iterator; + std::vector ops; + public: + /** + * Requests that all ops are prepared. This should + * primarily involve making sure that a persistent record + * of the operations is stored where necessary. + * + * All ops will be prepared under a transaction on the + * specified store. If any operation fails on prepare, + * this transaction will be rolled back. + * + * 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. + */ + bool prepare(TransactionalStore* const store); + /** + * Signals that the ops all prepared all completed + * 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. + */ + void commit(); + /** + * Rolls back all the operations. + * + * Should only be called either after a call to prepare() + * returns true (2pc) or instead of a prepare call + * ('server-local') + */ + void rollback(); + /** + * Adds an operation to the transaction. + */ + void enlist(TxOp* const op); + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/TxOp.h b/qpid/cpp/src/broker/TxOp.h new file mode 100644 index 0000000000..8546a42616 --- /dev/null +++ b/qpid/cpp/src/broker/TxOp.h @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _TxOp_ +#define _TxOp_ + +#include "TransactionalStore.h" + +namespace qpid { + namespace broker { + class TxOp{ + public: + virtual bool prepare(TransactionContext*) throw() = 0; + virtual void commit() throw() = 0; + virtual void rollback() throw() = 0; + virtual ~TxOp(){} + }; + } +} + + +#endif diff --git a/qpid/cpp/src/broker/TxPublish.cpp b/qpid/cpp/src/broker/TxPublish.cpp new file mode 100644 index 0000000000..687505909c --- /dev/null +++ b/qpid/cpp/src/broker/TxPublish.cpp @@ -0,0 +1,60 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "TxPublish.h" + +using namespace qpid::broker; + +TxPublish::TxPublish(Message::shared_ptr _msg) : msg(_msg) {} + +bool TxPublish::prepare(TransactionContext* ctxt) throw(){ + try{ + for_each(queues.begin(), queues.end(), Prepare(ctxt, msg)); + return true; + }catch(...){ + std::cout << "TxPublish::prepare() - Failed to prepare" << std::endl; + return false; + } +} + +void TxPublish::commit() throw(){ + for_each(queues.begin(), queues.end(), Commit(msg)); +} + +void TxPublish::rollback() throw(){ +} + +void TxPublish::deliverTo(Queue::shared_ptr& queue){ + queues.push_back(queue); +} + +TxPublish::Prepare::Prepare(TransactionContext* _ctxt, Message::shared_ptr& _msg) + : ctxt(_ctxt), msg(_msg){} + +void TxPublish::Prepare::operator()(Queue::shared_ptr& queue){ + queue->enqueue(ctxt, msg); +} + +TxPublish::Commit::Commit(Message::shared_ptr& _msg) : msg(_msg){} + +void TxPublish::Commit::operator()(Queue::shared_ptr& queue){ + queue->process(msg); +} + diff --git a/qpid/cpp/src/broker/TxPublish.h b/qpid/cpp/src/broker/TxPublish.h new file mode 100644 index 0000000000..29b1dc38af --- /dev/null +++ b/qpid/cpp/src/broker/TxPublish.h @@ -0,0 +1,78 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _TxPublish_ +#define _TxPublish_ + +#include +#include +#include +#include "Deliverable.h" +#include "BrokerMessage.h" +#include "MessageStore.h" +#include "BrokerQueue.h" +#include "TxOp.h" + +namespace qpid { + namespace broker { + /** + * Defines the behaviour for publish operations on a + * transactional channel. Messages are routed through + * exchanges when received but are not at that stage delivered + * to the matching queues, rather the queues are held in an + * instance of this class. On prepare() the message is marked + * enqueued to the relevant queues in the MessagesStore. On + * commit() the messages will be passed to the queue for + * dispatch or to be added to the in-memory queue. + */ + class TxPublish : public TxOp, public Deliverable{ + class Prepare{ + TransactionContext* ctxt; + Message::shared_ptr& msg; + public: + Prepare(TransactionContext* ctxt, Message::shared_ptr& msg); + void operator()(Queue::shared_ptr& queue); + }; + + class Commit{ + Message::shared_ptr& msg; + public: + Commit(Message::shared_ptr& msg); + void operator()(Queue::shared_ptr& queue); + }; + + Message::shared_ptr msg; + std::list queues; + + public: + TxPublish(Message::shared_ptr msg); + virtual bool prepare(TransactionContext* ctxt) throw(); + virtual void commit() throw(); + virtual void rollback() throw(); + + virtual void deliverTo(Queue::shared_ptr& queue); + + virtual ~TxPublish(){} + }; + } +} + + +#endif diff --git a/qpid/cpp/src/client/AckMode.h b/qpid/cpp/src/client/AckMode.h new file mode 100644 index 0000000000..9ad5ef925c --- /dev/null +++ b/qpid/cpp/src/client/AckMode.h @@ -0,0 +1,102 @@ +#ifndef _client_AckMode_h +#define _client_AckMode_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 client { + +/** + * The available acknowledgements modes. + * + * \ingroup clientapi + */ +enum AckMode { + /** No acknowledgement will be sent, broker can + discard messages as soon as they are delivered + to a consumer using this mode. **/ + NO_ACK = 0, + /** Each message will be automatically + acknowledged as soon as it is delivered to the + application **/ + AUTO_ACK = 1, + /** Acknowledgements will be sent automatically, + but not for each message. **/ + LAZY_ACK = 2, + /** The application is responsible for explicitly + acknowledging messages. **/ + CLIENT_ACK = 3 +}; + +}} // namespace qpid::client + + + +#endif /*!_client_AckMode_h*/ +#ifndef _client_AckMode_h +#define _client_AckMode_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 client { + +/** + * The available acknowledgements modes. + * + * \ingroup clientapi + */ +enum AckMode { + /** No acknowledgement will be sent, broker can + discard messages as soon as they are delivered + to a consumer using this mode. **/ + NO_ACK = 0, + /** Each message will be automatically + acknowledged as soon as it is delivered to the + application **/ + AUTO_ACK = 1, + /** Acknowledgements will be sent automatically, + but not for each message. **/ + LAZY_ACK = 2, + /** The application is responsible for explicitly + acknowledging messages. **/ + CLIENT_ACK = 3 +}; + +}} // namespace qpid::client + + + +#endif /*!_client_AckMode_h*/ diff --git a/qpid/cpp/src/client/BasicMessageChannel.cpp b/qpid/cpp/src/client/BasicMessageChannel.cpp new file mode 100644 index 0000000000..26c3fe543c --- /dev/null +++ b/qpid/cpp/src/client/BasicMessageChannel.cpp @@ -0,0 +1,395 @@ +/* + * + * 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 "BasicMessageChannel.h" +#include "../framing/AMQMethodBody.h" +#include "ClientChannel.h" +#include "ReturnedMessageHandler.h" +#include "MessageListener.h" +#include "../framing/FieldTable.h" +#include "Connection.h" +#include +#include +#include +#include + +namespace qpid { +namespace client { + +using namespace std; +using namespace sys; +using namespace framing; +using boost::format; + +namespace { + +// Destination name constants +const std::string BASIC_GET("__basic_get__"); +const std::string BASIC_RETURN("__basic_return__"); + +// Reference name constant +const std::string BASIC_REF("__basic_reference__"); +} + +class BasicMessageChannel::WaitableDestination : + public IncomingMessage::Destination +{ + public: + WaitableDestination() : shutdownFlag(false) {} + void message(const Message& msg) { + Mutex::ScopedLock l(monitor); + queue.push(msg); + monitor.notify(); + } + + void empty() { + Mutex::ScopedLock l(monitor); + queue.push(Empty()); + monitor.notify(); + } + + bool wait(Message& msgOut) { + Mutex::ScopedLock l(monitor); + while (queue.empty() && !shutdownFlag) + monitor.wait(); + if (shutdownFlag) + return false; + Message* msg = boost::get(&queue.front()); + bool success = msg; + if (success) + msgOut=*msg; + queue.pop(); + if (!queue.empty()) + monitor.notify(); // Wake another waiter. + return success; + } + + void shutdown() { + Mutex::ScopedLock l(monitor); + shutdownFlag = true; + monitor.notifyAll(); + } + + private: + struct Empty {}; + typedef boost::variant Item; + sys::Monitor monitor; + std::queue queue; + bool shutdownFlag; +}; + + +BasicMessageChannel::BasicMessageChannel(Channel& ch) + : channel(ch), returnsHandler(0), + destGet(new WaitableDestination()), + destDispatch(new WaitableDestination()) +{ + incoming.addDestination(BASIC_RETURN, *destDispatch); +} + +void BasicMessageChannel::consume( + Queue& queue, std::string& tag, MessageListener* listener, + AckMode ackMode, bool noLocal, bool synch, const FieldTable* fields) +{ + { + // Note we create a consumer even if tag="". In that case + // It will be renamed when we handle BasicConsumeOkBody. + // + Mutex::ScopedLock l(lock); + ConsumerMap::iterator i = consumers.find(tag); + if (i != consumers.end()) + THROW_QPID_ERROR(CLIENT_ERROR, + "Consumer already exists with tag="+tag); + Consumer& c = consumers[tag]; + c.listener = listener; + c.ackMode = ackMode; + c.lastDeliveryTag = 0; + } + + // FIXME aconway 2007-03-23: get processed in both. + + // BasicConsumeOkBody is really processed in handle(), here + // we just pick up the tag to return to the user. + // + // We can't process it here because messages for the consumer may + // already be arriving. + // + BasicConsumeOkBody::shared_ptr ok = + channel.sendAndReceiveSync( + synch, + new BasicConsumeBody( + channel.version, 0, queue.getName(), tag, noLocal, + ackMode == NO_ACK, false, !synch, + fields ? *fields : FieldTable())); + tag = ok->getConsumerTag(); +} + + +void BasicMessageChannel::cancel(const std::string& tag, bool synch) { + Consumer c; + { + Mutex::ScopedLock l(lock); + ConsumerMap::iterator i = consumers.find(tag); + if (i == consumers.end()) + return; + c = i->second; + consumers.erase(i); + } + if(c.ackMode == LAZY_ACK && c.lastDeliveryTag > 0) + channel.send(new BasicAckBody(channel.version, c.lastDeliveryTag, true)); + channel.sendAndReceiveSync( + synch, new BasicCancelBody(channel.version, tag, !synch)); +} + +void BasicMessageChannel::close(){ + ConsumerMap consumersCopy; + { + Mutex::ScopedLock l(lock); + consumersCopy = consumers; + consumers.clear(); + } + destGet->shutdown(); + destDispatch->shutdown(); + for (ConsumerMap::iterator i=consumersCopy.begin(); + i != consumersCopy.end(); ++i) + { + Consumer& c = i->second; + if ((c.ackMode == LAZY_ACK || c.ackMode == AUTO_ACK) + && c.lastDeliveryTag > 0) + { + channel.send(new BasicAckBody(channel.version, c.lastDeliveryTag, true)); + } + } +} + + +bool BasicMessageChannel::get( + Message& msg, const Queue& queue, AckMode ackMode) +{ + // Prepare for incoming response + incoming.addDestination(BASIC_GET, *destGet); + channel.send( + new BasicGetBody(channel.version, 0, queue.getName(), ackMode)); + bool got = destGet->wait(msg); + return got; +} + +void BasicMessageChannel::publish( + const Message& msg, const Exchange& exchange, + const std::string& routingKey, bool mandatory, bool immediate) +{ + const string e = exchange.getName(); + string key = routingKey; + + // Make a header for the message + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + BasicHeaderProperties::copy( + *static_cast(header->getProperties()), msg); + header->setContentSize(msg.getData().size()); + + channel.send( + new BasicPublishBody( + channel.version, 0, e, key, mandatory, immediate)); + channel.send(header); + string data = msg.getData(); + u_int64_t data_length = data.length(); + if(data_length > 0){ + //frame itself uses 8 bytes + u_int32_t frag_size = channel.connection->getMaxFrameSize() - 8; + if(data_length < frag_size){ + channel.send(new AMQContentBody(data)); + }else{ + u_int32_t offset = 0; + u_int32_t remaining = data_length - offset; + while (remaining > 0) { + u_int32_t length = remaining > frag_size ? frag_size : remaining; + string frag(data.substr(offset, length)); + channel.send(new AMQContentBody(frag)); + + offset += length; + remaining = data_length - offset; + } + } + } +} + +void BasicMessageChannel::handle(boost::shared_ptr method) { + assert(method->amqpClassId() ==BasicGetBody::CLASS_ID); + switch(method->amqpMethodId()) { + case BasicGetOkBody::METHOD_ID: { + incoming.openReference(BASIC_REF); + incoming.createMessage(BASIC_GET, BASIC_REF); + return; + } + case BasicGetEmptyBody::METHOD_ID: { + incoming.getDestination(BASIC_GET).empty(); + incoming.removeDestination(BASIC_GET); + return; + } + case BasicDeliverBody::METHOD_ID: { + BasicDeliverBody::shared_ptr deliver= + boost::shared_polymorphic_downcast(method); + incoming.openReference(BASIC_REF); + Message& msg = incoming.createMessage( + deliver->getConsumerTag(), BASIC_REF); + msg.setDestination(deliver->getConsumerTag()); + msg.setDeliveryTag(deliver->getDeliveryTag()); + msg.setRedelivered(deliver->getRedelivered()); + return; + } + case BasicReturnBody::METHOD_ID: { + incoming.openReference(BASIC_REF); + incoming.createMessage(BASIC_RETURN, BASIC_REF); + return; + } + case BasicConsumeOkBody::METHOD_ID: { + Mutex::ScopedLock l(lock); + BasicConsumeOkBody::shared_ptr consumeOk = + boost::shared_polymorphic_downcast(method); + std::string tag = consumeOk->getConsumerTag(); + ConsumerMap::iterator i = consumers.find(std::string()); + if (i != consumers.end()) { + // Need to rename the un-named consumer. + if (consumers.find(tag) == consumers.end()) { + consumers[tag] = i->second; + consumers.erase(i); + } + else // Tag already exists. + throw ChannelException(404, "Tag already exists: "+tag); + } + // FIXME aconway 2007-03-23: Integrate consumer & destination + // maps. + incoming.addDestination(tag, *destDispatch); + return; + } + } + throw Channel::UnknownMethod(); +} + +void BasicMessageChannel::handle(AMQHeaderBody::shared_ptr header) { + BasicHeaderProperties* props = + boost::polymorphic_downcast( + header->getProperties()); + IncomingMessage::Reference& ref = incoming.getReference(BASIC_REF); + assert (ref.messages.size() == 1); + ref.messages.front().BasicHeaderProperties::operator=(*props); + incoming_size = header->getContentSize(); + if (incoming_size==0) + incoming.closeReference(BASIC_REF); +} + +void BasicMessageChannel::handle(AMQContentBody::shared_ptr content){ + incoming.appendReference(BASIC_REF, content->getData()); + size_t size = incoming.getReference(BASIC_REF).data.size(); + if (size >= incoming_size) { + incoming.closeReference(BASIC_REF); + if (size > incoming_size) + throw ChannelException(502, "Content exceeded declared size"); + } +} + +void BasicMessageChannel::deliver(Consumer& consumer, Message& msg){ + //record delivery tag: + consumer.lastDeliveryTag = msg.getDeliveryTag(); + + //allow registered listener to handle the message + consumer.listener->received(msg); + + if(channel.isOpen()){ + bool multiple(false); + switch(consumer.ackMode){ + case LAZY_ACK: + multiple = true; + if(++(consumer.count) < channel.getPrefetch()) + break; + //else drop-through + case AUTO_ACK: + consumer.lastDeliveryTag = 0; + channel.send( + new BasicAckBody( + channel.version, + msg.getDeliveryTag(), + multiple)); + case NO_ACK: // Nothing to do + case CLIENT_ACK: // User code must ack. + break; + // TODO aconway 2007-02-22: Provide a way for user + // to ack! + } + } + + //as it stands, transactionality is entirely orthogonal to ack + //mode, though the acks will not be processed by the broker under + //a transaction until it commits. +} + + +void BasicMessageChannel::run() { + while(channel.isOpen()) { + try { + Message msg; + bool gotMessge = destDispatch->wait(msg); + if (gotMessge) { + if(msg.getDestination() == BASIC_RETURN) { + ReturnedMessageHandler* handler=0; + { + Mutex::ScopedLock l(lock); + handler=returnsHandler; + } + if(handler != 0) + handler->returned(msg); + } + else { + Consumer consumer; + { + Mutex::ScopedLock l(lock); + ConsumerMap::iterator i = consumers.find( + msg.getDestination()); + if(i == consumers.end()) + THROW_QPID_ERROR(PROTOCOL_ERROR+504, + "Unknown consumer tag=" + + msg.getDestination()); + consumer = i->second; + } + deliver(consumer, msg); + } + } + } + catch (const ShutdownException&) { + /* Orderly shutdown */ + } + catch (const Exception& e) { + // FIXME aconway 2007-02-20: Report exception to user. + cout << "client::BasicMessageChannel::run() terminated by: " + << e.toString() << endl; + } + } +} + +void BasicMessageChannel::setReturnedMessageHandler(ReturnedMessageHandler* handler){ + Mutex::ScopedLock l(lock); + returnsHandler = handler; +} + +void BasicMessageChannel::setQos(){ + channel.sendAndReceive( + new BasicQosBody(channel.version, 0, channel.getPrefetch(), false)); + if(channel.isTransactional()) + channel.sendAndReceive(new TxSelectBody(channel.version)); +} + +}} // namespace qpid::client diff --git a/qpid/cpp/src/client/BasicMessageChannel.h b/qpid/cpp/src/client/BasicMessageChannel.h new file mode 100644 index 0000000000..aaedfd6bf1 --- /dev/null +++ b/qpid/cpp/src/client/BasicMessageChannel.h @@ -0,0 +1,91 @@ +#ifndef _client_BasicMessageChannel_h +#define _client_BasicMessageChannel_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 "MessageChannel.h" +#include "IncomingMessage.h" +#include + +namespace qpid { +namespace client { +/** + * Messaging implementation using AMQP 0-8 BasicMessageChannel class + * to send and receiving messages. + */ +class BasicMessageChannel : public MessageChannel +{ + public: + BasicMessageChannel(Channel& parent); + + void consume( + Queue& queue, std::string& tag, MessageListener* listener, + AckMode ackMode = NO_ACK, bool noLocal = false, bool synch = true, + const framing::FieldTable* fields = 0); + + void cancel(const std::string& tag, bool synch = true); + + bool get(Message& msg, const Queue& queue, AckMode ackMode = NO_ACK); + + void publish(const Message& msg, const Exchange& exchange, + const std::string& routingKey, + bool mandatory = false, bool immediate = false); + + void setReturnedMessageHandler(ReturnedMessageHandler* handler); + + void run(); + + void handle(boost::shared_ptr); + + void handle(shared_ptr); + + void handle(shared_ptr); + + void setQos(); + + void close(); + + private: + + class WaitableDestination; + struct Consumer{ + MessageListener* listener; + AckMode ackMode; + int count; + u_int64_t lastDeliveryTag; + }; + typedef std::map ConsumerMap; + + void deliver(Consumer& consumer, Message& msg); + + sys::Mutex lock; + Channel& channel; + IncomingMessage incoming; + uint64_t incoming_size; + ConsumerMap consumers ; + ReturnedMessageHandler* returnsHandler; + boost::scoped_ptr destGet; + boost::scoped_ptr destDispatch; +}; + +}} // namespace qpid::client + + + +#endif /*!_client_BasicMessageChannel_h*/ diff --git a/qpid/cpp/src/client/ClientAdapter.cpp b/qpid/cpp/src/client/ClientAdapter.cpp new file mode 100644 index 0000000000..4bf91f915b --- /dev/null +++ b/qpid/cpp/src/client/ClientAdapter.cpp @@ -0,0 +1,70 @@ +/* + * + * 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 "AMQP_ClientOperations.h" +#include "ClientAdapter.h" +#include "Connection.h" +#include "../Exception.h" +#include "../framing/AMQMethodBody.h" + +namespace qpid { +namespace client { + +using namespace qpid; +using namespace qpid::framing; + +typedef std::vector::iterator queue_iterator; + +void ClientAdapter::handleMethodInContext( + boost::shared_ptr method, + const MethodContext& context +) +{ + try{ + method->invoke(*clientOps, context); + }catch(ChannelException& e){ + connection.client->getChannel().close( + context, e.code, e.toString(), + method->amqpClassId(), method->amqpMethodId()); + connection.closeChannel(getId()); + }catch(ConnectionException& e){ + connection.client->getConnection().close( + context, e.code, e.toString(), + method->amqpClassId(), method->amqpMethodId()); + }catch(std::exception& e){ + connection.client->getConnection().close( + context, 541/*internal error*/, e.what(), + method->amqpClassId(), method->amqpMethodId()); + } +} + +void ClientAdapter::handleHeader(AMQHeaderBody::shared_ptr body) { + channel->handleHeader(body); +} + +void ClientAdapter::handleContent(AMQContentBody::shared_ptr body) { + channel->handleContent(body); +} + +void ClientAdapter::handleHeartbeat(AMQHeartbeatBody::shared_ptr) { + // TODO aconway 2007-01-17: Implement heartbeats. +} + + + +}} // namespace qpid::client + diff --git a/qpid/cpp/src/client/ClientAdapter.h b/qpid/cpp/src/client/ClientAdapter.h new file mode 100644 index 0000000000..ca029a793f --- /dev/null +++ b/qpid/cpp/src/client/ClientAdapter.h @@ -0,0 +1,66 @@ +#ifndef _client_ClientAdapter_h +#define _client_ClientAdapter_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 "../framing/ChannelAdapter.h" +#include "ClientChannel.h" + +namespace qpid { +namespace client { + +class AMQMethodBody; +class Connection; + +/** + * Per-channel protocol adapter. + * + * Translates protocol bodies into calls on the core Channel, + * Connection and Client objects. + * + * Owns a channel, has references to Connection and Client. + */ +class ClientAdapter : public framing::ChannelAdapter +{ + public: + ClientAdapter(std::auto_ptr ch, Connection&, Client&); + Channel& getChannel() { return *channel; } + + void handleHeader(boost::shared_ptr); + void handleContent(boost::shared_ptr); + void handleHeartbeat(boost::shared_ptr); + + private: + void handleMethodInContext( + boost::shared_ptr method, + const framing::MethodContext& context); + + class ClientOps; + + std::auto_ptr channel; + Connection& connection; + Client& client; + boost::shared_ptr clientOps; +}; + +}} // namespace qpid::client + + + +#endif /*!_client_ClientAdapter_h*/ diff --git a/qpid/cpp/src/client/ClientChannel.cpp b/qpid/cpp/src/client/ClientChannel.cpp new file mode 100644 index 0000000000..eda872fc30 --- /dev/null +++ b/qpid/cpp/src/client/ClientChannel.cpp @@ -0,0 +1,340 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include +#include "ClientChannel.h" +#include "../sys/Monitor.h" +#include "ClientMessage.h" +#include "../QpidError.h" +#include "MethodBodyInstances.h" +#include "Connection.h" +#include "BasicMessageChannel.h" +// FIXME aconway 2007-03-21: +//#include "MessageMessageChannel.h" + +// FIXME aconway 2007-01-26: Evaluate all throws, ensure consistent +// handling of errors that should close the connection or the channel. +// Make sure the user thread receives a connection in each case. +// +using namespace std; +using namespace boost; +using namespace qpid::client; +using namespace qpid::framing; +using namespace qpid::sys; + +Channel::Channel(bool _transactional, u_int16_t _prefetch, + MessageChannel* impl) : + // FIXME aconway 2007-03-21: MessageMessageChannel + messaging(impl ? impl : new BasicMessageChannel(*this)), + connection(0), + prefetch(_prefetch), + transactional(_transactional) +{ } + +Channel::~Channel(){ + close(); +} + +void Channel::open(ChannelId id, Connection& con) +{ + if (isOpen()) + THROW_QPID_ERROR(INTERNAL_ERROR, "Attempt to re-open channel "+id); + connection = &con; + init(id, con, con.getVersion()); // ChannelAdapter initialization. + string oob; + if (id != 0) + sendAndReceive(new ChannelOpenBody(version, oob)); +} + +void Channel::protocolInit( + const std::string& uid, const std::string& pwd, const std::string& vhost) { + assert(connection); + responses.expect(); + connection->connector->init(); // Send ProtocolInit block. + ConnectionStartBody::shared_ptr connectionStart = + responses.receive(); + + FieldTable props; + string mechanism("PLAIN"); + string response = ((char)0) + uid + ((char)0) + pwd; + string locale("en_US"); + ConnectionTuneBody::shared_ptr proposal = + sendAndReceive( + new ConnectionStartOkBody( + version, connectionStart->getRequestId(), + props, mechanism, + response, locale)); + + /** + * Assume for now that further challenges will not be required + //receive connection.secure + responses.receive(connection_secure)); + //send connection.secure-ok + connection->send(new AMQFrame(0, new ConnectionSecureOkBody(response))); + **/ + + send(new ConnectionTuneOkBody( + version, proposal->getRequestId(), + proposal->getChannelMax(), connection->getMaxFrameSize(), + proposal->getHeartbeat())); + + uint16_t heartbeat = proposal->getHeartbeat(); + connection->connector->setReadTimeout(heartbeat * 2); + connection->connector->setWriteTimeout(heartbeat); + + // Send connection open. + std::string capabilities; + responses.expect(); + send(new ConnectionOpenBody(version, vhost, capabilities, true)); + //receive connection.open-ok (or redirect, but ignore that for now + //esp. as using force=true). + AMQMethodBody::shared_ptr openResponse = responses.receive(); + if(openResponse->isA()) { + //ok + }else if(openResponse->isA()){ + //ignore for now + ConnectionRedirectBody::shared_ptr redirect( + shared_polymorphic_downcast(openResponse)); + cout << "Received redirection to " << redirect->getHost() + << endl; + } else { + THROW_QPID_ERROR(PROTOCOL_ERROR, "Bad response to Connection.open"); + } +} + +bool Channel::isOpen() const { return connection; } + +void Channel::setQos() { + messaging->setQos(); +} + +void Channel::setPrefetch(uint16_t _prefetch){ + prefetch = _prefetch; + setQos(); +} + +void Channel::declareExchange(Exchange& exchange, bool synch){ + string name = exchange.getName(); + string type = exchange.getType(); + FieldTable args; + sendAndReceiveSync( + synch, + new ExchangeDeclareBody( + version, 0, name, type, false, false, false, false, !synch, args)); +} + +void Channel::deleteExchange(Exchange& exchange, bool synch){ + string name = exchange.getName(); + sendAndReceiveSync( + synch, + new ExchangeDeleteBody(version, 0, name, false, !synch)); +} + +void Channel::declareQueue(Queue& queue, bool synch){ + string name = queue.getName(); + FieldTable args; + QueueDeclareOkBody::shared_ptr response = + sendAndReceiveSync( + synch, + new QueueDeclareBody( + version, 0, name, false/*passive*/, queue.isDurable(), + queue.isExclusive(), queue.isAutoDelete(), !synch, args)); + if(synch) { + if(queue.getName().length() == 0) + queue.setName(response->getQueue()); + } +} + +void Channel::deleteQueue(Queue& queue, bool ifunused, bool ifempty, bool synch){ + //ticket, queue, ifunused, ifempty, nowait + string name = queue.getName(); + sendAndReceiveSync( + synch, + new QueueDeleteBody(version, 0, name, ifunused, ifempty, !synch)); +} + +void Channel::bind(const Exchange& exchange, const Queue& queue, const std::string& key, const FieldTable& args, bool synch){ + string e = exchange.getName(); + string q = queue.getName(); + sendAndReceiveSync( + synch, + new QueueBindBody(version, 0, q, e, key,!synch, args)); +} + +void Channel::commit(){ + sendAndReceive(new TxCommitBody(version)); +} + +void Channel::rollback(){ + sendAndReceive(new TxRollbackBody(version)); +} + +void Channel::handleMethodInContext( + AMQMethodBody::shared_ptr method, const MethodContext&) +{ + // TODO aconway 2007-03-23: Special case for consume OK as it + // is both an expected response and needs handling in this thread. + // Need to review & reationalize the client-side processing model. + if (method->isA()) { + messaging->handle(method); + responses.signalResponse(method); + return; + } + if(responses.isWaiting()) { + responses.signalResponse(method); + return; + } + try { + switch (method->amqpClassId()) { + case BasicDeliverBody::CLASS_ID: messaging->handle(method); break; + case ChannelCloseBody::CLASS_ID: handleChannel(method); break; + case ConnectionCloseBody::CLASS_ID: handleConnection(method); break; + default: throw UnknownMethod(); + } + } + catch (const UnknownMethod&) { + connection->close( + 504, "Unknown method", + method->amqpClassId(), method->amqpMethodId()); + } + } + +void Channel::handleChannel(AMQMethodBody::shared_ptr method) { + switch (method->amqpMethodId()) { + case ChannelCloseBody::METHOD_ID: + peerClose(shared_polymorphic_downcast(method)); + return; + case ChannelFlowBody::METHOD_ID: + // FIXME aconway 2007-02-22: Not yet implemented. + return; + } + throw UnknownMethod(); +} + +void Channel::handleConnection(AMQMethodBody::shared_ptr method) { + if (method->amqpMethodId() == ConnectionCloseBody::METHOD_ID) { + connection->close(); + return; + } + throw UnknownMethod(); +} + +void Channel::handleHeader(AMQHeaderBody::shared_ptr body){ + messaging->handle(body); +} + +void Channel::handleContent(AMQContentBody::shared_ptr body){ + messaging->handle(body); +} + +void Channel::handleHeartbeat(AMQHeartbeatBody::shared_ptr /*body*/){ + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Channel received heartbeat"); +} + +void Channel::start(){ + dispatcher = Thread(*messaging); +} + +// Close called by local application. +void Channel::close( + uint16_t code, const std::string& text, + ClassId classId, MethodId methodId) +{ + if (isOpen()) { + try { + if (getId() != 0) { + sendAndReceive( + new ChannelCloseBody( + version, code, text, classId, methodId)); + } + static_cast(connection)->erase(getId()); + closeInternal(); + } catch (...) { + static_cast(connection)->erase(getId()); + closeInternal(); + throw; + } + } +} + +// Channel closed by peer. +void Channel::peerClose(ChannelCloseBody::shared_ptr) { + assert(isOpen()); + closeInternal(); +} + +void Channel::closeInternal() { + if (isOpen()); + { + messaging->close(); + connection = 0; + // A 0 response means we are closed. + responses.signalResponse(AMQMethodBody::shared_ptr()); + } + dispatcher.join(); +} + +AMQMethodBody::shared_ptr Channel::sendAndReceive( + AMQMethodBody* toSend, ClassId c, MethodId m) +{ + responses.expect(); + send(toSend); + return responses.receive(c, m); +} + +AMQMethodBody::shared_ptr Channel::sendAndReceiveSync( + bool sync, AMQMethodBody* body, ClassId c, MethodId m) +{ + if(sync) + return sendAndReceive(body, c, m); + else { + send(body); + return AMQMethodBody::shared_ptr(); + } +} + +void Channel::consume( + Queue& queue, std::string& tag, MessageListener* listener, + AckMode ackMode, bool noLocal, bool synch, const FieldTable* fields) { + messaging->consume(queue, tag, listener, ackMode, noLocal, synch, fields); +} + +void Channel::cancel(const std::string& tag, bool synch) { + messaging->cancel(tag, synch); +} + +bool Channel::get(Message& msg, const Queue& queue, AckMode ackMode) { + return messaging->get(msg, queue, ackMode); +} + +void Channel::publish(const Message& msg, const Exchange& exchange, + const std::string& routingKey, + bool mandatory, bool immediate) { + messaging->publish(msg, exchange, routingKey, mandatory, immediate); +} + +void Channel::setReturnedMessageHandler(ReturnedMessageHandler* handler) { + messaging->setReturnedMessageHandler(handler); +} + +void Channel::run() { + messaging->run(); +} + diff --git a/qpid/cpp/src/client/ClientChannel.h b/qpid/cpp/src/client/ClientChannel.h new file mode 100644 index 0000000000..a7e0d2ec31 --- /dev/null +++ b/qpid/cpp/src/client/ClientChannel.h @@ -0,0 +1,352 @@ +#ifndef _client_ClientChannel_h +#define _client_ClientChannel_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../framing/amqp_framing.h" +#include "ClientExchange.h" +#include "ClientMessage.h" +#include "ClientQueue.h" +#include "ResponseHandler.h" +#include "../framing/ChannelAdapter.h" +#include "../sys/Thread.h" +#include "AckMode.h" + +namespace qpid { + +namespace framing { +class ChannelCloseBody; +class AMQMethodBody; +} + +namespace client { + +class Connection; +class MessageChannel; +class MessageListener; +class ReturnedMessageHandler; + +/** + * Represents an AMQP channel, i.e. loosely a session of work. It + * is through a channel that most of the AMQP 'methods' are + * exposed. + * + * \ingroup clientapi + */ +class Channel : public framing::ChannelAdapter +{ + private: + struct UnknownMethod {}; + + sys::Mutex lock; + boost::scoped_ptr messaging; + Connection* connection; + sys::Thread dispatcher; + ResponseHandler responses; + + uint16_t prefetch; + const bool transactional; + framing::ProtocolVersion version; + + void handleHeader(framing::AMQHeaderBody::shared_ptr body); + void handleContent(framing::AMQContentBody::shared_ptr body); + void handleHeartbeat(framing::AMQHeartbeatBody::shared_ptr body); + void handleMethodInContext( + framing::AMQMethodBody::shared_ptr, const framing::MethodContext&); + void handleChannel(framing::AMQMethodBody::shared_ptr method); + void handleConnection(framing::AMQMethodBody::shared_ptr method); + + void setQos(); + + void protocolInit( + const std::string& uid, const std::string& pwd, + const std::string& vhost); + + framing::AMQMethodBody::shared_ptr sendAndReceive( + framing::AMQMethodBody*, framing::ClassId, framing::MethodId); + + framing::AMQMethodBody::shared_ptr sendAndReceiveSync( + bool sync, + framing::AMQMethodBody*, framing::ClassId, framing::MethodId); + + template + boost::shared_ptr sendAndReceive(framing::AMQMethodBody* body) { + return boost::shared_polymorphic_downcast( + sendAndReceive(body, BodyType::CLASS_ID, BodyType::METHOD_ID)); + } + + template + boost::shared_ptr sendAndReceiveSync( + bool sync, framing::AMQMethodBody* body) { + return boost::shared_polymorphic_downcast( + sendAndReceiveSync( + sync, body, BodyType::CLASS_ID, BodyType::METHOD_ID)); + } + + void open(framing::ChannelId, Connection&); + void closeInternal(); + void peerClose(boost::shared_ptr); + + // FIXME aconway 2007-02-23: Get rid of friendships. + friend class Connection; + friend class BasicMessageChannel; // for sendAndReceive. + friend class MessageMessageChannel; // for sendAndReceive. + + public: + + /** + * Creates a channel object. + * + * @param transactional if true, the publishing and acknowledgement + * of messages will be transactional and can be committed or + * aborted in atomic units (@see commit(), @see rollback()) + * + * @param prefetch specifies the number of unacknowledged + * messages the channel is willing to have sent to it + * asynchronously + * + * @param messageImpl Alternate messaging implementation class to + * allow alternate protocol implementations of messaging + * operations. Takes ownership. + */ + Channel( + bool transactional = false, u_int16_t prefetch = 500, + MessageChannel* messageImpl = 0); + + ~Channel(); + + /** + * Declares an exchange. + * + * In AMQP Exchanges are the destinations to which messages + * are published. They have Queues bound to them and route + * messages they receive to those queues. The routing rules + * depend on the type of the exchange. + * + * @param exchange an Exchange object representing the + * exchange to declare + * + * @param synch if true this call will block until a response + * is received from the broker + */ + void declareExchange(Exchange& exchange, bool synch = true); + /** + * Deletes an exchange + * + * @param exchange an Exchange object representing the exchange to delete + * + * @param synch if true this call will block until a response + * is received from the broker + */ + void deleteExchange(Exchange& exchange, bool synch = true); + /** + * Declares a Queue + * + * @param queue a Queue object representing the queue to declare + * + * @param synch if true this call will block until a response + * is received from the broker + */ + void declareQueue(Queue& queue, bool synch = true); + /** + * Deletes a Queue + * + * @param queue a Queue object representing the queue to delete + * + * @param synch if true this call will block until a response + * is received from the broker + */ + void deleteQueue(Queue& queue, bool ifunused = false, bool ifempty = false, bool synch = true); + /** + * Binds a queue to an exchange. The exact semantics of this + * (in particular how 'routing keys' and 'binding arguments' + * are used) depends on the type of the exchange. + * + * @param exchange an Exchange object representing the + * exchange to bind to + * + * @param queue a Queue object representing the queue to be + * bound + * + * @param key the 'routing key' for the binding + * + * @param args the 'binding arguments' for the binding + * + * @param synch if true this call will block until a response + * is received from the broker + */ + void bind(const Exchange& exchange, const Queue& queue, + const std::string& key, const framing::FieldTable& args, + bool synch = true); + + /** + * For a transactional channel this will commit all + * publications and acknowledgements since the last commit (or + * the channel was opened if there has been no previous + * commit). This will cause published messages to become + * available to consumers and acknowledged messages to be + * consumed and removed from the queues they were dispatched + * from. + * + * Transactionailty of a channel is specified when the channel + * object is created (@see Channel()). + */ + void commit(); + + /** + * For a transactional channel, this will rollback any + * publications or acknowledgements. It will be as if the + * ppblished messages were never sent and the acknowledged + * messages were never consumed. + */ + void rollback(); + + /** + * Change the prefetch in use. + */ + void setPrefetch(uint16_t prefetch); + + uint16_t getPrefetch() { return prefetch; } + + /** + * Start message dispatching on a new thread + */ + void start(); + + /** + * Close the channel with optional error information. + * Closing a channel that is not open has no effect. + */ + void close( + framing::ReplyCode = 200, const std::string& ="OK", + framing::ClassId = 0, framing::MethodId = 0); + + /** True if the channel is transactional */ + bool isTransactional() { return transactional; } + + /** True if the channel is open */ + bool isOpen() const; + + /** Get the connection associated with this channel */ + Connection& getConnection() { return *connection; } + + /** Return the protocol version */ + framing::ProtocolVersion getVersion() const { return version ; } + + /** + * Creates a 'consumer' for a queue. Messages in (or arriving + * at) that queue will be delivered to consumers + * asynchronously. + * + * @param queue a Queue instance representing the queue to + * consume from + * + * @param tag an identifier to associate with the consumer + * that can be used to cancel its subscription (if empty, this + * will be assigned by the broker) + * + * @param listener a pointer to an instance of an + * implementation of the MessageListener interface. Messages + * received from this queue for this consumer will result in + * invocation of the received() method on the listener, with + * the message itself passed in. + * + * @param ackMode the mode of acknowledgement that the broker + * should assume for this consumer. @see AckMode + * + * @param noLocal if true, this consumer will not be sent any + * message published by this connection + * + * @param synch if true this call will block until a response + * is received from the broker + */ + void consume( + Queue& queue, std::string& tag, MessageListener* listener, + AckMode ackMode = NO_ACK, bool noLocal = false, bool synch = true, + const framing::FieldTable* fields = 0); + + /** + * Cancels a subscription previously set up through a call to consume(). + * + * @param tag the identifier used (or assigned) in the consume + * request that set up the subscription to be cancelled. + * + * @param synch if true this call will block until a response + * is received from the broker + */ + void cancel(const std::string& tag, bool synch = true); + /** + * Synchronous pull of a message from a queue. + * + * @param msg a message object that will contain the message + * headers and content if the call completes. + * + * @param queue the queue to consume from + * + * @param ackMode the acknowledgement mode to use (@see + * AckMode) + * + * @return true if a message was succcessfully dequeued from + * the queue, false if the queue was empty. + */ + bool get(Message& msg, const Queue& queue, AckMode ackMode = NO_ACK); + + /** + * Publishes (i.e. sends a message to the broker). + * + * @param msg the message to publish + * + * @param exchange the exchange to publish the message to + * + * @param routingKey the routing key to publish with + * + * @param mandatory if true and the exchange to which this + * publish is directed has no matching bindings, the message + * will be returned (see setReturnedMessageHandler()). + * + * @param immediate if true and there is no consumer to + * receive this message on publication, the message will be + * returned (see setReturnedMessageHandler()). + */ + void publish(const Message& msg, const Exchange& exchange, + const std::string& routingKey, + bool mandatory = false, bool immediate = false); + + /** + * Set a handler for this channel that will process any + * returned messages + * + * @see publish() + */ + void setReturnedMessageHandler(ReturnedMessageHandler* handler); + + /** + * Deliver messages from the broker to the appropriate MessageListener. + */ + void run(); + + +}; + +}} + +#endif /*!_client_ClientChannel_h*/ diff --git a/qpid/cpp/src/client/ClientExchange.cpp b/qpid/cpp/src/client/ClientExchange.cpp new file mode 100644 index 0000000000..d5914beea2 --- /dev/null +++ b/qpid/cpp/src/client/ClientExchange.cpp @@ -0,0 +1,34 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "ClientExchange.h" + +qpid::client::Exchange::Exchange(std::string _name, std::string _type) : name(_name), type(_type){} +const std::string& qpid::client::Exchange::getName() const { return name; } +const std::string& qpid::client::Exchange::getType() const { return type; } + +const std::string qpid::client::Exchange::DIRECT_EXCHANGE = "direct"; +const std::string qpid::client::Exchange::TOPIC_EXCHANGE = "topic"; +const std::string qpid::client::Exchange::HEADERS_EXCHANGE = "headers"; + +const qpid::client::Exchange qpid::client::Exchange::DEFAULT_EXCHANGE("", DIRECT_EXCHANGE); +const qpid::client::Exchange qpid::client::Exchange::STANDARD_DIRECT_EXCHANGE("amq.direct", DIRECT_EXCHANGE); +const qpid::client::Exchange qpid::client::Exchange::STANDARD_TOPIC_EXCHANGE("amq.topic", TOPIC_EXCHANGE); +const qpid::client::Exchange qpid::client::Exchange::STANDARD_HEADERS_EXCHANGE("amq.headers", HEADERS_EXCHANGE); diff --git a/qpid/cpp/src/client/ClientExchange.h b/qpid/cpp/src/client/ClientExchange.h new file mode 100644 index 0000000000..a8ac21fa9b --- /dev/null +++ b/qpid/cpp/src/client/ClientExchange.h @@ -0,0 +1,106 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include + +#ifndef _Exchange_ +#define _Exchange_ + +namespace qpid { +namespace client { + + /** + * A 'handle' used to represent an AMQP exchange in the Channel + * methods. Exchanges are the destinations to which messages are + * published. + * + * There are different types of exchange (the standard types are + * available as static constants, see DIRECT_EXCHANGE, + * TOPIC_EXCHANGE and HEADERS_EXCHANGE). A Queue can be bound to + * an exchange using Channel::bind() and messages published to + * that exchange are then routed to the queue based on the details + * of the binding and the type of exchange. + * + * There are some standard exchange instances that are predeclared + * on all AMQP brokers. These are defined as static members + * STANDARD_DIRECT_EXCHANGE, STANDARD_TOPIC_EXCHANGE and + * STANDARD_HEADERS_EXCHANGE. There is also the 'default' exchange + * (member DEFAULT_EXCHANGE) which is nameless and of type + * 'direct' and has every declared queue bound to it by queue + * name. + * + * \ingroup clientapi + */ + class Exchange{ + const std::string name; + const std::string type; + + public: + /** + * A direct exchange routes messages published with routing + * key X to any queue bound with key X (i.e. an exact match is + * used). + */ + static const std::string DIRECT_EXCHANGE; + /** + * A topic exchange treat the key with which a queue is bound + * as a pattern and routes all messages whose routing keys + * match that pattern to the bound queue. The routing key for + * a message must consist of zero or more alpha-numeric words + * delimited by dots. The pattern is of a similar form but * + * can be used to match excatly one word and # can be used to + * match zero or more words. + */ + static const std::string TOPIC_EXCHANGE; + /** + * The headers exchange routes messages based on whether their + * headers match the binding arguments specified when + * binding. (see the AMQP spec for more details). + */ + static const std::string HEADERS_EXCHANGE; + + /** + * The 'default' exchange, nameless and of type 'direct'. Has + * every declared queue bound to it by name. + */ + static const Exchange DEFAULT_EXCHANGE; + /** + * The standard direct exchange, named amq.direct. + */ + static const Exchange STANDARD_DIRECT_EXCHANGE; + /** + * The standard topic exchange, named amq.topic. + */ + static const Exchange STANDARD_TOPIC_EXCHANGE; + /** + * The standard headers exchange, named amq.header. + */ + static const Exchange STANDARD_HEADERS_EXCHANGE; + + Exchange(std::string name, std::string type = DIRECT_EXCHANGE); + const std::string& getName() const; + const std::string& getType() const; + }; + +} +} + + +#endif diff --git a/qpid/cpp/src/client/ClientMessage.h b/qpid/cpp/src/client/ClientMessage.h new file mode 100644 index 0000000000..dc25b4070b --- /dev/null +++ b/qpid/cpp/src/client/ClientMessage.h @@ -0,0 +1,62 @@ +#ifndef _client_ClientMessage_h +#define _client_ClientMessage_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../framing/BasicHeaderProperties.h" + +namespace qpid { +namespace client { + +/** + * A representation of messages for sent or recived through the + * client api. + * + * \ingroup clientapi + */ +class Message : public framing::BasicHeaderProperties { + public: + Message(const std::string& data_=std::string()) : data(data_) {} + + std::string getData() const { return data; } + void setData(const std::string& _data) { data = _data; } + + std::string getDestination() const { return destination; } + void setDestination(const std::string& dest) { destination = dest; } + + // TODO aconway 2007-03-22: only needed for Basic.deliver support. + uint64_t getDeliveryTag() const { return deliveryTag; } + void setDeliveryTag(uint64_t dt) { deliveryTag = dt; } + + bool isRedelivered() const { return redelivered; } + void setRedelivered(bool _redelivered){ redelivered = _redelivered; } + + private: + std::string data; + std::string destination; + bool redelivered; + uint64_t deliveryTag; +}; + +}} + +#endif /*!_client_ClientMessage_h*/ diff --git a/qpid/cpp/src/client/ClientQueue.cpp b/qpid/cpp/src/client/ClientQueue.cpp new file mode 100644 index 0000000000..613cf8d288 --- /dev/null +++ b/qpid/cpp/src/client/ClientQueue.cpp @@ -0,0 +1,58 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "ClientQueue.h" + +qpid::client::Queue::Queue() : name(""), autodelete(true), exclusive(true), durable(false){} + +qpid::client::Queue::Queue(std::string _name) : name(_name), autodelete(false), exclusive(false), durable(false){} + +qpid::client::Queue::Queue(std::string _name, bool temp) : name(_name), autodelete(temp), exclusive(temp), durable(false){} + +qpid::client::Queue::Queue(std::string _name, bool _autodelete, bool _exclusive, bool _durable) + : name(_name), autodelete(_autodelete), exclusive(_exclusive), durable(_durable){} + +const std::string& qpid::client::Queue::getName() const{ + return name; +} + +void qpid::client::Queue::setName(const std::string& _name){ + name = _name; +} + +bool qpid::client::Queue::isAutoDelete() const{ + return autodelete; +} + +bool qpid::client::Queue::isExclusive() const{ + return exclusive; +} + +bool qpid::client::Queue::isDurable() const{ + return durable; +} + +void qpid::client::Queue::setDurable(bool _durable){ + durable = _durable; +} + + + + diff --git a/qpid/cpp/src/client/ClientQueue.h b/qpid/cpp/src/client/ClientQueue.h new file mode 100644 index 0000000000..b37a44b004 --- /dev/null +++ b/qpid/cpp/src/client/ClientQueue.h @@ -0,0 +1,103 @@ +#ifndef _client_ClientQueue_h +#define _client_ClientQueue_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 { + + /** + * A 'handle' used to represent an AMQP queue in the Channel + * methods. Creating an instance of this class does not cause the + * queue to be created on the broker. Rather, an instance of this + * class should be passed to Channel::declareQueue() to ensure + * that the queue exists or is created. + * + * Queues hold messages and allow clients to consume + * (see Channel::consume()) or get (see Channel::get()) those messags. A + * queue receives messages by being bound to one or more Exchange; + * messages published to that exchange may then be routed to the + * queue based on the details of the binding and the type of the + * exchange (see Channel::bind()). + * + * Queues are identified by a name. They can be exclusive (in which + * case they can only be used in the context of the connection + * over which they were declared, and are deleted when then + * connection closes), or they can be shared. Shared queues can be + * auto deleted when they have no consumers. + * + * We use the term 'temporary queue' to refer to an exclusive + * queue. + * + * \ingroup clientapi + */ + class Queue{ + std::string name; + const bool autodelete; + const bool exclusive; + bool durable; + + public: + + /** + * Creates an unnamed, non-durable, temporary queue. A name + * will be assigned to this queue instance by a call to + * Channel::declareQueue(). + */ + Queue(); + /** + * Creates a shared, non-durable, queue with a given name, + * that will not be autodeleted. + * + * @param name the name of the queue + */ + Queue(std::string name); + /** + * Creates a non-durable queue with a given name. + * + * @param name the name of the queue + * + * @param temp if true the queue will be a temporary queue, if + * false it will be shared and not autodeleted. + */ + Queue(std::string name, bool temp); + /** + * This constructor allows the autodelete, exclusive and + * durable propeties to be explictly set. Note however that if + * exclusive is true, autodelete has no meaning as exclusive + * queues are always destroyed when the connection that + * created them is closed. + */ + Queue(std::string name, bool autodelete, bool exclusive, bool durable); + const std::string& getName() const; + void setName(const std::string&); + bool isAutoDelete() const; + bool isExclusive() const; + bool isDurable() const; + void setDurable(bool durable); + }; + +} +} + +#endif /*!_client_ClientQueue_h*/ diff --git a/qpid/cpp/src/client/Connection.cpp b/qpid/cpp/src/client/Connection.cpp new file mode 100644 index 0000000000..365311ab37 --- /dev/null +++ b/qpid/cpp/src/client/Connection.cpp @@ -0,0 +1,156 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "Connection.h" +#include "ClientChannel.h" +#include "ClientMessage.h" +#include "../QpidError.h" +#include +#include +#include "MethodBodyInstances.h" +#include + +using namespace qpid::framing; +using namespace qpid::sys; + + +namespace qpid { +namespace client { + +const std::string Connection::OK("OK"); + +Connection::Connection( + bool _debug, uint32_t _max_frame_size, + framing::ProtocolVersion _version +) : channelIdCounter(0), version(_version), max_frame_size(_max_frame_size), + defaultConnector(version, _debug, _max_frame_size), + isOpen(false), debug(_debug) +{ + setConnector(defaultConnector); +} + +Connection::~Connection(){} + +void Connection::setConnector(Connector& con) +{ + connector = &con; + connector->setInputHandler(this); + connector->setTimeoutHandler(this); + connector->setShutdownHandler(this); + out = connector->getOutputHandler(); +} + +void Connection::open( + const std::string& host, int port, + const std::string& uid, const std::string& pwd, const std::string& vhost) +{ + if (isOpen) + THROW_QPID_ERROR(INTERNAL_ERROR, "Channel object is already open"); + connector->connect(host, port); + channels[0] = &channel0; + channel0.open(0, *this); + channel0.protocolInit(uid, pwd, vhost); + isOpen = true; +} + +void Connection::shutdown() { + close(); +} + +void Connection::close( + ReplyCode code, const string& msg, ClassId classId, MethodId methodId +) +{ + if(isOpen) { + // TODO aconway 2007-01-29: Exception handling - could end up + // partly closed with threads left unjoined. + isOpen = false; + channel0.sendAndReceive( + new ConnectionCloseBody( + getVersion(), code, msg, classId, methodId)); + + using boost::bind; + for_each(channels.begin(), channels.end(), + bind(&Channel::closeInternal, + bind(&ChannelMap::value_type::second, _1))); + channels.clear(); + connector->close(); + } +} + +void Connection::openChannel(Channel& channel) { + ChannelId id = ++channelIdCounter; + assert (channels.find(id) == channels.end()); + assert(out); + channels[id] = &channel; + channel.open(id, *this); +} + +void Connection::erase(ChannelId id) { + channels.erase(id); +} + +void Connection::received(AMQFrame* frame){ + // FIXME aconway 2007-01-25: Mutex + ChannelId id = frame->getChannel(); + Channel* channel = channels[id]; + // FIXME aconway 2007-01-26: Exception thrown here is hanging the + // client. Need to review use of exceptions. + if (channel == 0) + THROW_QPID_ERROR( + PROTOCOL_ERROR+504, + (boost::format("Invalid channel number %g") % id).str()); + try{ + channel->handleBody(frame->getBody()); + }catch(const qpid::QpidError& e){ + channelException( + *channel, dynamic_cast(frame->getBody().get()), e); + } +} + +void Connection::send(AMQFrame* frame) { + out->send(frame); +} + +void Connection::channelException( + Channel& channel, AMQMethodBody* method, const QpidError& e) +{ + int code = (e.code >= PROTOCOL_ERROR) ? e.code - PROTOCOL_ERROR : 500; + string msg = e.msg; + if(method == 0) + channel.close(code, msg); + else + channel.close( + code, msg, method->amqpClassId(), method->amqpMethodId()); +} + +void Connection::idleIn(){ + connector->close(); +} + +void Connection::idleOut(){ + out->send(new AMQFrame(version, 0, new AMQHeartbeatBody())); +} + +}} // namespace qpid::client diff --git a/qpid/cpp/src/client/Connection.h b/qpid/cpp/src/client/Connection.h new file mode 100644 index 0000000000..5e0b413dac --- /dev/null +++ b/qpid/cpp/src/client/Connection.h @@ -0,0 +1,179 @@ +#ifndef _client_Connection_ +#define _client_Connection_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../QpidError.h" +#include "ClientChannel.h" +#include "Connector.h" +#include "../sys/ShutdownHandler.h" +#include "../sys/TimeoutHandler.h" + + +namespace qpid { + +/** + * The client namespace contains all classes that make up a client + * implementation of the AMQP protocol. The key classes that form + * the basis of the client API to be used by applications are + * Connection and Channel. + */ +namespace client { + +/** + * \internal provide access to selected private channel functions + * for the Connection without making it a friend of the entire channel. + */ +class ConnectionForChannel : + public framing::InputHandler, + public framing::OutputHandler, + public sys::TimeoutHandler, + public sys::ShutdownHandler + +{ + private: + friend class Channel; + virtual void erase(framing::ChannelId) = 0; +}; + + +/** + * \defgroup clientapi Application API for an AMQP client + */ + +/** + * Represents a connection to an AMQP broker. All communication is + * initiated by establishing a connection, then opening one or + * more Channels over that connection. + * + * \ingroup clientapi + */ +class Connection : public ConnectionForChannel +{ + typedef std::map ChannelMap; + + framing::ChannelId channelIdCounter; + static const std::string OK; + + framing::ProtocolVersion version; + const uint32_t max_frame_size; + ChannelMap channels; + Connector defaultConnector; + Connector* connector; + framing::OutputHandler* out; + volatile bool isOpen; + Channel channel0; + bool debug; + + void erase(framing::ChannelId); + void channelException( + Channel&, framing::AMQMethodBody*, const QpidError&); + + // TODO aconway 2007-01-26: too many friendships, untagle these classes. + friend class Channel; + + public: + /** + * Creates a connection object, but does not open the + * connection. + * + * @param _version the version of the protocol to connect with + * + * @param debug turns on tracing for the connection + * (i.e. prints details of the frames sent and received to std + * out). Optional and defaults to false. + * + * @param max_frame_size the maximum frame size that the + * client will accept. Optional and defaults to 65536. + */ + Connection(bool debug = false, uint32_t max_frame_size = 65536, + framing::ProtocolVersion=framing::highestProtocolVersion); + ~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). + */ + void open(const std::string& host, int port = 5672, + const std::string& uid = "guest", + const std::string& pwd = "guest", + const std::string& virtualhost = "/"); + + /** + * Close the connection with optional error information for the peer. + * + * Any further use of this connection (without reopening it) will + * not succeed. + */ + void close(framing::ReplyCode=200, const std::string& msg=OK, + framing::ClassId = 0, framing::MethodId = 0); + + /** + * Associate a Channel with this connection and open it for use. + * + * In AMQP channels are like multi-plexed 'sessions' of work over + * a connection. Almost all the interaction with AMQP is done over + * a channel. + * + * @param connection the connection object to be associated with + * the channel. Call Channel::close() to close the channel. + */ + void openChannel(Channel&); + + + // TODO aconway 2007-01-26: can these be private? + void send(framing::AMQFrame*); + void received(framing::AMQFrame*); + void idleOut(); + void idleIn(); + void shutdown(); + + /**\internal used for testing */ + void setConnector(Connector& connector); + + /** + * @return the maximum frame size in use on this connection + */ + inline uint32_t getMaxFrameSize(){ return max_frame_size; } + + /** @return protocol version in use on this connection. */ + framing::ProtocolVersion getVersion() const { return version; } +}; + +}} // namespace qpid::client + + +#endif diff --git a/qpid/cpp/src/client/Connector.cpp b/qpid/cpp/src/client/Connector.cpp new file mode 100644 index 0000000000..566e58ec13 --- /dev/null +++ b/qpid/cpp/src/client/Connector.cpp @@ -0,0 +1,188 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include +#include "../QpidError.h" +#include "../sys/Time.h" +#include "Connector.h" + +namespace qpid { +namespace client { + +using namespace qpid::sys; +using namespace qpid::framing; +using qpid::QpidError; + +Connector::Connector( + ProtocolVersion ver, bool _debug, uint32_t buffer_size +) : debug(_debug), + receive_buffer_size(buffer_size), + send_buffer_size(buffer_size), + version(ver), + closed(true), + lastIn(0), lastOut(0), + timeout(0), + idleIn(0), idleOut(0), + timeoutHandler(0), + shutdownHandler(0), + inbuf(receive_buffer_size), + outbuf(send_buffer_size) +{ } + +Connector::~Connector(){ } + +void Connector::connect(const std::string& host, int port){ + socket = Socket::createTcp(); + socket.connect(host, port); + closed = false; + receiver = Thread(this); +} + +void Connector::init(){ + ProtocolInitiation init(version); + writeBlock(&init); +} + +void Connector::close(){ + closed = true; + socket.close(); + receiver.join(); +} + +void Connector::setInputHandler(InputHandler* handler){ + input = handler; +} + +void Connector::setShutdownHandler(ShutdownHandler* handler){ + shutdownHandler = handler; +} + +OutputHandler* Connector::getOutputHandler(){ + return this; +} + +void Connector::send(AMQFrame* f){ + std::auto_ptr frame(f); + AMQBody::shared_ptr body = frame->getBody(); + writeBlock(frame.get()); + if(debug) std::cout << "SENT: " << *frame << std::endl; +} + +void Connector::writeBlock(AMQDataBlock* data){ + Mutex::ScopedLock l(writeLock); + data->encode(outbuf); + //transfer data to wire + outbuf.flip(); + writeToSocket(outbuf.start(), outbuf.available()); + outbuf.clear(); +} + +void Connector::writeToSocket(char* data, size_t available){ + size_t written = 0; + while(written < available && !closed){ + ssize_t sent = socket.send(data + written, available-written); + if(sent > 0) { + lastOut = now() * TIME_MSEC; + written += sent; + } + } +} + +void Connector::handleClosed(){ + closed = true; + socket.close(); + if(shutdownHandler) shutdownHandler->shutdown(); +} + +void Connector::checkIdle(ssize_t status){ + if(timeoutHandler){ + Time t = now() * TIME_MSEC; + if(status == Socket::SOCKET_TIMEOUT) { + if(idleIn && (t - lastIn > idleIn)){ + timeoutHandler->idleIn(); + } + } + else if(status == 0 || status == Socket::SOCKET_EOF) { + handleClosed(); + } + else { + lastIn = t; + } + if(idleOut && (t - lastOut > idleOut)){ + timeoutHandler->idleOut(); + } + } +} + +void Connector::setReadTimeout(uint16_t t){ + idleIn = t * 1000;//t is in secs + if(idleIn && (!timeout || idleIn < timeout)){ + timeout = idleIn; + setSocketTimeout(); + } + +} + +void Connector::setWriteTimeout(uint16_t t){ + idleOut = t * 1000;//t is in secs + if(idleOut && (!timeout || idleOut < timeout)){ + timeout = idleOut; + setSocketTimeout(); + } +} + +void Connector::setSocketTimeout(){ + socket.setTimeout(timeout*TIME_MSEC); +} + +void Connector::setTimeoutHandler(TimeoutHandler* handler){ + timeoutHandler = handler; +} + +void Connector::run(){ + try{ + while(!closed){ + ssize_t available = inbuf.available(); + if(available < 1){ + THROW_QPID_ERROR(INTERNAL_ERROR, "Frame exceeds buffer size."); + } + ssize_t received = socket.recv(inbuf.start(), available); + checkIdle(received); + + if(!closed && received > 0){ + inbuf.move(received); + inbuf.flip();//position = 0, limit = total data read + + AMQFrame frame(version); + while(frame.decode(inbuf)){ + if(debug) std::cout << "RECV: " << frame << std::endl; + input->received(&frame); + } + //need to compact buffer to preserve any 'extra' data + inbuf.compact(); + } + } + } catch (const std::exception& e) { + std::cout << e.what() << std::endl; + handleClosed(); + } +} + +}} // namespace qpid::client diff --git a/qpid/cpp/src/client/Connector.h b/qpid/cpp/src/client/Connector.h new file mode 100644 index 0000000000..928bfa2d14 --- /dev/null +++ b/qpid/cpp/src/client/Connector.h @@ -0,0 +1,98 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _Connector_ +#define _Connector_ + + +#include "../framing/InputHandler.h" +#include "../framing/OutputHandler.h" +#include "../framing/InitiationHandler.h" +#include "../framing/ProtocolInitiation.h" +#include "../framing/ProtocolVersion.h" +#include "../sys/ShutdownHandler.h" +#include "../sys/TimeoutHandler.h" +#include "../sys/Thread.h" +#include "../sys/Monitor.h" +#include "../sys/Socket.h" + +namespace qpid { + +namespace client { + +class Connector : public framing::OutputHandler, + private sys::Runnable +{ + const bool debug; + const int receive_buffer_size; + const int send_buffer_size; + framing::ProtocolVersion version; + + bool closed; + + int64_t lastIn; + int64_t lastOut; + int64_t timeout; + uint32_t idleIn; + uint32_t idleOut; + + sys::TimeoutHandler* timeoutHandler; + sys::ShutdownHandler* shutdownHandler; + framing::InputHandler* input; + framing::InitiationHandler* initialiser; + framing::OutputHandler* output; + + framing::Buffer inbuf; + framing::Buffer outbuf; + + sys::Mutex writeLock; + sys::Thread receiver; + + sys::Socket socket; + + void checkIdle(ssize_t status); + void writeBlock(framing::AMQDataBlock* data); + void writeToSocket(char* data, size_t available); + void setSocketTimeout(); + + void run(); + void handleClosed(); + + friend class Channel; + public: + Connector(framing::ProtocolVersion pVersion, + bool debug = false, uint32_t buffer_size = 1024); + virtual ~Connector(); + virtual void connect(const std::string& host, int port); + virtual void init(); + virtual void close(); + virtual void setInputHandler(framing::InputHandler* handler); + virtual void setTimeoutHandler(sys::TimeoutHandler* handler); + virtual void setShutdownHandler(sys::ShutdownHandler* handler); + virtual framing::OutputHandler* getOutputHandler(); + virtual void send(framing::AMQFrame* frame); + virtual void setReadTimeout(uint16_t timeout); + virtual void setWriteTimeout(uint16_t timeout); +}; + +}} + + +#endif diff --git a/qpid/cpp/src/client/IncomingMessage.cpp b/qpid/cpp/src/client/IncomingMessage.cpp new file mode 100644 index 0000000000..05c4bc2378 --- /dev/null +++ b/qpid/cpp/src/client/IncomingMessage.cpp @@ -0,0 +1,130 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "IncomingMessage.h" +#include "../Exception.h" +#include "ClientMessage.h" +#include + +namespace qpid { +namespace client { + +using boost::format; +using sys::Mutex; + +IncomingMessage::Destination::~Destination() {} + +void IncomingMessage::openReference(const std::string& name) { + Mutex::ScopedLock l(lock); + if (references.find(name) != references.end()) + throw ConnectionException( + 503, format("Attempt to open existing reference %s.") % name); + references[name]; + return; +} + +void IncomingMessage::appendReference( + const std::string& name, const std::string& data) +{ + Mutex::ScopedLock l(lock); + getRefUnlocked(name).data += data; +} + +Message& IncomingMessage::createMessage( + const std::string& destination, const std::string& reference) +{ + Mutex::ScopedLock l(lock); + getDestUnlocked(destination); // Verify destination. + Reference& ref = getRefUnlocked(reference); + ref.messages.resize(ref.messages.size() +1); + ref.messages.back().setDestination(destination); + return ref.messages.back(); +} + +void IncomingMessage::closeReference(const std::string& name) { + Reference refCopy; + { + Mutex::ScopedLock l(lock); + refCopy = getRefUnlocked(name); + references.erase(name); + } + for (std::vector::iterator i = refCopy.messages.begin(); + i != refCopy.messages.end(); + ++i) + { + i->setData(refCopy.data); + // TODO aconway 2007-03-23: Thread safety, + // can a destination be removed while we're doing this? + getDestination(i->getDestination()).message(*i); + } +} + + +void IncomingMessage::addDestination(std::string name, Destination& dest) { + Mutex::ScopedLock l(lock); + DestinationMap::iterator i = destinations.find(name); + if (i == destinations.end()) + destinations[name]=&dest; + else if (i->second != &dest) + throw ConnectionException( + 503, format("Destination already exists: %s.") % name); +} + +void IncomingMessage::removeDestination(std::string name) { + Mutex::ScopedLock l(lock); + DestinationMap::iterator i = destinations.find(name); + if (i == destinations.end()) + throw ConnectionException( + 503, format("No such destination: %s.") % name); + destinations.erase(i); +} + +IncomingMessage::Destination& IncomingMessage::getDestination( + const std::string& name) { + return getDestUnlocked(name); +} + +IncomingMessage::Reference& IncomingMessage::getReference( + const std::string& name) { + return getRefUnlocked(name); +} + +IncomingMessage::Reference& IncomingMessage::getRefUnlocked( + const std::string& name) { + Mutex::ScopedLock l(lock); + ReferenceMap::iterator i = references.find(name); + if (i == references.end()) + throw ConnectionException( + 503, format("No such reference: %s.") % name); + return i->second; +} + +IncomingMessage::Destination& IncomingMessage::getDestUnlocked( + const std::string& name) { + Mutex::ScopedLock l(lock); + DestinationMap::iterator i = destinations.find(name); + if (i == destinations.end()) + throw ConnectionException( + 503, format("No such destination: %s.") % name); + return *i->second; +} + +}} // namespace qpid::client diff --git a/qpid/cpp/src/client/IncomingMessage.h b/qpid/cpp/src/client/IncomingMessage.h new file mode 100644 index 0000000000..b01bd3eedc --- /dev/null +++ b/qpid/cpp/src/client/IncomingMessage.h @@ -0,0 +1,114 @@ +#ifndef _IncomingMessage_ +#define _IncomingMessage_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../sys/Mutex.h" +#include +#include + + +namespace qpid { +namespace client { + +class Message; + +/** + * Manage incoming messages. + * + * Uses reference and destination concepts from 0-9 Messsage class. + * + * Basic messages use special destination and reference names to indicate + * get-ok, return etc. messages. + * + */ +class IncomingMessage { + public: + /** Accumulate data associated with a set of messages. */ + struct Reference { + std::string data; + std::vector messages; + }; + + /** Interface to a destination for messages. */ + class Destination { + public: + virtual ~Destination(); + + /** Pass a message to the destination */ + virtual void message(const Message&) = 0; + + /** Notify destination of queue-empty contition */ + virtual void empty() = 0; + }; + + + /** Add a reference. Throws if already open. */ + void openReference(const std::string& name); + + /** Get a reference. Throws if not already open. */ + void appendReference(const std::string& name, + const std::string& data); + + /** Create a message to destination associated with reference + *@exception if destination or reference non-existent. + */ + Message& createMessage(const std::string& destination, + const std::string& reference); + + /** Get a reference. + *@exception if non-existent. + */ + Reference& getReference(const std::string& name); + + /** Close a reference and deliver all its messages. + * Throws if not open or a message has an invalid destination. + */ + void closeReference(const std::string& name); + + /** Add a destination. + *@exception if a different Destination is already registered + * under name. + */ + void addDestination(std::string name, Destination&); + + /** Remove a destination. Throws if does not exist */ + void removeDestination(std::string name); + + /** Get a destination. Throws if does not exist */ + Destination& getDestination(const std::string& name); + private: + + typedef std::map ReferenceMap; + typedef std::map DestinationMap; + + Reference& getRefUnlocked(const std::string& name); + Destination& getDestUnlocked(const std::string& name); + + mutable sys::Mutex lock; + ReferenceMap references; + DestinationMap destinations; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/client/Makefile.am b/qpid/cpp/src/client/Makefile.am new file mode 100644 index 0000000000..4a98c3f539 --- /dev/null +++ b/qpid/cpp/src/client/Makefile.am @@ -0,0 +1,34 @@ +AM_CXXFLAGS = $(WARNING_CFLAGS) +INCLUDES = \ + -I$(srcdir)/../gen \ + $(APR_CXXFLAGS) + +lib_LTLIBRARIES = libqpidclient.la +libqpidclient_la_LIBADD = ../libqpidcommon.la +libqpidclient_la_LDFLAGS = -version-info $(LIBTOOL_VERSION_INFO_ARG) +libqpidclient_la_SOURCES = \ + ClientChannel.cpp \ + ClientExchange.cpp \ + ClientQueue.cpp \ + BasicMessageChannel.cpp \ + Connection.cpp \ + Connector.cpp \ + IncomingMessage.cpp \ + MessageListener.cpp \ + ResponseHandler.cpp \ + ReturnedMessageHandler.cpp +pkginclude_HEADERS = \ + AckMode.h \ + ClientChannel.h \ + ClientExchange.h \ + ClientMessage.h \ + ClientQueue.h \ + Connection.h \ + Connector.h \ + IncomingMessage.h \ + MessageChannel.h \ + BasicMessageChannel.h \ + MessageListener.h \ + MethodBodyInstances.h \ + ResponseHandler.h \ + ReturnedMessageHandler.h diff --git a/qpid/cpp/src/client/MessageChannel.h b/qpid/cpp/src/client/MessageChannel.h new file mode 100644 index 0000000000..2fa387b7f7 --- /dev/null +++ b/qpid/cpp/src/client/MessageChannel.h @@ -0,0 +1,94 @@ +#ifndef _client_MessageChannel_h +#define _client_MessageChannel_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 "../shared_ptr.h" +#include "../sys/Runnable.h" +#include "AckMode.h" + +namespace qpid { + +namespace framing { +class AMQMethodBody; +class AMQHeaderBody; +class AMQContentBody; +class FieldTable; +} + +namespace client { + +class Channel; +class Message; +class Queue; +class Exchange; +class MessageListener; +class ReturnedMessageHandler; + +/** + * Abstract interface for messaging implementation for a channel. + * + *@see Channel for documentation. + */ +class MessageChannel : public sys::Runnable +{ + public: + /**@see Channel::consume */ + virtual void consume( + Queue& queue, std::string& tag, MessageListener* listener, + AckMode ackMode = NO_ACK, bool noLocal = false, bool synch = true, + const framing::FieldTable* fields = 0) = 0; + + /**@see Channel::cancel */ + virtual void cancel(const std::string& tag, bool synch = true) = 0; + + /**@see Channel::get */ + virtual bool get( + Message& msg, const Queue& queue, AckMode ackMode = NO_ACK) = 0; + + /**@see Channel::get */ + virtual void publish(const Message& msg, const Exchange& exchange, + const std::string& routingKey, + bool mandatory = false, bool immediate = false) = 0; + + /**@see Channel::setReturnedMessageHandler */ + virtual void setReturnedMessageHandler( + ReturnedMessageHandler* handler) = 0; + + /** Handle an incoming method. */ + virtual void handle(shared_ptr) = 0; + + /** Handle an incoming header */ + virtual void handle(shared_ptr) = 0; + + /** Handle an incoming content */ + virtual void handle(shared_ptr) = 0; + + /** Send channel's QOS settings */ + virtual void setQos() = 0; + + /** Channel is closing */ + virtual void close() = 0; +}; + +}} // namespace qpid::client + + + +#endif /*!_client_MessageChannel_h*/ diff --git a/qpid/cpp/src/client/MessageListener.cpp b/qpid/cpp/src/client/MessageListener.cpp new file mode 100644 index 0000000000..68ebedeb0d --- /dev/null +++ b/qpid/cpp/src/client/MessageListener.cpp @@ -0,0 +1,24 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "MessageListener.h" + +qpid::client::MessageListener::~MessageListener() {} diff --git a/qpid/cpp/src/client/MessageListener.h b/qpid/cpp/src/client/MessageListener.h new file mode 100644 index 0000000000..501862a3ef --- /dev/null +++ b/qpid/cpp/src/client/MessageListener.h @@ -0,0 +1,49 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include + +#ifndef _MessageListener_ +#define _MessageListener_ + +#include "ClientMessage.h" + +namespace qpid { +namespace client { + + /** + * An interface through which asynchronously delivered messages + * can be received by an application. + * + * @see Channel::consume() + * + * \ingroup clientapi + */ + class MessageListener{ + public: + virtual ~MessageListener(); + virtual void received(Message& msg) = 0; + }; + +} +} + + +#endif diff --git a/qpid/cpp/src/client/MethodBodyInstances.h b/qpid/cpp/src/client/MethodBodyInstances.h new file mode 100644 index 0000000000..57b9bf73ce --- /dev/null +++ b/qpid/cpp/src/client/MethodBodyInstances.h @@ -0,0 +1,100 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../framing/amqp_framing.h" + +#ifndef _MethodBodyInstances_h_ +#define _MethodBodyInstances_h_ + +namespace qpid { +namespace client { + +/** + * A list of method body instances that can be used to compare against + * incoming bodies. + */ +class MethodBodyInstances +{ +private: + qpid::framing::ProtocolVersion version; +public: + const qpid::framing::BasicCancelOkBody basic_cancel_ok; + const qpid::framing::BasicConsumeOkBody basic_consume_ok; + const qpid::framing::BasicDeliverBody basic_deliver; + const qpid::framing::BasicGetEmptyBody basic_get_empty; + const qpid::framing::BasicGetOkBody basic_get_ok; + const qpid::framing::BasicQosOkBody basic_qos_ok; + const qpid::framing::BasicReturnBody basic_return; + const qpid::framing::ChannelCloseBody channel_close; + const qpid::framing::ChannelCloseOkBody channel_close_ok; + const qpid::framing::ChannelFlowBody channel_flow; + const qpid::framing::ChannelOpenOkBody channel_open_ok; + const qpid::framing::ConnectionCloseBody connection_close; + const qpid::framing::ConnectionCloseOkBody connection_close_ok; + const qpid::framing::ConnectionOpenOkBody connection_open_ok; + const qpid::framing::ConnectionRedirectBody connection_redirect; + const qpid::framing::ConnectionStartBody connection_start; + const qpid::framing::ConnectionTuneBody connection_tune; + const qpid::framing::ExchangeDeclareOkBody exchange_declare_ok; + const qpid::framing::ExchangeDeleteOkBody exchange_delete_ok; + const qpid::framing::QueueDeclareOkBody queue_declare_ok; + const qpid::framing::QueueDeleteOkBody queue_delete_ok; + const qpid::framing::QueueBindOkBody queue_bind_ok; + const qpid::framing::TxCommitOkBody tx_commit_ok; + const qpid::framing::TxRollbackOkBody tx_rollback_ok; + const qpid::framing::TxSelectOkBody tx_select_ok; + + MethodBodyInstances(uint8_t major, uint8_t minor) : + version(major, minor), + basic_cancel_ok(version), + basic_consume_ok(version), + basic_deliver(version), + basic_get_empty(version), + basic_get_ok(version), + basic_qos_ok(version), + basic_return(version), + channel_close(version), + channel_close_ok(version), + channel_flow(version), + channel_open_ok(version), + connection_close(version), + connection_close_ok(version), + connection_open_ok(version), + connection_redirect(version), + connection_start(version), + connection_tune(version), + exchange_declare_ok(version), + exchange_delete_ok(version), + queue_declare_ok(version), + queue_delete_ok(version), + queue_bind_ok(version), + tx_commit_ok(version), + tx_rollback_ok(version), + tx_select_ok(version) + {} + +}; + +static MethodBodyInstances method_bodies(8, 0); + +} // namespace client +} // namespace qpid + +#endif diff --git a/qpid/cpp/src/client/ResponseHandler.cpp b/qpid/cpp/src/client/ResponseHandler.cpp new file mode 100644 index 0000000000..ca0129d587 --- /dev/null +++ b/qpid/cpp/src/client/ResponseHandler.cpp @@ -0,0 +1,79 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../QpidError.h" +#include +#include "ResponseHandler.h" +#include "../framing/AMQMethodBody.h" + +using namespace qpid::sys; +using namespace qpid::framing; + +namespace qpid { +namespace client { + +ResponseHandler::ResponseHandler() : waiting(false), shutdownFlag(false) {} + +ResponseHandler::~ResponseHandler(){} + +bool ResponseHandler::isWaiting() { + Monitor::ScopedLock l(monitor); + return waiting; +} + +void ResponseHandler::expect(){ + Monitor::ScopedLock l(monitor); + waiting = true; +} + +void ResponseHandler::signalResponse(MethodPtr _response) +{ + Monitor::ScopedLock l(monitor); + response = _response; + if (!response) + shutdownFlag=true; + waiting = false; + monitor.notify(); +} + +ResponseHandler::MethodPtr ResponseHandler::receive() { + Monitor::ScopedLock l(monitor); + while (!response && !shutdownFlag) + monitor.wait(); + if (shutdownFlag) + THROW_QPID_ERROR( + PROTOCOL_ERROR, "Channel closed unexpectedly."); + MethodPtr result = response; + response.reset(); + return result; +} + +ResponseHandler::MethodPtr ResponseHandler::receive(ClassId c, MethodId m) { + MethodPtr response = receive(); + if(c != response->amqpClassId() || m != response->amqpMethodId()) { + THROW_QPID_ERROR( + PROTOCOL_ERROR, + boost::format("Expected class:method %d:%d, got %d:%d") + % c % m % response->amqpClassId() % response->amqpMethodId()); + } + return response; +} + +}} // namespace qpid::client diff --git a/qpid/cpp/src/client/ResponseHandler.h b/qpid/cpp/src/client/ResponseHandler.h new file mode 100644 index 0000000000..289a5dd994 --- /dev/null +++ b/qpid/cpp/src/client/ResponseHandler.h @@ -0,0 +1,75 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../shared_ptr.h" +#include "../sys/Monitor.h" + +#ifndef _ResponseHandler_ +#define _ResponseHandler_ + +namespace qpid { + +namespace framing { +class AMQMethodBody; +} + +namespace client { + +/** + * Holds a response from the broker peer for the client. + */ +class ResponseHandler{ + typedef shared_ptr MethodPtr; + bool waiting; + bool shutdownFlag; + MethodPtr response; + sys::Monitor monitor; + + public: + ResponseHandler(); + ~ResponseHandler(); + + /** Is a response expected? */ + bool isWaiting(); + + /** Provide a response to the waiting thread */ + void signalResponse(MethodPtr response); + + /** Indicate a message is expected. */ + void expect(); + + /** Wait for a response. */ + MethodPtr receive(); + + /** Wait for a specific response. */ + MethodPtr receive(framing::ClassId, framing::MethodId); + + /** Template version of receive returns typed pointer. */ + template + shared_ptr receive() { + return shared_polymorphic_downcast( + receive(BodyType::CLASS_ID, BodyType::METHOD_ID)); + } +}; + +}} + + +#endif diff --git a/qpid/cpp/src/client/ReturnedMessageHandler.cpp b/qpid/cpp/src/client/ReturnedMessageHandler.cpp new file mode 100644 index 0000000000..35d0b5c0a8 --- /dev/null +++ b/qpid/cpp/src/client/ReturnedMessageHandler.cpp @@ -0,0 +1,24 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "ReturnedMessageHandler.h" + +qpid::client::ReturnedMessageHandler::~ReturnedMessageHandler() {} diff --git a/qpid/cpp/src/client/ReturnedMessageHandler.h b/qpid/cpp/src/client/ReturnedMessageHandler.h new file mode 100644 index 0000000000..8b42fc0764 --- /dev/null +++ b/qpid/cpp/src/client/ReturnedMessageHandler.h @@ -0,0 +1,49 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include + +#ifndef _ReturnedMessageHandler_ +#define _ReturnedMessageHandler_ + +#include "ClientMessage.h" + +namespace qpid { +namespace client { + + /** + * An interface through which returned messages can be received by + * an application. + * + * @see Channel::setReturnedMessageHandler() + * + * \ingroup clientapi + */ + class ReturnedMessageHandler{ + public: + virtual ~ReturnedMessageHandler(); + virtual void returned(Message& msg) = 0; + }; + +} +} + + +#endif diff --git a/qpid/cpp/src/doxygen_mainpage.h b/qpid/cpp/src/doxygen_mainpage.h new file mode 100644 index 0000000000..b354238cd0 --- /dev/null +++ b/qpid/cpp/src/doxygen_mainpage.h @@ -0,0 +1,45 @@ +// This header file is just for doxygen documentation purposes. + +/*!\mainpage Qpid C++ Developer Kit. + * + *\section intro_sec Introduction + * + * The Qpid project provides implementations of the AMQP messaging specification in several programming language. + * + * Qpidc provides APIs and libraries to implement AMQP + * clients in C++. Qpidc clients can interact with any compliant AMQP + * message broker. The Qpid project also provides an AMQP broker + * daemon called qpidd that you can use with your qpidc clients. + * + *\section install_sec Installation + * + * If you are installing from the source distribution +
+   > ./configure && make
+   > make install  
+ * This will build and install the client development kit and the broker + * in standard places. Use + * ./configure --help for more options. + * + * You can also install from RPMs with the rpm -i command. + * You will need + * - qpidc for core libraries. + * - qpidc-devel for header files and developer documentation. + * - qpidd for the broker daemon. + * + *\section getstart_sec Getting Started + * + * If you have installed in the standard places you should use + * these compile flags: + * + * -I/usr/include/qpidc -I/usr/include/qpidc/framing -I/usr/include/qpidc/sys + * + * and these link flags: + * + * -lqpidcommon -lqpidclient + * + * If you have installed somewhere else you should modify the flags + * appropriately. + * + * See the \ref clientapi "client API module" for more on the client API. + */ diff --git a/qpid/cpp/src/framing/AMQBody.cpp b/qpid/cpp/src/framing/AMQBody.cpp new file mode 100644 index 0000000000..a64d224a86 --- /dev/null +++ b/qpid/cpp/src/framing/AMQBody.cpp @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "AMQBody.h" +#include + +std::ostream& qpid::framing::operator<<(std::ostream& out, const qpid::framing::AMQBody& body) +{ + body.print(out); + return out; +} + +qpid::framing::AMQBody::~AMQBody() {} + + diff --git a/qpid/cpp/src/framing/AMQBody.h b/qpid/cpp/src/framing/AMQBody.h new file mode 100644 index 0000000000..eaa568c06a --- /dev/null +++ b/qpid/cpp/src/framing/AMQBody.h @@ -0,0 +1,59 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include +#include "amqp_types.h" +#include "Buffer.h" + +#ifndef _AMQBody_ +#define _AMQBody_ + +namespace qpid { + namespace framing { + + class AMQBody + { + public: + typedef boost::shared_ptr shared_ptr; + + virtual ~AMQBody(); + virtual uint32_t size() const = 0; + virtual uint8_t type() const = 0; + virtual void encode(Buffer& buffer) const = 0; + virtual void decode(Buffer& buffer, uint32_t size) = 0; + + virtual void print(std::ostream& out) const = 0; + }; + + std::ostream& operator<<(std::ostream& out, const AMQBody& body) ; + + enum BodyTypes { + METHOD_BODY = 1, + HEADER_BODY = 2, + CONTENT_BODY = 3, + HEARTBEAT_BODY = 8, + REQUEST_BODY = 9, + RESPONSE_BODY = 10 + }; + } +} + + +#endif diff --git a/qpid/cpp/src/framing/AMQContentBody.cpp b/qpid/cpp/src/framing/AMQContentBody.cpp new file mode 100644 index 0000000000..19d2e5714a --- /dev/null +++ b/qpid/cpp/src/framing/AMQContentBody.cpp @@ -0,0 +1,43 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "AMQContentBody.h" +#include + +qpid::framing::AMQContentBody::AMQContentBody(){ +} + +qpid::framing::AMQContentBody::AMQContentBody(const string& _data) : data(_data){ +} + +uint32_t qpid::framing::AMQContentBody::size() 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 (" << size() << " bytes)"; +} diff --git a/qpid/cpp/src/framing/AMQContentBody.h b/qpid/cpp/src/framing/AMQContentBody.h new file mode 100644 index 0000000000..6d4c1ef4b6 --- /dev/null +++ b/qpid/cpp/src/framing/AMQContentBody.h @@ -0,0 +1,53 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "amqp_types.h" +#include "AMQBody.h" +#include "Buffer.h" + +#ifndef _AMQContentBody_ +#define _AMQContentBody_ + +namespace qpid { +namespace framing { + +class AMQContentBody : public AMQBody +{ + string data; + +public: + typedef boost::shared_ptr shared_ptr; + + AMQContentBody(); + AMQContentBody(const string& data); + inline virtual ~AMQContentBody(){} + inline uint8_t type() const { return CONTENT_BODY; }; + inline string& getData(){ return data; } + uint32_t size() const; + void encode(Buffer& buffer) const; + void decode(Buffer& buffer, uint32_t size); + void print(std::ostream& out) const; +}; + +} +} + + +#endif diff --git a/qpid/cpp/src/framing/AMQDataBlock.h b/qpid/cpp/src/framing/AMQDataBlock.h new file mode 100644 index 0000000000..6ff61b185e --- /dev/null +++ b/qpid/cpp/src/framing/AMQDataBlock.h @@ -0,0 +1,42 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "Buffer.h" + +#ifndef _AMQDataBlock_ +#define _AMQDataBlock_ + +namespace qpid { +namespace framing { + +class AMQDataBlock +{ +public: + virtual ~AMQDataBlock() {} + virtual void encode(Buffer& buffer) = 0; + virtual bool decode(Buffer& buffer) = 0; + virtual uint32_t size() const = 0; +}; + +} +} + + +#endif diff --git a/qpid/cpp/src/framing/AMQFrame.cpp b/qpid/cpp/src/framing/AMQFrame.cpp new file mode 100644 index 0000000000..8b79286107 --- /dev/null +++ b/qpid/cpp/src/framing/AMQFrame.cpp @@ -0,0 +1,139 @@ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "AMQFrame.h" +#include "../QpidError.h" +#include "AMQRequestBody.h" +#include "AMQResponseBody.h" + + +namespace qpid { +namespace framing { + + +AMQP_MethodVersionMap AMQFrame::versionMap; + +AMQFrame::AMQFrame(ProtocolVersion _version): +version(_version) + { + assert(version != ProtocolVersion(0,0)); + } + +AMQFrame::AMQFrame(ProtocolVersion _version, uint16_t _channel, AMQBody* _body) : +version(_version), channel(_channel), body(_body) +{} + +AMQFrame::AMQFrame(ProtocolVersion _version, uint16_t _channel, const AMQBody::shared_ptr& _body) : +version(_version), channel(_channel), body(_body) +{} + +AMQFrame::~AMQFrame() {} + +uint16_t AMQFrame::getChannel(){ + return channel; +} + +AMQBody::shared_ptr AMQFrame::getBody(){ + return body; +} + +void AMQFrame::encode(Buffer& buffer) +{ + buffer.putOctet(body->type()); + buffer.putShort(channel); + buffer.putLong(body->size()); + body->encode(buffer); + buffer.putOctet(0xCE); +} + +uint32_t AMQFrame::size() const{ + assert(body.get()); + return 1/*type*/ + 2/*channel*/ + 4/*body size*/ + body->size() + + 1/*0xCE*/; +} + +bool AMQFrame::decode(Buffer& buffer) +{ + if(buffer.available() < 7) + return false; + buffer.record(); + uint32_t frameSize = decodeHead(buffer); + if(buffer.available() < frameSize + 1){ + buffer.restore(); + return false; + } + decodeBody(buffer, frameSize); + uint8_t end = buffer.getOctet(); + if(end != 0xCE) THROW_QPID_ERROR(FRAMING_ERROR, "Frame end not found"); + return true; +} + +uint32_t AMQFrame::decodeHead(Buffer& buffer){ + type = buffer.getOctet(); + channel = buffer.getShort(); + return buffer.getLong(); +} + +void AMQFrame::decodeBody(Buffer& buffer, uint32_t size) +{ + switch(type) + { + case METHOD_BODY: + body = AMQMethodBody::create(versionMap, version, buffer); + break; + case REQUEST_BODY: + body = AMQRequestBody::create(versionMap, version, buffer); + break; + case RESPONSE_BODY: + body = AMQResponseBody::create(versionMap, version, buffer); + break; + case HEADER_BODY: + body = AMQBody::shared_ptr(new AMQHeaderBody()); + break; + case CONTENT_BODY: + body = AMQBody::shared_ptr(new AMQContentBody()); + break; + case HEARTBEAT_BODY: + body = AMQBody::shared_ptr(new AMQHeartbeatBody()); + break; + default: + THROW_QPID_ERROR( + FRAMING_ERROR, + boost::format("Unknown frame type %d") % type); + } + body->decode(buffer, size); +} + +std::ostream& operator<<(std::ostream& out, const AMQFrame& t) +{ + out << "Frame[channel=" << t.channel << "; "; + if (t.body.get() == 0) + out << "empty"; + else + out << *t.body; + out << "]"; + return out; +} + + +}} // namespace qpid::framing diff --git a/qpid/cpp/src/framing/AMQFrame.h b/qpid/cpp/src/framing/AMQFrame.h new file mode 100644 index 0000000000..d4c2e0640d --- /dev/null +++ b/qpid/cpp/src/framing/AMQFrame.h @@ -0,0 +1,78 @@ +#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 + +#include "amqp_types.h" +#include "AMQBody.h" +#include "AMQDataBlock.h" +#include "AMQMethodBody.h" +#include "AMQHeaderBody.h" +#include "AMQContentBody.h" +#include "AMQHeartbeatBody.h" +#include "AMQP_MethodVersionMap.h" +#include "AMQP_HighestVersion.h" +#include "Buffer.h" + +namespace qpid { +namespace framing { + + +class AMQFrame : public AMQDataBlock +{ + public: + AMQFrame(ProtocolVersion _version = highestProtocolVersion); + AMQFrame(ProtocolVersion _version, uint16_t channel, AMQBody* body); + AMQFrame(ProtocolVersion _version, uint16_t channel, const AMQBody::shared_ptr& body); + virtual ~AMQFrame(); + virtual void encode(Buffer& buffer); + virtual bool decode(Buffer& buffer); + virtual uint32_t size() const; + uint16_t getChannel(); + AMQBody::shared_ptr getBody(); + + /** Convenience template to cast the body to an expected type */ + template boost::shared_ptr castBody() { + assert(dynamic_cast(getBody().get())); + boost::static_pointer_cast(getBody()); + } + + uint32_t decodeHead(Buffer& buffer); + void decodeBody(Buffer& buffer, uint32_t size); + + private: + static AMQP_MethodVersionMap versionMap; + ProtocolVersion version; + + uint16_t channel; + uint8_t type; + AMQBody::shared_ptr body; + + + friend std::ostream& operator<<(std::ostream& out, const AMQFrame& body); +}; + +}} // namespace qpid::framing + + +#endif diff --git a/qpid/cpp/src/framing/AMQHeaderBody.cpp b/qpid/cpp/src/framing/AMQHeaderBody.cpp new file mode 100644 index 0000000000..fccffd006c --- /dev/null +++ b/qpid/cpp/src/framing/AMQHeaderBody.cpp @@ -0,0 +1,75 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "AMQHeaderBody.h" +#include "../QpidError.h" +#include "BasicHeaderProperties.h" + +qpid::framing::AMQHeaderBody::AMQHeaderBody(int classId) : weight(0), contentSize(0){ + createProperties(classId); +} + +qpid::framing::AMQHeaderBody::AMQHeaderBody() : properties(0), weight(0), contentSize(0){ +} + +qpid::framing::AMQHeaderBody::~AMQHeaderBody(){ + delete properties; +} + +uint32_t qpid::framing::AMQHeaderBody::size() const{ + return 12 + properties->size(); +} + +void qpid::framing::AMQHeaderBody::encode(Buffer& buffer) const { + buffer.putShort(properties->classId()); + buffer.putShort(weight); + buffer.putLongLong(contentSize); + properties->encode(buffer); +} + +void qpid::framing::AMQHeaderBody::decode(Buffer& buffer, uint32_t bufSize){ + uint16_t classId = buffer.getShort(); + weight = buffer.getShort(); + contentSize = buffer.getLongLong(); + createProperties(classId); + properties->decode(buffer, bufSize - 12); +} + +void qpid::framing::AMQHeaderBody::createProperties(int classId){ + switch(classId){ + case BASIC: + properties = new qpid::framing::BasicHeaderProperties(); + break; + default: + THROW_QPID_ERROR(FRAMING_ERROR, "Unknown header class"); + } +} + +void qpid::framing::AMQHeaderBody::print(std::ostream& out) const +{ + out << "header (" << size() << " bytes)" << " content_size=" << getContentSize(); + const BasicHeaderProperties* props = + dynamic_cast(getProperties()); + if (props) { + out << ", message_id=" << props->getMessageId(); + out << ", delivery_mode=" << (int) props->getDeliveryMode(); + out << ", headers=" << const_cast(props)->getHeaders(); + } +} diff --git a/qpid/cpp/src/framing/AMQHeaderBody.h b/qpid/cpp/src/framing/AMQHeaderBody.h new file mode 100644 index 0000000000..691ceeff73 --- /dev/null +++ b/qpid/cpp/src/framing/AMQHeaderBody.h @@ -0,0 +1,60 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "amqp_types.h" +#include "AMQBody.h" +#include "Buffer.h" +#include "HeaderProperties.h" + +#ifndef _AMQHeaderBody_ +#define _AMQHeaderBody_ + +namespace qpid { +namespace framing { + +class AMQHeaderBody : public AMQBody +{ + HeaderProperties* properties; + uint16_t weight; + uint64_t contentSize; + + void createProperties(int classId); +public: + typedef boost::shared_ptr shared_ptr; + + AMQHeaderBody(int classId); + AMQHeaderBody(); + inline uint8_t type() const { return HEADER_BODY; } + HeaderProperties* getProperties(){ return properties; } + const HeaderProperties* getProperties() const { return properties; } + inline uint64_t getContentSize() const { return contentSize; } + inline void setContentSize(uint64_t _size) { contentSize = _size; } + virtual ~AMQHeaderBody(); + virtual uint32_t size() const; + virtual void encode(Buffer& buffer) const; + virtual void decode(Buffer& buffer, uint32_t size); + virtual void print(std::ostream& out) const; +}; + +} +} + + +#endif diff --git a/qpid/cpp/src/framing/AMQHeartbeatBody.cpp b/qpid/cpp/src/framing/AMQHeartbeatBody.cpp new file mode 100644 index 0000000000..140ce2e794 --- /dev/null +++ b/qpid/cpp/src/framing/AMQHeartbeatBody.cpp @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "AMQHeartbeatBody.h" +#include + +qpid::framing::AMQHeartbeatBody::~AMQHeartbeatBody() {} + +void qpid::framing::AMQHeartbeatBody::print(std::ostream& out) const { + out << "heartbeat"; +} diff --git a/qpid/cpp/src/framing/AMQHeartbeatBody.h b/qpid/cpp/src/framing/AMQHeartbeatBody.h new file mode 100644 index 0000000000..4c046b81a7 --- /dev/null +++ b/qpid/cpp/src/framing/AMQHeartbeatBody.h @@ -0,0 +1,47 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "amqp_types.h" +#include "AMQBody.h" +#include "Buffer.h" + +#ifndef _AMQHeartbeatBody_ +#define _AMQHeartbeatBody_ + +namespace qpid { +namespace framing { + +class AMQHeartbeatBody : public AMQBody +{ +public: + typedef boost::shared_ptr shared_ptr; + + virtual ~AMQHeartbeatBody(); + inline uint32_t size() const { return 0; } + inline uint8_t type() const { return HEARTBEAT_BODY; } + inline void encode(Buffer& ) const {} + inline void decode(Buffer& , uint32_t /*size*/) {} + virtual void print(std::ostream& out) const; +}; + +} +} + +#endif diff --git a/qpid/cpp/src/framing/AMQMethodBody.cpp b/qpid/cpp/src/framing/AMQMethodBody.cpp new file mode 100644 index 0000000000..44924b76e1 --- /dev/null +++ b/qpid/cpp/src/framing/AMQMethodBody.cpp @@ -0,0 +1,59 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "AMQFrame.h" +#include "AMQMethodBody.h" +#include "../QpidError.h" +#include "AMQP_MethodVersionMap.h" + +namespace qpid { +namespace framing { + +void AMQMethodBody::encodeId(Buffer& buffer) const{ + buffer.putShort(amqpClassId()); + buffer.putShort(amqpMethodId()); +} + +void AMQMethodBody::invoke(AMQP_ServerOperations&, const MethodContext&){ + assert(0); + THROW_QPID_ERROR(PROTOCOL_ERROR, "Method not supported by AMQP Server."); +} + +AMQMethodBody::shared_ptr AMQMethodBody::create( + AMQP_MethodVersionMap& versionMap, ProtocolVersion version, + Buffer& buffer) +{ + ClassMethodId id; + id.decode(buffer); + return AMQMethodBody::shared_ptr( + versionMap.createMethodBody( + id.classId, id.methodId, version.getMajor(), version.getMinor())); +} + +void AMQMethodBody::ClassMethodId::decode(Buffer& buffer) { + classId = buffer.getShort(); + methodId = buffer.getShort(); +} + +void AMQMethodBody::decode(Buffer& buffer, uint32_t /*size*/) { + decodeContent(buffer); +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/src/framing/AMQMethodBody.h b/qpid/cpp/src/framing/AMQMethodBody.h new file mode 100644 index 0000000000..c5f0a1adf7 --- /dev/null +++ b/qpid/cpp/src/framing/AMQMethodBody.h @@ -0,0 +1,84 @@ +#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 +#include "amqp_types.h" +#include "AMQBody.h" +#include "Buffer.h" +#include "AMQP_ServerOperations.h" +#include "MethodContext.h" + +namespace qpid { +namespace framing { + +class AMQP_MethodVersionMap; + +class AMQMethodBody : public AMQBody +{ + public: + typedef boost::shared_ptr shared_ptr; + + static shared_ptr create( + AMQP_MethodVersionMap& map, ProtocolVersion version, Buffer& buf); + + ProtocolVersion version; + uint8_t type() const { return METHOD_BODY; } + AMQMethodBody(uint8_t major, uint8_t minor) : version(major, minor) {} + AMQMethodBody(ProtocolVersion ver) : version(ver) {} + virtual ~AMQMethodBody() {} + void decode(Buffer&, uint32_t); + + virtual MethodId amqpMethodId() const = 0; + virtual ClassId amqpClassId() const = 0; + + virtual void invoke(AMQP_ServerOperations&, const MethodContext&); + + template bool isA() { + return amqpClassId()==T::CLASS_ID && amqpMethodId()==T::METHOD_ID; + } + + /** Return request ID or response correlationID */ + virtual RequestId getRequestId() const { return 0; } + + virtual bool isRequest() const { return false; } + virtual bool isResponse() const { return false; } + + protected: + static uint32_t baseSize() { return 4; } + + struct ClassMethodId { + uint16_t classId; + uint16_t methodId; + void decode(Buffer& b); + }; + + void encodeId(Buffer& buffer) const; + virtual void encodeContent(Buffer& buffer) const = 0; + virtual void decodeContent(Buffer& buffer) = 0; +}; + + +}} // namespace qpid::framing + + +#endif diff --git a/qpid/cpp/src/framing/AMQRequestBody.cpp b/qpid/cpp/src/framing/AMQRequestBody.cpp new file mode 100644 index 0000000000..54e1c11863 --- /dev/null +++ b/qpid/cpp/src/framing/AMQRequestBody.cpp @@ -0,0 +1,66 @@ +/* + * + * 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 "AMQRequestBody.h" +#include "AMQP_MethodVersionMap.h" + +namespace qpid { +namespace framing { + +void AMQRequestBody::Data::encode(Buffer& buffer) const { + buffer.putLongLong(requestId); + buffer.putLongLong(responseMark); + buffer.putLong(0); // Reserved long in spec. +} + +void AMQRequestBody::Data::decode(Buffer& buffer) { + requestId = buffer.getLongLong(); + responseMark = buffer.getLongLong(); + buffer.getLong(); // Ignore reserved long. +} + +void AMQRequestBody::encode(Buffer& buffer) const { + data.encode(buffer); + encodeId(buffer); + encodeContent(buffer); +} + +AMQRequestBody::shared_ptr +AMQRequestBody::create( + AMQP_MethodVersionMap& versionMap, ProtocolVersion version, + Buffer& buffer) +{ + ClassMethodId id; + Data data; + data.decode(buffer); + id.decode(buffer); + AMQRequestBody* body = dynamic_cast( + versionMap.createMethodBody( + id.classId, id.methodId, version.getMajor(), version.getMinor())); + assert(body); + body->data = data; + return AMQRequestBody::shared_ptr(body); +} + +void AMQRequestBody::printPrefix(std::ostream& out) const { + out << "request(id=" << data.requestId << ",mark=" + << data.responseMark << "): "; +} + +}} // namespace qpid::framing + diff --git a/qpid/cpp/src/framing/AMQRequestBody.h b/qpid/cpp/src/framing/AMQRequestBody.h new file mode 100644 index 0000000000..f21659a57a --- /dev/null +++ b/qpid/cpp/src/framing/AMQRequestBody.h @@ -0,0 +1,78 @@ +#ifndef _framing_AMQRequestBody_h +#define _framing_AMQRequestBody_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 "AMQMethodBody.h" + +namespace qpid { +namespace framing { + +/** + * Body of a request method frame. + */ +class AMQRequestBody : public AMQMethodBody +{ + public: + typedef boost::shared_ptr shared_ptr; + + struct Data { + Data(RequestId id=0, ResponseId mark=0) + : requestId(id), responseMark(mark) {} + void encode(Buffer&) const; + void decode(Buffer&); + + RequestId requestId; + ResponseId responseMark; + }; + + static Data& getData(const AMQBody::shared_ptr& body) { + return boost::dynamic_pointer_cast(body)->getData(); + } + + static shared_ptr create( + AMQP_MethodVersionMap& versionMap, ProtocolVersion version, + Buffer& buffer); + + AMQRequestBody(ProtocolVersion v, RequestId id=0, ResponseId mark=0) + : AMQMethodBody(v), data(id, mark) {} + + uint8_t type() const { return REQUEST_BODY; } + void encode(Buffer& buffer) const; + + Data& getData() { return data; } + RequestId getRequestId() const { return data.requestId; } + ResponseId getResponseMark() const { return data.responseMark; } + void setRequestId(RequestId id) { data.requestId=id; } + void setResponseMark(ResponseId mark) { data.responseMark=mark; } + + bool isRequest()const { return true; } + static const uint32_t baseSize() { return AMQMethodBody::baseSize()+20; } + protected: + void printPrefix(std::ostream& out) const; + + private: + Data data; +}; + +}} // namespace qpid::framing + + + +#endif /*!_framing_AMQRequestBody_h*/ diff --git a/qpid/cpp/src/framing/AMQResponseBody.cpp b/qpid/cpp/src/framing/AMQResponseBody.cpp new file mode 100644 index 0000000000..7da71a5d25 --- /dev/null +++ b/qpid/cpp/src/framing/AMQResponseBody.cpp @@ -0,0 +1,65 @@ +/* + * + * 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 "AMQFrame.h" +#include "AMQResponseBody.h" +#include "AMQP_MethodVersionMap.h" + +namespace qpid { +namespace framing { + +void AMQResponseBody::Data::encode(Buffer& buffer) const { + buffer.putLongLong(responseId); + buffer.putLongLong(requestId); + buffer.putLong(batchOffset); +} + +void AMQResponseBody::Data::decode(Buffer& buffer) { + responseId = buffer.getLongLong(); + requestId = buffer.getLongLong(); + batchOffset = buffer.getLong(); +} + +void AMQResponseBody::encode(Buffer& buffer) const { + data.encode(buffer); + encodeId(buffer); + encodeContent(buffer); +} + +AMQResponseBody::shared_ptr AMQResponseBody::create( + AMQP_MethodVersionMap& versionMap, ProtocolVersion version, + Buffer& buffer) +{ + ClassMethodId id; + Data data; + data.decode(buffer); + id.decode(buffer); + AMQResponseBody* body = dynamic_cast( + versionMap.createMethodBody( + id.classId, id.methodId, version.getMajor(), version.getMinor())); + assert(body); + body->data = data; + return AMQResponseBody::shared_ptr(body); +} + +void AMQResponseBody::printPrefix(std::ostream& out) const { + out << "response(id=" << data.responseId << ",request=" << data.requestId + << ",batch=" << data.batchOffset << "): "; +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/src/framing/AMQResponseBody.h b/qpid/cpp/src/framing/AMQResponseBody.h new file mode 100644 index 0000000000..fa381baddd --- /dev/null +++ b/qpid/cpp/src/framing/AMQResponseBody.h @@ -0,0 +1,85 @@ +#ifndef _framing_AMQResponseBody_h +#define _framing_AMQResponseBody_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 "AMQMethodBody.h" + +namespace qpid { +namespace framing { + +class AMQP_MethodVersionMap; + +/** + * Body of a response method frame. + */ +class AMQResponseBody : public AMQMethodBody +{ + + public: + typedef boost::shared_ptr shared_ptr; + + struct Data { + Data(ResponseId id=0, RequestId req=0, BatchOffset off=0) + : responseId(id), requestId(req), batchOffset(off) {} + void encode(Buffer&) const; + void decode(Buffer&); + + uint64_t responseId; + uint64_t requestId; + uint32_t batchOffset; + }; + + static Data& getData(const AMQBody::shared_ptr& body) { + return boost::dynamic_pointer_cast(body)->getData(); + } + + static shared_ptr create( + AMQP_MethodVersionMap& versionMap, ProtocolVersion version, + Buffer& buffer); + + AMQResponseBody( + ProtocolVersion v, ResponseId id=0, RequestId req=0, BatchOffset off=0) + : AMQMethodBody(v), data(id, req, off) {} + + uint8_t type() const { return RESPONSE_BODY; } + void encode(Buffer& buffer) const; + + Data& getData() { return data; } + ResponseId getResponseId() const { return data.responseId; } + RequestId getRequestId() const { return data.requestId; } + BatchOffset getBatchOffset() const { return data.batchOffset; } + void setResponseId(ResponseId id) { data.responseId = id; } + void setRequestId(RequestId id) { data.requestId = id; } + void setBatchOffset(BatchOffset id) { data.batchOffset = id; } + + bool isResponse() const { return true; } + protected: + static const uint32_t baseSize() { return AMQMethodBody::baseSize()+20; } + void printPrefix(std::ostream& out) const; + + private: + Data data; +}; + +}} // namespace qpid::framing + + + +#endif /*!_framing_AMQResponseBody_h*/ diff --git a/qpid/cpp/src/framing/BasicHeaderProperties.cpp b/qpid/cpp/src/framing/BasicHeaderProperties.cpp new file mode 100644 index 0000000000..dfa5e1bc3f --- /dev/null +++ b/qpid/cpp/src/framing/BasicHeaderProperties.cpp @@ -0,0 +1,103 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "BasicHeaderProperties.h" + +//TODO: This could be easily generated from the spec + +qpid::framing::BasicHeaderProperties::BasicHeaderProperties() : deliveryMode(DeliveryMode(0)), priority(0), timestamp(0){} +qpid::framing::BasicHeaderProperties::~BasicHeaderProperties(){} + +uint32_t qpid::framing::BasicHeaderProperties::size() const{ + uint32_t bytes = 2;//flags + if(contentType.length() > 0) bytes += contentType.length() + 1; + if(contentEncoding.length() > 0) bytes += contentEncoding.length() + 1; + if(headers.count() > 0) bytes += headers.size(); + if(deliveryMode != 0) bytes += 1; + if(priority != 0) bytes += 1; + if(correlationId.length() > 0) bytes += correlationId.length() + 1; + if(replyTo.length() > 0) bytes += replyTo.length() + 1; + if(expiration.length() > 0) bytes += expiration.length() + 1; + if(messageId.length() > 0) bytes += messageId.length() + 1; + if(timestamp != 0) bytes += 8; + if(type.length() > 0) bytes += type.length() + 1; + if(userId.length() > 0) bytes += userId.length() + 1; + if(appId.length() > 0) bytes += appId.length() + 1; + if(clusterId.length() > 0) bytes += clusterId.length() + 1; + + return bytes; +} + +void qpid::framing::BasicHeaderProperties::encode(qpid::framing::Buffer& buffer) const{ + uint16_t flags = getFlags(); + buffer.putShort(flags); + + if(contentType.length() > 0) buffer.putShortString(contentType); + if(contentEncoding.length() > 0) buffer.putShortString(contentEncoding); + if(headers.count() > 0) buffer.putFieldTable(headers); + if(deliveryMode != 0) buffer.putOctet(deliveryMode); + if(priority != 0) buffer.putOctet(priority); + if(correlationId.length() > 0) buffer.putShortString(correlationId); + if(replyTo.length() > 0) buffer.putShortString(replyTo); + if(expiration.length() > 0) buffer.putShortString(expiration); + if(messageId.length() > 0) buffer.putShortString(messageId); + if(timestamp != 0) buffer.putLongLong(timestamp);; + if(type.length() > 0) buffer.putShortString(type); + if(userId.length() > 0) buffer.putShortString(userId); + if(appId.length() > 0) buffer.putShortString(appId); + if(clusterId.length() > 0) buffer.putShortString(clusterId); +} + +void qpid::framing::BasicHeaderProperties::decode(qpid::framing::Buffer& buffer, uint32_t /*size*/){ + uint16_t flags = buffer.getShort(); + if(flags & (1 << 15)) buffer.getShortString(contentType); + if(flags & (1 << 14)) buffer.getShortString(contentEncoding); + if(flags & (1 << 13)) buffer.getFieldTable(headers); + if(flags & (1 << 12)) deliveryMode = DeliveryMode(buffer.getOctet()); + if(flags & (1 << 11)) priority = buffer.getOctet(); + if(flags & (1 << 10)) buffer.getShortString(correlationId); + if(flags & (1 << 9)) buffer.getShortString(replyTo); + if(flags & (1 << 8)) buffer.getShortString(expiration); + if(flags & (1 << 7)) buffer.getShortString(messageId); + if(flags & (1 << 6)) timestamp = buffer.getLongLong(); + if(flags & (1 << 5)) buffer.getShortString(type); + if(flags & (1 << 4)) buffer.getShortString(userId); + if(flags & (1 << 3)) buffer.getShortString(appId); + if(flags & (1 << 2)) buffer.getShortString(clusterId); +} + +uint16_t qpid::framing::BasicHeaderProperties::getFlags() const{ + uint16_t flags(0); + if(contentType.length() > 0) flags |= (1 << 15); + if(contentEncoding.length() > 0) flags |= (1 << 14); + if(headers.count() > 0) flags |= (1 << 13); + if(deliveryMode != 0) flags |= (1 << 12); + if(priority != 0) flags |= (1 << 11); + if(correlationId.length() > 0) flags |= (1 << 10); + if(replyTo.length() > 0) flags |= (1 << 9); + if(expiration.length() > 0) flags |= (1 << 8); + if(messageId.length() > 0) flags |= (1 << 7); + if(timestamp != 0) flags |= (1 << 6); + if(type.length() > 0) flags |= (1 << 5); + if(userId.length() > 0) flags |= (1 << 4); + if(appId.length() > 0) flags |= (1 << 3); + if(clusterId.length() > 0) flags |= (1 << 2); + return flags; +} diff --git a/qpid/cpp/src/framing/BasicHeaderProperties.h b/qpid/cpp/src/framing/BasicHeaderProperties.h new file mode 100644 index 0000000000..a6347b37fd --- /dev/null +++ b/qpid/cpp/src/framing/BasicHeaderProperties.h @@ -0,0 +1,115 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "amqp_types.h" +#include "Buffer.h" +#include "FieldTable.h" +#include "HeaderProperties.h" + +#ifndef _BasicHeaderProperties_ +#define _BasicHeaderProperties_ + +namespace qpid { +namespace framing { + +enum DeliveryMode { TRANSIENT = 1, PERSISTENT = 2}; + +class BasicHeaderProperties : public HeaderProperties +{ + string contentType; + string contentEncoding; + FieldTable headers; + DeliveryMode deliveryMode; + uint8_t priority; + string correlationId; + string replyTo; + string expiration; + string messageId; + uint64_t timestamp; + string type; + string userId; + string appId; + string clusterId; + + uint16_t getFlags() const; + + public: + BasicHeaderProperties(); + virtual ~BasicHeaderProperties(); + virtual uint32_t size() const; + virtual void encode(Buffer& buffer) const; + virtual void decode(Buffer& buffer, uint32_t size); + + virtual uint8_t classId() { return BASIC; } + + string getContentType() const { return contentType; } + string getContentEncoding() const { return contentEncoding; } + FieldTable& getHeaders() { return headers; } + const FieldTable& getHeaders() const { return headers; } + DeliveryMode getDeliveryMode() const { return deliveryMode; } + uint8_t getPriority() const { return priority; } + string getCorrelationId() const {return correlationId; } + string getReplyTo() const { return replyTo; } + string getExpiration() const { return expiration; } + string getMessageId() const {return messageId; } + uint64_t getTimestamp() const { return timestamp; } + string getType() const { return type; } + string getUserId() const { return userId; } + string getAppId() const { return appId; } + string getClusterId() const { return clusterId; } + + void setContentType(const string& _type){ contentType = _type; } + void setContentEncoding(const string& encoding){ contentEncoding = encoding; } + void setHeaders(const FieldTable& _headers){ headers = _headers; } + void setDeliveryMode(DeliveryMode mode){ deliveryMode = mode; } + void setPriority(uint8_t _priority){ priority = _priority; } + void setCorrelationId(const string& _correlationId){ correlationId = _correlationId; } + void setReplyTo(const string& _replyTo){ replyTo = _replyTo;} + void setExpiration(const string& _expiration){ expiration = _expiration; } + void setMessageId(const string& _messageId){ messageId = _messageId; } + void setTimestamp(uint64_t _timestamp){ timestamp = _timestamp; } + void setType(const string& _type){ type = _type; } + void setUserId(const string& _userId){ userId = _userId; } + void setAppId(const string& _appId){appId = _appId; } + void setClusterId(const string& _clusterId){ clusterId = _clusterId; } + + /** \internal + * Template to copy between types like BasicHeaderProperties. + */ + template + static void copy(T& to, const U& from) { + to.setContentType(from.getContentType()); + to.setContentEncoding(from.getContentEncoding()); + to.setHeaders(from.getHeaders()); + to.setDeliveryMode(from.getDeliveryMode()); + to.setPriority(from.getPriority()); + to.setCorrelationId(from.getCorrelationId()); + to.setReplyTo(from.getReplyTo()); + to.setExpiration(from.getExpiration()); + to.setMessageId(from.getMessageId()); + to.setTimestamp(from.getTimestamp()); + to.setType(from.getType()); + to.setUserId(from.getUserId()); + to.setAppId(from.getAppId()); + to.setClusterId(from.getClusterId()); + } +}; +}} +#endif diff --git a/qpid/cpp/src/framing/BodyHandler.cpp b/qpid/cpp/src/framing/BodyHandler.cpp new file mode 100644 index 0000000000..3b389fb5ec --- /dev/null +++ b/qpid/cpp/src/framing/BodyHandler.cpp @@ -0,0 +1,60 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../QpidError.h" +#include "BodyHandler.h" +#include "AMQRequestBody.h" +#include "AMQResponseBody.h" +#include "AMQMethodBody.h" +#include "AMQHeaderBody.h" +#include "AMQContentBody.h" +#include "AMQHeartbeatBody.h" + +using namespace qpid::framing; +using namespace boost; + +BodyHandler::~BodyHandler() {} + +void BodyHandler::handleBody(shared_ptr body) { + switch(body->type()) + { + case REQUEST_BODY: + handleRequest(shared_polymorphic_cast(body)); + break; + case RESPONSE_BODY: + handleResponse(shared_polymorphic_cast(body)); + break; + case METHOD_BODY: + handleMethod(shared_polymorphic_cast(body)); + break; + case HEADER_BODY: + handleHeader(shared_polymorphic_cast(body)); + break; + case CONTENT_BODY: + handleContent(shared_polymorphic_cast(body)); + break; + case HEARTBEAT_BODY: + handleHeartbeat(shared_polymorphic_cast(body)); + break; + default: + QPID_ERROR(PROTOCOL_ERROR, "Unknown frame type "+body->type()); + } +} + diff --git a/qpid/cpp/src/framing/BodyHandler.h b/qpid/cpp/src/framing/BodyHandler.h new file mode 100644 index 0000000000..cb3f0997b0 --- /dev/null +++ b/qpid/cpp/src/framing/BodyHandler.h @@ -0,0 +1,61 @@ +#ifndef _BodyHandler_ +#define _BodyHandler_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "Requester.h" +#include "Responder.h" + +namespace qpid { +namespace framing { + +class AMQRequestBody; +class AMQResponseBody; +class AMQMethodBody; +class AMQHeaderBody; +class AMQContentBody; +class AMQHeartbeatBody; + +/** + * Interface to handle incoming frame bodies. + * Derived classes provide logic for each frame type. + */ +class BodyHandler { + public: + virtual ~BodyHandler(); + virtual void handleBody(boost::shared_ptr body); + + protected: + virtual void handleRequest(boost::shared_ptr) = 0; + virtual void handleResponse(boost::shared_ptr) = 0; + virtual void handleMethod(boost::shared_ptr) = 0; + virtual void handleHeader(boost::shared_ptr) = 0; + virtual void handleContent(boost::shared_ptr) = 0; + virtual void handleHeartbeat(boost::shared_ptr) = 0; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/framing/Buffer.cpp b/qpid/cpp/src/framing/Buffer.cpp new file mode 100644 index 0000000000..2a14e854d0 --- /dev/null +++ b/qpid/cpp/src/framing/Buffer.cpp @@ -0,0 +1,183 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "Buffer.h" +#include "FramingContent.h" +#include "FieldTable.h" + +qpid::framing::Buffer::Buffer(uint32_t _size) : size(_size), owner(true), position(0), limit(_size){ + data = new char[size]; +} + +qpid::framing::Buffer::Buffer(char* _data, uint32_t _size) : size(_size), owner(false), data(_data), position(0), limit(_size){ +} + +qpid::framing::Buffer::~Buffer(){ + if(owner) delete[] data; +} + +void qpid::framing::Buffer::flip(){ + limit = position; + position = 0; +} + +void qpid::framing::Buffer::clear(){ + limit = size; + position = 0; +} + +void qpid::framing::Buffer::compact(){ + uint32_t p = limit - position; + //copy p chars from position to 0 + memmove(data, data + position, p); + limit = size; + position = p; +} + +void qpid::framing::Buffer::record(){ + r_position = position; + r_limit = limit; +} + +void qpid::framing::Buffer::restore(){ + position = r_position; + limit = r_limit; +} + +uint32_t qpid::framing::Buffer::available(){ + return limit - position; +} + +char* qpid::framing::Buffer::start(){ + return data + position; +} + +void qpid::framing::Buffer::move(uint32_t bytes){ + position += bytes; +} + +void qpid::framing::Buffer::putOctet(uint8_t i){ + data[position++] = i; +} + +void qpid::framing::Buffer::putShort(uint16_t i){ + uint16_t b = i; + data[position++] = (uint8_t) (0xFF & (b >> 8)); + data[position++] = (uint8_t) (0xFF & b); +} + +void qpid::framing::Buffer::putLong(uint32_t i){ + 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 qpid::framing::Buffer::putLongLong(uint64_t i){ + uint32_t hi = i >> 32; + uint32_t lo = i; + putLong(hi); + putLong(lo); +} + +uint8_t qpid::framing::Buffer::getOctet(){ + return (uint8_t) data[position++]; +} + +uint16_t qpid::framing::Buffer::getShort(){ + uint16_t hi = (unsigned char) data[position++]; + hi = hi << 8; + hi |= (unsigned char) data[position++]; + return hi; +} + +uint32_t qpid::framing::Buffer::getLong(){ + 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 qpid::framing::Buffer::getLongLong(){ + uint64_t hi = getLong(); + uint64_t lo = getLong(); + hi = hi << 32; + return hi | lo; +} + + +void qpid::framing::Buffer::putShortString(const string& s){ + uint8_t len = s.length(); + putOctet(len); + s.copy(data + position, len); + position += len; +} + +void qpid::framing::Buffer::putLongString(const string& s){ + uint32_t len = s.length(); + putLong(len); + s.copy(data + position, len); + position += len; +} + +void qpid::framing::Buffer::getShortString(string& s){ + uint8_t len = getOctet(); + s.assign(data + position, len); + position += len; +} + +void qpid::framing::Buffer::getLongString(string& s){ + uint32_t len = getLong(); + s.assign(data + position, len); + position += len; +} + +void qpid::framing::Buffer::putFieldTable(const FieldTable& t){ + t.encode(*this); +} + +void qpid::framing::Buffer::getFieldTable(FieldTable& t){ + t.decode(*this); +} + +void qpid::framing::Buffer::putContent(const Content& c){ + c.encode(*this); +} + +void qpid::framing::Buffer::getContent(Content& c){ + c.decode(*this); +} + +void qpid::framing::Buffer::putRawData(const string& s){ + uint32_t len = s.length(); + s.copy(data + position, len); + position += len; +} + +void qpid::framing::Buffer::getRawData(string& s, uint32_t len){ + s.assign(data + position, len); + position += len; +} diff --git a/qpid/cpp/src/framing/Buffer.h b/qpid/cpp/src/framing/Buffer.h new file mode 100644 index 0000000000..e1a3fb065a --- /dev/null +++ b/qpid/cpp/src/framing/Buffer.h @@ -0,0 +1,86 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "amqp_types.h" + +#ifndef _Buffer_ +#define _Buffer_ + +namespace qpid { +namespace framing { + +class Content; +class FieldTable; + +class Buffer +{ + const uint32_t size; + const bool owner;//indicates whether the data is owned by this instance + char* data; + uint32_t position; + uint32_t limit; + uint32_t r_position; + uint32_t r_limit; + +public: + + Buffer(uint32_t size); + Buffer(char* data, uint32_t size); + ~Buffer(); + + void flip(); + void clear(); + void compact(); + void record(); + void restore(); + uint32_t available(); + char* start(); + void move(uint32_t bytes); + + void putOctet(uint8_t i); + void putShort(uint16_t i); + void putLong(uint32_t i); + void putLongLong(uint64_t i); + + uint8_t getOctet(); + uint16_t getShort(); + uint32_t getLong(); + uint64_t getLongLong(); + + void putShortString(const string& s); + void putLongString(const string& s); + void getShortString(string& s); + void getLongString(string& s); + + void putFieldTable(const FieldTable& t); + void getFieldTable(FieldTable& t); + + void putContent(const Content& c); + void getContent(Content& c); + + void putRawData(const string& s); + void getRawData(string& s, uint32_t size); + +}; + +}} // namespace qpid::framing + + +#endif diff --git a/qpid/cpp/src/framing/ChannelAdapter.cpp b/qpid/cpp/src/framing/ChannelAdapter.cpp new file mode 100644 index 0000000000..99a14f08fb --- /dev/null +++ b/qpid/cpp/src/framing/ChannelAdapter.cpp @@ -0,0 +1,99 @@ +/* + * + * 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 "ChannelAdapter.h" +#include "AMQFrame.h" +#include "../Exception.h" + +using boost::format; + +namespace qpid { +namespace framing { + +void ChannelAdapter::init( + ChannelId i, OutputHandler& o, ProtocolVersion v) +{ + assertChannelNotOpen(); + id = i; + out = &o; + version = v; +} + +RequestId ChannelAdapter::send(AMQBody::shared_ptr body) { + RequestId result = 0; + assertChannelOpen(); + switch (body->type()) { + case REQUEST_BODY: { + AMQRequestBody::shared_ptr request = + boost::shared_polymorphic_downcast(body); + requester.sending(request->getData()); + result = request->getData().requestId; + break; + } + case RESPONSE_BODY: { + AMQResponseBody::shared_ptr response = + boost::shared_polymorphic_downcast(body); + responder.sending(response->getData()); + break; + } + } + out->send(new AMQFrame(getVersion(), getId(), body)); + return result; +} + +void ChannelAdapter::handleRequest(AMQRequestBody::shared_ptr request) { + assertMethodOk(*request); + AMQRequestBody::Data& requestData = request->getData(); + responder.received(requestData); + handleMethodInContext(request, MethodContext(this, request)); +} + +void ChannelAdapter::handleResponse(AMQResponseBody::shared_ptr response) { + assertMethodOk(*response); + // TODO aconway 2007-01-30: Consider a response handled on receipt. + // Review - any cases where this is not the case? + AMQResponseBody::Data& responseData = response->getData(); + requester.processed(responseData); + handleMethod(response); +} + +void ChannelAdapter::handleMethod(AMQMethodBody::shared_ptr method) { + assertMethodOk(*method); + handleMethodInContext(method, MethodContext(this, method)); +} + +void ChannelAdapter::assertMethodOk(AMQMethodBody& method) const { + if (getId() != 0 && method.amqpClassId() == ConnectionOpenBody::CLASS_ID) + throw ConnectionException( + 504, format("Connection method on non-0 channel %d.")%getId()); +} + +void ChannelAdapter::assertChannelOpen() const { + if (getId() != 0 && !isOpen()) + throw ConnectionException( + 504, format("Channel %d is not open.")%getId()); +} + +void ChannelAdapter::assertChannelNotOpen() const { + if (getId() != 0 && isOpen()) + throw ConnectionException( + 504, format("Channel %d is already open.") % getId()); +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/src/framing/ChannelAdapter.h b/qpid/cpp/src/framing/ChannelAdapter.h new file mode 100644 index 0000000000..493191d92b --- /dev/null +++ b/qpid/cpp/src/framing/ChannelAdapter.h @@ -0,0 +1,105 @@ +#ifndef _ChannelAdapter_ +#define _ChannelAdapter_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "BodyHandler.h" +#include "Requester.h" +#include "Responder.h" +#include "amqp_types.h" + +namespace qpid { +namespace framing { + +class MethodContext; + +// FIXME aconway 2007-02-20: Rename as ChannelBase or just Channel. + +/** + * Base class for client and broker channels. + * + * - receives frame bodies from the network. + * - Updates request/response data. + * - Dispatches requests with a MethodContext for responses. + * + * send() + * - Updates request/resposne ID data. + * - Forwards frame to the peer. + * + * Thread safety: OBJECT UNSAFE. Instances must not be called + * concurrently. AMQP defines channels to be serialized. + */ +class ChannelAdapter : public BodyHandler { + public: + /** + *@param output Processed frames are forwarded to this handler. + */ + ChannelAdapter(ChannelId id_=0, OutputHandler* out_=0, + ProtocolVersion ver=ProtocolVersion()) + : id(id_), out(out_), version(ver) {} + + /** Initialize the channel adapter. */ + void init(ChannelId, OutputHandler&, ProtocolVersion); + + ChannelId getId() const { return id; } + ProtocolVersion getVersion() const { return version; } + + /** + * Wrap body in a frame and send the frame. + * Takes ownership of body. + */ + RequestId send(AMQBody::shared_ptr body); + RequestId send(AMQBody* body) { return send(AMQBody::shared_ptr(body)); } + + void handleMethod(boost::shared_ptr); + void handleRequest(boost::shared_ptr); + void handleResponse(boost::shared_ptr); + + virtual bool isOpen() const = 0; + + protected: + void assertMethodOk(AMQMethodBody& method) const; + void assertChannelOpen() const; + void assertChannelNotOpen() const; + + virtual void handleMethodInContext( + boost::shared_ptr method, + const MethodContext& context) = 0; + + RequestId getFirstAckRequest() { return requester.getFirstAckRequest(); } + RequestId getLastAckRequest() { return requester.getLastAckRequest(); } + RequestId getNextSendRequestId() { return requester.getNextId(); } + + private: + ChannelId id; + OutputHandler* out; + ProtocolVersion version; + Requester requester; + Responder responder; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/framing/FieldTable.cpp b/qpid/cpp/src/framing/FieldTable.cpp new file mode 100644 index 0000000000..c4881a7c94 --- /dev/null +++ b/qpid/cpp/src/framing/FieldTable.cpp @@ -0,0 +1,150 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "FieldTable.h" +#include "../QpidError.h" +#include "Buffer.h" +#include "Value.h" +#include + +namespace qpid { +namespace framing { + +FieldTable::~FieldTable() {} + +uint32_t FieldTable::size() const { + uint32_t len(4); + for(ValueMap::const_iterator i = values.begin(); i != values.end(); ++i) { + // 2 = shortstr_len_byyte + type_char_byte + len += 2 + (i->first).size() + (i->second)->size(); + } + 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) { + out << "{"; + FieldTable::ValueMap::const_iterator i = t.getMap().begin(); + if (i != t.getMap().end()) out << *i++; + while (i != t.getMap().end()) + { + out << "," << *i++; + } + return out << "}"; +} + +void FieldTable::setString(const std::string& name, const std::string& value){ + values[name] = ValuePtr(new StringValue(value)); +} + +void FieldTable::setInt(const std::string& name, int value){ + values[name] = ValuePtr(new IntegerValue(value)); +} + +void FieldTable::setTimestamp(const std::string& name, uint64_t value){ + values[name] = ValuePtr(new TimeValue(value)); +} + +void FieldTable::setTable(const std::string& name, const FieldTable& value){ + values[name] = ValuePtr(new FieldTableValue(value)); +} + +namespace { +template T default_value() { return T(); } +template <> int default_value() { return 0; } +template <> uint64_t default_value() { return 0; } +} + +template +T FieldTable::getValue(const std::string& name) const +{ + ValueMap::const_iterator i = values.find(name); + if (i == values.end()) return default_value(); + const ValueOps *vt = dynamic_cast*>(i->second.get()); + return vt->getValue(); +} + +std::string FieldTable::getString(const std::string& name) const { + return getValue(name); +} + +int FieldTable::getInt(const std::string& name) const { + return getValue(name); +} + +uint64_t FieldTable::getTimestamp(const std::string& name) const { + return getValue(name); +} + +void FieldTable::getTable(const std::string& name, FieldTable& value) const { + value = getValue(name); +} + +void FieldTable::encode(Buffer& buffer) const{ + buffer.putLong(size() - 4); + for (ValueMap::const_iterator i = values.begin(); i!=values.end(); ++i) { + buffer.putShortString(i->first); + buffer.putOctet(i->second->getType()); + i->second->encode(buffer); + } +} + +void FieldTable::decode(Buffer& buffer){ + uint32_t len = buffer.getLong(); + uint32_t available = buffer.available(); + if (available < len) + THROW_QPID_ERROR(FRAMING_ERROR, "Not enough data for field table."); + uint32_t leftover = available - len; + while(buffer.available() > leftover){ + std::string name; + buffer.getShortString(name); + std::auto_ptr value(Value::decode_value(buffer)); + values[name] = ValuePtr(value.release()); + } +} + + +bool FieldTable::operator==(const FieldTable& x) const { + 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) +{ + values.erase(values.find(name)); +} + +} +} diff --git a/qpid/cpp/src/framing/FieldTable.h b/qpid/cpp/src/framing/FieldTable.h new file mode 100644 index 0000000000..2be3e6d3ff --- /dev/null +++ b/qpid/cpp/src/framing/FieldTable.h @@ -0,0 +1,90 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "amqp_types.h" + +#ifndef _FieldTable_ +#define _FieldTable_ + +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 Value; +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; + + ~FieldTable(); + uint32_t size() const; + int count() const; + void setString(const std::string& name, const std::string& value); + void setInt(const std::string& name, int value); + void setTimestamp(const std::string& name, uint64_t value); + void setTable(const std::string& name, const FieldTable& value); + //void setDecimal(string& name, xxx& value); + std::string getString(const std::string& name) const; + int getInt(const std::string& name) const; + uint64_t getTimestamp(const std::string& name) const; + void getTable(const std::string& name, FieldTable& value) const; + //void getDecimal(string& name, xxx& value); + void erase(const std::string& name); + + void encode(Buffer& buffer) const; + void decode(Buffer& buffer); + + bool operator==(const FieldTable& other) const; + + // TODO aconway 2006-09-26: Yeuch! Rework FieldTable to have + // a map-like interface. + const ValueMap& getMap() const { return values; } + ValueMap& getMap() { return values; } + + private: + friend std::ostream& operator<<(std::ostream& out, const FieldTable& body); + ValueMap values; + template T getValue(const std::string& name) const; +}; + +class FieldNotFoundException{}; +class UnknownFieldName : public FieldNotFoundException{}; +class IncorrectFieldType : public FieldNotFoundException{}; +} +} + + +#endif diff --git a/qpid/cpp/src/framing/FramingContent.cpp b/qpid/cpp/src/framing/FramingContent.cpp new file mode 100644 index 0000000000..1f8f77d129 --- /dev/null +++ b/qpid/cpp/src/framing/FramingContent.cpp @@ -0,0 +1,75 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include + +#include "Buffer.h" +#include "FramingContent.h" +#include "../QpidError.h" +#include + +namespace qpid { +namespace framing { + +Content::Content() : discriminator(0) {} + +Content::Content(uint8_t _discriminator, const string& _value): discriminator(_discriminator), value(_value) { + validate(); +} + +void Content::validate() { + if (discriminator == REFERENCE) { + if(value.empty()) { + THROW_QPID_ERROR(FRAMING_ERROR, "Reference cannot be empty"); + } + }else if (discriminator != INLINE) { + std::stringstream out; + out << "Invalid discriminator: " << (int) discriminator; + THROW_QPID_ERROR(FRAMING_ERROR, out.str()); + } +} + +Content::~Content() {} + +void Content::encode(Buffer& buffer) const { + buffer.putOctet(discriminator); + buffer.putLongString(value); +} + +void Content::decode(Buffer& buffer) { + discriminator = buffer.getOctet(); + buffer.getLongString(value); + validate(); +} + +size_t Content::size() const { + return 1/*discriminator*/ + 4/*for recording size of long string*/ + value.size(); +} + +std::ostream& operator<<(std::ostream& out, const Content& content) { + if (content.discriminator == REFERENCE) { + out << "{REF:" << content.value << "}"; + } else if (content.discriminator == INLINE) { + out << "{INLINE:" << content.value.size() << " bytes}"; + } + return out; +} + +}} // namespace framing::qpid diff --git a/qpid/cpp/src/framing/FramingContent.h b/qpid/cpp/src/framing/FramingContent.h new file mode 100644 index 0000000000..876e90c905 --- /dev/null +++ b/qpid/cpp/src/framing/FramingContent.h @@ -0,0 +1,41 @@ +#ifndef _framing_FramingContent_h +#define _framing_FramingContent_h + +#include + +namespace qpid { +namespace framing { + +enum discriminator_types { INLINE = 0, REFERENCE = 1 }; + +/** + * A representation of the AMQP 'content' data type (used for message + * bodies) which can hold inline data or a reference. + */ +class Content +{ + uint8_t discriminator; + string value; + + void validate(); + + public: + Content(); + Content(uint8_t _discriminator, const string& _value); + ~Content(); + + void encode(Buffer& buffer) const; + void decode(Buffer& buffer); + size_t size() const; + bool isInline() const { return discriminator == INLINE; } + bool isReference() const { return discriminator == REFERENCE; } + const string& getValue() const { return value; } + void setValue(const string& newValue) { value = newValue; } + + friend std::ostream& operator<<(std::ostream&, const Content&); +}; + +}} // namespace qpid::framing + + +#endif /*!_framing_FramingContent_h*/ diff --git a/qpid/cpp/src/framing/HeaderProperties.h b/qpid/cpp/src/framing/HeaderProperties.h new file mode 100644 index 0000000000..ae8b796aa9 --- /dev/null +++ b/qpid/cpp/src/framing/HeaderProperties.h @@ -0,0 +1,46 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "amqp_types.h" +#include "Buffer.h" + +#ifndef _HeaderProperties_ +#define _HeaderProperties_ + +namespace qpid { +namespace framing { + + enum header_classes{BASIC = 60}; + + class HeaderProperties + { + + public: + inline virtual ~HeaderProperties(){} + virtual uint8_t classId() = 0; + virtual uint32_t size() 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/framing/InitiationHandler.cpp b/qpid/cpp/src/framing/InitiationHandler.cpp new file mode 100644 index 0000000000..eceeaf4abc --- /dev/null +++ b/qpid/cpp/src/framing/InitiationHandler.cpp @@ -0,0 +1,24 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "InitiationHandler.h" + +qpid::framing::InitiationHandler::~InitiationHandler() {} diff --git a/qpid/cpp/src/framing/InitiationHandler.h b/qpid/cpp/src/framing/InitiationHandler.h new file mode 100644 index 0000000000..16a6b502e8 --- /dev/null +++ b/qpid/cpp/src/framing/InitiationHandler.h @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include + +#ifndef _InitiationHandler_ +#define _InitiationHandler_ + +#include "ProtocolInitiation.h" + +namespace qpid { +namespace framing { + + class InitiationHandler{ + public: + virtual ~InitiationHandler(); + virtual void initiated(const ProtocolInitiation&) = 0; + }; + +} +} + + +#endif diff --git a/qpid/cpp/src/framing/InputHandler.h b/qpid/cpp/src/framing/InputHandler.h new file mode 100644 index 0000000000..dc6814b849 --- /dev/null +++ b/qpid/cpp/src/framing/InputHandler.h @@ -0,0 +1,39 @@ +#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 "AMQFrame.h" +#include + +namespace qpid { +namespace framing { + +class InputHandler : private boost::noncopyable { + public: + virtual ~InputHandler() {} + virtual void received(AMQFrame* frame) = 0; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/framing/MethodContext.cpp b/qpid/cpp/src/framing/MethodContext.cpp new file mode 100644 index 0000000000..73af73f8e5 --- /dev/null +++ b/qpid/cpp/src/framing/MethodContext.cpp @@ -0,0 +1,31 @@ +/* + * + * 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 "MethodContext.h" +#include "amqp_types.h" +#include "AMQRequestBody.h" + +namespace qpid { +namespace framing { + +RequestId MethodContext::getRequestId() const { + return boost::shared_polymorphic_downcast(methodBody) + ->getRequestId(); +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/src/framing/MethodContext.h b/qpid/cpp/src/framing/MethodContext.h new file mode 100644 index 0000000000..80e4c55d7e --- /dev/null +++ b/qpid/cpp/src/framing/MethodContext.h @@ -0,0 +1,75 @@ +#ifndef _framing_MethodContext_h +#define _framing_MethodContext_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 "OutputHandler.h" +#include "ProtocolVersion.h" + +namespace qpid { +namespace framing { + +class BodyHandler; +class AMQMethodBody; +class ChannelAdapter; + +/** + * Invocation context for an AMQP method. + * + * It provides the method being processed and the channel on which + * it arrived. + * + * All Handler functions take a MethodContext as the last parameter. + */ +struct MethodContext +{ + typedef boost::shared_ptr BodyPtr; + + MethodContext(ChannelAdapter* ch=0, BodyPtr method=BodyPtr()) + : channel(ch), methodBody(method) {} + + /** + * Channel on which the method being processed arrived. + * 0 if the method was constructed by the caller + * rather than received from a channel. + */ + ChannelAdapter* channel; + + /** + * Body of the method being processed. + * It's useful for passing around instead of unpacking all its parameters. + * It's also provides the request ID when constructing a response. + */ + BodyPtr methodBody; + + /** + * Return methodBody's request ID. + * It is an error to call this if methodBody is not a request. + */ + RequestId getRequestId() const; +}; + + +}} // namespace qpid::framing + + + +#endif /*!_framing_MethodContext_h*/ diff --git a/qpid/cpp/src/framing/OutputHandler.h b/qpid/cpp/src/framing/OutputHandler.h new file mode 100644 index 0000000000..9ffd4227d8 --- /dev/null +++ b/qpid/cpp/src/framing/OutputHandler.h @@ -0,0 +1,39 @@ +#ifndef _OutputHandler_ +#define _OutputHandler_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 { +class AMQFrame; + +class OutputHandler : private boost::noncopyable { + public: + virtual ~OutputHandler() {} + virtual void send(AMQFrame* frame) = 0; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/framing/ProtocolInitiation.cpp b/qpid/cpp/src/framing/ProtocolInitiation.cpp new file mode 100644 index 0000000000..a6d1b17f6e --- /dev/null +++ b/qpid/cpp/src/framing/ProtocolInitiation.cpp @@ -0,0 +1,63 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "ProtocolInitiation.h" + +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){ + buffer.putOctet('A'); + buffer.putOctet('M'); + buffer.putOctet('Q'); + buffer.putOctet('P'); + 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 + buffer.getOctet();//class + buffer.getOctet();//instance + version.setMajor(buffer.getOctet()); + version.setMinor(buffer.getOctet()); + return true; + }else{ + return false; + } +} + +//TODO: this should prbably be generated from the spec at some point to keep the version numbers up to date + +}} // namespace qpid::framing diff --git a/qpid/cpp/src/framing/ProtocolInitiation.h b/qpid/cpp/src/framing/ProtocolInitiation.h new file mode 100644 index 0000000000..adfdc8215d --- /dev/null +++ b/qpid/cpp/src/framing/ProtocolInitiation.h @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "amqp_types.h" +#include "Buffer.h" +#include "AMQDataBlock.h" +#include "ProtocolVersion.h" + +#ifndef _ProtocolInitiation_ +#define _ProtocolInitiation_ + +namespace qpid { +namespace framing { + +class ProtocolInitiation : public AMQDataBlock +{ +private: + ProtocolVersion version; + +public: + ProtocolInitiation(); + ProtocolInitiation(uint8_t major, uint8_t minor); + ProtocolInitiation(ProtocolVersion p); + virtual ~ProtocolInitiation(); + virtual void encode(Buffer& buffer); + virtual bool decode(Buffer& buffer); + inline virtual uint32_t size() 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; } +}; + +} +} + + +#endif diff --git a/qpid/cpp/src/framing/ProtocolVersion.cpp b/qpid/cpp/src/framing/ProtocolVersion.cpp new file mode 100644 index 0000000000..7a96bfa925 --- /dev/null +++ b/qpid/cpp/src/framing/ProtocolVersion.cpp @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "ProtocolVersion.h" +#include + +using namespace qpid::framing; + +const std::string ProtocolVersion::toString() const +{ + std::stringstream ss; + ss << major_ << "-" << minor_; + 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_; +} + diff --git a/qpid/cpp/src/framing/ProtocolVersion.h b/qpid/cpp/src/framing/ProtocolVersion.h new file mode 100644 index 0000000000..a2a755397b --- /dev/null +++ b/qpid/cpp/src/framing/ProtocolVersion.h @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _ProtocolVersion_ +#define _ProtocolVersion_ + +#include "amqp_types.h" + +namespace qpid +{ +namespace framing +{ + +class ProtocolVersion +{ +private: + uint8_t major_; + uint8_t minor_; + +public: + ProtocolVersion(uint8_t _major=0, uint8_t _minor=0) + : major_(_major), minor_(_minor) {} + + uint8_t getMajor() const { return major_; } + void setMajor(uint8_t major) { major_ = major; } + uint8_t getMinor() const { return minor_; } + void setMinor(uint8_t minor) { minor_ = minor; } + const std::string toString() const; + + ProtocolVersion& operator=(ProtocolVersion p); + + bool operator==(ProtocolVersion p) const; + bool operator!=(ProtocolVersion p) const { return ! (*this == p); } +}; + +} // namespace framing +} // namespace qpid + + +#endif // ifndef _ProtocolVersion_ diff --git a/qpid/cpp/src/framing/ProtocolVersionException.cpp b/qpid/cpp/src/framing/ProtocolVersionException.cpp new file mode 100644 index 0000000000..b68b3af1f9 --- /dev/null +++ b/qpid/cpp/src/framing/ProtocolVersionException.cpp @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include +#include "ProtocolVersionException.h" + + +using namespace qpid::framing; + +void ProtocolVersionException::init(const std::string& msg) +{ + whatStr = boost::str( + boost::format("ProtocolVersionException: %s found: %s") + % versionFound.toString() % msg); +} + diff --git a/qpid/cpp/src/framing/ProtocolVersionException.h b/qpid/cpp/src/framing/ProtocolVersionException.h new file mode 100644 index 0000000000..0186ed7441 --- /dev/null +++ b/qpid/cpp/src/framing/ProtocolVersionException.h @@ -0,0 +1,56 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _ProtocolVersionException_ +#define _ProtocolVersionException_ + +#include "../Exception.h" +#include "ProtocolVersion.h" +#include +#include + +namespace qpid { +namespace framing { + +class ProtocolVersionException : public qpid::Exception +{ +protected: + ProtocolVersion versionFound; + +public: + ~ProtocolVersionException() throw() {} + + template + ProtocolVersionException( + ProtocolVersion ver, const T& msg) throw () : versionFound(ver) + { init(boost::lexical_cast(msg)); } + + template + ProtocolVersionException(const T& msg) throw () + { init(boost::lexical_cast(msg)); } + + private: + void init(const std::string& msg); +}; + +}} // namespace qpid::framing + +#endif //ifndef _ProtocolVersionException_ diff --git a/qpid/cpp/src/framing/Proxy.cpp b/qpid/cpp/src/framing/Proxy.cpp new file mode 100644 index 0000000000..0b2a882a49 --- /dev/null +++ b/qpid/cpp/src/framing/Proxy.cpp @@ -0,0 +1,32 @@ +/* + * + * 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 "Proxy.h" +#include "ChannelAdapter.h" +#include "ProtocolVersion.h" + +namespace qpid { +namespace framing { + +Proxy::~Proxy() {} + +ProtocolVersion Proxy::getProtocolVersion() const { + return channel.getVersion(); +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/src/framing/Proxy.h b/qpid/cpp/src/framing/Proxy.h new file mode 100644 index 0000000000..8ed46ed748 --- /dev/null +++ b/qpid/cpp/src/framing/Proxy.h @@ -0,0 +1,51 @@ +#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 "ProtocolVersion.h" + +namespace qpid { +namespace framing { + +class ChannelAdapter; +class FieldTable; +class Content; + +/** + * Base class for proxies. + */ +class Proxy +{ + + public: + Proxy(ChannelAdapter& ch) : channel(ch) {} + virtual ~Proxy(); + + ProtocolVersion getProtocolVersion() const; + + protected: + ChannelAdapter& channel; +}; + +}} // namespace qpid::framing + + + +#endif /*!_framing_Proxy_h*/ diff --git a/qpid/cpp/src/framing/Requester.cpp b/qpid/cpp/src/framing/Requester.cpp new file mode 100644 index 0000000000..42cf4c392f --- /dev/null +++ b/qpid/cpp/src/framing/Requester.cpp @@ -0,0 +1,40 @@ +/* + * + * 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 "Requester.h" +#include "../QpidError.h" + +namespace qpid { +namespace framing { + +Requester::Requester() : lastId(0), responseMark(0) {} + +void Requester::sending(AMQRequestBody::Data& request) { + request.requestId = ++lastId; + request.responseMark = responseMark; +} + +void Requester::processed(const AMQResponseBody::Data& response) { + responseMark = response.responseId; + firstAckRequest = response.requestId; + lastAckRequest = firstAckRequest + response.batchOffset; +} + +}} // namespace qpid::framing diff --git a/qpid/cpp/src/framing/Requester.h b/qpid/cpp/src/framing/Requester.h new file mode 100644 index 0000000000..dcc4460041 --- /dev/null +++ b/qpid/cpp/src/framing/Requester.h @@ -0,0 +1,67 @@ +#ifndef _framing_Requester_h +#define _framing_Requester_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 "AMQRequestBody.h" +#include "AMQResponseBody.h" + +namespace qpid { +namespace framing { + +class AMQRequestBody; +class AMQResponseBody; + +/** + * Manage request IDs and the response mark for locally initiated requests. + * + * THREAD UNSAFE: This class is called as frames are sent or received + * sequentially on a connection, so it does not need to be thread safe. + */ +class Requester +{ + public: + Requester(); + + /** Called before sending a request to set request data. */ + void sending(AMQRequestBody::Data&); + + /** Called after processing a response. */ + void processed(const AMQResponseBody::Data&); + + /** Get the next request id to be used. */ + RequestId getNextId() { return lastId + 1; } + /** Get the first request acked by this response */ + RequestId getFirstAckRequest() { return firstAckRequest; } + /** Get the last request acked by this response */ + RequestId getLastAckRequest() { return lastAckRequest; } + + private: + RequestId lastId; + ResponseId responseMark; + ResponseId firstAckRequest; + ResponseId lastAckRequest; +}; + +}} // namespace qpid::framing + + + +#endif /*!_framing_Requester_h*/ diff --git a/qpid/cpp/src/framing/Responder.cpp b/qpid/cpp/src/framing/Responder.cpp new file mode 100644 index 0000000000..e8c8135387 --- /dev/null +++ b/qpid/cpp/src/framing/Responder.cpp @@ -0,0 +1,43 @@ +/* + * + * 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 "Responder.h" +#include "../QpidError.h" + +namespace qpid { +namespace framing { + +Responder::Responder() : lastId(0), responseMark(0) {} + +void Responder::received(const AMQRequestBody::Data& request) { + if (request.responseMark < responseMark || request.responseMark > lastId) + THROW_QPID_ERROR( + PROTOCOL_ERROR, boost::format("Invalid response mark %d.") + %request.responseMark); + responseMark = request.responseMark; +} + +void Responder::sending(AMQResponseBody::Data& response) { + response.responseId = ++lastId; + assert(response.requestId); // Should be already set. + response.batchOffset = 0; +} + +}} // namespace qpid::framing + diff --git a/qpid/cpp/src/framing/Responder.h b/qpid/cpp/src/framing/Responder.h new file mode 100644 index 0000000000..0e1785256b --- /dev/null +++ b/qpid/cpp/src/framing/Responder.h @@ -0,0 +1,61 @@ +#ifndef _framing_Responder_h +#define _framing_Responder_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 "AMQRequestBody.h" +#include "AMQResponseBody.h" + +namespace qpid { +namespace framing { + +/** + * Manage response ids and response mark remotely initianted requests. + * + * THREAD UNSAFE: This class is called as frames are sent or received + * sequentially on a connection, so it does not need to be thread safe. + */ +class Responder +{ + public: + Responder(); + + /** Called after receiving a request. */ + void received(const AMQRequestBody::Data& request); + + /** Called before sending a response to set respose data. */ + void sending(AMQResponseBody::Data& response); + + /** Get the ID of the highest response acknowledged by the peer. */ + ResponseId getResponseMark() { return responseMark; } + + // TODO aconway 2007-01-14: Batching support - store unsent + // Response for equality comparison with subsequent responses. + // + + private: + ResponseId lastId; + ResponseId responseMark; +}; + +}} // namespace qpid::framing + + + +#endif /*!_framing_Responder_h*/ diff --git a/qpid/cpp/src/framing/Value.cpp b/qpid/cpp/src/framing/Value.cpp new file mode 100644 index 0000000000..b5016f3dd0 --- /dev/null +++ b/qpid/cpp/src/framing/Value.cpp @@ -0,0 +1,122 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "Value.h" +#include "Buffer.h" +#include "FieldTable.h" +#include "../QpidError.h" +#include + +namespace qpid { +namespace framing { + +Value::~Value() {} + +void StringValue::encode(Buffer& buffer){ + buffer.putLongString(value); +} +void StringValue::decode(Buffer& buffer){ + buffer.getLongString(value); +} + +void IntegerValue::encode(Buffer& buffer){ + buffer.putLong((uint32_t) value); +} +void IntegerValue::decode(Buffer& buffer){ + value = buffer.getLong(); +} + +void TimeValue::encode(Buffer& buffer){ + buffer.putLongLong(value); +} +void TimeValue::decode(Buffer& buffer){ + value = buffer.getLongLong(); +} + +void DecimalValue::encode(Buffer& buffer){ + buffer.putOctet(value.decimals); + buffer.putLong(value.value); +} +void DecimalValue::decode(Buffer& buffer){ + value = Decimal(buffer.getLong(), buffer.getOctet()); +} + +void FieldTableValue::encode(Buffer& buffer){ + buffer.putFieldTable(value); +} +void FieldTableValue::decode(Buffer& buffer){ + buffer.getFieldTable(value); +} + +std::auto_ptr Value::decode_value(Buffer& buffer) +{ + std::auto_ptr value; + uint8_t type = buffer.getOctet(); + switch(type){ + case 'S': + value.reset(new StringValue()); + break; + case 'I': + value.reset(new IntegerValue()); + break; + case 'D': + value.reset(new DecimalValue()); + break; + case 'T': + value.reset(new TimeValue()); + break; + case 'F': + value.reset(new FieldTableValue()); + break; + + //non-standard types, introduced in java client for JMS compliance + case 'x': + value.reset(new BinaryValue()); + break; + default: + std::stringstream out; + out << "Unknown field table value type: " << type; + THROW_QPID_ERROR(FRAMING_ERROR, out.str()); + } + value->decode(buffer); + return value; +} + +EmptyValue::~EmptyValue() {} + +void EmptyValue::print(std::ostream& out) const +{ + out << ""; +} + +std::ostream& operator<<(std::ostream& out, const Value& v) { + v.print(out); + return out; +} + +std::ostream& operator<<(std::ostream& out, const Decimal& d) +{ + return out << "Decimal(" << d.value << "," << d.decimals << ")"; +} + +}} + + + diff --git a/qpid/cpp/src/framing/Value.h b/qpid/cpp/src/framing/Value.h new file mode 100644 index 0000000000..a6cff8ec88 --- /dev/null +++ b/qpid/cpp/src/framing/Value.h @@ -0,0 +1,171 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "amqp_types.h" +#include "FieldTable.h" + +#ifndef _Value_ +#define _Value_ + +namespace qpid { +namespace framing { + +class Buffer; + +/** + * Represents a decimal value. + * No arithmetic functionality for now, we only care about encoding/decoding. + */ +struct Decimal { + uint32_t value; + uint8_t decimals; + + Decimal(uint32_t value_=0, uint8_t decimals_=0) : value(value_), decimals(decimals_) {} + bool operator==(const Decimal& d) const { + return decimals == d.decimals && value == d.value; + } + bool operator!=(const Decimal& d) const { return !(*this == d); } +}; + +std::ostream& operator<<(std::ostream& out, const Decimal& d); + +/** + * Polymorpic base class for values. + */ +class Value { + public: + virtual ~Value(); + virtual uint32_t size() const = 0; + virtual char getType() const = 0; + virtual void encode(Buffer& buffer) = 0; + virtual void decode(Buffer& buffer) = 0; + virtual bool operator==(const Value&) const = 0; + bool operator!=(const Value& v) const { return !(*this == v); } + virtual void print(std::ostream& out) const = 0; + + /** Create a new value by decoding from the buffer */ + static std::auto_ptr decode_value(Buffer& buffer); +}; + +std::ostream& operator<<(std::ostream& out, const Value& d); + + +/** + * Template for common operations on Value sub-classes. + */ +template +class ValueOps : public Value +{ + protected: + T value; + public: + ValueOps() {} + ValueOps(const T& v) : value(v) {} + const T& getValue() const { return value; } + T& getValue() { return value; } + + virtual bool operator==(const Value& v) const { + const ValueOps* vo = dynamic_cast*>(&v); + if (vo == 0) return false; + else return value == vo->value; + } + + void print(std::ostream& out) const { out << value; } +}; + + +class StringValue : public ValueOps { + public: + StringValue(const std::string& v) : ValueOps(v) {} + StringValue() {} + virtual uint32_t size() const { return 4 + value.length(); } + virtual char getType() const { return 'S'; } + virtual void encode(Buffer& buffer); + virtual void decode(Buffer& buffer); +}; + +class IntegerValue : public ValueOps { + public: + IntegerValue(int v) : ValueOps(v) {} + IntegerValue(){} + virtual uint32_t size() const { return 4; } + virtual char getType() const { return 'I'; } + virtual void encode(Buffer& buffer); + virtual void decode(Buffer& buffer); +}; + +class TimeValue : public ValueOps { + public: + TimeValue(uint64_t v) : ValueOps(v){} + TimeValue(){} + virtual uint32_t size() const { return 8; } + virtual char getType() const { return 'T'; } + virtual void encode(Buffer& buffer); + virtual void decode(Buffer& buffer); +}; + +class DecimalValue : public ValueOps { + public: + DecimalValue(const Decimal& d) : ValueOps(d) {} + DecimalValue(uint32_t value_=0, uint8_t decimals_=0) : + ValueOps(Decimal(value_, decimals_)){} + virtual uint32_t size() const { return 5; } + virtual char getType() const { return 'D'; } + virtual void encode(Buffer& buffer); + virtual void decode(Buffer& buffer); +}; + + +class FieldTableValue : public ValueOps { + public: + FieldTableValue(const FieldTable& v) : ValueOps(v){} + FieldTableValue(){} + virtual uint32_t size() const { return 4 + value.size(); } + virtual char getType() const { return 'F'; } + virtual void encode(Buffer& buffer); + virtual void decode(Buffer& buffer); +}; + +class EmptyValue : public Value { + public: + ~EmptyValue(); + virtual uint32_t size() const { return 0; } + virtual char getType() const { return 0; } + virtual void encode(Buffer& ) {} + virtual void decode(Buffer& ) {} + virtual bool operator==(const Value& v) const { + return dynamic_cast(&v); + } + virtual void print(std::ostream& out) const; +}; + +//non-standard types, introduced in java client for JMS compliance +class BinaryValue : public StringValue { + public: + BinaryValue(const std::string& v) : StringValue(v) {} + BinaryValue() {} + virtual char getType() const { return 'x'; } +}; + +}} // qpid::framing + +#endif diff --git a/qpid/cpp/src/framing/amqp_framing.h b/qpid/cpp/src/framing/amqp_framing.h new file mode 100644 index 0000000000..5cbaedb102 --- /dev/null +++ b/qpid/cpp/src/framing/amqp_framing.h @@ -0,0 +1,36 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "amqp_types.h" +#include "AMQFrame.h" +#include "AMQBody.h" +#include "BodyHandler.h" +#include "AMQMethodBody.h" +#include "AMQHeaderBody.h" +#include "AMQContentBody.h" +#include "AMQHeartbeatBody.h" +#include "AMQP_MethodVersionMap.h" +#include "InputHandler.h" +#include "OutputHandler.h" +#include "InitiationHandler.h" +#include "ProtocolInitiation.h" +#include "BasicHeaderProperties.h" +#include "ProtocolVersion.h" +#include "ProtocolVersionException.h" diff --git a/qpid/cpp/src/framing/amqp_types.h b/qpid/cpp/src/framing/amqp_types.h new file mode 100644 index 0000000000..f0bd0ce427 --- /dev/null +++ b/qpid/cpp/src/framing/amqp_types.h @@ -0,0 +1,57 @@ +#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 + * Type definitions and forward declarations of all types used to + * in AMQP messages. + */ + +#include +#ifdef _WINDOWS +#include "windows.h" +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; +#endif +#ifndef _WINDOWS +#include +#endif + +namespace qpid { +namespace framing { + +using std::string; +typedef uint16_t ChannelId; +typedef uint64_t RequestId; +typedef uint64_t ResponseId; +typedef uint32_t BatchOffset; +typedef uint16_t ClassId; +typedef uint16_t MethodId; +typedef uint16_t ReplyCode; + +// Types represented by classes. +class Content; +class FieldTable; +}} // namespace qpid::framing +#endif diff --git a/qpid/cpp/src/framing/amqp_types_full.h b/qpid/cpp/src/framing/amqp_types_full.h new file mode 100644 index 0000000000..6a24a99d38 --- /dev/null +++ b/qpid/cpp/src/framing/amqp_types_full.h @@ -0,0 +1,36 @@ +#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 + * Type definitions and full declarations of all types used to + * in AMQP messages. + * + * Its 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 do increases compile + * times. + */ + +#include "amqp_types.h" +#include "FramingContent.h" +#include "FieldTable.h" + +#endif /*!_framing_amqp_types_decl_h*/ diff --git a/qpid/cpp/src/gen/Makefile.am b/qpid/cpp/src/gen/Makefile.am new file mode 100644 index 0000000000..470000092c --- /dev/null +++ b/qpid/cpp/src/gen/Makefile.am @@ -0,0 +1,37 @@ +include gen-src.mk + +BUILT_SOURCES = $(generated_sources) $(generated_headers) +pkginclude_HEADERS=$(generated_headers) + +# Distribute the generated sources, at least for now, since +# the generator code is in java. +EXTRA_DIST = $(BUILT_SOURCES) +DISTCLEANFILES = $(BUILT_SOURCES) timestamp gen-src.mk + +# Don't attempt to run the code generator unless configure has set +# CAN_GENERATE_CODE, indicating that the amqp.xml and tools needed +# to run the code generator are available. +# +if CAN_GENERATE_CODE + +gentools_dir = $(srcdir)/../../gentools +spec_dir = $(srcdir)/../../../specs + +# FIXME aconway 2007-01-04: Enabling Basic class until +# new messaging class is ready to replace it. +# spec = $(spec_dir)/amqp.0-9.xml $(spec_dir)/amqp-errata.0-9.xml $(spec_dir)/amqp-nogen.0-9.xml +spec = $(spec_dir)/amqp.0-9.xml $(spec_dir)/amqp-errata.0-9.xml + +gentools_srcdir = $(gentools_dir)/src/org/apache/qpid/gentools + +$(BUILT_SOURCES) timestamp: $(spec) $(java_sources) $(cxx_templates) Makefile.am + rm -f $(generated_sources) + cd $(gentools_srcdir) && rm -f *.class && $(JAVAC) *.java + $(JAVA) -cp $(gentools_dir)/src org.apache.qpid.gentools.Main \ + -c -o . -t $(gentools_dir)/templ.cpp $(spec) + touch timestamp + +gen-src.mk: timestamp + ./make-gen-src-mk.sh $(gentools_dir) $(gentools_srcdir) > $@-t + mv $@-t $@ +endif diff --git a/qpid/cpp/src/gen/make-gen-src-mk.sh b/qpid/cpp/src/gen/make-gen-src-mk.sh new file mode 100755 index 0000000000..08eb8ea134 --- /dev/null +++ b/qpid/cpp/src/gen/make-gen-src-mk.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# Generate the gen-src.mk makefile fragment, to stdout. +# Usage: + +gentools_dir=$1 +gentools_srcdir=$2 + +wildcard() { echo `ls $* 2>/dev/null` ; } + +cat < -#include +#include "broker/Broker.h" +#include "broker/Configuration.h" #include #include #include #include -#include +#include "../config.h" #include static char const* programName = "qpidd"; diff --git a/qpid/cpp/src/shared_ptr.h b/qpid/cpp/src/shared_ptr.h new file mode 100644 index 0000000000..c4d547e5bb --- /dev/null +++ b/qpid/cpp/src/shared_ptr.h @@ -0,0 +1,36 @@ +#ifndef _common_shared_ptr_h +#define _common_shared_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 +#include + +namespace qpid { +/// Import shared_ptr definitions into qpid namespace. +using boost::shared_ptr; +using boost::dynamic_pointer_cast; +using boost::static_pointer_cast; +using boost::const_pointer_cast; +using boost::shared_polymorphic_downcast; +} // namespace qpid + + + +#endif /*!_common_shared_ptr_h*/ diff --git a/qpid/cpp/src/sys/Acceptor.h b/qpid/cpp/src/sys/Acceptor.h new file mode 100644 index 0000000000..f8edb3cef7 --- /dev/null +++ b/qpid/cpp/src/sys/Acceptor.h @@ -0,0 +1,47 @@ +#ifndef _sys_Acceptor_h +#define _sys_Acceptor_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../SharedObject.h" + +namespace qpid { +namespace sys { + +class ConnectionInputHandlerFactory; + +class Acceptor : public qpid::SharedObject +{ + public: + static Acceptor::shared_ptr create(int16_t port, int backlog, int threads, bool trace = false); + virtual ~Acceptor() = 0; + virtual uint16_t getPort() const = 0; + virtual void run(qpid::sys::ConnectionInputHandlerFactory* factory) = 0; + virtual void shutdown() = 0; +}; + +}} + + + +#endif /*!_sys_Acceptor_h*/ diff --git a/qpid/cpp/src/sys/AtomicCount.h b/qpid/cpp/src/sys/AtomicCount.h new file mode 100644 index 0000000000..63670cbf00 --- /dev/null +++ b/qpid/cpp/src/sys/AtomicCount.h @@ -0,0 +1,53 @@ +#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 "ScopedIncrement.h" + +namespace qpid { +namespace sys { + +/** + * Atomic counter. + */ +class AtomicCount : boost::noncopyable { + public: + typedef ScopedDecrement ScopedDecrement; + typedef 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/sys/Condition.h b/qpid/cpp/src/sys/Condition.h new file mode 100644 index 0000000000..455b179683 --- /dev/null +++ b/qpid/cpp/src/sys/Condition.h @@ -0,0 +1,128 @@ +#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. + * + */ + +#include +#include +#include "Mutex.h" +#include "Time.h" + +#ifdef USE_APR +#include +#endif + +namespace qpid { +namespace sys { + +/** + * A condition variable for thread synchronization. + */ +class Condition +{ + public: + inline Condition(); + inline ~Condition(); + inline void wait(Mutex&); + inline bool wait(Mutex&, const Time& absoluteTime); + inline void notify(); + inline void notifyAll(); + + private: +#ifdef USE_APR + apr_thread_cond_t* condition; +#else + pthread_cond_t condition; +#endif +}; + + +// APR ================================================================ +#ifdef USE_APR + +Condition::Condition() { + CHECK_APR_SUCCESS(apr_thread_cond_create(&condition, APRPool::get())); +} + +Condition::~Condition() { + CHECK_APR_SUCCESS(apr_thread_cond_destroy(condition)); +} + +void Condition::wait(Mutex& mutex) { + CHECK_APR_SUCCESS(apr_thread_cond_wait(condition, mutex.mutex)); +} + +bool Condition::wait(Mutex& mutex, const Time& absoluteTime){ + // APR uses microseconds. + apr_status_t status = + apr_thread_cond_timedwait( + condition, mutex.mutex, absoluteTime/TIME_USEC); + if(status != APR_TIMEUP) CHECK_APR_SUCCESS(status); + return status == 0; +} + +void Condition::notify(){ + CHECK_APR_SUCCESS(apr_thread_cond_signal(condition)); +} + +void Condition::notifyAll(){ + CHECK_APR_SUCCESS(apr_thread_cond_broadcast(condition)); +} + +#else +// POSIX ================================================================ + +Condition::Condition() { + QPID_POSIX_THROW_IF(pthread_cond_init(&condition, 0)); +} + +Condition::~Condition() { + QPID_POSIX_THROW_IF(pthread_cond_destroy(&condition)); +} + +void Condition::wait(Mutex& mutex) { + QPID_POSIX_THROW_IF(pthread_cond_wait(&condition, &mutex.mutex)); +} + +bool Condition::wait(Mutex& mutex, const Time& 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; +} + +void Condition::notify(){ + QPID_POSIX_THROW_IF(pthread_cond_signal(&condition)); +} + +void Condition::notifyAll(){ + QPID_POSIX_THROW_IF(pthread_cond_broadcast(&condition)); +} +#endif /*USE_APR*/ + + +}} +#endif /*!_sys_Condition_h*/ diff --git a/qpid/cpp/src/sys/ConnectionInputHandler.h b/qpid/cpp/src/sys/ConnectionInputHandler.h new file mode 100644 index 0000000000..df9bf55f89 --- /dev/null +++ b/qpid/cpp/src/sys/ConnectionInputHandler.h @@ -0,0 +1,45 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _ConnectionInputHandler_ +#define _ConnectionInputHandler_ + +#include "../framing/InputHandler.h" +#include "../framing/InitiationHandler.h" +#include "../framing/ProtocolInitiation.h" +#include "TimeoutHandler.h" + +namespace qpid { +namespace sys { + + class ConnectionInputHandler : + public qpid::framing::InitiationHandler, + public qpid::framing::InputHandler, + public TimeoutHandler + { + public: + virtual void closed() = 0; + }; + +} +} + + +#endif diff --git a/qpid/cpp/src/sys/ConnectionInputHandlerFactory.h b/qpid/cpp/src/sys/ConnectionInputHandlerFactory.h new file mode 100644 index 0000000000..af7d411928 --- /dev/null +++ b/qpid/cpp/src/sys/ConnectionInputHandlerFactory.h @@ -0,0 +1,46 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _ConnectionInputHandlerFactory_ +#define _ConnectionInputHandlerFactory_ + +#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: + virtual ConnectionInputHandler* create(ConnectionOutputHandler* ctxt) = 0; + virtual ~ConnectionInputHandlerFactory(){} +}; + +}} + + +#endif diff --git a/qpid/cpp/src/sys/ConnectionOutputHandler.h b/qpid/cpp/src/sys/ConnectionOutputHandler.h new file mode 100644 index 0000000000..81bbbd1a17 --- /dev/null +++ b/qpid/cpp/src/sys/ConnectionOutputHandler.h @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _ConnectionOutputHandler_ +#define _ConnectionOutputHandler_ + +#include "../framing/OutputHandler.h" + +namespace qpid { +namespace sys { + +/** + * Provides the output handler associated with a connection. + */ +class ConnectionOutputHandler : public virtual qpid::framing::OutputHandler +{ + public: + virtual void close() = 0; +}; + +}} + + +#endif diff --git a/qpid/cpp/src/sys/Module.h b/qpid/cpp/src/sys/Module.h new file mode 100644 index 0000000000..224e1b9c1b --- /dev/null +++ b/qpid/cpp/src/sys/Module.h @@ -0,0 +1,161 @@ +#ifndef _sys_Module_h +#define _sys_Module_h + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../QpidError.h" + +namespace qpid { +namespace sys { +#if USE_APR +#include + typedef apr_dso_handle_t* dso_handle_t; +#else + typedef void* dso_handle_t; +#endif + + template class Module : private boost::noncopyable + { + typedef T* create_t(); + typedef void destroy_t(T*); + + dso_handle_t handle; + destroy_t* destroy; + T* ptr; + + void load(const std::string& name); + void unload(); + void* getSymbol(const std::string& name); + + public: + Module(const std::string& name); + T* operator->(); + T* get(); + ~Module() throw(); + }; + +} +} + +using namespace qpid::sys; + +template Module::Module(const std::string& module) : destroy(0), ptr(0) +{ + load(module); + //TODO: need a better strategy for symbol names to allow multiple + //modules to be loaded without clashes... + + //Note: need the double cast to avoid errors in casting from void* to function pointer with -pedantic + create_t* create = reinterpret_cast(reinterpret_cast(getSymbol("create"))); + destroy = reinterpret_cast(reinterpret_cast(getSymbol("destroy"))); + ptr = create(); +} + +template T* Module::operator->() +{ + return ptr; +} + +template T* Module::get() +{ + return ptr; +} + +template Module::~Module() throw() +{ + try { + if (handle && ptr) { + destroy(ptr); + } + if (handle) unload(); + } catch (std::exception& e) { + std::cout << "Error while destroying module: " << e.what() << std::endl; + } + destroy = 0; + handle = 0; + ptr = 0; +} + +// APR ================================================================ +#if USE_APR + +#include "apr/APRBase.h" +#include "apr/APRPool.h" + +template void Module::load(const std::string& name) +{ + CHECK_APR_SUCCESS(apr_dso_load(&handle, name.c_str(), APRPool::get())); +} + +template void Module::unload() +{ + CHECK_APR_SUCCESS(apr_dso_unload(handle)); +} + +template void* Module::getSymbol(const std::string& name) +{ + apr_dso_handle_sym_t symbol; + CHECK_APR_SUCCESS(apr_dso_sym(&symbol, handle, name.c_str())); + return (void*) symbol; +} + +// POSIX================================================================ +#else + +#include + +template void Module::load(const std::string& name) +{ + dlerror(); + handle = dlopen(name.c_str(), RTLD_NOW); + const char* error = dlerror(); + if (error) { + THROW_QPID_ERROR(INTERNAL_ERROR, error); + } +} + +template void Module::unload() +{ + dlerror(); + dlclose(handle); + const char* error = dlerror(); + if (error) { + THROW_QPID_ERROR(INTERNAL_ERROR, error); + } +} + +template void* Module::getSymbol(const std::string& name) +{ + dlerror(); + void* sym = dlsym(handle, name.c_str()); + const char* error = dlerror(); + if (error) { + THROW_QPID_ERROR(INTERNAL_ERROR, error); + } + return sym; +} + +#endif //if USE_APR + +#endif //ifndef _sys_Module_h + diff --git a/qpid/cpp/src/sys/Monitor.h b/qpid/cpp/src/sys/Monitor.h new file mode 100644 index 0000000000..1b8ae1a527 --- /dev/null +++ b/qpid/cpp/src/sys/Monitor.h @@ -0,0 +1,55 @@ +#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 +#include "Condition.h" + +#ifdef USE_APR +#include +#endif + +namespace qpid { +namespace sys { + +/** + * A monitor is a condition variable and a mutex + */ +class Monitor : public Mutex, public Condition { + public: + using Condition::wait; + inline void wait(); + inline bool wait(const Time& absoluteTime); +}; + + +void Monitor::wait() { + Condition::wait(*this); +} + +bool Monitor::wait(const Time& absoluteTime) { + return Condition::wait(*this, absoluteTime); +} + +}} +#endif /*!_sys_Monitor_h*/ diff --git a/qpid/cpp/src/sys/Mutex.h b/qpid/cpp/src/sys/Mutex.h new file mode 100644 index 0000000000..825b519039 --- /dev/null +++ b/qpid/cpp/src/sys/Mutex.h @@ -0,0 +1,165 @@ +#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. + * + */ + +#ifdef USE_APR +#include +#include "apr/APRBase.h" +#include "apr/APRPool.h" +#else +#include +#include "posix/check.h" +#endif +#include + +namespace qpid { +namespace sys { + +class Condition; + +/** + * 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) { l.lock(); } + ~ScopedLock() { mutex.unlock(); } + private: + L& mutex; +}; + +template +class ScopedUnlock +{ + public: + ScopedUnlock(L& l) : mutex(l) { l.unlock(); } + ~ScopedUnlock() { mutex.lock(); } + private: + L& mutex; +}; + +/** + * Mutex lock. + */ +class Mutex : private boost::noncopyable { + public: + typedef ScopedLock ScopedLock; + typedef ScopedUnlock ScopedUnlock; + + inline Mutex(); + inline ~Mutex(); + inline void lock(); + inline void unlock(); + inline void trylock(); + + protected: +#ifdef USE_APR + apr_thread_mutex_t* mutex; +#else + pthread_mutex_t mutex; +#endif + friend class Condition; +}; + +#ifdef USE_APR +// APR ================================================================ + +Mutex::Mutex() { + CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, APRPool::get())); +} + +Mutex::~Mutex(){ + CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); +} + +void Mutex::lock() { + CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); +} +void Mutex::unlock() { + CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); +} + +void Mutex::trylock() { + CHECK_APR_SUCCESS(apr_thread_mutex_trylock(mutex)); +} + +#else +// POSIX ================================================================ + +/** + * PODMutex is a POD, can be static-initialized with + * PODMutex m = QPID_PODMUTEX_INITIALIZER + */ +struct PODMutex +{ + typedef ScopedLock ScopedLock; + + inline void lock(); + inline void unlock(); + inline void trylock(); + + // Must be public to be a POD: + pthread_mutex_t mutex; +}; + +#define QPID_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } + + +void PODMutex::lock() { + QPID_POSIX_THROW_IF(pthread_mutex_lock(&mutex)); +} +void PODMutex::unlock() { + QPID_POSIX_THROW_IF(pthread_mutex_unlock(&mutex)); +} + +void PODMutex::trylock() { + QPID_POSIX_THROW_IF(pthread_mutex_trylock(&mutex)); +} + + +Mutex::Mutex() { + QPID_POSIX_THROW_IF(pthread_mutex_init(&mutex, 0)); +} + +Mutex::~Mutex(){ + QPID_POSIX_THROW_IF(pthread_mutex_destroy(&mutex)); +} + +void Mutex::lock() { + QPID_POSIX_THROW_IF(pthread_mutex_lock(&mutex)); +} +void Mutex::unlock() { + QPID_POSIX_THROW_IF(pthread_mutex_unlock(&mutex)); +} + +void Mutex::trylock() { + QPID_POSIX_THROW_IF(pthread_mutex_trylock(&mutex)); +} + +#endif // USE_APR + +}} + + + +#endif /*!_sys_Mutex_h*/ diff --git a/qpid/cpp/src/sys/ProducerConsumer.cpp b/qpid/cpp/src/sys/ProducerConsumer.cpp new file mode 100644 index 0000000000..1cf2a79784 --- /dev/null +++ b/qpid/cpp/src/sys/ProducerConsumer.cpp @@ -0,0 +1,141 @@ +/* + * + * 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 "../QpidError.h" +#include "ScopedIncrement.h" +#include "ProducerConsumer.h" + +namespace qpid { +namespace sys { + +// // ================ ProducerConsumer + +ProducerConsumer::ProducerConsumer(size_t init_items) + : items(init_items), waiters(0), shutdownFlag(false) +{} + +void ProducerConsumer::shutdown() { + Mutex::ScopedLock l(monitor); + shutdownFlag = true; + monitor.notifyAll(); + // Wait for waiting consumers to wake up. + while (waiters > 0) + monitor.wait(); +} + +size_t ProducerConsumer::available() const { + Mutex::ScopedLock l(monitor); + return items; +} + +size_t ProducerConsumer::consumers() const { + Mutex::ScopedLock l(monitor); + return waiters; +} + +// ================ Lock + +ProducerConsumer::Lock::Lock(ProducerConsumer& p) + : pc(p), lock(p.monitor), status(INCOMPLETE) {} + +bool ProducerConsumer::Lock::isOk() const { + return !pc.isShutdown() && status==INCOMPLETE; +} + +void ProducerConsumer::Lock::checkOk() const { + assert(!pc.isShutdown()); + assert(status == INCOMPLETE); +} + +ProducerConsumer::Lock::~Lock() { + assert(status != INCOMPLETE || pc.isShutdown()); +} + +void ProducerConsumer::Lock::confirm() { + checkOk(); + status = CONFIRMED; +} + +void ProducerConsumer::Lock::cancel() { + checkOk(); + status = CANCELLED; +} + +// ================ ProducerLock + +ProducerConsumer::ProducerLock::ProducerLock(ProducerConsumer& p) : Lock(p) +{} + + +ProducerConsumer::ProducerLock::~ProducerLock() { + if (status == CONFIRMED) { + pc.items++; + pc.monitor.notify(); // Notify a consumer. + } +} + +// ================ ConsumerLock + +ProducerConsumer::ConsumerLock::ConsumerLock(ProducerConsumer& p) : Lock(p) +{ + if (isOk()) { + ScopedIncrement inc(pc.waiters); + while (pc.items == 0 && !pc.shutdownFlag) { + pc.monitor.wait(); + } + } +} + +ProducerConsumer::ConsumerLock::ConsumerLock( + ProducerConsumer& p, const Time& timeout) : Lock(p) +{ + if (isOk()) { + // Don't wait if timeout==0 + if (timeout == 0) { + if (pc.items == 0) + status = TIMEOUT; + return; + } + else { + Time deadline = now() + timeout; + ScopedIncrement inc(pc.waiters); + while (pc.items == 0 && !pc.shutdownFlag) { + if (!pc.monitor.wait(deadline)) { + status = TIMEOUT; + return; + } + } + } + } +} + +ProducerConsumer::ConsumerLock::~ConsumerLock() { + if (pc.isShutdown()) { + if (pc.waiters == 0) + pc.monitor.notifyAll(); // Notify shutdown thread(s) + } + else if (status==CONFIRMED) { + pc.items--; + if (pc.items > 0) + pc.monitor.notify(); // Notify another consumer. + } +} + + +}} // namespace qpid::sys diff --git a/qpid/cpp/src/sys/ProducerConsumer.h b/qpid/cpp/src/sys/ProducerConsumer.h new file mode 100644 index 0000000000..144f4ed600 --- /dev/null +++ b/qpid/cpp/src/sys/ProducerConsumer.h @@ -0,0 +1,165 @@ +#ifndef _sys_ProducerConsumer_h +#define _sys_ProducerConsumer_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 "../Exception.h" +#include "Monitor.h" + +namespace qpid { +namespace sys { + +/** + * Producer-consumer synchronisation. + * + * Producers increase the number of available items, consumers reduce it. + * Consumers wait till an item is available. Waiting threads can be + * woken for shutdown using shutdown(). + * + * Note: Currently implements unbounded producer-consumer, i.e. no limit + * to available items, producers never block. Can be extended to support + * bounded PC if required. + * + // TODO aconway 2007-02-13: example, from tests. +*/ +class ProducerConsumer +{ + public: + ProducerConsumer(size_t init_items=0); + + ~ProducerConsumer() { shutdown(); } + + /** + * Wake any threads waiting for ProducerLock or ConsumerLock. + *@post No threads are waiting in Producer or Consumer locks. + */ + void shutdown(); + + /** True if queue is shutdown */ + bool isShutdown() { return shutdownFlag; } + + /** Number of items available for consumers */ + size_t available() const; + + /** Number of consumers waiting for items */ + size_t consumers() const; + + /** True if available == 0 */ + bool empty() const { return available() == 0; } + + /** + * Base class for producer and consumer locks. + */ + class Lock : private boost::noncopyable { + public: + + /** + * You must call isOk() after creating a lock to verify its state. + * + *@return true means the lock succeeded. You MUST call either + *confirm() or cancel() before the lock goes out of scope. + * + * false means the lock failed - timed out or the + * ProducerConsumer is shutdown. You should not do anything in + * the scope of the lock. + */ + bool isOk() const; + + /** + * Confirm that an item was produced/consumed. + *@pre isOk() + */ + void confirm(); + + /** + * Cancel the lock to indicate nothing was produced/consumed. + * Note that locks are not actually released until destroyed. + * + *@pre isOk() + */ + void cancel(); + + /** True if this lock experienced a timeout */ + bool isTimedOut() const { return status == TIMEOUT; } + + /** True if we have been shutdown */ + bool isShutdown() const { return pc.isShutdown(); } + + ProducerConsumer& pc; + + protected: + /** Lock status */ + enum Status { INCOMPLETE, CONFIRMED, CANCELLED, TIMEOUT }; + + Lock(ProducerConsumer& p); + ~Lock(); + void checkOk() const; + Mutex::ScopedLock lock; + Status status; + }; + + /** Lock for code that produces items. */ + struct ProducerLock : public Lock { + /** + * Acquire locks to produce an item. + *@post If isOk() the calling thread has exclusive access + * to produce an item. + */ + ProducerLock(ProducerConsumer& p); + + /** Release locks, signal waiting consumers if confirm() was called. */ + ~ProducerLock(); + }; + + /** Lock for code that consumes items */ + struct ConsumerLock : public Lock { + /** + * Wait for an item to consume and acquire locks. + * + *@post If isOk() there is at least one item available and the + *calling thread has exclusive access to consume it. + */ + ConsumerLock(ProducerConsumer& p); + + /** + * Wait up to timeout to acquire lock. + *@post If isOk() caller has a producer lock. + * If isTimedOut() there was a timeout. + * If neither then we were shutdown. + */ + ConsumerLock(ProducerConsumer& p, const Time& timeout); + + /** Release locks */ + ~ConsumerLock(); + }; + + private: + mutable Monitor monitor; + size_t items; + size_t waiters; + bool shutdownFlag; + + friend class Lock; + friend class ProducerLock; + friend class ConsumerLock; +}; + +}} // namespace qpid::sys + +#endif /*!_sys_ProducerConsumer_h*/ diff --git a/qpid/cpp/src/sys/Runnable.cpp b/qpid/cpp/src/sys/Runnable.cpp new file mode 100644 index 0000000000..30122c682f --- /dev/null +++ b/qpid/cpp/src/sys/Runnable.cpp @@ -0,0 +1,32 @@ +/* + * + * 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 "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/sys/Runnable.h b/qpid/cpp/src/sys/Runnable.h new file mode 100644 index 0000000000..fb3927c612 --- /dev/null +++ b/qpid/cpp/src/sys/Runnable.h @@ -0,0 +1,50 @@ +#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 + +namespace qpid { +namespace sys { + +/** + * Interface for objects that can be run, e.g. in a thread. + */ +class Runnable +{ + public: + /** Type to represent a runnable as a Functor */ + typedef boost::function0 Functor; + + 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/sys/ScopedIncrement.h b/qpid/cpp/src/sys/ScopedIncrement.h new file mode 100644 index 0000000000..f14461ddaf --- /dev/null +++ b/qpid/cpp/src/sys/ScopedIncrement.h @@ -0,0 +1,59 @@ +#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 + +namespace qpid { +namespace sys { + +/** Increment counter in constructor and decrement in destructor. */ +template +class ScopedIncrement : boost::noncopyable +{ + public: + ScopedIncrement(T& c) : count(c) { ++count; } + ~ScopedIncrement() { --count; } + private: + T& count; +}; + + +/** 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/sys/ShutdownHandler.h b/qpid/cpp/src/sys/ShutdownHandler.h new file mode 100644 index 0000000000..88baecb5b6 --- /dev/null +++ b/qpid/cpp/src/sys/ShutdownHandler.h @@ -0,0 +1,37 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _ShutdownHandler_ +#define _ShutdownHandler_ + +namespace qpid { +namespace sys { + + class ShutdownHandler + { + public: + virtual void shutdown() = 0; + virtual ~ShutdownHandler(){} + }; + +} +} + +#endif diff --git a/qpid/cpp/src/sys/Socket.h b/qpid/cpp/src/sys/Socket.h new file mode 100644 index 0000000000..ea03222aed --- /dev/null +++ b/qpid/cpp/src/sys/Socket.h @@ -0,0 +1,88 @@ +#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 +#include "Time.h" + +#ifdef USE_APR +#include +#endif + +namespace qpid { +namespace sys { + +class Socket +{ + public: + /** Create an initialized TCP socket */ + static Socket createTcp(); + + /** Create a socket wrapper for descriptor. */ +#ifdef USE_APR + Socket(apr_socket_t* descriptor = 0); +#else + Socket(int descriptor = 0); +#endif + + /** Set timeout for read and write */ + void setTimeout(Time interval); + + void connect(const std::string& host, int port); + + void close(); + + enum { SOCKET_TIMEOUT=-2, SOCKET_EOF=-3 } ErrorCode; + + /** Returns bytes sent or an ErrorCode value < 0. */ + ssize_t send(const void* data, size_t size); + + /** + * Returns bytes received, an ErrorCode value < 0 or 0 + * if the connection closed in an orderly manner. + */ + ssize_t recv(void* data, size_t size); + + /** 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. + */ + int listen(int port = 0, int backlog = 10); + + /** Get file descriptor */ + int fd(); + + private: +#ifdef USE_APR + apr_socket_t* socket; +#else + void init() const; + mutable int socket; // Initialized on demand. +#endif +}; + +}} + + +#endif /*!_sys_Socket_h*/ diff --git a/qpid/cpp/src/sys/Thread.h b/qpid/cpp/src/sys/Thread.h new file mode 100644 index 0000000000..e52f2a1b3e --- /dev/null +++ b/qpid/cpp/src/sys/Thread.h @@ -0,0 +1,142 @@ +#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 "Runnable.h" + +#ifdef USE_APR +#include +#include +#include "apr/APRPool.h" +#include "apr/APRBase.h" +#else +#include "posix/check.h" +#include +#endif + +namespace qpid { +namespace sys { + +class Thread +{ + public: + inline static Thread current(); + inline static void yield(); + + inline Thread(); + inline explicit Thread(qpid::sys::Runnable*); + inline explicit Thread(qpid::sys::Runnable&); + + inline void join(); + + inline long id(); + + private: +#ifdef USE_APR + static void* APR_THREAD_FUNC runRunnable(apr_thread_t* thread, void *data); + inline Thread(apr_thread_t* t); + apr_thread_t* thread; +#else + static void* runRunnable(void* runnable); + inline Thread(pthread_t); + pthread_t thread; +#endif +}; + + +Thread::Thread() : thread(0) {} + +// APR ================================================================ +#ifdef USE_APR + +Thread::Thread(Runnable* runnable) { + CHECK_APR_SUCCESS( + apr_thread_create(&thread, 0, runRunnable, runnable, APRPool::get())); +} + +Thread::Thread(Runnable& runnable) { + CHECK_APR_SUCCESS( + apr_thread_create(&thread, 0, runRunnable, &runnable, APRPool::get())); +} + +void Thread::join(){ + apr_status_t status; + if (thread != 0) + CHECK_APR_SUCCESS(apr_thread_join(&status, thread)); +} + +long Thread::id() { + return long(thread); +} + +Thread::Thread(apr_thread_t* t) : thread(t) {} + +Thread Thread::current(){ + apr_thread_t* thr; + apr_os_thread_t osthr = apr_os_thread_current(); + CHECK_APR_SUCCESS(apr_os_thread_put(&thr, &osthr, APRPool::get())); + return Thread(thr); +} + +void Thread::yield() +{ + apr_thread_yield(); +} + + +// POSIX ================================================================ +#else + +Thread::Thread(Runnable* runnable) { + QPID_POSIX_THROW_IF(pthread_create(&thread, NULL, runRunnable, runnable)); +} + +Thread::Thread(Runnable& runnable) { + QPID_POSIX_THROW_IF(pthread_create(&thread, NULL, runRunnable, &runnable)); +} + +void Thread::join(){ + QPID_POSIX_THROW_IF(pthread_join(thread, 0)); +} + +long Thread::id() { + return long(thread); +} + +Thread::Thread(pthread_t thr) : thread(thr) {} + +Thread Thread::current() { + return Thread(pthread_self()); +} + +void Thread::yield() +{ + QPID_POSIX_THROW_IF(pthread_yield()); +} + + +#endif + +}} + +#endif /*!_sys_Thread_h*/ diff --git a/qpid/cpp/src/sys/ThreadSafeQueue.h b/qpid/cpp/src/sys/ThreadSafeQueue.h new file mode 100644 index 0000000000..ce8b0b1bd9 --- /dev/null +++ b/qpid/cpp/src/sys/ThreadSafeQueue.h @@ -0,0 +1,98 @@ +#ifndef _sys_ThreadSafeQueue_h +#define _sys_ThreadSafeQueue_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 "ProducerConsumer.h" +#include "../Exception.h" + +namespace qpid { +namespace sys { + +/** + * A thread safe queue template. + */ +template > +class ThreadSafeQueue +{ + public: + + ThreadSafeQueue() {} + + /** Push a value onto the back of the queue */ + void push(const T& value) { + ProducerConsumer::ProducerLock producer(pc); + if (producer.isOk()) { + producer.confirm(); + container.push_back(value); + } + } + + /** Pop a value from the front of the queue. Waits till value is available. + *@throw ShutdownException if queue is shutdown while waiting. + */ + T pop() { + ProducerConsumer::ConsumerLock consumer(pc); + if (consumer.isOk()) { + consumer.confirm(); + T value(container.front()); + container.pop_front(); + return value; + } + throw ShutdownException(); + } + + /** + * If a value becomes available within the timeout, set outValue + * and return true. Otherwise return false; + */ + bool pop(T& outValue, const Time& timeout) { + ProducerConsumer::ConsumerLock consumer(pc, timeout); + if (consumer.isOk()) { + consumer.confirm(); + outValue = container.front(); + container.pop_front(); + return true; + } + return false; + } + + /** Interrupt threads waiting in pop() */ + void shutdown() { pc.shutdown(); } + + /** True if queue is shutdown */ + bool isShutdown() { return pc.isShutdown(); } + + /** Size of the queue */ + size_t size() { ProducerConsumer::Lock l(pc); return container.size(); } + + /** True if queue is empty */ + bool empty() { ProducerConsumer::Lock l(pc); return container.empty(); } + + private: + ProducerConsumer pc; + ContainerType container; +}; + +}} // namespace qpid::sys + + + +#endif /*!_sys_ThreadSafeQueue_h*/ diff --git a/qpid/cpp/src/sys/Time.cpp b/qpid/cpp/src/sys/Time.cpp new file mode 100644 index 0000000000..ad6185b966 --- /dev/null +++ b/qpid/cpp/src/sys/Time.cpp @@ -0,0 +1,60 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "Time.h" + +namespace qpid { +namespace sys { + +// APR ================================================================ +#if USE_APR + +Time now() { return apr_time_now() * TIME_USEC; } + +// POSIX================================================================ +#else + +Time now() { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return toTime(ts); +} + +struct timespec toTimespec(const Time& t) { + struct timespec ts; + toTimespec(ts, t); + return ts; +} + +struct timespec& toTimespec(struct timespec& ts, const Time& t) { + ts.tv_sec = t / TIME_SEC; + ts.tv_nsec = t % TIME_SEC; + return ts; +} + +Time toTime(const struct timespec& ts) { + return ts.tv_sec*TIME_SEC + ts.tv_nsec; +} + + +#endif +}} + diff --git a/qpid/cpp/src/sys/Time.h b/qpid/cpp/src/sys/Time.h new file mode 100644 index 0000000000..47609d51df --- /dev/null +++ b/qpid/cpp/src/sys/Time.h @@ -0,0 +1,58 @@ +#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 + +#ifdef USE_APR +#include +#else +#include +#endif + +namespace qpid { +namespace sys { + +/** Time in nanoseconds */ +typedef int64_t Time; + +Time now(); + +/** Nanoseconds per second. */ +const Time TIME_SEC = 1000*1000*1000; +/** Nanoseconds per millisecond */ +const Time TIME_MSEC = 1000*1000; +/** Nanoseconds per microseconds. */ +const Time TIME_USEC = 1000; +/** Nanoseconds per nanosecond. */ +const Time TIME_NSEC = 1; + +#ifndef USE_APR +struct timespec toTimespec(const Time& t); +struct timespec& toTimespec(struct timespec& ts, const Time& t); +Time toTime(const struct timespec& ts); +#endif + +}} + +#endif /*!_sys_Time_h*/ diff --git a/qpid/cpp/src/sys/TimeoutHandler.h b/qpid/cpp/src/sys/TimeoutHandler.h new file mode 100644 index 0000000000..0c10709bbf --- /dev/null +++ b/qpid/cpp/src/sys/TimeoutHandler.h @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _TimeoutHandler_ +#define _TimeoutHandler_ + +namespace qpid { +namespace sys { + + class TimeoutHandler + { + public: + virtual void idleOut() = 0; + virtual void idleIn() = 0; + virtual ~TimeoutHandler(){} + }; + +} +} + + +#endif diff --git a/qpid/cpp/src/sys/apr/APRAcceptor.cpp b/qpid/cpp/src/sys/apr/APRAcceptor.cpp new file mode 100644 index 0000000000..b2535d9e30 --- /dev/null +++ b/qpid/cpp/src/sys/apr/APRAcceptor.cpp @@ -0,0 +1,120 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../Acceptor.h" +#include "../ConnectionInputHandlerFactory.h" +#include "LFProcessor.h" +#include "LFSessionContext.h" +#include "APRBase.h" +#include "APRPool.h" + +namespace qpid { +namespace sys { + +class APRAcceptor : public Acceptor +{ + public: + APRAcceptor(int16_t port, int backlog, int threads, bool trace); + virtual uint16_t getPort() const; + virtual void run(qpid::sys::ConnectionInputHandlerFactory* factory); + virtual void shutdown(); + + private: + void shutdownImpl(); + + private: + int16_t port; + bool trace; + LFProcessor processor; + apr_socket_t* socket; + volatile bool running; + Mutex shutdownLock; +}; + +// Define generic Acceptor::create() to return APRAcceptor. +Acceptor::shared_ptr Acceptor::create(int16_t port, int backlog, int threads, bool trace) +{ + return Acceptor::shared_ptr(new APRAcceptor(port, backlog, threads, trace)); +} +// Must define Acceptor virtual dtor. +Acceptor::~Acceptor() {} + +APRAcceptor::APRAcceptor(int16_t port_, int backlog, int threads, bool trace_) : + port(port_), + trace(trace_), + processor(APRPool::get(), threads, 1000, 5000000), + running(false) +{ + apr_sockaddr_t* address; + CHECK_APR_SUCCESS(apr_sockaddr_info_get(&address, APR_ANYADDR, APR_UNSPEC, port, APR_IPV4_ADDR_OK, APRPool::get())); + CHECK_APR_SUCCESS(apr_socket_create(&socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, APRPool::get())); + CHECK_APR_SUCCESS(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1)); + CHECK_APR_SUCCESS(apr_socket_bind(socket, address)); + CHECK_APR_SUCCESS(apr_socket_listen(socket, backlog)); +} + +uint16_t APRAcceptor::getPort() const { + apr_sockaddr_t* address; + CHECK_APR_SUCCESS(apr_socket_addr_get(&address, APR_LOCAL, socket)); + return address->port; +} + +void APRAcceptor::run(ConnectionInputHandlerFactory* factory) { + running = true; + processor.start(); + std::cout << "Listening on port " << getPort() << "..." << std::endl; + while(running) { + apr_socket_t* client; + apr_status_t status = apr_socket_accept(&client, socket, APRPool::get()); + if(status == APR_SUCCESS){ + //make this socket non-blocking: + CHECK_APR_SUCCESS(apr_socket_timeout_set(client, 0)); + CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_SO_NONBLOCK, 1)); + CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_TCP_NODELAY, 1)); + CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_SO_SNDBUF, 32768)); + CHECK_APR_SUCCESS(apr_socket_opt_set(client, APR_SO_RCVBUF, 32768)); + LFSessionContext* session = new LFSessionContext(APRPool::get(), client, &processor, trace); + session->init(factory->create(session)); + }else{ + Mutex::ScopedLock locker(shutdownLock); + if(running) { + if(status != APR_EINTR){ + std::cout << "ERROR: " << get_desc(status) << std::endl; + } + shutdownImpl(); + } + } + } +} + +void APRAcceptor::shutdown() { + Mutex::ScopedLock locker(shutdownLock); + if (running) + shutdownImpl(); +} + +void APRAcceptor::shutdownImpl() { + running = false; + processor.stop(); + CHECK_APR_SUCCESS(apr_socket_close(socket)); +} + + +}} diff --git a/qpid/cpp/src/sys/apr/APRBase.cpp b/qpid/cpp/src/sys/apr/APRBase.cpp new file mode 100644 index 0000000000..01c8246c91 --- /dev/null +++ b/qpid/cpp/src/sys/apr/APRBase.cpp @@ -0,0 +1,90 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../../QpidError.h" +#include "APRBase.h" + +using namespace qpid::sys; + +APRBase* APRBase::instance = 0; + +APRBase* APRBase::getInstance(){ + if(instance == 0){ + instance = new APRBase(); + } + return instance; +} + + +APRBase::APRBase() : count(0){ + apr_initialize(); + CHECK_APR_SUCCESS(apr_pool_create(&pool, 0)); + CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, pool)); +} + +APRBase::~APRBase(){ + CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); + apr_pool_destroy(pool); + apr_terminate(); +} + +bool APRBase::_increment(){ + bool deleted(false); + CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); + if(this == instance){ + count++; + }else{ + deleted = true; + } + CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); + return !deleted; +} + +void APRBase::_decrement(){ + APRBase* copy = 0; + CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); + if(--count == 0){ + copy = instance; + instance = 0; + } + CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); + if(copy != 0){ + delete copy; + } +} + +void APRBase::increment(){ + int count = 0; + while(count++ < 2 && !getInstance()->_increment()){ + std::cout << "WARNING: APR initialization triggered concurrently with termination." << std::endl; + } +} + +void APRBase::decrement(){ + getInstance()->_decrement(); +} + +std::string qpid::sys::get_desc(apr_status_t status){ + const int size = 50; + char tmp[size]; + return std::string(apr_strerror(status, tmp, size)); +} + diff --git a/qpid/cpp/src/sys/apr/APRBase.h b/qpid/cpp/src/sys/apr/APRBase.h new file mode 100644 index 0000000000..e9dc085c3b --- /dev/null +++ b/qpid/cpp/src/sys/apr/APRBase.h @@ -0,0 +1,78 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _APRBase_ +#define _APRBase_ + +#include +#include +#include +#include "../../QpidError.h" + +namespace qpid { +namespace sys { + + /** + * Use of APR libraries necessitates explicit init and terminate + * calls. Any class using APR libs should obtain the reference to + * this singleton and increment on construction, decrement on + * destruction. This class can then correctly initialise apr + * before the first use and terminate after the last use. + */ + class APRBase{ + static APRBase* instance; + apr_pool_t* pool; + apr_thread_mutex_t* mutex; + int count; + + APRBase(); + ~APRBase(); + static APRBase* getInstance(); + bool _increment(); + void _decrement(); + public: + static void increment(); + static void decrement(); + }; + + //this is also a convenient place for a helper function for error checking: + void check(apr_status_t status, const char* file, const int line); + std::string get_desc(apr_status_t status); + +#define CHECK_APR_SUCCESS(A) qpid::sys::check(A, __FILE__, __LINE__); + +} +} + +// Inlined as it is called *a lot* +void inline qpid::sys::check(apr_status_t status, const char* file, const int line){ + if (status != APR_SUCCESS){ + const int size = 50; + char tmp[size]; + std::string msg(apr_strerror(status, tmp, size)); + throw qpid::QpidError(APR_ERROR + ((int) status), msg, + qpid::SrcLine(file, line)); + } +} + + + + +#endif diff --git a/qpid/cpp/src/sys/apr/APRPool.cpp b/qpid/cpp/src/sys/apr/APRPool.cpp new file mode 100644 index 0000000000..e8b71f6e8a --- /dev/null +++ b/qpid/cpp/src/sys/apr/APRPool.cpp @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "APRPool.h" +#include "APRBase.h" +#include + +using namespace qpid::sys; + +APRPool::APRPool(){ + APRBase::increment(); + CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); +} + +APRPool::~APRPool(){ + apr_pool_destroy(pool); + APRBase::decrement(); +} + +apr_pool_t* APRPool::get() { + return boost::details::pool::singleton_default::instance().pool; +} + diff --git a/qpid/cpp/src/sys/apr/APRPool.h b/qpid/cpp/src/sys/apr/APRPool.h new file mode 100644 index 0000000000..da7661fcfa --- /dev/null +++ b/qpid/cpp/src/sys/apr/APRPool.h @@ -0,0 +1,50 @@ +#ifndef _APRPool_ +#define _APRPool_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 { +/** + * Singleton APR memory pool. + */ +class APRPool : private boost::noncopyable { + public: + APRPool(); + ~APRPool(); + + /** Get singleton instance */ + static apr_pool_t* get(); + + private: + apr_pool_t* pool; +}; + +}} + + + + + +#endif /*!_APRPool_*/ diff --git a/qpid/cpp/src/sys/apr/APRSocket.cpp b/qpid/cpp/src/sys/apr/APRSocket.cpp new file mode 100644 index 0000000000..96dbd132a1 --- /dev/null +++ b/qpid/cpp/src/sys/apr/APRSocket.cpp @@ -0,0 +1,78 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "APRBase.h" +#include "APRSocket.h" +#include +#include + +using namespace qpid::sys; +using namespace qpid::framing; + +APRSocket::APRSocket(apr_socket_t* _socket) : socket(_socket), closed(false){ + +} + +void APRSocket::read(qpid::framing::Buffer& buffer){ + apr_size_t bytes; + bytes = buffer.available(); + apr_status_t s = apr_socket_recv(socket, buffer.start(), &bytes); + buffer.move(bytes); + if(APR_STATUS_IS_TIMEUP(s)){ + //timed out + }else if(APR_STATUS_IS_EOF(s)){ + close(); + } +} + +void APRSocket::write(qpid::framing::Buffer& buffer){ + apr_size_t bytes; + do{ + bytes = buffer.available(); + apr_socket_send(socket, buffer.start(), &bytes); + buffer.move(bytes); + }while(bytes > 0); +} + +void APRSocket::close(){ + if(!closed){ + std::cout << "Closing socket " << socket << "@" << this << std::endl; + CHECK_APR_SUCCESS(apr_socket_close(socket)); + closed = true; + } +} + +bool APRSocket::isOpen() const { + return !closed; +} + +uint8_t APRSocket::read(){ + char data[1]; + apr_size_t bytes = 1; + apr_status_t s = apr_socket_recv(socket, data, &bytes); + if(APR_STATUS_IS_EOF(s) || bytes == 0){ + return 0; + }else{ + return *data; + } +} + +APRSocket::~APRSocket(){ +} diff --git a/qpid/cpp/src/sys/apr/APRSocket.h b/qpid/cpp/src/sys/apr/APRSocket.h new file mode 100644 index 0000000000..323500e61a --- /dev/null +++ b/qpid/cpp/src/sys/apr/APRSocket.h @@ -0,0 +1,48 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _APRSocket_ +#define _APRSocket_ + +#include +#include "../../framing/Buffer.h" + +namespace qpid { +namespace sys { + + class APRSocket + { + apr_socket_t* const socket; + volatile bool closed; + public: + APRSocket(apr_socket_t* socket); + void read(qpid::framing::Buffer& b); + void write(qpid::framing::Buffer& b); + void close(); + bool isOpen() const; + uint8_t read(); + ~APRSocket(); + }; + +} +} + + +#endif diff --git a/qpid/cpp/src/sys/apr/LFProcessor.cpp b/qpid/cpp/src/sys/apr/LFProcessor.cpp new file mode 100644 index 0000000000..691af97c70 --- /dev/null +++ b/qpid/cpp/src/sys/apr/LFProcessor.cpp @@ -0,0 +1,179 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../../QpidError.h" +#include "LFProcessor.h" +#include "APRBase.h" +#include "LFSessionContext.h" + +using namespace qpid::sys; +using qpid::QpidError; + +// TODO aconway 2006-10-12: stopped is read outside locks. +// + +LFProcessor::LFProcessor(apr_pool_t* pool, int _workers, int _size, int _timeout) : + size(_size), + timeout(_timeout), + signalledCount(0), + current(0), + count(0), + workerCount(_workers), + hasLeader(false), + workers(new Thread[_workers]), + stopped(false) +{ + + CHECK_APR_SUCCESS(apr_pollset_create(&pollset, size, pool, APR_POLLSET_THREADSAFE)); +} + + +LFProcessor::~LFProcessor(){ + if (!stopped) stop(); + delete[] workers; + CHECK_APR_SUCCESS(apr_pollset_destroy(pollset)); +} + +void LFProcessor::start(){ + for(int i = 0; i < workerCount; i++){ + workers[i] = Thread(this); + } +} + +void LFProcessor::add(const apr_pollfd_t* const fd){ + CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd)); + Monitor::ScopedLock l(countLock); + sessions.push_back(reinterpret_cast(fd->client_data)); + count++; +} + +void LFProcessor::remove(const apr_pollfd_t* const fd){ + CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd)); + Monitor::ScopedLock l(countLock); + sessions.erase(find(sessions.begin(), sessions.end(), reinterpret_cast(fd->client_data))); + count--; +} + +void LFProcessor::reactivate(const apr_pollfd_t* const fd){ + CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd)); +} + +void LFProcessor::deactivate(const apr_pollfd_t* const fd){ + CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd)); +} + +void LFProcessor::update(const apr_pollfd_t* const fd){ + CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd)); + CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd)); +} + +bool LFProcessor::full(){ + Mutex::ScopedLock locker(countLock); + return count == size; +} + +bool LFProcessor::empty(){ + Mutex::ScopedLock locker(countLock); + return count == 0; +} + +void LFProcessor::poll() { + apr_status_t status = APR_EGENERAL; + do{ + current = 0; + if(!stopped){ + status = apr_pollset_poll(pollset, timeout, &signalledCount, &signalledFDs); + } + }while(status != APR_SUCCESS && !stopped); +} + +void LFProcessor::run(){ + try{ + while(!stopped){ + const apr_pollfd_t* event = 0; + LFSessionContext* session = 0; + { + Monitor::ScopedLock l(leadLock); + waitToLead(); + event = getNextEvent(); + if(!event) return; + session = reinterpret_cast( + event->client_data); + session->startProcessing(); + relinquishLead(); + } + + //process event: + if(event->rtnevents & APR_POLLIN) session->read(); + if(event->rtnevents & APR_POLLOUT) session->write(); + + if(session->isClosed()){ + session->handleClose(); + Monitor::ScopedLock l(countLock); + sessions.erase(find(sessions.begin(),sessions.end(), session)); + count--; + }else{ + session->stopProcessing(); + } + } + }catch(std::exception e){ + std::cout << e.what() << std::endl; + } +} + +void LFProcessor::waitToLead(){ + while(hasLeader && !stopped) leadLock.wait(); + hasLeader = !stopped; +} + +void LFProcessor::relinquishLead(){ + hasLeader = false; + leadLock.notify(); +} + +const apr_pollfd_t* LFProcessor::getNextEvent(){ + while(true){ + if(stopped){ + return 0; + }else if(current < signalledCount){ + //use result of previous poll if one is available + return signalledFDs + (current++); + }else{ + //else poll to get new events + poll(); + } + } +} + +void LFProcessor::stop(){ + stopped = true; + { + Monitor::ScopedLock l(leadLock); + leadLock.notifyAll(); + } + for(int i = 0; i < workerCount; i++){ + workers[i].join(); + } + for(iterator i = sessions.begin(); i < sessions.end(); i++){ + (*i)->shutdown(); + } +} + diff --git a/qpid/cpp/src/sys/apr/LFProcessor.h b/qpid/cpp/src/sys/apr/LFProcessor.h new file mode 100644 index 0000000000..62f6536bde --- /dev/null +++ b/qpid/cpp/src/sys/apr/LFProcessor.h @@ -0,0 +1,121 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _LFProcessor_ +#define _LFProcessor_ + +#include +#include +#include +#include "../Monitor.h" +#include "../Runnable.h" +#include "../Thread.h" + +namespace qpid { +namespace sys { + + class LFSessionContext; + + /** + * This class processes a poll set using the leaders-followers + * pattern for thread synchronization: the leader will poll and on + * the poll returning, it will remove a session, promote a + * follower to leadership, then process the session. + */ + class LFProcessor : private virtual qpid::sys::Runnable + { + typedef std::vector::iterator iterator; + + const int size; + const apr_interval_time_t timeout; + apr_pollset_t* pollset; + int signalledCount; + int current; + const apr_pollfd_t* signalledFDs; + int count; + const int workerCount; + bool hasLeader; + qpid::sys::Thread* workers; + qpid::sys::Monitor leadLock; + qpid::sys::Mutex countLock; + std::vector sessions; + volatile bool stopped; + + const apr_pollfd_t* getNextEvent(); + void waitToLead(); + void relinquishLead(); + void poll(); + virtual void run(); + + public: + LFProcessor(apr_pool_t* pool, int workers, int size, int timeout); + /** + * Add the fd to the poll set. Relies on the client_data being + * an instance of LFSessionContext. + */ + void add(const apr_pollfd_t* const fd); + /** + * Remove the fd from the poll set. + */ + void remove(const apr_pollfd_t* const fd); + /** + * Signal that the fd passed in, already part of the pollset, + * has had its flags altered. + */ + void update(const apr_pollfd_t* const fd); + /** + * Add an fd back to the poll set after deactivation. + */ + void reactivate(const apr_pollfd_t* const fd); + /** + * Temporarily remove the fd from the poll set. Called when processing + * is about to begin. + */ + void deactivate(const apr_pollfd_t* const fd); + /** + * Indicates whether the capacity of this processor has been + * reached (or whether it can still handle further fd's). + */ + bool full(); + /** + * Indicates whether there are any fd's registered. + */ + bool empty(); + /** + * Stop processing. + */ + void stop(); + /** + * Start processing. + */ + void start(); + /** + * Is processing stopped? + */ + bool isStopped(); + + ~LFProcessor(); + }; + +} +} + + +#endif diff --git a/qpid/cpp/src/sys/apr/LFSessionContext.cpp b/qpid/cpp/src/sys/apr/LFSessionContext.cpp new file mode 100644 index 0000000000..a3616d80a4 --- /dev/null +++ b/qpid/cpp/src/sys/apr/LFSessionContext.cpp @@ -0,0 +1,179 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "LFSessionContext.h" +#include "APRBase.h" +#include "../../QpidError.h" +#include + +using namespace qpid::sys; +using namespace qpid::sys; +using namespace qpid::framing; + +LFSessionContext::LFSessionContext(apr_pool_t* _pool, apr_socket_t* _socket, + LFProcessor* const _processor, + bool _debug) : + debug(_debug), + socket(_socket), + initiated(false), + in(65536), + out(65536), + processor(_processor), + processing(false), + closing(false) +{ + + fd.p = _pool; + fd.desc_type = APR_POLL_SOCKET; + fd.reqevents = APR_POLLIN; + fd.client_data = this; + fd.desc.s = _socket; + + out.flip(); +} + +LFSessionContext::~LFSessionContext(){ + +} + +void LFSessionContext::read(){ + socket.read(in); + in.flip(); + if(initiated){ + AMQFrame frame; + try{ + while(frame.decode(in)){ + if(debug) log("RECV", &frame); + handler->received(&frame); + } + }catch(QpidError error){ + std::cout << "Error [" << error.code << "] " << error.msg + << " (" << error.loc.file << ":" << error.loc.line + << ")" << std::endl; + } + }else{ + ProtocolInitiation protocolInit; + if(protocolInit.decode(in)){ + handler->initiated(protocolInit); + initiated = true; + if(debug) std::cout << "INIT [" << &socket << "]" << std::endl; + } + } + in.compact(); +} + +void LFSessionContext::write(){ + bool done = isClosed(); + while(!done){ + if(out.available() > 0){ + socket.write(out); + if(out.available() > 0){ + + //incomplete write, leave flags to receive notification of readiness to write + done = true;//finished processing for now, but write is still in progress + } + }else{ + //do we have any frames to write? + Mutex::ScopedLock l(writeLock); + if(!framesToWrite.empty()){ + out.clear(); + bool encoded(false); + AMQFrame* frame = framesToWrite.front(); + while(frame && out.available() >= frame->size()){ + encoded = true; + frame->encode(out); + if(debug) log("SENT", frame); + delete frame; + framesToWrite.pop(); + frame = framesToWrite.empty() ? 0 : framesToWrite.front(); + } + if(!encoded) THROW_QPID_ERROR(FRAMING_ERROR, "Could not write frame, too large for buffer."); + out.flip(); + }else{ + //reset flags, don't care about writability anymore + fd.reqevents = APR_POLLIN; + done = true; + + if(closing){ + socket.close(); + } + } + } + } +} + +void LFSessionContext::send(AMQFrame* frame){ + Mutex::ScopedLock l(writeLock); + if(!closing){ + framesToWrite.push(frame); + if(!(fd.reqevents & APR_POLLOUT)){ + fd.reqevents |= APR_POLLOUT; + if(!processing){ + processor->update(&fd); + } + } + } +} + +void LFSessionContext::startProcessing(){ + Mutex::ScopedLock l(writeLock); + processing = true; + processor->deactivate(&fd); +} + +void LFSessionContext::stopProcessing(){ + Mutex::ScopedLock l(writeLock); + processor->reactivate(&fd); + processing = false; +} + +void LFSessionContext::close(){ + Mutex::ScopedLock l(writeLock); + closing = true; + if(!processing){ + //allow pending frames to be written to socket + fd.reqevents = APR_POLLOUT; + processor->update(&fd); + } +} + +void LFSessionContext::handleClose(){ + handler->closed(); + std::cout << "Session closed [" << &socket << "]" << std::endl; + delete handler; + delete this; +} + +void LFSessionContext::shutdown(){ + socket.close(); + handleClose(); +} + +void LFSessionContext::init(ConnectionInputHandler* _handler){ + handler = _handler; + processor->add(&fd); +} + +void LFSessionContext::log(const std::string& desc, AMQFrame* const frame){ + Mutex::ScopedLock l(logLock); + std::cout << desc << " [" << &socket << "]: " << *frame << std::endl; +} + +Mutex LFSessionContext::logLock; diff --git a/qpid/cpp/src/sys/apr/LFSessionContext.h b/qpid/cpp/src/sys/apr/LFSessionContext.h new file mode 100644 index 0000000000..99aa39bd6e --- /dev/null +++ b/qpid/cpp/src/sys/apr/LFSessionContext.h @@ -0,0 +1,90 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 _LFSessionContext_ +#define _LFSessionContext_ + +#include + +#include +#include +#include + +#include "../../framing/AMQFrame.h" +#include "../../framing/Buffer.h" +#include "../Monitor.h" +#include "../ConnectionOutputHandler.h" +#include "../ConnectionInputHandler.h" + +#include "APRSocket.h" +#include "LFProcessor.h" + +namespace qpid { +namespace sys { + + +class LFSessionContext : public virtual qpid::sys::ConnectionOutputHandler +{ + const bool debug; + APRSocket socket; + bool initiated; + + qpid::framing::Buffer in; + qpid::framing::Buffer out; + + qpid::sys::ConnectionInputHandler* handler; + LFProcessor* const processor; + + apr_pollfd_t fd; + + std::queue framesToWrite; + qpid::sys::Mutex writeLock; + + bool processing; + bool closing; + + static qpid::sys::Mutex logLock; + void log(const std::string& desc, + qpid::framing::AMQFrame* const frame); + + + public: + LFSessionContext(apr_pool_t* pool, apr_socket_t* socket, + LFProcessor* const processor, + bool debug = false); + virtual ~LFSessionContext(); + virtual void send(qpid::framing::AMQFrame* frame); + virtual void close(); + void read(); + void write(); + void init(qpid::sys::ConnectionInputHandler* handler); + void startProcessing(); + void stopProcessing(); + void handleClose(); + void shutdown(); + inline apr_pollfd_t* const getFd(){ return &fd; } + inline bool isClosed(){ return !socket.isOpen(); } +}; + +} +} + + +#endif diff --git a/qpid/cpp/src/sys/apr/Socket.cpp b/qpid/cpp/src/sys/apr/Socket.cpp new file mode 100644 index 0000000000..1b9c980441 --- /dev/null +++ b/qpid/cpp/src/sys/apr/Socket.cpp @@ -0,0 +1,86 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + + +#include "../Socket.h" +#include "APRBase.h" +#include "APRPool.h" + + +using namespace qpid::sys; + +Socket Socket::createTcp() { + Socket s; + CHECK_APR_SUCCESS( + apr_socket_create( + &s.socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, + APRPool::get())); + return s; +} + +Socket::Socket(apr_socket_t* s) { + socket = s; +} + +void Socket::setTimeout(Time interval) { + apr_socket_timeout_set(socket, interval/TIME_USEC); +} + +void Socket::connect(const std::string& host, int port) { + apr_sockaddr_t* address; + CHECK_APR_SUCCESS( + apr_sockaddr_info_get( + &address, host.c_str(), APR_UNSPEC, port, APR_IPV4_ADDR_OK, + APRPool::get())); + CHECK_APR_SUCCESS(apr_socket_connect(socket, address)); +} + +void Socket::close() { + if (socket == 0) return; + CHECK_APR_SUCCESS(apr_socket_close(socket)); + socket = 0; +} + +ssize_t Socket::send(const void* data, size_t size) +{ + apr_size_t sent = size; + apr_status_t status = + apr_socket_send(socket, reinterpret_cast(data), &sent); + if (APR_STATUS_IS_TIMEUP(status)) return SOCKET_TIMEOUT; + if (APR_STATUS_IS_EOF(status)) return SOCKET_EOF; + CHECK_APR_SUCCESS(status); + return sent; +} + +ssize_t Socket::recv(void* data, size_t size) +{ + apr_size_t received = size; + apr_status_t status = + apr_socket_recv(socket, reinterpret_cast(data), &received); + if (APR_STATUS_IS_TIMEUP(status)) + return SOCKET_TIMEOUT; + if (APR_STATUS_IS_EOF(status)) + return SOCKET_EOF; + CHECK_APR_SUCCESS(status); + return received; +} + + diff --git a/qpid/cpp/src/sys/apr/Thread.cpp b/qpid/cpp/src/sys/apr/Thread.cpp new file mode 100644 index 0000000000..67d2853d9f --- /dev/null +++ b/qpid/cpp/src/sys/apr/Thread.cpp @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "../Thread.h" + +using namespace qpid::sys; +using qpid::sys::Runnable; + +void* APR_THREAD_FUNC Thread::runRunnable(apr_thread_t* thread, void *data) { + reinterpret_cast(data)->run(); + CHECK_APR_SUCCESS(apr_thread_exit(thread, APR_SUCCESS)); + return NULL; +} + + diff --git a/qpid/cpp/src/sys/posix/EventChannel.cpp b/qpid/cpp/src/sys/posix/EventChannel.cpp new file mode 100644 index 0000000000..1d584d6318 --- /dev/null +++ b/qpid/cpp/src/sys/posix/EventChannel.cpp @@ -0,0 +1,325 @@ +/* + * + * 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 + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "../../QpidError.h" +#include "../Monitor.h" + +#include "check.h" +#include "EventChannel.h" + +using namespace std; + + +// Convenience template to zero out a struct. +template struct ZeroStruct : public S { + ZeroStruct() { memset(this, 0, sizeof(*this)); } +}; + +namespace qpid { +namespace sys { + + +/** + * EventHandler wraps an epoll file descriptor. Acts as private + * interface between EventChannel and subclasses. + * + * Also implements Event interface for events that are not associated + * with a file descriptor and are passed via the message queue. + */ +class EventHandler : public Event, private Monitor +{ + public: + EventHandler(int epollSize = 256); + ~EventHandler(); + + int getEpollFd() { return epollFd; } + void epollAdd(int fd, uint32_t epollEvents, Event* event); + void epollMod(int fd, uint32_t epollEvents, Event* event); + void epollDel(int fd); + + void mqPut(Event* event); + Event* mqGet(); + + protected: + // Should never be called, only complete. + void prepare(EventHandler&) { assert(0); } + Event* complete(EventHandler& eh); + + private: + int epollFd; + std::string mqName; + int mqFd; + std::queue mqEvents; +}; + +EventHandler::EventHandler(int epollSize) +{ + epollFd = epoll_create(epollSize); + if (epollFd < 0) throw QPID_POSIX_ERROR(errno); + + // Create a POSIX message queue for non-fd events. + // We write one byte and never read it is always ready for read + // when we add it to epoll. + // + ZeroStruct attr; + attr.mq_maxmsg = 1; + attr.mq_msgsize = 1; + do { + char tmpnam[L_tmpnam]; + tmpnam_r(tmpnam); + mqName = tmpnam + 4; // Skip "tmp/" + mqFd = mq_open( + mqName.c_str(), O_CREAT|O_EXCL|O_RDWR|O_NONBLOCK, S_IRWXU, &attr); + if (mqFd < 0) throw QPID_POSIX_ERROR(errno); + } while (mqFd == EEXIST); // Name already taken, try again. + + static char zero = '\0'; + mq_send(mqFd, &zero, 1, 0); + epollAdd(mqFd, 0, this); +} + +EventHandler::~EventHandler() { + mq_close(mqFd); + mq_unlink(mqName.c_str()); +} + +void EventHandler::mqPut(Event* event) { + ScopedLock l(*this); + assert(event != 0); + mqEvents.push(event); + epollMod(mqFd, EPOLLIN|EPOLLONESHOT, this); +} + +Event* EventHandler::mqGet() { + ScopedLock l(*this); + if (mqEvents.empty()) + return 0; + Event* event = mqEvents.front(); + mqEvents.pop(); + if(!mqEvents.empty()) + epollMod(mqFd, EPOLLIN|EPOLLONESHOT, this); + return event; +} + +void EventHandler::epollAdd(int fd, uint32_t epollEvents, Event* event) +{ + ZeroStruct ee; + ee.data.ptr = event; + ee.events = epollEvents; + if (epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &ee) < 0) + throw QPID_POSIX_ERROR(errno); +} + +void EventHandler::epollMod(int fd, uint32_t epollEvents, Event* event) +{ + ZeroStruct ee; + ee.data.ptr = event; + ee.events = epollEvents; + if (epoll_ctl(epollFd, EPOLL_CTL_MOD, fd, &ee) < 0) + throw QPID_POSIX_ERROR(errno); +} + +void EventHandler::epollDel(int fd) { + if (epoll_ctl(epollFd, EPOLL_CTL_DEL, fd, 0) < 0) + throw QPID_POSIX_ERROR(errno); +} + +Event* EventHandler::complete(EventHandler& eh) +{ + assert(&eh == this); + Event* event = mqGet(); + return event==0 ? 0 : event->complete(eh); +} + +// ================================================================ +// EventChannel + +EventChannel::shared_ptr EventChannel::create() { + return shared_ptr(new EventChannel()); +} + +EventChannel::EventChannel() : handler(new EventHandler()) {} + +EventChannel::~EventChannel() {} + +void EventChannel::postEvent(Event& e) +{ + e.prepare(*handler); +} + +Event* EventChannel::getEvent() +{ + static const int infiniteTimeout = -1; + ZeroStruct epollEvent; + + // Loop until we can complete the event. Some events may re-post + // themselves and return 0 from complete, e.g. partial reads. // + Event* event = 0; + while (event == 0) { + int eventCount = epoll_wait(handler->getEpollFd(), + &epollEvent, 1, infiniteTimeout); + if (eventCount < 0) { + if (errno != EINTR) { + // TODO aconway 2006-11-28: Proper handling/logging of errors. + cerr << BOOST_CURRENT_FUNCTION << " ignoring error " + << PosixError::getMessage(errno) << endl; + assert(0); + } + } + else if (eventCount == 1) { + event = reinterpret_cast(epollEvent.data.ptr); + assert(event != 0); + try { + event = event->complete(*handler); + } + catch (const Exception& e) { + if (event) + event->setError(e); + } + catch (const std::exception& e) { + if (event) + event->setError(e); + } + } + } + return event; +} + +Event::~Event() {} + +void Event::prepare(EventHandler& handler) +{ + handler.mqPut(this); +} + +bool Event::hasError() const { + return error; +} + +void Event::throwIfError() throw (Exception) { + if (hasError()) + error.throwSelf(); +} + +Event* Event::complete(EventHandler&) +{ + return this; +} + +void Event::dispatch() +{ + try { + if (!callback.empty()) + callback(); + } catch (const std::exception&) { + throw; + } catch (...) { + throw QPID_ERROR(INTERNAL_ERROR, "Unknown exception."); + } +} + +void Event::setError(const ExceptionHolder& e) { + error = e; +} + +void ReadEvent::prepare(EventHandler& handler) +{ + handler.epollAdd(descriptor, EPOLLIN | EPOLLONESHOT, this); +} + +ssize_t ReadEvent::doRead() { + ssize_t n = ::read(descriptor, static_cast(buffer) + received, + size - received); + if (n > 0) received += n; + return n; +} + +Event* ReadEvent::complete(EventHandler& handler) +{ + // Read as much as possible without blocking. + ssize_t n = doRead(); + while (n > 0 && received < size) doRead(); + + if (received == size) { + handler.epollDel(descriptor); + received = 0; // Reset for re-use. + return this; + } + else if (n <0 && (errno == EAGAIN)) { + // Keep polling for more. + handler.epollMod(descriptor, EPOLLIN | EPOLLONESHOT, this); + return 0; + } + else { + // Unexpected EOF or error. Throw ENODATA for EOF. + handler.epollDel(descriptor); + received = 0; // Reset for re-use. + throw QPID_POSIX_ERROR((n < 0) ? errno : ENODATA); + } +} + +void WriteEvent::prepare(EventHandler& handler) +{ + handler.epollAdd(descriptor, EPOLLOUT | EPOLLONESHOT, this); +} + +Event* WriteEvent::complete(EventHandler& handler) +{ + ssize_t n = write(descriptor, static_cast(buffer) + written, + size - written); + if (n < 0) throw QPID_POSIX_ERROR(errno); + written += n; + if(written < size) { + // Keep polling. + handler.epollMod(descriptor, EPOLLOUT | EPOLLONESHOT, this); + return 0; + } + written = 0; // Reset for re-use. + handler.epollDel(descriptor); + return this; +} + +void AcceptEvent::prepare(EventHandler& handler) +{ + handler.epollAdd(descriptor, EPOLLIN | EPOLLONESHOT, this); +} + +Event* AcceptEvent::complete(EventHandler& handler) +{ + handler.epollDel(descriptor); + accepted = ::accept(descriptor, 0, 0); + if (accepted < 0) throw QPID_POSIX_ERROR(errno); + return this; +} + +}} diff --git a/qpid/cpp/src/sys/posix/EventChannel.h b/qpid/cpp/src/sys/posix/EventChannel.h new file mode 100644 index 0000000000..4177839d00 --- /dev/null +++ b/qpid/cpp/src/sys/posix/EventChannel.h @@ -0,0 +1,176 @@ +#ifndef _sys_EventChannel_h +#define _sys_EventChannel_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 "../../SharedObject.h" +#include "../../ExceptionHolder.h" +#include +#include + +namespace qpid { +namespace sys { + +class Event; +class EventHandler; +class EventChannel; + +/** + * Base class for all Events. + */ +class Event +{ + public: + /** Type for callback when event is dispatched */ + typedef boost::function0 Callback; + + /** + * Create an event with optional callback. + * Instances of Event are sent directly through the channel. + * Derived classes define additional waiting behaviour. + *@param cb A callback functor that is invoked when dispatch() is called. + */ + Event(Callback cb = 0) : callback(cb) {} + + virtual ~Event(); + + /** Call the callback provided to the constructor, if any. */ + void dispatch(); + + /** True if there was an error processing this event */ + bool hasError() const; + + /** If hasError() throw the corresponding exception. */ + void throwIfError() throw(Exception); + + protected: + virtual void prepare(EventHandler&); + virtual Event* complete(EventHandler&); + void setError(const ExceptionHolder& e); + + Callback callback; + ExceptionHolder error; + + friend class EventChannel; + friend class EventHandler; +}; + +template +class IOEvent : public Event { + public: + void getDescriptor() const { return descriptor; } + size_t getSize() const { return size; } + BufT getBuffer() const { return buffer; } + + protected: + IOEvent(int fd, Callback cb, size_t sz, BufT buf) : + Event(cb), descriptor(fd), buffer(buf), size(sz) {} + + int descriptor; + BufT buffer; + size_t size; +}; + +/** Asynchronous read event */ +class ReadEvent : public IOEvent +{ + public: + explicit ReadEvent(int fd=-1, void* buf=0, size_t sz=0, Callback cb=0) : + IOEvent(fd, cb, sz, buf), received(0) {} + + private: + void prepare(EventHandler&); + Event* complete(EventHandler&); + ssize_t doRead(); + + size_t received; +}; + +/** Asynchronous write event */ +class WriteEvent : public IOEvent +{ + public: + explicit WriteEvent(int fd=-1, const void* buf=0, size_t sz=0, + Callback cb=0) : + IOEvent(fd, cb, sz, buf), written(0) {} + + protected: + void prepare(EventHandler&); + Event* complete(EventHandler&); + + private: + ssize_t doWrite(); + size_t written; +}; + +/** Asynchronous socket accept event */ +class AcceptEvent : public Event +{ + public: + /** Accept a connection on fd. */ + explicit AcceptEvent(int fd=-1, Callback cb=0) : + Event(cb), descriptor(fd), accepted(0) {} + + /** Get descriptor for server socket */ + int getAcceptedDesscriptor() const { return accepted; } + + private: + void prepare(EventHandler&); + Event* complete(EventHandler&); + + int descriptor; + int accepted; +}; + + +class QueueSet; + +/** + * Channel to post and wait for events. + */ +class EventChannel : public qpid::SharedObject +{ + public: + static shared_ptr create(); + + ~EventChannel(); + + /** Post an event to the channel. */ + void postEvent(Event& event); + + /** Post an event to the channel. Must not be 0. */ + void postEvent(Event* event) { postEvent(*event); } + + /** + * Wait for the next complete event. + *@return Pointer to event. Will never return 0. + */ + Event* getEvent(); + + private: + EventChannel(); + boost::shared_ptr handler; +}; + + +}} + + + +#endif /*!_sys_EventChannel_h*/ diff --git a/qpid/cpp/src/sys/posix/EventChannelAcceptor.cpp b/qpid/cpp/src/sys/posix/EventChannelAcceptor.cpp new file mode 100644 index 0000000000..94dda99d78 --- /dev/null +++ b/qpid/cpp/src/sys/posix/EventChannelAcceptor.cpp @@ -0,0 +1,149 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../ConnectionOutputHandler.h" +#include "../ConnectionInputHandler.h" +#include "../ConnectionInputHandlerFactory.h" +#include "../Acceptor.h" +#include "../Socket.h" +#include "../../framing/Buffer.h" +#include "../../framing/AMQFrame.h" +#include "../../Exception.h" + +#include "EventChannelConnection.h" + +namespace qpid { +namespace sys { + +using namespace qpid::framing; +using namespace std; + +class EventChannelAcceptor : public Acceptor { + public: + + + EventChannelAcceptor( + int16_t port_, int backlog, int nThreads, bool trace_ + ); + + int getPort() const; + + void run(ConnectionInputHandlerFactory& factory); + + void shutdown(); + + private: + + void accept(); + + Mutex lock; + Socket listener; + const int port; + const bool isTrace; + bool isRunning; + boost::ptr_vector connections; + AcceptEvent acceptEvent; + ConnectionInputHandlerFactory* factory; + bool isShutdown; + EventChannelThreads::shared_ptr threads; +}; + +Acceptor::shared_ptr Acceptor::create( + int16_t port, int backlog, int threads, bool trace) +{ + return Acceptor::shared_ptr( + new EventChannelAcceptor(port, backlog, threads, trace)); +} + +// Must define Acceptor virtual dtor. +Acceptor::~Acceptor() {} + +EventChannelAcceptor::EventChannelAcceptor( + int16_t port_, int backlog, int nThreads, bool trace_ +) : listener(Socket::createTcp()), + port(listener.listen(int(port_), backlog)), + isTrace(trace_), + isRunning(false), + acceptEvent(listener.fd(), + boost::bind(&EventChannelAcceptor::accept, this)), + factory(0), + isShutdown(false), + threads(EventChannelThreads::create(EventChannel::create(), nThreads)) +{ } + +int EventChannelAcceptor::getPort() const { + return port; // Immutable no need for lock. +} + +void EventChannelAcceptor::run(ConnectionInputHandlerFactory& f) { + { + Mutex::ScopedLock l(lock); + if (!isRunning && !isShutdown) { + isRunning = true; + factory = &f; + threads->post(acceptEvent); + } + } + threads->join(); // Wait for shutdown. +} + +void EventChannelAcceptor::shutdown() { + bool doShutdown = false; + { + Mutex::ScopedLock l(lock); + doShutdown = !isShutdown; // I'm the shutdown thread. + isShutdown = true; + } + if (doShutdown) { + ::close(acceptEvent.getDescriptor()); + threads->shutdown(); + for_each(connections.begin(), connections.end(), + boost::bind(&EventChannelConnection::close, _1)); + } + threads->join(); +} + +void EventChannelAcceptor::accept() +{ + // No lock, we only post one accept event at a time. + if (isShutdown) + return; + if (acceptEvent.getException()) { + Exception::log(*acceptEvent.getException(), + "EventChannelAcceptor::accept"); + shutdown(); + return; + } + // TODO aconway 2006-11-29: Need to reap closed connections also. + int fd = acceptEvent.getAcceptedDesscriptor(); + connections.push_back( + new EventChannelConnection(threads, *factory, fd, fd, isTrace)); + threads->post(acceptEvent); // Keep accepting. +} + +}} // namespace qpid::sys diff --git a/qpid/cpp/src/sys/posix/EventChannelConnection.cpp b/qpid/cpp/src/sys/posix/EventChannelConnection.cpp new file mode 100644 index 0000000000..cb6506bdde --- /dev/null +++ b/qpid/cpp/src/sys/posix/EventChannelConnection.cpp @@ -0,0 +1,229 @@ +/* + * + * 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 + +#include "EventChannelConnection.h" +#include "../ConnectionInputHandlerFactory.h" +#include "../../QpidError.h" + +using namespace std; +using namespace qpid; +using namespace qpid::framing; + +namespace qpid { +namespace sys { + +const size_t EventChannelConnection::bufferSize = 65536; + +EventChannelConnection::EventChannelConnection( + EventChannelThreads::shared_ptr threads_, + ConnectionInputHandlerFactory& factory_, + int rfd, + int wfd, + bool isTrace_ +) : + readFd(rfd), + writeFd(wfd ? wfd : rfd), + readCallback(boost::bind(&EventChannelConnection::closeOnException, + this, &EventChannelConnection::endInitRead)), + + isWriting(false), + isClosed(false), + threads(threads_), + handler(factory_.create(this)), + in(bufferSize), + out(bufferSize), + isTrace(isTrace_) +{ + BOOST_ASSERT(readFd > 0); + BOOST_ASSERT(writeFd > 0); + closeOnException(&EventChannelConnection::startRead); +} + + +void EventChannelConnection::send(std::auto_ptr frame) { + { + Monitor::ScopedLock lock(monitor); + assert(frame.get()); + writeFrames.push_back(frame.release()); + } + closeOnException(&EventChannelConnection::startWrite); +} + +void EventChannelConnection::close() { + { + Monitor::ScopedLock lock(monitor); + if (isClosed) + return; + isClosed = true; + } + ::close(readFd); + ::close(writeFd); + { + Monitor::ScopedLock lock(monitor); + while (busyThreads > 0) + monitor.wait(); + } + handler->closed(); +} + +void EventChannelConnection::closeNoThrow() { + Exception::tryCatchLog( + boost::bind(&EventChannelConnection::close, this), + false, + "Exception closing channel" + ); +} + +/** + * Call f in a try/catch block and close the connection if + * an exception is thrown. + */ +void EventChannelConnection::closeOnException(MemberFnPtr f) +{ + try { + Exception::tryCatchLog( + boost::bind(f, this), + "Closing connection due to exception" + ); + return; + } catch (...) { + // Exception was already logged by tryCatchLog + closeNoThrow(); + } +} + +// Post the write event. +// Always called inside closeOnException. +// Called by endWrite and send, but only one thread writes at a time. +// +void EventChannelConnection::startWrite() { + FrameQueue::auto_type frame; + { + Monitor::ScopedLock lock(monitor); + // Stop if closed or a write event is already in progress. + if (isClosed || isWriting) + return; + if (writeFrames.empty()) { + isWriting = false; + return; + } + isWriting = true; + frame = writeFrames.pop_front(); + } + // No need to lock here - only one thread can be writing at a time. + out.clear(); + if (isTrace) + cout << "Send on socket " << writeFd << ": " << *frame << endl; + frame->encode(out); + out.flip(); + writeEvent = WriteEvent( + writeFd, out.start(), out.available(), + boost::bind(&EventChannelConnection::closeOnException, + this, &EventChannelConnection::endWrite)); + threads->post(writeEvent); +} + +// ScopedBusy ctor increments busyThreads. +// dtor decrements and calls monitor.notifyAll if it reaches 0. +// +struct EventChannelConnection::ScopedBusy : public AtomicCount::ScopedIncrement +{ + ScopedBusy(EventChannelConnection& ecc) + : AtomicCount::ScopedIncrement( + ecc.busyThreads, boost::bind(&Monitor::notifyAll, &ecc.monitor)) + {} +}; + +// Write event completed. +// Always called by a channel thread inside closeOnException. +// +void EventChannelConnection::endWrite() { + ScopedBusy(*this); + { + Monitor::ScopedLock lock(monitor); + isWriting = false; + if (isClosed) + return; + writeEvent.throwIfException(); + } + // Check if there's more in to write in the write queue. + startWrite(); +} + + +// Post the read event. +// Always called inside closeOnException. +// Called from ctor and end[Init]Read, so only one call at a time +// is possible since we only post one read event at a time. +// +void EventChannelConnection::startRead() { + // Non blocking read, as much as we can swallow. + readEvent = ReadEvent( + readFd, in.start(), in.available(), readCallback,true); + threads->post(readEvent); +} + +// Completion of initial read, expect protocolInit. +// Always called inside closeOnException in channel thread. +// Only called by one thread at a time. +void EventChannelConnection::endInitRead() { + ScopedBusy(*this); + if (!isClosed) { + readEvent.throwIfException(); + in.move(readEvent.getBytesRead()); + in.flip(); + ProtocolInitiation protocolInit; + if(protocolInit.decode(in)){ + handler->initiated(&protocolInit); + readCallback = boost::bind( + &EventChannelConnection::closeOnException, + this, &EventChannelConnection::endRead); + } + in.compact(); + // Continue reading. + startRead(); + } +} + +// Normal reads, expect a frame. +// Always called inside closeOnException in channel thread. +void EventChannelConnection::endRead() { + ScopedBusy(*this); + if (!isClosed) { + readEvent.throwIfException(); + in.move(readEvent.getBytesRead()); + in.flip(); + AMQFrame frame; + while (frame.decode(in)) { + // TODO aconway 2006-11-30: received should take Frame& + if (isTrace) + cout << "Received on socket " << readFd + << ": " << frame << endl; + handler->received(&frame); + } + in.compact(); + startRead(); + } +} + +}} // namespace qpid::sys diff --git a/qpid/cpp/src/sys/posix/EventChannelConnection.h b/qpid/cpp/src/sys/posix/EventChannelConnection.h new file mode 100644 index 0000000000..0c1eeff087 --- /dev/null +++ b/qpid/cpp/src/sys/posix/EventChannelConnection.h @@ -0,0 +1,102 @@ +#ifndef _posix_EventChannelConnection_h +#define _posix_EventChannelConnection_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 "EventChannelThreads.h" +#include "../Monitor.h" +#include "../ConnectionOutputHandler.h" +#include "../ConnectionInputHandler.h" +#include "../AtomicCount.h" +#include "../../framing/AMQFrame.h" + +namespace qpid { +namespace sys { + +class ConnectionInputHandlerFactory; + +/** + * Implements ConnectionOutputHandler and delegates to a ConnectionInputHandler + * for a connection via the EventChannel. + *@param readDescriptor file descriptor for reading. + *@param writeDescriptor file descriptor for writing, + * by default same as readDescriptor + */ +class EventChannelConnection : public ConnectionOutputHandler { + public: + EventChannelConnection( + EventChannelThreads::shared_ptr threads, + ConnectionInputHandlerFactory& factory, + int readDescriptor, + int writeDescriptor = 0, + bool isTrace = false + ); + + // TODO aconway 2006-11-30: ConnectionOutputHandler::send should take auto_ptr + virtual void send(qpid::framing::AMQFrame* frame) { + send(std::auto_ptr(frame)); + } + + virtual void send(std::auto_ptr frame); + + virtual void close(); + + private: + typedef boost::ptr_deque FrameQueue; + typedef void (EventChannelConnection::*MemberFnPtr)(); + struct ScopedBusy; + + void startWrite(); + void endWrite(); + void startRead(); + void endInitRead(); + void endRead(); + void closeNoThrow(); + void closeOnException(MemberFnPtr); + bool shouldContinue(bool& flag); + + static const size_t bufferSize; + + Monitor monitor; + + int readFd, writeFd; + ReadEvent readEvent; + WriteEvent writeEvent; + Event::Callback readCallback; + bool isWriting; + bool isClosed; + AtomicCount busyThreads; + + EventChannelThreads::shared_ptr threads; + std::auto_ptr handler; + qpid::framing::Buffer in, out; + FrameQueue writeFrames; + bool isTrace; + + friend struct ScopedBusy; +}; + + +}} // namespace qpid::sys + + + +#endif /*!_posix_EventChannelConnection_h*/ diff --git a/qpid/cpp/src/sys/posix/EventChannelThreads.cpp b/qpid/cpp/src/sys/posix/EventChannelThreads.cpp new file mode 100644 index 0000000000..90caf901b1 --- /dev/null +++ b/qpid/cpp/src/sys/posix/EventChannelThreads.cpp @@ -0,0 +1,119 @@ +/* + * + * 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 "EventChannelThreads.h" +#include "../Runnable.h" +#include +using namespace std; +#include + +namespace qpid { +namespace sys { + +EventChannelThreads::shared_ptr EventChannelThreads::create( + EventChannel::shared_ptr ec) +{ + return EventChannelThreads::shared_ptr(new EventChannelThreads(ec)); +} + +EventChannelThreads::EventChannelThreads(EventChannel::shared_ptr ec) : + channel(ec), nWaiting(0), state(RUNNING) +{ + // TODO aconway 2006-11-15: Estimate initial threads based on CPUs. + addThread(); +} + +EventChannelThreads::~EventChannelThreads() { + shutdown(); + join(); +} + +void EventChannelThreads::shutdown() +{ + ScopedLock lock(*this); + if (state != RUNNING) // Already shutting down. + return; + for (size_t i = 0; i < workers.size(); ++i) { + channel->postEvent(terminate); + } + state = TERMINATE_SENT; + notify(); // Wake up one join() thread. +} + +void EventChannelThreads::join() +{ + { + ScopedLock lock(*this); + while (state == RUNNING) // Wait for shutdown to start. + wait(); + if (state == SHUTDOWN) // Shutdown is complete + return; + if (state == JOINING) { + // Someone else is doing the join. + while (state != SHUTDOWN) + wait(); + return; + } + // I'm the joining thread + assert(state == TERMINATE_SENT); + state = JOINING; + } // Drop the lock. + + for (size_t i = 0; i < workers.size(); ++i) { + assert(state == JOINING); // Only this thread can change JOINING. + workers[i].join(); + } + state = SHUTDOWN; + notifyAll(); // Notify other join() threaeds. +} + +void EventChannelThreads::addThread() { + ScopedLock l(*this); + workers.push_back(Thread(*this)); +} + +void EventChannelThreads::run() +{ + // Start life waiting. Decrement on exit. + AtomicCount::ScopedIncrement inc(nWaiting); + try { + while (true) { + Event* e = channel->getEvent(); + assert(e != 0); + if (e == &terminate) { + return; + } + AtomicCount::ScopedDecrement dec(nWaiting); + // I'm no longer waiting, make sure someone is. + if (dec == 0) + addThread(); + e->dispatch(); + } + } + catch (const std::exception& e) { + // TODO aconway 2006-11-15: need better logging across the board. + std::cerr << "EventChannelThreads::run() caught: " << e.what() + << std::endl; + } + catch (...) { + std::cerr << "EventChannelThreads::run() caught unknown exception." + << std::endl; + } +} + +}} diff --git a/qpid/cpp/src/sys/posix/EventChannelThreads.h b/qpid/cpp/src/sys/posix/EventChannelThreads.h new file mode 100644 index 0000000000..eb8b7cf287 --- /dev/null +++ b/qpid/cpp/src/sys/posix/EventChannelThreads.h @@ -0,0 +1,92 @@ +#ifndef _posix_EventChannelThreads_h +#define _sys_EventChannelThreads_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 "../../Exception.h" +#include "../Time.h" +#include "../Monitor.h" +#include "../Thread.h" +#include "../AtomicCount.h" +#include "EventChannel.h" + +namespace qpid { +namespace sys { + +/** + Dynamic thread pool serving an EventChannel. + + Threads run a loop { e = getEvent(); e->dispatch(); } + The size of the thread pool is automatically adjusted to optimal size. +*/ +class EventChannelThreads : + public qpid::SharedObject, + public sys::Monitor, private sys::Runnable +{ + public: + /** Create the thread pool and start initial threads. */ + static EventChannelThreads::shared_ptr create( + EventChannel::shared_ptr channel + ); + + ~EventChannelThreads(); + + /** Post event to the underlying channel */ + void postEvent(Event& event) { channel->postEvent(event); } + + /** Post event to the underlying channel Must not be 0. */ + void postEvent(Event* event) { channel->postEvent(event); } + + /** + * Terminate all threads. + * + * Returns immediately, use join() to wait till all threads are + * shut down. + */ + void shutdown(); + + /** Wait for all threads to terminate. */ + void join(); + + private: + typedef std::vector Threads; + typedef enum { + RUNNING, TERMINATE_SENT, JOINING, SHUTDOWN + } State; + + EventChannelThreads(EventChannel::shared_ptr underlyingChannel); + void addThread(); + + void run(); + bool keepRunning(); + void adjustThreads(); + + EventChannel::shared_ptr channel; + Threads workers; + sys::AtomicCount nWaiting; + State state; + Event terminate; +}; + + +}} + + +#endif /*!_sys_EventChannelThreads_h*/ diff --git a/qpid/cpp/src/sys/posix/PosixAcceptor.cpp b/qpid/cpp/src/sys/posix/PosixAcceptor.cpp new file mode 100644 index 0000000000..6ac0c2b11b --- /dev/null +++ b/qpid/cpp/src/sys/posix/PosixAcceptor.cpp @@ -0,0 +1,48 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "../Acceptor.h" +#include "../../Exception.h" + +namespace qpid { +namespace sys { + +namespace { +void fail() { throw qpid::Exception("PosixAcceptor not implemented"); } +} + +class PosixAcceptor : public Acceptor { + public: + virtual int16_t getPort() const { fail(); return 0; } + virtual void run(qpid::sys::ConnectionInputHandlerFactory* ) { fail(); } + virtual void shutdown() { fail(); } +}; + +// Define generic Acceptor::create() to return APRAcceptor. + Acceptor::shared_ptr Acceptor::create(int16_t , int, int, bool) +{ + return Acceptor::shared_ptr(new PosixAcceptor()); +} + +// Must define Acceptor virtual dtor. +Acceptor::~Acceptor() {} + +}} diff --git a/qpid/cpp/src/sys/posix/Socket.cpp b/qpid/cpp/src/sys/posix/Socket.cpp new file mode 100644 index 0000000000..6d6ac7f49c --- /dev/null +++ b/qpid/cpp/src/sys/posix/Socket.cpp @@ -0,0 +1,118 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../../QpidError.h" +#include "check.h" +#include "../Socket.h" + +using namespace qpid::sys; + +Socket Socket::createTcp() +{ + int s = ::socket (PF_INET, SOCK_STREAM, 0); + if (s < 0) throw QPID_POSIX_ERROR(errno); + return s; +} + +Socket::Socket(int descriptor) : socket(descriptor) {} + +void Socket::setTimeout(Time interval) +{ + struct timeval tv; + tv.tv_sec = interval/TIME_SEC; + tv.tv_usec = (interval%TIME_SEC)/TIME_USEC; + setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); +} + +void Socket::connect(const std::string& host, int port) +{ + struct sockaddr_in name; + name.sin_family = AF_INET; + name.sin_port = htons(port); + struct hostent* hp = gethostbyname ( host.c_str() ); + if (hp == 0) throw QPID_POSIX_ERROR(errno); + memcpy(&name.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length); + if (::connect(socket, (struct sockaddr*)(&name), sizeof(name)) < 0) + throw QPID_POSIX_ERROR(errno); +} + +void +Socket::close() +{ + if (socket == 0) return; + if (::close(socket) < 0) throw QPID_POSIX_ERROR(errno); + socket = 0; +} + +ssize_t +Socket::send(const void* data, size_t size) +{ + ssize_t sent = ::send(socket, data, size, 0); + if (sent < 0) { + if (errno == ECONNRESET) return SOCKET_EOF; + if (errno == ETIMEDOUT) return SOCKET_TIMEOUT; + throw QPID_POSIX_ERROR(errno); + } + return sent; +} + +ssize_t +Socket::recv(void* data, size_t size) +{ + ssize_t received = ::recv(socket, data, size, 0); + if (received < 0) { + if (errno == ETIMEDOUT) return SOCKET_TIMEOUT; + throw QPID_POSIX_ERROR(errno); + } + return received; +} + +int Socket::listen(int port, int backlog) +{ + struct sockaddr_in name; + name.sin_family = AF_INET; + name.sin_port = htons(port); + name.sin_addr.s_addr = 0; + if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) < 0) + throw QPID_POSIX_ERROR(errno); + if (::listen(socket, backlog) < 0) + throw QPID_POSIX_ERROR(errno); + + socklen_t namelen = sizeof(name); + if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0) + throw QPID_POSIX_ERROR(errno); + + return ntohs(name.sin_port); +} + + +int Socket::fd() +{ + return socket; +} diff --git a/qpid/cpp/src/sys/posix/Thread.cpp b/qpid/cpp/src/sys/posix/Thread.cpp new file mode 100644 index 0000000000..5b8d9e2180 --- /dev/null +++ b/qpid/cpp/src/sys/posix/Thread.cpp @@ -0,0 +1,28 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "../Thread.h" + +void* qpid::sys::Thread::runRunnable(void* p) +{ + static_cast(p)->run(); + return 0; +} diff --git a/qpid/cpp/src/sys/posix/check.cpp b/qpid/cpp/src/sys/posix/check.cpp new file mode 100644 index 0000000000..408679caa8 --- /dev/null +++ b/qpid/cpp/src/sys/posix/check.cpp @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include +#include "check.h" + +namespace qpid { +namespace sys { + +std::string +PosixError::getMessage(int errNo) +{ + char buf[512]; + return std::string(strerror_r(errNo, buf, sizeof(buf))); +} + +PosixError::PosixError(int errNo, const qpid::SrcLine& loc) throw() + : qpid::QpidError(INTERNAL_ERROR + errNo, getMessage(errNo), loc) +{ } + +}} diff --git a/qpid/cpp/src/sys/posix/check.h b/qpid/cpp/src/sys/posix/check.h new file mode 100644 index 0000000000..099044afa3 --- /dev/null +++ b/qpid/cpp/src/sys/posix/check.h @@ -0,0 +1,62 @@ +#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 +#include +#include "../../QpidError.h" + +namespace qpid { +namespace sys { + +/** + * Exception with message from errno. + */ +class PosixError : public qpid::QpidError +{ + public: + static std::string getMessage(int errNo); + + PosixError(int errNo, const qpid::SrcLine& location) throw(); + + ~PosixError() throw() {} + + int getErrNo() { return errNo; } + + Exception* clone() const throw() { return new PosixError(*this); } + + void throwSelf() const { throw *this; } + + private: + int errNo; +}; + +}} + +/** Create a PosixError for the current file/line and errno. */ +#define QPID_POSIX_ERROR(errNo) ::qpid::sys::PosixError(errNo, SRCLINE) + +/** Throw a posix error if errNo is non-zero */ +#define QPID_POSIX_THROW_IF(ERRNO) \ + if ((ERRNO) != 0) throw QPID_POSIX_ERROR((ERRNO)) +#endif /*!_posix_check_h*/ diff --git a/qpid/cpp/src/tests/.vg-supp b/qpid/cpp/src/tests/.vg-supp new file mode 100644 index 0000000000..b5abdf1385 --- /dev/null +++ b/qpid/cpp/src/tests/.vg-supp @@ -0,0 +1,18 @@ +{ + + Memcheck:Leak + fun:_Znwj + fun:_ZN4qpid6broker17ReferenceRegistry4openERKSs + fun:_ZN13ReferenceTestC1Ev + fun:_ZN7CppUnit25ConcretTestFixtureFactoryI13ReferenceTestE11makeFixtureEv + fun:_ZNK7CppUnit27TestSuiteBuilderContextBase15makeTestFixtureEv + fun:_ZNK7CppUnit23TestSuiteBuilderContextI13ReferenceTestE11makeFixtureEv + fun:_ZN13ReferenceTest15addTestsToSuiteERN7CppUnit27TestSuiteBuilderContextBaseE + fun:_ZN13ReferenceTest5suiteEv + fun:_ZN7CppUnit16TestSuiteFactoryI13ReferenceTestE8makeTestEv + fun:_ZN7CppUnit19TestFactoryRegistry14addTestToSuiteEPNS_9TestSuiteE + fun:_ZN7CppUnit19TestFactoryRegistry8makeTestEv + obj:/usr/bin/DllPlugInTester + obj:/usr/bin/DllPlugInTester + fun:(below main) +} diff --git a/qpid/cpp/src/tests/APRBaseTest.cpp b/qpid/cpp/src/tests/APRBaseTest.cpp new file mode 100644 index 0000000000..5ed8bf1918 --- /dev/null +++ b/qpid/cpp/src/tests/APRBaseTest.cpp @@ -0,0 +1,47 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../sys/apr/APRBase.h" +#include "qpid_test_plugin.h" +#include + +using namespace qpid::sys; + +class APRBaseTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(APRBaseTest); + CPPUNIT_TEST(testMe); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testMe() + { + APRBase::increment(); + APRBase::increment(); + APRBase::decrement(); + APRBase::decrement(); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(APRBaseTest); + diff --git a/qpid/cpp/src/tests/AccumulatedAckTest.cpp b/qpid/cpp/src/tests/AccumulatedAckTest.cpp new file mode 100644 index 0000000000..56870209fe --- /dev/null +++ b/qpid/cpp/src/tests/AccumulatedAckTest.cpp @@ -0,0 +1,107 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/AccumulatedAck.h" +#include "qpid_test_plugin.h" +#include +#include + +using std::list; +using namespace qpid::broker; + +class AccumulatedAckTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(AccumulatedAckTest); + CPPUNIT_TEST(testGeneral); + CPPUNIT_TEST(testCovers); + CPPUNIT_TEST(testUpdateAndConsolidate); + CPPUNIT_TEST_SUITE_END(); + + public: + void testGeneral() + { + AccumulatedAck ack(0); + ack.clear(); + ack.update(3,3); + ack.update(7,7); + ack.update(9,9); + ack.update(1,2); + ack.update(4,5); + ack.update(6,6); + + for(int i = 1; i <= 7; i++) CPPUNIT_ASSERT(ack.covers(i)); + CPPUNIT_ASSERT(ack.covers(9)); + + CPPUNIT_ASSERT(!ack.covers(8)); + CPPUNIT_ASSERT(!ack.covers(10)); + + ack.consolidate(); + + for(int i = 1; i <= 7; i++) CPPUNIT_ASSERT(ack.covers(i)); + CPPUNIT_ASSERT(ack.covers(9)); + + CPPUNIT_ASSERT(!ack.covers(8)); + CPPUNIT_ASSERT(!ack.covers(10)); + } + + void testCovers() + { + AccumulatedAck ack(5); + ack.individual.push_back(7); + ack.individual.push_back(9); + + CPPUNIT_ASSERT(ack.covers(1)); + CPPUNIT_ASSERT(ack.covers(2)); + CPPUNIT_ASSERT(ack.covers(3)); + CPPUNIT_ASSERT(ack.covers(4)); + CPPUNIT_ASSERT(ack.covers(5)); + CPPUNIT_ASSERT(ack.covers(7)); + CPPUNIT_ASSERT(ack.covers(9)); + + CPPUNIT_ASSERT(!ack.covers(6)); + CPPUNIT_ASSERT(!ack.covers(8)); + CPPUNIT_ASSERT(!ack.covers(10)); + } + + void testUpdateAndConsolidate() + { + AccumulatedAck ack(0); + ack.update(1, 1); + ack.update(3, 3); + ack.update(10, 10); + ack.update(8, 8); + ack.update(6, 6); + ack.update(3, 3); + ack.update(2, 2); + ack.update(0, 5); + ack.consolidate(); + CPPUNIT_ASSERT_EQUAL((uint64_t) 6, ack.range); + CPPUNIT_ASSERT_EQUAL((size_t) 2, ack.individual.size()); + list::iterator i = ack.individual.begin(); + CPPUNIT_ASSERT_EQUAL((uint64_t) 8, *i); + i++; + CPPUNIT_ASSERT_EQUAL((uint64_t) 10, *i); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(AccumulatedAckTest); + diff --git a/qpid/cpp/src/tests/BrokerChannelTest.cpp b/qpid/cpp/src/tests/BrokerChannelTest.cpp new file mode 100644 index 0000000000..006391bbd2 --- /dev/null +++ b/qpid/cpp/src/tests/BrokerChannelTest.cpp @@ -0,0 +1,357 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/BrokerChannel.h" +#include "../broker/BrokerMessage.h" +#include "../broker/BrokerQueue.h" +#include "../broker/FanOutExchange.h" +#include "../broker/NullMessageStore.h" +#include "qpid_test_plugin.h" +#include +#include +#include "AMQP_HighestVersion.h" +#include "../framing/AMQFrame.h" +#include "MockChannel.h" +#include "../broker/Connection.h" +#include "../framing/ProtocolInitiation.h" +#include + +using namespace boost; +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::sys; +using std::string; +using std::queue; + +struct MockHandler : ConnectionOutputHandler{ + boost::ptr_vector frames; + + void send(AMQFrame* frame){ frames.push_back(frame); } + + void close() {}; +}; + + +class BrokerChannelTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(BrokerChannelTest); + CPPUNIT_TEST(testConsumerMgmt); + CPPUNIT_TEST(testDeliveryNoAck); + CPPUNIT_TEST(testDeliveryAndRecovery); + CPPUNIT_TEST(testStaging); + CPPUNIT_TEST(testQueuePolicy); + CPPUNIT_TEST_SUITE_END(); + + Broker::shared_ptr broker; + Connection connection; + MockHandler handler; + + class MockMessageStore : public NullMessageStore + { + struct MethodCall + { + const string name; + PersistableMessage* msg; + const string data;//only needed for appendContent + + void check(const MethodCall& other) const + { + CPPUNIT_ASSERT_EQUAL(name, other.name); + CPPUNIT_ASSERT_EQUAL(msg, other.msg); + CPPUNIT_ASSERT_EQUAL(data, other.data); + } + }; + + queue expected; + bool expectMode;//true when setting up expected calls + + void handle(const MethodCall& call) + { + if (expectMode) { + expected.push(call); + } else { + call.check(expected.front()); + expected.pop(); + } + } + + void handle(const string& name, PersistableMessage* msg, const string& data) + { + MethodCall call = {name, msg, data}; + handle(call); + } + + public: + + MockMessageStore() : expectMode(false) {} + + void stage(PersistableMessage& msg) + { + if(!expectMode) msg.setPersistenceId(1); + MethodCall call = {"stage", &msg, ""}; + handle(call); + } + + void appendContent(PersistableMessage& msg, const string& data) + { + MethodCall call = {"appendContent", &msg, data}; + handle(call); + } + + // Don't hide overloads. + using NullMessageStore::destroy; + + void destroy(PersistableMessage& msg) + { + MethodCall call = {"destroy", &msg, ""}; + handle(call); + } + + void expect() + { + expectMode = true; + } + + void test() + { + expectMode = false; + } + + void check() + { + CPPUNIT_ASSERT(expected.empty()); + } + }; + + + public: + + BrokerChannelTest() : + broker(Broker::create()), + connection(&handler, *broker) + { + connection.initiated(ProtocolInitiation()); + } + + + void testConsumerMgmt(){ + Queue::shared_ptr queue(new Queue("my_queue")); + Channel channel(connection, 0, 0, 0); + channel.open(); + CPPUNIT_ASSERT(!channel.exists("my_consumer")); + + ConnectionToken* owner = 0; + string tag("my_consumer"); + channel.consume(tag, queue, false, false, owner); + string tagA; + string tagB; + channel.consume(tagA, queue, false, false, owner); + channel.consume(tagB, queue, false, false, owner); + CPPUNIT_ASSERT_EQUAL((uint32_t) 3, queue->getConsumerCount()); + CPPUNIT_ASSERT(channel.exists("my_consumer")); + CPPUNIT_ASSERT(channel.exists(tagA)); + CPPUNIT_ASSERT(channel.exists(tagB)); + channel.cancel(tagA); + CPPUNIT_ASSERT_EQUAL((uint32_t) 2, queue->getConsumerCount()); + CPPUNIT_ASSERT(channel.exists("my_consumer")); + CPPUNIT_ASSERT(!channel.exists(tagA)); + CPPUNIT_ASSERT(channel.exists(tagB)); + channel.close(); + CPPUNIT_ASSERT_EQUAL((uint32_t) 0, queue->getConsumerCount()); + } + + void testDeliveryNoAck(){ + Channel channel(connection, 7, 10000); + channel.open(); + const string data("abcdefghijklmn"); + Message::shared_ptr msg( + createMessage("test", "my_routing_key", "my_message_id", 14)); + addContent(msg, data); + Queue::shared_ptr queue(new Queue("my_queue")); + ConnectionToken* owner(0); + string tag("no_ack"); + channel.consume(tag, queue, false, false, owner); + + queue->deliver(msg); + CPPUNIT_ASSERT_EQUAL((size_t) 4, handler.frames.size()); + CPPUNIT_ASSERT_EQUAL(ChannelId(0), handler.frames[0].getChannel()); + CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[1].getChannel()); + CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[2].getChannel()); + CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[3].getChannel()); + CPPUNIT_ASSERT(dynamic_cast( + handler.frames[0].getBody().get())); + CPPUNIT_ASSERT(dynamic_cast( + handler.frames[1].getBody().get())); + CPPUNIT_ASSERT(dynamic_cast( + handler.frames[2].getBody().get())); + AMQContentBody* contentBody = dynamic_cast( + handler.frames[3].getBody().get()); + CPPUNIT_ASSERT(contentBody); + CPPUNIT_ASSERT_EQUAL(data, contentBody->getData()); + } + + void testDeliveryAndRecovery(){ + Channel channel(connection, 7, 10000); + channel.open(); + const string data("abcdefghijklmn"); + + Message::shared_ptr msg(createMessage("test", "my_routing_key", "my_message_id", 14)); + addContent(msg, data); + + Queue::shared_ptr queue(new Queue("my_queue")); + ConnectionToken* owner(0); + string tag("ack"); + channel.consume(tag, queue, true, false, owner); + + queue->deliver(msg); + CPPUNIT_ASSERT_EQUAL((size_t) 4, handler.frames.size()); + CPPUNIT_ASSERT_EQUAL(ChannelId(0), handler.frames[0].getChannel()); + CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[1].getChannel()); + CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[2].getChannel()); + CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[3].getChannel()); + CPPUNIT_ASSERT(dynamic_cast( + handler.frames[0].getBody().get())); + CPPUNIT_ASSERT(dynamic_cast( + handler.frames[1].getBody().get())); + CPPUNIT_ASSERT(dynamic_cast( + handler.frames[2].getBody().get())); + AMQContentBody* contentBody = dynamic_cast( + handler.frames[3].getBody().get()); + CPPUNIT_ASSERT(contentBody); + CPPUNIT_ASSERT_EQUAL(data, contentBody->getData()); + } + + void testStaging(){ + MockMessageStore store; + Channel channel( + connection, 1, 1000/*framesize*/, &store, 10/*staging threshold*/); + const string data[] = {"abcde", "fghij", "klmno"}; + + Message* msg = new BasicMessage( + 0, "my_exchange", "my_routing_key", false, false, + MockChannel::basicGetBody()); + + store.expect(); + store.stage(*msg); + for (int i = 0; i < 3; i++) { + store.appendContent(*msg, data[i]); + } + store.destroy(*msg); + store.test(); + + Exchange::shared_ptr exchange = + broker->getExchanges().declare("my_exchange", "fanout").first; + Queue::shared_ptr queue(new Queue("my_queue")); + exchange->bind(queue, "", 0); + + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + uint64_t contentSize(0); + for (int i = 0; i < 3; i++) { + contentSize += data[i].size(); + } + header->setContentSize(contentSize); + channel.handlePublish(msg); + channel.handleHeader(header); + + for (int i = 0; i < 3; i++) { + AMQContentBody::shared_ptr body(new AMQContentBody(data[i])); + channel.handleContent(body); + } + Message::shared_ptr msg2 = queue->dequeue(); + CPPUNIT_ASSERT_EQUAL(msg, msg2.get()); + msg2.reset();//should trigger destroy call + + store.check(); + } + + + //NOTE: strictly speaking this should/could be part of QueueTest, + //but as it can usefully use the same utility classes as this + //class it is defined here for simpllicity + void testQueuePolicy() + { + MockMessageStore store; + {//must ensure that store is last thing deleted as it is needed by destructor of lazy loaded content + const string data1("abcd"); + const string data2("efghijk"); + const string data3("lmnopqrstuvwxyz"); + Message::shared_ptr msg1(createMessage("e", "A", "MsgA", data1.size())); + Message::shared_ptr msg2(createMessage("e", "B", "MsgB", data2.size())); + Message::shared_ptr msg3(createMessage("e", "C", "MsgC", data3.size())); + addContent(msg1, data1); + addContent(msg2, data2); + addContent(msg3, data3); + + QueuePolicy policy(2, 0);//third message should be stored on disk and lazy loaded + FieldTable settings; + policy.update(settings); + + store.expect(); + store.stage(*msg3); + store.destroy(*msg3); + store.test(); + + Queue::shared_ptr queue(new Queue("my_queue", false, &store, 0)); + queue->configure(settings);//set policy + queue->deliver(msg1); + queue->deliver(msg2); + queue->deliver(msg3); + + Message::shared_ptr next = queue->dequeue(); + CPPUNIT_ASSERT_EQUAL(msg1, next); + CPPUNIT_ASSERT_EQUAL((uint32_t) data1.size(), next->encodedContentSize()); + next = queue->dequeue(); + CPPUNIT_ASSERT_EQUAL(msg2, next); + CPPUNIT_ASSERT_EQUAL((uint32_t) data2.size(), next->encodedContentSize()); + next = queue->dequeue(); + CPPUNIT_ASSERT_EQUAL(msg3, next); + CPPUNIT_ASSERT_EQUAL((uint32_t) 0, next->encodedContentSize()); + + next.reset(); + msg1.reset(); + msg2.reset(); + msg3.reset();//must clear all references to messages to allow them to be destroyed + + } + store.check(); + } + + Message* createMessage(const string& exchange, const string& routingKey, const string& messageId, uint64_t contentSize) + { + BasicMessage* msg = new BasicMessage( + 0, exchange, routingKey, false, false, + MockChannel::basicGetBody()); + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + header->setContentSize(contentSize); + msg->setHeader(header); + msg->getHeaderProperties()->setMessageId(messageId); + return msg; + } + + void addContent(Message::shared_ptr msg, const string& data) + { + AMQContentBody::shared_ptr body(new AMQContentBody(data)); + msg->addContent(body); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(BrokerChannelTest); diff --git a/qpid/cpp/src/tests/ClientChannelTest.cpp b/qpid/cpp/src/tests/ClientChannelTest.cpp new file mode 100644 index 0000000000..458931c4f4 --- /dev/null +++ b/qpid/cpp/src/tests/ClientChannelTest.cpp @@ -0,0 +1,193 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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_test_plugin.h" +#include "InProcessBroker.h" +#include "../client/ClientChannel.h" +#include "../client/ClientMessage.h" +#include "../client/ClientQueue.h" +#include "../client/ClientExchange.h" +#include "../client/MessageListener.h" + +using namespace std; +using namespace boost; +using namespace qpid::client; +using namespace qpid::sys; +using namespace qpid::framing; + +/// Small frame size so we can create fragmented messages. +const size_t FRAME_MAX = 256; + + +/** + * Test client API using an in-process broker. + */ +class ClientChannelTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(ClientChannelTest); + CPPUNIT_TEST(testPublishGet); + CPPUNIT_TEST(testGetNoContent); + CPPUNIT_TEST(testConsumeCancel); + CPPUNIT_TEST(testConsumePublished); + CPPUNIT_TEST(testGetFragmentedMessage); + CPPUNIT_TEST(testConsumeFragmentedMessage); + CPPUNIT_TEST_SUITE_END(); + + struct Listener: public qpid::client::MessageListener { + vector messages; + Monitor monitor; + void received(Message& msg) { + Mutex::ScopedLock l(monitor); + messages.push_back(msg); + monitor.notifyAll(); + } + }; + + InProcessBrokerClient connection; // client::connection + local broker + Channel channel; + const std::string qname; + const std::string data; + Queue queue; + Exchange exchange; + Listener listener; + + public: + + ClientChannelTest() + : connection(FRAME_MAX), + qname("testq"), data("hello"), + queue(qname, true), exchange("", Exchange::DIRECT_EXCHANGE) + { + connection.openChannel(channel); + CPPUNIT_ASSERT(channel.getId() != 0); + channel.declareQueue(queue); + } + + void testPublishGet() { + Message pubMsg(data); + pubMsg.getHeaders().setString("hello", "world"); + channel.publish(pubMsg, exchange, qname); + Message getMsg; + CPPUNIT_ASSERT(channel.get(getMsg, queue)); + CPPUNIT_ASSERT_EQUAL(data, getMsg.getData()); + CPPUNIT_ASSERT_EQUAL(string("world"), + getMsg.getHeaders().getString("hello")); + CPPUNIT_ASSERT(!channel.get(getMsg, queue)); // Empty queue + } + + void testGetNoContent() { + Message pubMsg; + pubMsg.getHeaders().setString("hello", "world"); + channel.publish(pubMsg, exchange, qname); + Message getMsg; + CPPUNIT_ASSERT(channel.get(getMsg, queue)); + CPPUNIT_ASSERT(getMsg.getData().empty()); + CPPUNIT_ASSERT_EQUAL(string("world"), + getMsg.getHeaders().getString("hello")); + } + + void testConsumeCancel() { + string tag; // Broker assigned + channel.consume(queue, tag, &listener); + channel.start(); + CPPUNIT_ASSERT_EQUAL(size_t(0), listener.messages.size()); + channel.publish(Message("a"), exchange, qname); + { + Mutex::ScopedLock l(listener.monitor); + Time deadline(now() + 1*TIME_SEC); + while (listener.messages.size() != 1) { + CPPUNIT_ASSERT(listener.monitor.wait(deadline)); + } + } + CPPUNIT_ASSERT_EQUAL(size_t(1), listener.messages.size()); + CPPUNIT_ASSERT_EQUAL(string("a"), listener.messages[0].getData()); + + channel.publish(Message("b"), exchange, qname); + channel.publish(Message("c"), exchange, qname); + { + Mutex::ScopedLock l(listener.monitor); + while (listener.messages.size() != 3) { + CPPUNIT_ASSERT(listener.monitor.wait(1*TIME_SEC)); + } + } + CPPUNIT_ASSERT_EQUAL(size_t(3), listener.messages.size()); + CPPUNIT_ASSERT_EQUAL(string("b"), listener.messages[1].getData()); + CPPUNIT_ASSERT_EQUAL(string("c"), listener.messages[2].getData()); + + channel.cancel(tag); + channel.publish(Message("d"), exchange, qname); + CPPUNIT_ASSERT_EQUAL(size_t(3), listener.messages.size()); + { + Mutex::ScopedLock l(listener.monitor); + CPPUNIT_ASSERT(!listener.monitor.wait(TIME_SEC/2)); + } + Message msg; + CPPUNIT_ASSERT(channel.get(msg, queue)); + CPPUNIT_ASSERT_EQUAL(string("d"), msg.getData()); + } + + // Consume already-published messages + void testConsumePublished() { + Message pubMsg("x"); + pubMsg.getHeaders().setString("y", "z"); + channel.publish(pubMsg, exchange, qname); + string tag; + channel.consume(queue, tag, &listener); + CPPUNIT_ASSERT_EQUAL(size_t(0), listener.messages.size()); + channel.start(); + { + Mutex::ScopedLock l(listener.monitor); + while (listener.messages.size() != 1) + CPPUNIT_ASSERT(listener.monitor.wait(1*TIME_SEC)); + } + CPPUNIT_ASSERT_EQUAL(string("x"), listener.messages[0].getData()); + CPPUNIT_ASSERT_EQUAL(string("z"), + listener.messages[0].getHeaders().getString("y")); + } + + void testGetFragmentedMessage() { + string longStr(FRAME_MAX*2, 'x'); // Longer than max frame size. + channel.publish(Message(longStr), exchange, qname); + Message getMsg; + CPPUNIT_ASSERT(channel.get(getMsg, queue)); + } + + void testConsumeFragmentedMessage() { + string xx(FRAME_MAX*2, 'x'); + channel.publish(Message(xx), exchange, qname); + channel.start(); + string tag; + channel.consume(queue, tag, &listener); + string yy(FRAME_MAX*2, 'y'); + channel.publish(Message(yy), exchange, qname); + { + Mutex::ScopedLock l(listener.monitor); + while (listener.messages.size() != 2) + CPPUNIT_ASSERT(listener.monitor.wait(1*TIME_SEC)); + } + CPPUNIT_ASSERT_EQUAL(xx, listener.messages[0].getData()); + CPPUNIT_ASSERT_EQUAL(yy, listener.messages[1].getData()); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(ClientChannelTest); diff --git a/qpid/cpp/src/tests/ConfigurationTest.cpp b/qpid/cpp/src/tests/ConfigurationTest.cpp new file mode 100644 index 0000000000..ecaa2865ce --- /dev/null +++ b/qpid/cpp/src/tests/ConfigurationTest.cpp @@ -0,0 +1,98 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/Configuration.h" +#include "qpid_test_plugin.h" +#include + +using namespace std; +using namespace qpid::broker; + +class ConfigurationTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(ConfigurationTest); + CPPUNIT_TEST(testIsHelp); + CPPUNIT_TEST(testPortLongForm); + CPPUNIT_TEST(testPortShortForm); + CPPUNIT_TEST(testStore); + CPPUNIT_TEST(testStagingThreshold); + CPPUNIT_TEST(testVarious); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testIsHelp() + { + Configuration conf; + char* argv[] = {"ignore", "--help"}; + conf.parse("ignore", 2, argv); + CPPUNIT_ASSERT(conf.isHelp()); + } + + void testPortLongForm() + { + Configuration conf; + char* argv[] = {"ignore", "--port", "6789"}; + conf.parse("ignore", 3, argv); + CPPUNIT_ASSERT_EQUAL(6789, conf.getPort()); + } + + void testPortShortForm() + { + Configuration conf; + char* argv[] = {"ignore", "-p", "6789"}; + conf.parse("ignore", 3, argv); + CPPUNIT_ASSERT_EQUAL(6789, conf.getPort()); + } + + void testStore() + { + Configuration conf; + char* argv[] = {"ignore", "--store", "my-store-module.so"}; + conf.parse("ignore", 3, argv); + std::string expected("my-store-module.so"); + CPPUNIT_ASSERT_EQUAL(expected, conf.getStore()); + } + + void testStagingThreshold() + { + Configuration conf; + char* argv[] = {"ignore", "--staging-threshold", "123456789"}; + conf.parse("ignore", 3, argv); + long expected = 123456789; + CPPUNIT_ASSERT_EQUAL(expected, conf.getStagingThreshold()); + } + + void testVarious() + { + Configuration conf; + char* argv[] = {"ignore", "-t", "--worker-threads", "10"}; + conf.parse("ignore", 4, argv); + CPPUNIT_ASSERT_EQUAL(5672, conf.getPort());//default + CPPUNIT_ASSERT_EQUAL(10, conf.getWorkerThreads()); + CPPUNIT_ASSERT(conf.isTrace()); + CPPUNIT_ASSERT(!conf.isHelp()); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(ConfigurationTest); + diff --git a/qpid/cpp/src/tests/EventChannelConnectionTest.cpp b/qpid/cpp/src/tests/EventChannelConnectionTest.cpp new file mode 100644 index 0000000000..24cd492441 --- /dev/null +++ b/qpid/cpp/src/tests/EventChannelConnectionTest.cpp @@ -0,0 +1,109 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../framing/AMQHeartbeatBody.h" +#include "../framing/AMQFrame.h" +#include "../sys/posix/EventChannelConnection.h" +#include "../sys/ConnectionInputHandler.h" +#include "../sys/ConnectionInputHandlerFactory.h" +#include "../sys/Socket.h" +#include "qpid_test_plugin.h" +#include "MockConnectionInputHandler.h" + +using namespace qpid::sys; +using namespace qpid::framing; +using namespace std; + +class EventChannelConnectionTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(EventChannelConnectionTest); + CPPUNIT_TEST(testSendReceive); + CPPUNIT_TEST(testCloseExternal); + CPPUNIT_TEST(testCloseException); + CPPUNIT_TEST_SUITE_END(); + + public: + + void setUp() { + threads = EventChannelThreads::create(); + CPPUNIT_ASSERT_EQUAL(0, ::pipe(pipe)); + connection.reset( + new EventChannelConnection(threads, factory, pipe[0], pipe[1])); + CPPUNIT_ASSERT(factory.handler != 0); + } + + void tearDown() { + threads->shutdown(); + threads->join(); + } + + void testSendReceive() + { + // Send a protocol initiation. + Buffer buf(1024); + ProtocolInitiation(4,2).encode(buf); + buf.flip(); + ssize_t n = write(pipe[1], buf.start(), buf.available()); + CPPUNIT_ASSERT_EQUAL(ssize_t(buf.available()), n); + + // Verify session handler got the protocol init. + ProtocolInitiation init = factory.handler->waitForProtocolInit(); + CPPUNIT_ASSERT_EQUAL(int(4), int(init.getMajor())); + CPPUNIT_ASSERT_EQUAL(int(2), int(init.getMinor())); + + // Send a heartbeat frame, verify connection got it. + connection->send(new AMQFrame(42, new AMQHeartbeatBody())); + AMQFrame frame = factory.handler->waitForFrame(); + CPPUNIT_ASSERT_EQUAL(uint16_t(42), frame.getChannel()); + CPPUNIT_ASSERT_EQUAL(uint8_t(HEARTBEAT_BODY), + frame.getBody()->type()); + threads->shutdown(); + } + + // Make sure the handler is closed if the connection is closed. + void testCloseExternal() { + connection->close(); + factory.handler->waitForClosed(); + } + + // Make sure the handler is closed if the connection closes or fails. + // TODO aconway 2006-12-18: logs exception message in test output. + void testCloseException() { + ::close(pipe[0]); + ::close(pipe[1]); + // TODO aconway 2006-12-18: Shouldn't this be failing? + connection->send(new AMQFrame(42, new AMQHeartbeatBody())); + factory.handler->waitForClosed(); + } + + private: + EventChannelThreads::shared_ptr threads; + int pipe[2]; + std::auto_ptr connection; + MockConnectionInputHandlerFactory factory; +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(EventChannelConnectionTest); + diff --git a/qpid/cpp/src/tests/EventChannelTest.cpp b/qpid/cpp/src/tests/EventChannelTest.cpp new file mode 100644 index 0000000000..45229ce20f --- /dev/null +++ b/qpid/cpp/src/tests/EventChannelTest.cpp @@ -0,0 +1,187 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../sys/posix/EventChannel.h" +#include "../sys/posix/check.h" +#include "../sys/Runnable.h" +#include "../sys/Socket.h" +#include "../sys/Thread.h" +#include "qpid_test_plugin.h" + +#include +#include +#include +#include +#include + +using namespace qpid::sys; + + +const char hello[] = "hello"; +const size_t size = sizeof(hello); + +struct RunMe : public Runnable +{ + bool ran; + RunMe() : ran(false) {} + void run() { ran = true; } +}; + +class EventChannelTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(EventChannelTest); + CPPUNIT_TEST(testEvent); + CPPUNIT_TEST(testRead); + CPPUNIT_TEST(testFailedRead); + CPPUNIT_TEST(testWrite); + CPPUNIT_TEST(testFailedWrite); + CPPUNIT_TEST(testReadWrite); + CPPUNIT_TEST(testAccept); + CPPUNIT_TEST_SUITE_END(); + + private: + EventChannel::shared_ptr ec; + int pipe[2]; + char readBuf[size]; + + public: + + void setUp() + { + memset(readBuf, size, 0); + ec = EventChannel::create(); + if (::pipe(pipe) != 0) throw QPID_POSIX_ERROR(errno); + // Ignore SIGPIPE, otherwise we will crash writing to broken pipe. + signal(SIGPIPE, SIG_IGN); + } + + // Verify that calling getEvent returns event. + template bool isNextEvent(T& event) + { + return &event == dynamic_cast(ec->getEvent()); + } + + template bool isNextEventOk(T& event) + { + Event* next = ec->getEvent(); + if (next) next->throwIfError(); + return &event == next; + } + + void testEvent() + { + RunMe runMe; + CPPUNIT_ASSERT(!runMe.ran); + // Instances of Event just pass thru the channel immediately. + Event e(runMe.functor()); + ec->postEvent(e); + CPPUNIT_ASSERT(isNextEventOk(e)); + e.dispatch(); + CPPUNIT_ASSERT(runMe.ran); + } + + void testRead() { + ReadEvent re(pipe[0], readBuf, size); + ec->postEvent(re); + CPPUNIT_ASSERT_EQUAL(ssize_t(size), ::write(pipe[1], hello, size)); + CPPUNIT_ASSERT(isNextEventOk(re)); + CPPUNIT_ASSERT_EQUAL(size, re.getSize()); + CPPUNIT_ASSERT_EQUAL(std::string(hello), std::string(readBuf)); + } + + void testFailedRead() + { + ReadEvent re(pipe[0], readBuf, size); + ec->postEvent(re); + + // EOF before all data read. + ::close(pipe[1]); + CPPUNIT_ASSERT(isNextEvent(re)); + CPPUNIT_ASSERT(re.hasError()); + try { + re.throwIfError(); + CPPUNIT_FAIL("Expected QpidError."); + } + catch (const qpid::QpidError&) { } + + // Bad file descriptor. Note in this case we fail + // in postEvent and throw immediately. + try { + ReadEvent bad; + ec->postEvent(bad); + CPPUNIT_FAIL("Expected QpidError."); + } + catch (const qpid::QpidError&) { } + } + + void testWrite() { + WriteEvent wr(pipe[1], hello, size); + ec->postEvent(wr); + CPPUNIT_ASSERT(isNextEventOk(wr)); + CPPUNIT_ASSERT_EQUAL(ssize_t(size), ::read(pipe[0], readBuf, size));; + CPPUNIT_ASSERT_EQUAL(std::string(hello), std::string(readBuf)); + } + + void testFailedWrite() { + WriteEvent wr(pipe[1], hello, size); + ::close(pipe[0]); + ec->postEvent(wr); + CPPUNIT_ASSERT(isNextEvent(wr)); + CPPUNIT_ASSERT(wr.hasError()); + } + + void testReadWrite() + { + ReadEvent re(pipe[0], readBuf, size); + WriteEvent wr(pipe[1], hello, size); + ec->postEvent(re); + ec->postEvent(wr); + ec->getEvent(); + ec->getEvent(); + CPPUNIT_ASSERT_EQUAL(std::string(hello), std::string(readBuf)); + } + + void testAccept() { + Socket s = Socket::createTcp(); + int port = s.listen(0, 10); + CPPUNIT_ASSERT(port != 0); + + AcceptEvent ae(s.fd()); + ec->postEvent(ae); + Socket client = Socket::createTcp(); + client.connect("localhost", port); + CPPUNIT_ASSERT(isNextEvent(ae)); + ae.dispatch(); + + // Verify client writes are read by the accepted descriptor. + char readBuf[size]; + ReadEvent re(ae.getAcceptedDesscriptor(), readBuf, size); + ec->postEvent(re); + CPPUNIT_ASSERT_EQUAL(ssize_t(size), client.send(hello, sizeof(hello))); + CPPUNIT_ASSERT(isNextEvent(re)); + re.dispatch(); + CPPUNIT_ASSERT_EQUAL(std::string(hello), std::string(readBuf)); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(EventChannelTest); + diff --git a/qpid/cpp/src/tests/EventChannelThreadsTest.cpp b/qpid/cpp/src/tests/EventChannelThreadsTest.cpp new file mode 100644 index 0000000000..ee1e2859c4 --- /dev/null +++ b/qpid/cpp/src/tests/EventChannelThreadsTest.cpp @@ -0,0 +1,247 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include +#include + +#include "../sys/Socket.h" +#include "../sys/posix/EventChannelThreads.h" +#include "qpid_test_plugin.h" + + +using namespace std; + +using namespace qpid::sys; + +const int nConnections = 5; +const int nMessages = 10; // Messages read/written per connection. + + +// Accepts + reads + writes. +const int totalEvents = nConnections+2*nConnections*nMessages; + +/** + * Messages are numbered 0..nMessages. + * We count the total number of events, and the + * number of reads and writes for each message number. + */ +class TestResults : public Monitor { + public: + TestResults() : isShutdown(false), nEventsRemaining(totalEvents) {} + + void countEvent() { + if (--nEventsRemaining == 0) + shutdown(); + } + + void countRead(int messageNo) { + ++reads[messageNo]; + countEvent(); + } + + void countWrite(int messageNo) { + ++writes[messageNo]; + countEvent(); + } + + void shutdown(const std::string& exceptionMsg = std::string()) { + ScopedLock lock(*this); + exception = exceptionMsg; + isShutdown = true; + notifyAll(); + } + + void wait() { + ScopedLock lock(*this); + Time deadline = now() + 10*TIME_SEC; + while (!isShutdown) { + CPPUNIT_ASSERT(Monitor::wait(deadline)); + } + } + + bool isShutdown; + std::string exception; + AtomicCount reads[nMessages]; + AtomicCount writes[nMessages]; + AtomicCount nEventsRemaining; +}; + +TestResults results; + +EventChannelThreads::shared_ptr threads; + +// Functor to wrap callbacks in try/catch. +class SafeCallback { + public: + SafeCallback(Runnable& r) : callback(r.functor()) {} + SafeCallback(Event::Callback cb) : callback(cb) {} + + void operator()() { + std::string exception; + try { + callback(); + return; + } + catch (const std::exception& e) { + exception = e.what(); + } + catch (...) { + exception = "Unknown exception."; + } + results.shutdown(exception); + } + + private: + Event::Callback callback; +}; + +/** Repost an event N times. */ +class Repost { + public: + Repost(int n) : count (n) {} + virtual ~Repost() {} + + void repost(Event* event) { + if (--count==0) { + delete event; + } else { + threads->postEvent(event); + } + } + private: + int count; +}; + + + +/** Repeating read event. */ +class TestReadEvent : public ReadEvent, public Runnable, private Repost { + public: + explicit TestReadEvent(int fd=-1) : + ReadEvent(fd, &value, sizeof(value), SafeCallback(*this)), + Repost(nMessages) + {} + + void run() { + CPPUNIT_ASSERT_EQUAL(sizeof(value), getSize()); + CPPUNIT_ASSERT(0 <= value); + CPPUNIT_ASSERT(value < nMessages); + results.countRead(value); + repost(this); + } + + private: + int value; + ReadEvent original; +}; + + +/** Fire and forget write event */ +class TestWriteEvent : public WriteEvent, public Runnable, private Repost { + public: + TestWriteEvent(int fd=-1) : + WriteEvent(fd, &value, sizeof(value), SafeCallback(*this)), + Repost(nMessages), + value(0) + {} + + void run() { + CPPUNIT_ASSERT_EQUAL(sizeof(int), getSize()); + results.countWrite(value++); + repost(this); + } + + private: + int value; +}; + +/** Fire-and-forget Accept event, posts reads on the accepted connection. */ +class TestAcceptEvent : public AcceptEvent, public Runnable, private Repost { + public: + TestAcceptEvent(int fd=-1) : + AcceptEvent(fd, SafeCallback(*this)), + Repost(nConnections) + {} + + void run() { + threads->postEvent(new TestReadEvent(getAcceptedDesscriptor())); + results.countEvent(); + repost(this); + } +}; + +class EventChannelThreadsTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(EventChannelThreadsTest); + CPPUNIT_TEST(testThreads); + CPPUNIT_TEST_SUITE_END(); + + public: + + void setUp() { + threads = EventChannelThreads::create(EventChannel::create()); + } + + void tearDown() { + threads.reset(); + } + + void testThreads() + { + Socket listener = Socket::createTcp(); + int port = listener.listen(); + + // Post looping accept events, will repost nConnections times. + // The accept event will automatically post read events. + threads->postEvent(new TestAcceptEvent(listener.fd())); + + // Make connections. + Socket connections[nConnections]; + for (int i = 0; i < nConnections; ++i) { + connections[i] = Socket::createTcp(); + connections[i].connect("localhost", port); + } + + // Post looping write events. + for (int i = 0; i < nConnections; ++i) { + threads->postEvent(new TestWriteEvent(connections[i].fd())); + } + + // Wait for all events to be dispatched. + results.wait(); + + if (!results.exception.empty()) CPPUNIT_FAIL(results.exception); + CPPUNIT_ASSERT_EQUAL(0, int(results.nEventsRemaining)); + + // Expect a read and write for each messageNo from each connection. + for (int messageNo = 0; messageNo < nMessages; ++messageNo) { + CPPUNIT_ASSERT_EQUAL(nConnections, int(results.reads[messageNo])); + CPPUNIT_ASSERT_EQUAL(nConnections, int(results.writes[messageNo])); + } + + threads->shutdown(); + threads->join(); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(EventChannelThreadsTest); + diff --git a/qpid/cpp/src/tests/ExchangeTest.cpp b/qpid/cpp/src/tests/ExchangeTest.cpp new file mode 100644 index 0000000000..97846cf527 --- /dev/null +++ b/qpid/cpp/src/tests/ExchangeTest.cpp @@ -0,0 +1,73 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "../broker/DeliverableMessage.h" +#include "../broker/DirectExchange.h" +#include "../broker/BrokerExchange.h" +#include "../broker/BrokerQueue.h" +#include "../broker/TopicExchange.h" +#include "qpid_test_plugin.h" +#include +#include "BasicGetBody.h" + +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::sys; + +class ExchangeTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(ExchangeTest); + CPPUNIT_TEST(testMe); + CPPUNIT_TEST_SUITE_END(); + + public: + + void 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(); + + Message::shared_ptr msgPtr( + new BasicMessage( + 0, "e", "A", true, true, + AMQMethodBody::shared_ptr( + new BasicGetBody(ProtocolVersion())))); + DeliverableMessage msg(msgPtr); + topic.route(msg, "abc", 0); + direct.route(msg, "abc", 0); + + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(ExchangeTest); diff --git a/qpid/cpp/src/tests/FieldTableTest.cpp b/qpid/cpp/src/tests/FieldTableTest.cpp new file mode 100644 index 0000000000..f485ca187e --- /dev/null +++ b/qpid/cpp/src/tests/FieldTableTest.cpp @@ -0,0 +1,55 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include +#include "../framing/amqp_framing.h" +#include "qpid_test_plugin.h" + +using namespace qpid::framing; + +class FieldTableTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(FieldTableTest); + CPPUNIT_TEST(testMe); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testMe() + { + FieldTable ft; + ft.setString("A", "BCDE"); + CPPUNIT_ASSERT_EQUAL(std::string("BCDE"), ft.getString("A")); + + Buffer buffer(100); + buffer.putFieldTable(ft); + buffer.flip(); + FieldTable ft2; + buffer.getFieldTable(ft2); + CPPUNIT_ASSERT_EQUAL(std::string("BCDE"), ft2.getString("A")); + + } +}; + + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(FieldTableTest); + diff --git a/qpid/cpp/src/tests/FramingTest.cpp b/qpid/cpp/src/tests/FramingTest.cpp new file mode 100644 index 0000000000..89a559d0bb --- /dev/null +++ b/qpid/cpp/src/tests/FramingTest.cpp @@ -0,0 +1,381 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "ConnectionRedirectBody.h" +#include "../framing/ProtocolVersion.h" +#include "../framing/amqp_framing.h" +#include +#include "qpid_test_plugin.h" +#include +#include +#include "../QpidError.h" +#include "AMQP_HighestVersion.h" +#include "../framing/AMQRequestBody.h" +#include "../framing/AMQResponseBody.h" +#include "../framing/Requester.h" +#include "../framing/Responder.h" +#include "InProcessBroker.h" +#include "../client/Connection.h" +#include "../client/ClientExchange.h" +#include "../client/ClientQueue.h" + +using namespace qpid; +using namespace qpid::framing; +using namespace std; + +template +std::string tostring(const T& x) +{ + std::ostringstream out; + out << x; + return out.str(); +} + +class FramingTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(FramingTest); + CPPUNIT_TEST(testBasicQosBody); + CPPUNIT_TEST(testConnectionSecureBody); + CPPUNIT_TEST(testConnectionRedirectBody); + CPPUNIT_TEST(testAccessRequestBody); + CPPUNIT_TEST(testBasicConsumeBody); + CPPUNIT_TEST(testConnectionRedirectBodyFrame); + CPPUNIT_TEST(testBasicConsumeOkBodyFrame); + CPPUNIT_TEST(testRequestBodyFrame); + CPPUNIT_TEST(testResponseBodyFrame); + CPPUNIT_TEST(testRequester); + CPPUNIT_TEST(testResponder); + CPPUNIT_TEST(testInlineContent); + CPPUNIT_TEST(testContentReference); + CPPUNIT_TEST(testContentValidation); + CPPUNIT_TEST(testRequestResponseRoundtrip); + CPPUNIT_TEST_SUITE_END(); + + private: + Buffer buffer; + ProtocolVersion version; + AMQP_MethodVersionMap versionMap; + + public: + + FramingTest() : buffer(1024), version(highestProtocolVersion) {} + + void testBasicQosBody() + { + BasicQosBody in(version, 0xCAFEBABE, 0xABBA, true); + in.encodeContent(buffer); + buffer.flip(); + BasicQosBody out(version); + out.decodeContent(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + void testConnectionSecureBody() + { + std::string s = "security credential"; + ConnectionSecureBody in(version, s); + in.encodeContent(buffer); + buffer.flip(); + ConnectionSecureBody out(version); + out.decodeContent(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + void testConnectionRedirectBody() + { + std::string a = "hostA"; + std::string b = "hostB"; + ConnectionRedirectBody in(version, 0, a, b); + in.encodeContent(buffer); + buffer.flip(); + ConnectionRedirectBody out(version); + out.decodeContent(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + void testAccessRequestBody() + { + std::string s = "text"; + AccessRequestBody in(version, s, true, false, true, false, true); + in.encodeContent(buffer); + buffer.flip(); + AccessRequestBody out(version); + out.decodeContent(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + void testBasicConsumeBody() + { + std::string q = "queue"; + std::string t = "tag"; + BasicConsumeBody in(version, 0, q, t, false, true, false, false, + FieldTable()); + in.encodeContent(buffer); + buffer.flip(); + BasicConsumeBody out(version); + out.decodeContent(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + + void testConnectionRedirectBodyFrame() + { + std::string a = "hostA"; + std::string b = "hostB"; + AMQFrame in(version, 999, + new ConnectionRedirectBody(version, 0, a, b)); + in.encode(buffer); + buffer.flip(); + AMQFrame out; + out.decode(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + void testBasicConsumeOkBodyFrame() + { + std::string s = "hostA"; + AMQFrame in(version, 999, new BasicConsumeOkBody(version, 0, s)); + in.encode(buffer); + buffer.flip(); + AMQFrame out; + for(int i = 0; i < 5; i++){ + out.decode(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + } + + void testRequestBodyFrame() { + std::string testing("testing"); + AMQBody::shared_ptr request(new ChannelOpenBody(version, testing)); + AMQFrame in(version, 999, request); + in.encode(buffer); + buffer.flip(); + AMQFrame out; + out.decode(buffer); + ChannelOpenBody* decoded = + dynamic_cast(out.getBody().get()); + CPPUNIT_ASSERT(decoded); + CPPUNIT_ASSERT_EQUAL(testing, decoded->getOutOfBand()); + } + + void testResponseBodyFrame() { + AMQBody::shared_ptr response(new ChannelOkBody(version)); + AMQFrame in(version, 999, response); + in.encode(buffer); + buffer.flip(); + AMQFrame out; + out.decode(buffer); + ChannelOkBody* decoded = + dynamic_cast(out.getBody().get()); + CPPUNIT_ASSERT(decoded); + } + + void testInlineContent() { + Content content(INLINE, "MyData"); + CPPUNIT_ASSERT(content.isInline()); + content.encode(buffer); + buffer.flip(); + Content recovered; + recovered.decode(buffer); + CPPUNIT_ASSERT(recovered.isInline()); + CPPUNIT_ASSERT_EQUAL(content.getValue(), recovered.getValue()); + } + + void testContentReference() { + Content content(REFERENCE, "MyRef"); + CPPUNIT_ASSERT(content.isReference()); + content.encode(buffer); + buffer.flip(); + Content recovered; + recovered.decode(buffer); + CPPUNIT_ASSERT(recovered.isReference()); + CPPUNIT_ASSERT_EQUAL(content.getValue(), recovered.getValue()); + } + + void testContentValidation() { + try { + Content content(REFERENCE, ""); + CPPUNIT_ASSERT(false);//fail, expected exception + } catch (QpidError& e) { + CPPUNIT_ASSERT_EQUAL(FRAMING_ERROR, e.code); + CPPUNIT_ASSERT_EQUAL(string("Reference cannot be empty"), e.msg); + } + + try { + Content content(2, "Blah"); + CPPUNIT_ASSERT(false);//fail, expected exception + } catch (QpidError& e) { + CPPUNIT_ASSERT_EQUAL(FRAMING_ERROR, e.code); + CPPUNIT_ASSERT_EQUAL(string("Invalid discriminator: 2"), e.msg); + } + + try { + buffer.putOctet(2); + buffer.putLongString("blah, blah"); + buffer.flip(); + Content content; + content.decode(buffer); + CPPUNIT_ASSERT(false);//fail, expected exception + } catch (QpidError& e) { + CPPUNIT_ASSERT_EQUAL(FRAMING_ERROR, e.code); + CPPUNIT_ASSERT_EQUAL(string("Invalid discriminator: 2"), e.msg); + } + + } + + void testRequester() { + Requester r; + AMQRequestBody::Data q; + AMQResponseBody::Data p; + + r.sending(q); + CPPUNIT_ASSERT_EQUAL(1ULL, q.requestId); + CPPUNIT_ASSERT_EQUAL(0ULL, q.responseMark); + + r.sending(q); + CPPUNIT_ASSERT_EQUAL(2ULL, q.requestId); + CPPUNIT_ASSERT_EQUAL(0ULL, q.responseMark); + + // Now process a response + p.responseId = 1; + p.requestId = 2; + r.processed(AMQResponseBody::Data(1, 2)); + + r.sending(q); + CPPUNIT_ASSERT_EQUAL(3ULL, q.requestId); + CPPUNIT_ASSERT_EQUAL(1ULL, q.responseMark); + + try { + r.processed(p); // Already processed this response. + CPPUNIT_FAIL("Expected exception"); + } catch (...) {} + + try { + p.requestId = 50; + r.processed(p); // No such request + CPPUNIT_FAIL("Expected exception"); + } catch (...) {} + + r.sending(q); // reqId=4 + r.sending(q); // reqId=5 + r.sending(q); // reqId=6 + p.responseId++; + p.requestId = 4; + p.batchOffset = 2; + r.processed(p); + r.sending(q); + CPPUNIT_ASSERT_EQUAL(7ULL, q.requestId); + CPPUNIT_ASSERT_EQUAL(2ULL, q.responseMark); + + p.responseId++; + p.requestId = 1; // Out of order + p.batchOffset = 0; + r.processed(p); + r.sending(q); + CPPUNIT_ASSERT_EQUAL(8ULL, q.requestId); + CPPUNIT_ASSERT_EQUAL(3ULL, q.responseMark); + } + + void testResponder() { + Responder r; + AMQRequestBody::Data q; + AMQResponseBody::Data p; + + q.requestId = 1; + q.responseMark = 0; + r.received(q); + p.requestId = q.requestId; + r.sending(p); + CPPUNIT_ASSERT_EQUAL(1ULL, p.responseId); + CPPUNIT_ASSERT_EQUAL(1ULL, p.requestId); + CPPUNIT_ASSERT_EQUAL(0U, p.batchOffset); + CPPUNIT_ASSERT_EQUAL(0ULL, r.getResponseMark()); + + q.requestId++; + q.responseMark = 1; + r.received(q); + r.sending(p); + CPPUNIT_ASSERT_EQUAL(2ULL, p.responseId); + CPPUNIT_ASSERT_EQUAL(0U, p.batchOffset); + CPPUNIT_ASSERT_EQUAL(1ULL, r.getResponseMark()); + + try { + // Response mark higher any request ID sent. + q.responseMark = 3; + r.received(q); + } catch(...) {} + + try { + // Response mark lower than previous response mark. + q.responseMark = 0; + r.received(q); + } catch(...) {} + + // TODO aconway 2007-01-14: Test for batching when supported. + + } + + // expect may contain null chars so use string(ptr,size) constructor + // Use sizeof(expect)-1 to strip the trailing null. +#define ASSERT_FRAME(expect, frame) \ + CPPUNIT_ASSERT_EQUAL(string(expect, sizeof(expect)-1), boost::lexical_cast(frame)) + + void testRequestResponseRoundtrip() { + broker::InProcessBroker ibroker(version); + client::Connection clientConnection; + clientConnection.setConnector(ibroker); + clientConnection.open(""); + client::Channel c; + clientConnection.openChannel(c); + + client::Exchange exchange( + "MyExchange", client::Exchange::TOPIC_EXCHANGE); + client::Queue queue("MyQueue", true); + c.declareExchange(exchange); + c.declareQueue(queue); + c.bind(exchange, queue, "MyTopic", framing::FieldTable()); + broker::InProcessBroker::Conversation::const_iterator i = ibroker.conversation.begin(); + ASSERT_FRAME("BROKER: Frame[channel=0; request(id=1,mark=0): ConnectionStart: versionMajor=0; versionMinor=9; serverProperties={}; mechanisms=PLAIN; locales=en_US]", *i++); + ASSERT_FRAME("CLIENT: Frame[channel=0; response(id=1,request=1,batch=0): ConnectionStartOk: clientProperties={}; mechanism=PLAIN; response=\000guest\000guest; locale=en_US]", *i++); + ASSERT_FRAME("BROKER: Frame[channel=0; request(id=2,mark=1): ConnectionTune: channelMax=100; frameMax=65536; heartbeat=0]", *i++); + ASSERT_FRAME("CLIENT: Frame[channel=0; response(id=2,request=2,batch=0): ConnectionTuneOk: channelMax=100; frameMax=65536; heartbeat=0]", *i++); + ASSERT_FRAME("CLIENT: Frame[channel=0; request(id=1,mark=0): ConnectionOpen: virtualHost=/; capabilities=; insist=1]", *i++); + ASSERT_FRAME("BROKER: Frame[channel=0; response(id=1,request=1,batch=0): ConnectionOpenOk: knownHosts=]", *i++); + ASSERT_FRAME("CLIENT: Frame[channel=1; request(id=1,mark=0): ChannelOpen: outOfBand=]", *i++); + ASSERT_FRAME("BROKER: Frame[channel=1; response(id=1,request=1,batch=0): ChannelOpenOk: channelId=]", *i++); + ASSERT_FRAME("CLIENT: Frame[channel=1; request(id=2,mark=1): ExchangeDeclare: ticket=0; exchange=MyExchange; type=topic; passive=0; durable=0; autoDelete=0; internal=0; nowait=0; arguments={}]", *i++); + ASSERT_FRAME("BROKER: Frame[channel=1; response(id=2,request=2,batch=0): ExchangeDeclareOk: ]", *i++); + ASSERT_FRAME("CLIENT: Frame[channel=1; request(id=3,mark=2): QueueDeclare: ticket=0; queue=MyQueue; passive=0; durable=0; exclusive=1; autoDelete=1; nowait=0; arguments={}]", *i++); + ASSERT_FRAME("BROKER: Frame[channel=1; response(id=3,request=3,batch=0): QueueDeclareOk: queue=MyQueue; messageCount=0; consumerCount=0]", *i++); + ASSERT_FRAME("CLIENT: Frame[channel=1; request(id=4,mark=3): QueueBind: ticket=0; queue=MyQueue; exchange=MyExchange; routingKey=MyTopic; nowait=0; arguments={}]", *i++); + ASSERT_FRAME("BROKER: Frame[channel=1; response(id=4,request=4,batch=0): QueueBindOk: ]", *i++); + } + }; + + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(FramingTest); + + + diff --git a/qpid/cpp/src/tests/HeaderTest.cpp b/qpid/cpp/src/tests/HeaderTest.cpp new file mode 100644 index 0000000000..29e2ddee3d --- /dev/null +++ b/qpid/cpp/src/tests/HeaderTest.cpp @@ -0,0 +1,141 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 "../framing/amqp_framing.h" +#include "qpid_test_plugin.h" + +using namespace qpid::framing; + +class HeaderTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(HeaderTest); + CPPUNIT_TEST(testGenericProperties); + CPPUNIT_TEST(testAllSpecificProperties); + CPPUNIT_TEST(testSomeSpecificProperties); + CPPUNIT_TEST_SUITE_END(); + +public: + + void testGenericProperties() + { + AMQHeaderBody body(BASIC); + dynamic_cast(body.getProperties())->getHeaders().setString("A", "BCDE"); + Buffer buffer(100); + + body.encode(buffer); + buffer.flip(); + AMQHeaderBody body2; + body2.decode(buffer, body.size()); + BasicHeaderProperties* props = + dynamic_cast(body2.getProperties()); + CPPUNIT_ASSERT_EQUAL(std::string("BCDE"), + props->getHeaders().getString("A")); + } + + void testAllSpecificProperties(){ + string contentType("text/html"); + string contentEncoding("UTF8"); + DeliveryMode deliveryMode(PERSISTENT); + uint8_t priority(3); + string correlationId("abc"); + string replyTo("no-address"); + string expiration("why is this a string?"); + string messageId("xyz"); + uint64_t timestamp(0xabcd); + string type("eh?"); + string userId("guest"); + string appId("just testing"); + string clusterId("no clustering required"); + + AMQHeaderBody body(BASIC); + BasicHeaderProperties* properties = + dynamic_cast(body.getProperties()); + properties->setContentType(contentType); + properties->getHeaders().setString("A", "BCDE"); + properties->setDeliveryMode(deliveryMode); + properties->setPriority(priority); + properties->setCorrelationId(correlationId); + properties->setReplyTo(replyTo); + properties->setExpiration(expiration); + properties->setMessageId(messageId); + properties->setTimestamp(timestamp); + properties->setType(type); + properties->setUserId(userId); + properties->setAppId(appId); + properties->setClusterId(clusterId); + + Buffer buffer(10000); + body.encode(buffer); + buffer.flip(); + AMQHeaderBody temp; + temp.decode(buffer, body.size()); + properties = dynamic_cast(temp.getProperties()); + + CPPUNIT_ASSERT_EQUAL(contentType, properties->getContentType()); + CPPUNIT_ASSERT_EQUAL(std::string("BCDE"), properties->getHeaders().getString("A")); + CPPUNIT_ASSERT_EQUAL(deliveryMode, properties->getDeliveryMode()); + CPPUNIT_ASSERT_EQUAL(priority, properties->getPriority()); + CPPUNIT_ASSERT_EQUAL(correlationId, properties->getCorrelationId()); + CPPUNIT_ASSERT_EQUAL(replyTo, properties->getReplyTo()); + CPPUNIT_ASSERT_EQUAL(expiration, properties->getExpiration()); + CPPUNIT_ASSERT_EQUAL(messageId, properties->getMessageId()); + CPPUNIT_ASSERT_EQUAL(timestamp, properties->getTimestamp()); + CPPUNIT_ASSERT_EQUAL(type, properties->getType()); + CPPUNIT_ASSERT_EQUAL(userId, properties->getUserId()); + CPPUNIT_ASSERT_EQUAL(appId, properties->getAppId()); + CPPUNIT_ASSERT_EQUAL(clusterId, properties->getClusterId()); + } + + void testSomeSpecificProperties(){ + string contentType("application/octet-stream"); + DeliveryMode deliveryMode(PERSISTENT); + uint8_t priority(6); + string expiration("Z"); + uint64_t timestamp(0xabe4a34a); + + AMQHeaderBody body(BASIC); + BasicHeaderProperties* properties = + dynamic_cast(body.getProperties()); + properties->setContentType(contentType); + properties->setDeliveryMode(deliveryMode); + properties->setPriority(priority); + properties->setExpiration(expiration); + properties->setTimestamp(timestamp); + + Buffer buffer(100); + body.encode(buffer); + buffer.flip(); + AMQHeaderBody temp; + temp.decode(buffer, body.size()); + properties = dynamic_cast(temp.getProperties()); + + CPPUNIT_ASSERT_EQUAL(contentType, properties->getContentType()); + CPPUNIT_ASSERT_EQUAL((int) deliveryMode, (int) properties->getDeliveryMode()); + CPPUNIT_ASSERT_EQUAL((int) priority, (int) properties->getPriority()); + CPPUNIT_ASSERT_EQUAL(expiration, properties->getExpiration()); + CPPUNIT_ASSERT_EQUAL(timestamp, properties->getTimestamp()); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(HeaderTest); + diff --git a/qpid/cpp/src/tests/HeadersExchangeTest.cpp b/qpid/cpp/src/tests/HeadersExchangeTest.cpp new file mode 100644 index 0000000000..64125f4a0a --- /dev/null +++ b/qpid/cpp/src/tests/HeadersExchangeTest.cpp @@ -0,0 +1,115 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "../broker/HeadersExchange.h" +#include "../framing/FieldTable.h" +#include "../framing/Value.h" +#include "qpid_test_plugin.h" + +using namespace qpid::broker; +using namespace qpid::framing; + +class HeadersExchangeTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(HeadersExchangeTest); + CPPUNIT_TEST(testMatchAll); + CPPUNIT_TEST(testMatchAny); + CPPUNIT_TEST(testMatchEmptyValue); + CPPUNIT_TEST(testMatchEmptyArgs); + CPPUNIT_TEST(testMatchNoXMatch); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testMatchAll() + { + FieldTable b, m; + b.setString("x-match", "all"); + b.setString("foo", "FOO"); + b.setInt("n", 42); + m.setString("foo", "FOO"); + m.setInt("n", 42); + CPPUNIT_ASSERT(HeadersExchange::match(b, m)); + + // Ignore extras. + m.setString("extra", "x"); + CPPUNIT_ASSERT(HeadersExchange::match(b, m)); + + // Fail mismatch, wrong value. + m.setString("foo", "NotFoo"); + CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); + + // Fail mismatch, missing value + m.erase("foo"); + CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); + } + + void testMatchAny() + { + FieldTable b, m; + b.setString("x-match", "any"); + b.setString("foo", "FOO"); + b.setInt("n", 42); + m.setString("foo", "FOO"); + CPPUNIT_ASSERT(HeadersExchange::match(b, m)); + m.erase("foo"); + CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); + m.setInt("n", 42); + CPPUNIT_ASSERT(HeadersExchange::match(b, m)); + } + + void testMatchEmptyValue() + { + FieldTable b, m; + b.setString("x-match", "all"); + b.getMap()["foo"] = FieldTable::ValuePtr(new EmptyValue()); + b.getMap()["n"] = FieldTable::ValuePtr(new EmptyValue()); + CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); + m.setString("foo", "blah"); + m.setInt("n", 123); + } + + void testMatchEmptyArgs() + { + FieldTable b, m; + m.setString("foo", "FOO"); + + b.setString("x-match", "all"); + CPPUNIT_ASSERT(HeadersExchange::match(b, m)); + b.setString("x-match", "any"); + CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); + } + + + void testMatchNoXMatch() + { + FieldTable b, m; + b.setString("foo", "FOO"); + m.setString("foo", "FOO"); + CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); + } + + +}; + +// make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(HeadersExchangeTest); diff --git a/qpid/cpp/src/tests/InMemoryContentTest.cpp b/qpid/cpp/src/tests/InMemoryContentTest.cpp new file mode 100644 index 0000000000..6c7dd58258 --- /dev/null +++ b/qpid/cpp/src/tests/InMemoryContentTest.cpp @@ -0,0 +1,92 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/InMemoryContent.h" +#include "qpid_test_plugin.h" +#include "AMQP_HighestVersion.h" +#include +#include +#include "../framing/AMQFrame.h" +#include "MockChannel.h" + +using std::list; +using std::string; +using boost::dynamic_pointer_cast; +using namespace qpid::broker; +using namespace qpid::framing; + + +class InMemoryContentTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(InMemoryContentTest); + CPPUNIT_TEST(testRefragmentation); + CPPUNIT_TEST_SUITE_END(); + +public: + void testRefragmentation() + { + {//no remainder + string out[] = {"abcde", "fghij", "klmno", "pqrst"}; + string in[] = {out[0] + out[1], out[2] + out[3]}; + refragment(2, in, 4, out); + } + {//remainder for last frame + string out[] = {"abcde", "fghij", "klmno", "pqrst", "uvw"}; + string in[] = {out[0] + out[1], out[2] + out[3] + out[4]}; + refragment(2, in, 5, out); + } + } + + + void refragment(size_t inCount, string* in, size_t outCount, string* out, uint32_t framesize = 5) + { + InMemoryContent content; + MockChannel channel(3); + + addframes(content, inCount, in); + content.send(channel, framesize); + CPPUNIT_ASSERT_EQUAL(outCount, channel.out.frames.size()); + + for (unsigned int i = 0; i < outCount; i++) { + AMQContentBody::shared_ptr chunk( + dynamic_pointer_cast( + channel.out.frames[i].getBody())); + CPPUNIT_ASSERT(chunk); + CPPUNIT_ASSERT_EQUAL(out[i], chunk->getData()); + CPPUNIT_ASSERT_EQUAL( + ChannelId(3), channel.out.frames[i].getChannel()); + } + } + + void addframes(InMemoryContent& content, size_t frameCount, string* frameData) + { + for (unsigned int i = 0; i < frameCount; i++) { + AMQContentBody::shared_ptr frame(new AMQContentBody(frameData[i])); + content.add(frame); + } + } + + +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(InMemoryContentTest); + diff --git a/qpid/cpp/src/tests/InProcessBroker.h b/qpid/cpp/src/tests/InProcessBroker.h new file mode 100644 index 0000000000..ff94ddbe9f --- /dev/null +++ b/qpid/cpp/src/tests/InProcessBroker.h @@ -0,0 +1,163 @@ +#ifndef _tests_InProcessBroker_h +#define _tests_InProcessBroker_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 "AMQP_HighestVersion.h" +#include "../framing/AMQFrame.h" +#include "../broker/Broker.h" +#include "../broker/Connection.h" +#include "../client/Connector.h" +#include "../client/Connection.h" + +#include +#include +#include + + +namespace qpid { +namespace broker { + +/** + * A broker that implements client::Connector allowing direct + * in-process connection of client to broker. Used to write round-trip + * tests without requiring an external broker process. + * + * Also allows you to "snoop" on frames exchanged between client & broker. + * + * see FramingTest::testRequestResponseRoundtrip() for example of use. + */ +class InProcessBroker : public client::Connector { + public: + enum Sender {CLIENT,BROKER}; + + /** A frame tagged with the sender */ + struct TaggedFrame { + TaggedFrame(Sender e, framing::AMQFrame* f) : frame(f), sender(e) {} + bool fromBroker() const { return sender == BROKER; } + bool fromClient() const { return sender == CLIENT; } + + template + MethodType* asMethod() { + return dynamic_cast(frame->getBody().get()); + } + shared_ptr frame; + Sender sender; + }; + + typedef std::vector Conversation; + + InProcessBroker(framing::ProtocolVersion ver= + framing::highestProtocolVersion + ) : + Connector(ver), + protocolInit(ver), + broker(broker::Broker::create()), + brokerOut(BROKER, conversation), + brokerConnection(&brokerOut, *broker), + clientOut(CLIENT, conversation, &brokerConnection) + {} + + ~InProcessBroker() { broker->shutdown(); } + + void connect(const std::string& /*host*/, int /*port*/) {} + void init() { brokerConnection.initiated(protocolInit); } + void close() {} + + /** Client's input handler. */ + void setInputHandler(framing::InputHandler* handler) { + brokerOut.in = handler; + } + + /** Called by client to send a frame */ + void send(framing::AMQFrame* frame) { + clientOut.send(frame); + } + + /** Entire client-broker conversation is recorded here */ + Conversation conversation; + + private: + /** OutputHandler that forwards data to an InputHandler */ + struct OutputToInputHandler : public sys::ConnectionOutputHandler { + OutputToInputHandler( + Sender sender_, Conversation& conversation_, + framing::InputHandler* ih=0 + ) : sender(sender_), conversation(conversation_), in(ih) {} + + void send(framing::AMQFrame* frame) { + conversation.push_back(TaggedFrame(sender, frame)); + in->received(frame); + } + + void close() {} + + Sender sender; + Conversation& conversation; + framing::InputHandler* in; + }; + + framing::ProtocolInitiation protocolInit; + Broker::shared_ptr broker; + OutputToInputHandler brokerOut; + broker::Connection brokerConnection; + OutputToInputHandler clientOut; +}; + +std::ostream& operator<<( + std::ostream& out, const InProcessBroker::TaggedFrame& tf) +{ + return out << (tf.fromBroker()? "BROKER: ":"CLIENT: ") << *tf.frame; +} + +std::ostream& operator<<( + std::ostream& out, const InProcessBroker::Conversation& conv) +{ + copy(conv.begin(), conv.end(), + std::ostream_iterator(out, "\n")); + return out; +} + +} // namespace broker + + +namespace client { +/** An in-process client+broker all in one. */ +class InProcessBrokerClient : public client::Connection { + public: + broker::InProcessBroker broker; + broker::InProcessBroker::Conversation& conversation; + + /** Constructor creates broker and opens client connection. */ + InProcessBrokerClient( + u_int32_t max_frame_size=65536, + framing::ProtocolVersion version= framing::highestProtocolVersion + ) : client::Connection(false, max_frame_size, version), + broker(version), + conversation(broker.conversation) + { + setConnector(broker); + open(""); + } +}; + + +}} // namespace qpid::client + + +#endif // _tests_InProcessBroker_h diff --git a/qpid/cpp/src/tests/LazyLoadedContentTest.cpp b/qpid/cpp/src/tests/LazyLoadedContentTest.cpp new file mode 100644 index 0000000000..9d0da2206d --- /dev/null +++ b/qpid/cpp/src/tests/LazyLoadedContentTest.cpp @@ -0,0 +1,112 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/LazyLoadedContent.h" +#include "AMQP_HighestVersion.h" +#include "../broker/NullMessageStore.h" +#include "qpid_test_plugin.h" +#include +#include +#include +#include "../framing/AMQFrame.h" +#include "MockChannel.h" +using std::list; +using std::string; +using boost::dynamic_pointer_cast; +using namespace qpid::broker; +using namespace qpid::framing; + + + +class LazyLoadedContentTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(LazyLoadedContentTest); + CPPUNIT_TEST(testFragmented); + CPPUNIT_TEST(testWhole); + CPPUNIT_TEST(testHalved); + CPPUNIT_TEST_SUITE_END(); + + class TestMessageStore : public NullMessageStore + { + const string content; + + public: + TestMessageStore(const string& _content) : content(_content) {} + + void loadContent(PersistableMessage&, string& data, uint64_t offset, uint32_t length) + { + if (offset + length <= content.size()) { + data = content.substr(offset, length); + } else{ + std::stringstream error; + error << "Invalid segment: offset=" << offset << ", length=" << length << ", content_length=" << content.size(); + throw qpid::Exception(error.str()); + } + } + }; + + +public: + void testFragmented() + { + string data = "abcdefghijklmnopqrstuvwxyz"; + uint32_t framesize = 5; + string out[] = {"abcde", "fghij", "klmno", "pqrst", "uvwxy", "z"}; + load(data, 6, out, framesize); + } + + void testWhole() + { + string data = "abcdefghijklmnopqrstuvwxyz"; + uint32_t framesize = 50; + string out[] = {data}; + load(data, 1, out, framesize); + } + + void testHalved() + { + string data = "abcdefghijklmnopqrstuvwxyz"; + uint32_t framesize = 13; + string out[] = {"abcdefghijklm", "nopqrstuvwxyz"}; + load(data, 2, out, framesize); + } + + void load(string& in, size_t outCount, string* out, uint32_t framesize) + { + TestMessageStore store(in); + LazyLoadedContent content(&store, 0, in.size()); + MockChannel channel(3); + content.send(channel, framesize); + CPPUNIT_ASSERT_EQUAL(outCount, channel.out.frames.size()); + + for (unsigned int i = 0; i < outCount; i++) { + AMQContentBody::shared_ptr chunk(dynamic_pointer_cast(channel.out.frames[i].getBody())); + CPPUNIT_ASSERT(chunk); + CPPUNIT_ASSERT_EQUAL(out[i], chunk->getData()); + CPPUNIT_ASSERT_EQUAL( + ChannelId(3), channel.out.frames[i].getChannel()); + } + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(LazyLoadedContentTest); + diff --git a/qpid/cpp/src/tests/Makefile.am b/qpid/cpp/src/tests/Makefile.am new file mode 100644 index 0000000000..1b4b65fb4f --- /dev/null +++ b/qpid/cpp/src/tests/Makefile.am @@ -0,0 +1,117 @@ +AM_CXXFLAGS = $(WARNING_CFLAGS) $(CPPUNIT_CXXFLAGS) +INCLUDES = \ + -I$(srcdir)/../gen \ + $(APR_CXXFLAGS) + +# Unit tests +broker_tests = \ + AccumulatedAckTest \ + BrokerChannelTest \ + ConfigurationTest \ + ExchangeTest \ + HeadersExchangeTest \ + InMemoryContentTest \ + LazyLoadedContentTest \ + MessageBuilderTest \ + MessageTest \ + ReferenceTest \ + QueueRegistryTest \ + QueueTest \ + QueuePolicyTest \ + TopicExchangeTest \ + TxAckTest \ + TxBufferTest \ + TxPublishTest \ + ValueTest \ + MessageHandlerTest + +client_tests = \ + ClientChannelTest + +framing_tests = \ + FieldTableTest \ + FramingTest \ + HeaderTest + +misc_tests = \ + ProducerConsumerTest + +posix_tests = \ + EventChannelTest \ + EventChannelThreadsTest + +unit_tests = \ + $(broker_tests) \ + $(client_tests) \ + $(framing_tests) \ + $(misc_tests) + +# Executable client tests + +client_exe_tests = \ + client_test \ + echo_service \ + topic_listener \ + topic_publisher + +noinst_PROGRAMS = $(client_exe_tests) + +TESTS_ENVIRONMENT = \ + VALGRIND=$(VALGRIND) \ + abs_builddir='$(abs_builddir)' \ + PATH="$(abs_builddir)/../src$(PATH_SEPARATOR)$$PATH" \ + abs_srcdir='$(abs_srcdir)' + +CLIENT_TESTS = client_test quick_topictest +TESTS = run-unit-tests start_broker $(CLIENT_TESTS) python_tests kill_broker + +EXTRA_DIST = \ + $(TESTS) \ + .vg-supp \ + InProcessBroker.h \ + MockChannel.h \ + MockConnectionInputHandler.h \ + qpid_test_plugin.h \ + setup \ + topicall \ + topictest \ + APRBaseTest.cpp + +CLEANFILES=qpidd.log +DISTCLEANFILES=gen.mk + +include gen.mk + +check_LTLIBRARIES += libdlclose_noop.la +libdlclose_noop_la_LDFLAGS = -module -rpath /home/aconway/svn/qpid/cpp/tests +libdlclose_noop_la_SOURCES = dlclose_noop.c + + +abs_builddir = @abs_builddir@ +extra_libs = $(CPPUNIT_LIBS) +lib_client = $(abs_builddir)/../client/libqpidclient.la +lib_common = $(abs_builddir)/../libqpidcommon.la +lib_broker = $(abs_builddir)/../broker/libqpidbroker.la + +gen.mk: Makefile.am + ( \ + for i in $(client_exe_tests); do \ + echo $${i}_SOURCES = $$i.cpp; \ + echo $${i}_LDADD = '$$(lib_client) $$(lib_common) $$(extra_libs)'; \ + done; \ + libs=; \ + for i in $(unit_tests); do \ + libs="$$libs $${i}.la"; \ + echo $${i}_la_SOURCES = $$i.cpp; \ + echo $${i}_la_LIBADD = '$$(lib_common) $$(lib_client)'; \ + echo $${i}_la_LIBADD += '$$(lib_broker) $$(extra_libs)'; \ + echo $${i}_la_LDFLAGS = "-module -rpath `pwd`"; \ + done; \ + echo "check_LTLIBRARIES =$$libs"; \ + ) \ + > $@-t + mv $@-t $@ + +check: $(check_LTLIBRARIES) $(lib_common) $(lib_client) $(lib_broker) + +# Rule to run unit tests from an individual test module. diff --git a/qpid/cpp/src/tests/MessageBuilderTest.cpp b/qpid/cpp/src/tests/MessageBuilderTest.cpp new file mode 100644 index 0000000000..b660987708 --- /dev/null +++ b/qpid/cpp/src/tests/MessageBuilderTest.cpp @@ -0,0 +1,225 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" +#include "../broker/BrokerMessage.h" +#include "../broker/MessageBuilder.h" +#include "../broker/NullMessageStore.h" +#include "../framing/Buffer.h" +#include "qpid_test_plugin.h" +#include +#include +#include "MockChannel.h" + +using namespace boost; +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::sys; + +class MessageBuilderTest : public CppUnit::TestCase +{ + struct MockHandler : CompletionHandler { + Message::shared_ptr msg; + + virtual void complete(Message::shared_ptr _msg){ + msg = _msg; + } + }; + + class TestMessageStore : public NullMessageStore + { + Buffer* header; + Buffer* content; + const uint32_t contentBufferSize; + + public: + + void stage(PersistableMessage& msg) + { + if (msg.getPersistenceId() == 0) { + header = new Buffer(msg.encodedSize()); + msg.encode(*header); + content = new Buffer(contentBufferSize); + msg.setPersistenceId(1); + } else { + throw qpid::Exception("Message already staged!"); + } + } + + void appendContent(PersistableMessage& msg, const string& data) + { + if (msg.getPersistenceId() == 1) { + content->putRawData(data); + } else { + throw qpid::Exception("Invalid message id!"); + } + } + + using NullMessageStore::destroy; + + void destroy(PersistableMessage& msg) + { + CPPUNIT_ASSERT(msg.getPersistenceId()); + } + + BasicMessage::shared_ptr getRestoredMessage() + { + BasicMessage::shared_ptr msg(new BasicMessage()); + if (header) { + header->flip(); + msg->decodeHeader(*header); + delete header; + header = 0; + if (content) { + content->flip(); + msg->decodeContent(*content); + delete content; + content = 0; + } + } + return msg; + } + + //dont care about any of the other methods: + TestMessageStore(uint32_t _contentBufferSize) : NullMessageStore(), header(0), content(0), + contentBufferSize(_contentBufferSize) {} + ~TestMessageStore(){} + }; + + CPPUNIT_TEST_SUITE(MessageBuilderTest); + CPPUNIT_TEST(testHeaderOnly); + CPPUNIT_TEST(test1ContentFrame); + CPPUNIT_TEST(test2ContentFrames); + CPPUNIT_TEST(testStaging); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testHeaderOnly(){ + MockHandler handler; + MessageBuilder builder(&handler); + + Message::shared_ptr message( + new BasicMessage( + 0, "test", "my_routing_key", false, false, + MockChannel::basicGetBody())); + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + header->setContentSize(0); + + builder.initialise(message); + CPPUNIT_ASSERT(!handler.msg); + builder.setHeader(header); + CPPUNIT_ASSERT(handler.msg); + CPPUNIT_ASSERT_EQUAL(message, handler.msg); + } + + void test1ContentFrame(){ + MockHandler handler; + MessageBuilder builder(&handler); + + string data1("abcdefg"); + + Message::shared_ptr message( + new BasicMessage(0, "test", "my_routing_key", false, false, + MockChannel::basicGetBody())); + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + header->setContentSize(7); + AMQContentBody::shared_ptr part1(new AMQContentBody(data1)); + + builder.initialise(message); + CPPUNIT_ASSERT(!handler.msg); + builder.setHeader(header); + CPPUNIT_ASSERT(!handler.msg); + builder.addContent(part1); + CPPUNIT_ASSERT(handler.msg); + CPPUNIT_ASSERT_EQUAL(message, handler.msg); + } + + void test2ContentFrames(){ + MockHandler handler; + MessageBuilder builder(&handler); + + string data1("abcdefg"); + string data2("hijklmn"); + + Message::shared_ptr message( + new BasicMessage(0, "test", "my_routing_key", false, false, + MockChannel::basicGetBody())); + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + header->setContentSize(14); + AMQContentBody::shared_ptr part1(new AMQContentBody(data1)); + AMQContentBody::shared_ptr part2(new AMQContentBody(data2)); + + builder.initialise(message); + CPPUNIT_ASSERT(!handler.msg); + builder.setHeader(header); + CPPUNIT_ASSERT(!handler.msg); + builder.addContent(part1); + CPPUNIT_ASSERT(!handler.msg); + builder.addContent(part2); + CPPUNIT_ASSERT(handler.msg); + CPPUNIT_ASSERT_EQUAL(message, handler.msg); + } + + void testStaging(){ + //store must be the last thing to be destroyed or destructor + //of Message fails (it uses the store to call destroy if lazy + //loaded content is in use) + TestMessageStore store(14); + { + MockHandler handler; + MessageBuilder builder(&handler, &store, 5); + + string data1("abcdefg"); + string data2("hijklmn"); + + Message::shared_ptr message( + new BasicMessage(0, "test", "my_routing_key", false, false, + MockChannel::basicGetBody())); + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + header->setContentSize(14); + BasicHeaderProperties* properties = dynamic_cast(header->getProperties()); + properties->setMessageId("MyMessage"); + properties->getHeaders().setString("abc", "xyz"); + + AMQContentBody::shared_ptr part1(new AMQContentBody(data1)); + AMQContentBody::shared_ptr part2(new AMQContentBody(data2)); + + builder.initialise(message); + builder.setHeader(header); + builder.addContent(part1); + builder.addContent(part2); + CPPUNIT_ASSERT(handler.msg); + CPPUNIT_ASSERT_EQUAL(message, handler.msg); + + BasicMessage::shared_ptr restored = store.getRestoredMessage(); + CPPUNIT_ASSERT_EQUAL(message->getExchange(), restored->getExchange()); + CPPUNIT_ASSERT_EQUAL(message->getRoutingKey(), restored->getRoutingKey()); + CPPUNIT_ASSERT_EQUAL(message->getHeaderProperties()->getMessageId(), restored->getHeaderProperties()->getMessageId()); + CPPUNIT_ASSERT_EQUAL(message->getHeaderProperties()->getHeaders().getString("abc"), + restored->getHeaderProperties()->getHeaders().getString("abc")); + CPPUNIT_ASSERT_EQUAL((uint64_t) 14, restored->contentSize()); + } + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(MessageBuilderTest); diff --git a/qpid/cpp/src/tests/MessageHandlerTest.cpp b/qpid/cpp/src/tests/MessageHandlerTest.cpp new file mode 100644 index 0000000000..277c0fc4b9 --- /dev/null +++ b/qpid/cpp/src/tests/MessageHandlerTest.cpp @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +//#include +//#include +#include "../framing/amqp_framing.h" +#include "qpid_test_plugin.h" + +#include "../broker/BrokerAdapter.h" + +using namespace qpid::framing; +using namespace qpid::broker; + +class MessageHandlerTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(MessageHandlerTest); + CPPUNIT_TEST(testOpenMethod); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + + MessageHandlerTest() + { + } + + void testOpenMethod() + { + //AMQFrame frame(highestProtocolVersion, 0, method); + //TestBodyHandler handler(method); + //handler.handleBody(frame.getBody()); + } + +}; + + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(MessageHandlerTest); + diff --git a/qpid/cpp/src/tests/MessageTest.cpp b/qpid/cpp/src/tests/MessageTest.cpp new file mode 100644 index 0000000000..136c6f2d8d --- /dev/null +++ b/qpid/cpp/src/tests/MessageTest.cpp @@ -0,0 +1,88 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/BrokerMessage.h" +#include "qpid_test_plugin.h" +#include +#include "AMQP_HighestVersion.h" +#include "../framing/AMQFrame.h" +#include "MockChannel.h" + +using namespace boost; +using namespace qpid::broker; +using namespace qpid::framing; + +class MessageTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(MessageTest); + CPPUNIT_TEST(testEncodeDecode); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testEncodeDecode() + { + string exchange = "MyExchange"; + string routingKey = "MyRoutingKey"; + string messageId = "MyMessage"; + string data1("abcdefg"); + string data2("hijklmn"); + + BasicMessage::shared_ptr msg( + new BasicMessage(0, exchange, routingKey, false, false, + MockChannel::basicGetBody())); + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + header->setContentSize(14); + AMQContentBody::shared_ptr part1(new AMQContentBody(data1)); + AMQContentBody::shared_ptr part2(new AMQContentBody(data2)); + msg->setHeader(header); + msg->addContent(part1); + msg->addContent(part2); + + msg->getHeaderProperties()->setMessageId(messageId); + msg->getHeaderProperties()->setDeliveryMode(PERSISTENT); + msg->getHeaderProperties()->getHeaders().setString("abc", "xyz"); + + Buffer buffer(msg->encodedSize()); + msg->encode(buffer); + buffer.flip(); + + msg.reset(new BasicMessage()); + msg->decode(buffer); + CPPUNIT_ASSERT_EQUAL(exchange, msg->getExchange()); + CPPUNIT_ASSERT_EQUAL(routingKey, msg->getRoutingKey()); + CPPUNIT_ASSERT_EQUAL(messageId, msg->getHeaderProperties()->getMessageId()); + CPPUNIT_ASSERT_EQUAL(PERSISTENT, msg->getHeaderProperties()->getDeliveryMode()); + CPPUNIT_ASSERT_EQUAL(string("xyz"), msg->getHeaderProperties()->getHeaders().getString("abc")); + CPPUNIT_ASSERT_EQUAL((uint64_t) 14, msg->contentSize()); + + MockChannel channel(1); + msg->deliver(channel, "ignore", 0, 100); + CPPUNIT_ASSERT_EQUAL((size_t) 3, channel.out.frames.size()); + AMQContentBody::shared_ptr contentBody(dynamic_pointer_cast(channel.out.frames[2].getBody())); + CPPUNIT_ASSERT(contentBody); + CPPUNIT_ASSERT_EQUAL(data1 + data2, contentBody->getData()); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(MessageTest); + diff --git a/qpid/cpp/src/tests/MockChannel.h b/qpid/cpp/src/tests/MockChannel.h new file mode 100644 index 0000000000..e47d591a9e --- /dev/null +++ b/qpid/cpp/src/tests/MockChannel.h @@ -0,0 +1,70 @@ +#ifndef _tests_MockChannel_h +#define _tests_MockChannel_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 "../framing/MethodContext.h" +#include "../framing/ChannelAdapter.h" +#include "../framing/OutputHandler.h" +#include "../framing/AMQFrame.h" +#include "BasicGetBody.h" +#include +#include + +/** Mock output handler to collect frames */ +struct MockOutputHandler : public qpid::framing::OutputHandler { + boost::ptr_vector frames; + void send(qpid::framing::AMQFrame* frame){ frames.push_back(frame); } +}; + +/** + * Combination mock OutputHandler and ChannelAdapter for tests. + */ +struct MockChannel : public qpid::framing::ChannelAdapter +{ + typedef qpid::framing::BasicGetBody Body; + static Body::shared_ptr basicGetBody() { + return Body::shared_ptr( + new Body(qpid::framing::ProtocolVersion())); + } + + MockOutputHandler out; + + MockChannel(qpid::framing::ChannelId id) { + init(id, out, qpid::framing::ProtocolVersion()); + } + + bool isOpen() const { return true; } + + void handleHeader( + boost::shared_ptr b) { send(b); } + void handleContent( + boost::shared_ptr b) { send(b); } + void handleHeartbeat( + boost::shared_ptr b) { send(b); } + void handleMethodInContext( + boost::shared_ptr method, + const qpid::framing::MethodContext& context) + { + context.channel->send(method); + }; + +}; + +#endif /*!_tests_MockChannel_h*/ diff --git a/qpid/cpp/src/tests/MockConnectionInputHandler.h b/qpid/cpp/src/tests/MockConnectionInputHandler.h new file mode 100644 index 0000000000..4503ac33a5 --- /dev/null +++ b/qpid/cpp/src/tests/MockConnectionInputHandler.h @@ -0,0 +1,113 @@ +#ifndef _tests_MockConnectionInputHandler_h +#define _tests_MockConnectionInputHandler_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 "../sys/ConnectionInputHandler.h" +#include "../sys/ConnectionInputHandlerFactory.h" +#include "../sys/Monitor.h" +#include "../framing/ProtocolInitiation.h" + +struct MockConnectionInputHandler : public qpid::sys::ConnectionInputHandler { + + MockConnectionInputHandler() : state(START) {} + + ~MockConnectionInputHandler() {} + + void initiated(const qpid::framing::ProtocolInitiation& pi) { + qpid::sys::Monitor::ScopedLock l(monitor); + init = pi; + setState(GOT_INIT); + } + + void received(qpid::framing::AMQFrame* framep) { + qpid::sys::Monitor::ScopedLock l(monitor); + frame = *framep; + setState(GOT_FRAME); + } + + qpid::framing::ProtocolInitiation waitForProtocolInit() { + waitFor(GOT_INIT); + return init; + } + + qpid::framing::AMQFrame waitForFrame() { + waitFor(GOT_FRAME); + return frame; + } + + void waitForClosed() { + waitFor(CLOSED); + } + + void closed() { + qpid::sys::Monitor::ScopedLock l(monitor); + setState(CLOSED); + } + + void idleOut() {} + void idleIn() {} + + private: + typedef enum { START, GOT_INIT, GOT_FRAME, CLOSED } State; + + void setState(State s) { + state = s; + monitor.notify(); + } + + void waitFor(State s) { + qpid::sys::Monitor::ScopedLock l(monitor); + qpid::sys::Time deadline = qpid::sys::now() + 10*qpid::sys::TIME_SEC; + while (state != s) + CPPUNIT_ASSERT(monitor.wait(deadline)); + } + + qpid::sys::Monitor monitor; + State state; + qpid::framing::ProtocolInitiation init; + qpid::framing::AMQFrame frame; +}; + + +struct MockConnectionInputHandlerFactory : public qpid::sys::ConnectionInputHandlerFactory { + MockConnectionInputHandlerFactory() : handler(0) {} + + qpid::sys::ConnectionInputHandler* create(qpid::sys::ConnectionOutputHandler*) { + qpid::sys::Monitor::ScopedLock lock(monitor); + handler = new MockConnectionInputHandler(); + monitor.notifyAll(); + return handler; + } + + void waitForHandler() { + qpid::sys::Monitor::ScopedLock lock(monitor); + qpid::sys::Time deadline = + qpid::sys::now() + 500 * qpid::sys::TIME_SEC; + while (handler == 0) + CPPUNIT_ASSERT(monitor.wait(deadline)); + } + + MockConnectionInputHandler* handler; + qpid::sys::Monitor monitor; +}; + + + +#endif /*!_tests_MockConnectionInputHandler_h*/ diff --git a/qpid/cpp/src/tests/ProducerConsumerTest.cpp b/qpid/cpp/src/tests/ProducerConsumerTest.cpp new file mode 100644 index 0000000000..f2f3ab689a --- /dev/null +++ b/qpid/cpp/src/tests/ProducerConsumerTest.cpp @@ -0,0 +1,284 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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_test_plugin.h" +#include "InProcessBroker.h" +#include "../sys/ProducerConsumer.h" +#include "../sys/Thread.h" +#include "AMQP_HighestVersion.h" +#include "../sys/AtomicCount.h" + +using namespace qpid; +using namespace sys; +using namespace framing; +using namespace boost; +using namespace std; + +/** A counter that notifies a monitor when changed */ +class WatchedCounter : public Monitor { + public: + WatchedCounter(int i=0) : count(i) {} + WatchedCounter(const WatchedCounter& c) : Monitor(), count(int(c)) {} + + WatchedCounter& operator=(const WatchedCounter& x) { + return *this = int(x); + } + + WatchedCounter& operator=(int i) { + Lock l(*this); + count = i; + return *this; + } + + int operator++() { + Lock l(*this); + notifyAll(); + return ++count; + } + + int operator++(int) { + Lock l(*this); + notifyAll(); + return count++; + } + + bool operator==(int i) const { + Lock l(const_cast(*this)); + return i == count; + } + + operator int() const { + Lock l(const_cast(*this)); + return count; + } + + bool waitFor(int i, Time timeout=TIME_SEC) { + Lock l(*this); + Time deadline = timeout+now(); + while (count != i) { + if (!wait(deadline)) + return false; + } + assert(count == i); + return true; + } + + private: + typedef Mutex::ScopedLock Lock; + int count; +}; + +class ProducerConsumerTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(ProducerConsumerTest); + CPPUNIT_TEST(testProduceConsume); + CPPUNIT_TEST(testTimeout); + CPPUNIT_TEST(testShutdown); + CPPUNIT_TEST(testCancel); + CPPUNIT_TEST_SUITE_END(); + + public: + client::InProcessBrokerClient client; + ProducerConsumer pc; + + WatchedCounter shutdown; + WatchedCounter timeout; + WatchedCounter consumed; + WatchedCounter produced; + + struct ConsumeRunnable : public Runnable { + ProducerConsumerTest& test; + ConsumeRunnable(ProducerConsumerTest& test_) : test(test_) {} + void run() { test.consume(); } + }; + + struct ConsumeTimeoutRunnable : public Runnable { + ProducerConsumerTest& test; + Time timeout; + ConsumeTimeoutRunnable(ProducerConsumerTest& test_, const Time& t) + : test(test_), timeout(t) {} + void run() { test.consumeTimeout(timeout); } + }; + + + void consumeInternal(ProducerConsumer::ConsumerLock& consumer) { + if (pc.isShutdown()) { + ++shutdown; + return; + } + if (consumer.isTimedOut()) { + ++timeout; + return; + } + CPPUNIT_ASSERT(consumer.isOk()); + CPPUNIT_ASSERT(pc.available() > 0); + consumer.confirm(); + consumed++; + } + + void consume() { + ProducerConsumer::ConsumerLock consumer(pc); + consumeInternal(consumer); + }; + + void consumeTimeout(const Time& timeout) { + ProducerConsumer::ConsumerLock consumer(pc, timeout); + consumeInternal(consumer); + }; + + void produce() { + ProducerConsumer::ProducerLock producer(pc); + CPPUNIT_ASSERT(producer.isOk()); + producer.confirm(); + produced++; + } + + void join(vector& threads) { + for_each(threads.begin(), threads.end(), bind(&Thread::join,_1)); + } + + vector startThreads(size_t n, Runnable& runnable) { + vector threads(n); + while (n > 0) + threads[--n] = Thread(runnable); + return threads; + } + +public: + ProducerConsumerTest() : client() {} + + void testProduceConsume() { + ConsumeRunnable runMe(*this); + produce(); + produce(); + CPPUNIT_ASSERT(produced.waitFor(2)); + vector threads = startThreads(1, runMe); + CPPUNIT_ASSERT(consumed.waitFor(1)); + join(threads); + + threads = startThreads(1, runMe); + CPPUNIT_ASSERT(consumed.waitFor(2)); + join(threads); + + threads = startThreads(3, runMe); + produce(); + produce(); + CPPUNIT_ASSERT(consumed.waitFor(4)); + produce(); + CPPUNIT_ASSERT(consumed.waitFor(5)); + join(threads); + CPPUNIT_ASSERT_EQUAL(0, int(shutdown)); + } + + void testTimeout() { + try { + // 0 timeout no items available throws exception + ProducerConsumer::ConsumerLock consumer(pc, 0); + CPPUNIT_FAIL("Expected exception"); + } catch(...){} + + produce(); + CPPUNIT_ASSERT(produced.waitFor(1)); + CPPUNIT_ASSERT_EQUAL(1, int(pc.available())); + { + // 0 timeout succeeds if there's an item available. + ProducerConsumer::ConsumerLock consume(pc, 0); + CPPUNIT_ASSERT(consume.isOk()); + consume.confirm(); + } + CPPUNIT_ASSERT_EQUAL(0, int(pc.available())); + + // Produce an item within the timeout. + ConsumeTimeoutRunnable runMe(*this, 2*TIME_SEC); + vector threads = startThreads(1, runMe); + produce(); + CPPUNIT_ASSERT(consumed.waitFor(1)); + join(threads); + } + + + void testShutdown() { + ConsumeRunnable runMe(*this); + vector threads = startThreads(2, runMe); + while (pc.consumers() != 2) + Thread::yield(); + pc.shutdown(); + CPPUNIT_ASSERT(shutdown.waitFor(2)); + join(threads); + + threads = startThreads(1, runMe); // Should shutdown immediately. + CPPUNIT_ASSERT(shutdown.waitFor(3)); + join(threads); + + // Produce/consume while shutdown should return isShutdown and + // throw on confirm. + try { + ProducerConsumer::ProducerLock p(pc); + CPPUNIT_ASSERT(pc.isShutdown()); + CPPUNIT_FAIL("Expected exception"); + } + catch (...) {} // Expected + try { + ProducerConsumer::ConsumerLock c(pc); + CPPUNIT_ASSERT(pc.isShutdown()); + CPPUNIT_FAIL("Expected exception"); + } + catch (...) {} // Expected + } + + void testCancel() { + CPPUNIT_ASSERT_EQUAL(size_t(0), pc.available()); + { + ProducerConsumer::ProducerLock p(pc); + CPPUNIT_ASSERT(p.isOk()); + p.cancel(); + } + // Nothing was produced. + CPPUNIT_ASSERT_EQUAL(size_t(0), pc.available()); + { + ProducerConsumer::ConsumerLock c(pc, 0); + CPPUNIT_ASSERT(c.isTimedOut()); + } + // Now produce but cancel the consume + { + ProducerConsumer::ProducerLock p(pc); + CPPUNIT_ASSERT(p.isOk()); + p.confirm(); + } + CPPUNIT_ASSERT_EQUAL(size_t(1), pc.available()); + { + ProducerConsumer::ConsumerLock c(pc); + CPPUNIT_ASSERT(c.isOk()); + c.cancel(); + } + CPPUNIT_ASSERT_EQUAL(size_t(1), pc.available()); + } +}; + + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(ProducerConsumerTest); + diff --git a/qpid/cpp/src/tests/QueuePolicyTest.cpp b/qpid/cpp/src/tests/QueuePolicyTest.cpp new file mode 100644 index 0000000000..5ccc9417cd --- /dev/null +++ b/qpid/cpp/src/tests/QueuePolicyTest.cpp @@ -0,0 +1,89 @@ + /* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/QueuePolicy.h" +#include "qpid_test_plugin.h" + +using namespace qpid::broker; +using namespace qpid::framing; + +class QueuePolicyTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(QueuePolicyTest); + CPPUNIT_TEST(testCount); + CPPUNIT_TEST(testSize); + CPPUNIT_TEST(testBoth); + CPPUNIT_TEST(testSettings); + CPPUNIT_TEST_SUITE_END(); + + public: + void testCount(){ + QueuePolicy policy(5, 0); + CPPUNIT_ASSERT(!policy.limitExceeded()); + for (int i = 0; i < 5; i++) policy.enqueued(10); + CPPUNIT_ASSERT_EQUAL((uint64_t) 0, policy.getMaxSize()); + CPPUNIT_ASSERT_EQUAL((uint32_t) 5, policy.getMaxCount()); + CPPUNIT_ASSERT(!policy.limitExceeded()); + policy.enqueued(10); + CPPUNIT_ASSERT(policy.limitExceeded()); + policy.dequeued(10); + CPPUNIT_ASSERT(!policy.limitExceeded()); + policy.enqueued(10); + CPPUNIT_ASSERT(policy.limitExceeded()); + } + + void testSize(){ + QueuePolicy policy(0, 50); + for (int i = 0; i < 5; i++) policy.enqueued(10); + CPPUNIT_ASSERT(!policy.limitExceeded()); + policy.enqueued(10); + CPPUNIT_ASSERT(policy.limitExceeded()); + policy.dequeued(10); + CPPUNIT_ASSERT(!policy.limitExceeded()); + policy.enqueued(10); + CPPUNIT_ASSERT(policy.limitExceeded()); + } + + void testBoth(){ + QueuePolicy policy(5, 50); + for (int i = 0; i < 5; i++) policy.enqueued(11); + CPPUNIT_ASSERT(policy.limitExceeded()); + policy.dequeued(20); + CPPUNIT_ASSERT(!policy.limitExceeded());//fails + policy.enqueued(5); + policy.enqueued(10); + CPPUNIT_ASSERT(policy.limitExceeded()); + } + + void testSettings(){ + //test reading and writing the policy from/to field table + FieldTable settings; + QueuePolicy a(101, 303); + a.update(settings); + QueuePolicy b(settings); + CPPUNIT_ASSERT_EQUAL(a.getMaxCount(), b.getMaxCount()); + CPPUNIT_ASSERT_EQUAL(a.getMaxSize(), b.getMaxSize()); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(QueuePolicyTest); + diff --git a/qpid/cpp/src/tests/QueueRegistryTest.cpp b/qpid/cpp/src/tests/QueueRegistryTest.cpp new file mode 100644 index 0000000000..d01fbd0ad4 --- /dev/null +++ b/qpid/cpp/src/tests/QueueRegistryTest.cpp @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "../broker/QueueRegistry.h" +#include "qpid_test_plugin.h" +#include + +using namespace qpid::broker; + +class QueueRegistryTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(QueueRegistryTest); + CPPUNIT_TEST(testDeclare); + CPPUNIT_TEST(testDeclareTmp); + CPPUNIT_TEST(testFind); + CPPUNIT_TEST(testDestroy); + CPPUNIT_TEST_SUITE_END(); + + private: + std::string foo, bar; + QueueRegistry reg; + std::pair qc; + + public: + void setUp() { + foo = "foo"; + bar = "bar"; + } + + void testDeclare() { + qc = reg.declare(foo, false, 0, 0); + Queue::shared_ptr q = qc.first; + CPPUNIT_ASSERT(q); + CPPUNIT_ASSERT(qc.second); // New queue + CPPUNIT_ASSERT_EQUAL(foo, q->getName()); + + qc = reg.declare(foo, false, 0, 0); + CPPUNIT_ASSERT_EQUAL(q, qc.first); + CPPUNIT_ASSERT(!qc.second); + + qc = reg.declare(bar, false, 0, 0); + q = qc.first; + CPPUNIT_ASSERT(q); + CPPUNIT_ASSERT_EQUAL(true, qc.second); + CPPUNIT_ASSERT_EQUAL(bar, q->getName()); + } + + void testDeclareTmp() + { + qc = reg.declare(std::string(), false, 0, 0); + CPPUNIT_ASSERT(qc.second); + CPPUNIT_ASSERT_EQUAL(std::string("tmp_1"), qc.first->getName()); + } + + void testFind() { + CPPUNIT_ASSERT(reg.find(foo) == 0); + + reg.declare(foo, false, 0, 0); + reg.declare(bar, false, 0, 0); + Queue::shared_ptr q = reg.find(bar); + CPPUNIT_ASSERT(q); + CPPUNIT_ASSERT_EQUAL(bar, q->getName()); + } + + void testDestroy() { + qc = reg.declare(foo, false, 0, 0); + reg.destroy(foo); + // Queue is gone from the registry. + CPPUNIT_ASSERT(reg.find(foo) == 0); + // Queue is not actually destroyed till we drop our reference. + CPPUNIT_ASSERT_EQUAL(foo, qc.first->getName()); + // We shoud be the only reference. + CPPUNIT_ASSERT_EQUAL(1L, qc.first.use_count()); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(QueueRegistryTest); diff --git a/qpid/cpp/src/tests/QueueTest.cpp b/qpid/cpp/src/tests/QueueTest.cpp new file mode 100644 index 0000000000..bb2b424375 --- /dev/null +++ b/qpid/cpp/src/tests/QueueTest.cpp @@ -0,0 +1,149 @@ + /* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/BrokerQueue.h" +#include "../broker/QueueRegistry.h" +#include "qpid_test_plugin.h" +#include +#include "MockChannel.h" + +using namespace qpid::broker; +using namespace qpid::sys; + + +class TestConsumer : public virtual Consumer{ +public: + Message::shared_ptr last; + + virtual bool deliver(Message::shared_ptr& msg); +}; + + +class QueueTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(QueueTest); + CPPUNIT_TEST(testConsumers); + CPPUNIT_TEST(testRegistry); + CPPUNIT_TEST(testDequeue); + CPPUNIT_TEST_SUITE_END(); + + public: + Message::shared_ptr message(std::string exchange, std::string routingKey) { + return Message::shared_ptr( + new BasicMessage(0, exchange, routingKey, true, true, + MockChannel::basicGetBody())); + } + + void testConsumers(){ + Queue::shared_ptr queue(new Queue("my_queue", true)); + + //Test adding consumers: + TestConsumer c1; + TestConsumer c2; + queue->consume(&c1); + queue->consume(&c2); + + CPPUNIT_ASSERT_EQUAL(uint32_t(2), queue->getConsumerCount()); + + //Test basic delivery: + Message::shared_ptr msg1 = message("e", "A"); + Message::shared_ptr msg2 = message("e", "B"); + Message::shared_ptr msg3 = message("e", "C"); + + queue->deliver(msg1); + CPPUNIT_ASSERT_EQUAL(msg1.get(), c1.last.get()); + + queue->deliver(msg2); + CPPUNIT_ASSERT_EQUAL(msg2.get(), c2.last.get()); + + queue->deliver(msg3); + CPPUNIT_ASSERT_EQUAL(msg3.get(), c1.last.get()); + + //Test cancellation: + queue->cancel(&c1); + CPPUNIT_ASSERT_EQUAL(uint32_t(1), queue->getConsumerCount()); + queue->cancel(&c2); + CPPUNIT_ASSERT_EQUAL(uint32_t(0), queue->getConsumerCount()); + } + + void testRegistry(){ + //Test use of queues in registry: + QueueRegistry registry; + registry.declare("queue1", true, true); + registry.declare("queue2", true, true); + registry.declare("queue3", true, true); + + CPPUNIT_ASSERT(registry.find("queue1")); + CPPUNIT_ASSERT(registry.find("queue2")); + CPPUNIT_ASSERT(registry.find("queue3")); + + registry.destroy("queue1"); + registry.destroy("queue2"); + registry.destroy("queue3"); + + CPPUNIT_ASSERT(!registry.find("queue1")); + CPPUNIT_ASSERT(!registry.find("queue2")); + CPPUNIT_ASSERT(!registry.find("queue3")); + } + + void testDequeue(){ + Queue::shared_ptr queue(new Queue("my_queue", true)); + Message::shared_ptr msg1 = message("e", "A"); + Message::shared_ptr msg2 = message("e", "B"); + Message::shared_ptr msg3 = message("e", "C"); + Message::shared_ptr received; + + queue->deliver(msg1); + queue->deliver(msg2); + queue->deliver(msg3); + + CPPUNIT_ASSERT_EQUAL(uint32_t(3), queue->getMessageCount()); + + received = queue->dequeue(); + CPPUNIT_ASSERT_EQUAL(msg1.get(), received.get()); + CPPUNIT_ASSERT_EQUAL(uint32_t(2), queue->getMessageCount()); + + received = queue->dequeue(); + CPPUNIT_ASSERT_EQUAL(msg2.get(), received.get()); + CPPUNIT_ASSERT_EQUAL(uint32_t(1), queue->getMessageCount()); + + TestConsumer consumer; + queue->consume(&consumer); + queue->dispatch(); + CPPUNIT_ASSERT_EQUAL(msg3.get(), consumer.last.get()); + CPPUNIT_ASSERT_EQUAL(uint32_t(0), queue->getMessageCount()); + + received = queue->dequeue(); + CPPUNIT_ASSERT(!received); + CPPUNIT_ASSERT_EQUAL(uint32_t(0), queue->getMessageCount()); + + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(QueueTest); + +//TestConsumer +bool TestConsumer::deliver(Message::shared_ptr& msg){ + last = msg; + return true; +} + diff --git a/qpid/cpp/src/tests/ReferenceTest.cpp b/qpid/cpp/src/tests/ReferenceTest.cpp new file mode 100644 index 0000000000..b179ab8fdd --- /dev/null +++ b/qpid/cpp/src/tests/ReferenceTest.cpp @@ -0,0 +1,102 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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_test_plugin.h" +#include "../broker/Reference.h" +#include "../broker/BrokerMessageMessage.h" +#include "MessageTransferBody.h" +#include "MessageAppendBody.h" +#include "../broker/CompletionHandler.h" + +using namespace boost; +using namespace qpid::broker; +using namespace qpid::framing; +using namespace std; + +class ReferenceTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(ReferenceTest); + CPPUNIT_TEST(testRegistry); + CPPUNIT_TEST(testReference); + CPPUNIT_TEST_SUITE_END(); + + ProtocolVersion v; + ReferenceRegistry registry; + Reference::shared_ptr r1; + MessageTransferBody::shared_ptr t1, t2; + MessageMessage::shared_ptr m1, m2; + MessageAppendBody::shared_ptr a1, a2; + public: + + ReferenceTest() : + r1(registry.open("bar")), + t1(new MessageTransferBody(v)), + t2(new MessageTransferBody(v)), + m1(new MessageMessage(0, 1, t1, r1)), + m2(new MessageMessage(0, 2, t2, r1)), + a1(new MessageAppendBody(v)), + a2(new MessageAppendBody(v)) + {} + + void testRegistry() { + Reference::shared_ptr ref = registry.open("foo"); + CPPUNIT_ASSERT_EQUAL(string("foo"), ref->getId()); + CPPUNIT_ASSERT(ref == registry.get("foo")); + try { + registry.get("none"); + CPPUNIT_FAIL("Expected exception"); + } catch (...) {} + try { + registry.open("foo"); + CPPUNIT_FAIL("Expected exception"); + } catch(...) {} + } + + void testReference() { + r1->addMessage(m1); + r1->addMessage(m2); + CPPUNIT_ASSERT_EQUAL(size_t(2), r1->getMessages().size()); + r1->append(a1); + r1->append(a2); + CPPUNIT_ASSERT_EQUAL(size_t(2), r1->getAppends().size()); + const vector messages = r1->getMessages(); + r1->close(); + try { + registry.open("bar"); + CPPUNIT_FAIL("Expected exception"); + } catch(...) {} + + CPPUNIT_ASSERT_EQUAL(messages[0], m1); + CPPUNIT_ASSERT_EQUAL(messages[0]->getReference()->getAppends()[0], a1); + CPPUNIT_ASSERT_EQUAL(messages[0]->getReference()->getAppends()[1], a2); + + CPPUNIT_ASSERT_EQUAL(messages[1], m2); + CPPUNIT_ASSERT_EQUAL(messages[1]->getReference()->getAppends()[0], a1); + CPPUNIT_ASSERT_EQUAL(messages[1]->getReference()->getAppends()[1], a2); + } + + +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(ReferenceTest); diff --git a/qpid/cpp/src/tests/TopicExchangeTest.cpp b/qpid/cpp/src/tests/TopicExchangeTest.cpp new file mode 100644 index 0000000000..39035c776f --- /dev/null +++ b/qpid/cpp/src/tests/TopicExchangeTest.cpp @@ -0,0 +1,200 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "../broker/TopicExchange.h" +#include "qpid_test_plugin.h" + +using namespace qpid::broker; + +Tokens makeTokens(char** begin, char** end) +{ + Tokens t; + t.insert(t.end(), begin, end); + return t; +} + +// Calculate size of an array. +#define LEN(a) (sizeof(a)/sizeof(a[0])) + +// Convert array to token vector +#define TOKENS(a) makeTokens(a, a + LEN(a)) + +// Allow CPPUNIT_EQUALS to print a Tokens. +CppUnit::OStringStream& operator <<(CppUnit::OStringStream& out, const Tokens& v) +{ + out << "[ "; + for (Tokens::const_iterator i = v.begin(); + i != v.end(); ++i) + { + out << '"' << *i << '"' << (i+1 == v.end() ? "]" : ", "); + } + return out; +} + + +class TokensTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(TokensTest); + CPPUNIT_TEST(testTokens); + CPPUNIT_TEST_SUITE_END(); + + public: + void testTokens() + { + Tokens tokens("hello.world"); + char* expect[] = {"hello", "world"}; + CPPUNIT_ASSERT_EQUAL(TOKENS(expect), tokens); + + tokens = "a.b.c"; + char* expect2[] = { "a", "b", "c" }; + CPPUNIT_ASSERT_EQUAL(TOKENS(expect2), tokens); + + tokens = ""; + CPPUNIT_ASSERT(tokens.empty()); + + tokens = "x"; + char* expect3[] = { "x" }; + CPPUNIT_ASSERT_EQUAL(TOKENS(expect3), tokens); + + tokens = (".x"); + char* expect4[] = { "", "x" }; + CPPUNIT_ASSERT_EQUAL(TOKENS(expect4), tokens); + + tokens = ("x."); + char* expect5[] = { "x", "" }; + CPPUNIT_ASSERT_EQUAL(TOKENS(expect5), tokens); + + tokens = ("."); + char* expect6[] = { "", "" }; + CPPUNIT_ASSERT_EQUAL(TOKENS(expect6), tokens); + + tokens = (".."); + char* expect7[] = { "", "", "" }; + CPPUNIT_ASSERT_EQUAL(TOKENS(expect7), tokens); + } + +}; + +#define ASSERT_NORMALIZED(expect, pattern) \ + CPPUNIT_ASSERT_EQUAL(Tokens(expect), static_cast(TopicPattern(pattern))) +class TopicPatternTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(TopicPatternTest); + CPPUNIT_TEST(testNormalize); + CPPUNIT_TEST(testPlain); + CPPUNIT_TEST(testStar); + CPPUNIT_TEST(testHash); + CPPUNIT_TEST(testMixed); + CPPUNIT_TEST(testCombo); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testNormalize() + { + CPPUNIT_ASSERT(TopicPattern("").empty()); + ASSERT_NORMALIZED("a.b.c", "a.b.c"); + ASSERT_NORMALIZED("a.*.c", "a.*.c"); + ASSERT_NORMALIZED("#", "#"); + ASSERT_NORMALIZED("#", "#.#.#.#"); + ASSERT_NORMALIZED("*.*.*.#", "#.*.#.*.#.#.*"); + ASSERT_NORMALIZED("a.*.*.*.#", "a.*.#.*.#.*.#"); + ASSERT_NORMALIZED("a.*.*.*.#", "a.*.#.*.#.*"); + } + + void testPlain() { + TopicPattern p("ab.cd.e"); + CPPUNIT_ASSERT(p.match("ab.cd.e")); + CPPUNIT_ASSERT(!p.match("abx.cd.e")); + CPPUNIT_ASSERT(!p.match("ab.cd")); + CPPUNIT_ASSERT(!p.match("ab.cd..e.")); + CPPUNIT_ASSERT(!p.match("ab.cd.e.")); + CPPUNIT_ASSERT(!p.match(".ab.cd.e")); + + p = ""; + CPPUNIT_ASSERT(p.match("")); + + p = "."; + CPPUNIT_ASSERT(p.match(".")); + } + + + void testStar() + { + TopicPattern p("a.*.b"); + CPPUNIT_ASSERT(p.match("a.xx.b")); + CPPUNIT_ASSERT(!p.match("a.b")); + + p = "*.x"; + CPPUNIT_ASSERT(p.match("y.x")); + CPPUNIT_ASSERT(p.match(".x")); + CPPUNIT_ASSERT(!p.match("x")); + + p = "x.x.*"; + CPPUNIT_ASSERT(p.match("x.x.y")); + CPPUNIT_ASSERT(p.match("x.x.")); + CPPUNIT_ASSERT(!p.match("x.x")); + CPPUNIT_ASSERT(!p.match("q.x.y")); + } + + void testHash() + { + TopicPattern p("a.#.b"); + CPPUNIT_ASSERT(p.match("a.b")); + CPPUNIT_ASSERT(p.match("a.x.b")); + CPPUNIT_ASSERT(p.match("a..x.y.zz.b")); + CPPUNIT_ASSERT(!p.match("a.b.")); + CPPUNIT_ASSERT(!p.match("q.x.b")); + + p = "a.#"; + CPPUNIT_ASSERT(p.match("a")); + CPPUNIT_ASSERT(p.match("a.b")); + CPPUNIT_ASSERT(p.match("a.b.c")); + + p = "#.a"; + CPPUNIT_ASSERT(p.match("a")); + CPPUNIT_ASSERT(p.match("x.y.a")); + } + + void testMixed() + { + TopicPattern p("*.x.#.y"); + CPPUNIT_ASSERT(p.match("a.x.y")); + CPPUNIT_ASSERT(p.match("a.x.p.qq.y")); + CPPUNIT_ASSERT(!p.match("a.a.x.y")); + CPPUNIT_ASSERT(!p.match("aa.x.b.c")); + + p = "a.#.b.*"; + CPPUNIT_ASSERT(p.match("a.b.x")); + CPPUNIT_ASSERT(p.match("a.x.x.x.b.x")); + } + + void testCombo() { + TopicPattern p("*.#.#.*.*.#"); + CPPUNIT_ASSERT(p.match("x.y.z")); + CPPUNIT_ASSERT(p.match("x.y.z.a.b.c")); + CPPUNIT_ASSERT(!p.match("x.y")); + CPPUNIT_ASSERT(!p.match("x")); + } +}; + + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(TopicPatternTest); +CPPUNIT_TEST_SUITE_REGISTRATION(TokensTest); diff --git a/qpid/cpp/src/tests/TxAckTest.cpp b/qpid/cpp/src/tests/TxAckTest.cpp new file mode 100644 index 0000000000..91e07a3faa --- /dev/null +++ b/qpid/cpp/src/tests/TxAckTest.cpp @@ -0,0 +1,113 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/NullMessageStore.h" +#include "../broker/RecoveryManager.h" +#include "../broker/TxAck.h" +#include "qpid_test_plugin.h" +#include +#include +#include +#include "MockChannel.h" + +using std::list; +using std::vector; +using namespace qpid::broker; +using namespace qpid::framing; + +class TxAckTest : public CppUnit::TestCase +{ + + class TestMessageStore : public NullMessageStore + { + public: + vector dequeued; + + void dequeue(TransactionContext*, PersistableMessage& msg, const PersistableQueue& /*queue*/) + { + dequeued.push_back(&msg); + } + + TestMessageStore() : NullMessageStore() {} + ~TestMessageStore(){} + }; + + CPPUNIT_TEST_SUITE(TxAckTest); + CPPUNIT_TEST(testPrepare); + CPPUNIT_TEST(testCommit); + CPPUNIT_TEST_SUITE_END(); + + + AccumulatedAck acked; + TestMessageStore store; + Queue::shared_ptr queue; + vector messages; + list deliveries; + TxAck op; + + +public: + + TxAckTest() : acked(0), queue(new Queue("my_queue", false, &store, 0)), op(acked, deliveries) + { + for(int i = 0; i < 10; i++){ + Message::shared_ptr msg( + new BasicMessage(0, "exchange", "routing_key", false, false, + MockChannel::basicGetBody())); + msg->setHeader(AMQHeaderBody::shared_ptr(new AMQHeaderBody(BASIC))); + msg->getHeaderProperties()->setDeliveryMode(PERSISTENT); + messages.push_back(msg); + deliveries.push_back(DeliveryRecord(msg, queue, "xyz", (i+1))); + } + + //assume msgs 1-5, 7 and 9 are all acked (i.e. 6, 8 & 10 are not) + acked.range = 5; + acked.individual.push_back(7); + acked.individual.push_back(9); + } + + void testPrepare() + { + //ensure acked messages are discarded, i.e. dequeued from store + op.prepare(0); + CPPUNIT_ASSERT_EQUAL((size_t) 7, store.dequeued.size()); + CPPUNIT_ASSERT_EQUAL((size_t) 10, deliveries.size()); + int dequeued[] = {0, 1, 2, 3, 4, 6, 8}; + for (int i = 0; i < 7; i++) { + CPPUNIT_ASSERT_EQUAL((PersistableMessage*) messages[dequeued[i]].get(), store.dequeued[i]); + } + } + + void testCommit() + { + //emsure acked messages are removed from list + op.commit(); + CPPUNIT_ASSERT_EQUAL((size_t) 3, deliveries.size()); + list::iterator i = deliveries.begin(); + CPPUNIT_ASSERT(i->matches(6));//msg 6 + CPPUNIT_ASSERT((++i)->matches(8));//msg 8 + CPPUNIT_ASSERT((++i)->matches(10));//msg 10 + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(TxAckTest); + diff --git a/qpid/cpp/src/tests/TxBufferTest.cpp b/qpid/cpp/src/tests/TxBufferTest.cpp new file mode 100644 index 0000000000..0d1fe7a04b --- /dev/null +++ b/qpid/cpp/src/tests/TxBufferTest.cpp @@ -0,0 +1,269 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/TxBuffer.h" +#include "qpid_test_plugin.h" +#include +#include + +using namespace qpid::broker; + +template void assertEqualVector(std::vector& expected, std::vector& actual){ + unsigned int i = 0; + while(i < expected.size() && i < actual.size()){ + CPPUNIT_ASSERT_EQUAL(expected[i], actual[i]); + i++; + } + CPPUNIT_ASSERT(i == expected.size()); + CPPUNIT_ASSERT(i == actual.size()); +} + +class TxBufferTest : public CppUnit::TestCase +{ + class MockTxOp : public TxOp{ + enum op_codes {PREPARE=2, COMMIT=4, ROLLBACK=8}; + std::vector expected; + std::vector actual; + bool failOnPrepare; + public: + MockTxOp() : failOnPrepare(false) {} + MockTxOp(bool _failOnPrepare) : failOnPrepare(_failOnPrepare) {} + + bool prepare(TransactionContext*) throw(){ + actual.push_back(PREPARE); + return !failOnPrepare; + } + void commit() throw(){ + actual.push_back(COMMIT); + } + void rollback() throw(){ + actual.push_back(ROLLBACK); + } + 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{ + enum op_codes {BEGIN=2, COMMIT=4, ABORT=8}; + std::vector expected; + std::vector actual; + + enum states {OPEN = 1, COMMITTED = 2, ABORTED = 3}; + int state; + + class TestTransactionContext : public TransactionContext{ + MockTransactionalStore* store; + public: + TestTransactionContext(MockTransactionalStore* _store) : store(_store) {} + void commit(){ + if(store->state != OPEN) throw "txn already completed"; + store->state = COMMITTED; + } + + void abort(){ + if(store->state != OPEN) throw "txn already completed"; + store->state = ABORTED; + } + ~TestTransactionContext(){} + }; + + + public: + MockTransactionalStore() : state(OPEN){} + + std::auto_ptr begin(const std::string&){ + throw "Operation not supported"; + } + void prepare(TPCTransactionContext&){ + throw "Operation not supported"; + } + + std::auto_ptr begin(){ + actual.push_back(BEGIN); + std::auto_ptr txn(new TestTransactionContext(this)); + return txn; + } + 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& expectCommit(){ + expected.push_back(COMMIT); + return *this; + } + MockTransactionalStore& expectAbort(){ + expected.push_back(ABORT); + return *this; + } + void check(){ + assertEqualVector(expected, actual); + } + + bool isCommitted(){ + return state == COMMITTED; + } + + bool isAborted(){ + return state == ABORTED; + } + + bool isOpen() const{ + return state == OPEN; + } + ~MockTransactionalStore(){} + }; + + CPPUNIT_TEST_SUITE(TxBufferTest); + CPPUNIT_TEST(testPrepareAndCommit); + CPPUNIT_TEST(testFailOnPrepare); + CPPUNIT_TEST(testRollback); + CPPUNIT_TEST(testBufferIsClearedAfterRollback); + CPPUNIT_TEST(testBufferIsClearedAfterCommit); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testPrepareAndCommit(){ + MockTransactionalStore store; + store.expectBegin().expectCommit(); + + MockTxOp opA; + opA.expectPrepare().expectCommit(); + MockTxOp opB; + opB.expectPrepare().expectPrepare().expectCommit().expectCommit();//opB enlisted twice to test reative order + MockTxOp opC; + opC.expectPrepare().expectCommit(); + + TxBuffer buffer; + buffer.enlist(&opA); + buffer.enlist(&opB); + buffer.enlist(&opB);//opB enlisted twice + buffer.enlist(&opC); + + CPPUNIT_ASSERT(buffer.prepare(&store)); + buffer.commit(); + store.check(); + CPPUNIT_ASSERT(store.isCommitted()); + opA.check(); + opB.check(); + opC.check(); + } + + void testFailOnPrepare(){ + MockTransactionalStore store; + store.expectBegin().expectAbort(); + + MockTxOp opA; + opA.expectPrepare(); + MockTxOp opB(true); + opB.expectPrepare(); + MockTxOp opC;//will never get prepare as b will fail + + TxBuffer buffer; + buffer.enlist(&opA); + buffer.enlist(&opB); + buffer.enlist(&opC); + + CPPUNIT_ASSERT(!buffer.prepare(&store)); + store.check(); + CPPUNIT_ASSERT(store.isAborted()); + opA.check(); + opB.check(); + opC.check(); + } + + void testRollback(){ + MockTxOp opA; + opA.expectRollback(); + MockTxOp opB(true); + opB.expectRollback(); + MockTxOp opC; + opC.expectRollback(); + + TxBuffer buffer; + buffer.enlist(&opA); + buffer.enlist(&opB); + buffer.enlist(&opC); + + buffer.rollback(); + opA.check(); + opB.check(); + opC.check(); + } + + void testBufferIsClearedAfterRollback(){ + MockTxOp opA; + opA.expectRollback(); + MockTxOp opB; + opB.expectRollback(); + + TxBuffer buffer; + buffer.enlist(&opA); + buffer.enlist(&opB); + + buffer.rollback(); + buffer.commit();//second call should not reach ops + opA.check(); + opB.check(); + } + + void testBufferIsClearedAfterCommit(){ + MockTxOp opA; + opA.expectCommit(); + MockTxOp opB; + opB.expectCommit(); + + TxBuffer buffer; + buffer.enlist(&opA); + buffer.enlist(&opB); + + buffer.commit(); + buffer.rollback();//second call should not reach ops + opA.check(); + opB.check(); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(TxBufferTest); + diff --git a/qpid/cpp/src/tests/TxPublishTest.cpp b/qpid/cpp/src/tests/TxPublishTest.cpp new file mode 100644 index 0000000000..84d2666b6c --- /dev/null +++ b/qpid/cpp/src/tests/TxPublishTest.cpp @@ -0,0 +1,108 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "../broker/NullMessageStore.h" +#include "../broker/RecoveryManager.h" +#include "../broker/TxPublish.h" +#include "qpid_test_plugin.h" +#include +#include +#include +#include "MockChannel.h" + +using std::list; +using std::pair; +using std::vector; +using namespace qpid::broker; +using namespace qpid::framing; + +class TxPublishTest : public CppUnit::TestCase +{ + typedef std::pair msg_queue_pair; + + class TestMessageStore : public NullMessageStore + { + public: + vector enqueued; + + void enqueue(TransactionContext*, PersistableMessage& msg, const PersistableQueue& queue) + { + enqueued.push_back(msg_queue_pair(queue.getName(), &msg)); + } + + //dont care about any of the other methods: + TestMessageStore() : NullMessageStore(false) {} + ~TestMessageStore(){} + }; + + CPPUNIT_TEST_SUITE(TxPublishTest); + CPPUNIT_TEST(testPrepare); + CPPUNIT_TEST(testCommit); + CPPUNIT_TEST_SUITE_END(); + + + TestMessageStore store; + Queue::shared_ptr queue1; + Queue::shared_ptr queue2; + Message::shared_ptr const msg; + TxPublish op; + +public: + + TxPublishTest() : + queue1(new Queue("queue1", false, &store, 0)), + queue2(new Queue("queue2", false, &store, 0)), + msg(new BasicMessage(0, "exchange", "routing_key", false, false, + MockChannel::basicGetBody())), + op(msg) + { + msg->setHeader(AMQHeaderBody::shared_ptr(new AMQHeaderBody(BASIC))); + msg->getHeaderProperties()->setDeliveryMode(PERSISTENT); + op.deliverTo(queue1); + op.deliverTo(queue2); + } + + void testPrepare() + { + //ensure messages are enqueued in store + op.prepare(0); + CPPUNIT_ASSERT_EQUAL((size_t) 2, store.enqueued.size()); + CPPUNIT_ASSERT_EQUAL(string("queue1"), store.enqueued[0].first); + CPPUNIT_ASSERT_EQUAL((PersistableMessage*) msg.get(), store.enqueued[0].second); + CPPUNIT_ASSERT_EQUAL(string("queue2"), store.enqueued[1].first); + CPPUNIT_ASSERT_EQUAL((PersistableMessage*) msg.get(), store.enqueued[1].second); + } + + void testCommit() + { + //ensure messages are delivered to queue + op.commit(); + CPPUNIT_ASSERT_EQUAL((uint32_t) 1, queue1->getMessageCount()); + CPPUNIT_ASSERT_EQUAL(msg, queue1->dequeue()); + + CPPUNIT_ASSERT_EQUAL((uint32_t) 1, queue2->getMessageCount()); + CPPUNIT_ASSERT_EQUAL(msg, queue2->dequeue()); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(TxPublishTest); + diff --git a/qpid/cpp/src/tests/ValueTest.cpp b/qpid/cpp/src/tests/ValueTest.cpp new file mode 100644 index 0000000000..2d1fc45461 --- /dev/null +++ b/qpid/cpp/src/tests/ValueTest.cpp @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "../framing/Value.h" +#include "qpid_test_plugin.h" + +using namespace qpid::framing; + + +class ValueTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(ValueTest); + CPPUNIT_TEST(testStringValueEquals); + CPPUNIT_TEST(testIntegerValueEquals); + CPPUNIT_TEST(testDecimalValueEquals); + CPPUNIT_TEST(testFieldTableValueEquals); + CPPUNIT_TEST_SUITE_END(); + + StringValue s; + IntegerValue i; + DecimalValue d; + FieldTableValue ft; + EmptyValue e; + + public: + ValueTest() : + s("abc"), + i(42), + d(1234,2) + + { + ft.getValue().setString("foo", "FOO"); + ft.getValue().setInt("magic", 7); + } + + void testStringValueEquals() + { + + CPPUNIT_ASSERT(StringValue("abc") == s); + CPPUNIT_ASSERT(s != StringValue("foo")); + CPPUNIT_ASSERT(s != e); + CPPUNIT_ASSERT(e != d); + CPPUNIT_ASSERT(e != ft); + } + + void testIntegerValueEquals() + { + CPPUNIT_ASSERT(IntegerValue(42) == i); + CPPUNIT_ASSERT(IntegerValue(5) != i); + CPPUNIT_ASSERT(i != e); + CPPUNIT_ASSERT(i != d); + } + + void testDecimalValueEquals() + { + CPPUNIT_ASSERT(DecimalValue(1234, 2) == d); + CPPUNIT_ASSERT(DecimalValue(12345, 2) != d); + CPPUNIT_ASSERT(DecimalValue(1234, 3) != d); + CPPUNIT_ASSERT(d != s); + } + + + void testFieldTableValueEquals() + { + CPPUNIT_ASSERT_EQUAL(std::string("FOO"), + ft.getValue().getString("foo")); + CPPUNIT_ASSERT_EQUAL(7, ft.getValue().getInt("magic")); + + FieldTableValue f2; + CPPUNIT_ASSERT(ft != f2); + f2.getValue().setString("foo", "FOO"); + CPPUNIT_ASSERT(ft != f2); + f2.getValue().setInt("magic", 7); + CPPUNIT_ASSERT_EQUAL(ft,f2); + CPPUNIT_ASSERT(ft == f2); + f2.getValue().setString("foo", "BAR"); + CPPUNIT_ASSERT(ft != f2); + CPPUNIT_ASSERT(ft != i); + } + +}; + + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(ValueTest); + diff --git a/qpid/cpp/src/tests/client_test.cpp b/qpid/cpp/src/tests/client_test.cpp new file mode 100644 index 0000000000..5c084302d8 --- /dev/null +++ b/qpid/cpp/src/tests/client_test.cpp @@ -0,0 +1,138 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 "../QpidError.h" +#include "../client/ClientChannel.h" +#include "../client/Connection.h" +#include "../client/ClientMessage.h" +#include "../client/MessageListener.h" +#include "../sys/Monitor.h" +#include "../framing/FieldTable.h" + +using namespace qpid::client; +using namespace qpid::sys; +using std::string; + +bool verbose = false; + +/** + * A simple message listener implementation that prints out the + * message content then notifies a montitor allowing the test to + * complete. + */ +class SimpleListener : public virtual MessageListener{ + Monitor* monitor; + +public: + inline SimpleListener(Monitor* _monitor) : monitor(_monitor){} + + inline virtual void received(Message& msg){ + if (verbose) + std::cout << "Received message " << msg.getData() << std::endl; + monitor->notify(); + } +}; + +int main(int argc, char**) +{ + verbose = argc > 1; + try { + //Use a custom exchange + Exchange exchange("MyExchange", Exchange::TOPIC_EXCHANGE); + //Use a named, temporary queue + Queue queue("MyQueue", true); + + + Connection con(verbose); + string host("localhost"); + con.open(host, 5672, "guest", "guest", "/test"); + if (verbose) + std::cout << "Opened connection." << std::endl; + + //Create and open a channel on the connection through which + //most functionality is exposed + Channel channel; + con.openChannel(channel); + if (verbose) std::cout << "Opened channel." << std::endl; + + //'declare' the exchange and the queue, which will create them + //as they don't exist + channel.declareExchange(exchange); + if (verbose) std::cout << "Declared exchange." << std::endl; + channel.declareQueue(queue); + if (verbose) std::cout << "Declared queue." << std::endl; + + //now bind the queue to the exchange + qpid::framing::FieldTable args; + channel.bind(exchange, queue, "MyTopic", args); + if (verbose) std::cout << "Bound queue to exchange." << std::endl; + + //Set up a message listener to receive any messages that + //arrive in our queue on the broker. We only expect one, and + //as it will be received on another thread, we create a + //montior to use to notify the main thread when that message + //is received. + Monitor monitor; + SimpleListener listener(&monitor); + string tag("MyTag"); + channel.consume(queue, tag, &listener); + if (verbose) std::cout << "Registered consumer." << std::endl; + + //we need to enable the message dispatching for this channel + //and we want that to occur on another thread so we call + //start(). + channel.start(); + + //Now we create and publish a message to our exchange with a + //routing key that will cause it to be routed to our queue + Message msg; + string data("MyMessage"); + msg.setData(data); + channel.publish(msg, exchange, "MyTopic"); + if (verbose) std::cout << "Published message: " << data << std::endl; + + { + Monitor::ScopedLock l(monitor); + //now we wait until we receive notification that the + //message was received + monitor.wait(); + } + + //close the channel & connection + channel.close(); + if (verbose) std::cout << "Closed channel." << std::endl; + con.close(); + if (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/dlclose_noop.c b/qpid/cpp/src/tests/dlclose_noop.c new file mode 100644 index 0000000000..ba2fa75891 --- /dev/null +++ b/qpid/cpp/src/tests/dlclose_noop.c @@ -0,0 +1,30 @@ +/* + * + * 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) {} + diff --git a/qpid/cpp/src/tests/echo_service.cpp b/qpid/cpp/src/tests/echo_service.cpp new file mode 100644 index 0000000000..14224eeee5 --- /dev/null +++ b/qpid/cpp/src/tests/echo_service.cpp @@ -0,0 +1,230 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 class provides an example of using AMQP for a request-response + * style system. 'Requests' are messages sent to a well known + * destination. A 'service' process consumes these message and + * responds by echoing the message back to the sender on a + * sender-specified private queue. + */ + +#include "../QpidError.h" +#include "../client/ClientChannel.h" +#include "../client/Connection.h" +#include "../client/ClientExchange.h" +#include "../client/MessageListener.h" +#include "../client/ClientQueue.h" +#include "../sys/Time.h" +#include +#include + +using namespace qpid::client; +using namespace qpid::sys; +using std::string; + + +/** + * A message listener implementation representing the 'service', this + * will 'echo' any requests received. + */ +class EchoServer : public MessageListener{ + Channel* const channel; +public: + EchoServer(Channel* channel); + virtual void received(Message& msg); +}; + +/** + * A message listener implementation that merely prints received + * messages to the console. Used to report on 'echo' responses. + */ +class LoggingListener : public MessageListener{ +public: + virtual void received(Message& msg); +}; + +/** + * A utility class that manages the command line options needed to run + * the example confirgurably. + */ +class Args{ + string host; + int port; + bool trace; + bool help; + bool client; +public: + inline Args() : host("localhost"), port(5672), trace(false), help(false), client(false){} + void parse(int argc, char** argv); + void usage(); + + inline const string& getHost() const { return host;} + inline int getPort() const { return port; } + inline bool getTrace() const { return trace; } + inline bool getHelp() const { return help; } + inline bool getClient() const { return client; } +}; + +/** + * The main test path. There are two basic modes: 'client' and + * 'service'. First one or more services are started, then one or more + * clients are started and messages can be sent. + */ +int main(int argc, char** argv){ + const std::string echo_service("echo_service"); + Args args; + args.parse(argc, argv); + if (args.getHelp()) { + args.usage(); + } else if (args.getClient()) { + //we have been started in 'client' mode, i.e. we will send an + //echo requests and print responses received. + try { + //Create connection & open a channel + Connection connection(args.getTrace()); + connection.open(args.getHost(), args.getPort()); + Channel channel; + connection.openChannel(channel); + + //Setup: declare the private 'response' queue and bind it + //to the direct exchange by its name which will be + //generated by the server + Queue response; + channel.declareQueue(response); + qpid::framing::FieldTable emptyArgs; + channel.bind(Exchange::STANDARD_DIRECT_EXCHANGE, response, response.getName(), emptyArgs); + + //Consume from the response queue, logging all echoed message to console: + LoggingListener listener; + std::string tag; + channel.consume(response, tag, &listener); + + //Process incoming requests on a new thread + channel.start(); + + //get messages from console and send them: + std::string text; + std::cout << "Enter text to send:" << std::endl; + while (std::getline(std::cin, text)) { + std::cout << "Sending " << text << " to echo server." << std::endl; + Message msg; + msg.getHeaders().setString("RESPONSE_QUEUE", response.getName()); + msg.setData(text); + channel.publish(msg, Exchange::STANDARD_DIRECT_EXCHANGE, echo_service); + + std::cout << "Enter text to send:" << std::endl; + } + + connection.close(); + } catch(qpid::QpidError error) { + std::cout << error.what() << std::endl; + } + } else { + // we are in 'service' mode, i.e. we will consume messages + // from the request queue and echo each request back to the + // senders own private response queue. + try { + //Create connection & open a channel + Connection connection(args.getTrace()); + connection.open(args.getHost(), args.getPort()); + Channel channel; + connection.openChannel(channel); + + //Setup: declare the 'request' queue and bind it to the direct exchange with a 'well known' name + Queue request("request"); + channel.declareQueue(request); + qpid::framing::FieldTable emptyArgs; + channel.bind(Exchange::STANDARD_DIRECT_EXCHANGE, request, echo_service, emptyArgs); + + //Consume from the request queue, echoing back all messages received to the client that sent them + EchoServer server(&channel); + std::string tag = "server_tag"; + channel.consume(request, tag, &server); + + //Process incoming requests on the main thread + channel.run(); + + connection.close(); + } catch(qpid::QpidError error) { + std::cout << error.what() << std::endl; + } + } +} + +EchoServer::EchoServer(Channel* _channel) : channel(_channel){} + +void EchoServer::received(Message& message) +{ + //get name of response queues binding to the default direct exchange: + const std::string name = message.getHeaders().getString("RESPONSE_QUEUE"); + + if (name.empty()) { + std::cout << "Cannot echo " << message.getData() << ", no response queue specified." << std::endl; + } else { + //print message to console: + std::cout << "Echoing " << message.getData() << " back to " << name << std::endl; + + //'echo' the message back: + channel->publish(message, Exchange::STANDARD_DIRECT_EXCHANGE, name); + } +} + +void LoggingListener::received(Message& message) +{ + //print message to console: + std::cout << "Received echo: " << message.getData() << std::endl; +} + + +void Args::parse(int argc, char** argv){ + for(int i = 1; i < argc; i++){ + string name(argv[i]); + if("-help" == name){ + help = true; + break; + }else if("-host" == name){ + host = argv[++i]; + }else if("-port" == name){ + port = atoi(argv[++i]); + }else if("-trace" == name){ + trace = true; + }else if("-client" == name){ + client = true; + }else{ + std::cout << "Warning: unrecognised option " << name << std::endl; + } + } +} + +void Args::usage(){ + std::cout << "Options:" << std::endl; + std::cout << " -help" << std::endl; + std::cout << " Prints this usage message" << std::endl; + std::cout << " -host " << std::endl; + std::cout << " Specifies host to connect to (default is localhost)" << std::endl; + std::cout << " -port " << std::endl; + std::cout << " Specifies port to conect to (default is 5762)" << std::endl; + std::cout << " -trace" << std::endl; + std::cout << " Indicates that the frames sent and received should be logged" << std::endl; + std::cout << " -client" << std::endl; + std::cout << " Run as a client (else will run as a server)" << std::endl; +} diff --git a/qpid/cpp/src/tests/examples.Makefile b/qpid/cpp/src/tests/examples.Makefile new file mode 100644 index 0000000000..45999f7852 --- /dev/null +++ b/qpid/cpp/src/tests/examples.Makefile @@ -0,0 +1,66 @@ +# +# XXX: Edit these locations to suit. +# +BOOST_LOCATION := $(HOME)/local/boost-1.33.1 +APR_LOCATION := $(HOME)/local/apr-1.2.7 + +CXXFLAGS := -DNDEBUG -DUSE_APR -MMD -fpic + +# +# Configure Boost. +# +BOOST_CFLAGS := -I$(BOOST_LOCATION)/include/boost-1_33_1 +CXXFLAGS := $(CXXFLAGS) $(BOOST_CFLAGS) + +# +# Configure APR. +# +APR_CFLAGS := -I$(APR_LOCATION)/include/apr-1 +APR_LDFLAGS := $(shell $(APR_LOCATION)/bin/apr-1-config --libs) -L$(APR_LOCATION)/lib -lapr-1 +CXXFLAGS := $(CXXFLAGS) $(APR_CFLAGS) +LDFLAGS := $(LDFLAGS) $(APR_LDFLAGS) + +# +# Configure Qpid cpp client. +# +QPID_CLIENT_LDFLAGS := ../lib/libcommon.so ../lib/libclient.so +includeDir := ../include +QPID_CLIENT_CFLAGS := \ + -I$(includeDir)/gen \ + -I$(includeDir)/client \ + -I$(includeDir)/broker \ + -I$(includeDir)/common \ + -I$(includeDir)/common/sys \ + -I$(includeDir)/common/framing + +CXXFLAGS := $(CXXFLAGS) $(QPID_CLIENT_CFLAGS) +LDFLAGS := $(LDFLAGS) $(QPID_CLIENT_LDFLAGS) + +CXX := g++ + +# +# Add rule to build examples. +# +.SUFFIX: .cpp +%: %.cpp + $(CXX) $(CXXFLAGS) $(LDFLAGS) $< -o $@ + +# +# Define targets. +# + +EXAMPLES := client_test topic_listener topic_publisher echo_service + +cppFiles := $(wildcard *.cpp) +programs = $(foreach cppFile, $(cppFiles), $(subst .cpp, ,$(cppFile))) + +.PHONY: +all: $(programs) + +debug: + @echo cppFiles = $(cppFiles) + @echo programs = $(programs) + +.PHONY: +clean: + -rm $(EXAMPLES) diff --git a/qpid/cpp/src/tests/examples.README b/qpid/cpp/src/tests/examples.README new file mode 100644 index 0000000000..65f908c249 --- /dev/null +++ b/qpid/cpp/src/tests/examples.README @@ -0,0 +1,18 @@ +Building the examples +--------------------- + +You had better edit the Makefile and provide the locations for APR and boost. + +Then just type 'make'. + + +Running the examples +-------------------- + +Before running the examples ensure that you have setup your LD_LIBRARY_PATH. + +Most of the examples take the following connection parameters for your +AMQP broker: + + -host host + -port port diff --git a/qpid/cpp/src/tests/kill_broker b/qpid/cpp/src/tests/kill_broker new file mode 100755 index 0000000000..b71ca22ffd --- /dev/null +++ b/qpid/cpp/src/tests/kill_broker @@ -0,0 +1,3 @@ +#!/bin/sh +PID=qpidd.pid +if [ -f $PID ] ; then kill -9 `cat $PID` ; rm -f $PID ; fi diff --git a/qpid/cpp/src/tests/python_tests b/qpid/cpp/src/tests/python_tests new file mode 100755 index 0000000000..585c1da913 --- /dev/null +++ b/qpid/cpp/src/tests/python_tests @@ -0,0 +1,8 @@ +#!/bin/sh +# Run the python tests. +if test -d ../../../python ; then + cd ../../../python && ./run-tests -v -s "0-9" -I cpp_failing_0-9.txt +else + echo Warning: python tests not found. +fi + diff --git a/qpid/cpp/src/tests/qpid_test_plugin.h b/qpid/cpp/src/tests/qpid_test_plugin.h new file mode 100644 index 0000000000..b2f4a8ffed --- /dev/null +++ b/qpid/cpp/src/tests/qpid_test_plugin.h @@ -0,0 +1,43 @@ +#ifndef _qpid_test_plugin_ +#define _qpid_test_plugin_ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * Convenience to include cppunit headers needed by qpid test plugins and + * workaround for warning from superfluous main() declaration + * in cppunit/TestPlugIn.h + */ + +#include +#include +#include +#include + +// Redefine CPPUNIT_PLUGIN_IMPLEMENT_MAIN to a dummy typedef to avoid warnings. +// +#if defined(CPPUNIT_HAVE_UNIX_DLL_LOADER) || defined(CPPUNIT_HAVE_UNIX_SHL_LOADER) +#undef CPPUNIT_PLUGIN_IMPLEMENT_MAIN +#define CPPUNIT_PLUGIN_IMPLEMENT_MAIN() typedef char __CppUnitPlugInImplementMainDummyTypeDef +#endif + +#endif /*!_qpid_test_plugin_*/ diff --git a/qpid/cpp/src/tests/quick_topictest b/qpid/cpp/src/tests/quick_topictest new file mode 100755 index 0000000000..9df5b5c84c --- /dev/null +++ b/qpid/cpp/src/tests/quick_topictest @@ -0,0 +1,7 @@ +#!/bin/sh +# Quick and quiet topic test for make check. +./topictest -s2 -m2 -b1 > topictest.log 2>&1 || { + echo See topictest.log. + exit 1 +} +rm topictest.log diff --git a/qpid/cpp/src/tests/run-python-tests b/qpid/cpp/src/tests/run-python-tests new file mode 100755 index 0000000000..e69de29bb2 diff --git a/qpid/cpp/src/tests/run-unit-tests b/qpid/cpp/src/tests/run-unit-tests new file mode 100755 index 0000000000..f066a38205 --- /dev/null +++ b/qpid/cpp/src/tests/run-unit-tests @@ -0,0 +1,37 @@ +#!/bin/sh +# +# Library names (without path or .so) and CppUnit test paths can be +# specified on the command line or in env var UNIT_TESTS. For example: +# +# Selected test classes: +# ./run-unit-tests ValueTest ClientChannelTest +# +# Individual test method +# ./run-unit-tests ValueTest :ValueTest::testStringValueEquals +# +# Build and run selected tests: +# make check TESTS=run-unit-tests UNIT_TESTS=ClientChannelTest +# + +# Default VALGRIND from the path and $srcdir to . but +# don't override values set by make. +test -z "$VALGRIND" -a -z "$MAKEFLAGS" && VALGRIND=`which valgrind` 2>/dev/null +test -z "$srcdir" && srcdir=. + +rm -f valgrind.out +vg_log=--log-file-exactly=valgrind.out +source $srcdir/setup +for u in $* $UNIT_TESTS ; do + case $u in + :*) TEST_ARGS="$TEST_ARGS $u" ;; # A test path. + *) TEST_ARGS="$TEST_ARGS $pwd/.libs/$u.so" ;; # A test library. + esac +done +# If none specified, run all tests in .libs +test -z "$TEST_ARGS" && TEST_ARGS="$pwd/.libs/*Test.so" +fail=0 + +$vg DllPlugInTester -c -b $TEST_ARGS || fail=1 +vg_check valgrind.out || fail=1 + +exit $fail diff --git a/qpid/cpp/src/tests/setup b/qpid/cpp/src/tests/setup new file mode 100644 index 0000000000..aaa3afd9b8 --- /dev/null +++ b/qpid/cpp/src/tests/setup @@ -0,0 +1,81 @@ +# -*- sh -*- + +test "$VERBOSE" = yes && set -x + +pwd=`pwd` +test -z "$abs_srcdir" && abs_srcdir=$pwd + +t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$ +pid=0 +test -z "$TEST_DEBUG" && +trap 's=$?;test $pid = 0||kill -2 $pid;cd "$pwd" && rm -rf $t0 && exit $s' 0 +test -z "$TEST_DEBUG" && trap '(exit $?); exit $?' 1 2 13 15 + +framework_failure=0 +mkdir -p $tmp || framework_failure=1 +cd $tmp || framework_failure=1 + +gen_supp=--gen-suppressions=all +# This option makes valgrind significantly slower. +full_leak_check=--leak-check=full +demangle=--demangle=yes + +vg_options=" + --suppressions=$abs_srcdir/.vg-supp + --num-callers=25 + --track-fds=yes + $demangle + $full_leak_check + $gen_supp + $vg_log + " +# configure tests for the existence of valgrind. +# If it's not available, then make $vg and vg_check no-ops. +if test x$VALGRIND = x; then + vg= +else + vg="libtool --mode=execute $VALGRIND `echo $vg_options` --" + # Suppress dlclose or valgrind traces wont have test library symbols. + vg="env LD_PRELOAD=$pwd/.libs/libdlclose_noop.so $vg" +fi + + +vg_leak_check() +{ + local file=$1 + local fail + # If we detect a leak, dump all output to stderr. + grep -E '^==[0-9]+== +definitely lost: [^0]' $file \ + && { fail=1; cat $file 1>&2; + echo "found memory leaks (see log file, $file); see above" 1>&2; } + test "$fail" = '' +} + + +# Ensure 1) that there is an ERROR SUMMARY line, and +# 2) that the number of errors is 0. +# An offending line looks like this: +# ==29302== ERROR SUMMARY: 4 errors from 2 contexts (suppressed: 16 from 5) +vg_error_check() +{ + local file=$1 + local fail + # If we detect a leak, dump all output to stderr. + grep -E '^==[0-9]+== ERROR SUMMARY:' $file > /dev/null \ + || { fail=1; cat $file 1>&2; + echo "no valgrind ERROR SUMMARY line in $file" 1>&2; } + if test "$fail" = ''; then + grep -E '^==[0-9]+== ERROR SUMMARY: [^0] ' $file \ + && { fail=1; cat $file 1>&2; + echo "valgrind reported errors in $file; see above" 1>&2; } + fi + test "$fail" = '' +} + +vg_check() +{ + local file=$1 + if test x$VALGRIND != x; then + vg_error_check $file && vg_leak_check $file + fi +} diff --git a/qpid/cpp/src/tests/start_broker b/qpid/cpp/src/tests/start_broker new file mode 100755 index 0000000000..64d26883be --- /dev/null +++ b/qpid/cpp/src/tests/start_broker @@ -0,0 +1,14 @@ +#!/bin/sh +set -e + +LOG=`pwd`/qpidd.log +PID=`pwd`/qpidd.pid + +rm -rf $LOG $PID + +# Start the daemon, recording its PID. +../qpidd > $LOG 2>&1 & echo $! > $PID + +# FIXME aconway 2007-01-18: qpidd should not return till it is accepting +# connections, remove arbitrary sleep. +sleep 5 diff --git a/qpid/cpp/src/tests/topic_listener.cpp b/qpid/cpp/src/tests/topic_listener.cpp new file mode 100644 index 0000000000..0b7d6c4e86 --- /dev/null +++ b/qpid/cpp/src/tests/topic_listener.cpp @@ -0,0 +1,217 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 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 "../QpidError.h" +#include "../client/ClientChannel.h" +#include "../client/Connection.h" +#include "../client/ClientExchange.h" +#include "../client/MessageListener.h" +#include "../client/ClientQueue.h" +#include "../sys/Time.h" +#include +#include + +using namespace qpid::client; +using namespace qpid::sys; +using namespace std; + +/** + * A message listener implementation in which the runtime logic is + * defined. + */ +class Listener : public MessageListener{ + Channel* const channel; + const string responseQueue; + const bool transactional; + bool init; + int count; + Time start; + + void shutdown(); + void report(); +public: + Listener(Channel* channel, const string& reponseQueue, bool tx); + virtual void received(Message& msg); +}; + +/** + * A utility class for managing the options passed in. + */ +class Args{ + string host; + int port; + AckMode ackMode; + bool transactional; + int prefetch; + bool trace; + bool help; +public: + inline Args() : host("localhost"), port(5672), ackMode(NO_ACK), transactional(false), prefetch(1000), trace(false), help(false){} + void parse(int argc, char** argv); + void usage(); + + const string& getHost() const { return host;} + int getPort() const { return port; } + AckMode getAckMode(){ return ackMode; } + bool getTransactional() const { return transactional; } + int getPrefetch(){ return prefetch; } + bool getTrace() const { return trace; } + bool getHelp() const { return help; } +}; + +/** + * 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){ + Args args; + args.parse(argc, argv); + if(args.getHelp()){ + args.usage(); + }else{ + try{ + cout << "topic_listener: Started." << endl; + Connection connection(args.getTrace()); + connection.open(args.getHost(), args.getPort(), "guest", "guest", "/test"); + Channel channel(args.getTransactional(), args.getPrefetch()); + connection.openChannel(channel); + + //declare exchange, queue and bind them: + Queue response("response"); + channel.declareQueue(response); + + Queue control; + channel.declareQueue(control); + qpid::framing::FieldTable bindArgs; + channel.bind(Exchange::STANDARD_TOPIC_EXCHANGE, control, "topic_control", bindArgs); + //set up listener + Listener listener(&channel, response.getName(), args.getTransactional()); + string tag; + channel.consume(control, tag, &listener, args.getAckMode()); + cout << "topic_listener: Consuming." << endl; + channel.run(); + connection.close(); + cout << "topic_listener: normal exit" << endl; + return 0; + }catch(qpid::QpidError error){ + cout << "topic_listener: " << error.what() << endl; + } + } + return 1; +} + +Listener::Listener(Channel* _channel, const string& _responseq, bool tx) : + channel(_channel), responseQueue(_responseq), transactional(tx), init(false), count(0){} + +void Listener::received(Message& message){ + if(!init){ + start = now(); + count = 0; + init = true; + } + string type(message.getHeaders().getString("TYPE")); + + if(type == "TERMINATION_REQUEST"){ + shutdown(); + }else if(type == "REPORT_REQUEST"){ + //send a report: + report(); + init = false; + }else if (++count % 100 == 0){ + cout <<"Received " << count << " messages." << endl; + } +} + +void Listener::shutdown(){ + channel->close(); +} + +void Listener::report(){ + Time finish = now(); + Time time = finish - start; + stringstream reportstr; + reportstr << "Received " << count << " messages in " + << time/TIME_MSEC << " ms."; + Message msg(reportstr.str()); + msg.getHeaders().setString("TYPE", "REPORT"); + channel->publish(msg, string(), responseQueue); + if(transactional){ + channel->commit(); + } +} + + +void Args::parse(int argc, char** argv){ + for(int i = 1; i < argc; i++){ + string name(argv[i]); + if("-help" == name){ + help = true; + break; + }else if("-host" == name){ + host = argv[++i]; + }else if("-port" == name){ + port = atoi(argv[++i]); + }else if("-ack_mode" == name){ + ackMode = AckMode(atoi(argv[++i])); + }else if("-transactional" == name){ + transactional = true; + }else if("-prefetch" == name){ + prefetch = atoi(argv[++i]); + }else if("-trace" == name){ + trace = true; + }else{ + cout << "Warning: unrecognised option " << name << endl; + } + } +} + +void Args::usage(){ + cout << "Options:" << endl; + cout << " -help" << endl; + cout << " Prints this usage message" << endl; + cout << " -host " << endl; + cout << " Specifies host to connect to (default is localhost)" << endl; + cout << " -port " << endl; + cout << " Specifies port to conect to (default is 5762)" << endl; + cout << " -ack_mode " << endl; + cout << " Sets the acknowledgement mode" << endl; + cout << " 0=NO_ACK (default), 1=AUTO_ACK, 2=LAZY_ACK" << endl; + cout << " -transactional" << endl; + cout << " Indicates the client should use transactions" << endl; + cout << " -prefetch " << endl; + cout << " Specifies the prefetch count (default is 1000)" << endl; + cout << " -trace" << endl; + cout << " Indicates that the frames sent and received should be logged" << endl; +} diff --git a/qpid/cpp/src/tests/topic_publisher.cpp b/qpid/cpp/src/tests/topic_publisher.cpp new file mode 100644 index 0000000000..e4b39a2966 --- /dev/null +++ b/qpid/cpp/src/tests/topic_publisher.cpp @@ -0,0 +1,287 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 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 "../QpidError.h" +#include "../client/ClientChannel.h" +#include "../client/Connection.h" +#include "../client/ClientExchange.h" +#include "../client/MessageListener.h" +#include "../client/ClientQueue.h" +#include "../sys/Monitor.h" +#include +#include "../sys/Time.h" +#include +#include + +using namespace qpid::client; +using namespace qpid::sys; +using std::string; + +/** + * 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 : public MessageListener{ + Channel* const channel; + const std::string controlTopic; + const bool transactional; + Monitor monitor; + int count; + + void waitForCompletion(int msgs); + string generateData(int size); + +public: + Publisher(Channel* channel, const std::string& controlTopic, bool tx); + virtual void received(Message& msg); + int64_t publish(int msgs, int listeners, int size); + void terminate(); +}; + +/** + * A utility class for managing the options passed in to the test + */ +class Args{ + string host; + int port; + int messages; + int subscribers; + AckMode ackMode; + bool transactional; + int prefetch; + int batches; + int delay; + int size; + bool trace; + bool help; +public: + inline Args() : host("localhost"), port(5672), messages(1000), subscribers(1), + ackMode(NO_ACK), transactional(false), prefetch(1000), batches(1), + delay(0), size(256), trace(false), help(false){} + + void parse(int argc, char** argv); + void usage(); + + const string& getHost() const { return host;} + int getPort() const { return port; } + int getMessages() const { return messages; } + int getSubscribers() const { return subscribers; } + AckMode getAckMode(){ return ackMode; } + bool getTransactional() const { return transactional; } + int getPrefetch(){ return prefetch; } + int getBatches(){ return batches; } + int getDelay(){ return delay; } + int getSize(){ return size; } + bool getTrace() const { return trace; } + bool getHelp() const { return help; } +}; + +int main(int argc, char** argv) { + Args args; + args.parse(argc, argv); + if(args.getHelp()){ + args.usage(); + } else { + try{ + Connection connection(args.getTrace()); + connection.open(args.getHost(), args.getPort(), "guest", "guest", "/test"); + Channel channel(args.getTransactional(), args.getPrefetch()); + connection.openChannel(channel); + + //declare queue (relying on default binding): + Queue response("response"); + channel.declareQueue(response); + + //set up listener + Publisher publisher(&channel, "topic_control", args.getTransactional()); + std::string tag("mytag"); + channel.consume(response, tag, &publisher, args.getAckMode()); + channel.start(); + + int batchSize(args.getBatches()); + int64_t max(0); + int64_t min(0); + int64_t sum(0); + for(int i = 0; i < batchSize; i++){ + if(i > 0 && args.getDelay()) sleep(args.getDelay()); + int64_t msecs = + publisher.publish(args.getMessages(), + args.getSubscribers(), + args.getSize()) / TIME_MSEC; + if(!max || msecs > max) max = msecs; + if(!min || msecs < min) min = msecs; + sum += msecs; + std::cout << "Completed " << (i+1) << " of " << batchSize + << " in " << msecs << "ms" << std::endl; + } + publisher.terminate(); + int64_t avg = sum / batchSize; + if(batchSize > 1){ + std::cout << batchSize << " batches completed. avg=" << avg << + ", max=" << max << ", min=" << min << std::endl; + } + channel.close(); + connection.close(); + return 0; + }catch(qpid::QpidError error) { + std::cout << error.what() << std::endl; + } + } + return 1; +} + +Publisher::Publisher(Channel* _channel, const std::string& _controlTopic, bool tx) : + channel(_channel), controlTopic(_controlTopic), transactional(tx){} + +void Publisher::received(Message& ){ + //count responses and when all are received end the current batch + Monitor::ScopedLock l(monitor); + if(--count == 0){ + monitor.notify(); + } +} + +void Publisher::waitForCompletion(int msgs){ + count = msgs; + monitor.wait(); +} + +int64_t Publisher::publish(int msgs, int listeners, int size){ + Message msg; + msg.setData(generateData(size)); + Time start = now(); + { + Monitor::ScopedLock l(monitor); + for(int i = 0; i < msgs; i++){ + channel->publish( + msg, Exchange::STANDARD_TOPIC_EXCHANGE, controlTopic); + } + //send report request + Message reportRequest; + reportRequest.getHeaders().setString("TYPE", "REPORT_REQUEST"); + channel->publish(reportRequest, Exchange::STANDARD_TOPIC_EXCHANGE, controlTopic); + if(transactional){ + channel->commit(); + } + + waitForCompletion(listeners); + } + + Time finish = now(); + return finish - start; +} + +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; + terminationRequest.getHeaders().setString("TYPE", "TERMINATION_REQUEST"); + channel->publish(terminationRequest, Exchange::STANDARD_TOPIC_EXCHANGE, controlTopic); + if(transactional){ + channel->commit(); + } +} + +void Args::parse(int argc, char** argv){ + for(int i = 1; i < argc; i++){ + string name(argv[i]); + if("-help" == name){ + help = true; + break; + }else if("-host" == name){ + host = argv[++i]; + }else if("-port" == name){ + port = atoi(argv[++i]); + }else if("-messages" == name){ + messages = atoi(argv[++i]); + }else if("-subscribers" == name){ + subscribers = atoi(argv[++i]); + }else if("-ack_mode" == name){ + ackMode = AckMode(atoi(argv[++i])); + }else if("-transactional" == name){ + transactional = true; + }else if("-prefetch" == name){ + prefetch = atoi(argv[++i]); + }else if("-batches" == name){ + batches = atoi(argv[++i]); + }else if("-delay" == name){ + delay = atoi(argv[++i]); + }else if("-size" == name){ + size = atoi(argv[++i]); + }else if("-trace" == name){ + trace = true; + }else{ + std::cout << "Warning: unrecognised option " << name << std::endl; + } + } +} + +void Args::usage(){ + std::cout << "Options:" << std::endl; + std::cout << " -help" << std::endl; + std::cout << " Prints this usage message" << std::endl; + std::cout << " -host " << std::endl; + std::cout << " Specifies host to connect to (default is localhost)" << std::endl; + std::cout << " -port " << std::endl; + std::cout << " Specifies port to conect to (default is 5762)" << std::endl; + std::cout << " -messages " << std::endl; + std::cout << " Specifies how many messages to send" << std::endl; + std::cout << " -subscribers " << std::endl; + std::cout << " Specifies how many subscribers to expect reports from" << std::endl; + std::cout << " -ack_mode " << std::endl; + std::cout << " Sets the acknowledgement mode" << std::endl; + std::cout << " 0=NO_ACK (default), 1=AUTO_ACK, 2=LAZY_ACK" << std::endl; + std::cout << " -transactional" << std::endl; + std::cout << " Indicates the client should use transactions" << std::endl; + std::cout << " -prefetch " << std::endl; + std::cout << " Specifies the prefetch count (default is 1000)" << std::endl; + std::cout << " -batches " << std::endl; + std::cout << " Specifies how many batches to run" << std::endl; + std::cout << " -delay " << std::endl; + std::cout << " Causes a delay between each batch" << std::endl; + std::cout << " -size " << std::endl; + std::cout << " Sets the size of the published messages (default is 256 bytes)" << std::endl; + std::cout << " -trace" << std::endl; + std::cout << " Indicates that the frames sent and received should be logged" << std::endl; +} diff --git a/qpid/cpp/src/tests/topictest b/qpid/cpp/src/tests/topictest new file mode 100755 index 0000000000..92e40b2c37 --- /dev/null +++ b/qpid/cpp/src/tests/topictest @@ -0,0 +1,39 @@ +#!/bin/bash +# 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:" opt ; do + case $opt in + s) SUBSCRIBERS=$OPTARG ;; + m) MESSAGES=$OPTARG ;; + b) BATCHES=$OPTARG ;; + ?) + echo "Usage: %0 [-s ] [-m ]" + exit 1 + ;; + esac +done + +subscribe() { + echo Start subscriber $1 + LOG="subscriber_$1.log" + ./topic_listener > $LOG 2>&1 && rm -f $LOG +} + +publish() { + ./topic_publisher -messages $MESSAGES -batches $BATCHES -subscribers $SUBSCRIBERS +} + +for ((i=$SUBSCRIBERS ; i--; )); do + subscribe $i & +done +# FIXME aconway 2007-03-27: Hack around startup race. Fix topic test. +sleep 1 +publish 2>&1 || exit 1 diff --git a/qpid/cpp/tests/.vg-supp b/qpid/cpp/tests/.vg-supp deleted file mode 100644 index b5abdf1385..0000000000 --- a/qpid/cpp/tests/.vg-supp +++ /dev/null @@ -1,18 +0,0 @@ -{ - - Memcheck:Leak - fun:_Znwj - fun:_ZN4qpid6broker17ReferenceRegistry4openERKSs - fun:_ZN13ReferenceTestC1Ev - fun:_ZN7CppUnit25ConcretTestFixtureFactoryI13ReferenceTestE11makeFixtureEv - fun:_ZNK7CppUnit27TestSuiteBuilderContextBase15makeTestFixtureEv - fun:_ZNK7CppUnit23TestSuiteBuilderContextI13ReferenceTestE11makeFixtureEv - fun:_ZN13ReferenceTest15addTestsToSuiteERN7CppUnit27TestSuiteBuilderContextBaseE - fun:_ZN13ReferenceTest5suiteEv - fun:_ZN7CppUnit16TestSuiteFactoryI13ReferenceTestE8makeTestEv - fun:_ZN7CppUnit19TestFactoryRegistry14addTestToSuiteEPNS_9TestSuiteE - fun:_ZN7CppUnit19TestFactoryRegistry8makeTestEv - obj:/usr/bin/DllPlugInTester - obj:/usr/bin/DllPlugInTester - fun:(below main) -} diff --git a/qpid/cpp/tests/APRBaseTest.cpp b/qpid/cpp/tests/APRBaseTest.cpp deleted file mode 100644 index 7d95c3bf52..0000000000 --- a/qpid/cpp/tests/APRBaseTest.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 -#include -#include - -using namespace qpid::sys; - -class APRBaseTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(APRBaseTest); - CPPUNIT_TEST(testMe); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testMe() - { - APRBase::increment(); - APRBase::increment(); - APRBase::decrement(); - APRBase::decrement(); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(APRBaseTest); - diff --git a/qpid/cpp/tests/AccumulatedAckTest.cpp b/qpid/cpp/tests/AccumulatedAckTest.cpp deleted file mode 100644 index 30554f808e..0000000000 --- a/qpid/cpp/tests/AccumulatedAckTest.cpp +++ /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. - * - */ -#include -#include -#include -#include - -using std::list; -using namespace qpid::broker; - -class AccumulatedAckTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(AccumulatedAckTest); - CPPUNIT_TEST(testGeneral); - CPPUNIT_TEST(testCovers); - CPPUNIT_TEST(testUpdateAndConsolidate); - CPPUNIT_TEST_SUITE_END(); - - public: - void testGeneral() - { - AccumulatedAck ack(0); - ack.clear(); - ack.update(3,3); - ack.update(7,7); - ack.update(9,9); - ack.update(1,2); - ack.update(4,5); - ack.update(6,6); - - for(int i = 1; i <= 7; i++) CPPUNIT_ASSERT(ack.covers(i)); - CPPUNIT_ASSERT(ack.covers(9)); - - CPPUNIT_ASSERT(!ack.covers(8)); - CPPUNIT_ASSERT(!ack.covers(10)); - - ack.consolidate(); - - for(int i = 1; i <= 7; i++) CPPUNIT_ASSERT(ack.covers(i)); - CPPUNIT_ASSERT(ack.covers(9)); - - CPPUNIT_ASSERT(!ack.covers(8)); - CPPUNIT_ASSERT(!ack.covers(10)); - } - - void testCovers() - { - AccumulatedAck ack(5); - ack.individual.push_back(7); - ack.individual.push_back(9); - - CPPUNIT_ASSERT(ack.covers(1)); - CPPUNIT_ASSERT(ack.covers(2)); - CPPUNIT_ASSERT(ack.covers(3)); - CPPUNIT_ASSERT(ack.covers(4)); - CPPUNIT_ASSERT(ack.covers(5)); - CPPUNIT_ASSERT(ack.covers(7)); - CPPUNIT_ASSERT(ack.covers(9)); - - CPPUNIT_ASSERT(!ack.covers(6)); - CPPUNIT_ASSERT(!ack.covers(8)); - CPPUNIT_ASSERT(!ack.covers(10)); - } - - void testUpdateAndConsolidate() - { - AccumulatedAck ack(0); - ack.update(1, 1); - ack.update(3, 3); - ack.update(10, 10); - ack.update(8, 8); - ack.update(6, 6); - ack.update(3, 3); - ack.update(2, 2); - ack.update(0, 5); - ack.consolidate(); - CPPUNIT_ASSERT_EQUAL((uint64_t) 6, ack.range); - CPPUNIT_ASSERT_EQUAL((size_t) 2, ack.individual.size()); - list::iterator i = ack.individual.begin(); - CPPUNIT_ASSERT_EQUAL((uint64_t) 8, *i); - i++; - CPPUNIT_ASSERT_EQUAL((uint64_t) 10, *i); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(AccumulatedAckTest); - diff --git a/qpid/cpp/tests/BrokerChannelTest.cpp b/qpid/cpp/tests/BrokerChannelTest.cpp deleted file mode 100644 index 66a7138dab..0000000000 --- a/qpid/cpp/tests/BrokerChannelTest.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "AMQFrame.h" -#include "MockChannel.h" -#include "broker/Connection.h" -#include "ProtocolInitiation.h" -#include - -using namespace boost; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -using std::string; -using std::queue; - -struct MockHandler : ConnectionOutputHandler{ - boost::ptr_vector frames; - - void send(AMQFrame* frame){ frames.push_back(frame); } - - void close() {}; -}; - - -class BrokerChannelTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(BrokerChannelTest); - CPPUNIT_TEST(testConsumerMgmt); - CPPUNIT_TEST(testDeliveryNoAck); - CPPUNIT_TEST(testDeliveryAndRecovery); - CPPUNIT_TEST(testStaging); - CPPUNIT_TEST(testQueuePolicy); - CPPUNIT_TEST_SUITE_END(); - - Broker::shared_ptr broker; - Connection connection; - MockHandler handler; - - class MockMessageStore : public NullMessageStore - { - struct MethodCall - { - const string name; - PersistableMessage* msg; - const string data;//only needed for appendContent - - void check(const MethodCall& other) const - { - CPPUNIT_ASSERT_EQUAL(name, other.name); - CPPUNIT_ASSERT_EQUAL(msg, other.msg); - CPPUNIT_ASSERT_EQUAL(data, other.data); - } - }; - - queue expected; - bool expectMode;//true when setting up expected calls - - void handle(const MethodCall& call) - { - if (expectMode) { - expected.push(call); - } else { - call.check(expected.front()); - expected.pop(); - } - } - - void handle(const string& name, PersistableMessage* msg, const string& data) - { - MethodCall call = {name, msg, data}; - handle(call); - } - - public: - - MockMessageStore() : expectMode(false) {} - - void stage(PersistableMessage& msg) - { - if(!expectMode) msg.setPersistenceId(1); - MethodCall call = {"stage", &msg, ""}; - handle(call); - } - - void appendContent(PersistableMessage& msg, const string& data) - { - MethodCall call = {"appendContent", &msg, data}; - handle(call); - } - - // Don't hide overloads. - using NullMessageStore::destroy; - - void destroy(PersistableMessage& msg) - { - MethodCall call = {"destroy", &msg, ""}; - handle(call); - } - - void expect() - { - expectMode = true; - } - - void test() - { - expectMode = false; - } - - void check() - { - CPPUNIT_ASSERT(expected.empty()); - } - }; - - - public: - - BrokerChannelTest() : - broker(Broker::create()), - connection(&handler, *broker) - { - connection.initiated(ProtocolInitiation()); - } - - - void testConsumerMgmt(){ - Queue::shared_ptr queue(new Queue("my_queue")); - Channel channel(connection, 0, 0, 0); - channel.open(); - CPPUNIT_ASSERT(!channel.exists("my_consumer")); - - ConnectionToken* owner = 0; - string tag("my_consumer"); - channel.consume(tag, queue, false, false, owner); - string tagA; - string tagB; - channel.consume(tagA, queue, false, false, owner); - channel.consume(tagB, queue, false, false, owner); - CPPUNIT_ASSERT_EQUAL((uint32_t) 3, queue->getConsumerCount()); - CPPUNIT_ASSERT(channel.exists("my_consumer")); - CPPUNIT_ASSERT(channel.exists(tagA)); - CPPUNIT_ASSERT(channel.exists(tagB)); - channel.cancel(tagA); - CPPUNIT_ASSERT_EQUAL((uint32_t) 2, queue->getConsumerCount()); - CPPUNIT_ASSERT(channel.exists("my_consumer")); - CPPUNIT_ASSERT(!channel.exists(tagA)); - CPPUNIT_ASSERT(channel.exists(tagB)); - channel.close(); - CPPUNIT_ASSERT_EQUAL((uint32_t) 0, queue->getConsumerCount()); - } - - void testDeliveryNoAck(){ - Channel channel(connection, 7, 10000); - channel.open(); - const string data("abcdefghijklmn"); - Message::shared_ptr msg( - createMessage("test", "my_routing_key", "my_message_id", 14)); - addContent(msg, data); - Queue::shared_ptr queue(new Queue("my_queue")); - ConnectionToken* owner(0); - string tag("no_ack"); - channel.consume(tag, queue, false, false, owner); - - queue->deliver(msg); - CPPUNIT_ASSERT_EQUAL((size_t) 4, handler.frames.size()); - CPPUNIT_ASSERT_EQUAL(ChannelId(0), handler.frames[0].getChannel()); - CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[1].getChannel()); - CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[2].getChannel()); - CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[3].getChannel()); - CPPUNIT_ASSERT(dynamic_cast( - handler.frames[0].getBody().get())); - CPPUNIT_ASSERT(dynamic_cast( - handler.frames[1].getBody().get())); - CPPUNIT_ASSERT(dynamic_cast( - handler.frames[2].getBody().get())); - AMQContentBody* contentBody = dynamic_cast( - handler.frames[3].getBody().get()); - CPPUNIT_ASSERT(contentBody); - CPPUNIT_ASSERT_EQUAL(data, contentBody->getData()); - } - - void testDeliveryAndRecovery(){ - Channel channel(connection, 7, 10000); - channel.open(); - const string data("abcdefghijklmn"); - - Message::shared_ptr msg(createMessage("test", "my_routing_key", "my_message_id", 14)); - addContent(msg, data); - - Queue::shared_ptr queue(new Queue("my_queue")); - ConnectionToken* owner(0); - string tag("ack"); - channel.consume(tag, queue, true, false, owner); - - queue->deliver(msg); - CPPUNIT_ASSERT_EQUAL((size_t) 4, handler.frames.size()); - CPPUNIT_ASSERT_EQUAL(ChannelId(0), handler.frames[0].getChannel()); - CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[1].getChannel()); - CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[2].getChannel()); - CPPUNIT_ASSERT_EQUAL(ChannelId(7), handler.frames[3].getChannel()); - CPPUNIT_ASSERT(dynamic_cast( - handler.frames[0].getBody().get())); - CPPUNIT_ASSERT(dynamic_cast( - handler.frames[1].getBody().get())); - CPPUNIT_ASSERT(dynamic_cast( - handler.frames[2].getBody().get())); - AMQContentBody* contentBody = dynamic_cast( - handler.frames[3].getBody().get()); - CPPUNIT_ASSERT(contentBody); - CPPUNIT_ASSERT_EQUAL(data, contentBody->getData()); - } - - void testStaging(){ - MockMessageStore store; - Channel channel( - connection, 1, 1000/*framesize*/, &store, 10/*staging threshold*/); - const string data[] = {"abcde", "fghij", "klmno"}; - - Message* msg = new BasicMessage( - 0, "my_exchange", "my_routing_key", false, false, - MockChannel::basicGetBody()); - - store.expect(); - store.stage(*msg); - for (int i = 0; i < 3; i++) { - store.appendContent(*msg, data[i]); - } - store.destroy(*msg); - store.test(); - - Exchange::shared_ptr exchange = - broker->getExchanges().declare("my_exchange", "fanout").first; - Queue::shared_ptr queue(new Queue("my_queue")); - exchange->bind(queue, "", 0); - - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - uint64_t contentSize(0); - for (int i = 0; i < 3; i++) { - contentSize += data[i].size(); - } - header->setContentSize(contentSize); - channel.handlePublish(msg); - channel.handleHeader(header); - - for (int i = 0; i < 3; i++) { - AMQContentBody::shared_ptr body(new AMQContentBody(data[i])); - channel.handleContent(body); - } - Message::shared_ptr msg2 = queue->dequeue(); - CPPUNIT_ASSERT_EQUAL(msg, msg2.get()); - msg2.reset();//should trigger destroy call - - store.check(); - } - - - //NOTE: strictly speaking this should/could be part of QueueTest, - //but as it can usefully use the same utility classes as this - //class it is defined here for simpllicity - void testQueuePolicy() - { - MockMessageStore store; - {//must ensure that store is last thing deleted as it is needed by destructor of lazy loaded content - const string data1("abcd"); - const string data2("efghijk"); - const string data3("lmnopqrstuvwxyz"); - Message::shared_ptr msg1(createMessage("e", "A", "MsgA", data1.size())); - Message::shared_ptr msg2(createMessage("e", "B", "MsgB", data2.size())); - Message::shared_ptr msg3(createMessage("e", "C", "MsgC", data3.size())); - addContent(msg1, data1); - addContent(msg2, data2); - addContent(msg3, data3); - - QueuePolicy policy(2, 0);//third message should be stored on disk and lazy loaded - FieldTable settings; - policy.update(settings); - - store.expect(); - store.stage(*msg3); - store.destroy(*msg3); - store.test(); - - Queue::shared_ptr queue(new Queue("my_queue", false, &store, 0)); - queue->configure(settings);//set policy - queue->deliver(msg1); - queue->deliver(msg2); - queue->deliver(msg3); - - Message::shared_ptr next = queue->dequeue(); - CPPUNIT_ASSERT_EQUAL(msg1, next); - CPPUNIT_ASSERT_EQUAL((uint32_t) data1.size(), next->encodedContentSize()); - next = queue->dequeue(); - CPPUNIT_ASSERT_EQUAL(msg2, next); - CPPUNIT_ASSERT_EQUAL((uint32_t) data2.size(), next->encodedContentSize()); - next = queue->dequeue(); - CPPUNIT_ASSERT_EQUAL(msg3, next); - CPPUNIT_ASSERT_EQUAL((uint32_t) 0, next->encodedContentSize()); - - next.reset(); - msg1.reset(); - msg2.reset(); - msg3.reset();//must clear all references to messages to allow them to be destroyed - - } - store.check(); - } - - Message* createMessage(const string& exchange, const string& routingKey, const string& messageId, uint64_t contentSize) - { - BasicMessage* msg = new BasicMessage( - 0, exchange, routingKey, false, false, - MockChannel::basicGetBody()); - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - header->setContentSize(contentSize); - msg->setHeader(header); - msg->getHeaderProperties()->setMessageId(messageId); - return msg; - } - - void addContent(Message::shared_ptr msg, const string& data) - { - AMQContentBody::shared_ptr body(new AMQContentBody(data)); - msg->addContent(body); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(BrokerChannelTest); diff --git a/qpid/cpp/tests/ClientChannelTest.cpp b/qpid/cpp/tests/ClientChannelTest.cpp deleted file mode 100644 index d041106a23..0000000000 --- a/qpid/cpp/tests/ClientChannelTest.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 "qpid_test_plugin.h" -#include "InProcessBroker.h" -#include "ClientChannel.h" -#include "ClientMessage.h" -#include "ClientQueue.h" -#include "ClientExchange.h" -#include "client/MessageListener.h" - -using namespace std; -using namespace boost; -using namespace qpid::client; -using namespace qpid::sys; -using namespace qpid::framing; - -/// Small frame size so we can create fragmented messages. -const size_t FRAME_MAX = 256; - - -/** - * Test client API using an in-process broker. - */ -class ClientChannelTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(ClientChannelTest); - CPPUNIT_TEST(testPublishGet); - CPPUNIT_TEST(testGetNoContent); - CPPUNIT_TEST(testConsumeCancel); - CPPUNIT_TEST(testConsumePublished); - CPPUNIT_TEST(testGetFragmentedMessage); - CPPUNIT_TEST(testConsumeFragmentedMessage); - CPPUNIT_TEST_SUITE_END(); - - struct Listener: public qpid::client::MessageListener { - vector messages; - Monitor monitor; - void received(Message& msg) { - Mutex::ScopedLock l(monitor); - messages.push_back(msg); - monitor.notifyAll(); - } - }; - - InProcessBrokerClient connection; // client::connection + local broker - Channel channel; - const std::string qname; - const std::string data; - Queue queue; - Exchange exchange; - Listener listener; - - public: - - ClientChannelTest() - : connection(FRAME_MAX), - qname("testq"), data("hello"), - queue(qname, true), exchange("", Exchange::DIRECT_EXCHANGE) - { - connection.openChannel(channel); - CPPUNIT_ASSERT(channel.getId() != 0); - channel.declareQueue(queue); - } - - void testPublishGet() { - Message pubMsg(data); - pubMsg.getHeaders().setString("hello", "world"); - channel.publish(pubMsg, exchange, qname); - Message getMsg; - CPPUNIT_ASSERT(channel.get(getMsg, queue)); - CPPUNIT_ASSERT_EQUAL(data, getMsg.getData()); - CPPUNIT_ASSERT_EQUAL(string("world"), - getMsg.getHeaders().getString("hello")); - CPPUNIT_ASSERT(!channel.get(getMsg, queue)); // Empty queue - } - - void testGetNoContent() { - Message pubMsg; - pubMsg.getHeaders().setString("hello", "world"); - channel.publish(pubMsg, exchange, qname); - Message getMsg; - CPPUNIT_ASSERT(channel.get(getMsg, queue)); - CPPUNIT_ASSERT(getMsg.getData().empty()); - CPPUNIT_ASSERT_EQUAL(string("world"), - getMsg.getHeaders().getString("hello")); - } - - void testConsumeCancel() { - string tag; // Broker assigned - channel.consume(queue, tag, &listener); - channel.start(); - CPPUNIT_ASSERT_EQUAL(size_t(0), listener.messages.size()); - channel.publish(Message("a"), exchange, qname); - { - Mutex::ScopedLock l(listener.monitor); - Time deadline(now() + 1*TIME_SEC); - while (listener.messages.size() != 1) { - CPPUNIT_ASSERT(listener.monitor.wait(deadline)); - } - } - CPPUNIT_ASSERT_EQUAL(size_t(1), listener.messages.size()); - CPPUNIT_ASSERT_EQUAL(string("a"), listener.messages[0].getData()); - - channel.publish(Message("b"), exchange, qname); - channel.publish(Message("c"), exchange, qname); - { - Mutex::ScopedLock l(listener.monitor); - while (listener.messages.size() != 3) { - CPPUNIT_ASSERT(listener.monitor.wait(1*TIME_SEC)); - } - } - CPPUNIT_ASSERT_EQUAL(size_t(3), listener.messages.size()); - CPPUNIT_ASSERT_EQUAL(string("b"), listener.messages[1].getData()); - CPPUNIT_ASSERT_EQUAL(string("c"), listener.messages[2].getData()); - - channel.cancel(tag); - channel.publish(Message("d"), exchange, qname); - CPPUNIT_ASSERT_EQUAL(size_t(3), listener.messages.size()); - { - Mutex::ScopedLock l(listener.monitor); - CPPUNIT_ASSERT(!listener.monitor.wait(TIME_SEC/2)); - } - Message msg; - CPPUNIT_ASSERT(channel.get(msg, queue)); - CPPUNIT_ASSERT_EQUAL(string("d"), msg.getData()); - } - - // Consume already-published messages - void testConsumePublished() { - Message pubMsg("x"); - pubMsg.getHeaders().setString("y", "z"); - channel.publish(pubMsg, exchange, qname); - string tag; - channel.consume(queue, tag, &listener); - CPPUNIT_ASSERT_EQUAL(size_t(0), listener.messages.size()); - channel.start(); - { - Mutex::ScopedLock l(listener.monitor); - while (listener.messages.size() != 1) - CPPUNIT_ASSERT(listener.monitor.wait(1*TIME_SEC)); - } - CPPUNIT_ASSERT_EQUAL(string("x"), listener.messages[0].getData()); - CPPUNIT_ASSERT_EQUAL(string("z"), - listener.messages[0].getHeaders().getString("y")); - } - - void testGetFragmentedMessage() { - string longStr(FRAME_MAX*2, 'x'); // Longer than max frame size. - channel.publish(Message(longStr), exchange, qname); - Message getMsg; - CPPUNIT_ASSERT(channel.get(getMsg, queue)); - } - - void testConsumeFragmentedMessage() { - string xx(FRAME_MAX*2, 'x'); - channel.publish(Message(xx), exchange, qname); - channel.start(); - string tag; - channel.consume(queue, tag, &listener); - string yy(FRAME_MAX*2, 'y'); - channel.publish(Message(yy), exchange, qname); - { - Mutex::ScopedLock l(listener.monitor); - while (listener.messages.size() != 2) - CPPUNIT_ASSERT(listener.monitor.wait(1*TIME_SEC)); - } - CPPUNIT_ASSERT_EQUAL(xx, listener.messages[0].getData()); - CPPUNIT_ASSERT_EQUAL(yy, listener.messages[1].getData()); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(ClientChannelTest); diff --git a/qpid/cpp/tests/ConfigurationTest.cpp b/qpid/cpp/tests/ConfigurationTest.cpp deleted file mode 100644 index 3a1d5ba85d..0000000000 --- a/qpid/cpp/tests/ConfigurationTest.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 -#include -#include - -using namespace std; -using namespace qpid::broker; - -class ConfigurationTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(ConfigurationTest); - CPPUNIT_TEST(testIsHelp); - CPPUNIT_TEST(testPortLongForm); - CPPUNIT_TEST(testPortShortForm); - CPPUNIT_TEST(testStore); - CPPUNIT_TEST(testStagingThreshold); - CPPUNIT_TEST(testVarious); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testIsHelp() - { - Configuration conf; - char* argv[] = {"ignore", "--help"}; - conf.parse("ignore", 2, argv); - CPPUNIT_ASSERT(conf.isHelp()); - } - - void testPortLongForm() - { - Configuration conf; - char* argv[] = {"ignore", "--port", "6789"}; - conf.parse("ignore", 3, argv); - CPPUNIT_ASSERT_EQUAL(6789, conf.getPort()); - } - - void testPortShortForm() - { - Configuration conf; - char* argv[] = {"ignore", "-p", "6789"}; - conf.parse("ignore", 3, argv); - CPPUNIT_ASSERT_EQUAL(6789, conf.getPort()); - } - - void testStore() - { - Configuration conf; - char* argv[] = {"ignore", "--store", "my-store-module.so"}; - conf.parse("ignore", 3, argv); - std::string expected("my-store-module.so"); - CPPUNIT_ASSERT_EQUAL(expected, conf.getStore()); - } - - void testStagingThreshold() - { - Configuration conf; - char* argv[] = {"ignore", "--staging-threshold", "123456789"}; - conf.parse("ignore", 3, argv); - long expected = 123456789; - CPPUNIT_ASSERT_EQUAL(expected, conf.getStagingThreshold()); - } - - void testVarious() - { - Configuration conf; - char* argv[] = {"ignore", "-t", "--worker-threads", "10"}; - conf.parse("ignore", 4, argv); - CPPUNIT_ASSERT_EQUAL(5672, conf.getPort());//default - CPPUNIT_ASSERT_EQUAL(10, conf.getWorkerThreads()); - CPPUNIT_ASSERT(conf.isTrace()); - CPPUNIT_ASSERT(!conf.isHelp()); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(ConfigurationTest); - diff --git a/qpid/cpp/tests/EventChannelConnectionTest.cpp b/qpid/cpp/tests/EventChannelConnectionTest.cpp deleted file mode 100644 index 66561daf83..0000000000 --- a/qpid/cpp/tests/EventChannelConnectionTest.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 -#include -#include "framing/AMQHeartbeatBody.h" -#include "framing/AMQFrame.h" -#include "sys/posix/EventChannelConnection.h" -#include "sys/ConnectionInputHandler.h" -#include "sys/ConnectionInputHandlerFactory.h" -#include "sys/Socket.h" -#include "qpid_test_plugin.h" -#include "MockConnectionInputHandler.h" - -using namespace qpid::sys; -using namespace qpid::framing; -using namespace std; - -class EventChannelConnectionTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(EventChannelConnectionTest); - CPPUNIT_TEST(testSendReceive); - CPPUNIT_TEST(testCloseExternal); - CPPUNIT_TEST(testCloseException); - CPPUNIT_TEST_SUITE_END(); - - public: - - void setUp() { - threads = EventChannelThreads::create(); - CPPUNIT_ASSERT_EQUAL(0, ::pipe(pipe)); - connection.reset( - new EventChannelConnection(threads, factory, pipe[0], pipe[1])); - CPPUNIT_ASSERT(factory.handler != 0); - } - - void tearDown() { - threads->shutdown(); - threads->join(); - } - - void testSendReceive() - { - // Send a protocol initiation. - Buffer buf(1024); - ProtocolInitiation(4,2).encode(buf); - buf.flip(); - ssize_t n = write(pipe[1], buf.start(), buf.available()); - CPPUNIT_ASSERT_EQUAL(ssize_t(buf.available()), n); - - // Verify session handler got the protocol init. - ProtocolInitiation init = factory.handler->waitForProtocolInit(); - CPPUNIT_ASSERT_EQUAL(int(4), int(init.getMajor())); - CPPUNIT_ASSERT_EQUAL(int(2), int(init.getMinor())); - - // Send a heartbeat frame, verify connection got it. - connection->send(new AMQFrame(42, new AMQHeartbeatBody())); - AMQFrame frame = factory.handler->waitForFrame(); - CPPUNIT_ASSERT_EQUAL(uint16_t(42), frame.getChannel()); - CPPUNIT_ASSERT_EQUAL(uint8_t(HEARTBEAT_BODY), - frame.getBody()->type()); - threads->shutdown(); - } - - // Make sure the handler is closed if the connection is closed. - void testCloseExternal() { - connection->close(); - factory.handler->waitForClosed(); - } - - // Make sure the handler is closed if the connection closes or fails. - // TODO aconway 2006-12-18: logs exception message in test output. - void testCloseException() { - ::close(pipe[0]); - ::close(pipe[1]); - // TODO aconway 2006-12-18: Shouldn't this be failing? - connection->send(new AMQFrame(42, new AMQHeartbeatBody())); - factory.handler->waitForClosed(); - } - - private: - EventChannelThreads::shared_ptr threads; - int pipe[2]; - std::auto_ptr connection; - MockConnectionInputHandlerFactory factory; -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(EventChannelConnectionTest); - diff --git a/qpid/cpp/tests/EventChannelTest.cpp b/qpid/cpp/tests/EventChannelTest.cpp deleted file mode 100644 index 8e5c724a15..0000000000 --- a/qpid/cpp/tests/EventChannelTest.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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -using namespace qpid::sys; - - -const char hello[] = "hello"; -const size_t size = sizeof(hello); - -struct RunMe : public Runnable -{ - bool ran; - RunMe() : ran(false) {} - void run() { ran = true; } -}; - -class EventChannelTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(EventChannelTest); - CPPUNIT_TEST(testEvent); - CPPUNIT_TEST(testRead); - CPPUNIT_TEST(testFailedRead); - CPPUNIT_TEST(testWrite); - CPPUNIT_TEST(testFailedWrite); - CPPUNIT_TEST(testReadWrite); - CPPUNIT_TEST(testAccept); - CPPUNIT_TEST_SUITE_END(); - - private: - EventChannel::shared_ptr ec; - int pipe[2]; - char readBuf[size]; - - public: - - void setUp() - { - memset(readBuf, size, 0); - ec = EventChannel::create(); - if (::pipe(pipe) != 0) throw QPID_POSIX_ERROR(errno); - // Ignore SIGPIPE, otherwise we will crash writing to broken pipe. - signal(SIGPIPE, SIG_IGN); - } - - // Verify that calling getEvent returns event. - template bool isNextEvent(T& event) - { - return &event == dynamic_cast(ec->getEvent()); - } - - template bool isNextEventOk(T& event) - { - Event* next = ec->getEvent(); - if (next) next->throwIfError(); - return &event == next; - } - - void testEvent() - { - RunMe runMe; - CPPUNIT_ASSERT(!runMe.ran); - // Instances of Event just pass thru the channel immediately. - Event e(runMe.functor()); - ec->postEvent(e); - CPPUNIT_ASSERT(isNextEventOk(e)); - e.dispatch(); - CPPUNIT_ASSERT(runMe.ran); - } - - void testRead() { - ReadEvent re(pipe[0], readBuf, size); - ec->postEvent(re); - CPPUNIT_ASSERT_EQUAL(ssize_t(size), ::write(pipe[1], hello, size)); - CPPUNIT_ASSERT(isNextEventOk(re)); - CPPUNIT_ASSERT_EQUAL(size, re.getSize()); - CPPUNIT_ASSERT_EQUAL(std::string(hello), std::string(readBuf)); - } - - void testFailedRead() - { - ReadEvent re(pipe[0], readBuf, size); - ec->postEvent(re); - - // EOF before all data read. - ::close(pipe[1]); - CPPUNIT_ASSERT(isNextEvent(re)); - CPPUNIT_ASSERT(re.hasError()); - try { - re.throwIfError(); - CPPUNIT_FAIL("Expected QpidError."); - } - catch (const qpid::QpidError&) { } - - // Bad file descriptor. Note in this case we fail - // in postEvent and throw immediately. - try { - ReadEvent bad; - ec->postEvent(bad); - CPPUNIT_FAIL("Expected QpidError."); - } - catch (const qpid::QpidError&) { } - } - - void testWrite() { - WriteEvent wr(pipe[1], hello, size); - ec->postEvent(wr); - CPPUNIT_ASSERT(isNextEventOk(wr)); - CPPUNIT_ASSERT_EQUAL(ssize_t(size), ::read(pipe[0], readBuf, size));; - CPPUNIT_ASSERT_EQUAL(std::string(hello), std::string(readBuf)); - } - - void testFailedWrite() { - WriteEvent wr(pipe[1], hello, size); - ::close(pipe[0]); - ec->postEvent(wr); - CPPUNIT_ASSERT(isNextEvent(wr)); - CPPUNIT_ASSERT(wr.hasError()); - } - - void testReadWrite() - { - ReadEvent re(pipe[0], readBuf, size); - WriteEvent wr(pipe[1], hello, size); - ec->postEvent(re); - ec->postEvent(wr); - ec->getEvent(); - ec->getEvent(); - CPPUNIT_ASSERT_EQUAL(std::string(hello), std::string(readBuf)); - } - - void testAccept() { - Socket s = Socket::createTcp(); - int port = s.listen(0, 10); - CPPUNIT_ASSERT(port != 0); - - AcceptEvent ae(s.fd()); - ec->postEvent(ae); - Socket client = Socket::createTcp(); - client.connect("localhost", port); - CPPUNIT_ASSERT(isNextEvent(ae)); - ae.dispatch(); - - // Verify client writes are read by the accepted descriptor. - char readBuf[size]; - ReadEvent re(ae.getAcceptedDesscriptor(), readBuf, size); - ec->postEvent(re); - CPPUNIT_ASSERT_EQUAL(ssize_t(size), client.send(hello, sizeof(hello))); - CPPUNIT_ASSERT(isNextEvent(re)); - re.dispatch(); - CPPUNIT_ASSERT_EQUAL(std::string(hello), std::string(readBuf)); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(EventChannelTest); - diff --git a/qpid/cpp/tests/EventChannelThreadsTest.cpp b/qpid/cpp/tests/EventChannelThreadsTest.cpp deleted file mode 100644 index 285ed29518..0000000000 --- a/qpid/cpp/tests/EventChannelThreadsTest.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 -#include - -#include -#include -#include - - -using namespace std; - -using namespace qpid::sys; - -const int nConnections = 5; -const int nMessages = 10; // Messages read/written per connection. - - -// Accepts + reads + writes. -const int totalEvents = nConnections+2*nConnections*nMessages; - -/** - * Messages are numbered 0..nMessages. - * We count the total number of events, and the - * number of reads and writes for each message number. - */ -class TestResults : public Monitor { - public: - TestResults() : isShutdown(false), nEventsRemaining(totalEvents) {} - - void countEvent() { - if (--nEventsRemaining == 0) - shutdown(); - } - - void countRead(int messageNo) { - ++reads[messageNo]; - countEvent(); - } - - void countWrite(int messageNo) { - ++writes[messageNo]; - countEvent(); - } - - void shutdown(const std::string& exceptionMsg = std::string()) { - ScopedLock lock(*this); - exception = exceptionMsg; - isShutdown = true; - notifyAll(); - } - - void wait() { - ScopedLock lock(*this); - Time deadline = now() + 10*TIME_SEC; - while (!isShutdown) { - CPPUNIT_ASSERT(Monitor::wait(deadline)); - } - } - - bool isShutdown; - std::string exception; - AtomicCount reads[nMessages]; - AtomicCount writes[nMessages]; - AtomicCount nEventsRemaining; -}; - -TestResults results; - -EventChannelThreads::shared_ptr threads; - -// Functor to wrap callbacks in try/catch. -class SafeCallback { - public: - SafeCallback(Runnable& r) : callback(r.functor()) {} - SafeCallback(Event::Callback cb) : callback(cb) {} - - void operator()() { - std::string exception; - try { - callback(); - return; - } - catch (const std::exception& e) { - exception = e.what(); - } - catch (...) { - exception = "Unknown exception."; - } - results.shutdown(exception); - } - - private: - Event::Callback callback; -}; - -/** Repost an event N times. */ -class Repost { - public: - Repost(int n) : count (n) {} - virtual ~Repost() {} - - void repost(Event* event) { - if (--count==0) { - delete event; - } else { - threads->postEvent(event); - } - } - private: - int count; -}; - - - -/** Repeating read event. */ -class TestReadEvent : public ReadEvent, public Runnable, private Repost { - public: - explicit TestReadEvent(int fd=-1) : - ReadEvent(fd, &value, sizeof(value), SafeCallback(*this)), - Repost(nMessages) - {} - - void run() { - CPPUNIT_ASSERT_EQUAL(sizeof(value), getSize()); - CPPUNIT_ASSERT(0 <= value); - CPPUNIT_ASSERT(value < nMessages); - results.countRead(value); - repost(this); - } - - private: - int value; - ReadEvent original; -}; - - -/** Fire and forget write event */ -class TestWriteEvent : public WriteEvent, public Runnable, private Repost { - public: - TestWriteEvent(int fd=-1) : - WriteEvent(fd, &value, sizeof(value), SafeCallback(*this)), - Repost(nMessages), - value(0) - {} - - void run() { - CPPUNIT_ASSERT_EQUAL(sizeof(int), getSize()); - results.countWrite(value++); - repost(this); - } - - private: - int value; -}; - -/** Fire-and-forget Accept event, posts reads on the accepted connection. */ -class TestAcceptEvent : public AcceptEvent, public Runnable, private Repost { - public: - TestAcceptEvent(int fd=-1) : - AcceptEvent(fd, SafeCallback(*this)), - Repost(nConnections) - {} - - void run() { - threads->postEvent(new TestReadEvent(getAcceptedDesscriptor())); - results.countEvent(); - repost(this); - } -}; - -class EventChannelThreadsTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(EventChannelThreadsTest); - CPPUNIT_TEST(testThreads); - CPPUNIT_TEST_SUITE_END(); - - public: - - void setUp() { - threads = EventChannelThreads::create(EventChannel::create()); - } - - void tearDown() { - threads.reset(); - } - - void testThreads() - { - Socket listener = Socket::createTcp(); - int port = listener.listen(); - - // Post looping accept events, will repost nConnections times. - // The accept event will automatically post read events. - threads->postEvent(new TestAcceptEvent(listener.fd())); - - // Make connections. - Socket connections[nConnections]; - for (int i = 0; i < nConnections; ++i) { - connections[i] = Socket::createTcp(); - connections[i].connect("localhost", port); - } - - // Post looping write events. - for (int i = 0; i < nConnections; ++i) { - threads->postEvent(new TestWriteEvent(connections[i].fd())); - } - - // Wait for all events to be dispatched. - results.wait(); - - if (!results.exception.empty()) CPPUNIT_FAIL(results.exception); - CPPUNIT_ASSERT_EQUAL(0, int(results.nEventsRemaining)); - - // Expect a read and write for each messageNo from each connection. - for (int messageNo = 0; messageNo < nMessages; ++messageNo) { - CPPUNIT_ASSERT_EQUAL(nConnections, int(results.reads[messageNo])); - CPPUNIT_ASSERT_EQUAL(nConnections, int(results.writes[messageNo])); - } - - threads->shutdown(); - threads->join(); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(EventChannelThreadsTest); - diff --git a/qpid/cpp/tests/ExchangeTest.cpp b/qpid/cpp/tests/ExchangeTest.cpp deleted file mode 100644 index cccec92024..0000000000 --- a/qpid/cpp/tests/ExchangeTest.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 -#include -#include -#include -#include -#include -#include -#include "BasicGetBody.h" - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -class ExchangeTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(ExchangeTest); - CPPUNIT_TEST(testMe); - CPPUNIT_TEST_SUITE_END(); - - public: - - void 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(); - - Message::shared_ptr msgPtr( - new BasicMessage( - 0, "e", "A", true, true, - AMQMethodBody::shared_ptr( - new BasicGetBody(ProtocolVersion())))); - DeliverableMessage msg(msgPtr); - topic.route(msg, "abc", 0); - direct.route(msg, "abc", 0); - - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(ExchangeTest); diff --git a/qpid/cpp/tests/FieldTableTest.cpp b/qpid/cpp/tests/FieldTableTest.cpp deleted file mode 100644 index 8d9285bf4b..0000000000 --- a/qpid/cpp/tests/FieldTableTest.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 -#include -#include - -using namespace qpid::framing; - -class FieldTableTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(FieldTableTest); - CPPUNIT_TEST(testMe); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testMe() - { - FieldTable ft; - ft.setString("A", "BCDE"); - CPPUNIT_ASSERT_EQUAL(std::string("BCDE"), ft.getString("A")); - - Buffer buffer(100); - buffer.putFieldTable(ft); - buffer.flip(); - FieldTable ft2; - buffer.getFieldTable(ft2); - CPPUNIT_ASSERT_EQUAL(std::string("BCDE"), ft2.getString("A")); - - } -}; - - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(FieldTableTest); - diff --git a/qpid/cpp/tests/FramingTest.cpp b/qpid/cpp/tests/FramingTest.cpp deleted file mode 100644 index f8754337c8..0000000000 --- a/qpid/cpp/tests/FramingTest.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "AMQRequestBody.h" -#include "AMQResponseBody.h" -#include "Requester.h" -#include "Responder.h" -#include "InProcessBroker.h" -#include "client/Connection.h" -#include "client/ClientExchange.h" -#include "client/ClientQueue.h" - -using namespace qpid; -using namespace qpid::framing; -using namespace std; - -template -std::string tostring(const T& x) -{ - std::ostringstream out; - out << x; - return out.str(); -} - -class FramingTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(FramingTest); - CPPUNIT_TEST(testBasicQosBody); - CPPUNIT_TEST(testConnectionSecureBody); - CPPUNIT_TEST(testConnectionRedirectBody); - CPPUNIT_TEST(testAccessRequestBody); - CPPUNIT_TEST(testBasicConsumeBody); - CPPUNIT_TEST(testConnectionRedirectBodyFrame); - CPPUNIT_TEST(testBasicConsumeOkBodyFrame); - CPPUNIT_TEST(testRequestBodyFrame); - CPPUNIT_TEST(testResponseBodyFrame); - CPPUNIT_TEST(testRequester); - CPPUNIT_TEST(testResponder); - CPPUNIT_TEST(testInlineContent); - CPPUNIT_TEST(testContentReference); - CPPUNIT_TEST(testContentValidation); - CPPUNIT_TEST(testRequestResponseRoundtrip); - CPPUNIT_TEST_SUITE_END(); - - private: - Buffer buffer; - ProtocolVersion version; - AMQP_MethodVersionMap versionMap; - - public: - - FramingTest() : buffer(1024), version(highestProtocolVersion) {} - - void testBasicQosBody() - { - BasicQosBody in(version, 0xCAFEBABE, 0xABBA, true); - in.encodeContent(buffer); - buffer.flip(); - BasicQosBody out(version); - out.decodeContent(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - void testConnectionSecureBody() - { - std::string s = "security credential"; - ConnectionSecureBody in(version, s); - in.encodeContent(buffer); - buffer.flip(); - ConnectionSecureBody out(version); - out.decodeContent(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - void testConnectionRedirectBody() - { - std::string a = "hostA"; - std::string b = "hostB"; - ConnectionRedirectBody in(version, 0, a, b); - in.encodeContent(buffer); - buffer.flip(); - ConnectionRedirectBody out(version); - out.decodeContent(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - void testAccessRequestBody() - { - std::string s = "text"; - AccessRequestBody in(version, s, true, false, true, false, true); - in.encodeContent(buffer); - buffer.flip(); - AccessRequestBody out(version); - out.decodeContent(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - void testBasicConsumeBody() - { - std::string q = "queue"; - std::string t = "tag"; - BasicConsumeBody in(version, 0, q, t, false, true, false, false, - FieldTable()); - in.encodeContent(buffer); - buffer.flip(); - BasicConsumeBody out(version); - out.decodeContent(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - - void testConnectionRedirectBodyFrame() - { - std::string a = "hostA"; - std::string b = "hostB"; - AMQFrame in(version, 999, - new ConnectionRedirectBody(version, 0, a, b)); - in.encode(buffer); - buffer.flip(); - AMQFrame out; - out.decode(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - void testBasicConsumeOkBodyFrame() - { - std::string s = "hostA"; - AMQFrame in(version, 999, new BasicConsumeOkBody(version, 0, s)); - in.encode(buffer); - buffer.flip(); - AMQFrame out; - for(int i = 0; i < 5; i++){ - out.decode(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - } - - void testRequestBodyFrame() { - std::string testing("testing"); - AMQBody::shared_ptr request(new ChannelOpenBody(version, testing)); - AMQFrame in(version, 999, request); - in.encode(buffer); - buffer.flip(); - AMQFrame out; - out.decode(buffer); - ChannelOpenBody* decoded = - dynamic_cast(out.getBody().get()); - CPPUNIT_ASSERT(decoded); - CPPUNIT_ASSERT_EQUAL(testing, decoded->getOutOfBand()); - } - - void testResponseBodyFrame() { - AMQBody::shared_ptr response(new ChannelOkBody(version)); - AMQFrame in(version, 999, response); - in.encode(buffer); - buffer.flip(); - AMQFrame out; - out.decode(buffer); - ChannelOkBody* decoded = - dynamic_cast(out.getBody().get()); - CPPUNIT_ASSERT(decoded); - } - - void testInlineContent() { - Content content(INLINE, "MyData"); - CPPUNIT_ASSERT(content.isInline()); - content.encode(buffer); - buffer.flip(); - Content recovered; - recovered.decode(buffer); - CPPUNIT_ASSERT(recovered.isInline()); - CPPUNIT_ASSERT_EQUAL(content.getValue(), recovered.getValue()); - } - - void testContentReference() { - Content content(REFERENCE, "MyRef"); - CPPUNIT_ASSERT(content.isReference()); - content.encode(buffer); - buffer.flip(); - Content recovered; - recovered.decode(buffer); - CPPUNIT_ASSERT(recovered.isReference()); - CPPUNIT_ASSERT_EQUAL(content.getValue(), recovered.getValue()); - } - - void testContentValidation() { - try { - Content content(REFERENCE, ""); - CPPUNIT_ASSERT(false);//fail, expected exception - } catch (QpidError& e) { - CPPUNIT_ASSERT_EQUAL(FRAMING_ERROR, e.code); - CPPUNIT_ASSERT_EQUAL(string("Reference cannot be empty"), e.msg); - } - - try { - Content content(2, "Blah"); - CPPUNIT_ASSERT(false);//fail, expected exception - } catch (QpidError& e) { - CPPUNIT_ASSERT_EQUAL(FRAMING_ERROR, e.code); - CPPUNIT_ASSERT_EQUAL(string("Invalid discriminator: 2"), e.msg); - } - - try { - buffer.putOctet(2); - buffer.putLongString("blah, blah"); - buffer.flip(); - Content content; - content.decode(buffer); - CPPUNIT_ASSERT(false);//fail, expected exception - } catch (QpidError& e) { - CPPUNIT_ASSERT_EQUAL(FRAMING_ERROR, e.code); - CPPUNIT_ASSERT_EQUAL(string("Invalid discriminator: 2"), e.msg); - } - - } - - void testRequester() { - Requester r; - AMQRequestBody::Data q; - AMQResponseBody::Data p; - - r.sending(q); - CPPUNIT_ASSERT_EQUAL(1ULL, q.requestId); - CPPUNIT_ASSERT_EQUAL(0ULL, q.responseMark); - - r.sending(q); - CPPUNIT_ASSERT_EQUAL(2ULL, q.requestId); - CPPUNIT_ASSERT_EQUAL(0ULL, q.responseMark); - - // Now process a response - p.responseId = 1; - p.requestId = 2; - r.processed(AMQResponseBody::Data(1, 2)); - - r.sending(q); - CPPUNIT_ASSERT_EQUAL(3ULL, q.requestId); - CPPUNIT_ASSERT_EQUAL(1ULL, q.responseMark); - - try { - r.processed(p); // Already processed this response. - CPPUNIT_FAIL("Expected exception"); - } catch (...) {} - - try { - p.requestId = 50; - r.processed(p); // No such request - CPPUNIT_FAIL("Expected exception"); - } catch (...) {} - - r.sending(q); // reqId=4 - r.sending(q); // reqId=5 - r.sending(q); // reqId=6 - p.responseId++; - p.requestId = 4; - p.batchOffset = 2; - r.processed(p); - r.sending(q); - CPPUNIT_ASSERT_EQUAL(7ULL, q.requestId); - CPPUNIT_ASSERT_EQUAL(2ULL, q.responseMark); - - p.responseId++; - p.requestId = 1; // Out of order - p.batchOffset = 0; - r.processed(p); - r.sending(q); - CPPUNIT_ASSERT_EQUAL(8ULL, q.requestId); - CPPUNIT_ASSERT_EQUAL(3ULL, q.responseMark); - } - - void testResponder() { - Responder r; - AMQRequestBody::Data q; - AMQResponseBody::Data p; - - q.requestId = 1; - q.responseMark = 0; - r.received(q); - p.requestId = q.requestId; - r.sending(p); - CPPUNIT_ASSERT_EQUAL(1ULL, p.responseId); - CPPUNIT_ASSERT_EQUAL(1ULL, p.requestId); - CPPUNIT_ASSERT_EQUAL(0U, p.batchOffset); - CPPUNIT_ASSERT_EQUAL(0ULL, r.getResponseMark()); - - q.requestId++; - q.responseMark = 1; - r.received(q); - r.sending(p); - CPPUNIT_ASSERT_EQUAL(2ULL, p.responseId); - CPPUNIT_ASSERT_EQUAL(0U, p.batchOffset); - CPPUNIT_ASSERT_EQUAL(1ULL, r.getResponseMark()); - - try { - // Response mark higher any request ID sent. - q.responseMark = 3; - r.received(q); - } catch(...) {} - - try { - // Response mark lower than previous response mark. - q.responseMark = 0; - r.received(q); - } catch(...) {} - - // TODO aconway 2007-01-14: Test for batching when supported. - - } - - // expect may contain null chars so use string(ptr,size) constructor - // Use sizeof(expect)-1 to strip the trailing null. -#define ASSERT_FRAME(expect, frame) \ - CPPUNIT_ASSERT_EQUAL(string(expect, sizeof(expect)-1), boost::lexical_cast(frame)) - - void testRequestResponseRoundtrip() { - broker::InProcessBroker ibroker(version); - client::Connection clientConnection; - clientConnection.setConnector(ibroker); - clientConnection.open(""); - client::Channel c; - clientConnection.openChannel(c); - - client::Exchange exchange( - "MyExchange", client::Exchange::TOPIC_EXCHANGE); - client::Queue queue("MyQueue", true); - c.declareExchange(exchange); - c.declareQueue(queue); - c.bind(exchange, queue, "MyTopic", framing::FieldTable()); - broker::InProcessBroker::Conversation::const_iterator i = ibroker.conversation.begin(); - ASSERT_FRAME("BROKER: Frame[channel=0; request(id=1,mark=0): ConnectionStart: versionMajor=0; versionMinor=9; serverProperties={}; mechanisms=PLAIN; locales=en_US]", *i++); - ASSERT_FRAME("CLIENT: Frame[channel=0; response(id=1,request=1,batch=0): ConnectionStartOk: clientProperties={}; mechanism=PLAIN; response=\000guest\000guest; locale=en_US]", *i++); - ASSERT_FRAME("BROKER: Frame[channel=0; request(id=2,mark=1): ConnectionTune: channelMax=100; frameMax=65536; heartbeat=0]", *i++); - ASSERT_FRAME("CLIENT: Frame[channel=0; response(id=2,request=2,batch=0): ConnectionTuneOk: channelMax=100; frameMax=65536; heartbeat=0]", *i++); - ASSERT_FRAME("CLIENT: Frame[channel=0; request(id=1,mark=0): ConnectionOpen: virtualHost=/; capabilities=; insist=1]", *i++); - ASSERT_FRAME("BROKER: Frame[channel=0; response(id=1,request=1,batch=0): ConnectionOpenOk: knownHosts=]", *i++); - ASSERT_FRAME("CLIENT: Frame[channel=1; request(id=1,mark=0): ChannelOpen: outOfBand=]", *i++); - ASSERT_FRAME("BROKER: Frame[channel=1; response(id=1,request=1,batch=0): ChannelOpenOk: channelId=]", *i++); - ASSERT_FRAME("CLIENT: Frame[channel=1; request(id=2,mark=1): ExchangeDeclare: ticket=0; exchange=MyExchange; type=topic; passive=0; durable=0; autoDelete=0; internal=0; nowait=0; arguments={}]", *i++); - ASSERT_FRAME("BROKER: Frame[channel=1; response(id=2,request=2,batch=0): ExchangeDeclareOk: ]", *i++); - ASSERT_FRAME("CLIENT: Frame[channel=1; request(id=3,mark=2): QueueDeclare: ticket=0; queue=MyQueue; passive=0; durable=0; exclusive=1; autoDelete=1; nowait=0; arguments={}]", *i++); - ASSERT_FRAME("BROKER: Frame[channel=1; response(id=3,request=3,batch=0): QueueDeclareOk: queue=MyQueue; messageCount=0; consumerCount=0]", *i++); - ASSERT_FRAME("CLIENT: Frame[channel=1; request(id=4,mark=3): QueueBind: ticket=0; queue=MyQueue; exchange=MyExchange; routingKey=MyTopic; nowait=0; arguments={}]", *i++); - ASSERT_FRAME("BROKER: Frame[channel=1; response(id=4,request=4,batch=0): QueueBindOk: ]", *i++); - } - }; - - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(FramingTest); - - - diff --git a/qpid/cpp/tests/HeaderTest.cpp b/qpid/cpp/tests/HeaderTest.cpp deleted file mode 100644 index 77e68829c3..0000000000 --- a/qpid/cpp/tests/HeaderTest.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 -#include -#include - -using namespace qpid::framing; - -class HeaderTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(HeaderTest); - CPPUNIT_TEST(testGenericProperties); - CPPUNIT_TEST(testAllSpecificProperties); - CPPUNIT_TEST(testSomeSpecificProperties); - CPPUNIT_TEST_SUITE_END(); - -public: - - void testGenericProperties() - { - AMQHeaderBody body(BASIC); - dynamic_cast(body.getProperties())->getHeaders().setString("A", "BCDE"); - Buffer buffer(100); - - body.encode(buffer); - buffer.flip(); - AMQHeaderBody body2; - body2.decode(buffer, body.size()); - BasicHeaderProperties* props = - dynamic_cast(body2.getProperties()); - CPPUNIT_ASSERT_EQUAL(std::string("BCDE"), - props->getHeaders().getString("A")); - } - - void testAllSpecificProperties(){ - string contentType("text/html"); - string contentEncoding("UTF8"); - DeliveryMode deliveryMode(PERSISTENT); - uint8_t priority(3); - string correlationId("abc"); - string replyTo("no-address"); - string expiration("why is this a string?"); - string messageId("xyz"); - uint64_t timestamp(0xabcd); - string type("eh?"); - string userId("guest"); - string appId("just testing"); - string clusterId("no clustering required"); - - AMQHeaderBody body(BASIC); - BasicHeaderProperties* properties = - dynamic_cast(body.getProperties()); - properties->setContentType(contentType); - properties->getHeaders().setString("A", "BCDE"); - properties->setDeliveryMode(deliveryMode); - properties->setPriority(priority); - properties->setCorrelationId(correlationId); - properties->setReplyTo(replyTo); - properties->setExpiration(expiration); - properties->setMessageId(messageId); - properties->setTimestamp(timestamp); - properties->setType(type); - properties->setUserId(userId); - properties->setAppId(appId); - properties->setClusterId(clusterId); - - Buffer buffer(10000); - body.encode(buffer); - buffer.flip(); - AMQHeaderBody temp; - temp.decode(buffer, body.size()); - properties = dynamic_cast(temp.getProperties()); - - CPPUNIT_ASSERT_EQUAL(contentType, properties->getContentType()); - CPPUNIT_ASSERT_EQUAL(std::string("BCDE"), properties->getHeaders().getString("A")); - CPPUNIT_ASSERT_EQUAL(deliveryMode, properties->getDeliveryMode()); - CPPUNIT_ASSERT_EQUAL(priority, properties->getPriority()); - CPPUNIT_ASSERT_EQUAL(correlationId, properties->getCorrelationId()); - CPPUNIT_ASSERT_EQUAL(replyTo, properties->getReplyTo()); - CPPUNIT_ASSERT_EQUAL(expiration, properties->getExpiration()); - CPPUNIT_ASSERT_EQUAL(messageId, properties->getMessageId()); - CPPUNIT_ASSERT_EQUAL(timestamp, properties->getTimestamp()); - CPPUNIT_ASSERT_EQUAL(type, properties->getType()); - CPPUNIT_ASSERT_EQUAL(userId, properties->getUserId()); - CPPUNIT_ASSERT_EQUAL(appId, properties->getAppId()); - CPPUNIT_ASSERT_EQUAL(clusterId, properties->getClusterId()); - } - - void testSomeSpecificProperties(){ - string contentType("application/octet-stream"); - DeliveryMode deliveryMode(PERSISTENT); - uint8_t priority(6); - string expiration("Z"); - uint64_t timestamp(0xabe4a34a); - - AMQHeaderBody body(BASIC); - BasicHeaderProperties* properties = - dynamic_cast(body.getProperties()); - properties->setContentType(contentType); - properties->setDeliveryMode(deliveryMode); - properties->setPriority(priority); - properties->setExpiration(expiration); - properties->setTimestamp(timestamp); - - Buffer buffer(100); - body.encode(buffer); - buffer.flip(); - AMQHeaderBody temp; - temp.decode(buffer, body.size()); - properties = dynamic_cast(temp.getProperties()); - - CPPUNIT_ASSERT_EQUAL(contentType, properties->getContentType()); - CPPUNIT_ASSERT_EQUAL((int) deliveryMode, (int) properties->getDeliveryMode()); - CPPUNIT_ASSERT_EQUAL((int) priority, (int) properties->getPriority()); - CPPUNIT_ASSERT_EQUAL(expiration, properties->getExpiration()); - CPPUNIT_ASSERT_EQUAL(timestamp, properties->getTimestamp()); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(HeaderTest); - diff --git a/qpid/cpp/tests/HeadersExchangeTest.cpp b/qpid/cpp/tests/HeadersExchangeTest.cpp deleted file mode 100644 index 6cd51c55a9..0000000000 --- a/qpid/cpp/tests/HeadersExchangeTest.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 -#include -#include -#include - -using namespace qpid::broker; -using namespace qpid::framing; - -class HeadersExchangeTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(HeadersExchangeTest); - CPPUNIT_TEST(testMatchAll); - CPPUNIT_TEST(testMatchAny); - CPPUNIT_TEST(testMatchEmptyValue); - CPPUNIT_TEST(testMatchEmptyArgs); - CPPUNIT_TEST(testMatchNoXMatch); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testMatchAll() - { - FieldTable b, m; - b.setString("x-match", "all"); - b.setString("foo", "FOO"); - b.setInt("n", 42); - m.setString("foo", "FOO"); - m.setInt("n", 42); - CPPUNIT_ASSERT(HeadersExchange::match(b, m)); - - // Ignore extras. - m.setString("extra", "x"); - CPPUNIT_ASSERT(HeadersExchange::match(b, m)); - - // Fail mismatch, wrong value. - m.setString("foo", "NotFoo"); - CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); - - // Fail mismatch, missing value - m.erase("foo"); - CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); - } - - void testMatchAny() - { - FieldTable b, m; - b.setString("x-match", "any"); - b.setString("foo", "FOO"); - b.setInt("n", 42); - m.setString("foo", "FOO"); - CPPUNIT_ASSERT(HeadersExchange::match(b, m)); - m.erase("foo"); - CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); - m.setInt("n", 42); - CPPUNIT_ASSERT(HeadersExchange::match(b, m)); - } - - void testMatchEmptyValue() - { - FieldTable b, m; - b.setString("x-match", "all"); - b.getMap()["foo"] = FieldTable::ValuePtr(new EmptyValue()); - b.getMap()["n"] = FieldTable::ValuePtr(new EmptyValue()); - CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); - m.setString("foo", "blah"); - m.setInt("n", 123); - } - - void testMatchEmptyArgs() - { - FieldTable b, m; - m.setString("foo", "FOO"); - - b.setString("x-match", "all"); - CPPUNIT_ASSERT(HeadersExchange::match(b, m)); - b.setString("x-match", "any"); - CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); - } - - - void testMatchNoXMatch() - { - FieldTable b, m; - b.setString("foo", "FOO"); - m.setString("foo", "FOO"); - CPPUNIT_ASSERT(!HeadersExchange::match(b, m)); - } - - -}; - -// make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(HeadersExchangeTest); diff --git a/qpid/cpp/tests/InMemoryContentTest.cpp b/qpid/cpp/tests/InMemoryContentTest.cpp deleted file mode 100644 index 4597ee5e5d..0000000000 --- a/qpid/cpp/tests/InMemoryContentTest.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 -#include -#include -#include "AMQFrame.h" -#include "MockChannel.h" - -using std::list; -using std::string; -using boost::dynamic_pointer_cast; -using namespace qpid::broker; -using namespace qpid::framing; - - -class InMemoryContentTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(InMemoryContentTest); - CPPUNIT_TEST(testRefragmentation); - CPPUNIT_TEST_SUITE_END(); - -public: - void testRefragmentation() - { - {//no remainder - string out[] = {"abcde", "fghij", "klmno", "pqrst"}; - string in[] = {out[0] + out[1], out[2] + out[3]}; - refragment(2, in, 4, out); - } - {//remainder for last frame - string out[] = {"abcde", "fghij", "klmno", "pqrst", "uvw"}; - string in[] = {out[0] + out[1], out[2] + out[3] + out[4]}; - refragment(2, in, 5, out); - } - } - - - void refragment(size_t inCount, string* in, size_t outCount, string* out, uint32_t framesize = 5) - { - InMemoryContent content; - MockChannel channel(3); - - addframes(content, inCount, in); - content.send(channel, framesize); - CPPUNIT_ASSERT_EQUAL(outCount, channel.out.frames.size()); - - for (unsigned int i = 0; i < outCount; i++) { - AMQContentBody::shared_ptr chunk( - dynamic_pointer_cast( - channel.out.frames[i].getBody())); - CPPUNIT_ASSERT(chunk); - CPPUNIT_ASSERT_EQUAL(out[i], chunk->getData()); - CPPUNIT_ASSERT_EQUAL( - ChannelId(3), channel.out.frames[i].getChannel()); - } - } - - void addframes(InMemoryContent& content, size_t frameCount, string* frameData) - { - for (unsigned int i = 0; i < frameCount; i++) { - AMQContentBody::shared_ptr frame(new AMQContentBody(frameData[i])); - content.add(frame); - } - } - - -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(InMemoryContentTest); - diff --git a/qpid/cpp/tests/InProcessBroker.h b/qpid/cpp/tests/InProcessBroker.h deleted file mode 100644 index 2882ab28e8..0000000000 --- a/qpid/cpp/tests/InProcessBroker.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef _tests_InProcessBroker_h -#define _tests_InProcessBroker_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 "AMQP_HighestVersion.h" -#include "framing/AMQFrame.h" -#include "broker/Broker.h" -#include "broker/Connection.h" -#include "client/Connector.h" -#include "client/Connection.h" - -#include -#include -#include - - -namespace qpid { -namespace broker { - -/** - * A broker that implements client::Connector allowing direct - * in-process connection of client to broker. Used to write round-trip - * tests without requiring an external broker process. - * - * Also allows you to "snoop" on frames exchanged between client & broker. - * - * see FramingTest::testRequestResponseRoundtrip() for example of use. - */ -class InProcessBroker : public client::Connector { - public: - enum Sender {CLIENT,BROKER}; - - /** A frame tagged with the sender */ - struct TaggedFrame { - TaggedFrame(Sender e, framing::AMQFrame* f) : frame(f), sender(e) {} - bool fromBroker() const { return sender == BROKER; } - bool fromClient() const { return sender == CLIENT; } - - template - MethodType* asMethod() { - return dynamic_cast(frame->getBody().get()); - } - shared_ptr frame; - Sender sender; - }; - - typedef std::vector Conversation; - - InProcessBroker(framing::ProtocolVersion ver= - framing::highestProtocolVersion - ) : - Connector(ver), - protocolInit(ver), - broker(broker::Broker::create()), - brokerOut(BROKER, conversation), - brokerConnection(&brokerOut, *broker), - clientOut(CLIENT, conversation, &brokerConnection) - {} - - ~InProcessBroker() { broker->shutdown(); } - - void connect(const std::string& /*host*/, int /*port*/) {} - void init() { brokerConnection.initiated(protocolInit); } - void close() {} - - /** Client's input handler. */ - void setInputHandler(framing::InputHandler* handler) { - brokerOut.in = handler; - } - - /** Called by client to send a frame */ - void send(framing::AMQFrame* frame) { - clientOut.send(frame); - } - - /** Entire client-broker conversation is recorded here */ - Conversation conversation; - - private: - /** OutputHandler that forwards data to an InputHandler */ - struct OutputToInputHandler : public sys::ConnectionOutputHandler { - OutputToInputHandler( - Sender sender_, Conversation& conversation_, - framing::InputHandler* ih=0 - ) : sender(sender_), conversation(conversation_), in(ih) {} - - void send(framing::AMQFrame* frame) { - conversation.push_back(TaggedFrame(sender, frame)); - in->received(frame); - } - - void close() {} - - Sender sender; - Conversation& conversation; - framing::InputHandler* in; - }; - - framing::ProtocolInitiation protocolInit; - Broker::shared_ptr broker; - OutputToInputHandler brokerOut; - broker::Connection brokerConnection; - OutputToInputHandler clientOut; -}; - -std::ostream& operator<<( - std::ostream& out, const InProcessBroker::TaggedFrame& tf) -{ - return out << (tf.fromBroker()? "BROKER: ":"CLIENT: ") << *tf.frame; -} - -std::ostream& operator<<( - std::ostream& out, const InProcessBroker::Conversation& conv) -{ - copy(conv.begin(), conv.end(), - std::ostream_iterator(out, "\n")); - return out; -} - -} // namespace broker - - -namespace client { -/** An in-process client+broker all in one. */ -class InProcessBrokerClient : public client::Connection { - public: - broker::InProcessBroker broker; - broker::InProcessBroker::Conversation& conversation; - - /** Constructor creates broker and opens client connection. */ - InProcessBrokerClient( - u_int32_t max_frame_size=65536, - framing::ProtocolVersion version= framing::highestProtocolVersion - ) : client::Connection(false, max_frame_size, version), - broker(version), - conversation(broker.conversation) - { - setConnector(broker); - open(""); - } -}; - - -}} // namespace qpid::client - - -#endif // _tests_InProcessBroker_h diff --git a/qpid/cpp/tests/LazyLoadedContentTest.cpp b/qpid/cpp/tests/LazyLoadedContentTest.cpp deleted file mode 100644 index 4cd8e9b307..0000000000 --- a/qpid/cpp/tests/LazyLoadedContentTest.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 -#include -#include -#include -#include -#include -#include -#include "AMQFrame.h" -#include "MockChannel.h" -using std::list; -using std::string; -using boost::dynamic_pointer_cast; -using namespace qpid::broker; -using namespace qpid::framing; - - - -class LazyLoadedContentTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(LazyLoadedContentTest); - CPPUNIT_TEST(testFragmented); - CPPUNIT_TEST(testWhole); - CPPUNIT_TEST(testHalved); - CPPUNIT_TEST_SUITE_END(); - - class TestMessageStore : public NullMessageStore - { - const string content; - - public: - TestMessageStore(const string& _content) : content(_content) {} - - void loadContent(PersistableMessage&, string& data, uint64_t offset, uint32_t length) - { - if (offset + length <= content.size()) { - data = content.substr(offset, length); - } else{ - std::stringstream error; - error << "Invalid segment: offset=" << offset << ", length=" << length << ", content_length=" << content.size(); - throw qpid::Exception(error.str()); - } - } - }; - - -public: - void testFragmented() - { - string data = "abcdefghijklmnopqrstuvwxyz"; - uint32_t framesize = 5; - string out[] = {"abcde", "fghij", "klmno", "pqrst", "uvwxy", "z"}; - load(data, 6, out, framesize); - } - - void testWhole() - { - string data = "abcdefghijklmnopqrstuvwxyz"; - uint32_t framesize = 50; - string out[] = {data}; - load(data, 1, out, framesize); - } - - void testHalved() - { - string data = "abcdefghijklmnopqrstuvwxyz"; - uint32_t framesize = 13; - string out[] = {"abcdefghijklm", "nopqrstuvwxyz"}; - load(data, 2, out, framesize); - } - - void load(string& in, size_t outCount, string* out, uint32_t framesize) - { - TestMessageStore store(in); - LazyLoadedContent content(&store, 0, in.size()); - MockChannel channel(3); - content.send(channel, framesize); - CPPUNIT_ASSERT_EQUAL(outCount, channel.out.frames.size()); - - for (unsigned int i = 0; i < outCount; i++) { - AMQContentBody::shared_ptr chunk(dynamic_pointer_cast(channel.out.frames[i].getBody())); - CPPUNIT_ASSERT(chunk); - CPPUNIT_ASSERT_EQUAL(out[i], chunk->getData()); - CPPUNIT_ASSERT_EQUAL( - ChannelId(3), channel.out.frames[i].getChannel()); - } - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(LazyLoadedContentTest); - diff --git a/qpid/cpp/tests/Makefile.am b/qpid/cpp/tests/Makefile.am deleted file mode 100644 index 6ae3598a98..0000000000 --- a/qpid/cpp/tests/Makefile.am +++ /dev/null @@ -1,123 +0,0 @@ -AM_CXXFLAGS = $(WARNING_CFLAGS) $(CPPUNIT_CXXFLAGS) -INCLUDES = \ - -I$(top_srcdir)/gen \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/lib/client \ - -I$(top_srcdir)/lib/broker \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/common/sys \ - -I$(top_srcdir)/lib/common/framing \ - $(APR_CXXFLAGS) - -# Unit tests -broker_tests = \ - AccumulatedAckTest \ - BrokerChannelTest \ - ConfigurationTest \ - ExchangeTest \ - HeadersExchangeTest \ - InMemoryContentTest \ - LazyLoadedContentTest \ - MessageBuilderTest \ - MessageTest \ - ReferenceTest \ - QueueRegistryTest \ - QueueTest \ - QueuePolicyTest \ - TopicExchangeTest \ - TxAckTest \ - TxBufferTest \ - TxPublishTest \ - ValueTest \ - MessageHandlerTest - -client_tests = \ - ClientChannelTest - -framing_tests = \ - FieldTableTest \ - FramingTest \ - HeaderTest - -misc_tests = \ - ProducerConsumerTest - -posix_tests = \ - EventChannelTest \ - EventChannelThreadsTest - -unit_tests = \ - $(broker_tests) \ - $(client_tests) \ - $(framing_tests) \ - $(misc_tests) - -# Executable client tests - -client_exe_tests = \ - client_test \ - echo_service \ - topic_listener \ - topic_publisher - -noinst_PROGRAMS = $(client_exe_tests) - -TESTS_ENVIRONMENT = \ - VALGRIND=$(VALGRIND) \ - abs_builddir='$(abs_builddir)' \ - PATH="$(abs_builddir)/../src$(PATH_SEPARATOR)$$PATH" \ - abs_srcdir='$(abs_srcdir)' - -CLIENT_TESTS = client_test quick_topictest -TESTS = run-unit-tests start_broker $(CLIENT_TESTS) python_tests kill_broker - -EXTRA_DIST = \ - $(TESTS) \ - .vg-supp \ - InProcessBroker.h \ - MockChannel.h \ - MockConnectionInputHandler.h \ - qpid_test_plugin.h \ - setup \ - topicall \ - topictest \ - APRBaseTest.cpp - -CLEANFILES=qpidd.log -DISTCLEANFILES=gen.mk - -include gen.mk - -check_LTLIBRARIES += libdlclose_noop.la -libdlclose_noop_la_LDFLAGS = -module -rpath /home/aconway/svn/qpid/cpp/tests -libdlclose_noop_la_SOURCES = dlclose_noop.c - - -abs_builddir = @abs_builddir@ -extra_libs = $(CPPUNIT_LIBS) -lib_client = $(abs_builddir)/../lib/client/libqpidclient.la -lib_common = $(abs_builddir)/../lib/common/libqpidcommon.la -lib_broker = $(abs_builddir)/../lib/broker/libqpidbroker.la - -gen.mk: Makefile.am - ( \ - for i in $(client_exe_tests); do \ - echo $${i}_SOURCES = $$i.cpp; \ - echo $${i}_LDADD = '$$(lib_client) $$(lib_common) $$(extra_libs)'; \ - done; \ - libs=; \ - for i in $(unit_tests); do \ - libs="$$libs $${i}.la"; \ - echo $${i}_la_SOURCES = $$i.cpp; \ - echo $${i}_la_LIBADD = '$$(lib_common) $$(lib_client)'; \ - echo $${i}_la_LIBADD += '$$(lib_broker) $$(extra_libs)'; \ - echo $${i}_la_LDFLAGS = "-module -rpath `pwd`"; \ - done; \ - echo "check_LTLIBRARIES =$$libs"; \ - ) \ - > $@-t - mv $@-t $@ - -check: $(check_LTLIBRARIES) $(lib_common) $(lib_client) $(lib_broker) - -# Rule to run unit tests from an individual test module. diff --git a/qpid/cpp/tests/MessageBuilderTest.cpp b/qpid/cpp/tests/MessageBuilderTest.cpp deleted file mode 100644 index 68e5abf60e..0000000000 --- a/qpid/cpp/tests/MessageBuilderTest.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 "MockChannel.h" - -using namespace boost; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -class MessageBuilderTest : public CppUnit::TestCase -{ - struct MockHandler : CompletionHandler { - Message::shared_ptr msg; - - virtual void complete(Message::shared_ptr _msg){ - msg = _msg; - } - }; - - class TestMessageStore : public NullMessageStore - { - Buffer* header; - Buffer* content; - const uint32_t contentBufferSize; - - public: - - void stage(PersistableMessage& msg) - { - if (msg.getPersistenceId() == 0) { - header = new Buffer(msg.encodedSize()); - msg.encode(*header); - content = new Buffer(contentBufferSize); - msg.setPersistenceId(1); - } else { - throw qpid::Exception("Message already staged!"); - } - } - - void appendContent(PersistableMessage& msg, const string& data) - { - if (msg.getPersistenceId() == 1) { - content->putRawData(data); - } else { - throw qpid::Exception("Invalid message id!"); - } - } - - using NullMessageStore::destroy; - - void destroy(PersistableMessage& msg) - { - CPPUNIT_ASSERT(msg.getPersistenceId()); - } - - BasicMessage::shared_ptr getRestoredMessage() - { - BasicMessage::shared_ptr msg(new BasicMessage()); - if (header) { - header->flip(); - msg->decodeHeader(*header); - delete header; - header = 0; - if (content) { - content->flip(); - msg->decodeContent(*content); - delete content; - content = 0; - } - } - return msg; - } - - //dont care about any of the other methods: - TestMessageStore(uint32_t _contentBufferSize) : NullMessageStore(), header(0), content(0), - contentBufferSize(_contentBufferSize) {} - ~TestMessageStore(){} - }; - - CPPUNIT_TEST_SUITE(MessageBuilderTest); - CPPUNIT_TEST(testHeaderOnly); - CPPUNIT_TEST(test1ContentFrame); - CPPUNIT_TEST(test2ContentFrames); - CPPUNIT_TEST(testStaging); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testHeaderOnly(){ - MockHandler handler; - MessageBuilder builder(&handler); - - Message::shared_ptr message( - new BasicMessage( - 0, "test", "my_routing_key", false, false, - MockChannel::basicGetBody())); - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - header->setContentSize(0); - - builder.initialise(message); - CPPUNIT_ASSERT(!handler.msg); - builder.setHeader(header); - CPPUNIT_ASSERT(handler.msg); - CPPUNIT_ASSERT_EQUAL(message, handler.msg); - } - - void test1ContentFrame(){ - MockHandler handler; - MessageBuilder builder(&handler); - - string data1("abcdefg"); - - Message::shared_ptr message( - new BasicMessage(0, "test", "my_routing_key", false, false, - MockChannel::basicGetBody())); - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - header->setContentSize(7); - AMQContentBody::shared_ptr part1(new AMQContentBody(data1)); - - builder.initialise(message); - CPPUNIT_ASSERT(!handler.msg); - builder.setHeader(header); - CPPUNIT_ASSERT(!handler.msg); - builder.addContent(part1); - CPPUNIT_ASSERT(handler.msg); - CPPUNIT_ASSERT_EQUAL(message, handler.msg); - } - - void test2ContentFrames(){ - MockHandler handler; - MessageBuilder builder(&handler); - - string data1("abcdefg"); - string data2("hijklmn"); - - Message::shared_ptr message( - new BasicMessage(0, "test", "my_routing_key", false, false, - MockChannel::basicGetBody())); - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - header->setContentSize(14); - AMQContentBody::shared_ptr part1(new AMQContentBody(data1)); - AMQContentBody::shared_ptr part2(new AMQContentBody(data2)); - - builder.initialise(message); - CPPUNIT_ASSERT(!handler.msg); - builder.setHeader(header); - CPPUNIT_ASSERT(!handler.msg); - builder.addContent(part1); - CPPUNIT_ASSERT(!handler.msg); - builder.addContent(part2); - CPPUNIT_ASSERT(handler.msg); - CPPUNIT_ASSERT_EQUAL(message, handler.msg); - } - - void testStaging(){ - //store must be the last thing to be destroyed or destructor - //of Message fails (it uses the store to call destroy if lazy - //loaded content is in use) - TestMessageStore store(14); - { - MockHandler handler; - MessageBuilder builder(&handler, &store, 5); - - string data1("abcdefg"); - string data2("hijklmn"); - - Message::shared_ptr message( - new BasicMessage(0, "test", "my_routing_key", false, false, - MockChannel::basicGetBody())); - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - header->setContentSize(14); - BasicHeaderProperties* properties = dynamic_cast(header->getProperties()); - properties->setMessageId("MyMessage"); - properties->getHeaders().setString("abc", "xyz"); - - AMQContentBody::shared_ptr part1(new AMQContentBody(data1)); - AMQContentBody::shared_ptr part2(new AMQContentBody(data2)); - - builder.initialise(message); - builder.setHeader(header); - builder.addContent(part1); - builder.addContent(part2); - CPPUNIT_ASSERT(handler.msg); - CPPUNIT_ASSERT_EQUAL(message, handler.msg); - - BasicMessage::shared_ptr restored = store.getRestoredMessage(); - CPPUNIT_ASSERT_EQUAL(message->getExchange(), restored->getExchange()); - CPPUNIT_ASSERT_EQUAL(message->getRoutingKey(), restored->getRoutingKey()); - CPPUNIT_ASSERT_EQUAL(message->getHeaderProperties()->getMessageId(), restored->getHeaderProperties()->getMessageId()); - CPPUNIT_ASSERT_EQUAL(message->getHeaderProperties()->getHeaders().getString("abc"), - restored->getHeaderProperties()->getHeaders().getString("abc")); - CPPUNIT_ASSERT_EQUAL((uint64_t) 14, restored->contentSize()); - } - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(MessageBuilderTest); diff --git a/qpid/cpp/tests/MessageHandlerTest.cpp b/qpid/cpp/tests/MessageHandlerTest.cpp deleted file mode 100644 index 55971355f6..0000000000 --- a/qpid/cpp/tests/MessageHandlerTest.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 -//#include -#include -#include - -#include - -using namespace qpid::framing; -using namespace qpid::broker; - -class MessageHandlerTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(MessageHandlerTest); - CPPUNIT_TEST(testOpenMethod); - CPPUNIT_TEST_SUITE_END(); -private: - -public: - - MessageHandlerTest() - { - } - - void testOpenMethod() - { - //AMQFrame frame(highestProtocolVersion, 0, method); - //TestBodyHandler handler(method); - //handler.handleBody(frame.getBody()); - } - -}; - - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(MessageHandlerTest); - diff --git a/qpid/cpp/tests/MessageTest.cpp b/qpid/cpp/tests/MessageTest.cpp deleted file mode 100644 index 6d766c2260..0000000000 --- a/qpid/cpp/tests/MessageTest.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 -#include -#include -#include -#include "AMQFrame.h" -#include "MockChannel.h" - -using namespace boost; -using namespace qpid::broker; -using namespace qpid::framing; - -class MessageTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(MessageTest); - CPPUNIT_TEST(testEncodeDecode); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testEncodeDecode() - { - string exchange = "MyExchange"; - string routingKey = "MyRoutingKey"; - string messageId = "MyMessage"; - string data1("abcdefg"); - string data2("hijklmn"); - - BasicMessage::shared_ptr msg( - new BasicMessage(0, exchange, routingKey, false, false, - MockChannel::basicGetBody())); - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - header->setContentSize(14); - AMQContentBody::shared_ptr part1(new AMQContentBody(data1)); - AMQContentBody::shared_ptr part2(new AMQContentBody(data2)); - msg->setHeader(header); - msg->addContent(part1); - msg->addContent(part2); - - msg->getHeaderProperties()->setMessageId(messageId); - msg->getHeaderProperties()->setDeliveryMode(PERSISTENT); - msg->getHeaderProperties()->getHeaders().setString("abc", "xyz"); - - Buffer buffer(msg->encodedSize()); - msg->encode(buffer); - buffer.flip(); - - msg.reset(new BasicMessage()); - msg->decode(buffer); - CPPUNIT_ASSERT_EQUAL(exchange, msg->getExchange()); - CPPUNIT_ASSERT_EQUAL(routingKey, msg->getRoutingKey()); - CPPUNIT_ASSERT_EQUAL(messageId, msg->getHeaderProperties()->getMessageId()); - CPPUNIT_ASSERT_EQUAL(PERSISTENT, msg->getHeaderProperties()->getDeliveryMode()); - CPPUNIT_ASSERT_EQUAL(string("xyz"), msg->getHeaderProperties()->getHeaders().getString("abc")); - CPPUNIT_ASSERT_EQUAL((uint64_t) 14, msg->contentSize()); - - MockChannel channel(1); - msg->deliver(channel, "ignore", 0, 100); - CPPUNIT_ASSERT_EQUAL((size_t) 3, channel.out.frames.size()); - AMQContentBody::shared_ptr contentBody(dynamic_pointer_cast(channel.out.frames[2].getBody())); - CPPUNIT_ASSERT(contentBody); - CPPUNIT_ASSERT_EQUAL(data1 + data2, contentBody->getData()); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(MessageTest); - diff --git a/qpid/cpp/tests/MockChannel.h b/qpid/cpp/tests/MockChannel.h deleted file mode 100644 index 79aa1d35af..0000000000 --- a/qpid/cpp/tests/MockChannel.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _tests_MockChannel_h -#define _tests_MockChannel_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 "framing/MethodContext.h" -#include "framing/ChannelAdapter.h" -#include "framing/OutputHandler.h" -#include "framing/AMQFrame.h" -#include "BasicGetBody.h" -#include -#include - -/** Mock output handler to collect frames */ -struct MockOutputHandler : public qpid::framing::OutputHandler { - boost::ptr_vector frames; - void send(qpid::framing::AMQFrame* frame){ frames.push_back(frame); } -}; - -/** - * Combination mock OutputHandler and ChannelAdapter for tests. - */ -struct MockChannel : public qpid::framing::ChannelAdapter -{ - typedef qpid::framing::BasicGetBody Body; - static Body::shared_ptr basicGetBody() { - return Body::shared_ptr( - new Body(qpid::framing::ProtocolVersion())); - } - - MockOutputHandler out; - - MockChannel(qpid::framing::ChannelId id) { - init(id, out, qpid::framing::ProtocolVersion()); - } - - bool isOpen() const { return true; } - - void handleHeader( - boost::shared_ptr b) { send(b); } - void handleContent( - boost::shared_ptr b) { send(b); } - void handleHeartbeat( - boost::shared_ptr b) { send(b); } - void handleMethodInContext( - boost::shared_ptr method, - const qpid::framing::MethodContext& context) - { - context.channel->send(method); - }; - -}; - -#endif /*!_tests_MockChannel_h*/ diff --git a/qpid/cpp/tests/MockConnectionInputHandler.h b/qpid/cpp/tests/MockConnectionInputHandler.h deleted file mode 100644 index 55dbceaf44..0000000000 --- a/qpid/cpp/tests/MockConnectionInputHandler.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef _tests_MockConnectionInputHandler_h -#define _tests_MockConnectionInputHandler_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 "sys/ConnectionInputHandler.h" -#include "sys/ConnectionInputHandlerFactory.h" -#include "sys/Monitor.h" -#include "framing/ProtocolInitiation.h" - -struct MockConnectionInputHandler : public qpid::sys::ConnectionInputHandler { - - MockConnectionInputHandler() : state(START) {} - - ~MockConnectionInputHandler() {} - - void initiated(const qpid::framing::ProtocolInitiation& pi) { - qpid::sys::Monitor::ScopedLock l(monitor); - init = pi; - setState(GOT_INIT); - } - - void received(qpid::framing::AMQFrame* framep) { - qpid::sys::Monitor::ScopedLock l(monitor); - frame = *framep; - setState(GOT_FRAME); - } - - qpid::framing::ProtocolInitiation waitForProtocolInit() { - waitFor(GOT_INIT); - return init; - } - - qpid::framing::AMQFrame waitForFrame() { - waitFor(GOT_FRAME); - return frame; - } - - void waitForClosed() { - waitFor(CLOSED); - } - - void closed() { - qpid::sys::Monitor::ScopedLock l(monitor); - setState(CLOSED); - } - - void idleOut() {} - void idleIn() {} - - private: - typedef enum { START, GOT_INIT, GOT_FRAME, CLOSED } State; - - void setState(State s) { - state = s; - monitor.notify(); - } - - void waitFor(State s) { - qpid::sys::Monitor::ScopedLock l(monitor); - qpid::sys::Time deadline = qpid::sys::now() + 10*qpid::sys::TIME_SEC; - while (state != s) - CPPUNIT_ASSERT(monitor.wait(deadline)); - } - - qpid::sys::Monitor monitor; - State state; - qpid::framing::ProtocolInitiation init; - qpid::framing::AMQFrame frame; -}; - - -struct MockConnectionInputHandlerFactory : public qpid::sys::ConnectionInputHandlerFactory { - MockConnectionInputHandlerFactory() : handler(0) {} - - qpid::sys::ConnectionInputHandler* create(qpid::sys::ConnectionOutputHandler*) { - qpid::sys::Monitor::ScopedLock lock(monitor); - handler = new MockConnectionInputHandler(); - monitor.notifyAll(); - return handler; - } - - void waitForHandler() { - qpid::sys::Monitor::ScopedLock lock(monitor); - qpid::sys::Time deadline = - qpid::sys::now() + 500 * qpid::sys::TIME_SEC; - while (handler == 0) - CPPUNIT_ASSERT(monitor.wait(deadline)); - } - - MockConnectionInputHandler* handler; - qpid::sys::Monitor monitor; -}; - - - -#endif /*!_tests_MockConnectionInputHandler_h*/ diff --git a/qpid/cpp/tests/ProducerConsumerTest.cpp b/qpid/cpp/tests/ProducerConsumerTest.cpp deleted file mode 100644 index ee94a56c55..0000000000 --- a/qpid/cpp/tests/ProducerConsumerTest.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 -#include - -#include - -#include -#include "InProcessBroker.h" -#include "sys/ProducerConsumer.h" -#include "sys/Thread.h" -#include "AMQP_HighestVersion.h" -#include "sys/AtomicCount.h" - -using namespace qpid; -using namespace sys; -using namespace framing; -using namespace boost; -using namespace std; - -/** A counter that notifies a monitor when changed */ -class WatchedCounter : public Monitor { - public: - WatchedCounter(int i=0) : count(i) {} - WatchedCounter(const WatchedCounter& c) : Monitor(), count(int(c)) {} - - WatchedCounter& operator=(const WatchedCounter& x) { - return *this = int(x); - } - - WatchedCounter& operator=(int i) { - Lock l(*this); - count = i; - return *this; - } - - int operator++() { - Lock l(*this); - notifyAll(); - return ++count; - } - - int operator++(int) { - Lock l(*this); - notifyAll(); - return count++; - } - - bool operator==(int i) const { - Lock l(const_cast(*this)); - return i == count; - } - - operator int() const { - Lock l(const_cast(*this)); - return count; - } - - bool waitFor(int i, Time timeout=TIME_SEC) { - Lock l(*this); - Time deadline = timeout+now(); - while (count != i) { - if (!wait(deadline)) - return false; - } - assert(count == i); - return true; - } - - private: - typedef Mutex::ScopedLock Lock; - int count; -}; - -class ProducerConsumerTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(ProducerConsumerTest); - CPPUNIT_TEST(testProduceConsume); - CPPUNIT_TEST(testTimeout); - CPPUNIT_TEST(testShutdown); - CPPUNIT_TEST(testCancel); - CPPUNIT_TEST_SUITE_END(); - - public: - client::InProcessBrokerClient client; - ProducerConsumer pc; - - WatchedCounter shutdown; - WatchedCounter timeout; - WatchedCounter consumed; - WatchedCounter produced; - - struct ConsumeRunnable : public Runnable { - ProducerConsumerTest& test; - ConsumeRunnable(ProducerConsumerTest& test_) : test(test_) {} - void run() { test.consume(); } - }; - - struct ConsumeTimeoutRunnable : public Runnable { - ProducerConsumerTest& test; - Time timeout; - ConsumeTimeoutRunnable(ProducerConsumerTest& test_, const Time& t) - : test(test_), timeout(t) {} - void run() { test.consumeTimeout(timeout); } - }; - - - void consumeInternal(ProducerConsumer::ConsumerLock& consumer) { - if (pc.isShutdown()) { - ++shutdown; - return; - } - if (consumer.isTimedOut()) { - ++timeout; - return; - } - CPPUNIT_ASSERT(consumer.isOk()); - CPPUNIT_ASSERT(pc.available() > 0); - consumer.confirm(); - consumed++; - } - - void consume() { - ProducerConsumer::ConsumerLock consumer(pc); - consumeInternal(consumer); - }; - - void consumeTimeout(const Time& timeout) { - ProducerConsumer::ConsumerLock consumer(pc, timeout); - consumeInternal(consumer); - }; - - void produce() { - ProducerConsumer::ProducerLock producer(pc); - CPPUNIT_ASSERT(producer.isOk()); - producer.confirm(); - produced++; - } - - void join(vector& threads) { - for_each(threads.begin(), threads.end(), bind(&Thread::join,_1)); - } - - vector startThreads(size_t n, Runnable& runnable) { - vector threads(n); - while (n > 0) - threads[--n] = Thread(runnable); - return threads; - } - -public: - ProducerConsumerTest() : client() {} - - void testProduceConsume() { - ConsumeRunnable runMe(*this); - produce(); - produce(); - CPPUNIT_ASSERT(produced.waitFor(2)); - vector threads = startThreads(1, runMe); - CPPUNIT_ASSERT(consumed.waitFor(1)); - join(threads); - - threads = startThreads(1, runMe); - CPPUNIT_ASSERT(consumed.waitFor(2)); - join(threads); - - threads = startThreads(3, runMe); - produce(); - produce(); - CPPUNIT_ASSERT(consumed.waitFor(4)); - produce(); - CPPUNIT_ASSERT(consumed.waitFor(5)); - join(threads); - CPPUNIT_ASSERT_EQUAL(0, int(shutdown)); - } - - void testTimeout() { - try { - // 0 timeout no items available throws exception - ProducerConsumer::ConsumerLock consumer(pc, 0); - CPPUNIT_FAIL("Expected exception"); - } catch(...){} - - produce(); - CPPUNIT_ASSERT(produced.waitFor(1)); - CPPUNIT_ASSERT_EQUAL(1, int(pc.available())); - { - // 0 timeout succeeds if there's an item available. - ProducerConsumer::ConsumerLock consume(pc, 0); - CPPUNIT_ASSERT(consume.isOk()); - consume.confirm(); - } - CPPUNIT_ASSERT_EQUAL(0, int(pc.available())); - - // Produce an item within the timeout. - ConsumeTimeoutRunnable runMe(*this, 2*TIME_SEC); - vector threads = startThreads(1, runMe); - produce(); - CPPUNIT_ASSERT(consumed.waitFor(1)); - join(threads); - } - - - void testShutdown() { - ConsumeRunnable runMe(*this); - vector threads = startThreads(2, runMe); - while (pc.consumers() != 2) - Thread::yield(); - pc.shutdown(); - CPPUNIT_ASSERT(shutdown.waitFor(2)); - join(threads); - - threads = startThreads(1, runMe); // Should shutdown immediately. - CPPUNIT_ASSERT(shutdown.waitFor(3)); - join(threads); - - // Produce/consume while shutdown should return isShutdown and - // throw on confirm. - try { - ProducerConsumer::ProducerLock p(pc); - CPPUNIT_ASSERT(pc.isShutdown()); - CPPUNIT_FAIL("Expected exception"); - } - catch (...) {} // Expected - try { - ProducerConsumer::ConsumerLock c(pc); - CPPUNIT_ASSERT(pc.isShutdown()); - CPPUNIT_FAIL("Expected exception"); - } - catch (...) {} // Expected - } - - void testCancel() { - CPPUNIT_ASSERT_EQUAL(size_t(0), pc.available()); - { - ProducerConsumer::ProducerLock p(pc); - CPPUNIT_ASSERT(p.isOk()); - p.cancel(); - } - // Nothing was produced. - CPPUNIT_ASSERT_EQUAL(size_t(0), pc.available()); - { - ProducerConsumer::ConsumerLock c(pc, 0); - CPPUNIT_ASSERT(c.isTimedOut()); - } - // Now produce but cancel the consume - { - ProducerConsumer::ProducerLock p(pc); - CPPUNIT_ASSERT(p.isOk()); - p.confirm(); - } - CPPUNIT_ASSERT_EQUAL(size_t(1), pc.available()); - { - ProducerConsumer::ConsumerLock c(pc); - CPPUNIT_ASSERT(c.isOk()); - c.cancel(); - } - CPPUNIT_ASSERT_EQUAL(size_t(1), pc.available()); - } -}; - - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(ProducerConsumerTest); - diff --git a/qpid/cpp/tests/QueuePolicyTest.cpp b/qpid/cpp/tests/QueuePolicyTest.cpp deleted file mode 100644 index 20917dcd6a..0000000000 --- a/qpid/cpp/tests/QueuePolicyTest.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 -#include - -using namespace qpid::broker; -using namespace qpid::framing; - -class QueuePolicyTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(QueuePolicyTest); - CPPUNIT_TEST(testCount); - CPPUNIT_TEST(testSize); - CPPUNIT_TEST(testBoth); - CPPUNIT_TEST(testSettings); - CPPUNIT_TEST_SUITE_END(); - - public: - void testCount(){ - QueuePolicy policy(5, 0); - CPPUNIT_ASSERT(!policy.limitExceeded()); - for (int i = 0; i < 5; i++) policy.enqueued(10); - CPPUNIT_ASSERT_EQUAL((uint64_t) 0, policy.getMaxSize()); - CPPUNIT_ASSERT_EQUAL((uint32_t) 5, policy.getMaxCount()); - CPPUNIT_ASSERT(!policy.limitExceeded()); - policy.enqueued(10); - CPPUNIT_ASSERT(policy.limitExceeded()); - policy.dequeued(10); - CPPUNIT_ASSERT(!policy.limitExceeded()); - policy.enqueued(10); - CPPUNIT_ASSERT(policy.limitExceeded()); - } - - void testSize(){ - QueuePolicy policy(0, 50); - for (int i = 0; i < 5; i++) policy.enqueued(10); - CPPUNIT_ASSERT(!policy.limitExceeded()); - policy.enqueued(10); - CPPUNIT_ASSERT(policy.limitExceeded()); - policy.dequeued(10); - CPPUNIT_ASSERT(!policy.limitExceeded()); - policy.enqueued(10); - CPPUNIT_ASSERT(policy.limitExceeded()); - } - - void testBoth(){ - QueuePolicy policy(5, 50); - for (int i = 0; i < 5; i++) policy.enqueued(11); - CPPUNIT_ASSERT(policy.limitExceeded()); - policy.dequeued(20); - CPPUNIT_ASSERT(!policy.limitExceeded());//fails - policy.enqueued(5); - policy.enqueued(10); - CPPUNIT_ASSERT(policy.limitExceeded()); - } - - void testSettings(){ - //test reading and writing the policy from/to field table - FieldTable settings; - QueuePolicy a(101, 303); - a.update(settings); - QueuePolicy b(settings); - CPPUNIT_ASSERT_EQUAL(a.getMaxCount(), b.getMaxCount()); - CPPUNIT_ASSERT_EQUAL(a.getMaxSize(), b.getMaxSize()); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(QueuePolicyTest); - diff --git a/qpid/cpp/tests/QueueRegistryTest.cpp b/qpid/cpp/tests/QueueRegistryTest.cpp deleted file mode 100644 index 3926d56292..0000000000 --- a/qpid/cpp/tests/QueueRegistryTest.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 -#include -#include - -using namespace qpid::broker; - -class QueueRegistryTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(QueueRegistryTest); - CPPUNIT_TEST(testDeclare); - CPPUNIT_TEST(testDeclareTmp); - CPPUNIT_TEST(testFind); - CPPUNIT_TEST(testDestroy); - CPPUNIT_TEST_SUITE_END(); - - private: - std::string foo, bar; - QueueRegistry reg; - std::pair qc; - - public: - void setUp() { - foo = "foo"; - bar = "bar"; - } - - void testDeclare() { - qc = reg.declare(foo, false, 0, 0); - Queue::shared_ptr q = qc.first; - CPPUNIT_ASSERT(q); - CPPUNIT_ASSERT(qc.second); // New queue - CPPUNIT_ASSERT_EQUAL(foo, q->getName()); - - qc = reg.declare(foo, false, 0, 0); - CPPUNIT_ASSERT_EQUAL(q, qc.first); - CPPUNIT_ASSERT(!qc.second); - - qc = reg.declare(bar, false, 0, 0); - q = qc.first; - CPPUNIT_ASSERT(q); - CPPUNIT_ASSERT_EQUAL(true, qc.second); - CPPUNIT_ASSERT_EQUAL(bar, q->getName()); - } - - void testDeclareTmp() - { - qc = reg.declare(std::string(), false, 0, 0); - CPPUNIT_ASSERT(qc.second); - CPPUNIT_ASSERT_EQUAL(std::string("tmp_1"), qc.first->getName()); - } - - void testFind() { - CPPUNIT_ASSERT(reg.find(foo) == 0); - - reg.declare(foo, false, 0, 0); - reg.declare(bar, false, 0, 0); - Queue::shared_ptr q = reg.find(bar); - CPPUNIT_ASSERT(q); - CPPUNIT_ASSERT_EQUAL(bar, q->getName()); - } - - void testDestroy() { - qc = reg.declare(foo, false, 0, 0); - reg.destroy(foo); - // Queue is gone from the registry. - CPPUNIT_ASSERT(reg.find(foo) == 0); - // Queue is not actually destroyed till we drop our reference. - CPPUNIT_ASSERT_EQUAL(foo, qc.first->getName()); - // We shoud be the only reference. - CPPUNIT_ASSERT_EQUAL(1L, qc.first.use_count()); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(QueueRegistryTest); diff --git a/qpid/cpp/tests/QueueTest.cpp b/qpid/cpp/tests/QueueTest.cpp deleted file mode 100644 index e90c9259cf..0000000000 --- a/qpid/cpp/tests/QueueTest.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 -#include -#include -#include -#include "MockChannel.h" - -using namespace qpid::broker; -using namespace qpid::sys; - - -class TestConsumer : public virtual Consumer{ -public: - Message::shared_ptr last; - - virtual bool deliver(Message::shared_ptr& msg); -}; - - -class QueueTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(QueueTest); - CPPUNIT_TEST(testConsumers); - CPPUNIT_TEST(testRegistry); - CPPUNIT_TEST(testDequeue); - CPPUNIT_TEST_SUITE_END(); - - public: - Message::shared_ptr message(std::string exchange, std::string routingKey) { - return Message::shared_ptr( - new BasicMessage(0, exchange, routingKey, true, true, - MockChannel::basicGetBody())); - } - - void testConsumers(){ - Queue::shared_ptr queue(new Queue("my_queue", true)); - - //Test adding consumers: - TestConsumer c1; - TestConsumer c2; - queue->consume(&c1); - queue->consume(&c2); - - CPPUNIT_ASSERT_EQUAL(uint32_t(2), queue->getConsumerCount()); - - //Test basic delivery: - Message::shared_ptr msg1 = message("e", "A"); - Message::shared_ptr msg2 = message("e", "B"); - Message::shared_ptr msg3 = message("e", "C"); - - queue->deliver(msg1); - CPPUNIT_ASSERT_EQUAL(msg1.get(), c1.last.get()); - - queue->deliver(msg2); - CPPUNIT_ASSERT_EQUAL(msg2.get(), c2.last.get()); - - queue->deliver(msg3); - CPPUNIT_ASSERT_EQUAL(msg3.get(), c1.last.get()); - - //Test cancellation: - queue->cancel(&c1); - CPPUNIT_ASSERT_EQUAL(uint32_t(1), queue->getConsumerCount()); - queue->cancel(&c2); - CPPUNIT_ASSERT_EQUAL(uint32_t(0), queue->getConsumerCount()); - } - - void testRegistry(){ - //Test use of queues in registry: - QueueRegistry registry; - registry.declare("queue1", true, true); - registry.declare("queue2", true, true); - registry.declare("queue3", true, true); - - CPPUNIT_ASSERT(registry.find("queue1")); - CPPUNIT_ASSERT(registry.find("queue2")); - CPPUNIT_ASSERT(registry.find("queue3")); - - registry.destroy("queue1"); - registry.destroy("queue2"); - registry.destroy("queue3"); - - CPPUNIT_ASSERT(!registry.find("queue1")); - CPPUNIT_ASSERT(!registry.find("queue2")); - CPPUNIT_ASSERT(!registry.find("queue3")); - } - - void testDequeue(){ - Queue::shared_ptr queue(new Queue("my_queue", true)); - Message::shared_ptr msg1 = message("e", "A"); - Message::shared_ptr msg2 = message("e", "B"); - Message::shared_ptr msg3 = message("e", "C"); - Message::shared_ptr received; - - queue->deliver(msg1); - queue->deliver(msg2); - queue->deliver(msg3); - - CPPUNIT_ASSERT_EQUAL(uint32_t(3), queue->getMessageCount()); - - received = queue->dequeue(); - CPPUNIT_ASSERT_EQUAL(msg1.get(), received.get()); - CPPUNIT_ASSERT_EQUAL(uint32_t(2), queue->getMessageCount()); - - received = queue->dequeue(); - CPPUNIT_ASSERT_EQUAL(msg2.get(), received.get()); - CPPUNIT_ASSERT_EQUAL(uint32_t(1), queue->getMessageCount()); - - TestConsumer consumer; - queue->consume(&consumer); - queue->dispatch(); - CPPUNIT_ASSERT_EQUAL(msg3.get(), consumer.last.get()); - CPPUNIT_ASSERT_EQUAL(uint32_t(0), queue->getMessageCount()); - - received = queue->dequeue(); - CPPUNIT_ASSERT(!received); - CPPUNIT_ASSERT_EQUAL(uint32_t(0), queue->getMessageCount()); - - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(QueueTest); - -//TestConsumer -bool TestConsumer::deliver(Message::shared_ptr& msg){ - last = msg; - return true; -} - diff --git a/qpid/cpp/tests/ReferenceTest.cpp b/qpid/cpp/tests/ReferenceTest.cpp deleted file mode 100644 index 753f68ee75..0000000000 --- a/qpid/cpp/tests/ReferenceTest.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 "qpid_test_plugin.h" -#include "Reference.h" -#include "BrokerMessageMessage.h" -#include "MessageTransferBody.h" -#include "MessageAppendBody.h" -#include "CompletionHandler.h" - -using namespace boost; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace std; - -class ReferenceTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(ReferenceTest); - CPPUNIT_TEST(testRegistry); - CPPUNIT_TEST(testReference); - CPPUNIT_TEST_SUITE_END(); - - ProtocolVersion v; - ReferenceRegistry registry; - Reference::shared_ptr r1; - MessageTransferBody::shared_ptr t1, t2; - MessageMessage::shared_ptr m1, m2; - MessageAppendBody::shared_ptr a1, a2; - public: - - ReferenceTest() : - r1(registry.open("bar")), - t1(new MessageTransferBody(v)), - t2(new MessageTransferBody(v)), - m1(new MessageMessage(0, 1, t1, r1)), - m2(new MessageMessage(0, 2, t2, r1)), - a1(new MessageAppendBody(v)), - a2(new MessageAppendBody(v)) - {} - - void testRegistry() { - Reference::shared_ptr ref = registry.open("foo"); - CPPUNIT_ASSERT_EQUAL(string("foo"), ref->getId()); - CPPUNIT_ASSERT(ref == registry.get("foo")); - try { - registry.get("none"); - CPPUNIT_FAIL("Expected exception"); - } catch (...) {} - try { - registry.open("foo"); - CPPUNIT_FAIL("Expected exception"); - } catch(...) {} - } - - void testReference() { - r1->addMessage(m1); - r1->addMessage(m2); - CPPUNIT_ASSERT_EQUAL(size_t(2), r1->getMessages().size()); - r1->append(a1); - r1->append(a2); - CPPUNIT_ASSERT_EQUAL(size_t(2), r1->getAppends().size()); - const vector messages = r1->getMessages(); - r1->close(); - try { - registry.open("bar"); - CPPUNIT_FAIL("Expected exception"); - } catch(...) {} - - CPPUNIT_ASSERT_EQUAL(messages[0], m1); - CPPUNIT_ASSERT_EQUAL(messages[0]->getReference()->getAppends()[0], a1); - CPPUNIT_ASSERT_EQUAL(messages[0]->getReference()->getAppends()[1], a2); - - CPPUNIT_ASSERT_EQUAL(messages[1], m2); - CPPUNIT_ASSERT_EQUAL(messages[1]->getReference()->getAppends()[0], a1); - CPPUNIT_ASSERT_EQUAL(messages[1]->getReference()->getAppends()[1], a2); - } - - -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(ReferenceTest); diff --git a/qpid/cpp/tests/TopicExchangeTest.cpp b/qpid/cpp/tests/TopicExchangeTest.cpp deleted file mode 100644 index 4ba9cdd6e5..0000000000 --- a/qpid/cpp/tests/TopicExchangeTest.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 -#include - -using namespace qpid::broker; - -Tokens makeTokens(char** begin, char** end) -{ - Tokens t; - t.insert(t.end(), begin, end); - return t; -} - -// Calculate size of an array. -#define LEN(a) (sizeof(a)/sizeof(a[0])) - -// Convert array to token vector -#define TOKENS(a) makeTokens(a, a + LEN(a)) - -// Allow CPPUNIT_EQUALS to print a Tokens. -CppUnit::OStringStream& operator <<(CppUnit::OStringStream& out, const Tokens& v) -{ - out << "[ "; - for (Tokens::const_iterator i = v.begin(); - i != v.end(); ++i) - { - out << '"' << *i << '"' << (i+1 == v.end() ? "]" : ", "); - } - return out; -} - - -class TokensTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(TokensTest); - CPPUNIT_TEST(testTokens); - CPPUNIT_TEST_SUITE_END(); - - public: - void testTokens() - { - Tokens tokens("hello.world"); - char* expect[] = {"hello", "world"}; - CPPUNIT_ASSERT_EQUAL(TOKENS(expect), tokens); - - tokens = "a.b.c"; - char* expect2[] = { "a", "b", "c" }; - CPPUNIT_ASSERT_EQUAL(TOKENS(expect2), tokens); - - tokens = ""; - CPPUNIT_ASSERT(tokens.empty()); - - tokens = "x"; - char* expect3[] = { "x" }; - CPPUNIT_ASSERT_EQUAL(TOKENS(expect3), tokens); - - tokens = (".x"); - char* expect4[] = { "", "x" }; - CPPUNIT_ASSERT_EQUAL(TOKENS(expect4), tokens); - - tokens = ("x."); - char* expect5[] = { "x", "" }; - CPPUNIT_ASSERT_EQUAL(TOKENS(expect5), tokens); - - tokens = ("."); - char* expect6[] = { "", "" }; - CPPUNIT_ASSERT_EQUAL(TOKENS(expect6), tokens); - - tokens = (".."); - char* expect7[] = { "", "", "" }; - CPPUNIT_ASSERT_EQUAL(TOKENS(expect7), tokens); - } - -}; - -#define ASSERT_NORMALIZED(expect, pattern) \ - CPPUNIT_ASSERT_EQUAL(Tokens(expect), static_cast(TopicPattern(pattern))) -class TopicPatternTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(TopicPatternTest); - CPPUNIT_TEST(testNormalize); - CPPUNIT_TEST(testPlain); - CPPUNIT_TEST(testStar); - CPPUNIT_TEST(testHash); - CPPUNIT_TEST(testMixed); - CPPUNIT_TEST(testCombo); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testNormalize() - { - CPPUNIT_ASSERT(TopicPattern("").empty()); - ASSERT_NORMALIZED("a.b.c", "a.b.c"); - ASSERT_NORMALIZED("a.*.c", "a.*.c"); - ASSERT_NORMALIZED("#", "#"); - ASSERT_NORMALIZED("#", "#.#.#.#"); - ASSERT_NORMALIZED("*.*.*.#", "#.*.#.*.#.#.*"); - ASSERT_NORMALIZED("a.*.*.*.#", "a.*.#.*.#.*.#"); - ASSERT_NORMALIZED("a.*.*.*.#", "a.*.#.*.#.*"); - } - - void testPlain() { - TopicPattern p("ab.cd.e"); - CPPUNIT_ASSERT(p.match("ab.cd.e")); - CPPUNIT_ASSERT(!p.match("abx.cd.e")); - CPPUNIT_ASSERT(!p.match("ab.cd")); - CPPUNIT_ASSERT(!p.match("ab.cd..e.")); - CPPUNIT_ASSERT(!p.match("ab.cd.e.")); - CPPUNIT_ASSERT(!p.match(".ab.cd.e")); - - p = ""; - CPPUNIT_ASSERT(p.match("")); - - p = "."; - CPPUNIT_ASSERT(p.match(".")); - } - - - void testStar() - { - TopicPattern p("a.*.b"); - CPPUNIT_ASSERT(p.match("a.xx.b")); - CPPUNIT_ASSERT(!p.match("a.b")); - - p = "*.x"; - CPPUNIT_ASSERT(p.match("y.x")); - CPPUNIT_ASSERT(p.match(".x")); - CPPUNIT_ASSERT(!p.match("x")); - - p = "x.x.*"; - CPPUNIT_ASSERT(p.match("x.x.y")); - CPPUNIT_ASSERT(p.match("x.x.")); - CPPUNIT_ASSERT(!p.match("x.x")); - CPPUNIT_ASSERT(!p.match("q.x.y")); - } - - void testHash() - { - TopicPattern p("a.#.b"); - CPPUNIT_ASSERT(p.match("a.b")); - CPPUNIT_ASSERT(p.match("a.x.b")); - CPPUNIT_ASSERT(p.match("a..x.y.zz.b")); - CPPUNIT_ASSERT(!p.match("a.b.")); - CPPUNIT_ASSERT(!p.match("q.x.b")); - - p = "a.#"; - CPPUNIT_ASSERT(p.match("a")); - CPPUNIT_ASSERT(p.match("a.b")); - CPPUNIT_ASSERT(p.match("a.b.c")); - - p = "#.a"; - CPPUNIT_ASSERT(p.match("a")); - CPPUNIT_ASSERT(p.match("x.y.a")); - } - - void testMixed() - { - TopicPattern p("*.x.#.y"); - CPPUNIT_ASSERT(p.match("a.x.y")); - CPPUNIT_ASSERT(p.match("a.x.p.qq.y")); - CPPUNIT_ASSERT(!p.match("a.a.x.y")); - CPPUNIT_ASSERT(!p.match("aa.x.b.c")); - - p = "a.#.b.*"; - CPPUNIT_ASSERT(p.match("a.b.x")); - CPPUNIT_ASSERT(p.match("a.x.x.x.b.x")); - } - - void testCombo() { - TopicPattern p("*.#.#.*.*.#"); - CPPUNIT_ASSERT(p.match("x.y.z")); - CPPUNIT_ASSERT(p.match("x.y.z.a.b.c")); - CPPUNIT_ASSERT(!p.match("x.y")); - CPPUNIT_ASSERT(!p.match("x")); - } -}; - - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(TopicPatternTest); -CPPUNIT_TEST_SUITE_REGISTRATION(TokensTest); diff --git a/qpid/cpp/tests/TxAckTest.cpp b/qpid/cpp/tests/TxAckTest.cpp deleted file mode 100644 index eb4ada4ac8..0000000000 --- a/qpid/cpp/tests/TxAckTest.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 -#include -#include -#include -#include -#include -#include -#include "MockChannel.h" - -using std::list; -using std::vector; -using namespace qpid::broker; -using namespace qpid::framing; - -class TxAckTest : public CppUnit::TestCase -{ - - class TestMessageStore : public NullMessageStore - { - public: - vector dequeued; - - void dequeue(TransactionContext*, PersistableMessage& msg, const PersistableQueue& /*queue*/) - { - dequeued.push_back(&msg); - } - - TestMessageStore() : NullMessageStore() {} - ~TestMessageStore(){} - }; - - CPPUNIT_TEST_SUITE(TxAckTest); - CPPUNIT_TEST(testPrepare); - CPPUNIT_TEST(testCommit); - CPPUNIT_TEST_SUITE_END(); - - - AccumulatedAck acked; - TestMessageStore store; - Queue::shared_ptr queue; - vector messages; - list deliveries; - TxAck op; - - -public: - - TxAckTest() : acked(0), queue(new Queue("my_queue", false, &store, 0)), op(acked, deliveries) - { - for(int i = 0; i < 10; i++){ - Message::shared_ptr msg( - new BasicMessage(0, "exchange", "routing_key", false, false, - MockChannel::basicGetBody())); - msg->setHeader(AMQHeaderBody::shared_ptr(new AMQHeaderBody(BASIC))); - msg->getHeaderProperties()->setDeliveryMode(PERSISTENT); - messages.push_back(msg); - deliveries.push_back(DeliveryRecord(msg, queue, "xyz", (i+1))); - } - - //assume msgs 1-5, 7 and 9 are all acked (i.e. 6, 8 & 10 are not) - acked.range = 5; - acked.individual.push_back(7); - acked.individual.push_back(9); - } - - void testPrepare() - { - //ensure acked messages are discarded, i.e. dequeued from store - op.prepare(0); - CPPUNIT_ASSERT_EQUAL((size_t) 7, store.dequeued.size()); - CPPUNIT_ASSERT_EQUAL((size_t) 10, deliveries.size()); - int dequeued[] = {0, 1, 2, 3, 4, 6, 8}; - for (int i = 0; i < 7; i++) { - CPPUNIT_ASSERT_EQUAL((PersistableMessage*) messages[dequeued[i]].get(), store.dequeued[i]); - } - } - - void testCommit() - { - //emsure acked messages are removed from list - op.commit(); - CPPUNIT_ASSERT_EQUAL((size_t) 3, deliveries.size()); - list::iterator i = deliveries.begin(); - CPPUNIT_ASSERT(i->matches(6));//msg 6 - CPPUNIT_ASSERT((++i)->matches(8));//msg 8 - CPPUNIT_ASSERT((++i)->matches(10));//msg 10 - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(TxAckTest); - diff --git a/qpid/cpp/tests/TxBufferTest.cpp b/qpid/cpp/tests/TxBufferTest.cpp deleted file mode 100644 index bd8ae3796b..0000000000 --- a/qpid/cpp/tests/TxBufferTest.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 - -using namespace qpid::broker; - -template void assertEqualVector(std::vector& expected, std::vector& actual){ - unsigned int i = 0; - while(i < expected.size() && i < actual.size()){ - CPPUNIT_ASSERT_EQUAL(expected[i], actual[i]); - i++; - } - CPPUNIT_ASSERT(i == expected.size()); - CPPUNIT_ASSERT(i == actual.size()); -} - -class TxBufferTest : public CppUnit::TestCase -{ - class MockTxOp : public TxOp{ - enum op_codes {PREPARE=2, COMMIT=4, ROLLBACK=8}; - std::vector expected; - std::vector actual; - bool failOnPrepare; - public: - MockTxOp() : failOnPrepare(false) {} - MockTxOp(bool _failOnPrepare) : failOnPrepare(_failOnPrepare) {} - - bool prepare(TransactionContext*) throw(){ - actual.push_back(PREPARE); - return !failOnPrepare; - } - void commit() throw(){ - actual.push_back(COMMIT); - } - void rollback() throw(){ - actual.push_back(ROLLBACK); - } - 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{ - enum op_codes {BEGIN=2, COMMIT=4, ABORT=8}; - std::vector expected; - std::vector actual; - - enum states {OPEN = 1, COMMITTED = 2, ABORTED = 3}; - int state; - - class TestTransactionContext : public TransactionContext{ - MockTransactionalStore* store; - public: - TestTransactionContext(MockTransactionalStore* _store) : store(_store) {} - void commit(){ - if(store->state != OPEN) throw "txn already completed"; - store->state = COMMITTED; - } - - void abort(){ - if(store->state != OPEN) throw "txn already completed"; - store->state = ABORTED; - } - ~TestTransactionContext(){} - }; - - - public: - MockTransactionalStore() : state(OPEN){} - - std::auto_ptr begin(const std::string&){ - throw "Operation not supported"; - } - void prepare(TPCTransactionContext&){ - throw "Operation not supported"; - } - - std::auto_ptr begin(){ - actual.push_back(BEGIN); - std::auto_ptr txn(new TestTransactionContext(this)); - return txn; - } - 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& expectCommit(){ - expected.push_back(COMMIT); - return *this; - } - MockTransactionalStore& expectAbort(){ - expected.push_back(ABORT); - return *this; - } - void check(){ - assertEqualVector(expected, actual); - } - - bool isCommitted(){ - return state == COMMITTED; - } - - bool isAborted(){ - return state == ABORTED; - } - - bool isOpen() const{ - return state == OPEN; - } - ~MockTransactionalStore(){} - }; - - CPPUNIT_TEST_SUITE(TxBufferTest); - CPPUNIT_TEST(testPrepareAndCommit); - CPPUNIT_TEST(testFailOnPrepare); - CPPUNIT_TEST(testRollback); - CPPUNIT_TEST(testBufferIsClearedAfterRollback); - CPPUNIT_TEST(testBufferIsClearedAfterCommit); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testPrepareAndCommit(){ - MockTransactionalStore store; - store.expectBegin().expectCommit(); - - MockTxOp opA; - opA.expectPrepare().expectCommit(); - MockTxOp opB; - opB.expectPrepare().expectPrepare().expectCommit().expectCommit();//opB enlisted twice to test reative order - MockTxOp opC; - opC.expectPrepare().expectCommit(); - - TxBuffer buffer; - buffer.enlist(&opA); - buffer.enlist(&opB); - buffer.enlist(&opB);//opB enlisted twice - buffer.enlist(&opC); - - CPPUNIT_ASSERT(buffer.prepare(&store)); - buffer.commit(); - store.check(); - CPPUNIT_ASSERT(store.isCommitted()); - opA.check(); - opB.check(); - opC.check(); - } - - void testFailOnPrepare(){ - MockTransactionalStore store; - store.expectBegin().expectAbort(); - - MockTxOp opA; - opA.expectPrepare(); - MockTxOp opB(true); - opB.expectPrepare(); - MockTxOp opC;//will never get prepare as b will fail - - TxBuffer buffer; - buffer.enlist(&opA); - buffer.enlist(&opB); - buffer.enlist(&opC); - - CPPUNIT_ASSERT(!buffer.prepare(&store)); - store.check(); - CPPUNIT_ASSERT(store.isAborted()); - opA.check(); - opB.check(); - opC.check(); - } - - void testRollback(){ - MockTxOp opA; - opA.expectRollback(); - MockTxOp opB(true); - opB.expectRollback(); - MockTxOp opC; - opC.expectRollback(); - - TxBuffer buffer; - buffer.enlist(&opA); - buffer.enlist(&opB); - buffer.enlist(&opC); - - buffer.rollback(); - opA.check(); - opB.check(); - opC.check(); - } - - void testBufferIsClearedAfterRollback(){ - MockTxOp opA; - opA.expectRollback(); - MockTxOp opB; - opB.expectRollback(); - - TxBuffer buffer; - buffer.enlist(&opA); - buffer.enlist(&opB); - - buffer.rollback(); - buffer.commit();//second call should not reach ops - opA.check(); - opB.check(); - } - - void testBufferIsClearedAfterCommit(){ - MockTxOp opA; - opA.expectCommit(); - MockTxOp opB; - opB.expectCommit(); - - TxBuffer buffer; - buffer.enlist(&opA); - buffer.enlist(&opB); - - buffer.commit(); - buffer.rollback();//second call should not reach ops - opA.check(); - opB.check(); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(TxBufferTest); - diff --git a/qpid/cpp/tests/TxPublishTest.cpp b/qpid/cpp/tests/TxPublishTest.cpp deleted file mode 100644 index 8ce0da6508..0000000000 --- a/qpid/cpp/tests/TxPublishTest.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 -#include -#include -#include -#include -#include -#include -#include "MockChannel.h" - -using std::list; -using std::pair; -using std::vector; -using namespace qpid::broker; -using namespace qpid::framing; - -class TxPublishTest : public CppUnit::TestCase -{ - typedef std::pair msg_queue_pair; - - class TestMessageStore : public NullMessageStore - { - public: - vector enqueued; - - void enqueue(TransactionContext*, PersistableMessage& msg, const PersistableQueue& queue) - { - enqueued.push_back(msg_queue_pair(queue.getName(), &msg)); - } - - //dont care about any of the other methods: - TestMessageStore() : NullMessageStore(false) {} - ~TestMessageStore(){} - }; - - CPPUNIT_TEST_SUITE(TxPublishTest); - CPPUNIT_TEST(testPrepare); - CPPUNIT_TEST(testCommit); - CPPUNIT_TEST_SUITE_END(); - - - TestMessageStore store; - Queue::shared_ptr queue1; - Queue::shared_ptr queue2; - Message::shared_ptr const msg; - TxPublish op; - -public: - - TxPublishTest() : - queue1(new Queue("queue1", false, &store, 0)), - queue2(new Queue("queue2", false, &store, 0)), - msg(new BasicMessage(0, "exchange", "routing_key", false, false, - MockChannel::basicGetBody())), - op(msg) - { - msg->setHeader(AMQHeaderBody::shared_ptr(new AMQHeaderBody(BASIC))); - msg->getHeaderProperties()->setDeliveryMode(PERSISTENT); - op.deliverTo(queue1); - op.deliverTo(queue2); - } - - void testPrepare() - { - //ensure messages are enqueued in store - op.prepare(0); - CPPUNIT_ASSERT_EQUAL((size_t) 2, store.enqueued.size()); - CPPUNIT_ASSERT_EQUAL(string("queue1"), store.enqueued[0].first); - CPPUNIT_ASSERT_EQUAL((PersistableMessage*) msg.get(), store.enqueued[0].second); - CPPUNIT_ASSERT_EQUAL(string("queue2"), store.enqueued[1].first); - CPPUNIT_ASSERT_EQUAL((PersistableMessage*) msg.get(), store.enqueued[1].second); - } - - void testCommit() - { - //ensure messages are delivered to queue - op.commit(); - CPPUNIT_ASSERT_EQUAL((uint32_t) 1, queue1->getMessageCount()); - CPPUNIT_ASSERT_EQUAL(msg, queue1->dequeue()); - - CPPUNIT_ASSERT_EQUAL((uint32_t) 1, queue2->getMessageCount()); - CPPUNIT_ASSERT_EQUAL(msg, queue2->dequeue()); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(TxPublishTest); - diff --git a/qpid/cpp/tests/ValueTest.cpp b/qpid/cpp/tests/ValueTest.cpp deleted file mode 100644 index a3f9ec2541..0000000000 --- a/qpid/cpp/tests/ValueTest.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 - -using namespace qpid::framing; - - -class ValueTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(ValueTest); - CPPUNIT_TEST(testStringValueEquals); - CPPUNIT_TEST(testIntegerValueEquals); - CPPUNIT_TEST(testDecimalValueEquals); - CPPUNIT_TEST(testFieldTableValueEquals); - CPPUNIT_TEST_SUITE_END(); - - StringValue s; - IntegerValue i; - DecimalValue d; - FieldTableValue ft; - EmptyValue e; - - public: - ValueTest() : - s("abc"), - i(42), - d(1234,2) - - { - ft.getValue().setString("foo", "FOO"); - ft.getValue().setInt("magic", 7); - } - - void testStringValueEquals() - { - - CPPUNIT_ASSERT(StringValue("abc") == s); - CPPUNIT_ASSERT(s != StringValue("foo")); - CPPUNIT_ASSERT(s != e); - CPPUNIT_ASSERT(e != d); - CPPUNIT_ASSERT(e != ft); - } - - void testIntegerValueEquals() - { - CPPUNIT_ASSERT(IntegerValue(42) == i); - CPPUNIT_ASSERT(IntegerValue(5) != i); - CPPUNIT_ASSERT(i != e); - CPPUNIT_ASSERT(i != d); - } - - void testDecimalValueEquals() - { - CPPUNIT_ASSERT(DecimalValue(1234, 2) == d); - CPPUNIT_ASSERT(DecimalValue(12345, 2) != d); - CPPUNIT_ASSERT(DecimalValue(1234, 3) != d); - CPPUNIT_ASSERT(d != s); - } - - - void testFieldTableValueEquals() - { - CPPUNIT_ASSERT_EQUAL(std::string("FOO"), - ft.getValue().getString("foo")); - CPPUNIT_ASSERT_EQUAL(7, ft.getValue().getInt("magic")); - - FieldTableValue f2; - CPPUNIT_ASSERT(ft != f2); - f2.getValue().setString("foo", "FOO"); - CPPUNIT_ASSERT(ft != f2); - f2.getValue().setInt("magic", 7); - CPPUNIT_ASSERT_EQUAL(ft,f2); - CPPUNIT_ASSERT(ft == f2); - f2.getValue().setString("foo", "BAR"); - CPPUNIT_ASSERT(ft != f2); - CPPUNIT_ASSERT(ft != i); - } - -}; - - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(ValueTest); - diff --git a/qpid/cpp/tests/client_test.cpp b/qpid/cpp/tests/client_test.cpp deleted file mode 100644 index 92952c69b1..0000000000 --- a/qpid/cpp/tests/client_test.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. - * - */ - -/** - * 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 -#include -#include -#include -#include -#include -#include - -using namespace qpid::client; -using namespace qpid::sys; -using std::string; - -bool verbose = false; - -/** - * A simple message listener implementation that prints out the - * message content then notifies a montitor allowing the test to - * complete. - */ -class SimpleListener : public virtual MessageListener{ - Monitor* monitor; - -public: - inline SimpleListener(Monitor* _monitor) : monitor(_monitor){} - - inline virtual void received(Message& msg){ - if (verbose) - std::cout << "Received message " << msg.getData() << std::endl; - monitor->notify(); - } -}; - -int main(int argc, char**) -{ - verbose = argc > 1; - try { - //Use a custom exchange - Exchange exchange("MyExchange", Exchange::TOPIC_EXCHANGE); - //Use a named, temporary queue - Queue queue("MyQueue", true); - - - Connection con(verbose); - string host("localhost"); - con.open(host, 5672, "guest", "guest", "/test"); - if (verbose) - std::cout << "Opened connection." << std::endl; - - //Create and open a channel on the connection through which - //most functionality is exposed - Channel channel; - con.openChannel(channel); - if (verbose) std::cout << "Opened channel." << std::endl; - - //'declare' the exchange and the queue, which will create them - //as they don't exist - channel.declareExchange(exchange); - if (verbose) std::cout << "Declared exchange." << std::endl; - channel.declareQueue(queue); - if (verbose) std::cout << "Declared queue." << std::endl; - - //now bind the queue to the exchange - qpid::framing::FieldTable args; - channel.bind(exchange, queue, "MyTopic", args); - if (verbose) std::cout << "Bound queue to exchange." << std::endl; - - //Set up a message listener to receive any messages that - //arrive in our queue on the broker. We only expect one, and - //as it will be received on another thread, we create a - //montior to use to notify the main thread when that message - //is received. - Monitor monitor; - SimpleListener listener(&monitor); - string tag("MyTag"); - channel.consume(queue, tag, &listener); - if (verbose) std::cout << "Registered consumer." << std::endl; - - //we need to enable the message dispatching for this channel - //and we want that to occur on another thread so we call - //start(). - channel.start(); - - //Now we create and publish a message to our exchange with a - //routing key that will cause it to be routed to our queue - Message msg; - string data("MyMessage"); - msg.setData(data); - channel.publish(msg, exchange, "MyTopic"); - if (verbose) std::cout << "Published message: " << data << std::endl; - - { - Monitor::ScopedLock l(monitor); - //now we wait until we receive notification that the - //message was received - monitor.wait(); - } - - //close the channel & connection - channel.close(); - if (verbose) std::cout << "Closed channel." << std::endl; - con.close(); - if (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/tests/dlclose_noop.c b/qpid/cpp/tests/dlclose_noop.c deleted file mode 100644 index ba2fa75891..0000000000 --- a/qpid/cpp/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) {} - diff --git a/qpid/cpp/tests/echo_service.cpp b/qpid/cpp/tests/echo_service.cpp deleted file mode 100644 index ff11a336fe..0000000000 --- a/qpid/cpp/tests/echo_service.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 class provides an example of using AMQP for a request-response - * style system. 'Requests' are messages sent to a well known - * destination. A 'service' process consumes these message and - * responds by echoing the message back to the sender on a - * sender-specified private queue. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace qpid::client; -using namespace qpid::sys; -using std::string; - - -/** - * A message listener implementation representing the 'service', this - * will 'echo' any requests received. - */ -class EchoServer : public MessageListener{ - Channel* const channel; -public: - EchoServer(Channel* channel); - virtual void received(Message& msg); -}; - -/** - * A message listener implementation that merely prints received - * messages to the console. Used to report on 'echo' responses. - */ -class LoggingListener : public MessageListener{ -public: - virtual void received(Message& msg); -}; - -/** - * A utility class that manages the command line options needed to run - * the example confirgurably. - */ -class Args{ - string host; - int port; - bool trace; - bool help; - bool client; -public: - inline Args() : host("localhost"), port(5672), trace(false), help(false), client(false){} - void parse(int argc, char** argv); - void usage(); - - inline const string& getHost() const { return host;} - inline int getPort() const { return port; } - inline bool getTrace() const { return trace; } - inline bool getHelp() const { return help; } - inline bool getClient() const { return client; } -}; - -/** - * The main test path. There are two basic modes: 'client' and - * 'service'. First one or more services are started, then one or more - * clients are started and messages can be sent. - */ -int main(int argc, char** argv){ - const std::string echo_service("echo_service"); - Args args; - args.parse(argc, argv); - if (args.getHelp()) { - args.usage(); - } else if (args.getClient()) { - //we have been started in 'client' mode, i.e. we will send an - //echo requests and print responses received. - try { - //Create connection & open a channel - Connection connection(args.getTrace()); - connection.open(args.getHost(), args.getPort()); - Channel channel; - connection.openChannel(channel); - - //Setup: declare the private 'response' queue and bind it - //to the direct exchange by its name which will be - //generated by the server - Queue response; - channel.declareQueue(response); - qpid::framing::FieldTable emptyArgs; - channel.bind(Exchange::STANDARD_DIRECT_EXCHANGE, response, response.getName(), emptyArgs); - - //Consume from the response queue, logging all echoed message to console: - LoggingListener listener; - std::string tag; - channel.consume(response, tag, &listener); - - //Process incoming requests on a new thread - channel.start(); - - //get messages from console and send them: - std::string text; - std::cout << "Enter text to send:" << std::endl; - while (std::getline(std::cin, text)) { - std::cout << "Sending " << text << " to echo server." << std::endl; - Message msg; - msg.getHeaders().setString("RESPONSE_QUEUE", response.getName()); - msg.setData(text); - channel.publish(msg, Exchange::STANDARD_DIRECT_EXCHANGE, echo_service); - - std::cout << "Enter text to send:" << std::endl; - } - - connection.close(); - } catch(qpid::QpidError error) { - std::cout << error.what() << std::endl; - } - } else { - // we are in 'service' mode, i.e. we will consume messages - // from the request queue and echo each request back to the - // senders own private response queue. - try { - //Create connection & open a channel - Connection connection(args.getTrace()); - connection.open(args.getHost(), args.getPort()); - Channel channel; - connection.openChannel(channel); - - //Setup: declare the 'request' queue and bind it to the direct exchange with a 'well known' name - Queue request("request"); - channel.declareQueue(request); - qpid::framing::FieldTable emptyArgs; - channel.bind(Exchange::STANDARD_DIRECT_EXCHANGE, request, echo_service, emptyArgs); - - //Consume from the request queue, echoing back all messages received to the client that sent them - EchoServer server(&channel); - std::string tag = "server_tag"; - channel.consume(request, tag, &server); - - //Process incoming requests on the main thread - channel.run(); - - connection.close(); - } catch(qpid::QpidError error) { - std::cout << error.what() << std::endl; - } - } -} - -EchoServer::EchoServer(Channel* _channel) : channel(_channel){} - -void EchoServer::received(Message& message) -{ - //get name of response queues binding to the default direct exchange: - const std::string name = message.getHeaders().getString("RESPONSE_QUEUE"); - - if (name.empty()) { - std::cout << "Cannot echo " << message.getData() << ", no response queue specified." << std::endl; - } else { - //print message to console: - std::cout << "Echoing " << message.getData() << " back to " << name << std::endl; - - //'echo' the message back: - channel->publish(message, Exchange::STANDARD_DIRECT_EXCHANGE, name); - } -} - -void LoggingListener::received(Message& message) -{ - //print message to console: - std::cout << "Received echo: " << message.getData() << std::endl; -} - - -void Args::parse(int argc, char** argv){ - for(int i = 1; i < argc; i++){ - string name(argv[i]); - if("-help" == name){ - help = true; - break; - }else if("-host" == name){ - host = argv[++i]; - }else if("-port" == name){ - port = atoi(argv[++i]); - }else if("-trace" == name){ - trace = true; - }else if("-client" == name){ - client = true; - }else{ - std::cout << "Warning: unrecognised option " << name << std::endl; - } - } -} - -void Args::usage(){ - std::cout << "Options:" << std::endl; - std::cout << " -help" << std::endl; - std::cout << " Prints this usage message" << std::endl; - std::cout << " -host " << std::endl; - std::cout << " Specifies host to connect to (default is localhost)" << std::endl; - std::cout << " -port " << std::endl; - std::cout << " Specifies port to conect to (default is 5762)" << std::endl; - std::cout << " -trace" << std::endl; - std::cout << " Indicates that the frames sent and received should be logged" << std::endl; - std::cout << " -client" << std::endl; - std::cout << " Run as a client (else will run as a server)" << std::endl; -} diff --git a/qpid/cpp/tests/examples.Makefile b/qpid/cpp/tests/examples.Makefile deleted file mode 100644 index 45999f7852..0000000000 --- a/qpid/cpp/tests/examples.Makefile +++ /dev/null @@ -1,66 +0,0 @@ -# -# XXX: Edit these locations to suit. -# -BOOST_LOCATION := $(HOME)/local/boost-1.33.1 -APR_LOCATION := $(HOME)/local/apr-1.2.7 - -CXXFLAGS := -DNDEBUG -DUSE_APR -MMD -fpic - -# -# Configure Boost. -# -BOOST_CFLAGS := -I$(BOOST_LOCATION)/include/boost-1_33_1 -CXXFLAGS := $(CXXFLAGS) $(BOOST_CFLAGS) - -# -# Configure APR. -# -APR_CFLAGS := -I$(APR_LOCATION)/include/apr-1 -APR_LDFLAGS := $(shell $(APR_LOCATION)/bin/apr-1-config --libs) -L$(APR_LOCATION)/lib -lapr-1 -CXXFLAGS := $(CXXFLAGS) $(APR_CFLAGS) -LDFLAGS := $(LDFLAGS) $(APR_LDFLAGS) - -# -# Configure Qpid cpp client. -# -QPID_CLIENT_LDFLAGS := ../lib/libcommon.so ../lib/libclient.so -includeDir := ../include -QPID_CLIENT_CFLAGS := \ - -I$(includeDir)/gen \ - -I$(includeDir)/client \ - -I$(includeDir)/broker \ - -I$(includeDir)/common \ - -I$(includeDir)/common/sys \ - -I$(includeDir)/common/framing - -CXXFLAGS := $(CXXFLAGS) $(QPID_CLIENT_CFLAGS) -LDFLAGS := $(LDFLAGS) $(QPID_CLIENT_LDFLAGS) - -CXX := g++ - -# -# Add rule to build examples. -# -.SUFFIX: .cpp -%: %.cpp - $(CXX) $(CXXFLAGS) $(LDFLAGS) $< -o $@ - -# -# Define targets. -# - -EXAMPLES := client_test topic_listener topic_publisher echo_service - -cppFiles := $(wildcard *.cpp) -programs = $(foreach cppFile, $(cppFiles), $(subst .cpp, ,$(cppFile))) - -.PHONY: -all: $(programs) - -debug: - @echo cppFiles = $(cppFiles) - @echo programs = $(programs) - -.PHONY: -clean: - -rm $(EXAMPLES) diff --git a/qpid/cpp/tests/examples.README b/qpid/cpp/tests/examples.README deleted file mode 100644 index 65f908c249..0000000000 --- a/qpid/cpp/tests/examples.README +++ /dev/null @@ -1,18 +0,0 @@ -Building the examples ---------------------- - -You had better edit the Makefile and provide the locations for APR and boost. - -Then just type 'make'. - - -Running the examples --------------------- - -Before running the examples ensure that you have setup your LD_LIBRARY_PATH. - -Most of the examples take the following connection parameters for your -AMQP broker: - - -host host - -port port diff --git a/qpid/cpp/tests/kill_broker b/qpid/cpp/tests/kill_broker deleted file mode 100755 index b71ca22ffd..0000000000 --- a/qpid/cpp/tests/kill_broker +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -PID=qpidd.pid -if [ -f $PID ] ; then kill -9 `cat $PID` ; rm -f $PID ; fi diff --git a/qpid/cpp/tests/python_tests b/qpid/cpp/tests/python_tests deleted file mode 100755 index 4ee177ce6a..0000000000 --- a/qpid/cpp/tests/python_tests +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# Run the python tests. -if test -d ../../python ; then - cd ../../python && ./run-tests -v -s "0-9" -I cpp_failing_0-9.txt -else - echo Warning: python tests not found. -fi - diff --git a/qpid/cpp/tests/qpid_test_plugin.h b/qpid/cpp/tests/qpid_test_plugin.h deleted file mode 100644 index b2f4a8ffed..0000000000 --- a/qpid/cpp/tests/qpid_test_plugin.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _qpid_test_plugin_ -#define _qpid_test_plugin_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * Convenience to include cppunit headers needed by qpid test plugins and - * workaround for warning from superfluous main() declaration - * in cppunit/TestPlugIn.h - */ - -#include -#include -#include -#include - -// Redefine CPPUNIT_PLUGIN_IMPLEMENT_MAIN to a dummy typedef to avoid warnings. -// -#if defined(CPPUNIT_HAVE_UNIX_DLL_LOADER) || defined(CPPUNIT_HAVE_UNIX_SHL_LOADER) -#undef CPPUNIT_PLUGIN_IMPLEMENT_MAIN -#define CPPUNIT_PLUGIN_IMPLEMENT_MAIN() typedef char __CppUnitPlugInImplementMainDummyTypeDef -#endif - -#endif /*!_qpid_test_plugin_*/ diff --git a/qpid/cpp/tests/quick_topictest b/qpid/cpp/tests/quick_topictest deleted file mode 100755 index 9df5b5c84c..0000000000 --- a/qpid/cpp/tests/quick_topictest +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -# Quick and quiet topic test for make check. -./topictest -s2 -m2 -b1 > topictest.log 2>&1 || { - echo See topictest.log. - exit 1 -} -rm topictest.log diff --git a/qpid/cpp/tests/run-python-tests b/qpid/cpp/tests/run-python-tests deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/qpid/cpp/tests/run-unit-tests b/qpid/cpp/tests/run-unit-tests deleted file mode 100755 index f066a38205..0000000000 --- a/qpid/cpp/tests/run-unit-tests +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# -# Library names (without path or .so) and CppUnit test paths can be -# specified on the command line or in env var UNIT_TESTS. For example: -# -# Selected test classes: -# ./run-unit-tests ValueTest ClientChannelTest -# -# Individual test method -# ./run-unit-tests ValueTest :ValueTest::testStringValueEquals -# -# Build and run selected tests: -# make check TESTS=run-unit-tests UNIT_TESTS=ClientChannelTest -# - -# Default VALGRIND from the path and $srcdir to . but -# don't override values set by make. -test -z "$VALGRIND" -a -z "$MAKEFLAGS" && VALGRIND=`which valgrind` 2>/dev/null -test -z "$srcdir" && srcdir=. - -rm -f valgrind.out -vg_log=--log-file-exactly=valgrind.out -source $srcdir/setup -for u in $* $UNIT_TESTS ; do - case $u in - :*) TEST_ARGS="$TEST_ARGS $u" ;; # A test path. - *) TEST_ARGS="$TEST_ARGS $pwd/.libs/$u.so" ;; # A test library. - esac -done -# If none specified, run all tests in .libs -test -z "$TEST_ARGS" && TEST_ARGS="$pwd/.libs/*Test.so" -fail=0 - -$vg DllPlugInTester -c -b $TEST_ARGS || fail=1 -vg_check valgrind.out || fail=1 - -exit $fail diff --git a/qpid/cpp/tests/setup b/qpid/cpp/tests/setup deleted file mode 100644 index aaa3afd9b8..0000000000 --- a/qpid/cpp/tests/setup +++ /dev/null @@ -1,81 +0,0 @@ -# -*- sh -*- - -test "$VERBOSE" = yes && set -x - -pwd=`pwd` -test -z "$abs_srcdir" && abs_srcdir=$pwd - -t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$ -pid=0 -test -z "$TEST_DEBUG" && -trap 's=$?;test $pid = 0||kill -2 $pid;cd "$pwd" && rm -rf $t0 && exit $s' 0 -test -z "$TEST_DEBUG" && trap '(exit $?); exit $?' 1 2 13 15 - -framework_failure=0 -mkdir -p $tmp || framework_failure=1 -cd $tmp || framework_failure=1 - -gen_supp=--gen-suppressions=all -# This option makes valgrind significantly slower. -full_leak_check=--leak-check=full -demangle=--demangle=yes - -vg_options=" - --suppressions=$abs_srcdir/.vg-supp - --num-callers=25 - --track-fds=yes - $demangle - $full_leak_check - $gen_supp - $vg_log - " -# configure tests for the existence of valgrind. -# If it's not available, then make $vg and vg_check no-ops. -if test x$VALGRIND = x; then - vg= -else - vg="libtool --mode=execute $VALGRIND `echo $vg_options` --" - # Suppress dlclose or valgrind traces wont have test library symbols. - vg="env LD_PRELOAD=$pwd/.libs/libdlclose_noop.so $vg" -fi - - -vg_leak_check() -{ - local file=$1 - local fail - # If we detect a leak, dump all output to stderr. - grep -E '^==[0-9]+== +definitely lost: [^0]' $file \ - && { fail=1; cat $file 1>&2; - echo "found memory leaks (see log file, $file); see above" 1>&2; } - test "$fail" = '' -} - - -# Ensure 1) that there is an ERROR SUMMARY line, and -# 2) that the number of errors is 0. -# An offending line looks like this: -# ==29302== ERROR SUMMARY: 4 errors from 2 contexts (suppressed: 16 from 5) -vg_error_check() -{ - local file=$1 - local fail - # If we detect a leak, dump all output to stderr. - grep -E '^==[0-9]+== ERROR SUMMARY:' $file > /dev/null \ - || { fail=1; cat $file 1>&2; - echo "no valgrind ERROR SUMMARY line in $file" 1>&2; } - if test "$fail" = ''; then - grep -E '^==[0-9]+== ERROR SUMMARY: [^0] ' $file \ - && { fail=1; cat $file 1>&2; - echo "valgrind reported errors in $file; see above" 1>&2; } - fi - test "$fail" = '' -} - -vg_check() -{ - local file=$1 - if test x$VALGRIND != x; then - vg_error_check $file && vg_leak_check $file - fi -} diff --git a/qpid/cpp/tests/start_broker b/qpid/cpp/tests/start_broker deleted file mode 100755 index fe30458463..0000000000 --- a/qpid/cpp/tests/start_broker +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -set -e - -LOG=`pwd`/qpidd.log -PID=`pwd`/qpidd.pid - -rm -rf $LOG $PID - -# Start the daemon, recording its PID. -../src/qpidd > $LOG 2>&1 & echo $! > $PID - -# FIXME aconway 2007-01-18: qpidd should not return till it is accepting -# connections, remove arbitrary sleep. -sleep 5 diff --git a/qpid/cpp/tests/topic_listener.cpp b/qpid/cpp/tests/topic_listener.cpp deleted file mode 100644 index 5928dac49a..0000000000 --- a/qpid/cpp/tests/topic_listener.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. - * - */ - -/** - * This file provides one half of a test and example of a pub-sub - * style of interaction. See 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 -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace qpid::client; -using namespace qpid::sys; -using namespace std; - -/** - * A message listener implementation in which the runtime logic is - * defined. - */ -class Listener : public MessageListener{ - Channel* const channel; - const string responseQueue; - const bool transactional; - bool init; - int count; - Time start; - - void shutdown(); - void report(); -public: - Listener(Channel* channel, const string& reponseQueue, bool tx); - virtual void received(Message& msg); -}; - -/** - * A utility class for managing the options passed in. - */ -class Args{ - string host; - int port; - AckMode ackMode; - bool transactional; - int prefetch; - bool trace; - bool help; -public: - inline Args() : host("localhost"), port(5672), ackMode(NO_ACK), transactional(false), prefetch(1000), trace(false), help(false){} - void parse(int argc, char** argv); - void usage(); - - const string& getHost() const { return host;} - int getPort() const { return port; } - AckMode getAckMode(){ return ackMode; } - bool getTransactional() const { return transactional; } - int getPrefetch(){ return prefetch; } - bool getTrace() const { return trace; } - bool getHelp() const { return help; } -}; - -/** - * 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){ - Args args; - args.parse(argc, argv); - if(args.getHelp()){ - args.usage(); - }else{ - try{ - cout << "topic_listener: Started." << endl; - Connection connection(args.getTrace()); - connection.open(args.getHost(), args.getPort(), "guest", "guest", "/test"); - Channel channel(args.getTransactional(), args.getPrefetch()); - connection.openChannel(channel); - - //declare exchange, queue and bind them: - Queue response("response"); - channel.declareQueue(response); - - Queue control; - channel.declareQueue(control); - qpid::framing::FieldTable bindArgs; - channel.bind(Exchange::STANDARD_TOPIC_EXCHANGE, control, "topic_control", bindArgs); - //set up listener - Listener listener(&channel, response.getName(), args.getTransactional()); - string tag; - channel.consume(control, tag, &listener, args.getAckMode()); - cout << "topic_listener: Consuming." << endl; - channel.run(); - connection.close(); - cout << "topic_listener: normal exit" << endl; - return 0; - }catch(qpid::QpidError error){ - cout << "topic_listener: " << error.what() << endl; - } - } - return 1; -} - -Listener::Listener(Channel* _channel, const string& _responseq, bool tx) : - channel(_channel), responseQueue(_responseq), transactional(tx), init(false), count(0){} - -void Listener::received(Message& message){ - if(!init){ - start = now(); - count = 0; - init = true; - } - string type(message.getHeaders().getString("TYPE")); - - if(type == "TERMINATION_REQUEST"){ - shutdown(); - }else if(type == "REPORT_REQUEST"){ - //send a report: - report(); - init = false; - }else if (++count % 100 == 0){ - cout <<"Received " << count << " messages." << endl; - } -} - -void Listener::shutdown(){ - channel->close(); -} - -void Listener::report(){ - Time finish = now(); - Time time = finish - start; - stringstream reportstr; - reportstr << "Received " << count << " messages in " - << time/TIME_MSEC << " ms."; - Message msg(reportstr.str()); - msg.getHeaders().setString("TYPE", "REPORT"); - channel->publish(msg, string(), responseQueue); - if(transactional){ - channel->commit(); - } -} - - -void Args::parse(int argc, char** argv){ - for(int i = 1; i < argc; i++){ - string name(argv[i]); - if("-help" == name){ - help = true; - break; - }else if("-host" == name){ - host = argv[++i]; - }else if("-port" == name){ - port = atoi(argv[++i]); - }else if("-ack_mode" == name){ - ackMode = AckMode(atoi(argv[++i])); - }else if("-transactional" == name){ - transactional = true; - }else if("-prefetch" == name){ - prefetch = atoi(argv[++i]); - }else if("-trace" == name){ - trace = true; - }else{ - cout << "Warning: unrecognised option " << name << endl; - } - } -} - -void Args::usage(){ - cout << "Options:" << endl; - cout << " -help" << endl; - cout << " Prints this usage message" << endl; - cout << " -host " << endl; - cout << " Specifies host to connect to (default is localhost)" << endl; - cout << " -port " << endl; - cout << " Specifies port to conect to (default is 5762)" << endl; - cout << " -ack_mode " << endl; - cout << " Sets the acknowledgement mode" << endl; - cout << " 0=NO_ACK (default), 1=AUTO_ACK, 2=LAZY_ACK" << endl; - cout << " -transactional" << endl; - cout << " Indicates the client should use transactions" << endl; - cout << " -prefetch " << endl; - cout << " Specifies the prefetch count (default is 1000)" << endl; - cout << " -trace" << endl; - cout << " Indicates that the frames sent and received should be logged" << endl; -} diff --git a/qpid/cpp/tests/topic_publisher.cpp b/qpid/cpp/tests/topic_publisher.cpp deleted file mode 100644 index 2fd1e6b810..0000000000 --- a/qpid/cpp/tests/topic_publisher.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. - * - */ - -/** - * This file provides one half of a test and example of a pub-sub - * style of interaction. See 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 -#include -#include -#include -#include -#include -#include -#include "unistd.h" -#include -#include -#include - -using namespace qpid::client; -using namespace qpid::sys; -using std::string; - -/** - * 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 : public MessageListener{ - Channel* const channel; - const std::string controlTopic; - const bool transactional; - Monitor monitor; - int count; - - void waitForCompletion(int msgs); - string generateData(int size); - -public: - Publisher(Channel* channel, const std::string& controlTopic, bool tx); - virtual void received(Message& msg); - int64_t publish(int msgs, int listeners, int size); - void terminate(); -}; - -/** - * A utility class for managing the options passed in to the test - */ -class Args{ - string host; - int port; - int messages; - int subscribers; - AckMode ackMode; - bool transactional; - int prefetch; - int batches; - int delay; - int size; - bool trace; - bool help; -public: - inline Args() : host("localhost"), port(5672), messages(1000), subscribers(1), - ackMode(NO_ACK), transactional(false), prefetch(1000), batches(1), - delay(0), size(256), trace(false), help(false){} - - void parse(int argc, char** argv); - void usage(); - - const string& getHost() const { return host;} - int getPort() const { return port; } - int getMessages() const { return messages; } - int getSubscribers() const { return subscribers; } - AckMode getAckMode(){ return ackMode; } - bool getTransactional() const { return transactional; } - int getPrefetch(){ return prefetch; } - int getBatches(){ return batches; } - int getDelay(){ return delay; } - int getSize(){ return size; } - bool getTrace() const { return trace; } - bool getHelp() const { return help; } -}; - -int main(int argc, char** argv) { - Args args; - args.parse(argc, argv); - if(args.getHelp()){ - args.usage(); - } else { - try{ - Connection connection(args.getTrace()); - connection.open(args.getHost(), args.getPort(), "guest", "guest", "/test"); - Channel channel(args.getTransactional(), args.getPrefetch()); - connection.openChannel(channel); - - //declare queue (relying on default binding): - Queue response("response"); - channel.declareQueue(response); - - //set up listener - Publisher publisher(&channel, "topic_control", args.getTransactional()); - std::string tag("mytag"); - channel.consume(response, tag, &publisher, args.getAckMode()); - channel.start(); - - int batchSize(args.getBatches()); - int64_t max(0); - int64_t min(0); - int64_t sum(0); - for(int i = 0; i < batchSize; i++){ - if(i > 0 && args.getDelay()) sleep(args.getDelay()); - int64_t msecs = - publisher.publish(args.getMessages(), - args.getSubscribers(), - args.getSize()) / TIME_MSEC; - if(!max || msecs > max) max = msecs; - if(!min || msecs < min) min = msecs; - sum += msecs; - std::cout << "Completed " << (i+1) << " of " << batchSize - << " in " << msecs << "ms" << std::endl; - } - publisher.terminate(); - int64_t avg = sum / batchSize; - if(batchSize > 1){ - std::cout << batchSize << " batches completed. avg=" << avg << - ", max=" << max << ", min=" << min << std::endl; - } - channel.close(); - connection.close(); - return 0; - }catch(qpid::QpidError error) { - std::cout << error.what() << std::endl; - } - } - return 1; -} - -Publisher::Publisher(Channel* _channel, const std::string& _controlTopic, bool tx) : - channel(_channel), controlTopic(_controlTopic), transactional(tx){} - -void Publisher::received(Message& ){ - //count responses and when all are received end the current batch - Monitor::ScopedLock l(monitor); - if(--count == 0){ - monitor.notify(); - } -} - -void Publisher::waitForCompletion(int msgs){ - count = msgs; - monitor.wait(); -} - -int64_t Publisher::publish(int msgs, int listeners, int size){ - Message msg; - msg.setData(generateData(size)); - Time start = now(); - { - Monitor::ScopedLock l(monitor); - for(int i = 0; i < msgs; i++){ - channel->publish( - msg, Exchange::STANDARD_TOPIC_EXCHANGE, controlTopic); - } - //send report request - Message reportRequest; - reportRequest.getHeaders().setString("TYPE", "REPORT_REQUEST"); - channel->publish(reportRequest, Exchange::STANDARD_TOPIC_EXCHANGE, controlTopic); - if(transactional){ - channel->commit(); - } - - waitForCompletion(listeners); - } - - Time finish = now(); - return finish - start; -} - -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; - terminationRequest.getHeaders().setString("TYPE", "TERMINATION_REQUEST"); - channel->publish(terminationRequest, Exchange::STANDARD_TOPIC_EXCHANGE, controlTopic); - if(transactional){ - channel->commit(); - } -} - -void Args::parse(int argc, char** argv){ - for(int i = 1; i < argc; i++){ - string name(argv[i]); - if("-help" == name){ - help = true; - break; - }else if("-host" == name){ - host = argv[++i]; - }else if("-port" == name){ - port = atoi(argv[++i]); - }else if("-messages" == name){ - messages = atoi(argv[++i]); - }else if("-subscribers" == name){ - subscribers = atoi(argv[++i]); - }else if("-ack_mode" == name){ - ackMode = AckMode(atoi(argv[++i])); - }else if("-transactional" == name){ - transactional = true; - }else if("-prefetch" == name){ - prefetch = atoi(argv[++i]); - }else if("-batches" == name){ - batches = atoi(argv[++i]); - }else if("-delay" == name){ - delay = atoi(argv[++i]); - }else if("-size" == name){ - size = atoi(argv[++i]); - }else if("-trace" == name){ - trace = true; - }else{ - std::cout << "Warning: unrecognised option " << name << std::endl; - } - } -} - -void Args::usage(){ - std::cout << "Options:" << std::endl; - std::cout << " -help" << std::endl; - std::cout << " Prints this usage message" << std::endl; - std::cout << " -host " << std::endl; - std::cout << " Specifies host to connect to (default is localhost)" << std::endl; - std::cout << " -port " << std::endl; - std::cout << " Specifies port to conect to (default is 5762)" << std::endl; - std::cout << " -messages " << std::endl; - std::cout << " Specifies how many messages to send" << std::endl; - std::cout << " -subscribers " << std::endl; - std::cout << " Specifies how many subscribers to expect reports from" << std::endl; - std::cout << " -ack_mode " << std::endl; - std::cout << " Sets the acknowledgement mode" << std::endl; - std::cout << " 0=NO_ACK (default), 1=AUTO_ACK, 2=LAZY_ACK" << std::endl; - std::cout << " -transactional" << std::endl; - std::cout << " Indicates the client should use transactions" << std::endl; - std::cout << " -prefetch " << std::endl; - std::cout << " Specifies the prefetch count (default is 1000)" << std::endl; - std::cout << " -batches " << std::endl; - std::cout << " Specifies how many batches to run" << std::endl; - std::cout << " -delay " << std::endl; - std::cout << " Causes a delay between each batch" << std::endl; - std::cout << " -size " << std::endl; - std::cout << " Sets the size of the published messages (default is 256 bytes)" << std::endl; - std::cout << " -trace" << std::endl; - std::cout << " Indicates that the frames sent and received should be logged" << std::endl; -} diff --git a/qpid/cpp/tests/topictest b/qpid/cpp/tests/topictest deleted file mode 100755 index 92e40b2c37..0000000000 --- a/qpid/cpp/tests/topictest +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -# 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:" opt ; do - case $opt in - s) SUBSCRIBERS=$OPTARG ;; - m) MESSAGES=$OPTARG ;; - b) BATCHES=$OPTARG ;; - ?) - echo "Usage: %0 [-s ] [-m ]" - exit 1 - ;; - esac -done - -subscribe() { - echo Start subscriber $1 - LOG="subscriber_$1.log" - ./topic_listener > $LOG 2>&1 && rm -f $LOG -} - -publish() { - ./topic_publisher -messages $MESSAGES -batches $BATCHES -subscribers $SUBSCRIBERS -} - -for ((i=$SUBSCRIBERS ; i--; )); do - subscribe $i & -done -# FIXME aconway 2007-03-27: Hack around startup race. Fix topic test. -sleep 1 -publish 2>&1 || exit 1 -- cgit v1.2.1