From 8a6ab3aa61d441b9210c05c84dc9998acfc38737 Mon Sep 17 00:00:00 2001 From: Alan Conway Date: Mon, 16 Oct 2006 13:50:26 +0000 Subject: Build system reorg, see README and Makefile comments for details. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@464494 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/DESIGN | 40 +- cpp/Makefile | 130 +++++- cpp/README | 2 + cpp/broker/Makefile | 39 -- cpp/broker/inc/AutoDelete.h | 54 --- cpp/broker/inc/Binding.h | 35 -- cpp/broker/inc/Broker.h | 86 ---- cpp/broker/inc/Channel.h | 199 ---------- cpp/broker/inc/Configuration.h | 135 ------- cpp/broker/inc/ConnectionToken.h | 35 -- cpp/broker/inc/Consumer.h | 34 -- cpp/broker/inc/DirectExchange.h | 52 --- cpp/broker/inc/Exchange.h | 41 -- cpp/broker/inc/ExchangeBinding.h | 45 --- cpp/broker/inc/ExchangeRegistry.h | 44 --- cpp/broker/inc/FanOutExchange.h | 55 --- cpp/broker/inc/HeadersExchange.h | 60 --- cpp/broker/inc/Message.h | 89 ----- cpp/broker/inc/NameGenerator.h | 36 -- cpp/broker/inc/Queue.h | 106 ----- cpp/broker/inc/QueueRegistry.h | 88 ----- cpp/broker/inc/Router.h | 39 -- cpp/broker/inc/SessionHandlerFactoryImpl.h | 49 --- cpp/broker/inc/SessionHandlerImpl.h | 233 ----------- cpp/broker/inc/TopicExchange.h | 94 ----- cpp/broker/src/AutoDelete.cpp | 93 ----- cpp/broker/src/Broker.cpp | 84 ---- cpp/broker/src/Channel.cpp | 256 ------------ cpp/broker/src/Configuration.cpp | 196 --------- cpp/broker/src/DirectExchange.cpp | 72 ---- cpp/broker/src/ExchangeBinding.cpp | 32 -- cpp/broker/src/ExchangeRegistry.cpp | 57 --- cpp/broker/src/FanOutExchange.cpp | 56 --- cpp/broker/src/HeadersExchange.cpp | 120 ------ cpp/broker/src/Message.cpp | 100 ----- cpp/broker/src/NameGenerator.cpp | 29 -- cpp/broker/src/Queue.cpp | 155 -------- cpp/broker/src/QueueRegistry.cpp | 72 ---- cpp/broker/src/Router.cpp | 32 -- cpp/broker/src/SessionHandlerFactoryImpl.cpp | 50 --- cpp/broker/src/SessionHandlerImpl.cpp | 405 ------------------- cpp/broker/src/TopicExchange.cpp | 163 -------- cpp/broker/test/ChannelTest.cpp | 162 -------- cpp/broker/test/ExchangeTest.cpp | 65 --- cpp/broker/test/HeadersExchangeTest.cpp | 112 ------ cpp/broker/test/Makefile | 20 - cpp/broker/test/MessageTest.cpp | 54 --- cpp/broker/test/QueueRegistryTest.cpp | 76 ---- cpp/broker/test/QueueTest.cpp | 176 --------- cpp/broker/test/RouterTest.cpp | 86 ---- cpp/broker/test/TopicExchangeTest.cpp | 184 --------- cpp/broker/test/ValueTest.cpp | 96 ----- cpp/client/Makefile | 41 -- cpp/client/inc/Channel.h | 127 ------ cpp/client/inc/Connection.h | 105 ----- cpp/client/inc/Exchange.h | 49 --- cpp/client/inc/IncomingMessage.h | 60 --- cpp/client/inc/Message.h | 86 ---- cpp/client/inc/MessageListener.h | 38 -- cpp/client/inc/Queue.h | 47 --- cpp/client/inc/ResponseHandler.h | 49 --- cpp/client/inc/ReturnedMessageHandler.h | 38 -- cpp/client/src/Channel.cpp | 438 --------------------- cpp/client/src/Connection.cpp | 237 ----------- cpp/client/src/Exchange.cpp | 30 -- cpp/client/src/IncomingMessage.cpp | 85 ---- cpp/client/src/Message.cpp | 147 ------- cpp/client/src/MessageListener.cpp | 21 - cpp/client/src/Queue.cpp | 47 --- cpp/client/src/ResponseHandler.cpp | 63 --- cpp/client/src/ReturnedMessageHandler.cpp | 21 - cpp/client/test/Makefile | 45 --- cpp/client/test/client_test.cpp | 97 ----- cpp/client/test/topic_listener.cpp | 180 --------- cpp/client/test/topic_publisher.cpp | 253 ------------ cpp/common/Makefile | 45 --- cpp/common/concurrent/inc/APRBase.h | 63 --- cpp/common/concurrent/inc/APRMonitor.h | 48 --- cpp/common/concurrent/inc/APRThread.h | 48 --- cpp/common/concurrent/inc/APRThreadFactory.h | 44 --- cpp/common/concurrent/inc/APRThreadPool.h | 67 ---- cpp/common/concurrent/inc/LMonitor.h | 44 --- cpp/common/concurrent/inc/LThreadFactory.h | 37 -- cpp/common/concurrent/inc/LockedQueue.h | 68 ---- cpp/common/concurrent/inc/Monitor.h | 59 --- cpp/common/concurrent/inc/MonitorImpl.h | 57 --- cpp/common/concurrent/inc/Runnable.h | 35 -- cpp/common/concurrent/inc/TaskQueue.h | 200 ---------- cpp/common/concurrent/inc/Thread.h | 37 -- cpp/common/concurrent/inc/ThreadFactory.h | 38 -- cpp/common/concurrent/inc/ThreadFactoryImpl.h | 52 --- cpp/common/concurrent/inc/ThreadPool.h | 40 -- cpp/common/concurrent/src/APRBase.cpp | 96 ----- cpp/common/concurrent/src/APRMonitor.cpp | 60 --- cpp/common/concurrent/src/APRThread.cpp | 50 --- cpp/common/concurrent/src/APRThreadFactory.cpp | 35 -- cpp/common/concurrent/src/APRThreadPool.cpp | 83 ---- cpp/common/concurrent/src/Runnable.cpp | 19 - cpp/common/error/inc/Exception.h | 46 --- cpp/common/error/inc/QpidError.h | 46 --- cpp/common/error/src/Exception.cpp | 21 - cpp/common/error/src/QpidError.cpp | 32 -- cpp/common/framing/Makefile | 28 -- cpp/common/framing/generated/Makefile | 41 -- .../framing/generated/stylesheets/amqp_client.xsl | 155 -------- .../stylesheets/amqp_client_handler_impl.xsl | 187 --------- .../stylesheets/amqp_client_operations.xsl | 105 ----- .../framing/generated/stylesheets/amqp_consts.xsl | 77 ---- .../framing/generated/stylesheets/amqp_server.xsl | 187 --------- .../stylesheets/amqp_server_handler_impl.xsl | 187 --------- .../stylesheets/amqp_server_operations.xsl | 113 ------ .../framing/generated/stylesheets/code_gen.xsl | 91 ----- .../framing/generated/stylesheets/code_utils.xsl | 210 ---------- .../framing/generated/stylesheets/convert_0.81.xsl | 407 ------------------- cpp/common/framing/generated/stylesheets/cpp.xsl | 315 --------------- .../framing/generated/stylesheets/framing.xsl | 49 --- .../framing/generated/stylesheets/prepare1.xsl | 104 ----- .../framing/generated/stylesheets/prepare2.xsl | 54 --- .../framing/generated/stylesheets/prepare3.xsl | 54 --- .../framing/generated/stylesheets/registry.xsl | 12 - cpp/common/framing/generated/stylesheets/utils.xsl | 194 --------- cpp/common/framing/inc/AMQBody.h | 48 --- cpp/common/framing/inc/AMQContentBody.h | 50 --- cpp/common/framing/inc/AMQDataBlock.h | 39 -- cpp/common/framing/inc/AMQFrame.h | 61 --- cpp/common/framing/inc/AMQHeaderBody.h | 57 --- cpp/common/framing/inc/AMQHeartbeatBody.h | 44 --- cpp/common/framing/inc/AMQMethodBody.h | 56 --- cpp/common/framing/inc/BasicHeaderProperties.h | 93 ----- cpp/common/framing/inc/BodyHandler.h | 51 --- cpp/common/framing/inc/Buffer.h | 78 ---- cpp/common/framing/inc/FieldTable.h | 78 ---- cpp/common/framing/inc/HeaderProperties.h | 43 -- cpp/common/framing/inc/InitiationHandler.h | 38 -- cpp/common/framing/inc/InputHandler.h | 38 -- cpp/common/framing/inc/OutputHandler.h | 38 -- cpp/common/framing/inc/ProtocolInitiation.h | 48 --- cpp/common/framing/inc/Value.h | 160 -------- cpp/common/framing/inc/amqp_framing.h | 31 -- cpp/common/framing/inc/amqp_types.h | 36 -- cpp/common/framing/src/AMQBody.cpp | 33 -- cpp/common/framing/src/AMQContentBody.cpp | 40 -- cpp/common/framing/src/AMQFrame.cpp | 115 ------ cpp/common/framing/src/AMQHeaderBody.cpp | 73 ---- cpp/common/framing/src/AMQHeartbeatBody.cpp | 26 -- cpp/common/framing/src/AMQMethodBody.cpp | 43 -- cpp/common/framing/src/BasicHeaderProperties.cpp | 100 ----- cpp/common/framing/src/BodyHandler.cpp | 51 --- cpp/common/framing/src/Buffer.cpp | 168 -------- cpp/common/framing/src/FieldTable.cpp | 147 ------- cpp/common/framing/src/InitiationHandler.cpp | 21 - cpp/common/framing/src/InputHandler.cpp | 21 - cpp/common/framing/src/OutputHandler.cpp | 21 - cpp/common/framing/src/ProtocolInitiation.cpp | 53 --- cpp/common/framing/src/Value.cpp | 111 ------ cpp/common/framing/test/BodyHandlerTest.cpp | 103 ----- cpp/common/framing/test/Makefile | 21 - cpp/common/framing/test/field_table_test.cpp | 52 --- cpp/common/framing/test/framing_test.cpp | 144 ------- cpp/common/framing/test/header_test.cpp | 141 ------- cpp/common/io/Makefile | 31 -- cpp/common/io/inc/APRConnector.h | 95 ----- cpp/common/io/inc/APRSocket.h | 45 --- cpp/common/io/inc/Acceptor.h | 53 --- cpp/common/io/inc/BlockingAPRAcceptor.h | 65 --- cpp/common/io/inc/BlockingAPRSessionContext.h | 94 ----- cpp/common/io/inc/Connector.h | 56 --- cpp/common/io/inc/ConnectorImpl.h | 53 --- cpp/common/io/inc/LConnector.h | 48 --- cpp/common/io/inc/LFAcceptor.h | 74 ---- cpp/common/io/inc/LFProcessor.h | 119 ------ cpp/common/io/inc/LFSessionContext.h | 88 ----- cpp/common/io/inc/SessionContext.h | 37 -- cpp/common/io/inc/SessionHandler.h | 42 -- cpp/common/io/inc/SessionHandlerFactory.h | 38 -- cpp/common/io/inc/SessionManager.h | 40 -- cpp/common/io/inc/ShutdownHandler.h | 34 -- cpp/common/io/inc/TimeoutHandler.h | 36 -- cpp/common/io/src/APRConnector.cpp | 201 ---------- cpp/common/io/src/APRSocket.cpp | 78 ---- cpp/common/io/src/Acceptor.cpp | 21 - cpp/common/io/src/BlockingAPRAcceptor.cpp | 101 ----- cpp/common/io/src/BlockingAPRSessionContext.cpp | 178 --------- cpp/common/io/src/LFAcceptor.cpp | 94 ----- cpp/common/io/src/LFProcessor.cpp | 193 --------- cpp/common/io/src/LFSessionContext.cpp | 189 --------- cpp/common/utils/inc/memory.h | 17 - cpp/common/utils/src/Makefile | 37 -- cpp/etc/stylesheets/amqp_client.xsl | 155 ++++++++ cpp/etc/stylesheets/amqp_client_handler_impl.xsl | 187 +++++++++ cpp/etc/stylesheets/amqp_client_operations.xsl | 105 +++++ cpp/etc/stylesheets/amqp_consts.xsl | 77 ++++ cpp/etc/stylesheets/amqp_server.xsl | 187 +++++++++ cpp/etc/stylesheets/amqp_server_handler_impl.xsl | 187 +++++++++ cpp/etc/stylesheets/amqp_server_operations.xsl | 113 ++++++ cpp/etc/stylesheets/code_gen.xsl | 91 +++++ cpp/etc/stylesheets/code_utils.xsl | 210 ++++++++++ cpp/etc/stylesheets/convert_0.81.xsl | 407 +++++++++++++++++++ cpp/etc/stylesheets/cpp.xsl | 315 +++++++++++++++ cpp/etc/stylesheets/framing.xsl | 49 +++ cpp/etc/stylesheets/prepare1.xsl | 104 +++++ cpp/etc/stylesheets/prepare2.xsl | 54 +++ cpp/etc/stylesheets/prepare3.xsl | 54 +++ cpp/etc/stylesheets/registry.xsl | 12 + cpp/etc/stylesheets/utils.xsl | 194 +++++++++ cpp/options.mk | 52 +-- cpp/qpidd/Makefile | 42 -- cpp/qpidd/src/qpidd.cpp | 52 --- cpp/src/memory.h | 17 + cpp/src/qpid/Exception.cpp | 21 + cpp/src/qpid/Exception.h | 46 +++ cpp/src/qpid/QpidError.cpp | 32 ++ cpp/src/qpid/QpidError.h | 46 +++ cpp/src/qpid/broker/AutoDelete.cpp | 93 +++++ cpp/src/qpid/broker/AutoDelete.h | 54 +++ cpp/src/qpid/broker/Binding.h | 35 ++ cpp/src/qpid/broker/Broker.cpp | 84 ++++ cpp/src/qpid/broker/Broker.h | 86 ++++ cpp/src/qpid/broker/Channel.cpp | 256 ++++++++++++ cpp/src/qpid/broker/Channel.h | 199 ++++++++++ cpp/src/qpid/broker/Configuration.cpp | 196 +++++++++ cpp/src/qpid/broker/Configuration.h | 135 +++++++ cpp/src/qpid/broker/ConnectionToken.h | 35 ++ cpp/src/qpid/broker/Consumer.h | 34 ++ cpp/src/qpid/broker/DirectExchange.cpp | 72 ++++ cpp/src/qpid/broker/DirectExchange.h | 52 +++ cpp/src/qpid/broker/Exchange.h | 41 ++ cpp/src/qpid/broker/ExchangeBinding.cpp | 32 ++ cpp/src/qpid/broker/ExchangeBinding.h | 45 +++ cpp/src/qpid/broker/ExchangeRegistry.cpp | 57 +++ cpp/src/qpid/broker/ExchangeRegistry.h | 44 +++ cpp/src/qpid/broker/FanOutExchange.cpp | 56 +++ cpp/src/qpid/broker/FanOutExchange.h | 55 +++ cpp/src/qpid/broker/HeadersExchange.cpp | 120 ++++++ cpp/src/qpid/broker/HeadersExchange.h | 60 +++ cpp/src/qpid/broker/Message.cpp | 100 +++++ cpp/src/qpid/broker/Message.h | 89 +++++ cpp/src/qpid/broker/NameGenerator.cpp | 29 ++ cpp/src/qpid/broker/NameGenerator.h | 36 ++ cpp/src/qpid/broker/Queue.cpp | 155 ++++++++ cpp/src/qpid/broker/Queue.h | 106 +++++ cpp/src/qpid/broker/QueueRegistry.cpp | 72 ++++ cpp/src/qpid/broker/QueueRegistry.h | 88 +++++ cpp/src/qpid/broker/Router.cpp | 32 ++ cpp/src/qpid/broker/Router.h | 39 ++ cpp/src/qpid/broker/SessionHandlerFactoryImpl.cpp | 50 +++ cpp/src/qpid/broker/SessionHandlerFactoryImpl.h | 49 +++ cpp/src/qpid/broker/SessionHandlerImpl.cpp | 405 +++++++++++++++++++ cpp/src/qpid/broker/SessionHandlerImpl.h | 233 +++++++++++ cpp/src/qpid/broker/TopicExchange.cpp | 163 ++++++++ cpp/src/qpid/broker/TopicExchange.h | 94 +++++ cpp/src/qpid/client/Channel.cpp | 438 +++++++++++++++++++++ cpp/src/qpid/client/Channel.h | 127 ++++++ cpp/src/qpid/client/Connection.cpp | 237 +++++++++++ cpp/src/qpid/client/Connection.h | 105 +++++ cpp/src/qpid/client/Exchange.cpp | 30 ++ cpp/src/qpid/client/Exchange.h | 49 +++ cpp/src/qpid/client/IncomingMessage.cpp | 85 ++++ cpp/src/qpid/client/IncomingMessage.h | 60 +++ cpp/src/qpid/client/Message.cpp | 147 +++++++ cpp/src/qpid/client/Message.h | 86 ++++ cpp/src/qpid/client/MessageListener.cpp | 21 + cpp/src/qpid/client/MessageListener.h | 38 ++ cpp/src/qpid/client/Queue.cpp | 47 +++ cpp/src/qpid/client/Queue.h | 47 +++ cpp/src/qpid/client/ResponseHandler.cpp | 63 +++ cpp/src/qpid/client/ResponseHandler.h | 49 +++ cpp/src/qpid/client/ReturnedMessageHandler.cpp | 21 + cpp/src/qpid/client/ReturnedMessageHandler.h | 38 ++ cpp/src/qpid/concurrent/APRBase.cpp | 96 +++++ cpp/src/qpid/concurrent/APRBase.h | 63 +++ cpp/src/qpid/concurrent/APRMonitor.cpp | 60 +++ cpp/src/qpid/concurrent/APRMonitor.h | 48 +++ cpp/src/qpid/concurrent/APRThread.cpp | 50 +++ cpp/src/qpid/concurrent/APRThread.h | 48 +++ cpp/src/qpid/concurrent/APRThreadFactory.cpp | 35 ++ cpp/src/qpid/concurrent/APRThreadFactory.h | 44 +++ cpp/src/qpid/concurrent/APRThreadPool.cpp | 83 ++++ cpp/src/qpid/concurrent/APRThreadPool.h | 67 ++++ cpp/src/qpid/concurrent/LMonitor.h | 44 +++ cpp/src/qpid/concurrent/LThreadFactory.h | 37 ++ cpp/src/qpid/concurrent/LockedQueue.h | 68 ++++ cpp/src/qpid/concurrent/Monitor.h | 59 +++ cpp/src/qpid/concurrent/MonitorImpl.h | 57 +++ cpp/src/qpid/concurrent/Runnable.cpp | 19 + cpp/src/qpid/concurrent/Runnable.h | 35 ++ cpp/src/qpid/concurrent/TaskQueue.h | 200 ++++++++++ cpp/src/qpid/concurrent/Thread.h | 37 ++ cpp/src/qpid/concurrent/ThreadFactory.h | 38 ++ cpp/src/qpid/concurrent/ThreadFactoryImpl.h | 52 +++ cpp/src/qpid/concurrent/ThreadPool.h | 40 ++ cpp/src/qpid/framing/AMQBody.cpp | 33 ++ cpp/src/qpid/framing/AMQBody.h | 48 +++ cpp/src/qpid/framing/AMQContentBody.cpp | 40 ++ cpp/src/qpid/framing/AMQContentBody.h | 50 +++ cpp/src/qpid/framing/AMQDataBlock.h | 39 ++ cpp/src/qpid/framing/AMQFrame.cpp | 115 ++++++ cpp/src/qpid/framing/AMQFrame.h | 61 +++ cpp/src/qpid/framing/AMQHeaderBody.cpp | 73 ++++ cpp/src/qpid/framing/AMQHeaderBody.h | 57 +++ cpp/src/qpid/framing/AMQHeartbeatBody.cpp | 26 ++ cpp/src/qpid/framing/AMQHeartbeatBody.h | 44 +++ cpp/src/qpid/framing/AMQMethodBody.cpp | 43 ++ cpp/src/qpid/framing/AMQMethodBody.h | 56 +++ cpp/src/qpid/framing/BasicHeaderProperties.cpp | 100 +++++ cpp/src/qpid/framing/BasicHeaderProperties.h | 93 +++++ cpp/src/qpid/framing/BodyHandler.cpp | 51 +++ cpp/src/qpid/framing/BodyHandler.h | 51 +++ cpp/src/qpid/framing/Buffer.cpp | 168 ++++++++ cpp/src/qpid/framing/Buffer.h | 78 ++++ cpp/src/qpid/framing/FieldTable.cpp | 147 +++++++ cpp/src/qpid/framing/FieldTable.h | 78 ++++ cpp/src/qpid/framing/HeaderProperties.h | 43 ++ cpp/src/qpid/framing/InitiationHandler.cpp | 21 + cpp/src/qpid/framing/InitiationHandler.h | 38 ++ cpp/src/qpid/framing/InputHandler.cpp | 21 + cpp/src/qpid/framing/InputHandler.h | 38 ++ cpp/src/qpid/framing/OutputHandler.cpp | 21 + cpp/src/qpid/framing/OutputHandler.h | 38 ++ cpp/src/qpid/framing/ProtocolInitiation.cpp | 53 +++ cpp/src/qpid/framing/ProtocolInitiation.h | 48 +++ cpp/src/qpid/framing/Value.cpp | 111 ++++++ cpp/src/qpid/framing/Value.h | 160 ++++++++ cpp/src/qpid/framing/amqp_framing.h | 31 ++ cpp/src/qpid/framing/amqp_types.h | 36 ++ cpp/src/qpid/io/APRConnector.cpp | 201 ++++++++++ cpp/src/qpid/io/APRConnector.h | 95 +++++ cpp/src/qpid/io/APRSocket.cpp | 78 ++++ cpp/src/qpid/io/APRSocket.h | 45 +++ cpp/src/qpid/io/Acceptor.cpp | 21 + cpp/src/qpid/io/Acceptor.h | 53 +++ cpp/src/qpid/io/BlockingAPRAcceptor.cpp | 101 +++++ cpp/src/qpid/io/BlockingAPRAcceptor.h | 65 +++ cpp/src/qpid/io/BlockingAPRSessionContext.cpp | 178 +++++++++ cpp/src/qpid/io/BlockingAPRSessionContext.h | 94 +++++ cpp/src/qpid/io/Connector.h | 56 +++ cpp/src/qpid/io/ConnectorImpl.h | 53 +++ cpp/src/qpid/io/LConnector.h | 48 +++ cpp/src/qpid/io/LFAcceptor.cpp | 94 +++++ cpp/src/qpid/io/LFAcceptor.h | 74 ++++ cpp/src/qpid/io/LFProcessor.cpp | 193 +++++++++ cpp/src/qpid/io/LFProcessor.h | 119 ++++++ cpp/src/qpid/io/LFSessionContext.cpp | 189 +++++++++ cpp/src/qpid/io/LFSessionContext.h | 88 +++++ cpp/src/qpid/io/SessionContext.h | 37 ++ cpp/src/qpid/io/SessionHandler.h | 42 ++ cpp/src/qpid/io/SessionHandlerFactory.h | 38 ++ cpp/src/qpid/io/SessionManager.h | 40 ++ cpp/src/qpid/io/ShutdownHandler.h | 34 ++ cpp/src/qpid/io/TimeoutHandler.h | 36 ++ cpp/src/qpidd.cpp | 48 +++ cpp/test/client/client_test.cpp | 97 +++++ cpp/test/client/topic_listener.cpp | 180 +++++++++ cpp/test/client/topic_publisher.cpp | 253 ++++++++++++ cpp/test/unit/qpid/broker/ChannelTest.cpp | 162 ++++++++ cpp/test/unit/qpid/broker/ExchangeTest.cpp | 65 +++ cpp/test/unit/qpid/broker/HeadersExchangeTest.cpp | 112 ++++++ cpp/test/unit/qpid/broker/Makefile | 20 + cpp/test/unit/qpid/broker/MessageTest.cpp | 54 +++ cpp/test/unit/qpid/broker/QueueRegistryTest.cpp | 76 ++++ cpp/test/unit/qpid/broker/QueueTest.cpp | 176 +++++++++ cpp/test/unit/qpid/broker/RouterTest.cpp | 86 ++++ cpp/test/unit/qpid/broker/TopicExchangeTest.cpp | 184 +++++++++ cpp/test/unit/qpid/broker/ValueTest.cpp | 96 +++++ cpp/test/unit/qpid/framing/BodyHandlerTest.cpp | 103 +++++ cpp/test/unit/qpid/framing/Makefile | 21 + cpp/test/unit/qpid/framing/field_table_test.cpp | 52 +++ cpp/test/unit/qpid/framing/framing_test.cpp | 144 +++++++ cpp/test/unit/qpid/framing/header_test.cpp | 141 +++++++ cpp/test_plugins.mk | 42 -- 370 files changed, 15607 insertions(+), 15940 deletions(-) delete mode 100644 cpp/broker/Makefile delete mode 100644 cpp/broker/inc/AutoDelete.h delete mode 100644 cpp/broker/inc/Binding.h delete mode 100644 cpp/broker/inc/Broker.h delete mode 100644 cpp/broker/inc/Channel.h delete mode 100644 cpp/broker/inc/Configuration.h delete mode 100644 cpp/broker/inc/ConnectionToken.h delete mode 100644 cpp/broker/inc/Consumer.h delete mode 100644 cpp/broker/inc/DirectExchange.h delete mode 100644 cpp/broker/inc/Exchange.h delete mode 100644 cpp/broker/inc/ExchangeBinding.h delete mode 100644 cpp/broker/inc/ExchangeRegistry.h delete mode 100644 cpp/broker/inc/FanOutExchange.h delete mode 100644 cpp/broker/inc/HeadersExchange.h delete mode 100644 cpp/broker/inc/Message.h delete mode 100644 cpp/broker/inc/NameGenerator.h delete mode 100644 cpp/broker/inc/Queue.h delete mode 100644 cpp/broker/inc/QueueRegistry.h delete mode 100644 cpp/broker/inc/Router.h delete mode 100644 cpp/broker/inc/SessionHandlerFactoryImpl.h delete mode 100644 cpp/broker/inc/SessionHandlerImpl.h delete mode 100644 cpp/broker/inc/TopicExchange.h delete mode 100644 cpp/broker/src/AutoDelete.cpp delete mode 100644 cpp/broker/src/Broker.cpp delete mode 100644 cpp/broker/src/Channel.cpp delete mode 100644 cpp/broker/src/Configuration.cpp delete mode 100644 cpp/broker/src/DirectExchange.cpp delete mode 100644 cpp/broker/src/ExchangeBinding.cpp delete mode 100644 cpp/broker/src/ExchangeRegistry.cpp delete mode 100644 cpp/broker/src/FanOutExchange.cpp delete mode 100644 cpp/broker/src/HeadersExchange.cpp delete mode 100644 cpp/broker/src/Message.cpp delete mode 100644 cpp/broker/src/NameGenerator.cpp delete mode 100644 cpp/broker/src/Queue.cpp delete mode 100644 cpp/broker/src/QueueRegistry.cpp delete mode 100644 cpp/broker/src/Router.cpp delete mode 100644 cpp/broker/src/SessionHandlerFactoryImpl.cpp delete mode 100644 cpp/broker/src/SessionHandlerImpl.cpp delete mode 100644 cpp/broker/src/TopicExchange.cpp delete mode 100644 cpp/broker/test/ChannelTest.cpp delete mode 100644 cpp/broker/test/ExchangeTest.cpp delete mode 100644 cpp/broker/test/HeadersExchangeTest.cpp delete mode 100644 cpp/broker/test/Makefile delete mode 100644 cpp/broker/test/MessageTest.cpp delete mode 100644 cpp/broker/test/QueueRegistryTest.cpp delete mode 100644 cpp/broker/test/QueueTest.cpp delete mode 100644 cpp/broker/test/RouterTest.cpp delete mode 100644 cpp/broker/test/TopicExchangeTest.cpp delete mode 100644 cpp/broker/test/ValueTest.cpp delete mode 100644 cpp/client/Makefile delete mode 100644 cpp/client/inc/Channel.h delete mode 100644 cpp/client/inc/Connection.h delete mode 100644 cpp/client/inc/Exchange.h delete mode 100644 cpp/client/inc/IncomingMessage.h delete mode 100644 cpp/client/inc/Message.h delete mode 100644 cpp/client/inc/MessageListener.h delete mode 100644 cpp/client/inc/Queue.h delete mode 100644 cpp/client/inc/ResponseHandler.h delete mode 100644 cpp/client/inc/ReturnedMessageHandler.h delete mode 100644 cpp/client/src/Channel.cpp delete mode 100644 cpp/client/src/Connection.cpp delete mode 100644 cpp/client/src/Exchange.cpp delete mode 100644 cpp/client/src/IncomingMessage.cpp delete mode 100644 cpp/client/src/Message.cpp delete mode 100644 cpp/client/src/MessageListener.cpp delete mode 100644 cpp/client/src/Queue.cpp delete mode 100644 cpp/client/src/ResponseHandler.cpp delete mode 100644 cpp/client/src/ReturnedMessageHandler.cpp delete mode 100644 cpp/client/test/Makefile delete mode 100644 cpp/client/test/client_test.cpp delete mode 100644 cpp/client/test/topic_listener.cpp delete mode 100644 cpp/client/test/topic_publisher.cpp delete mode 100644 cpp/common/Makefile delete mode 100644 cpp/common/concurrent/inc/APRBase.h delete mode 100644 cpp/common/concurrent/inc/APRMonitor.h delete mode 100644 cpp/common/concurrent/inc/APRThread.h delete mode 100644 cpp/common/concurrent/inc/APRThreadFactory.h delete mode 100644 cpp/common/concurrent/inc/APRThreadPool.h delete mode 100644 cpp/common/concurrent/inc/LMonitor.h delete mode 100644 cpp/common/concurrent/inc/LThreadFactory.h delete mode 100644 cpp/common/concurrent/inc/LockedQueue.h delete mode 100644 cpp/common/concurrent/inc/Monitor.h delete mode 100644 cpp/common/concurrent/inc/MonitorImpl.h delete mode 100644 cpp/common/concurrent/inc/Runnable.h delete mode 100644 cpp/common/concurrent/inc/TaskQueue.h delete mode 100644 cpp/common/concurrent/inc/Thread.h delete mode 100644 cpp/common/concurrent/inc/ThreadFactory.h delete mode 100644 cpp/common/concurrent/inc/ThreadFactoryImpl.h delete mode 100644 cpp/common/concurrent/inc/ThreadPool.h delete mode 100644 cpp/common/concurrent/src/APRBase.cpp delete mode 100644 cpp/common/concurrent/src/APRMonitor.cpp delete mode 100644 cpp/common/concurrent/src/APRThread.cpp delete mode 100644 cpp/common/concurrent/src/APRThreadFactory.cpp delete mode 100644 cpp/common/concurrent/src/APRThreadPool.cpp delete mode 100644 cpp/common/concurrent/src/Runnable.cpp delete mode 100644 cpp/common/error/inc/Exception.h delete mode 100644 cpp/common/error/inc/QpidError.h delete mode 100644 cpp/common/error/src/Exception.cpp delete mode 100644 cpp/common/error/src/QpidError.cpp delete mode 100644 cpp/common/framing/Makefile delete mode 100644 cpp/common/framing/generated/Makefile delete mode 100644 cpp/common/framing/generated/stylesheets/amqp_client.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/amqp_client_handler_impl.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/amqp_client_operations.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/amqp_consts.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/amqp_server.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/amqp_server_handler_impl.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/amqp_server_operations.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/code_gen.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/code_utils.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/convert_0.81.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/cpp.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/framing.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/prepare1.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/prepare2.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/prepare3.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/registry.xsl delete mode 100644 cpp/common/framing/generated/stylesheets/utils.xsl delete mode 100644 cpp/common/framing/inc/AMQBody.h delete mode 100644 cpp/common/framing/inc/AMQContentBody.h delete mode 100644 cpp/common/framing/inc/AMQDataBlock.h delete mode 100644 cpp/common/framing/inc/AMQFrame.h delete mode 100644 cpp/common/framing/inc/AMQHeaderBody.h delete mode 100644 cpp/common/framing/inc/AMQHeartbeatBody.h delete mode 100644 cpp/common/framing/inc/AMQMethodBody.h delete mode 100644 cpp/common/framing/inc/BasicHeaderProperties.h delete mode 100644 cpp/common/framing/inc/BodyHandler.h delete mode 100644 cpp/common/framing/inc/Buffer.h delete mode 100644 cpp/common/framing/inc/FieldTable.h delete mode 100644 cpp/common/framing/inc/HeaderProperties.h delete mode 100644 cpp/common/framing/inc/InitiationHandler.h delete mode 100644 cpp/common/framing/inc/InputHandler.h delete mode 100644 cpp/common/framing/inc/OutputHandler.h delete mode 100644 cpp/common/framing/inc/ProtocolInitiation.h delete mode 100644 cpp/common/framing/inc/Value.h delete mode 100644 cpp/common/framing/inc/amqp_framing.h delete mode 100644 cpp/common/framing/inc/amqp_types.h delete mode 100644 cpp/common/framing/src/AMQBody.cpp delete mode 100644 cpp/common/framing/src/AMQContentBody.cpp delete mode 100644 cpp/common/framing/src/AMQFrame.cpp delete mode 100644 cpp/common/framing/src/AMQHeaderBody.cpp delete mode 100644 cpp/common/framing/src/AMQHeartbeatBody.cpp delete mode 100644 cpp/common/framing/src/AMQMethodBody.cpp delete mode 100644 cpp/common/framing/src/BasicHeaderProperties.cpp delete mode 100644 cpp/common/framing/src/BodyHandler.cpp delete mode 100644 cpp/common/framing/src/Buffer.cpp delete mode 100644 cpp/common/framing/src/FieldTable.cpp delete mode 100644 cpp/common/framing/src/InitiationHandler.cpp delete mode 100644 cpp/common/framing/src/InputHandler.cpp delete mode 100644 cpp/common/framing/src/OutputHandler.cpp delete mode 100644 cpp/common/framing/src/ProtocolInitiation.cpp delete mode 100644 cpp/common/framing/src/Value.cpp delete mode 100644 cpp/common/framing/test/BodyHandlerTest.cpp delete mode 100644 cpp/common/framing/test/Makefile delete mode 100644 cpp/common/framing/test/field_table_test.cpp delete mode 100644 cpp/common/framing/test/framing_test.cpp delete mode 100644 cpp/common/framing/test/header_test.cpp delete mode 100644 cpp/common/io/Makefile delete mode 100644 cpp/common/io/inc/APRConnector.h delete mode 100644 cpp/common/io/inc/APRSocket.h delete mode 100644 cpp/common/io/inc/Acceptor.h delete mode 100644 cpp/common/io/inc/BlockingAPRAcceptor.h delete mode 100644 cpp/common/io/inc/BlockingAPRSessionContext.h delete mode 100644 cpp/common/io/inc/Connector.h delete mode 100644 cpp/common/io/inc/ConnectorImpl.h delete mode 100644 cpp/common/io/inc/LConnector.h delete mode 100644 cpp/common/io/inc/LFAcceptor.h delete mode 100644 cpp/common/io/inc/LFProcessor.h delete mode 100644 cpp/common/io/inc/LFSessionContext.h delete mode 100644 cpp/common/io/inc/SessionContext.h delete mode 100644 cpp/common/io/inc/SessionHandler.h delete mode 100644 cpp/common/io/inc/SessionHandlerFactory.h delete mode 100644 cpp/common/io/inc/SessionManager.h delete mode 100644 cpp/common/io/inc/ShutdownHandler.h delete mode 100644 cpp/common/io/inc/TimeoutHandler.h delete mode 100644 cpp/common/io/src/APRConnector.cpp delete mode 100644 cpp/common/io/src/APRSocket.cpp delete mode 100644 cpp/common/io/src/Acceptor.cpp delete mode 100644 cpp/common/io/src/BlockingAPRAcceptor.cpp delete mode 100644 cpp/common/io/src/BlockingAPRSessionContext.cpp delete mode 100644 cpp/common/io/src/LFAcceptor.cpp delete mode 100644 cpp/common/io/src/LFProcessor.cpp delete mode 100644 cpp/common/io/src/LFSessionContext.cpp delete mode 100644 cpp/common/utils/inc/memory.h delete mode 100644 cpp/common/utils/src/Makefile create mode 100644 cpp/etc/stylesheets/amqp_client.xsl create mode 100644 cpp/etc/stylesheets/amqp_client_handler_impl.xsl create mode 100644 cpp/etc/stylesheets/amqp_client_operations.xsl create mode 100644 cpp/etc/stylesheets/amqp_consts.xsl create mode 100644 cpp/etc/stylesheets/amqp_server.xsl create mode 100644 cpp/etc/stylesheets/amqp_server_handler_impl.xsl create mode 100644 cpp/etc/stylesheets/amqp_server_operations.xsl create mode 100644 cpp/etc/stylesheets/code_gen.xsl create mode 100644 cpp/etc/stylesheets/code_utils.xsl create mode 100644 cpp/etc/stylesheets/convert_0.81.xsl create mode 100644 cpp/etc/stylesheets/cpp.xsl create mode 100644 cpp/etc/stylesheets/framing.xsl create mode 100644 cpp/etc/stylesheets/prepare1.xsl create mode 100644 cpp/etc/stylesheets/prepare2.xsl create mode 100644 cpp/etc/stylesheets/prepare3.xsl create mode 100644 cpp/etc/stylesheets/registry.xsl create mode 100644 cpp/etc/stylesheets/utils.xsl delete mode 100644 cpp/qpidd/Makefile delete mode 100644 cpp/qpidd/src/qpidd.cpp create mode 100644 cpp/src/memory.h create mode 100644 cpp/src/qpid/Exception.cpp create mode 100644 cpp/src/qpid/Exception.h create mode 100644 cpp/src/qpid/QpidError.cpp create mode 100644 cpp/src/qpid/QpidError.h create mode 100644 cpp/src/qpid/broker/AutoDelete.cpp create mode 100644 cpp/src/qpid/broker/AutoDelete.h create mode 100644 cpp/src/qpid/broker/Binding.h create mode 100644 cpp/src/qpid/broker/Broker.cpp create mode 100644 cpp/src/qpid/broker/Broker.h create mode 100644 cpp/src/qpid/broker/Channel.cpp create mode 100644 cpp/src/qpid/broker/Channel.h create mode 100644 cpp/src/qpid/broker/Configuration.cpp create mode 100644 cpp/src/qpid/broker/Configuration.h create mode 100644 cpp/src/qpid/broker/ConnectionToken.h create mode 100644 cpp/src/qpid/broker/Consumer.h create mode 100644 cpp/src/qpid/broker/DirectExchange.cpp create mode 100644 cpp/src/qpid/broker/DirectExchange.h create mode 100644 cpp/src/qpid/broker/Exchange.h create mode 100644 cpp/src/qpid/broker/ExchangeBinding.cpp create mode 100644 cpp/src/qpid/broker/ExchangeBinding.h create mode 100644 cpp/src/qpid/broker/ExchangeRegistry.cpp create mode 100644 cpp/src/qpid/broker/ExchangeRegistry.h create mode 100644 cpp/src/qpid/broker/FanOutExchange.cpp create mode 100644 cpp/src/qpid/broker/FanOutExchange.h create mode 100644 cpp/src/qpid/broker/HeadersExchange.cpp create mode 100644 cpp/src/qpid/broker/HeadersExchange.h create mode 100644 cpp/src/qpid/broker/Message.cpp create mode 100644 cpp/src/qpid/broker/Message.h create mode 100644 cpp/src/qpid/broker/NameGenerator.cpp create mode 100644 cpp/src/qpid/broker/NameGenerator.h create mode 100644 cpp/src/qpid/broker/Queue.cpp create mode 100644 cpp/src/qpid/broker/Queue.h create mode 100644 cpp/src/qpid/broker/QueueRegistry.cpp create mode 100644 cpp/src/qpid/broker/QueueRegistry.h create mode 100644 cpp/src/qpid/broker/Router.cpp create mode 100644 cpp/src/qpid/broker/Router.h create mode 100644 cpp/src/qpid/broker/SessionHandlerFactoryImpl.cpp create mode 100644 cpp/src/qpid/broker/SessionHandlerFactoryImpl.h create mode 100644 cpp/src/qpid/broker/SessionHandlerImpl.cpp create mode 100644 cpp/src/qpid/broker/SessionHandlerImpl.h create mode 100644 cpp/src/qpid/broker/TopicExchange.cpp create mode 100644 cpp/src/qpid/broker/TopicExchange.h create mode 100644 cpp/src/qpid/client/Channel.cpp create mode 100644 cpp/src/qpid/client/Channel.h create mode 100644 cpp/src/qpid/client/Connection.cpp create mode 100644 cpp/src/qpid/client/Connection.h create mode 100644 cpp/src/qpid/client/Exchange.cpp create mode 100644 cpp/src/qpid/client/Exchange.h create mode 100644 cpp/src/qpid/client/IncomingMessage.cpp create mode 100644 cpp/src/qpid/client/IncomingMessage.h create mode 100644 cpp/src/qpid/client/Message.cpp create mode 100644 cpp/src/qpid/client/Message.h create mode 100644 cpp/src/qpid/client/MessageListener.cpp create mode 100644 cpp/src/qpid/client/MessageListener.h create mode 100644 cpp/src/qpid/client/Queue.cpp create mode 100644 cpp/src/qpid/client/Queue.h create mode 100644 cpp/src/qpid/client/ResponseHandler.cpp create mode 100644 cpp/src/qpid/client/ResponseHandler.h create mode 100644 cpp/src/qpid/client/ReturnedMessageHandler.cpp create mode 100644 cpp/src/qpid/client/ReturnedMessageHandler.h create mode 100644 cpp/src/qpid/concurrent/APRBase.cpp create mode 100644 cpp/src/qpid/concurrent/APRBase.h create mode 100644 cpp/src/qpid/concurrent/APRMonitor.cpp create mode 100644 cpp/src/qpid/concurrent/APRMonitor.h create mode 100644 cpp/src/qpid/concurrent/APRThread.cpp create mode 100644 cpp/src/qpid/concurrent/APRThread.h create mode 100644 cpp/src/qpid/concurrent/APRThreadFactory.cpp create mode 100644 cpp/src/qpid/concurrent/APRThreadFactory.h create mode 100644 cpp/src/qpid/concurrent/APRThreadPool.cpp create mode 100644 cpp/src/qpid/concurrent/APRThreadPool.h create mode 100644 cpp/src/qpid/concurrent/LMonitor.h create mode 100644 cpp/src/qpid/concurrent/LThreadFactory.h create mode 100644 cpp/src/qpid/concurrent/LockedQueue.h create mode 100644 cpp/src/qpid/concurrent/Monitor.h create mode 100644 cpp/src/qpid/concurrent/MonitorImpl.h create mode 100644 cpp/src/qpid/concurrent/Runnable.cpp create mode 100644 cpp/src/qpid/concurrent/Runnable.h create mode 100644 cpp/src/qpid/concurrent/TaskQueue.h create mode 100644 cpp/src/qpid/concurrent/Thread.h create mode 100644 cpp/src/qpid/concurrent/ThreadFactory.h create mode 100644 cpp/src/qpid/concurrent/ThreadFactoryImpl.h create mode 100644 cpp/src/qpid/concurrent/ThreadPool.h create mode 100644 cpp/src/qpid/framing/AMQBody.cpp create mode 100644 cpp/src/qpid/framing/AMQBody.h create mode 100644 cpp/src/qpid/framing/AMQContentBody.cpp create mode 100644 cpp/src/qpid/framing/AMQContentBody.h create mode 100644 cpp/src/qpid/framing/AMQDataBlock.h create mode 100644 cpp/src/qpid/framing/AMQFrame.cpp create mode 100644 cpp/src/qpid/framing/AMQFrame.h create mode 100644 cpp/src/qpid/framing/AMQHeaderBody.cpp create mode 100644 cpp/src/qpid/framing/AMQHeaderBody.h create mode 100644 cpp/src/qpid/framing/AMQHeartbeatBody.cpp create mode 100644 cpp/src/qpid/framing/AMQHeartbeatBody.h create mode 100644 cpp/src/qpid/framing/AMQMethodBody.cpp create mode 100644 cpp/src/qpid/framing/AMQMethodBody.h create mode 100644 cpp/src/qpid/framing/BasicHeaderProperties.cpp create mode 100644 cpp/src/qpid/framing/BasicHeaderProperties.h create mode 100644 cpp/src/qpid/framing/BodyHandler.cpp create mode 100644 cpp/src/qpid/framing/BodyHandler.h create mode 100644 cpp/src/qpid/framing/Buffer.cpp create mode 100644 cpp/src/qpid/framing/Buffer.h create mode 100644 cpp/src/qpid/framing/FieldTable.cpp create mode 100644 cpp/src/qpid/framing/FieldTable.h create mode 100644 cpp/src/qpid/framing/HeaderProperties.h create mode 100644 cpp/src/qpid/framing/InitiationHandler.cpp create mode 100644 cpp/src/qpid/framing/InitiationHandler.h create mode 100644 cpp/src/qpid/framing/InputHandler.cpp create mode 100644 cpp/src/qpid/framing/InputHandler.h create mode 100644 cpp/src/qpid/framing/OutputHandler.cpp create mode 100644 cpp/src/qpid/framing/OutputHandler.h create mode 100644 cpp/src/qpid/framing/ProtocolInitiation.cpp create mode 100644 cpp/src/qpid/framing/ProtocolInitiation.h create mode 100644 cpp/src/qpid/framing/Value.cpp create mode 100644 cpp/src/qpid/framing/Value.h create mode 100644 cpp/src/qpid/framing/amqp_framing.h create mode 100644 cpp/src/qpid/framing/amqp_types.h create mode 100644 cpp/src/qpid/io/APRConnector.cpp create mode 100644 cpp/src/qpid/io/APRConnector.h create mode 100644 cpp/src/qpid/io/APRSocket.cpp create mode 100644 cpp/src/qpid/io/APRSocket.h create mode 100644 cpp/src/qpid/io/Acceptor.cpp create mode 100644 cpp/src/qpid/io/Acceptor.h create mode 100644 cpp/src/qpid/io/BlockingAPRAcceptor.cpp create mode 100644 cpp/src/qpid/io/BlockingAPRAcceptor.h create mode 100644 cpp/src/qpid/io/BlockingAPRSessionContext.cpp create mode 100644 cpp/src/qpid/io/BlockingAPRSessionContext.h create mode 100644 cpp/src/qpid/io/Connector.h create mode 100644 cpp/src/qpid/io/ConnectorImpl.h create mode 100644 cpp/src/qpid/io/LConnector.h create mode 100644 cpp/src/qpid/io/LFAcceptor.cpp create mode 100644 cpp/src/qpid/io/LFAcceptor.h create mode 100644 cpp/src/qpid/io/LFProcessor.cpp create mode 100644 cpp/src/qpid/io/LFProcessor.h create mode 100644 cpp/src/qpid/io/LFSessionContext.cpp create mode 100644 cpp/src/qpid/io/LFSessionContext.h create mode 100644 cpp/src/qpid/io/SessionContext.h create mode 100644 cpp/src/qpid/io/SessionHandler.h create mode 100644 cpp/src/qpid/io/SessionHandlerFactory.h create mode 100644 cpp/src/qpid/io/SessionManager.h create mode 100644 cpp/src/qpid/io/ShutdownHandler.h create mode 100644 cpp/src/qpid/io/TimeoutHandler.h create mode 100644 cpp/src/qpidd.cpp create mode 100644 cpp/test/client/client_test.cpp create mode 100644 cpp/test/client/topic_listener.cpp create mode 100644 cpp/test/client/topic_publisher.cpp create mode 100644 cpp/test/unit/qpid/broker/ChannelTest.cpp create mode 100644 cpp/test/unit/qpid/broker/ExchangeTest.cpp create mode 100644 cpp/test/unit/qpid/broker/HeadersExchangeTest.cpp create mode 100644 cpp/test/unit/qpid/broker/Makefile create mode 100644 cpp/test/unit/qpid/broker/MessageTest.cpp create mode 100644 cpp/test/unit/qpid/broker/QueueRegistryTest.cpp create mode 100644 cpp/test/unit/qpid/broker/QueueTest.cpp create mode 100644 cpp/test/unit/qpid/broker/RouterTest.cpp create mode 100644 cpp/test/unit/qpid/broker/TopicExchangeTest.cpp create mode 100644 cpp/test/unit/qpid/broker/ValueTest.cpp create mode 100644 cpp/test/unit/qpid/framing/BodyHandlerTest.cpp create mode 100644 cpp/test/unit/qpid/framing/Makefile create mode 100644 cpp/test/unit/qpid/framing/field_table_test.cpp create mode 100644 cpp/test/unit/qpid/framing/framing_test.cpp create mode 100644 cpp/test/unit/qpid/framing/header_test.cpp delete mode 100644 cpp/test_plugins.mk (limited to 'cpp') diff --git a/cpp/DESIGN b/cpp/DESIGN index 476fd42bfa..7e9ba6755c 100644 --- a/cpp/DESIGN +++ b/cpp/DESIGN @@ -1,37 +1,27 @@ Qpid C++ AMQP implementation ============================= -The following is a brief description of the logical design of the -Qpid C++ code. += Project layout = -Layout +For Build system design see comment at start of Makefile. -There are three top level modules. The first two, client and broker, -containi the code required for an AMQP client and an AMQP broker -respectively. The third, common, contains code that is common to both -client and broker implementations. [Note that at present only the -client has been started]. +Project contains: + * Client library (lib/libqpid_client): src/qpid/client + * Broker library (lib/libqpid_broker): src/qpid/broker + * Common classes + * src/qpid/concurrent: concurrecy + * src/qpid/framing: wire encoding/decoding + * src/qpid/io: reading/writing + * src/qpid/Exception.cpp, QpidError.cpp: Exception classes. + * Qpid Daemon (bin/qpidd): src/qpidd.cpp -Within the common module there are currently four sub-modules. The -largest of these is framing, containing the definitions of classes -corresponding to key AMQP concepts such as frames, content & header -bodies, particular method bodies etc as well as some interfaces and -utilities used in the encoding and decoding of the wire protocol. +Unit tests in test/unit: each *Test.cpp builds a CppUnit plugin. -Two of the other sub-modules in common, io and concurrent, provide -abstractions of core io and concurrency constructs used in the client -and broker code. The intention is to allow these to be implemented in -different ways.interaction with the wire protocol. At present the -implementation of the io and concurrency abstractions is based on APR -(Apache Portable Runtime). [Note: the io module currently only -contains the abstractions as seen from the client - the Connector. It -will in due time likely have the analogous broker-side abstraction - -the Acceptor]. +Client tests in test/client: each *.cpp builds a test executable. -The final common sub-module is error, containing a simple exception -definition used in all the error handling. +Test utilities: test/include -Client Design += Client Design = The client module is primarily concerned with presenting the functionality offered by AMQP to users through a simple API that diff --git a/cpp/Makefile b/cpp/Makefile index 529ac1568f..586a934cce 100644 --- a/cpp/Makefile +++ b/cpp/Makefile @@ -13,37 +13,125 @@ # See the License for the specific language governing permissions and # limitations under the License. +# ---------------------------------------------------------------- # -# Master make file for c++ Qpid project (AMQP) +# Makefile for Qpid C++ project. +# +# Build system principles +# * Single Makefile (see http://www.apache.org/licenses/LICENSE-2.0) +# * Build from directories, no explicit source lists in Makefile. +# * Corresponding .cpp and .h files in same directory for easy editing. +# * Source directory structure mirrors C++ namespaces. # -# Calls the makefiles in the various subdirectories in order to -# build them in the correct sequence. +# Source directories: +# * src/ - .h and .cpp source files, directories mirror namespaces. +# * test/ +# * unit/ - unit tests (cppunit plugins), directories mirror namespaces. +# * include/ - .h files used by tests +# * client/ - sources for client test executables. +# * etc/ - Non-c++ resources, e.g. stylesheets. +# * gen/ - generated code # +# Output directories: +# * gen/ - (created by make) generated code +# * bin/ lib/ - exes & libraries. +# +# NOTE: always use := rather than = unless you have a specific need +# for delayed evaluation. See the link for details. +# + +include options.mk + +.PHONY: test all unittest pythontest + +test: all unittest pythontest + +## Generaged code + +SPEC := $(CURDIR)/../specs/amqp-8.0.xml +XSL := code_gen.xsl framing.xsl +STYLESHEETS := $(XSL:%=$(CURDIR)/etc/stylesheets/%) +TRANSFORM := java -jar $(CURDIR)/tools/saxon8.jar -o results.out $(SPEC) + +.PHONY: generate + +generate: gen/timestamp + +# Restart make if code is re-generated to get proper dependencies. +# Remove "clean" to avoid infinite loop. +REMAKE := exec $(MAKE) $(MAKECMDGOALS:clean=) +gen/timestamp: $(wildcard etc/stylesheets/*.xsl) $(SPEC) + mkdir -p gen/qpid/framing + echo > gen/timestamp + cd gen/qpid/framing && for s in $(STYLESHEETS) ; do $(TRANSFORM) $$s ; done + @echo "*** Re-generated code, re-starting make ***" + $(REMAKE) + +gen $(wildcard gen/qpid/framing/*.cpp): gen/timestamp + +## Libraries + +# Library command, late evaluated for $@ +LIB_CMD = $(CXX) -shared -o $@ $(LDFLAGS) $(CXXFLAGS) -lapr-1 + +# Common library. +COMMON_LIB := lib/libqpid_common.so.1.0 +COMMON_DIRS := qpid/concurrent qpid/framing qpid/io qpid +COMMON_SRC := $(wildcard gen/qpid/framing/*.cpp $(COMMON_DIRS:%=src/%/*.cpp)) +$(COMMON_LIB): generate $(COMMON_SRC:.cpp=.o) + $(LIB_CMD) $(COMMON_SRC:.cpp=.o) +all: $(COMMON_LIB) +UNITTESTS := $(UNITTESTS) $(wildcard $(COMMON_DIRS:%=test/unit/%/*Test.cpp)) + +# Client library. +CLIENT_LIB := lib/libqpid_client.so.1.0 +CLIENT_SRC := $(wildcard src/qpid/client/*.cpp) +$(CLIENT_LIB): $(CLIENT_SRC:.cpp=.o) $(COMMON_LIB) + $(LIB_CMD) $^ +all: $(CLIENT_LIB) +UNITTESTS := $(UNITTESTS) $(wildcard $(COMMON_DIRS:%=test/unit/%/*Test.cpp)) + +# Broker library. +BROKER_LIB := lib/libqpid_broker.so.1.0 +BROKER_SRC := $(wildcard src/qpid/broker/*.cpp) +$(BROKER_LIB): $(BROKER_SRC:.cpp=.o) $(COMMON_LIB) + $(LIB_CMD) $^ +all: $(BROKER_LIB) +UNITTESTS := $(UNITTESTS) $(wildcard test/unit/qpid/broker/*Test.cpp) + +# Implicit rule for unit test plugin libraries. +%Test.so: %Test.cpp + $(CXX) -shared -o $@ $< $($(LIB)_FLAGS) -Itest/include $(CXXFLAGS) $(LDFLAGS) -lapr-1 -lcppunit $(COMMON_LIB) $(BROKER_LIB) + +## Client tests -UNITTESTS=$(wildcard common/*/test/*.so broker/test/*.so) -SUBDIRS=common broker qpidd client +all: $(wildcard test/client/*.cpp:.cpp=) +test/client/%: test/client/%.cpp + $(CXX) -o $@ $< $($(LIB)_FLAGS) -Itest/include $(CXXFLAGS) $(LDFLAGS) -lapr-1 $(LINK_WITH_$(LIB)) $(LINK_WITH_$(LIB)_DEPS) -.PHONY: all test unittest pythontest runtests clean doxygen +## Daemon executable -test: all runtests +bin/qpidd: src/qpidd.o $(COMMON_LIB) $(BROKER_LIB) + $(CXX) -o $@ $(LDFLAGS) -lapr-1 $^ +all: bin/qpidd -unittest: - DllPlugInTester -c -b $(UNITTESTS) +## Run unit tests. +unittest: $(UNITTESTS:.cpp=.so) + DllPlugInTester -c -b $(UNITTESTS:.cpp=.so) -pythontest: - bin/qpidd >> qpidd.log & +## Run python tests +pythontest: bin/qpidd + bin/qpidd > qpidd.log & cd ../python ; ./run-tests -v -I cpp_failing.txt -runtests: - $(MAKE) -k unittest pythontest +## Doxygen documentation. +doxygen: doxygen/doxygen.cfg $(SOURCES) + cd doxygen && doxygen doxygen.cfg -all: - @for DIR in $(SUBDIRS) ; do $(MAKE) -C $$DIR all ; done +## Cleanup +clean:: + rm -f bin/* lib/* qpidd.log + rm -rf gen + rm -f `find src test -name '*.o' -o -name '*.d' -o -name '*.so'` -clean: - @for DIR in $(SUBDIRS) ; do $(MAKE) -C $$DIR clean ; done - @$(MAKE) -C doxygen clean - -@rm qpidd.log -doxygen: - @$(MAKE) -C doxygen all diff --git a/cpp/README b/cpp/README index edd80a1fbc..47f1590c7a 100644 --- a/cpp/README +++ b/cpp/README @@ -1,5 +1,7 @@ = Developer guide to C++ codebase = +See DESIGN for design notes, Makefile comment for build system notes. + == Prerequisites == Apache Portable Runtime 1.2.7: http://apr.apache.org/ diff --git a/cpp/broker/Makefile b/cpp/broker/Makefile deleted file mode 100644 index 5c96589d95..0000000000 --- a/cpp/broker/Makefile +++ /dev/null @@ -1,39 +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. -# - -# -# Build broker library. -# - -QPID_HOME = ../.. -include ${QPID_HOME}/cpp/options.mk -TARGET=$(BROKER_LIB) -SOURCES= $(wildcard src/*.cpp) -OBJECTS= $(subst .cpp,.o,$(SOURCES)) - -.PHONY: all clean - -all: $(TARGET) - @$(MAKE) -C test all - -clean: - -@rm -f $(TARGET) ${OBJECTS} src/*.d - @$(MAKE) -C test clean - -$(TARGET): $(OBJECTS) - $(CXX) -shared -o $@ $(LDFLAGS) $(OBJECTS) -lapr-1 $(COMMON_LIB) $(LIBDIR) - --include $(SOURCES:.cpp=.d) diff --git a/cpp/broker/inc/AutoDelete.h b/cpp/broker/inc/AutoDelete.h deleted file mode 100644 index 864d68358f..0000000000 --- a/cpp/broker/inc/AutoDelete.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _AutoDelete_ -#define _AutoDelete_ - -#include -#include -#include "MonitorImpl.h" -#include "Queue.h" -#include "QueueRegistry.h" -#include "ThreadFactoryImpl.h" - -namespace qpid { - namespace broker{ - class AutoDelete : private virtual qpid::concurrent::Runnable{ - qpid::concurrent::ThreadFactoryImpl factory; - qpid::concurrent::MonitorImpl lock; - qpid::concurrent::MonitorImpl monitor; - std::queue queues; - QueueRegistry* const registry; - const u_int32_t period; - volatile bool stopped; - qpid::concurrent::Thread* runner; - - Queue::shared_ptr const pop(); - void process(); - virtual void run(); - - public: - AutoDelete(QueueRegistry* const registry, u_int32_t period); - void add(Queue::shared_ptr const); - void start(); - void stop(); - }; - } -} - - -#endif diff --git a/cpp/broker/inc/Binding.h b/cpp/broker/inc/Binding.h deleted file mode 100644 index b11419e92c..0000000000 --- a/cpp/broker/inc/Binding.h +++ /dev/null @@ -1,35 +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. - * - */ -#ifndef _Binding_ -#define _Binding_ - -#include "FieldTable.h" - -namespace qpid { - namespace broker { - class Binding{ - public: - virtual void cancel() = 0; - virtual ~Binding(){} - }; - } -} - - -#endif - diff --git a/cpp/broker/inc/Broker.h b/cpp/broker/inc/Broker.h deleted file mode 100644 index 0cd2bd749e..0000000000 --- a/cpp/broker/inc/Broker.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef _Broker_ -#define _Broker_ - -/* - * - * 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 "Acceptor.h" -#include "Configuration.h" -#include "Runnable.h" -#include "SessionHandlerFactoryImpl.h" -#include -#include - -namespace qpid { - namespace broker { - /** - * A broker instance. - */ - class Broker : public qpid::concurrent::Runnable, private boost::noncopyable { - Broker(const Configuration& config); // Private, use create() - std::auto_ptr acceptor; - SessionHandlerFactoryImpl factory; - int16_t port; - bool isBound; - - public: - static const int16_t DEFAULT_PORT; - - virtual ~Broker(); - typedef std::tr1::shared_ptr shared_ptr; - - /** - * Create a broker. - * @param port Port to listen on or 0 to pick a port dynamically. - */ - static shared_ptr create(int port = DEFAULT_PORT); - - /** - * Create a broker from a Configuration. - */ - static shared_ptr create(const Configuration& config); - - /** - * Bind to the listening port. - * @return The port number bound. - */ - virtual int16_t bind(); - - /** - * 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() { return port; } - - /** - * 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(); - }; - } -} - - - -#endif /*!_Broker_*/ diff --git a/cpp/broker/inc/Channel.h b/cpp/broker/inc/Channel.h deleted file mode 100644 index 862d249ce1..0000000000 --- a/cpp/broker/inc/Channel.h +++ /dev/null @@ -1,199 +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. - * - */ -#ifndef _Channel_ -#define _Channel_ - -#include -#include -#include "AMQContentBody.h" -#include "AMQHeaderBody.h" -#include "BasicPublishBody.h" -#include "Binding.h" -#include "Consumer.h" -#include "Message.h" -#include "MonitorImpl.h" -#include "NameGenerator.h" -#include "OutputHandler.h" -#include "Queue.h" - -namespace qpid { - namespace broker { - /** - * Maintains state for an AMQP channel. Handles incoming and - * outgoing messages for that channel. - */ - class Channel{ - private: - class ConsumerImpl : public virtual Consumer{ - Channel* parent; - string tag; - Queue::shared_ptr queue; - ConnectionToken* const connection; - const bool ackExpected; - bool blocked; - public: - ConsumerImpl(Channel* parent, string& tag, Queue::shared_ptr queue, ConnectionToken* const connection, bool ack); - virtual bool deliver(Message::shared_ptr& msg); - void cancel(); - void requestDispatch(); - }; - - typedef std::map::iterator consumer_iterator; - - struct AckRecord{ - Message::shared_ptr msg; - Queue::shared_ptr queue; - string consumerTag; - u_int64_t deliveryTag; - bool pull; - - AckRecord(Message::shared_ptr _msg, - Queue::shared_ptr _queue, - const string _consumerTag, - const u_int64_t _deliveryTag) : msg(_msg), - queue(_queue), - consumerTag(_consumerTag), - deliveryTag(_deliveryTag), - pull(false){} - - AckRecord(Message::shared_ptr _msg, - Queue::shared_ptr _queue, - const u_int64_t _deliveryTag) : msg(_msg), - queue(_queue), - consumerTag(""), - deliveryTag(_deliveryTag), - pull(true){} - }; - - typedef std::vector::iterator ack_iterator; - - class MatchAck{ - const u_int64_t tag; - public: - MatchAck(u_int64_t tag); - bool operator()(AckRecord& record) const; - }; - - class Requeue{ - public: - void operator()(AckRecord& record) const; - }; - - class Redeliver{ - Channel* const channel; - public: - Redeliver(Channel* const channel); - void operator()(AckRecord& record) const; - }; - - class CalculatePrefetch{ - u_int32_t size; - u_int16_t count; - public: - CalculatePrefetch(); - void operator()(AckRecord& record); - u_int32_t getSize(); - u_int16_t getCount(); - }; - - const int id; - qpid::framing::OutputHandler* out; - u_int64_t deliveryTag; - Queue::shared_ptr defaultQueue; - bool transactional; - std::map consumers; - u_int32_t prefetchSize; - u_int16_t prefetchCount; - u_int32_t outstandingSize; - u_int16_t outstandingCount; - u_int32_t framesize; - Message::shared_ptr message; - NameGenerator tagGenerator; - std::vector unacknowledged; - qpid::concurrent::MonitorImpl deliveryLock; - - void deliver(Message::shared_ptr& msg, string& tag, Queue::shared_ptr& queue, bool ackExpected); - void checkMessage(const std::string& text); - bool checkPrefetch(Message::shared_ptr& msg); - void cancel(consumer_iterator consumer); - - template Operation processMessage(Operation route){ - if(message->isComplete()){ - route(message); - message.reset(); - } - return route; - } - - - public: - Channel(qpid::framing::OutputHandler* out, int id, u_int32_t framesize); - ~Channel(); - inline void setDefaultQueue(Queue::shared_ptr queue){ defaultQueue = queue; } - inline Queue::shared_ptr getDefaultQueue(){ return defaultQueue; } - inline u_int32_t setPrefetchSize(u_int32_t size){ return prefetchSize = size; } - inline u_int16_t setPrefetchCount(u_int16_t count){ return prefetchCount = count; } - bool exists(const string& consumerTag); - void consume(string& tag, Queue::shared_ptr queue, bool acks, bool exclusive, ConnectionToken* const connection = 0); - void cancel(const string& tag); - bool get(Queue::shared_ptr queue, bool ackExpected); - void begin(); - void close(); - void commit(); - void rollback(); - void ack(u_int64_t deliveryTag, bool multiple); - void recover(bool requeue); - - /** - * Handles the initial publish request though a - * channel. The header and (if applicable) content will be - * accumulated through calls to handleHeader() and - * handleContent() - */ - void handlePublish(Message* msg); - - /** - * A template method that handles a received header and if - * there is no content routes it using the functor passed - * in. - */ - template Operation handleHeader(qpid::framing::AMQHeaderBody::shared_ptr header, Operation route){ - checkMessage("Invalid message sequence: got header before publish."); - message->setHeader(header); - return processMessage(route); - } - - /** - * A template method that handles a received content and - * if this completes the message, routes it using the - * functor passed in. - */ - template Operation handleContent(qpid::framing::AMQContentBody::shared_ptr content, Operation route){ - checkMessage("Invalid message sequence: got content before publish."); - message->addContent(content); - return processMessage(route); - } - - }; - - struct InvalidAckException{}; - } -} - - -#endif diff --git a/cpp/broker/inc/Configuration.h b/cpp/broker/inc/Configuration.h deleted file mode 100644 index aaabdd23a0..0000000000 --- a/cpp/broker/inc/Configuration.h +++ /dev/null @@ -1,135 +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. - * - */ -#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 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 trace; - IntOption port; - IntOption workerThreads; - IntOption maxConnections; - IntOption connectionBacklog; - StringOption acceptor; - BoolOption help; - - typedef std::vector::iterator op_iterator; - std::vector options; - - public: - class ParseException : public Exception { - public: - ParseException(const std::string& msg) : Exception(msg) {} - }; - - - Configuration(); - ~Configuration(); - - void parse(int argc, char** argv); - - bool isHelp() const; - bool isTrace() const; - int getPort() const; - int getWorkerThreads() const; - int getMaxConnections() const; - int getConnectionBacklog() const; - std::string getAcceptor() const; - - void setHelp(bool b) { help.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 setAcceptor(const std::string& val) { acceptor.setValue(val); } - - void usage(); - }; - } -} - - -#endif diff --git a/cpp/broker/inc/ConnectionToken.h b/cpp/broker/inc/ConnectionToken.h deleted file mode 100644 index 1faefec2cc..0000000000 --- a/cpp/broker/inc/ConnectionToken.h +++ /dev/null @@ -1,35 +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. - * - */ -#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/cpp/broker/inc/Consumer.h b/cpp/broker/inc/Consumer.h deleted file mode 100644 index af2d5d7812..0000000000 --- a/cpp/broker/inc/Consumer.h +++ /dev/null @@ -1,34 +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. - * - */ -#ifndef _Consumer_ -#define _Consumer_ - -#include "Message.h" - -namespace qpid { - namespace broker { - class Consumer{ - public: - virtual bool deliver(Message::shared_ptr& msg) = 0; - virtual ~Consumer(){} - }; - } -} - - -#endif diff --git a/cpp/broker/inc/DirectExchange.h b/cpp/broker/inc/DirectExchange.h deleted file mode 100644 index faf5a0b949..0000000000 --- a/cpp/broker/inc/DirectExchange.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _DirectExchange_ -#define _DirectExchange_ - -#include -#include -#include "Exchange.h" -#include "FieldTable.h" -#include "Message.h" -#include "MonitorImpl.h" -#include "Queue.h" - -namespace qpid { -namespace broker { - class DirectExchange : public virtual Exchange{ - std::map > bindings; - qpid::concurrent::MonitorImpl lock; - - public: - static const std::string typeName; - - DirectExchange(const std::string& name); - - virtual void bind(Queue::shared_ptr queue, const std::string& routingKey, qpid::framing::FieldTable* args); - - virtual void unbind(Queue::shared_ptr queue, const std::string& routingKey, qpid::framing::FieldTable* args); - - virtual void route(Message::shared_ptr& msg, const std::string& routingKey, qpid::framing::FieldTable* args); - - virtual ~DirectExchange(); - }; -} -} - - -#endif diff --git a/cpp/broker/inc/Exchange.h b/cpp/broker/inc/Exchange.h deleted file mode 100644 index 1fdc00fae5..0000000000 --- a/cpp/broker/inc/Exchange.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _Exchange_ -#define _Exchange_ - -#include "FieldTable.h" -#include "Message.h" -#include "Queue.h" - -namespace qpid { -namespace broker { - class Exchange{ - const std::string name; - public: - explicit Exchange(const std::string& _name) : name(_name) {} - virtual ~Exchange(){} - std::string getName() { return name; } - virtual void bind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args) = 0; - virtual void unbind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args) = 0; - virtual void route(Message::shared_ptr& msg, const string& routingKey, qpid::framing::FieldTable* args) = 0; - }; -} -} - - -#endif diff --git a/cpp/broker/inc/ExchangeBinding.h b/cpp/broker/inc/ExchangeBinding.h deleted file mode 100644 index 4cbb73acbf..0000000000 --- a/cpp/broker/inc/ExchangeBinding.h +++ /dev/null @@ -1,45 +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. - * - */ -#ifndef _ExchangeBinding_ -#define _ExchangeBinding_ - -#include "Binding.h" -#include "FieldTable.h" -#include "Queue.h" - -namespace qpid { - namespace broker { - class Exchange; - class Queue; - - class ExchangeBinding : public virtual Binding{ - Exchange* e; - Queue::shared_ptr q; - const string key; - qpid::framing::FieldTable* args; - public: - ExchangeBinding(Exchange* _e, Queue::shared_ptr _q, const string& _key, qpid::framing::FieldTable* _args); - virtual void cancel(); - virtual ~ExchangeBinding(); - }; - } -} - - -#endif - diff --git a/cpp/broker/inc/ExchangeRegistry.h b/cpp/broker/inc/ExchangeRegistry.h deleted file mode 100644 index a4a778482c..0000000000 --- a/cpp/broker/inc/ExchangeRegistry.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _ExchangeRegistry_ -#define _ExchangeRegistry_ - -#include -#include "Exchange.h" -#include "Monitor.h" - -namespace qpid { -namespace broker { - class ExchangeRegistry{ - typedef std::map ExchangeMap; - ExchangeMap exchanges; - qpid::concurrent::Monitor* lock; - public: - ExchangeRegistry(); - void declare(Exchange* exchange); - void destroy(const string& name); - Exchange* get(const string& name); - Exchange* getDefault(); - inline qpid::concurrent::Monitor* getLock(){ return lock; } - ~ExchangeRegistry(); - }; -} -} - - -#endif diff --git a/cpp/broker/inc/FanOutExchange.h b/cpp/broker/inc/FanOutExchange.h deleted file mode 100644 index 1932e8429c..0000000000 --- a/cpp/broker/inc/FanOutExchange.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _FanOutExchange_ -#define _FanOutExchange_ - -#include -#include -#include "Exchange.h" -#include "FieldTable.h" -#include "Message.h" -#include "MonitorImpl.h" -#include "Queue.h" - -namespace qpid { -namespace broker { - -class FanOutExchange : public virtual Exchange { - std::vector bindings; - qpid::concurrent::MonitorImpl lock; - - public: - static const std::string typeName; - - FanOutExchange(const std::string& name); - - virtual void bind(Queue::shared_ptr queue, const std::string& routingKey, qpid::framing::FieldTable* args); - - virtual void unbind(Queue::shared_ptr queue, const std::string& routingKey, qpid::framing::FieldTable* args); - - virtual void route(Message::shared_ptr& msg, const std::string& routingKey, qpid::framing::FieldTable* args); - - virtual ~FanOutExchange(); -}; - -} -} - - - -#endif diff --git a/cpp/broker/inc/HeadersExchange.h b/cpp/broker/inc/HeadersExchange.h deleted file mode 100644 index 08bf0bb735..0000000000 --- a/cpp/broker/inc/HeadersExchange.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _HeadersExchange_ -#define _HeadersExchange_ - -#include -#include "Exchange.h" -#include "FieldTable.h" -#include "Message.h" -#include "MonitorImpl.h" -#include "Queue.h" - -namespace qpid { -namespace broker { - - -class HeadersExchange : public virtual Exchange { - typedef std::pair Binding; - typedef std::vector Bindings; - - Bindings bindings; - qpid::concurrent::MonitorImpl lock; - - public: - static const std::string typeName; - - HeadersExchange(const string& name); - - virtual void bind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args); - - virtual void unbind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args); - - virtual void route(Message::shared_ptr& msg, const string& routingKey, qpid::framing::FieldTable* args); - - virtual ~HeadersExchange(); - - static bool match(const qpid::framing::FieldTable& bindArgs, const qpid::framing::FieldTable& msgArgs); -}; - - - -} -} - -#endif diff --git a/cpp/broker/inc/Message.h b/cpp/broker/inc/Message.h deleted file mode 100644 index 94b9aa5bdd..0000000000 --- a/cpp/broker/inc/Message.h +++ /dev/null @@ -1,89 +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. - * - */ -#ifndef _Message_ -#define _Message_ - -#include "memory.h" -#include "AMQContentBody.h" -#include "AMQHeaderBody.h" -#include "BasicHeaderProperties.h" -#include "BasicPublishBody.h" -#include "ConnectionToken.h" -#include "OutputHandler.h" - -namespace qpid { - namespace broker { - class ExchangeRegistry; - - /** - * Represents an AMQP message, i.e. a header body, a list of - * content bodies and some details about the publication - * request. - */ - class Message{ - typedef std::vector content_list; - typedef content_list::iterator content_iterator; - - const ConnectionToken* const publisher; - const string exchange; - const string routingKey; - const bool mandatory; - const bool immediate; - bool redelivered; - qpid::framing::AMQHeaderBody::shared_ptr header; - content_list content; - u_int64_t size; - - void sendContent(qpid::framing::OutputHandler* out, - int channel, u_int32_t framesize); - - public: - typedef std::tr1::shared_ptr shared_ptr; - - Message(const ConnectionToken* const publisher, - const string& exchange, const string& routingKey, - bool mandatory, bool immediate); - ~Message(); - void setHeader(qpid::framing::AMQHeaderBody::shared_ptr header); - void addContent(qpid::framing::AMQContentBody::shared_ptr data); - bool isComplete(); - const ConnectionToken* const getPublisher(); - - void deliver(qpid::framing::OutputHandler* out, - int channel, - const string& consumerTag, - u_int64_t deliveryTag, - u_int32_t framesize); - void sendGetOk(qpid::framing::OutputHandler* out, - int channel, - u_int32_t messageCount, - u_int64_t deliveryTag, - u_int32_t framesize); - void redeliver(); - - qpid::framing::BasicHeaderProperties* getHeaderProperties(); - const string& getRoutingKey() const { return routingKey; } - const string& getExchange() const { return exchange; } - u_int64_t contentSize() const{ return size; } - - }; - } -} - - -#endif diff --git a/cpp/broker/inc/NameGenerator.h b/cpp/broker/inc/NameGenerator.h deleted file mode 100644 index 6e6e0acf28..0000000000 --- a/cpp/broker/inc/NameGenerator.h +++ /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. - * - */ -#ifndef _NameGenerator_ -#define _NameGenerator_ - -#include "Message.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/cpp/broker/inc/Queue.h b/cpp/broker/inc/Queue.h deleted file mode 100644 index 2229ba6235..0000000000 --- a/cpp/broker/inc/Queue.h +++ /dev/null @@ -1,106 +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. - * - */ -#ifndef _Queue_ -#define _Queue_ - -#include -#include -#include "memory.h" -#include "apr_time.h" -#include "amqp_types.h" -#include "Binding.h" -#include "ConnectionToken.h" -#include "Consumer.h" -#include "Message.h" -#include "MonitorImpl.h" - -namespace qpid { - namespace broker { - - /** - * Thrown when exclusive access would be violated. - */ - struct ExclusiveAccessException{}; - - /** - * 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{ - const string name; - const u_int32_t autodelete; - const bool durable; - const ConnectionToken* const owner; - std::vector consumers; - std::queue bindings; - std::queue messages; - bool queueing; - bool dispatching; - int next; - mutable qpid::concurrent::MonitorImpl lock; - apr_time_t lastUsed; - Consumer* exclusive; - - bool startDispatching(); - bool dispatch(Message::shared_ptr& msg); - - public: - - typedef std::tr1::shared_ptr shared_ptr; - - typedef std::vector vector; - - Queue(const string& name, bool durable = false, u_int32_t autodelete = 0, const ConnectionToken* const owner = 0); - ~Queue(); - /** - * Informs the queue of a binding that should be cancelled on - * destruction of the queue. - */ - void bound(Binding* b); - /** - * Delivers a message to the queue from where it will be - * dispatched to immediately to a consumer if one is - * available or stored for dequeue or later dispatch if - * not. - */ - void deliver(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); - Message::shared_ptr dequeue(); - u_int32_t purge(); - u_int32_t getMessageCount() const; - u_int32_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; - }; - } -} - - -#endif diff --git a/cpp/broker/inc/QueueRegistry.h b/cpp/broker/inc/QueueRegistry.h deleted file mode 100644 index ac12aa8f88..0000000000 --- a/cpp/broker/inc/QueueRegistry.h +++ /dev/null @@ -1,88 +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. - * - */ -#ifndef _QueueRegistry_ -#define _QueueRegistry_ - -#include -#include "MonitorImpl.h" -#include "Queue.h" - -namespace qpid { -namespace broker { - -class SessionHandlerImpl; - -/** - * 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(); - ~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, u_int32_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(); - - private: - typedef std::map QueueMap; - QueueMap queues; - qpid::concurrent::MonitorImpl lock; - int counter; - -}; - - -} -} - - -#endif diff --git a/cpp/broker/inc/Router.h b/cpp/broker/inc/Router.h deleted file mode 100644 index d462b69832..0000000000 --- a/cpp/broker/inc/Router.h +++ /dev/null @@ -1,39 +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. - * - */ -#ifndef _Router_ -#define _Router_ - -#include "ExchangeRegistry.h" -#include "Message.h" - -/** - * A routing functor - */ -namespace qpid { - namespace broker { - class Router{ - ExchangeRegistry& registry; - public: - Router(ExchangeRegistry& registry); - void operator()(Message::shared_ptr& msg); - }; - } -} - - -#endif diff --git a/cpp/broker/inc/SessionHandlerFactoryImpl.h b/cpp/broker/inc/SessionHandlerFactoryImpl.h deleted file mode 100644 index 2317a6667b..0000000000 --- a/cpp/broker/inc/SessionHandlerFactoryImpl.h +++ /dev/null @@ -1,49 +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. - * - */ -#ifndef _SessionHandlerFactoryImpl_ -#define _SessionHandlerFactoryImpl_ - -#include "AMQFrame.h" -#include "AutoDelete.h" -#include "DirectExchange.h" -#include "ExchangeRegistry.h" -#include "ProtocolInitiation.h" -#include "QueueRegistry.h" -#include "SessionHandlerFactory.h" -#include "TimeoutHandler.h" - -namespace qpid { - namespace broker { - - class SessionHandlerFactoryImpl : public virtual qpid::io::SessionHandlerFactory - { - QueueRegistry queues; - ExchangeRegistry exchanges; - const u_int32_t timeout;//timeout for auto-deleted queues (in ms) - AutoDelete cleaner; - public: - SessionHandlerFactoryImpl(u_int32_t timeout = 30000); - virtual qpid::io::SessionHandler* create(qpid::io::SessionContext* ctxt); - virtual ~SessionHandlerFactoryImpl(); - }; - - } -} - - -#endif diff --git a/cpp/broker/inc/SessionHandlerImpl.h b/cpp/broker/inc/SessionHandlerImpl.h deleted file mode 100644 index 549f51f5a1..0000000000 --- a/cpp/broker/inc/SessionHandlerImpl.h +++ /dev/null @@ -1,233 +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. - * - */ -#ifndef _SessionHandlerImpl_ -#define _SessionHandlerImpl_ - -#include -#include -#include -#include -#include "AMQFrame.h" -#include "AMQP_ClientProxy.h" -#include "AMQP_ServerOperations.h" -#include "AutoDelete.h" -#include "ExchangeRegistry.h" -#include "Channel.h" -#include "ConnectionToken.h" -#include "DirectExchange.h" -#include "OutputHandler.h" -#include "ProtocolInitiation.h" -#include "QueueRegistry.h" -#include "SessionContext.h" -#include "SessionHandler.h" -#include "TimeoutHandler.h" -#include "TopicExchange.h" - -namespace qpid { -namespace broker { - -struct ChannelException : public std::exception { - u_int16_t code; - string text; - ChannelException(u_int16_t _code, string _text) : code(_code), text(_text) {} - ~ChannelException() throw() {} - const char* what() const throw() { return text.c_str(); } -}; - -struct ConnectionException : public std::exception { - u_int16_t code; - string text; - ConnectionException(u_int16_t _code, string _text) : code(_code), text(_text) {} - ~ConnectionException() throw() {} - const char* what() const throw() { return text.c_str(); } -}; - -class SessionHandlerImpl : public virtual qpid::io::SessionHandler, - public virtual qpid::framing::AMQP_ServerOperations, - public virtual ConnectionToken -{ - typedef std::map::iterator channel_iterator; - typedef std::vector::iterator queue_iterator; - - qpid::io::SessionContext* context; - qpid::framing::AMQP_ClientProxy client; - QueueRegistry* queues; - ExchangeRegistry* const exchanges; - AutoDelete* const cleaner; - const u_int32_t timeout;//timeout for auto-deleted queues (in ms) - - ConnectionHandler* connectionHandler; - ChannelHandler* channelHandler; - BasicHandler* basicHandler; - ExchangeHandler* exchangeHandler; - QueueHandler* queueHandler; - - std::map channels; - std::vector exclusiveQueues; - - u_int32_t framemax; - u_int16_t heartbeat; - - void handleHeader(u_int16_t channel, qpid::framing::AMQHeaderBody::shared_ptr body); - void handleContent(u_int16_t channel, qpid::framing::AMQContentBody::shared_ptr body); - void handleHeartbeat(qpid::framing::AMQHeartbeatBody::shared_ptr body); - - Channel* getChannel(u_int16_t channel); - /** - * 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 no queue specified and channel has not declared one. - */ - Queue::shared_ptr getQueue(const string& name, u_int16_t channel); - - Exchange* findExchange(const string& name); - - public: - SessionHandlerImpl(qpid::io::SessionContext* context, QueueRegistry* queues, - ExchangeRegistry* exchanges, AutoDelete* cleaner, const u_int32_t timeout); - virtual void received(qpid::framing::AMQFrame* frame); - virtual void initiated(qpid::framing::ProtocolInitiation* header); - virtual void idleOut(); - virtual void idleIn(); - virtual void closed(); - virtual ~SessionHandlerImpl(); - - class ConnectionHandlerImpl : public virtual ConnectionHandler{ - SessionHandlerImpl* parent; - public: - inline ConnectionHandlerImpl(SessionHandlerImpl* _parent) : parent(_parent) {} - - virtual void startOk(u_int16_t channel, qpid::framing::FieldTable& clientProperties, string& mechanism, - string& response, string& locale); - - virtual void secureOk(u_int16_t channel, string& response); - - virtual void tuneOk(u_int16_t channel, u_int16_t channelMax, u_int32_t frameMax, u_int16_t heartbeat); - - virtual void open(u_int16_t channel, string& virtualHost, string& capabilities, bool insist); - - virtual void close(u_int16_t channel, u_int16_t replyCode, string& replyText, u_int16_t classId, - u_int16_t methodId); - - virtual void closeOk(u_int16_t channel); - - virtual ~ConnectionHandlerImpl(){} - }; - - class ChannelHandlerImpl : public virtual ChannelHandler{ - SessionHandlerImpl* parent; - public: - inline ChannelHandlerImpl(SessionHandlerImpl* _parent) : parent(_parent) {} - - virtual void open(u_int16_t channel, string& outOfBand); - - virtual void flow(u_int16_t channel, bool active); - - virtual void flowOk(u_int16_t channel, bool active); - - virtual void close(u_int16_t channel, u_int16_t replyCode, string& replyText, - u_int16_t classId, u_int16_t methodId); - - virtual void closeOk(u_int16_t channel); - - virtual ~ChannelHandlerImpl(){} - }; - - class ExchangeHandlerImpl : public virtual ExchangeHandler{ - SessionHandlerImpl* parent; - public: - inline ExchangeHandlerImpl(SessionHandlerImpl* _parent) : parent(_parent) {} - - virtual void declare(u_int16_t channel, u_int16_t ticket, string& exchange, string& type, - bool passive, bool durable, bool autoDelete, bool internal, bool nowait, - qpid::framing::FieldTable& arguments); - - virtual void delete_(u_int16_t channel, u_int16_t ticket, string& exchange, bool ifUnused, bool nowait); - - virtual ~ExchangeHandlerImpl(){} - }; - - - class QueueHandlerImpl : public virtual QueueHandler{ - SessionHandlerImpl* parent; - public: - inline QueueHandlerImpl(SessionHandlerImpl* _parent) : parent(_parent) {} - - virtual void declare(u_int16_t channel, u_int16_t ticket, string& queue, - bool passive, bool durable, bool exclusive, - bool autoDelete, bool nowait, qpid::framing::FieldTable& arguments); - - virtual void bind(u_int16_t channel, u_int16_t ticket, string& queue, - string& exchange, string& routingKey, bool nowait, - qpid::framing::FieldTable& arguments); - - virtual void purge(u_int16_t channel, u_int16_t ticket, string& queue, - bool nowait); - - virtual void delete_(u_int16_t channel, u_int16_t ticket, string& queue, bool ifUnused, bool ifEmpty, - bool nowait); - - virtual ~QueueHandlerImpl(){} - }; - - class BasicHandlerImpl : public virtual BasicHandler{ - SessionHandlerImpl* parent; - public: - inline BasicHandlerImpl(SessionHandlerImpl* _parent) : parent(_parent) {} - - virtual void qos(u_int16_t channel, u_int32_t prefetchSize, u_int16_t prefetchCount, bool global); - - virtual void consume(u_int16_t channel, u_int16_t ticket, string& queue, string& consumerTag, - bool noLocal, bool noAck, bool exclusive, bool nowait); - - virtual void cancel(u_int16_t channel, string& consumerTag, bool nowait); - - virtual void publish(u_int16_t channel, u_int16_t ticket, string& exchange, string& routingKey, - bool mandatory, bool immediate); - - virtual void get(u_int16_t channel, u_int16_t ticket, string& queue, bool noAck); - - virtual void ack(u_int16_t channel, u_int64_t deliveryTag, bool multiple); - - virtual void reject(u_int16_t channel, u_int64_t deliveryTag, bool requeue); - - virtual void recover(u_int16_t channel, bool requeue); - - virtual ~BasicHandlerImpl(){} - }; - - inline virtual ChannelHandler* getChannelHandler(){ return channelHandler; } - inline virtual ConnectionHandler* getConnectionHandler(){ return connectionHandler; } - inline virtual BasicHandler* getBasicHandler(){ return basicHandler; } - inline virtual ExchangeHandler* getExchangeHandler(){ return exchangeHandler; } - inline virtual QueueHandler* getQueueHandler(){ return queueHandler; } - - inline virtual AccessHandler* getAccessHandler(){ return 0; } - inline virtual FileHandler* getFileHandler(){ return 0; } - inline virtual StreamHandler* getStreamHandler(){ return 0; } - inline virtual TxHandler* getTxHandler(){ return 0; } - inline virtual DtxHandler* getDtxHandler(){ return 0; } - inline virtual TunnelHandler* getTunnelHandler(){ return 0; } -}; - -} -} - - -#endif diff --git a/cpp/broker/inc/TopicExchange.h b/cpp/broker/inc/TopicExchange.h deleted file mode 100644 index 227280103f..0000000000 --- a/cpp/broker/inc/TopicExchange.h +++ /dev/null @@ -1,94 +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. - * - */ -#ifndef _TopicExchange_ -#define _TopicExchange_ - -#include -#include -#include "Exchange.h" -#include "FieldTable.h" -#include "Message.h" -#include "MonitorImpl.h" -#include "Queue.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); } - /** Tokenize s */ - Tokens & operator=(const std::string& s); - - struct Hash { size_t operator()(const Tokens&) const; }; - typedef std::equal_to Equal; -}; - -/** - * 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::tr1::unordered_map BindingMap; - BindingMap bindings; - qpid::concurrent::MonitorImpl lock; - - public: - static const std::string typeName; - - TopicExchange(const string& name); - - virtual void bind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args); - - virtual void unbind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args); - - virtual void route(Message::shared_ptr& msg, const string& routingKey, qpid::framing::FieldTable* args); - - virtual ~TopicExchange(); -}; - - - -} -} - -#endif diff --git a/cpp/broker/src/AutoDelete.cpp b/cpp/broker/src/AutoDelete.cpp deleted file mode 100644 index 6793ec449d..0000000000 --- a/cpp/broker/src/AutoDelete.cpp +++ /dev/null @@ -1,93 +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 "AutoDelete.h" - -using namespace qpid::broker; - -AutoDelete::AutoDelete(QueueRegistry* const _registry, u_int32_t _period) : registry(_registry), - period(_period), - stopped(true), - runner(0){} - -void AutoDelete::add(Queue::shared_ptr const queue){ - lock.acquire(); - queues.push(queue); - lock.release(); -} - -Queue::shared_ptr const AutoDelete::pop(){ - Queue::shared_ptr next; - lock.acquire(); - if(!queues.empty()){ - next = queues.front(); - queues.pop(); - } - lock.release(); - 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.acquire(); - while(!stopped){ - process(); - monitor.wait(period); - } - monitor.release(); -} - -void AutoDelete::start(){ - monitor.acquire(); - if(stopped){ - runner = factory.create(this); - stopped = false; - monitor.release(); - runner->start(); - }else{ - monitor.release(); - } -} - -void AutoDelete::stop(){ - monitor.acquire(); - if(!stopped){ - stopped = true; - monitor.notify(); - monitor.release(); - runner->join(); - delete runner; - }else{ - monitor.release(); - } -} diff --git a/cpp/broker/src/Broker.cpp b/cpp/broker/src/Broker.cpp deleted file mode 100644 index b6472d1729..0000000000 --- a/cpp/broker/src/Broker.cpp +++ /dev/null @@ -1,84 +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 "Broker.h" -#include "Acceptor.h" -#include "Configuration.h" -#include "QpidError.h" -#include "SessionHandlerFactoryImpl.h" -#include "BlockingAPRAcceptor.h" -#include "LFAcceptor.h" - - -using namespace qpid::broker; -using namespace qpid::io; - -namespace { - Acceptor* createAcceptor(const Configuration& config){ - const string type(config.getAcceptor()); - if("blocking" == type){ - std::cout << "Using blocking acceptor " << std::endl; - return new BlockingAPRAcceptor(config.isTrace(), config.getConnectionBacklog()); - }else if("non-blocking" == type){ - std::cout << "Using non-blocking acceptor " << std::endl; - return new LFAcceptor(config.isTrace(), - config.getConnectionBacklog(), - config.getWorkerThreads(), - config.getMaxConnections()); - } - throw Configuration::ParseException("Unrecognised acceptor: " + type); - } -} - -Broker::Broker(const Configuration& config) : - acceptor(createAcceptor(config)), - port(config.getPort()), - isBound(false) {} - -Broker::shared_ptr Broker::create(int port) -{ - Configuration config; - config.setPort(port); - return create(config); -} - -Broker::shared_ptr Broker::create(const Configuration& config) { - return Broker::shared_ptr(new Broker(config)); -} - -int16_t Broker::bind() -{ - if (!isBound) { - port = acceptor->bind(port); - } - return port; -} - -void Broker::run() { - bind(); - acceptor->run(&factory); -} - -void Broker::shutdown() { - acceptor->shutdown(); -} - -Broker::~Broker() { } - -const int16_t Broker::DEFAULT_PORT(5672); diff --git a/cpp/broker/src/Channel.cpp b/cpp/broker/src/Channel.cpp deleted file mode 100644 index 34d69716c4..0000000000 --- a/cpp/broker/src/Channel.cpp +++ /dev/null @@ -1,256 +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 "Channel.h" -#include "QpidError.h" -#include -#include -#include - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::concurrent; - - -Channel::Channel(OutputHandler* _out, int _id, u_int32_t _framesize) : - id(_id), - out(_out), - deliveryTag(1), - transactional(false), - prefetchSize(0), - prefetchCount(0), - outstandingSize(0), - outstandingCount(0), - framesize(_framesize), - tagGenerator("sgen"){} - -Channel::~Channel(){ -} - -bool Channel::exists(const string& consumerTag){ - return consumers.find(consumerTag) != consumers.end(); -} - -void Channel::consume(string& tag, Queue::shared_ptr queue, bool acks, bool exclusive, ConnectionToken* const connection){ - if(tag.empty()) tag = tagGenerator.generate(); - - ConsumerImpl* c(new ConsumerImpl(this, tag, queue, connection, acks)); - try{ - queue->consume(c, exclusive);//may throw exception - consumers[tag] = c; - }catch(ExclusiveAccessException& e){ - delete c; - throw e; - } -} - -void Channel::cancel(consumer_iterator i){ - ConsumerImpl* c = i->second; - consumers.erase(i); - if(c){ - c->cancel(); - delete c; - } -} - -void Channel::cancel(const string& tag){ - consumer_iterator i = consumers.find(tag); - if(i != consumers.end()){ - cancel(i); - } -} - -void Channel::close(){ - //cancel all consumers - for(consumer_iterator i = consumers.begin(); i != consumers.end(); i = consumers.begin() ){ - cancel(i); - } -} - -void Channel::begin(){ - transactional = true; -} - -void Channel::commit(){ - -} - -void Channel::rollback(){ - -} - -void Channel::deliver(Message::shared_ptr& msg, string& consumerTag, Queue::shared_ptr& queue, bool ackExpected){ - Locker locker(deliveryLock); - - u_int64_t myDeliveryTag = deliveryTag++; - if(ackExpected){ - unacknowledged.push_back(AckRecord(msg, queue, consumerTag, myDeliveryTag)); - outstandingSize += msg->contentSize(); - outstandingCount++; - } - //send deliver method, header and content(s) - msg->deliver(out, id, consumerTag, myDeliveryTag, framesize); -} - -bool Channel::checkPrefetch(Message::shared_ptr& msg){ - Locker locker(deliveryLock); - bool countOk = !prefetchCount || prefetchCount > unacknowledged.size(); - bool sizeOk = !prefetchSize || prefetchSize > msg->contentSize() + outstandingSize || unacknowledged.empty(); - return countOk && sizeOk; -} - -Channel::ConsumerImpl::ConsumerImpl(Channel* _parent, 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; -} - -void Channel::ConsumerImpl::cancel(){ - if(queue) queue->cancel(this); -} - -void Channel::ConsumerImpl::requestDispatch(){ - if(blocked) queue->dispatch(); -} - -void Channel::checkMessage(const std::string& text){ - if(!message.get()){ - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, text); - } -} - -void Channel::handlePublish(Message* msg){ - if(message.get()){ - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got publish before previous content was completed."); - } - message = Message::shared_ptr(msg); -} - -void Channel::ack(u_int64_t _deliveryTag, bool multiple){ - Locker locker(deliveryLock);//need to synchronize with possible concurrent delivery - - ack_iterator i = find_if(unacknowledged.begin(), unacknowledged.end(), MatchAck(_deliveryTag)); - if(i == unacknowledged.end()){ - throw InvalidAckException(); - }else if(multiple){ - unacknowledged.erase(unacknowledged.begin(), ++i); - //recompute prefetch outstanding (note: messages delivered through get are ignored) - CalculatePrefetch calc(for_each(unacknowledged.begin(), unacknowledged.end(), CalculatePrefetch())); - outstandingSize = calc.getSize(); - outstandingCount = calc.getCount(); - }else{ - if(!i->pull){ - outstandingSize -= i->msg->contentSize(); - outstandingCount--; - } - unacknowledged.erase(i); - } - - //if the prefetch limit had previously been reached, there may - //be messages that can be now be delivered - for(consumer_iterator j = consumers.begin(); j != consumers.end(); j++){ - j->second->requestDispatch(); - } -} - -void Channel::recover(bool requeue){ - Locker locker(deliveryLock);//need to synchronize with possible concurrent delivery - - if(requeue){ - outstandingSize = 0; - outstandingCount = 0; - ack_iterator start(unacknowledged.begin()); - ack_iterator end(unacknowledged.end()); - for_each(start, end, Requeue()); - unacknowledged.erase(start, end); - }else{ - for_each(unacknowledged.begin(), unacknowledged.end(), Redeliver(this)); - } -} - -bool Channel::get(Queue::shared_ptr queue, bool ackExpected){ - Message::shared_ptr msg = queue->dequeue(); - if(msg){ - Locker locker(deliveryLock); - u_int64_t myDeliveryTag = deliveryTag++; - msg->sendGetOk(out, id, queue->getMessageCount() + 1, myDeliveryTag, framesize); - if(ackExpected){ - unacknowledged.push_back(AckRecord(msg, queue, myDeliveryTag)); - } - return true; - }else{ - return false; - } -} - -Channel::MatchAck::MatchAck(u_int64_t _tag) : tag(_tag) {} - -bool Channel::MatchAck::operator()(AckRecord& record) const{ - return tag == record.deliveryTag; -} - -void Channel::Requeue::operator()(AckRecord& record) const{ - record.msg->redeliver(); - record.queue->deliver(record.msg); -} - -Channel::Redeliver::Redeliver(Channel* const _channel) : channel(_channel) {} - -void Channel::Redeliver::operator()(AckRecord& record) const{ - if(record.pull){ - //if message was originally sent as response to get, we must requeue it - record.msg->redeliver(); - record.queue->deliver(record.msg); - }else{ - record.msg->deliver(channel->out, channel->id, record.consumerTag, record.deliveryTag, channel->framesize); - } -} - -Channel::CalculatePrefetch::CalculatePrefetch() : size(0){} - -void Channel::CalculatePrefetch::operator()(AckRecord& record){ - if(!record.pull){ - //ignore messages that were sent in response to get when calculating prefetch - size += record.msg->contentSize(); - count++; - } -} - -u_int32_t Channel::CalculatePrefetch::getSize(){ - return size; -} - -u_int16_t Channel::CalculatePrefetch::getCount(){ - return count; -} diff --git a/cpp/broker/src/Configuration.cpp b/cpp/broker/src/Configuration.cpp deleted file mode 100644 index 6e7df7889e..0000000000 --- a/cpp/broker/src/Configuration.cpp +++ /dev/null @@ -1,196 +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 "Configuration.h" -#include - -using namespace qpid::broker; -using namespace std; - -Configuration::Configuration() : - trace('t', "trace", "Print incoming & outgoing frames to the console (default=false)", false), - port('p', "port", "Sets the port to listen on (default=5672)", 5672), - workerThreads("worker-threads", "Sets the number of worker threads to use (default=5). Only valid for non-blocking acceptor.", 5), - maxConnections("max-connections", "Sets the maximum number of connections the broker can accept (default=500). Only valid for non-blocking acceptor.", 500), - connectionBacklog("connection-backlog", "Sets the connection backlog for the servers socket (default=10)", 10), - acceptor('a', "acceptor", "Sets the acceptor to use. Currently only two values are recognised, blocking and non-blocking (which is the default)", "non-blocking"), - help("help", "Prints usage information", false) -{ - options.push_back(&trace); - options.push_back(&port); - options.push_back(&workerThreads); - options.push_back(&maxConnections); - options.push_back(&connectionBacklog); - options.push_back(&acceptor); - options.push_back(&help); -} - -Configuration::~Configuration(){} - -void Configuration::parse(int argc, char** argv){ - 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){ - std::cout << "Warning: skipping unrecognised option " << argv[position] << std::endl; - position++; - } - } -} - -void Configuration::usage(){ - for(op_iterator i = options.begin(); i < options.end(); i++){ - (*i)->print(std::cout); - } -} - -bool Configuration::isHelp() const { - return help.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(); -} - -string Configuration::getAcceptor() const { - return acceptor.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 << " or "; - } - 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()); -} - -// 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& _value){ - value = strcasecmp(_value.c_str(), "true") == 0; -} diff --git a/cpp/broker/src/DirectExchange.cpp b/cpp/broker/src/DirectExchange.cpp deleted file mode 100644 index 94cfbc766d..0000000000 --- a/cpp/broker/src/DirectExchange.cpp +++ /dev/null @@ -1,72 +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 "DirectExchange.h" -#include "ExchangeBinding.h" -#include - -using namespace qpid::broker; -using namespace qpid::framing; - -DirectExchange::DirectExchange(const string& _name) : Exchange(_name) { - -} - -void DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, FieldTable* args){ - lock.acquire(); - std::vector& queues(bindings[routingKey]); - std::vector::iterator i = find(queues.begin(), queues.end(), queue); - if(i == queues.end()){ - bindings[routingKey].push_back(queue); - queue->bound(new ExchangeBinding(this, queue, routingKey, args)); - } - lock.release(); -} - -void DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, FieldTable* /*args*/){ - lock.acquire(); - 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); - } - } - lock.release(); -} - -void DirectExchange::route(Message::shared_ptr& msg, const string& routingKey, FieldTable* /*args*/){ - lock.acquire(); - std::vector& queues(bindings[routingKey]); - int count(0); - for(std::vector::iterator i = queues.begin(); i != queues.end(); i++, count++){ - (*i)->deliver(msg); - } - if(!count){ - std::cout << "WARNING: DirectExchange " << getName() << " could not route message with key " << routingKey << std::endl; - } - lock.release(); -} - -DirectExchange::~DirectExchange(){ - -} - - -const std::string DirectExchange::typeName("direct"); diff --git a/cpp/broker/src/ExchangeBinding.cpp b/cpp/broker/src/ExchangeBinding.cpp deleted file mode 100644 index 6160a67fd3..0000000000 --- a/cpp/broker/src/ExchangeBinding.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 "ExchangeBinding.h" -#include "Exchange.h" - -using namespace qpid::broker; -using namespace qpid::framing; - -ExchangeBinding::ExchangeBinding(Exchange* _e, Queue::shared_ptr _q, const string& _key, FieldTable* _args) : e(_e), q(_q), key(_key), args(_args){} - -void ExchangeBinding::cancel(){ - e->unbind(q, key, args); - delete this; -} - -ExchangeBinding::~ExchangeBinding(){ -} diff --git a/cpp/broker/src/ExchangeRegistry.cpp b/cpp/broker/src/ExchangeRegistry.cpp deleted file mode 100644 index 05396382a7..0000000000 --- a/cpp/broker/src/ExchangeRegistry.cpp +++ /dev/null @@ -1,57 +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 "ExchangeRegistry.h" -#include "MonitorImpl.h" - -using namespace qpid::broker; -using namespace qpid::concurrent; - -ExchangeRegistry::ExchangeRegistry() : lock(new MonitorImpl()){} - -ExchangeRegistry::~ExchangeRegistry(){ - for (ExchangeMap::iterator i = exchanges.begin(); i != exchanges.end(); ++i) - { - delete i->second; - } - delete lock; -} - -void ExchangeRegistry::declare(Exchange* exchange){ - exchanges[exchange->getName()] = exchange; -} - -void ExchangeRegistry::destroy(const string& name){ - if(exchanges[name]){ - delete exchanges[name]; - exchanges.erase(name); - } -} - -Exchange* ExchangeRegistry::get(const string& name){ - return exchanges[name]; -} - -namespace -{ -const std::string empty; -} - -Exchange* ExchangeRegistry::getDefault() -{ - return get(empty); -} diff --git a/cpp/broker/src/FanOutExchange.cpp b/cpp/broker/src/FanOutExchange.cpp deleted file mode 100644 index e8cb8f6315..0000000000 --- a/cpp/broker/src/FanOutExchange.cpp +++ /dev/null @@ -1,56 +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 "FanOutExchange.h" -#include "ExchangeBinding.h" -#include - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::concurrent; - -FanOutExchange::FanOutExchange(const std::string& _name) : Exchange(_name) {} - -void FanOutExchange::bind(Queue::shared_ptr queue, const string& routingKey, FieldTable* args){ - Locker 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); - queue->bound(new ExchangeBinding(this, queue, routingKey, args)); - } -} - -void FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*routingKey*/, FieldTable* /*args*/){ - Locker locker(lock); - Queue::vector::iterator i = std::find(bindings.begin(), bindings.end(), queue); - if (i != bindings.end()) { - bindings.erase(i); - // TODO aconway 2006-09-14: What about the ExchangeBinding object? Don't we have to verify routingKey/args match? - } -} - -void FanOutExchange::route(Message::shared_ptr& msg, const string& /*routingKey*/, FieldTable* /*args*/){ - Locker locker(lock); - for(Queue::vector::iterator i = bindings.begin(); i != bindings.end(); ++i){ - (*i)->deliver(msg); - } -} - -FanOutExchange::~FanOutExchange() {} - -const std::string FanOutExchange::typeName("fanout"); diff --git a/cpp/broker/src/HeadersExchange.cpp b/cpp/broker/src/HeadersExchange.cpp deleted file mode 100644 index 65204cdb85..0000000000 --- a/cpp/broker/src/HeadersExchange.cpp +++ /dev/null @@ -1,120 +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 "HeadersExchange.h" -#include "ExchangeBinding.h" -#include "Value.h" -#include "QpidError.h" -#include - - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::concurrent; - -// 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, FieldTable* args){ - std::cout << "HeadersExchange::bind" << std::endl; - Locker 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)); - queue->bound(new ExchangeBinding(this, queue, routingKey, args)); -} - -void HeadersExchange::unbind(Queue::shared_ptr queue, const string& /*routingKey*/, FieldTable* args){ - Locker locker(lock); - Bindings::iterator i = - std::find(bindings.begin(),bindings.end(), Binding(*args, queue)); - if (i != bindings.end()) bindings.erase(i); -} - - -void HeadersExchange::route(Message::shared_ptr& msg, const string& /*routingKey*/, FieldTable* args){ - std::cout << "route: " << *args << std::endl; - Locker locker(lock);; - for (Bindings::iterator i = bindings.begin(); i != bindings.end(); ++i) { - if (match(i->first, *args)) i->second->deliver(msg); - } -} - -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/cpp/broker/src/Message.cpp b/cpp/broker/src/Message.cpp deleted file mode 100644 index 0a8a5f7a4d..0000000000 --- a/cpp/broker/src/Message.cpp +++ /dev/null @@ -1,100 +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 "MonitorImpl.h" -#include "Message.h" -#include "ExchangeRegistry.h" -#include - -using namespace std::tr1;//for *_pointer_cast methods -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::concurrent; - - -Message::Message(const ConnectionToken* const _publisher, - const string& _exchange, const string& _routingKey, - bool _mandatory, bool _immediate) : publisher(_publisher), - exchange(_exchange), - routingKey(_routingKey), - mandatory(_mandatory), - immediate(_immediate), - redelivered(false), - size(0){ - -} - -Message::~Message(){ -} - -void Message::setHeader(AMQHeaderBody::shared_ptr _header){ - this->header = _header; -} - -void Message::addContent(AMQContentBody::shared_ptr data){ - content.push_back(data); - size += data->size(); -} - -bool Message::isComplete(){ - return header.get() && (header->getContentSize() == contentSize()); -} - -void Message::redeliver(){ - redelivered = true; -} - -void Message::deliver(OutputHandler* out, int channel, - const string& consumerTag, u_int64_t deliveryTag, - u_int32_t framesize){ - - out->send(new AMQFrame(channel, new BasicDeliverBody(consumerTag, deliveryTag, redelivered, exchange, routingKey))); - sendContent(out, channel, framesize); -} - -void Message::sendGetOk(OutputHandler* out, - int channel, - u_int32_t messageCount, - u_int64_t deliveryTag, - u_int32_t framesize){ - - out->send(new AMQFrame(channel, new BasicGetOkBody(deliveryTag, redelivered, exchange, routingKey, messageCount))); - sendContent(out, channel, framesize); -} - -void Message::sendContent(OutputHandler* out, int channel, u_int32_t framesize){ - AMQBody::shared_ptr headerBody = static_pointer_cast(header); - out->send(new AMQFrame(channel, headerBody)); - for(content_iterator i = content.begin(); i != content.end(); i++){ - if((*i)->size() > framesize){ - //TODO: need to split it - std::cout << "WARNING: Dropped message. Re-fragmentation not yet implemented." << std::endl; - }else{ - AMQBody::shared_ptr contentBody = static_pointer_cast(*i); - out->send(new AMQFrame(channel, contentBody)); - } - } -} - -BasicHeaderProperties* Message::getHeaderProperties(){ - return dynamic_cast(header->getProperties()); -} - -const ConnectionToken* const Message::getPublisher(){ - return publisher; -} - diff --git a/cpp/broker/src/NameGenerator.cpp b/cpp/broker/src/NameGenerator.cpp deleted file mode 100644 index 46aa385a7e..0000000000 --- a/cpp/broker/src/NameGenerator.cpp +++ /dev/null @@ -1,29 +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 "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/cpp/broker/src/Queue.cpp b/cpp/broker/src/Queue.cpp deleted file mode 100644 index eaaa3ffa31..0000000000 --- a/cpp/broker/src/Queue.cpp +++ /dev/null @@ -1,155 +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 "Queue.h" -#include "MonitorImpl.h" -#include - -using namespace qpid::broker; -using namespace qpid::concurrent; - -Queue::Queue(const string& _name, bool _durable, u_int32_t _autodelete, const ConnectionToken* const _owner) : - name(_name), - autodelete(_autodelete), - durable(_durable), - owner(_owner), - queueing(false), - dispatching(false), - next(0), - lastUsed(0), - exclusive(0) -{ - if(autodelete) lastUsed = apr_time_as_msec(apr_time_now()); -} - -Queue::~Queue(){ - for(Binding* b = bindings.front(); !bindings.empty(); b = bindings.front()){ - b->cancel(); - bindings.pop(); - } -} - -void Queue::bound(Binding* b){ - bindings.push(b); -} - -void Queue::deliver(Message::shared_ptr& msg){ - Locker locker(lock); - if(queueing || !dispatch(msg)){ - queueing = true; - messages.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(){ - Locker locker(lock); - if(queueing && !dispatching){ - dispatching = true; - return true; - }else{ - return false; - } -} - -void Queue::dispatch(){ - bool proceed = startDispatching(); - while(proceed){ - Locker locker(lock); - if(!messages.empty() && dispatch(messages.front())){ - messages.pop(); - }else{ - dispatching = false; - proceed = false; - queueing = !messages.empty(); - } - } -} - -void Queue::consume(Consumer* c, bool requestExclusive){ - Locker locker(lock); - if(exclusive) throw ExclusiveAccessException(); - if(requestExclusive){ - if(!consumers.empty()) throw ExclusiveAccessException(); - exclusive = c; - } - - if(autodelete && consumers.empty()) lastUsed = 0; - consumers.push_back(c); -} - -void Queue::cancel(Consumer* c){ - Locker locker(lock); - consumers.erase(find(consumers.begin(), consumers.end(), c)); - if(autodelete && consumers.empty()) lastUsed = apr_time_as_msec(apr_time_now()); - if(exclusive == c) exclusive = 0; -} - -Message::shared_ptr Queue::dequeue(){ - Locker locker(lock); - Message::shared_ptr msg; - if(!messages.empty()){ - msg = messages.front(); - messages.pop(); - } - return msg; -} - -u_int32_t Queue::purge(){ - Locker locker(lock); - int count = messages.size(); - while(!messages.empty()) messages.pop(); - return count; -} - -u_int32_t Queue::getMessageCount() const{ - Locker locker(lock); - return messages.size(); -} - -u_int32_t Queue::getConsumerCount() const{ - Locker locker(lock); - return consumers.size(); -} - -bool Queue::canAutoDelete() const{ - Locker locker(lock); - return lastUsed && ((apr_time_as_msec(apr_time_now()) - lastUsed) > autodelete); -} diff --git a/cpp/broker/src/QueueRegistry.cpp b/cpp/broker/src/QueueRegistry.cpp deleted file mode 100644 index f807415314..0000000000 --- a/cpp/broker/src/QueueRegistry.cpp +++ /dev/null @@ -1,72 +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 "QueueRegistry.h" -#include "MonitorImpl.h" -#include "SessionHandlerImpl.h" -#include -#include - -using namespace qpid::broker; -using namespace qpid::concurrent; - -QueueRegistry::QueueRegistry() : counter(1){} - -QueueRegistry::~QueueRegistry(){} - -std::pair -QueueRegistry::declare(const string& declareName, bool durable, u_int32_t autoDelete, const ConnectionToken* owner) -{ - Locker 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, durable, autoDelete, owner)); - queues[name] = queue; - return std::pair(queue, true); - } else { - return std::pair(i->second, false); - } -} - -void QueueRegistry::destroy(const string& name){ - Locker locker(lock); - queues.erase(name); -} - -Queue::shared_ptr QueueRegistry::find(const string& name){ - Locker 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; -} diff --git a/cpp/broker/src/Router.cpp b/cpp/broker/src/Router.cpp deleted file mode 100644 index c2dd74bf7d..0000000000 --- a/cpp/broker/src/Router.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 "Router.h" - -using namespace qpid::broker; - -Router::Router(ExchangeRegistry& _registry) : registry(_registry){} - -void Router::operator()(Message::shared_ptr& msg){ - Exchange* exchange = registry.get(msg->getExchange()); - if(exchange){ - exchange->route(msg, msg->getRoutingKey(), &(msg->getHeaderProperties()->getHeaders())); - }else{ - std::cout << "WARNING: Could not route message, unknown exchange: " << msg->getExchange() << std::endl; - } - -} diff --git a/cpp/broker/src/SessionHandlerFactoryImpl.cpp b/cpp/broker/src/SessionHandlerFactoryImpl.cpp deleted file mode 100644 index 39c627afef..0000000000 --- a/cpp/broker/src/SessionHandlerFactoryImpl.cpp +++ /dev/null @@ -1,50 +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 "SessionHandlerFactoryImpl.h" -#include "SessionHandlerImpl.h" -#include "FanOutExchange.h" -#include "HeadersExchange.h" - -using namespace qpid::broker; -using namespace qpid::io; - -namespace -{ -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"); -} - -SessionHandlerFactoryImpl::SessionHandlerFactoryImpl(u_int32_t _timeout) : timeout(_timeout), cleaner(&queues, timeout/10){ - exchanges.declare(new DirectExchange(empty)); // Default exchange. - exchanges.declare(new DirectExchange(amq_direct)); - exchanges.declare(new TopicExchange(amq_topic)); - exchanges.declare(new FanOutExchange(amq_fanout)); - exchanges.declare(new HeadersExchange(amq_match)); - cleaner.start(); -} - -SessionHandler* SessionHandlerFactoryImpl::create(SessionContext* ctxt){ - return new SessionHandlerImpl(ctxt, &queues, &exchanges, &cleaner, timeout); -} - -SessionHandlerFactoryImpl::~SessionHandlerFactoryImpl(){ - cleaner.stop(); -} diff --git a/cpp/broker/src/SessionHandlerImpl.cpp b/cpp/broker/src/SessionHandlerImpl.cpp deleted file mode 100644 index 0d8539332c..0000000000 --- a/cpp/broker/src/SessionHandlerImpl.cpp +++ /dev/null @@ -1,405 +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 "SessionHandlerImpl.h" -#include "FanOutExchange.h" -#include "HeadersExchange.h" -#include "Router.h" -#include "TopicExchange.h" -#include "assert.h" - -using namespace std::tr1; -using namespace qpid::broker; -using namespace qpid::io; -using namespace qpid::framing; -using namespace qpid::concurrent; - -SessionHandlerImpl::SessionHandlerImpl(SessionContext* _context, - QueueRegistry* _queues, - ExchangeRegistry* _exchanges, - AutoDelete* _cleaner, - const u_int32_t _timeout) : - context(_context), - client(context), - queues(_queues), - exchanges(_exchanges), - cleaner(_cleaner), - timeout(_timeout), - connectionHandler(new ConnectionHandlerImpl(this)), - channelHandler(new ChannelHandlerImpl(this)), - basicHandler(new BasicHandlerImpl(this)), - exchangeHandler(new ExchangeHandlerImpl(this)), - queueHandler(new QueueHandlerImpl(this)), - framemax(65536), - heartbeat(0) {} - -SessionHandlerImpl::~SessionHandlerImpl(){ - // TODO aconway 2006-09-07: Should be auto_ptr or plain members. - delete channelHandler; - delete connectionHandler; - delete basicHandler; - delete exchangeHandler; - delete queueHandler; -} - -Channel* SessionHandlerImpl::getChannel(u_int16_t channel){ - channel_iterator i = channels.find(channel); - if(i == channels.end()){ - throw ConnectionException(504, "Unknown channel: " + channel); - } - return i->second; -} - -Queue::shared_ptr SessionHandlerImpl::getQueue(const string& name, u_int16_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 = queues->find(name); - if (queue == 0) { - throw ChannelException( 404, "Queue not found: " + name); - } - } - return queue; -} - - -Exchange* SessionHandlerImpl::findExchange(const string& name){ - exchanges->getLock()->acquire(); - Exchange* exchange(exchanges->get(name)); - exchanges->getLock()->release(); - return exchange; -} - -void SessionHandlerImpl::received(qpid::framing::AMQFrame* frame){ - u_int16_t channel = frame->getChannel(); - AMQBody::shared_ptr body = frame->getBody(); - AMQMethodBody::shared_ptr method; - - switch(body->type()) - { - case METHOD_BODY: - method = dynamic_pointer_cast(body); - try{ - method->invoke(*this, channel); - }catch(ChannelException& e){ - channels[channel]->close(); - channels.erase(channel); - client.getChannel().close(channel, e.code, e.text, method->amqpClassId(), method->amqpMethodId()); - }catch(ConnectionException& e){ - client.getConnection().close(0, e.code, e.text, method->amqpClassId(), method->amqpMethodId()); - } - break; - - case HEADER_BODY: - this->handleHeader(channel, dynamic_pointer_cast(body)); - break; - - case CONTENT_BODY: - this->handleContent(channel, dynamic_pointer_cast(body)); - break; - - case HEARTBEAT_BODY: - //channel must be 0 - this->handleHeartbeat(dynamic_pointer_cast(body)); - break; - } -} - -void SessionHandlerImpl::initiated(qpid::framing::ProtocolInitiation* /*header*/){ - //send connection start - FieldTable properties; - string mechanisms("PLAIN"); - string locales("en_US"); - client.getConnection().start(0, 8, 0, properties, mechanisms, locales); -} - -void SessionHandlerImpl::idleOut(){ - -} - -void SessionHandlerImpl::idleIn(){ - -} - -void SessionHandlerImpl::closed(){ - for(channel_iterator i = channels.begin(); i != channels.end(); i = channels.begin()){ - Channel* c = i->second; - channels.erase(i); - c->close(); - delete c; - } - for(queue_iterator i = exclusiveQueues.begin(); i < exclusiveQueues.end(); i = exclusiveQueues.begin()){ - string name = (*i)->getName(); - queues->destroy(name); - exclusiveQueues.erase(i); - } -} - -void SessionHandlerImpl::handleHeader(u_int16_t channel, AMQHeaderBody::shared_ptr body){ - getChannel(channel)->handleHeader(body, Router(*exchanges)); -} - -void SessionHandlerImpl::handleContent(u_int16_t channel, AMQContentBody::shared_ptr body){ - getChannel(channel)->handleContent(body, Router(*exchanges)); -} - -void SessionHandlerImpl::handleHeartbeat(AMQHeartbeatBody::shared_ptr /*body*/){ - std::cout << "SessionHandlerImpl::handleHeartbeat()" << std::endl; -} - -void SessionHandlerImpl::ConnectionHandlerImpl::startOk( - u_int16_t /*channel*/, FieldTable& /*clientProperties*/, string& /*mechanism*/, - string& /*response*/, string& /*locale*/){ - - parent->client.getConnection().tune(0, 100, parent->framemax, parent->heartbeat); -} - -void SessionHandlerImpl::ConnectionHandlerImpl::secureOk(u_int16_t /*channel*/, string& /*response*/){} - -void SessionHandlerImpl::ConnectionHandlerImpl::tuneOk(u_int16_t /*channel*/, u_int16_t /*channelmax*/, u_int32_t framemax, u_int16_t heartbeat){ - parent->framemax = framemax; - parent->heartbeat = heartbeat; -} - -void SessionHandlerImpl::ConnectionHandlerImpl::open(u_int16_t /*channel*/, string& /*virtualHost*/, string& /*capabilities*/, bool /*insist*/){ - string knownhosts; - parent->client.getConnection().openOk(0, knownhosts); -} - -void SessionHandlerImpl::ConnectionHandlerImpl::close( - u_int16_t /*channel*/, u_int16_t /*replyCode*/, string& /*replyText*/, - u_int16_t /*classId*/, u_int16_t /*methodId*/) -{ - parent->client.getConnection().closeOk(0); - parent->context->close(); -} - -void SessionHandlerImpl::ConnectionHandlerImpl::closeOk(u_int16_t /*channel*/){ - parent->context->close(); -} - - - -void SessionHandlerImpl::ChannelHandlerImpl::open(u_int16_t channel, string& /*outOfBand*/){ - parent->channels[channel] = new Channel(parent->context, channel, parent->framemax); - parent->client.getChannel().openOk(channel); -} - -void SessionHandlerImpl::ChannelHandlerImpl::flow(u_int16_t /*channel*/, bool /*active*/){} -void SessionHandlerImpl::ChannelHandlerImpl::flowOk(u_int16_t /*channel*/, bool /*active*/){} - -void SessionHandlerImpl::ChannelHandlerImpl::close(u_int16_t channel, u_int16_t /*replyCode*/, string& /*replyText*/, - u_int16_t /*classId*/, u_int16_t /*methodId*/){ - Channel* c = parent->getChannel(channel); - if(c){ - parent->channels.erase(channel); - c->close(); - delete c; - parent->client.getChannel().closeOk(channel); - } -} - -void SessionHandlerImpl::ChannelHandlerImpl::closeOk(u_int16_t /*channel*/){} - - - -void SessionHandlerImpl::ExchangeHandlerImpl::declare(u_int16_t channel, u_int16_t /*ticket*/, string& exchange, string& type, - bool passive, bool /*durable*/, bool /*autoDelete*/, bool /*internal*/, bool nowait, - FieldTable& /*arguments*/){ - - if(!passive && ( - type != TopicExchange::typeName && - type != DirectExchange::typeName && - type != FanOutExchange::typeName && - type != HeadersExchange::typeName - ) - ) - { - throw ChannelException(540, "Exchange type not implemented: " + type); - } - - parent->exchanges->getLock()->acquire(); - if(!parent->exchanges->get(exchange)){ - if(type == TopicExchange::typeName){ - parent->exchanges->declare(new TopicExchange(exchange)); - }else if(type == DirectExchange::typeName){ - parent->exchanges->declare(new DirectExchange(exchange)); - }else if(type == FanOutExchange::typeName){ - parent->exchanges->declare(new DirectExchange(exchange)); - }else if (type == HeadersExchange::typeName) { - parent->exchanges->declare(new HeadersExchange(exchange)); - } - } - parent->exchanges->getLock()->release(); - if(!nowait){ - parent->client.getExchange().declareOk(channel); - } -} - -void SessionHandlerImpl::ExchangeHandlerImpl::delete_(u_int16_t channel, u_int16_t /*ticket*/, string& exchange, bool /*ifUnused*/, bool nowait){ - //TODO: implement unused - parent->exchanges->getLock()->acquire(); - parent->exchanges->destroy(exchange); - parent->exchanges->getLock()->release(); - if(!nowait) parent->client.getExchange().deleteOk(channel); -} - -void SessionHandlerImpl::QueueHandlerImpl::declare(u_int16_t channel, u_int16_t /*ticket*/, string& name, - bool passive, bool durable, bool exclusive, - bool autoDelete, bool nowait, FieldTable& /*arguments*/){ - Queue::shared_ptr queue; - if (passive && !name.empty()) { - queue = parent->getQueue(name, channel); - } else { - std::pair queue_created = parent->queues->declare(name, durable, autoDelete ? parent->timeout : 0, exclusive ? parent : 0); - queue = queue_created.first; - assert(queue); - if (queue_created.second) { // This is a new queue - parent->getChannel(channel)->setDefaultQueue(queue); - //add default binding: - parent->exchanges->getDefault()->bind(queue, name, 0); - if(exclusive){ - parent->exclusiveQueues.push_back(queue); - } else if(autoDelete){ - parent->cleaner->add(queue); - } - } - } - if(exclusive && !queue->isExclusiveOwner(parent)){ - throw ChannelException(405, "Cannot grant exclusive access to queue"); - } - if(!nowait){ - name = queue->getName(); - parent->client.getQueue().declareOk(channel, name, queue->getMessageCount(), queue->getConsumerCount()); - } -} - -void SessionHandlerImpl::QueueHandlerImpl::bind(u_int16_t channel, u_int16_t /*ticket*/, string& queueName, - string& exchangeName, string& routingKey, bool nowait, - FieldTable& arguments){ - - Queue::shared_ptr queue = parent->getQueue(queueName, channel); - Exchange* exchange = parent->exchanges->get(exchangeName); - if(exchange){ - if(routingKey.empty() && queueName.empty()) routingKey = queue->getName(); - exchange->bind(queue, routingKey, &arguments); - if(!nowait) parent->client.getQueue().bindOk(channel); - }else{ - throw ChannelException(404, "Bind failed. No such exchange: " + exchangeName); - } -} - -void SessionHandlerImpl::QueueHandlerImpl::purge(u_int16_t channel, u_int16_t /*ticket*/, string& queueName, bool nowait){ - - Queue::shared_ptr queue = parent->getQueue(queueName, channel); - int count = queue->purge(); - if(!nowait) parent->client.getQueue().purgeOk(channel, count); -} - -void SessionHandlerImpl::QueueHandlerImpl::delete_(u_int16_t channel, u_int16_t /*ticket*/, string& queue, - bool ifUnused, bool ifEmpty, bool nowait){ - ChannelException error(0, ""); - int count(0); - Queue::shared_ptr q = parent->getQueue(queue, channel); - 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(parent)){ - queue_iterator i = find(parent->exclusiveQueues.begin(), parent->exclusiveQueues.end(), q); - if(i < parent->exclusiveQueues.end()) parent->exclusiveQueues.erase(i); - } - count = q->getMessageCount(); - parent->queues->destroy(queue); - } - if(!nowait) parent->client.getQueue().deleteOk(channel, count); -} - - - - -void SessionHandlerImpl::BasicHandlerImpl::qos(u_int16_t channel, u_int32_t prefetchSize, u_int16_t prefetchCount, bool /*global*/){ - //TODO: handle global - parent->getChannel(channel)->setPrefetchSize(prefetchSize); - parent->getChannel(channel)->setPrefetchCount(prefetchCount); - parent->client.getBasic().qosOk(channel); -} - -void SessionHandlerImpl::BasicHandlerImpl::consume(u_int16_t channelId, u_int16_t /*ticket*/, - string& queueName, string& consumerTag, - bool noLocal, bool noAck, bool exclusive, - bool nowait){ - - Queue::shared_ptr queue = parent->getQueue(queueName, channelId); - Channel* channel = parent->channels[channelId]; - if(!consumerTag.empty() && channel->exists(consumerTag)){ - throw ConnectionException(530, "Consumer tags must be unique"); - } - - try{ - channel->consume(consumerTag, queue, !noAck, exclusive, noLocal ? parent : 0); - if(!nowait) parent->client.getBasic().consumeOk(channelId, consumerTag); - - //allow messages to be dispatched if required as there is now a consumer: - queue->dispatch(); - }catch(ExclusiveAccessException& e){ - if(exclusive) throw ChannelException(403, "Exclusive access cannot be granted"); - else throw ChannelException(403, "Access would violate previously granted exclusivity"); - } - -} - -void SessionHandlerImpl::BasicHandlerImpl::cancel(u_int16_t channel, string& consumerTag, bool nowait){ - parent->getChannel(channel)->cancel(consumerTag); - if(!nowait) parent->client.getBasic().cancelOk(channel, consumerTag); -} - -void SessionHandlerImpl::BasicHandlerImpl::publish(u_int16_t channel, u_int16_t /*ticket*/, - string& exchange, string& routingKey, - bool mandatory, bool immediate){ - - Message* msg = new Message(parent, exchange, routingKey, mandatory, immediate); - parent->getChannel(channel)->handlePublish(msg); -} - -void SessionHandlerImpl::BasicHandlerImpl::get(u_int16_t channelId, u_int16_t /*ticket*/, string& queueName, bool noAck){ - Queue::shared_ptr queue = parent->getQueue(queueName, channelId); - if(!parent->getChannel(channelId)->get(queue, !noAck)){ - string clusterId;//not used, part of an imatix hack - parent->client.getBasic().getEmpty(channelId, clusterId); - } -} - -void SessionHandlerImpl::BasicHandlerImpl::ack(u_int16_t channel, u_int64_t deliveryTag, bool multiple){ - try{ - parent->getChannel(channel)->ack(deliveryTag, multiple); - }catch(InvalidAckException& e){ - throw ConnectionException(530, "Received ack for unrecognised delivery tag"); - } -} - -void SessionHandlerImpl::BasicHandlerImpl::reject(u_int16_t /*channel*/, u_int64_t /*deliveryTag*/, bool /*requeue*/){} - -void SessionHandlerImpl::BasicHandlerImpl::recover(u_int16_t channel, bool requeue){ - parent->getChannel(channel)->recover(requeue); -} - diff --git a/cpp/broker/src/TopicExchange.cpp b/cpp/broker/src/TopicExchange.cpp deleted file mode 100644 index 53977747c4..0000000000 --- a/cpp/broker/src/TopicExchange.cpp +++ /dev/null @@ -1,163 +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 "TopicExchange.h" -#include "ExchangeBinding.h" -#include - -using namespace qpid::broker; -using namespace qpid::framing; - - -// 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; -} - -size_t Tokens::Hash::operator()(const Tokens& p) const { - size_t hash = 0; - for (Tokens::const_iterator i = p.begin(); i != p.end(); ++i) { - hash += std::tr1::hash()(*i); - } - return hash; -} - -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 more efficient Tokens impl that can operate on a string in place. -// -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, FieldTable* args){ - lock.acquire(); - TopicPattern routingPattern(routingKey); - bindings[routingPattern].push_back(queue); - queue->bound(new ExchangeBinding(this, queue, routingKey, args)); - lock.release(); -} - -void TopicExchange::unbind(Queue::shared_ptr queue, const string& routingKey, FieldTable* /*args*/){ - lock.acquire(); - 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); - lock.release(); -} - - -void TopicExchange::route(Message::shared_ptr& msg, const string& routingKey, FieldTable* /*args*/){ - lock.acquire(); - 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++){ - (*j)->deliver(msg); - } - } - } - lock.release(); -} - -TopicExchange::~TopicExchange() {} - -const std::string TopicExchange::typeName("topic"); - - diff --git a/cpp/broker/test/ChannelTest.cpp b/cpp/broker/test/ChannelTest.cpp deleted file mode 100644 index 001a0d9c00..0000000000 --- a/cpp/broker/test/ChannelTest.cpp +++ /dev/null @@ -1,162 +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 "Channel.h" -#include "Message.h" -#include -#include -#include - -using namespace std::tr1; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::concurrent; - -struct DummyRouter{ - Message::shared_ptr last; - - void operator()(Message::shared_ptr& msg){ - last = msg; - } -}; - -struct DummyHandler : OutputHandler{ - std::vector frames; - - virtual void send(AMQFrame* frame){ - frames.push_back(frame); - } -}; - - -class ChannelTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(ChannelTest); - CPPUNIT_TEST(testIncoming); - CPPUNIT_TEST(testConsumerMgmt); - CPPUNIT_TEST(testDeliveryNoAck); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testIncoming(){ - Channel channel(0, 0, 10000); - string routingKey("my_routing_key"); - channel.handlePublish(new Message(0, "test", routingKey, false, false)); - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - header->setContentSize(14); - string data1("abcdefg"); - string data2("hijklmn"); - AMQContentBody::shared_ptr part1(new AMQContentBody(data1)); - AMQContentBody::shared_ptr part2(new AMQContentBody(data2)); - - CPPUNIT_ASSERT(!channel.handleHeader(header, DummyRouter()).last); - CPPUNIT_ASSERT(!channel.handleContent(part1, DummyRouter()).last); - DummyRouter router = channel.handleContent(part2, DummyRouter()); - CPPUNIT_ASSERT(router.last); - CPPUNIT_ASSERT_EQUAL(routingKey, router.last->getRoutingKey()); - } - - void testConsumerMgmt(){ - Queue::shared_ptr queue(new Queue("my_queue")); - Channel channel(0, 0, 0); - CPPUNIT_ASSERT(!channel.exists("my_consumer")); - - ConnectionToken* owner; - 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((u_int32_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((u_int32_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((u_int32_t) 0, queue->getConsumerCount()); - } - - void testDeliveryNoAck(){ - DummyHandler handler; - Channel channel(&handler, 7, 10000); - - Message::shared_ptr msg(new Message(0, "test", "my_routing_key", false, false)); - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - header->setContentSize(14); - msg->setHeader(header); - AMQContentBody::shared_ptr body(new AMQContentBody("abcdefghijklmn")); - msg->addContent(body); - - 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) 3, handler.frames.size()); - CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[0]->getChannel()); - CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[1]->getChannel()); - CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[2]->getChannel()); - BasicDeliverBody::shared_ptr deliver(dynamic_pointer_cast(handler.frames[0]->getBody())); - AMQHeaderBody::shared_ptr contentHeader(dynamic_pointer_cast(handler.frames[1]->getBody())); - AMQContentBody::shared_ptr contentBody(dynamic_pointer_cast(handler.frames[2]->getBody())); - CPPUNIT_ASSERT(deliver); - CPPUNIT_ASSERT(contentHeader); - CPPUNIT_ASSERT(contentBody); - CPPUNIT_ASSERT_EQUAL(string("abcdefghijklmn"), contentBody->getData()); - } - - void testDeliveryAndRecovery(){ - DummyHandler handler; - Channel channel(&handler, 7, 10000); - - Message::shared_ptr msg(new Message(0, "test", "my_routing_key", false, false)); - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - header->setContentSize(14); - msg->setHeader(header); - AMQContentBody::shared_ptr body(new AMQContentBody("abcdefghijklmn")); - msg->addContent(body); - - Queue::shared_ptr queue(new Queue("my_queue")); - ConnectionToken* owner; - string tag("ack"); - channel.consume(tag, queue, true, false, owner); - - queue->deliver(msg); - CPPUNIT_ASSERT_EQUAL((size_t) 3, handler.frames.size()); - CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[0]->getChannel()); - CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[1]->getChannel()); - CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[2]->getChannel()); - BasicDeliverBody::shared_ptr deliver(dynamic_pointer_cast(handler.frames[0]->getBody())); - AMQHeaderBody::shared_ptr contentHeader(dynamic_pointer_cast(handler.frames[1]->getBody())); - AMQContentBody::shared_ptr contentBody(dynamic_pointer_cast(handler.frames[2]->getBody())); - CPPUNIT_ASSERT(deliver); - CPPUNIT_ASSERT(contentHeader); - CPPUNIT_ASSERT(contentBody); - CPPUNIT_ASSERT_EQUAL(string("abcdefghijklmn"), contentBody->getData()); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(ChannelTest); diff --git a/cpp/broker/test/ExchangeTest.cpp b/cpp/broker/test/ExchangeTest.cpp deleted file mode 100644 index 8c702ff836..0000000000 --- a/cpp/broker/test/ExchangeTest.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 "DirectExchange.h" -#include "Exchange.h" -#include "Queue.h" -#include "TopicExchange.h" -#include -#include - -using namespace qpid::broker; -using namespace qpid::concurrent; - -class ExchangeTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(ExchangeTest); - CPPUNIT_TEST(testMe); - CPPUNIT_TEST_SUITE_END(); - - public: - - // TODO aconway 2006-09-12: Need more detailed tests. - - void testMe() - { - Queue::shared_ptr queue(new Queue("queue", true, true)); - Queue::shared_ptr queue2(new Queue("queue2", true, 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 msg = Message::shared_ptr(new Message(0, "e", "A", true, true)); - topic.route(msg, "abc", 0); - direct.route(msg, "abc", 0); - - // TODO aconway 2006-09-12: TODO Why no assertions? - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(ExchangeTest); diff --git a/cpp/broker/test/HeadersExchangeTest.cpp b/cpp/broker/test/HeadersExchangeTest.cpp deleted file mode 100644 index d56e00543d..0000000000 --- a/cpp/broker/test/HeadersExchangeTest.cpp +++ /dev/null @@ -1,112 +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 "HeadersExchange.h" -#include "FieldTable.h" -#include "Value.h" -#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/cpp/broker/test/Makefile b/cpp/broker/test/Makefile deleted file mode 100644 index 172ce564bf..0000000000 --- a/cpp/broker/test/Makefile +++ /dev/null @@ -1,20 +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. -# - -QPID_HOME = ../../.. -LDLIBS=-lapr-1 -lcppunit $(COMMON_LIB) $(BROKER_LIB) -include ${QPID_HOME}/cpp/test_plugins.mk - diff --git a/cpp/broker/test/MessageTest.cpp b/cpp/broker/test/MessageTest.cpp deleted file mode 100644 index fc2c6e01bb..0000000000 --- a/cpp/broker/test/MessageTest.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "APRBase.h" -#include "Message.h" -#include -#include - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::concurrent; - -class MessageTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(MessageTest); - CPPUNIT_TEST(testMe); - CPPUNIT_TEST_SUITE_END(); - - public: - - // TODO aconway 2006-09-12: Need more detailed tests, - // need tests to assert something! - // - void testMe() - { - APRBase::increment(); - const int size(10); - for(int i = 0; i < size; i++){ - Message::shared_ptr msg = Message::shared_ptr(new Message(0, "A", "B", true, true)); - msg->setHeader(AMQHeaderBody::shared_ptr(new AMQHeaderBody())); - msg->addContent(AMQContentBody::shared_ptr(new AMQContentBody())); - msg.reset(); - } - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(MessageTest); - diff --git a/cpp/broker/test/QueueRegistryTest.cpp b/cpp/broker/test/QueueRegistryTest.cpp deleted file mode 100644 index bd739aaad5..0000000000 --- a/cpp/broker/test/QueueRegistryTest.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "QueueRegistry.h" -#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/cpp/broker/test/QueueTest.cpp b/cpp/broker/test/QueueTest.cpp deleted file mode 100644 index 1b4eb814cb..0000000000 --- a/cpp/broker/test/QueueTest.cpp +++ /dev/null @@ -1,176 +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 "Queue.h" -#include "QueueRegistry.h" -#include -#include - -using namespace qpid::broker; -using namespace qpid::concurrent; - - -class TestBinding : public virtual Binding{ - bool cancelled; - -public: - TestBinding(); - virtual void cancel(); - bool isCancelled(); -}; - -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(testBinding); - CPPUNIT_TEST(testRegistry); - CPPUNIT_TEST(testDequeue); - CPPUNIT_TEST_SUITE_END(); - - public: - void testConsumers(){ - Queue::shared_ptr queue(new Queue("my_queue", true, true)); - - //Test adding consumers: - TestConsumer c1; - TestConsumer c2; - queue->consume(&c1); - queue->consume(&c2); - - CPPUNIT_ASSERT_EQUAL(u_int32_t(2), queue->getConsumerCount()); - - //Test basic delivery: - Message::shared_ptr msg1 = Message::shared_ptr(new Message(0, "e", "A", true, true)); - Message::shared_ptr msg2 = Message::shared_ptr(new Message(0, "e", "B", true, true)); - Message::shared_ptr msg3 = Message::shared_ptr(new Message(0, "e", "C", true, true)); - - 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(u_int32_t(1), queue->getConsumerCount()); - queue->cancel(&c2); - CPPUNIT_ASSERT_EQUAL(u_int32_t(0), queue->getConsumerCount()); - } - - void testBinding(){ - Queue::shared_ptr queue(new Queue("my_queue", true, true)); - //Test bindings: - TestBinding a; - TestBinding b; - queue->bound(&a); - queue->bound(&b); - - queue.reset(); - - CPPUNIT_ASSERT(a.isCancelled()); - CPPUNIT_ASSERT(b.isCancelled()); - } - - 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, true)); - - Message::shared_ptr msg1 = Message::shared_ptr(new Message(0, "e", "A", true, true)); - Message::shared_ptr msg2 = Message::shared_ptr(new Message(0, "e", "B", true, true)); - Message::shared_ptr msg3 = Message::shared_ptr(new Message(0, "e", "C", true, true)); - Message::shared_ptr received; - - queue->deliver(msg1); - queue->deliver(msg2); - queue->deliver(msg3); - - CPPUNIT_ASSERT_EQUAL(u_int32_t(3), queue->getMessageCount()); - - received = queue->dequeue(); - CPPUNIT_ASSERT_EQUAL(msg1.get(), received.get()); - CPPUNIT_ASSERT_EQUAL(u_int32_t(2), queue->getMessageCount()); - - received = queue->dequeue(); - CPPUNIT_ASSERT_EQUAL(msg2.get(), received.get()); - CPPUNIT_ASSERT_EQUAL(u_int32_t(1), queue->getMessageCount()); - - TestConsumer consumer; - queue->consume(&consumer); - queue->dispatch(); - CPPUNIT_ASSERT_EQUAL(msg3.get(), consumer.last.get()); - CPPUNIT_ASSERT_EQUAL(u_int32_t(0), queue->getMessageCount()); - - received = queue->dequeue(); - CPPUNIT_ASSERT(!received); - CPPUNIT_ASSERT_EQUAL(u_int32_t(0), queue->getMessageCount()); - - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(QueueTest); - -//TestBinding -TestBinding::TestBinding() : cancelled(false) {} - -void TestBinding::cancel(){ - CPPUNIT_ASSERT(!cancelled); - cancelled = true; -} - -bool TestBinding::isCancelled(){ - return cancelled; -} - -//TestConsumer -bool TestConsumer::deliver(Message::shared_ptr& msg){ - last = msg; - return true; -} - diff --git a/cpp/broker/test/RouterTest.cpp b/cpp/broker/test/RouterTest.cpp deleted file mode 100644 index b1d4b9739f..0000000000 --- a/cpp/broker/test/RouterTest.cpp +++ /dev/null @@ -1,86 +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 "Channel.h" -#include "Exchange.h" -#include "ExchangeRegistry.h" -#include "Message.h" -#include "Router.h" -#include -#include -#include - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::concurrent; - -struct TestExchange : public Exchange{ - Message::shared_ptr msg; - string routingKey; - FieldTable* args; - - TestExchange() : Exchange("test"), args(0) {} - - void bind(Queue::shared_ptr /*queue*/, const string& /*routingKey*/, FieldTable* /*args*/){} - - void unbind(Queue::shared_ptr /*queue*/, const string& /*routingKey*/, FieldTable* /*args*/){ } - - void route(Message::shared_ptr& _msg, const string& _routingKey, FieldTable* _args){ - msg = _msg; - routingKey = _routingKey; - args = _args; - } -}; - -class RouterTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(RouterTest); - CPPUNIT_TEST(test); - CPPUNIT_TEST_SUITE_END(); - - public: - - void test() - { - ExchangeRegistry registry; - TestExchange* exchange = new TestExchange(); - registry.declare(exchange); - - string routingKey("my_routing_key"); - string name("name"); - string value("value"); - Message::shared_ptr msg(new Message(0, "test", routingKey, false, false)); - AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); - - dynamic_cast(header->getProperties())->getHeaders().setString(name, value); - msg->setHeader(header); - - Router router(registry); - router(msg); - - CPPUNIT_ASSERT(exchange->msg); - CPPUNIT_ASSERT_EQUAL(msg, exchange->msg); - CPPUNIT_ASSERT_EQUAL(routingKey, exchange->msg->getRoutingKey()); - CPPUNIT_ASSERT_EQUAL(routingKey, exchange->routingKey); - CPPUNIT_ASSERT_EQUAL(value, exchange->args->getString(name)); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(RouterTest); - diff --git a/cpp/broker/test/TopicExchangeTest.cpp b/cpp/broker/test/TopicExchangeTest.cpp deleted file mode 100644 index d9b49fc603..0000000000 --- a/cpp/broker/test/TopicExchangeTest.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "TopicExchange.h" -#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. -// TODO aconway 2006-09-19: Make it a template and put it in a shared test lib. -// -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/cpp/broker/test/ValueTest.cpp b/cpp/broker/test/ValueTest.cpp deleted file mode 100644 index ec9659e603..0000000000 --- a/cpp/broker/test/ValueTest.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "Value.h" -#include - -using namespace qpid::framing; - - -// Allow CPPUNIT_EQUALS to print a Tokens. -// TODO aconway 2006-09-19: Make it a template and put it in a shared test lib. -// -template -CppUnit::OStringStream& operator <<(CppUnit::OStringStream& out, - const ValueOps& v) -{ - out << v.getValue(); - return out; -} - - -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/cpp/client/Makefile b/cpp/client/Makefile deleted file mode 100644 index f3c8b11a7a..0000000000 --- a/cpp/client/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (c) 2006 The Apache Software Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# -# Build client library. -# - -QPID_HOME = ../.. -include ${QPID_HOME}/cpp/options.mk - -SOURCES := $(wildcard src/*.cpp) -OBJECTS := $(subst .cpp,.o,$(SOURCES)) -CLIENT_LIB=$(LIB_DIR)/libqpid_client.so.1.0 - -.PHONY: all clean - -all: $(CLIENT_LIB) - @$(MAKE) -C test all - -clean: - -@rm -f $(CLIENT_LIB) $(OBJECTS) src/*.d - $(MAKE) -C test clean - -$(CLIENT_LIB): $(OBJECTS) - $(CXX) -shared -o $@ $^ $(LDFLAGS) $(COMMON_LIB) - -# Dependencies --include $(SOURCES:.cpp=.d) diff --git a/cpp/client/inc/Channel.h b/cpp/client/inc/Channel.h deleted file mode 100644 index debecf922e..0000000000 --- a/cpp/client/inc/Channel.h +++ /dev/null @@ -1,127 +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 "sys/types.h" - -#ifndef _Channel_ -#define _Channel_ - -#include "amqp_framing.h" - -#include "ThreadFactory.h" - -#include "Connection.h" -#include "Exchange.h" -#include "IncomingMessage.h" -#include "Message.h" -#include "MessageListener.h" -#include "Queue.h" -#include "ResponseHandler.h" -#include "ReturnedMessageHandler.h" - -namespace qpid { -namespace client { - enum ack_modes {NO_ACK=0, AUTO_ACK=1, LAZY_ACK=2, CLIENT_ACK=3}; - - class Channel : private virtual qpid::framing::BodyHandler, public virtual qpid::concurrent::Runnable{ - struct Consumer{ - MessageListener* listener; - int ackMode; - int count; - u_int64_t lastDeliveryTag; - }; - typedef std::map::iterator consumer_iterator; - - u_int16_t id; - Connection* con; - qpid::concurrent::ThreadFactory* threadFactory; - qpid::concurrent::Thread* dispatcher; - qpid::framing::OutputHandler* out; - IncomingMessage* incoming; - ResponseHandler responses; - std::queue messages;//holds returned messages or those delivered for a consume - IncomingMessage* retrieved;//holds response to basic.get - qpid::concurrent::Monitor* dispatchMonitor; - qpid::concurrent::Monitor* retrievalMonitor; - std::map consumers; - ReturnedMessageHandler* returnsHandler; - bool closed; - - u_int16_t prefetch; - const bool transactional; - - void enqueue(); - void retrieve(Message& msg); - IncomingMessage* dequeue(); - void dispatch(); - void stop(); - void sendAndReceive(qpid::framing::AMQFrame* frame, const qpid::framing::AMQMethodBody& body); - void deliver(Consumer* consumer, Message& msg); - void setQos(); - void cancelAll(); - - virtual void handleMethod(qpid::framing::AMQMethodBody::shared_ptr body); - virtual void handleHeader(qpid::framing::AMQHeaderBody::shared_ptr body); - virtual void handleContent(qpid::framing::AMQContentBody::shared_ptr body); - virtual void handleHeartbeat(qpid::framing::AMQHeartbeatBody::shared_ptr body); - - public: - Channel(bool transactional = false, u_int16_t prefetch = 500); - ~Channel(); - - void declareExchange(Exchange& exchange, bool synch = true); - void deleteExchange(Exchange& exchange, bool synch = true); - void declareQueue(Queue& queue, bool synch = true); - void deleteQueue(Queue& queue, bool ifunused = false, bool ifempty = false, bool synch = true); - void bind(const Exchange& exchange, const Queue& queue, const std::string& key, - const qpid::framing::FieldTable& args, bool synch = true); - void consume(Queue& queue, std::string& tag, MessageListener* listener, - int ackMode = NO_ACK, bool noLocal = false, bool synch = true); - void cancel(std::string& tag, bool synch = true); - bool get(Message& msg, const Queue& queue, int ackMode = NO_ACK); - void publish(Message& msg, const Exchange& exchange, const std::string& routingKey, - bool mandatory = false, bool immediate = false); - - void commit(); - void rollback(); - - void setPrefetch(u_int16_t prefetch); - - /** - * Start message dispatching on a new thread - */ - void start(); - /** - * Do message dispatching on this thread - */ - void run(); - - void close(); - - void setReturnedMessageHandler(ReturnedMessageHandler* handler); - - friend class Connection; - }; - -} -} - - -#endif diff --git a/cpp/client/inc/Connection.h b/cpp/client/inc/Connection.h deleted file mode 100644 index 89169e92b1..0000000000 --- a/cpp/client/inc/Connection.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include - -#ifndef _Connection_ -#define _Connection_ - -#include "QpidError.h" -#include "Connector.h" -#include "ShutdownHandler.h" -#include "TimeoutHandler.h" - -#include "amqp_framing.h" -#include "Exchange.h" -#include "IncomingMessage.h" -#include "Message.h" -#include "MessageListener.h" -#include "Queue.h" -#include "ResponseHandler.h" - -namespace qpid { -namespace client { - - class Channel; - - class Connection : public virtual qpid::framing::InputHandler, - public virtual qpid::io::TimeoutHandler, - public virtual qpid::io::ShutdownHandler, - private virtual qpid::framing::BodyHandler{ - - typedef std::map::iterator iterator; - - static u_int16_t channelIdCounter; - - std::string host; - int port; - const u_int32_t max_frame_size; - std::map channels; - qpid::io::Connector* connector; - qpid::framing::OutputHandler* out; - ResponseHandler responses; - volatile bool closed; - - void channelException(Channel* channel, qpid::framing::AMQMethodBody* body, QpidError& e); - void error(int code, const string& msg, int classid = 0, int methodid = 0); - void closeChannel(Channel* channel, u_int16_t code, string& text, u_int16_t classId = 0, u_int16_t methodId = 0); - void sendAndReceive(qpid::framing::AMQFrame* frame, const qpid::framing::AMQMethodBody& body); - - virtual void handleMethod(qpid::framing::AMQMethodBody::shared_ptr body); - virtual void handleHeader(qpid::framing::AMQHeaderBody::shared_ptr body); - virtual void handleContent(qpid::framing::AMQContentBody::shared_ptr body); - virtual void handleHeartbeat(qpid::framing::AMQHeartbeatBody::shared_ptr body); - - public: - - Connection(bool debug = false, u_int32_t max_frame_size = 65536); - ~Connection(); - void open(const std::string& host, int port = 5672, - const std::string& uid = "guest", const std::string& pwd = "guest", - const std::string& virtualhost = "/"); - void close(); - void openChannel(Channel* channel); - /* - * Requests that the server close this channel, then removes - * the association to the channel from this connection - */ - void closeChannel(Channel* channel); - /* - * Removes the channel from association with this connection, - * without sending a close request to the server. - */ - void removeChannel(Channel* channel); - - virtual void received(qpid::framing::AMQFrame* frame); - - virtual void idleOut(); - virtual void idleIn(); - - virtual void shutdown(); - - inline u_int32_t getMaxFrameSize(){ return max_frame_size; } - }; - - -} -} - - -#endif diff --git a/cpp/client/inc/Exchange.h b/cpp/client/inc/Exchange.h deleted file mode 100644 index 66593a41cc..0000000000 --- a/cpp/client/inc/Exchange.h +++ /dev/null @@ -1,49 +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 - -#ifndef _Exchange_ -#define _Exchange_ - -namespace qpid { -namespace client { - - class Exchange{ - const std::string name; - const std::string type; - - public: - - static const std::string DIRECT_EXCHANGE; - static const std::string TOPIC_EXCHANGE; - static const std::string HEADERS_EXCHANGE; - - static const Exchange DEFAULT_DIRECT_EXCHANGE; - static const Exchange DEFAULT_TOPIC_EXCHANGE; - static const Exchange DEFAULT_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/cpp/client/inc/IncomingMessage.h b/cpp/client/inc/IncomingMessage.h deleted file mode 100644 index 90fed17ee0..0000000000 --- a/cpp/client/inc/IncomingMessage.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include -#include "amqp_framing.h" - -#ifndef _IncomingMessage_ -#define _IncomingMessage_ - -#include "Message.h" - -namespace qpid { -namespace client { - - class IncomingMessage{ - //content will be preceded by one of these method frames - qpid::framing::BasicDeliverBody::shared_ptr delivered; - qpid::framing::BasicReturnBody::shared_ptr returned; - qpid::framing::BasicGetOkBody::shared_ptr response; - qpid::framing::AMQHeaderBody::shared_ptr header; - std::vector content; - - u_int64_t contentSize(); - public: - IncomingMessage(qpid::framing::BasicDeliverBody::shared_ptr intro); - IncomingMessage(qpid::framing::BasicReturnBody::shared_ptr intro); - IncomingMessage(qpid::framing::BasicGetOkBody::shared_ptr intro); - ~IncomingMessage(); - void setHeader(qpid::framing::AMQHeaderBody::shared_ptr header); - void addContent(qpid::framing::AMQContentBody::shared_ptr content); - bool isComplete(); - bool isReturn(); - bool isDelivery(); - bool isResponse(); - const string& getConsumerTag();//only relevant if isDelivery() - qpid::framing::AMQHeaderBody::shared_ptr& getHeader(); - u_int64_t getDeliveryTag(); - void getData(string& data); - }; - -} -} - - -#endif diff --git a/cpp/client/inc/Message.h b/cpp/client/inc/Message.h deleted file mode 100644 index fc3ec34bcf..0000000000 --- a/cpp/client/inc/Message.h +++ /dev/null @@ -1,86 +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 "amqp_framing.h" - -#ifndef _Message_ -#define _Message_ - - -namespace qpid { -namespace client { - - class Message{ - qpid::framing::AMQHeaderBody::shared_ptr header; - string data; - bool redelivered; - u_int64_t deliveryTag; - - qpid::framing::BasicHeaderProperties* getHeaderProperties(); - Message(qpid::framing::AMQHeaderBody::shared_ptr& header); - public: - Message(); - ~Message(); - - inline std::string getData(){ return data; } - inline void setData(const std::string& _data){ data = _data; } - - inline bool isRedelivered(){ return redelivered; } - inline void setRedelivered(bool _redelivered){ redelivered = _redelivered; } - - inline u_int64_t getDeliveryTag(){ return deliveryTag; } - - std::string& getContentType(); - std::string& getContentEncoding(); - qpid::framing::FieldTable& getHeaders(); - u_int8_t getDeliveryMode(); - u_int8_t getPriority(); - std::string& getCorrelationId(); - std::string& getReplyTo(); - std::string& getExpiration(); - std::string& getMessageId(); - u_int64_t getTimestamp(); - std::string& getType(); - std::string& getUserId(); - std::string& getAppId(); - std::string& getClusterId(); - - void setContentType(std::string& type); - void setContentEncoding(std::string& encoding); - void setHeaders(qpid::framing::FieldTable& headers); - void setDeliveryMode(u_int8_t mode); - void setPriority(u_int8_t priority); - void setCorrelationId(std::string& correlationId); - void setReplyTo(std::string& replyTo); - void setExpiration(std::string& expiration); - void setMessageId(std::string& messageId); - void setTimestamp(u_int64_t timestamp); - void setType(std::string& type); - void setUserId(std::string& userId); - void setAppId(std::string& appId); - void setClusterId(std::string& clusterId); - - - friend class Channel; - }; - -} -} - - -#endif diff --git a/cpp/client/inc/MessageListener.h b/cpp/client/inc/MessageListener.h deleted file mode 100644 index 81b80ff5cb..0000000000 --- a/cpp/client/inc/MessageListener.h +++ /dev/null @@ -1,38 +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 - -#ifndef _MessageListener_ -#define _MessageListener_ - -#include "Message.h" - -namespace qpid { -namespace client { - - class MessageListener{ - public: - virtual ~MessageListener(); - virtual void received(Message& msg) = 0; - }; - -} -} - - -#endif diff --git a/cpp/client/inc/Queue.h b/cpp/client/inc/Queue.h deleted file mode 100644 index e0964af774..0000000000 --- a/cpp/client/inc/Queue.h +++ /dev/null @@ -1,47 +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 - -#ifndef _Queue_ -#define _Queue_ - -namespace qpid { -namespace client { - - class Queue{ - std::string name; - const bool autodelete; - const bool exclusive; - - public: - - Queue(); - Queue(std::string name); - Queue(std::string name, bool temp); - Queue(std::string name, bool autodelete, bool exclusive); - const std::string& getName() const; - void setName(const std::string&); - bool isAutoDelete() const; - bool isExclusive() const; - }; - -} -} - - -#endif diff --git a/cpp/client/inc/ResponseHandler.h b/cpp/client/inc/ResponseHandler.h deleted file mode 100644 index f5392c954d..0000000000 --- a/cpp/client/inc/ResponseHandler.h +++ /dev/null @@ -1,49 +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 "amqp_framing.h" -#include "Monitor.h" - -#ifndef _ResponseHandler_ -#define _ResponseHandler_ - -namespace qpid { - namespace client { - - class ResponseHandler{ - bool waiting; - qpid::framing::AMQMethodBody::shared_ptr response; - qpid::concurrent::Monitor* monitor; - - public: - ResponseHandler(); - ~ResponseHandler(); - inline bool isWaiting(){ return waiting; } - inline qpid::framing::AMQMethodBody::shared_ptr getResponse(){ return response; } - bool validate(const qpid::framing::AMQMethodBody& expected); - void waitForResponse(); - void signalResponse(qpid::framing::AMQMethodBody::shared_ptr response); - void receive(const qpid::framing::AMQMethodBody& expected); - void expect();//must be called before calling receive - }; - - } -} - - -#endif diff --git a/cpp/client/inc/ReturnedMessageHandler.h b/cpp/client/inc/ReturnedMessageHandler.h deleted file mode 100644 index 0d30d0ab32..0000000000 --- a/cpp/client/inc/ReturnedMessageHandler.h +++ /dev/null @@ -1,38 +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 - -#ifndef _ReturnedMessageHandler_ -#define _ReturnedMessageHandler_ - -#include "Message.h" - -namespace qpid { -namespace client { - - class ReturnedMessageHandler{ - public: - virtual ~ReturnedMessageHandler(); - virtual void returned(Message& msg) = 0; - }; - -} -} - - -#endif diff --git a/cpp/client/src/Channel.cpp b/cpp/client/src/Channel.cpp deleted file mode 100644 index cf2f5bc081..0000000000 --- a/cpp/client/src/Channel.cpp +++ /dev/null @@ -1,438 +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 "Channel.h" -#include "MonitorImpl.h" -#include "ThreadFactoryImpl.h" -#include "Message.h" -#include "QpidError.h" - -using namespace std::tr1;//to use dynamic_pointer_cast -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::concurrent; - -Channel::Channel(bool _transactional, u_int16_t _prefetch) : - id(0), - con(0), - dispatcher(0), - out(0), - incoming(0), - closed(true), - prefetch(_prefetch), - transactional(_transactional) -{ - threadFactory = new ThreadFactoryImpl(); - dispatchMonitor = new MonitorImpl(); - retrievalMonitor = new MonitorImpl(); -} - -Channel::~Channel(){ - if(dispatcher){ - stop(); - delete dispatcher; - } - delete retrievalMonitor; - delete dispatchMonitor; - delete threadFactory; -} - -void Channel::setPrefetch(u_int16_t _prefetch){ - prefetch = _prefetch; - if(con != 0 && out != 0){ - setQos(); - } -} - -void Channel::setQos(){ - sendAndReceive(new AMQFrame(id, new BasicQosBody(0, prefetch, false)), basic_qos_ok); - if(transactional){ - sendAndReceive(new AMQFrame(id, new TxSelectBody()), tx_select_ok); - } -} - -void Channel::declareExchange(Exchange& exchange, bool synch){ - string name = exchange.getName(); - string type = exchange.getType(); - FieldTable args; - AMQFrame* frame = new AMQFrame(id, new ExchangeDeclareBody(0, name, type, false, false, false, false, !synch, args)); - if(synch){ - sendAndReceive(frame, exchange_declare_ok); - }else{ - out->send(frame); - } -} - -void Channel::deleteExchange(Exchange& exchange, bool synch){ - string name = exchange.getName(); - AMQFrame* frame = new AMQFrame(id, new ExchangeDeleteBody(0, name, false, !synch)); - if(synch){ - sendAndReceive(frame, exchange_delete_ok); - }else{ - out->send(frame); - } -} - -void Channel::declareQueue(Queue& queue, bool synch){ - string name = queue.getName(); - FieldTable args; - AMQFrame* frame = new AMQFrame(id, new QueueDeclareBody(0, name, false, false, - queue.isExclusive(), - queue.isAutoDelete(), !synch, args)); - if(synch){ - sendAndReceive(frame, queue_declare_ok); - if(queue.getName().length() == 0){ - QueueDeclareOkBody::shared_ptr response = - dynamic_pointer_cast(responses.getResponse()); - queue.setName(response->getQueue()); - } - }else{ - out->send(frame); - } -} - -void Channel::deleteQueue(Queue& queue, bool ifunused, bool ifempty, bool synch){ - //ticket, queue, ifunused, ifempty, nowait - string name = queue.getName(); - AMQFrame* frame = new AMQFrame(id, new QueueDeleteBody(0, name, ifunused, ifempty, !synch)); - if(synch){ - sendAndReceive(frame, queue_delete_ok); - }else{ - out->send(frame); - } -} - -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(); - // TODO aconway 2006-10-10: not const correct, get rid of const_cast. - // - AMQFrame* frame = new AMQFrame(id, new QueueBindBody(0, q, e, key,!synch, const_cast(args))); - if(synch){ - sendAndReceive(frame, queue_bind_ok); - }else{ - out->send(frame); - } -} - -void Channel::consume(Queue& queue, std::string& tag, MessageListener* listener, - int ackMode, bool noLocal, bool synch){ - - string q = queue.getName(); - AMQFrame* frame = new AMQFrame(id, new BasicConsumeBody(0, q, (string&) tag, noLocal, ackMode == NO_ACK, false, !synch)); - if(synch){ - sendAndReceive(frame, basic_consume_ok); - BasicConsumeOkBody::shared_ptr response = dynamic_pointer_cast(responses.getResponse()); - tag = response->getConsumerTag(); - }else{ - out->send(frame); - } - Consumer* c = new Consumer(); - c->listener = listener; - c->ackMode = ackMode; - c->lastDeliveryTag = 0; - consumers[tag] = c; -} - -void Channel::cancel(std::string& tag, bool synch){ - Consumer* c = consumers[tag]; - if(c->ackMode == LAZY_ACK && c->lastDeliveryTag > 0){ - out->send(new AMQFrame(id, new BasicAckBody(c->lastDeliveryTag, true))); - } - - AMQFrame* frame = new AMQFrame(id, new BasicCancelBody((string&) tag, !synch)); - if(synch){ - sendAndReceive(frame, basic_cancel_ok); - }else{ - out->send(frame); - } - consumers.erase(tag); - if(c != 0){ - delete c; - } -} - -void Channel::cancelAll(){ - for(consumer_iterator i = consumers.begin(); i != consumers.end(); i = consumers.begin()){ - Consumer* c = i->second; - if((c->ackMode == LAZY_ACK || c->ackMode == AUTO_ACK) && c->lastDeliveryTag > 0){ - out->send(new AMQFrame(id, new BasicAckBody(c->lastDeliveryTag, true))); - } - consumers.erase(i); - delete c; - } -} - -void Channel::retrieve(Message& msg){ - retrievalMonitor->acquire(); - while(retrieved == 0){ - retrievalMonitor->wait(); - } - - msg.header = retrieved->getHeader(); - msg.deliveryTag = retrieved->getDeliveryTag(); - retrieved->getData(msg.data); - delete retrieved; - retrieved = 0; - - retrievalMonitor->release(); -} - -bool Channel::get(Message& msg, const Queue& queue, int ackMode){ - string name = queue.getName(); - AMQFrame* frame = new AMQFrame(id, new BasicGetBody(0, name, ackMode)); - responses.expect(); - out->send(frame); - responses.waitForResponse(); - AMQMethodBody::shared_ptr response = responses.getResponse(); - if(basic_get_ok.match(response.get())){ - if(incoming != 0){ - std::cout << "Existing message not complete" << std::endl; - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Existing message not complete"); - }else{ - incoming = new IncomingMessage(dynamic_pointer_cast(response)); - } - retrieve(msg); - return true; - }if(basic_get_empty.match(response.get())){ - return false; - }else{ - THROW_QPID_ERROR(PROTOCOL_ERROR + 500, "Unexpected response to basic.get."); - } -} - - -void Channel::publish(Message& msg, const Exchange& exchange, const std::string& routingKey, bool mandatory, bool immediate){ - string e = exchange.getName(); - string key = routingKey; - - out->send(new AMQFrame(id, new BasicPublishBody(0, e, key, mandatory, immediate))); - //break msg up into header frame and content frame(s) and send these - string data = msg.getData(); - msg.header->setContentSize(data.length()); - AMQBody::shared_ptr body(static_pointer_cast(msg.header)); - out->send(new AMQFrame(id, body)); - - int data_length = data.length(); - if(data_length > 0){ - //TODO fragmentation of messages, need to know max frame size for connection - int frag_size = con->getMaxFrameSize() - 4; - if(data_length < frag_size){ - out->send(new AMQFrame(id, new AMQContentBody(data))); - }else{ - int frag_count = data_length / frag_size; - for(int i = 0; i < frag_count; i++){ - int pos = i*frag_size; - int len = i < frag_count - 1 ? frag_size : data_length - pos; - string frag(data.substr(pos, len)); - out->send(new AMQFrame(id, new AMQContentBody(frag))); - } - } - } -} - -void Channel::commit(){ - AMQFrame* frame = new AMQFrame(id, new TxCommitBody()); - sendAndReceive(frame, tx_commit_ok); -} - -void Channel::rollback(){ - AMQFrame* frame = new AMQFrame(id, new TxRollbackBody()); - sendAndReceive(frame, tx_rollback_ok); -} - -void Channel::handleMethod(AMQMethodBody::shared_ptr body){ - //channel.flow, channel.close, basic.deliver, basic.return or a response to a synchronous request - if(responses.isWaiting()){ - responses.signalResponse(body); - }else if(basic_deliver.match(body.get())){ - if(incoming != 0){ - std::cout << "Existing message not complete [deliveryTag=" << incoming->getDeliveryTag() << "]" << std::endl; - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Existing message not complete"); - }else{ - incoming = new IncomingMessage(dynamic_pointer_cast(body)); - } - }else if(basic_return.match(body.get())){ - if(incoming != 0){ - std::cout << "Existing message not complete" << std::endl; - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Existing message not complete"); - }else{ - incoming = new IncomingMessage(dynamic_pointer_cast(body)); - } - }else if(channel_close.match(body.get())){ - con->removeChannel(this); - //need to signal application that channel has been closed through exception - - }else if(channel_flow.match(body.get())){ - - }else{ - //signal error - std::cout << "Unhandled method: " << *body << std::endl; - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Unhandled method"); - } -} - -void Channel::handleHeader(AMQHeaderBody::shared_ptr body){ - if(incoming == 0){ - //handle invalid frame sequence - std::cout << "Invalid message sequence: got header before return or deliver." << std::endl; - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got header before return or deliver."); - }else{ - incoming->setHeader(body); - if(incoming->isComplete()){ - enqueue(); - } - } -} - -void Channel::handleContent(AMQContentBody::shared_ptr body){ - if(incoming == 0){ - //handle invalid frame sequence - std::cout << "Invalid message sequence: got content before return or deliver." << std::endl; - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got content before return or deliver."); - }else{ - incoming->addContent(body); - if(incoming->isComplete()){ - enqueue(); - } - } -} - -void Channel::handleHeartbeat(AMQHeartbeatBody::shared_ptr /*body*/){ - THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Channel received heartbeat"); -} - -void Channel::start(){ - dispatcher = threadFactory->create(this); - dispatcher->start(); -} - -void Channel::stop(){ - closed = true; - dispatchMonitor->acquire(); - dispatchMonitor->notify(); - dispatchMonitor->release(); - if(dispatcher){ - dispatcher->join(); - } -} - -void Channel::run(){ - dispatch(); -} - -void Channel::enqueue(){ - if(incoming->isResponse()){ - retrievalMonitor->acquire(); - retrieved = incoming; - retrievalMonitor->notify(); - retrievalMonitor->release(); - }else{ - dispatchMonitor->acquire(); - messages.push(incoming); - dispatchMonitor->notify(); - dispatchMonitor->release(); - } - incoming = 0; -} - -IncomingMessage* Channel::dequeue(){ - dispatchMonitor->acquire(); - while(messages.empty() && !closed){ - dispatchMonitor->wait(); - } - IncomingMessage* msg = 0; - if(!messages.empty()){ - msg = messages.front(); - messages.pop(); - } - dispatchMonitor->release(); - return msg; -} - -void Channel::deliver(Consumer* consumer, Message& msg){ - //record delivery tag: - consumer->lastDeliveryTag = msg.getDeliveryTag(); - - //allow registered listener to handle the message - consumer->listener->received(msg); - - //if the handler calls close on the channel or connection while - //handling this message, then consumer will now have been deleted. - if(!closed){ - bool multiple(false); - switch(consumer->ackMode){ - case LAZY_ACK: - multiple = true; - if(++(consumer->count) < prefetch) break; - //else drop-through - case AUTO_ACK: - out->send(new AMQFrame(id, new BasicAckBody(msg.getDeliveryTag(), multiple))); - consumer->lastDeliveryTag = 0; - } - } - - //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 Channel::dispatch(){ - while(!closed){ - IncomingMessage* incomingMsg = dequeue(); - if(incomingMsg){ - //Note: msg is currently only valid for duration of this call - Message msg(incomingMsg->getHeader()); - incomingMsg->getData(msg.data); - if(incomingMsg->isReturn()){ - if(returnsHandler == 0){ - //print warning to log/console - std::cout << "Message returned: " << msg.getData() << std::endl; - }else{ - returnsHandler->returned(msg); - } - }else{ - msg.deliveryTag = incomingMsg->getDeliveryTag(); - std::string tag = incomingMsg->getConsumerTag(); - - if(consumers[tag] == 0){ - //signal error - std::cout << "Unknown consumer: " << tag << std::endl; - }else{ - deliver(consumers[tag], msg); - } - } - delete incomingMsg; - } - } -} - -void Channel::setReturnedMessageHandler(ReturnedMessageHandler* handler){ - returnsHandler = handler; -} - -void Channel::sendAndReceive(AMQFrame* frame, const AMQMethodBody& body){ - responses.expect(); - out->send(frame); - responses.receive(body); -} - -void Channel::close(){ - if(con != 0){ - con->closeChannel(this); - } -} diff --git a/cpp/client/src/Connection.cpp b/cpp/client/src/Connection.cpp deleted file mode 100644 index f332d2242c..0000000000 --- a/cpp/client/src/Connection.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "Connection.h" -#include "Channel.h" -#include "ConnectorImpl.h" -#include "Message.h" -#include "QpidError.h" -#include - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::io; -using namespace qpid::concurrent; - -u_int16_t Connection::channelIdCounter; - -Connection::Connection(bool debug, u_int32_t _max_frame_size) : max_frame_size(_max_frame_size), closed(true){ - connector = new ConnectorImpl(debug, _max_frame_size); -} - -Connection::~Connection(){ - delete connector; -} - -void Connection::open(const std::string& _host, int _port, const std::string& uid, const std::string& pwd, const std::string& virtualhost){ - host = _host; - port = _port; - connector->setInputHandler(this); - connector->setTimeoutHandler(this); - connector->setShutdownHandler(this); - out = connector->getOutputHandler(); - connector->connect(host, port); - - ProtocolInitiation* header = new ProtocolInitiation(8, 0); - responses.expect(); - connector->init(header); - responses.receive(connection_start); - - FieldTable props; - string mechanism("PLAIN"); - string response = ((char)0) + uid + ((char)0) + pwd; - string locale("en_US"); - responses.expect(); - out->send(new AMQFrame(0, new ConnectionStartOkBody(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 - out->send(new AMQFrame(0, new ConnectionSecureOkBody(response))); - **/ - - responses.receive(connection_tune); - - ConnectionTuneBody::shared_ptr proposal = std::tr1::dynamic_pointer_cast(responses.getResponse()); - out->send(new AMQFrame(0, new ConnectionTuneOkBody(proposal->getChannelMax(), max_frame_size, proposal->getHeartbeat()))); - - u_int16_t heartbeat = proposal->getHeartbeat(); - connector->setReadTimeout(heartbeat * 2); - connector->setWriteTimeout(heartbeat); - - //send connection.open - string capabilities; - string vhost = virtualhost; - responses.expect(); - out->send(new AMQFrame(0, new ConnectionOpenBody(vhost, capabilities, true))); - //receive connection.open-ok (or redirect, but ignore that for now esp. as using force=true). - responses.waitForResponse(); - if(responses.validate(connection_open_ok)){ - //ok - }else if(responses.validate(connection_redirect)){ - //ignore for now - ConnectionRedirectBody::shared_ptr redirect(std::tr1::dynamic_pointer_cast(responses.getResponse())); - std::cout << "Received redirection to " << redirect->getHost() << std::endl; - }else{ - THROW_QPID_ERROR(PROTOCOL_ERROR, "Bad response"); - } - -} - -void Connection::close(){ - if(!closed){ - u_int16_t code(200); - string text("Ok"); - u_int16_t classId(0); - u_int16_t methodId(0); - - sendAndReceive(new AMQFrame(0, new ConnectionCloseBody(code, text, classId, methodId)), connection_close_ok); - connector->close(); - } -} - -void Connection::openChannel(Channel* channel){ - channel->con = this; - channel->id = ++channelIdCounter; - channel->out = out; - channels[channel->id] = channel; - //now send frame to open channel and wait for response - string oob; - channel->sendAndReceive(new AMQFrame(channel->id, new ChannelOpenBody(oob)), channel_open_ok); - channel->setQos(); - channel->closed = false; -} - -void Connection::closeChannel(Channel* channel){ - //send frame to close channel - u_int16_t code(200); - string text("Ok"); - u_int16_t classId(0); - u_int16_t methodId(0); - closeChannel(channel, code, text, classId, methodId); -} - -void Connection::closeChannel(Channel* channel, u_int16_t code, string& text, u_int16_t classId, u_int16_t methodId){ - //send frame to close channel - channel->cancelAll(); - channel->closed = true; - channel->sendAndReceive(new AMQFrame(channel->id, new ChannelCloseBody(code, text, classId, methodId)), channel_close_ok); - channel->con = 0; - channel->out = 0; - removeChannel(channel); -} - -void Connection::removeChannel(Channel* channel){ - //send frame to close channel - - channels.erase(channel->id); - channel->out = 0; - channel->id = 0; - channel->con = 0; -} - -void Connection::received(AMQFrame* frame){ - u_int16_t channelId = frame->getChannel(); - - if(channelId == 0){ - this->handleBody(frame->getBody()); - }else{ - Channel* channel = channels[channelId]; - if(channel == 0){ - error(504, "Unknown channel"); - }else{ - try{ - channel->handleBody(frame->getBody()); - }catch(qpid::QpidError e){ - channelException(channel, dynamic_cast(frame->getBody().get()), e); - } - } - } -} - -void Connection::handleMethod(AMQMethodBody::shared_ptr body){ - //connection.close, basic.deliver, basic.return or a response to a synchronous request - if(responses.isWaiting()){ - responses.signalResponse(body); - }else if(connection_close.match(body.get())){ - //send back close ok - //close socket - ConnectionCloseBody* request = dynamic_cast(body.get()); - std::cout << "Connection closed by server: " << request->getReplyCode() << ":" << request->getReplyText() << std::endl; - connector->close(); - }else{ - std::cout << "Unhandled method for connection: " << *body << std::endl; - error(504, "Unrecognised method", body->amqpClassId(), body->amqpMethodId()); - } -} - -void Connection::handleHeader(AMQHeaderBody::shared_ptr /*body*/){ - error(504, "Channel error: received header body with channel 0."); -} - -void Connection::handleContent(AMQContentBody::shared_ptr /*body*/){ - error(504, "Channel error: received content body with channel 0."); -} - -void Connection::handleHeartbeat(AMQHeartbeatBody::shared_ptr /*body*/){ -} - -void Connection::sendAndReceive(AMQFrame* frame, const AMQMethodBody& body){ - responses.expect(); - out->send(frame); - responses.receive(body); -} - -void Connection::error(int code, const string& msg, int classid, int methodid){ - std::cout << "Connection exception generated: " << code << msg; - if(classid || methodid){ - std::cout << " [" << methodid << ":" << classid << "]"; - } - std::cout << std::endl; - sendAndReceive(new AMQFrame(0, new ConnectionCloseBody(code, msg, classid, methodid)), connection_close_ok); - connector->close(); -} - -void Connection::channelException(Channel* channel, AMQMethodBody* method, QpidError& e){ - std::cout << "Caught error from channel [" << e.code << "] " << e.msg << " (" << e.file << ":" << e.line << ")" << std::endl; - int code = e.code == PROTOCOL_ERROR ? e.code - PROTOCOL_ERROR : 500; - string msg = e.msg; - if(method == 0){ - closeChannel(channel, code, msg); - }else{ - closeChannel(channel, code, msg, method->amqpClassId(), method->amqpMethodId()); - } -} - -void Connection::idleIn(){ - std::cout << "Connection timed out due to abscence of heartbeat." << std::endl; - connector->close(); -} - -void Connection::idleOut(){ - out->send(new AMQFrame(0, new AMQHeartbeatBody())); -} - -void Connection::shutdown(){ - closed = true; - //close all channels - for(iterator i = channels.begin(); i != channels.end(); i++){ - i->second->stop(); - } -} diff --git a/cpp/client/src/Exchange.cpp b/cpp/client/src/Exchange.cpp deleted file mode 100644 index 681068dc4c..0000000000 --- a/cpp/client/src/Exchange.cpp +++ /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. - * - */ -#include "Exchange.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_DIRECT_EXCHANGE("amq.direct", DIRECT_EXCHANGE); -const qpid::client::Exchange qpid::client::Exchange::DEFAULT_TOPIC_EXCHANGE("amq.topic", TOPIC_EXCHANGE); -const qpid::client::Exchange qpid::client::Exchange::DEFAULT_HEADERS_EXCHANGE("amq.headers", HEADERS_EXCHANGE); diff --git a/cpp/client/src/IncomingMessage.cpp b/cpp/client/src/IncomingMessage.cpp deleted file mode 100644 index 9576051302..0000000000 --- a/cpp/client/src/IncomingMessage.cpp +++ /dev/null @@ -1,85 +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 "IncomingMessage.h" -#include "QpidError.h" -#include - -using namespace qpid::client; -using namespace qpid::framing; - -IncomingMessage::IncomingMessage(BasicDeliverBody::shared_ptr intro) : delivered(intro){} -IncomingMessage::IncomingMessage(BasicReturnBody::shared_ptr intro): returned(intro){} -IncomingMessage::IncomingMessage(BasicGetOkBody::shared_ptr intro): response(intro){} - -IncomingMessage::~IncomingMessage(){ -} - -void IncomingMessage::setHeader(AMQHeaderBody::shared_ptr _header){ - this->header = _header; -} - -void IncomingMessage::addContent(AMQContentBody::shared_ptr _content){ - this->content.push_back(_content); -} - -bool IncomingMessage::isComplete(){ - return header != 0 && header->getContentSize() == contentSize(); -} - -bool IncomingMessage::isReturn(){ - return returned; -} - -bool IncomingMessage::isDelivery(){ - return delivered; -} - -bool IncomingMessage::isResponse(){ - return response; -} - -const string& IncomingMessage::getConsumerTag(){ - if(!isDelivery()) THROW_QPID_ERROR(CLIENT_ERROR, "Consumer tag only valid for delivery"); - return delivered->getConsumerTag(); -} - -u_int64_t IncomingMessage::getDeliveryTag(){ - if(!isDelivery()) THROW_QPID_ERROR(CLIENT_ERROR, "Delivery tag only valid for delivery"); - return delivered->getDeliveryTag(); -} - -AMQHeaderBody::shared_ptr& IncomingMessage::getHeader(){ - return header; -} - -void IncomingMessage::getData(string& s){ - int count(content.size()); - for(int i = 0; i < count; i++){ - if(i == 0) s = content[i]->getData(); - else s += content[i]->getData(); - } -} - -u_int64_t IncomingMessage::contentSize(){ - u_int64_t size(0); - u_int64_t count(content.size()); - for(u_int64_t i = 0; i < count; i++){ - size += content[i]->size(); - } - return size; -} diff --git a/cpp/client/src/Message.cpp b/cpp/client/src/Message.cpp deleted file mode 100644 index 71befe57b1..0000000000 --- a/cpp/client/src/Message.cpp +++ /dev/null @@ -1,147 +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 "Message.h" - -using namespace qpid::client; -using namespace qpid::framing; - -Message::Message(){ - header = AMQHeaderBody::shared_ptr(new AMQHeaderBody(BASIC)); -} - -Message::Message(AMQHeaderBody::shared_ptr& _header) : header(_header){ -} - -Message::~Message(){ -} - -BasicHeaderProperties* Message::getHeaderProperties(){ - return dynamic_cast(header->getProperties()); -} - -std::string& Message::getContentType(){ - return getHeaderProperties()->getContentType(); -} - -std::string& Message::getContentEncoding(){ - return getHeaderProperties()->getContentEncoding(); -} - -FieldTable& Message::getHeaders(){ - return getHeaderProperties()->getHeaders(); -} - -u_int8_t Message::getDeliveryMode(){ - return getHeaderProperties()->getDeliveryMode(); -} - -u_int8_t Message::getPriority(){ - return getHeaderProperties()->getPriority(); -} - -std::string& Message::getCorrelationId(){ - return getHeaderProperties()->getCorrelationId(); -} - -std::string& Message::getReplyTo(){ - return getHeaderProperties()->getReplyTo(); -} - -std::string& Message::getExpiration(){ - return getHeaderProperties()->getExpiration(); -} - -std::string& Message::getMessageId(){ - return getHeaderProperties()->getMessageId(); -} - -u_int64_t Message::getTimestamp(){ - return getHeaderProperties()->getTimestamp(); -} - -std::string& Message::getType(){ - return getHeaderProperties()->getType(); -} - -std::string& Message::getUserId(){ - return getHeaderProperties()->getUserId(); -} - -std::string& Message::getAppId(){ - return getHeaderProperties()->getAppId(); -} - -std::string& Message::getClusterId(){ - return getHeaderProperties()->getClusterId(); -} - -void Message::setContentType(std::string& type){ - getHeaderProperties()->setContentType(type); -} - -void Message::setContentEncoding(std::string& encoding){ - getHeaderProperties()->setContentEncoding(encoding); -} - -void Message::setHeaders(FieldTable& headers){ - getHeaderProperties()->setHeaders(headers); -} - -void Message::setDeliveryMode(u_int8_t mode){ - getHeaderProperties()->setDeliveryMode(mode); -} - -void Message::setPriority(u_int8_t priority){ - getHeaderProperties()->setPriority(priority); -} - -void Message::setCorrelationId(std::string& correlationId){ - getHeaderProperties()->setCorrelationId(correlationId); -} - -void Message::setReplyTo(std::string& replyTo){ - getHeaderProperties()->setReplyTo(replyTo); -} - -void Message::setExpiration(std::string& expiration){ - getHeaderProperties()->setExpiration(expiration); -} - -void Message::setMessageId(std::string& messageId){ - getHeaderProperties()->setMessageId(messageId); -} - -void Message::setTimestamp(u_int64_t timestamp){ - getHeaderProperties()->setTimestamp(timestamp); -} - -void Message::setType(std::string& type){ - getHeaderProperties()->setType(type); -} - -void Message::setUserId(std::string& userId){ - getHeaderProperties()->setUserId(userId); -} - -void Message::setAppId(std::string& appId){ - getHeaderProperties()->setAppId(appId); -} - -void Message::setClusterId(std::string& clusterId){ - getHeaderProperties()->setClusterId(clusterId); -} diff --git a/cpp/client/src/MessageListener.cpp b/cpp/client/src/MessageListener.cpp deleted file mode 100644 index cf55db8edf..0000000000 --- a/cpp/client/src/MessageListener.cpp +++ /dev/null @@ -1,21 +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 "MessageListener.h" - -qpid::client::MessageListener::~MessageListener() {} diff --git a/cpp/client/src/Queue.cpp b/cpp/client/src/Queue.cpp deleted file mode 100644 index 5b2881f7ff..0000000000 --- a/cpp/client/src/Queue.cpp +++ /dev/null @@ -1,47 +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 "Queue.h" - -qpid::client::Queue::Queue() : name(""), autodelete(true), exclusive(true){} - -qpid::client::Queue::Queue(std::string _name) : name(_name), autodelete(false), exclusive(false){} - -qpid::client::Queue::Queue(std::string _name, bool temp) : name(_name), autodelete(temp), exclusive(temp){} - -qpid::client::Queue::Queue(std::string _name, bool _autodelete, bool _exclusive) - : name(_name), autodelete(_autodelete), exclusive(_exclusive){} - -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; -} - - - - diff --git a/cpp/client/src/ResponseHandler.cpp b/cpp/client/src/ResponseHandler.cpp deleted file mode 100644 index 6938539469..0000000000 --- a/cpp/client/src/ResponseHandler.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "ResponseHandler.h" -#include "MonitorImpl.h" -#include "QpidError.h" - -qpid::client::ResponseHandler::ResponseHandler() : waiting(false){ - monitor = new qpid::concurrent::MonitorImpl(); -} - -qpid::client::ResponseHandler::~ResponseHandler(){ - delete monitor; -} - -bool qpid::client::ResponseHandler::validate(const qpid::framing::AMQMethodBody& expected){ - return expected.match(response.get()); -} - -void qpid::client::ResponseHandler::waitForResponse(){ - monitor->acquire(); - if(waiting){ - monitor->wait(); - } - monitor->release(); -} - -void qpid::client::ResponseHandler::signalResponse(qpid::framing::AMQMethodBody::shared_ptr _response){ - response = _response; - monitor->acquire(); - waiting = false; - monitor->notify(); - monitor->release(); -} - -void qpid::client::ResponseHandler::receive(const qpid::framing::AMQMethodBody& expected){ - monitor->acquire(); - if(waiting){ - monitor->wait(); - } - monitor->release(); - if(!validate(expected)){ - THROW_QPID_ERROR(PROTOCOL_ERROR, "Protocol Error"); - } -} - -void qpid::client::ResponseHandler::expect(){ - waiting = true; -} diff --git a/cpp/client/src/ReturnedMessageHandler.cpp b/cpp/client/src/ReturnedMessageHandler.cpp deleted file mode 100644 index cfa91fee97..0000000000 --- a/cpp/client/src/ReturnedMessageHandler.cpp +++ /dev/null @@ -1,21 +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 "ReturnedMessageHandler.h" - -qpid::client::ReturnedMessageHandler::~ReturnedMessageHandler() {} diff --git a/cpp/client/test/Makefile b/cpp/client/test/Makefile deleted file mode 100644 index f35aab3e17..0000000000 --- a/cpp/client/test/Makefile +++ /dev/null @@ -1,45 +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. -# - -QPID_HOME = ../../.. -include ${QPID_HOME}/cpp/options.mk - -# TODO aconway 2006-09-12: These are system tests, not unit tests. -# We need client side unit tests. -# We should separate them from the system tets. -# We need an approach to automate the C++ client/server system tests. -# - -SOURCES=$(wildcard *.cpp) -TESTS=$(SOURCES:.cpp=) -DEPS= $(SOURCES:.cpp=.d) - -INCLUDES = $(TEST_INCLUDES) -LDLIBS= -lapr-1 $(COMMON_LIB) $(CLIENT_LIB) - -.PHONY: all clean - -all: $(TESTS) - -clean: - -@rm -f $(TESTS) $(DEPS) - -# Rule to build test programs. -%: %.cpp - $(CXX) -o $@ $< $(CXXFLAGS) $(LDFLAGS) $(LDLIBS) - -# Dependencies --include $(DEPS) diff --git a/cpp/client/test/client_test.cpp b/cpp/client/test/client_test.cpp deleted file mode 100644 index b899d494d7..0000000000 --- a/cpp/client/test/client_test.cpp +++ /dev/null @@ -1,97 +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 "QpidError.h" -#include "Channel.h" -#include "Connection.h" -#include "FieldTable.h" -#include "Message.h" -#include "MessageListener.h" - -#include "MonitorImpl.h" - - -using namespace qpid::client; -using namespace qpid::concurrent; - -class SimpleListener : public virtual MessageListener{ - Monitor* monitor; - -public: - inline SimpleListener(Monitor* _monitor) : monitor(_monitor){} - - inline virtual void received(Message& /*msg*/){ - std::cout << "Received message " /**<< msg **/<< std::endl; - monitor->acquire(); - monitor->notify(); - monitor->release(); - } -}; - -int main(int argc, char**) -{ - try{ - Connection con(argc > 1); - Channel channel; - Exchange exchange("MyExchange", Exchange::TOPIC_EXCHANGE); - Queue queue("MyQueue", true); - - string host("localhost"); - - con.open(host); - std::cout << "Opened connection." << std::endl; - con.openChannel(&channel); - std::cout << "Opened channel." << std::endl; - channel.declareExchange(exchange); - std::cout << "Declared exchange." << std::endl; - channel.declareQueue(queue); - std::cout << "Declared queue." << std::endl; - qpid::framing::FieldTable args; - channel.bind(exchange, queue, "MyTopic", args); - std::cout << "Bound queue to exchange." << std::endl; - - //set up a message listener - MonitorImpl monitor; - SimpleListener listener(&monitor); - string tag("MyTag"); - channel.consume(queue, tag, &listener); - channel.start(); - std::cout << "Registered consumer." << std::endl; - - Message msg; - string data("MyMessage"); - msg.setData(data); - channel.publish(msg, exchange, "MyTopic"); - std::cout << "Published message." << std::endl; - - monitor.acquire(); - monitor.wait(); - monitor.release(); - - - con.closeChannel(&channel); - std::cout << "Closed channel." << std::endl; - con.close(); - std::cout << "Closed connection." << std::endl; - }catch(qpid::QpidError error){ - std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; - return 1; - } - return 0; -} diff --git a/cpp/client/test/topic_listener.cpp b/cpp/client/test/topic_listener.cpp deleted file mode 100644 index a1b8e383a0..0000000000 --- a/cpp/client/test/topic_listener.cpp +++ /dev/null @@ -1,180 +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 "apr_time.h" -#include "QpidError.h" -#include "Channel.h" -#include "Connection.h" -#include "Exchange.h" -#include "MessageListener.h" -#include "Queue.h" - -using namespace qpid::client; - -class Listener : public MessageListener{ - Channel* const channel; - const std::string responseQueue; - const bool transactional; - bool init; - int count; - apr_time_t start; - - void shutdown(); - void report(); -public: - Listener(Channel* channel, const std::string& reponseQueue, bool tx); - virtual void received(Message& msg); -}; - -class Args{ - string host; - int port; - int 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(); - - inline const string& getHost() const { return host;} - inline int getPort() const { return port; } - inline int getAckMode(){ return ackMode; } - inline bool getTransactional() const { return transactional; } - inline int getPrefetch(){ return prefetch; } - inline bool getTrace() const { return trace; } - inline 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()); - 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::DEFAULT_TOPIC_EXCHANGE, control, "topic_control", bindArgs); - //set up listener - Listener listener(&channel, response.getName(), args.getTransactional()); - std::string tag; - channel.consume(control, tag, &listener, args.getAckMode()); - channel.run(); - connection.close(); - }catch(qpid::QpidError error){ - std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; - } - } -} - -Listener::Listener(Channel* _channel, const std::string& _responseq, bool tx) : - channel(_channel), responseQueue(_responseq), transactional(tx), init(false), count(0){} - -void Listener::received(Message& message){ - if(!init){ - start = apr_time_as_msec(apr_time_now()); - count = 0; - init = true; - } - std::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){ - std::cout <<"Received " << count << " messages." << std::endl; - } -} - -void Listener::shutdown(){ - channel->close(); -} - -void Listener::report(){ - apr_time_t finish = apr_time_as_msec(apr_time_now()); - apr_time_t time = finish - start; - std::stringstream reportstr; - reportstr << "Received " << count << " messages in " << time << " ms."; - Message msg; - msg.setData(reportstr.str()); - 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 = atoi(argv[++i]); - }else if("-transactional" == name){ - transactional = true; - }else if("-prefetch" == name){ - prefetch = 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 << " -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 << " -trace" << std::endl; - std::cout << " Indicates that the frames sent and received should be logged" << std::endl; -} diff --git a/cpp/client/test/topic_publisher.cpp b/cpp/client/test/topic_publisher.cpp deleted file mode 100644 index fc6b7f3b30..0000000000 --- a/cpp/client/test/topic_publisher.cpp +++ /dev/null @@ -1,253 +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 "unistd.h" -#include "apr_time.h" -#include "MonitorImpl.h" -#include "QpidError.h" -#include "Channel.h" -#include "Connection.h" -#include "Exchange.h" -#include "MessageListener.h" -#include "Queue.h" - -using namespace qpid::client; -using namespace qpid::concurrent; - -class Publisher : public MessageListener{ - Channel* const channel; - const std::string controlTopic; - const bool transactional; - MonitorImpl 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); - apr_time_t publish(int msgs, int listeners, int size); - void terminate(); -}; - -class Args{ - string host; - int port; - int messages; - int subscribers; - int 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(); - - inline const string& getHost() const { return host;} - inline int getPort() const { return port; } - inline int getMessages() const { return messages; } - inline int getSubscribers() const { return subscribers; } - inline int getAckMode(){ return ackMode; } - inline bool getTransactional() const { return transactional; } - inline int getPrefetch(){ return prefetch; } - inline int getBatches(){ return batches; } - inline int getDelay(){ return delay; } - inline int getSize(){ return size; } - inline bool getTrace() const { return trace; } - inline 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()); - 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()); - apr_time_t max(0); - apr_time_t min(0); - apr_time_t sum(0); - for(int i = 0; i < batchSize; i++){ - if(i > 0 && args.getDelay()) sleep(args.getDelay()); - apr_time_t time = publisher.publish(args.getMessages(), args.getSubscribers(), args.getSize()); - if(!max || time > max) max = time; - if(!min || time < min) min = time; - sum += time; - std::cout << "Completed " << (i+1) << " of " << batchSize << " in " << time << "ms" << std::endl; - } - publisher.terminate(); - apr_time_t avg = sum / batchSize; - if(batchSize > 1){ - std::cout << batchSize << " batches completed. avg=" << avg << - ", max=" << max << ", min=" << min << std::endl; - } - channel.close(); - connection.close(); - }catch(qpid::QpidError error){ - std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; - } - } -} - -Publisher::Publisher(Channel* _channel, const std::string& _controlTopic, bool tx) : - channel(_channel), controlTopic(_controlTopic), transactional(tx){} - -void Publisher::received(Message& msg){ - //count responses and when all are received end the current batch - monitor.acquire(); - if(--count == 0){ - monitor.notify(); - } - std::cout << "Received report: " << msg.getData() << " (" << count << " remaining)." << std::endl; - monitor.release(); -} - -void Publisher::waitForCompletion(int msgs){ - count = msgs; - monitor.wait(); -} - -apr_time_t Publisher::publish(int msgs, int listeners, int size){ - monitor.acquire(); - Message msg; - msg.setData(generateData(size)); - apr_time_t start(apr_time_as_msec(apr_time_now())); - for(int i = 0; i < msgs; i++){ - channel->publish(msg, Exchange::DEFAULT_TOPIC_EXCHANGE, controlTopic); - } - //send report request - Message reportRequest; - reportRequest.getHeaders().setString("TYPE", "REPORT_REQUEST"); - channel->publish(reportRequest, Exchange::DEFAULT_TOPIC_EXCHANGE, controlTopic); - if(transactional){ - channel->commit(); - } - - waitForCompletion(listeners); - monitor.release(); - apr_time_t finish(apr_time_as_msec(apr_time_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::DEFAULT_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 = 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/cpp/common/Makefile b/cpp/common/Makefile deleted file mode 100644 index 766d5fbcde..0000000000 --- a/cpp/common/Makefile +++ /dev/null @@ -1,45 +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. -# - -# -# Make file to build qpid_common library. -# - -QPID_HOME=../.. -include $(QPID_HOME)/cpp/options.mk -TARGET = $(LIB_DIR)/libqpid_common.so.1.0 -SOURCES = $(wildcard */src/*.cpp framing/generated/*.cpp error/*.cpp) -OBJECTS = $(SOURCES:.cpp=.o) -DEPS = $(SOURCES:.cpp=.d) - -GENERATED_OBJECTS = framing/generated/amqp_methods.o - -.PHONY: all clean - -# We have to do two separate makes to ensure we pick up all generated files. -all: - @$(MAKE) -C framing all - @$(MAKE) $(TARGET) - @$(MAKE) -C framing test - -clean: - @$(MAKE) -C framing clean - -@rm -f $(TARGET) $(OBJECTS) $(DEPS) - -$(TARGET): $(OBJECTS) - $(CXX) -shared -o $@ $(OBJECTS) $(LDFLAGS) -lapr-1 - --include $(DEPS) diff --git a/cpp/common/concurrent/inc/APRBase.h b/cpp/common/concurrent/inc/APRBase.h deleted file mode 100644 index e0b526faa1..0000000000 --- a/cpp/common/concurrent/inc/APRBase.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _APRBase_ -#define _APRBase_ - -#include -#include "apr_thread_mutex.h" -#include "apr_errno.h" - -namespace qpid { -namespace concurrent { - - /** - * 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 std::string& file, const int line); - std::string get_desc(apr_status_t status); - -#define CHECK_APR_SUCCESS(A) check(A, __FILE__, __LINE__); - -} -} - - - - -#endif diff --git a/cpp/common/concurrent/inc/APRMonitor.h b/cpp/common/concurrent/inc/APRMonitor.h deleted file mode 100644 index bf72596564..0000000000 --- a/cpp/common/concurrent/inc/APRMonitor.h +++ /dev/null @@ -1,48 +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. - * - */ -#ifndef _APRMonitor_ -#define _APRMonitor_ - -#include "apr_thread_mutex.h" -#include "apr_thread_cond.h" -#include "Monitor.h" - -namespace qpid { -namespace concurrent { - - class APRMonitor : public virtual Monitor - { - apr_pool_t* pool; - apr_thread_mutex_t* mutex; - apr_thread_cond_t* condition; - - public: - APRMonitor(); - virtual ~APRMonitor(); - virtual void wait(); - virtual void wait(u_int64_t time); - virtual void notify(); - virtual void notifyAll(); - virtual void acquire(); - virtual void release(); - }; -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/APRThread.h b/cpp/common/concurrent/inc/APRThread.h deleted file mode 100644 index d5034ce3b7..0000000000 --- a/cpp/common/concurrent/inc/APRThread.h +++ /dev/null @@ -1,48 +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. - * - */ -#ifndef _APRThread_ -#define _APRThread_ - -#include "apr_thread_proc.h" -#include "APRThread.h" -#include "Runnable.h" -#include "Thread.h" - -namespace qpid { -namespace concurrent { - - class APRThread : public virtual Thread - { - const Runnable* runnable; - apr_pool_t* pool; - apr_thread_t* runner; - - public: - APRThread(apr_pool_t* pool, Runnable* runnable); - virtual ~APRThread(); - virtual void start(); - virtual void join(); - virtual void interrupt(); - static unsigned int currentThread(); - }; - -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/APRThreadFactory.h b/cpp/common/concurrent/inc/APRThreadFactory.h deleted file mode 100644 index 87b240025d..0000000000 --- a/cpp/common/concurrent/inc/APRThreadFactory.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _APRThreadFactory_ -#define _APRThreadFactory_ - -#include "apr_thread_proc.h" - -#include "APRThread.h" -#include "Thread.h" -#include "ThreadFactory.h" -#include "Runnable.h" - -namespace qpid { -namespace concurrent { - - class APRThreadFactory : public virtual ThreadFactory - { - apr_pool_t* pool; - public: - APRThreadFactory(); - virtual ~APRThreadFactory(); - virtual Thread* create(Runnable* runnable); - }; - -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/APRThreadPool.h b/cpp/common/concurrent/inc/APRThreadPool.h deleted file mode 100644 index cf6d30774c..0000000000 --- a/cpp/common/concurrent/inc/APRThreadPool.h +++ /dev/null @@ -1,67 +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. - * - */ -#ifndef _APRThreadPool_ -#define _APRThreadPool_ - -#include -#include -#include "APRMonitor.h" -#include "Thread.h" -#include "ThreadFactory.h" -#include "ThreadPool.h" -#include "Runnable.h" - -namespace qpid { -namespace concurrent { - - class APRThreadPool : public virtual ThreadPool - { - class Worker : public virtual Runnable{ - APRThreadPool* pool; - public: - inline Worker(APRThreadPool* _pool) : pool(_pool){} - inline virtual void run(){ - while(pool->running){ - pool->runTask(); - } - } - }; - const bool deleteFactory; - const int size; - ThreadFactory* factory; - APRMonitor lock; - std::vector threads; - std::queue tasks; - Worker* worker; - volatile bool running; - - void runTask(); - public: - APRThreadPool(int size); - APRThreadPool(int size, ThreadFactory* factory); - virtual void start(); - virtual void stop(); - virtual void addTask(Runnable* task); - virtual ~APRThreadPool(); - }; - -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/LMonitor.h b/cpp/common/concurrent/inc/LMonitor.h deleted file mode 100644 index 8e2569921d..0000000000 --- a/cpp/common/concurrent/inc/LMonitor.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _LMonitor_ -#define _LMonitor_ - -/* Native Linux Monitor - Based of Kernel patch 19/20 */ - -#include "Monitor.h" - -namespace qpid { -namespace concurrent { - - class LMonitor : public virtual Monitor - { - - public: - LMonitor(); - virtual ~LMonitor(); - virtual void wait(); - virtual void notify(); - virtual void notifyAll(); - virtual void acquire(); - virtual void release(); - }; -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/LThreadFactory.h b/cpp/common/concurrent/inc/LThreadFactory.h deleted file mode 100644 index 4a573d1bd1..0000000000 --- a/cpp/common/concurrent/inc/LThreadFactory.h +++ /dev/null @@ -1,37 +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. - * - */ -#ifndef _LAPRThreadFactory_ -#define _LAPRThreadFactory_ - - -namespace qpid { -namespace concurrent { - - class LThreadFactory - { - public: - LThreadFactory(); - virtual ~LThreadFactory(); - virtual Thread* create(Runnable* runnable); - }; - -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/LockedQueue.h b/cpp/common/concurrent/inc/LockedQueue.h deleted file mode 100644 index ef3f0b8381..0000000000 --- a/cpp/common/concurrent/inc/LockedQueue.h +++ /dev/null @@ -1,68 +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. - * - */ -#ifndef _LockedQueue_ -#define _LockedQueue_ - -#include -#include "Monitor.h" - -/** - * A threadsafe queue abstraction - */ -namespace qpid { -namespace concurrent { - template class LockedQueue - { - L lock; - std::queue queue; - - public: - void put(T* item); - T* take(); - bool empty(); - }; - - template void LockedQueue::put(T* item){ - lock.acquire(); - queue.push(item); - lock.release(); - } - - template T* LockedQueue::take(){ - lock.acquire(); - T* item = 0; - if(!queue.empty()){ - item = queue.front(); - queue.pop(); - } - lock.release(); - return item; - } - - template bool LockedQueue::empty(){ - lock.acquire(); - bool result = queue.empty(); - lock.release(); - return result; - } - -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/Monitor.h b/cpp/common/concurrent/inc/Monitor.h deleted file mode 100644 index 7f1a299c6a..0000000000 --- a/cpp/common/concurrent/inc/Monitor.h +++ /dev/null @@ -1,59 +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. - * - */ -#ifndef _Monitor_ -#define _Monitor_ - -#include "amqp_types.h" - -namespace qpid { -namespace concurrent { - -class Monitor -{ - public: - virtual ~Monitor(){} - virtual void wait() = 0; - virtual void wait(u_int64_t time) = 0; - virtual void notify() = 0; - virtual void notifyAll() = 0; - virtual void acquire() = 0; - virtual void release() = 0; -}; - -/** - * Scoped locker for a monitor. - */ -class Locker -{ - public: - Locker(Monitor& lock_) : lock(lock_) { lock.acquire(); } - ~Locker() { lock.release(); } - - private: - Monitor& lock; - - // private and unimplemented to prevent copying - Locker(const Locker&); - void operator=(const Locker&); -}; - -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/MonitorImpl.h b/cpp/common/concurrent/inc/MonitorImpl.h deleted file mode 100644 index e96e81d795..0000000000 --- a/cpp/common/concurrent/inc/MonitorImpl.h +++ /dev/null @@ -1,57 +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. - * - */ - - -#ifndef _MonitorImpl_ -#define _MonitorImpl_ - -#ifdef _USE_APR_IO_ -#include "APRMonitor.h" -#else /* use POSIX Monitor */ -#include "LMonitor.h" -#endif - - -namespace qpid { -namespace concurrent { - -#ifdef _USE_APR_IO_ - class MonitorImpl : public virtual APRMonitor - { - - public: - MonitorImpl() : APRMonitor(){}; - virtual ~MonitorImpl(){}; - - }; -#else - class MonitorImpl : public virtual LMonitor - { - - public: - MonitorImpl() : LMonitor(){}; - virtual ~MonitorImpl(){}; - - }; -#endif - -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/Runnable.h b/cpp/common/concurrent/inc/Runnable.h deleted file mode 100644 index 9753a1ad0a..0000000000 --- a/cpp/common/concurrent/inc/Runnable.h +++ /dev/null @@ -1,35 +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. - * - */ -#ifndef _Runnable_ -#define _Runnable_ - -namespace qpid { -namespace concurrent { - - class Runnable - { - public: - virtual ~Runnable(); - virtual void run() = 0; - }; - -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/TaskQueue.h b/cpp/common/concurrent/inc/TaskQueue.h deleted file mode 100644 index e06a3ce069..0000000000 --- a/cpp/common/concurrent/inc/TaskQueue.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _TaskQueue_ -#define _TaskQueue_ - -#include -#include -#include -#include "LockedQueue.h" -#include "Runnable.h" -#include "ThreadPool.h" - -namespace qpid { -namespace concurrent { - template class TaskQueue : public virtual Runnable - { - const int max_iterations_per_run; - L lock; - //LockedQueue queue; - std::queue queue; - ThreadPool* const pool; - T* work; - bool running; - volatile bool stopped; - TaskQueue* next; - - volatile bool inrun; - - bool hasWork(); - void completed(); - - T* take(); - - protected: - /** - * Callback though which the task is executed - */ - virtual void execute(T* t) = 0; - /** - * Allows a task to be completed asynchronously to the - * execute() call if required. - */ - virtual bool isComplete(T* t); - /** - * Should be called to signal completion of a task that was - * signalled as not complete through the isComplete() methods - * return value. This will allow normal processing to resume. - */ - virtual void complete(); - - public: - TaskQueue(ThreadPool* const pool, int max_iterations_per_run = 100); - virtual void run(); - void trigger(); - bool append(T* t); - void stop(bool drain); - inline void setNext(TaskQueue* next){ this->next = next; } - }; - - template TaskQueue::TaskQueue(ThreadPool* const _pool, int _max_iterations_per_run) : - pool(_pool), - max_iterations_per_run(_max_iterations_per_run), - work(0), - running(false), - stopped(false), - next(0), inrun(false){ - } - - template void TaskQueue::run(){ - if(inrun) std::cout << "Already running" << std::endl; - inrun = true; - - bool blocked = false; - int count = max_iterations_per_run; - while(!blocked && hasWork() && count){ - execute(work); - if(isComplete(work)){ - completed(); - }else{ - blocked = true; - } - count--; - } - inrun = false; - - if(!blocked && count == 0){//performed max_iterations_per_run, requeue task to ensure fairness - //running will still be true at this point - lock.acquire(); - running = false; - if(stopped) lock.notify(); - lock.release(); - - trigger(); - }else if(hasWork()){//task was added to queue after we exited the loop above; should not need this? - trigger(); - } - } - - template void TaskQueue::trigger(){ - lock.acquire(); - if(!running){ - running = true; - pool->addTask(this); - } - lock.release(); - } - - template bool TaskQueue::hasWork(){ - lock.acquire(); - if(!work) work = take();//queue.take(); - if(!work){ - running = false; - if(stopped) lock.notify(); - } - lock.release(); - return work; - } - - template bool TaskQueue::append(T* item){ - if(!stopped){ - lock.acquire(); - - //queue.put(item); - queue.push(item); - - if(!running){ - running = true; - pool->addTask(this); - } - lock.release(); - //} - return true; - }else{ - return false; - } - } - - template bool TaskQueue::isComplete(T* item){ - return true;//by default assume all tasks are synchronous w.r.t. execute() - } - - - template void TaskQueue::completed(){ - if(next){ - if(!next->append(work)){ - std::cout << "Warning: dropping task as next queue appears to have stopped." << std::endl; - } - }else{ - delete work; - } - work = 0; - } - - template void TaskQueue::complete(){ - completed(); - lock.acquire(); - running = false; - if(stopped) lock.notify(); - lock.release(); - } - - template void TaskQueue::stop(bool drain){ - //prevent new tasks from being added - stopped = true; - //wait until no longer running - lock.acquire(); - while(running && (drain && hasWork())){ - lock.wait(); - } - lock.release(); - } - - template T* TaskQueue::take(){ - T* item = 0; - if(!queue.empty()){ - item = queue.front(); - queue.pop(); - } - return item; - } -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/Thread.h b/cpp/common/concurrent/inc/Thread.h deleted file mode 100644 index 6bd2a379ce..0000000000 --- a/cpp/common/concurrent/inc/Thread.h +++ /dev/null @@ -1,37 +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. - * - */ -#ifndef _Thread_ -#define _Thread_ - -namespace qpid { -namespace concurrent { - - class Thread - { - public: - virtual ~Thread(){} - virtual void start() = 0; - virtual void join() = 0; - virtual void interrupt() = 0; - }; - -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/ThreadFactory.h b/cpp/common/concurrent/inc/ThreadFactory.h deleted file mode 100644 index 53be000ff3..0000000000 --- a/cpp/common/concurrent/inc/ThreadFactory.h +++ /dev/null @@ -1,38 +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. - * - */ -#ifndef _ThreadFactory_ -#define _ThreadFactory_ - -#include "Thread.h" -#include "Runnable.h" - -namespace qpid { -namespace concurrent { - - class ThreadFactory - { - public: - virtual ~ThreadFactory(){} - virtual Thread* create(Runnable* runnable) = 0; - }; - -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/ThreadFactoryImpl.h b/cpp/common/concurrent/inc/ThreadFactoryImpl.h deleted file mode 100644 index a534b3c1e2..0000000000 --- a/cpp/common/concurrent/inc/ThreadFactoryImpl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _ThreadFactoryImpl_ -#define _ThreadFactoryImpl_ - - -#ifdef _USE_APR_IO_ -#include "APRThreadFactory.h" -#else -#include "LThreadFactory.h" -#endif - - -namespace qpid { -namespace concurrent { - - -#ifdef _USE_APR_IO_ - class ThreadFactoryImpl : public virtual APRThreadFactory - { - public: - ThreadFactoryImpl(): APRThreadFactory() {}; - virtual ~ThreadFactoryImpl() {}; - }; -#else - class ThreadFactoryImpl : public virtual LThreadFactory - { - public: - ThreadFactoryImpl(): LThreadFactory() {}; - virtual ~ThreadFactoryImpl() {}; - }; -#endif -} -} - - -#endif diff --git a/cpp/common/concurrent/inc/ThreadPool.h b/cpp/common/concurrent/inc/ThreadPool.h deleted file mode 100644 index 679c889ff3..0000000000 --- a/cpp/common/concurrent/inc/ThreadPool.h +++ /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. - * - */ -#ifndef _ThreadPool_ -#define _ThreadPool_ - -#include "Thread.h" -#include "Runnable.h" - -namespace qpid { -namespace concurrent { - - class ThreadPool - { - public: - virtual void start() = 0; - virtual void stop() = 0; - virtual void addTask(Runnable* runnable) = 0; - virtual ~ThreadPool(){} - }; - -} -} - - -#endif diff --git a/cpp/common/concurrent/src/APRBase.cpp b/cpp/common/concurrent/src/APRBase.cpp deleted file mode 100644 index f9b34b9333..0000000000 --- a/cpp/common/concurrent/src/APRBase.cpp +++ /dev/null @@ -1,96 +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 "APRBase.h" -#include "QpidError.h" - -using namespace qpid::concurrent; - -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(); -} - -void qpid::concurrent::check(apr_status_t status, const std::string& file, const int line){ - if (status != APR_SUCCESS){ - const int size = 50; - char tmp[size]; - std::string msg(apr_strerror(status, tmp, size)); - throw QpidError(APR_ERROR + ((int) status), msg, file, line); - } -} - -std::string qpid::concurrent::get_desc(apr_status_t status){ - const int size = 50; - char tmp[size]; - return std::string(apr_strerror(status, tmp, size)); -} - diff --git a/cpp/common/concurrent/src/APRMonitor.cpp b/cpp/common/concurrent/src/APRMonitor.cpp deleted file mode 100644 index 428d76dff9..0000000000 --- a/cpp/common/concurrent/src/APRMonitor.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "APRBase.h" -#include "APRMonitor.h" -#include - -qpid::concurrent::APRMonitor::APRMonitor(){ - APRBase::increment(); - CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); - CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, pool)); - CHECK_APR_SUCCESS(apr_thread_cond_create(&condition, pool)); -} - -qpid::concurrent::APRMonitor::~APRMonitor(){ - CHECK_APR_SUCCESS(apr_thread_cond_destroy(condition)); - CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); - apr_pool_destroy(pool); - APRBase::decrement(); -} - -void qpid::concurrent::APRMonitor::wait(){ - CHECK_APR_SUCCESS(apr_thread_cond_wait(condition, mutex)); -} - - -void qpid::concurrent::APRMonitor::wait(u_int64_t time){ - apr_status_t status = apr_thread_cond_timedwait(condition, mutex, time * 1000); - if(!status == APR_TIMEUP) CHECK_APR_SUCCESS(status); -} - -void qpid::concurrent::APRMonitor::notify(){ - CHECK_APR_SUCCESS(apr_thread_cond_signal(condition)); -} - -void qpid::concurrent::APRMonitor::notifyAll(){ - CHECK_APR_SUCCESS(apr_thread_cond_broadcast(condition)); -} - -void qpid::concurrent::APRMonitor::acquire(){ - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); -} - -void qpid::concurrent::APRMonitor::release(){ - CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); -} diff --git a/cpp/common/concurrent/src/APRThread.cpp b/cpp/common/concurrent/src/APRThread.cpp deleted file mode 100644 index 4167fb76ff..0000000000 --- a/cpp/common/concurrent/src/APRThread.cpp +++ /dev/null @@ -1,50 +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 "APRBase.h" -#include "APRThread.h" -#include "apr_portable.h" - -using namespace qpid::concurrent; - -void* APR_THREAD_FUNC ExecRunnable(apr_thread_t* thread, void *data){ - ((Runnable*) data)->run(); - CHECK_APR_SUCCESS(apr_thread_exit(thread, APR_SUCCESS)); - return NULL; -} - -APRThread::APRThread(apr_pool_t* _pool, Runnable* _runnable) : runnable(_runnable), pool(_pool) {} - -APRThread::~APRThread(){ -} - -void APRThread::start(){ - CHECK_APR_SUCCESS(apr_thread_create(&runner, NULL, ExecRunnable,(void*) runnable, pool)); -} - -void APRThread::join(){ - apr_status_t status; - CHECK_APR_SUCCESS(apr_thread_join(&status, runner)); -} - -void APRThread::interrupt(){ - CHECK_APR_SUCCESS(apr_thread_exit(runner, APR_SUCCESS)); -} - -unsigned int qpid::concurrent::APRThread::currentThread(){ - return apr_os_thread_current(); -} diff --git a/cpp/common/concurrent/src/APRThreadFactory.cpp b/cpp/common/concurrent/src/APRThreadFactory.cpp deleted file mode 100644 index 9ba68e9e56..0000000000 --- a/cpp/common/concurrent/src/APRThreadFactory.cpp +++ /dev/null @@ -1,35 +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 "APRBase.h" -#include "APRThreadFactory.h" - -using namespace qpid::concurrent; - -APRThreadFactory::APRThreadFactory(){ - APRBase::increment(); - CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); -} - -APRThreadFactory::~APRThreadFactory(){ - apr_pool_destroy(pool); - APRBase::decrement(); -} - -Thread* APRThreadFactory::create(Runnable* runnable){ - return new APRThread(pool, runnable); -} diff --git a/cpp/common/concurrent/src/APRThreadPool.cpp b/cpp/common/concurrent/src/APRThreadPool.cpp deleted file mode 100644 index 8518d98b67..0000000000 --- a/cpp/common/concurrent/src/APRThreadPool.cpp +++ /dev/null @@ -1,83 +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 "APRThreadFactory.h" -#include "APRThreadPool.h" -#include "QpidError.h" -#include - -using namespace qpid::concurrent; - -APRThreadPool::APRThreadPool(int _size) : deleteFactory(true), size(_size), factory(new APRThreadFactory()), running(false){ - worker = new Worker(this); -} - -APRThreadPool::APRThreadPool(int _size, ThreadFactory* _factory) : deleteFactory(false), size(_size), factory(_factory), running(false){ - worker = new Worker(this); -} - -APRThreadPool::~APRThreadPool(){ - if(deleteFactory) delete factory; -} - -void APRThreadPool::addTask(Runnable* task){ - lock.acquire(); - tasks.push(task); - lock.notifyAll(); - lock.release(); -} - -void APRThreadPool::runTask(){ - lock.acquire(); - while(tasks.empty()){ - lock.wait(); - } - Runnable* task = tasks.front(); - tasks.pop(); - lock.release(); - try{ - task->run(); - }catch(qpid::QpidError error){ - std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; - } -} - -void APRThreadPool::start(){ - if(!running){ - running = true; - for(int i = 0; i < size; i++){ - Thread* t = factory->create(worker); - t->start(); - threads.push_back(t); - } - } -} - -void APRThreadPool::stop(){ - if(!running){ - running = false; - lock.acquire(); - lock.notifyAll(); - lock.release(); - for(int i = 0; i < size; i++){ - threads[i]->join(); - delete threads[i]; - } - } -} - - diff --git a/cpp/common/concurrent/src/Runnable.cpp b/cpp/common/concurrent/src/Runnable.cpp deleted file mode 100644 index cf9b8d586f..0000000000 --- a/cpp/common/concurrent/src/Runnable.cpp +++ /dev/null @@ -1,19 +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" -qpid::concurrent::Runnable::~Runnable() {} diff --git a/cpp/common/error/inc/Exception.h b/cpp/common/error/inc/Exception.h deleted file mode 100644 index 709538c851..0000000000 --- a/cpp/common/error/inc/Exception.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _Exception_ -#define _Exception_ - -/* - * - * 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 -{ - /** - * 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() : whatStr(str) {} - Exception(const char* str) throw() : whatStr(str) {} - virtual ~Exception() throw(); - - const char* what() const throw() { return whatStr.c_str(); } - virtual std::string toString() const throw() { return whatStr; } - }; -} - -#endif /*!_Exception_*/ diff --git a/cpp/common/error/inc/QpidError.h b/cpp/common/error/inc/QpidError.h deleted file mode 100644 index 3310c71a88..0000000000 --- a/cpp/common/error/inc/QpidError.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef __QpidError__ -#define __QpidError__ -/* - * - * 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" - -namespace qpid { - - class QpidError : public Exception { - public: - const int code; - const std::string msg; - const std::string file; - const int line; - - QpidError(int _code, const std::string& _msg, const std::string& _file, int _line) throw(); - ~QpidError() throw(); - }; - -#define THROW_QPID_ERROR(A, B) throw QpidError(A, B, __FILE__, __LINE__) - -} - -#define PROTOCOL_ERROR 10000 -#define APR_ERROR 20000 -#define FRAMING_ERROR 30000 -#define CLIENT_ERROR 40000 -#define INTERNAL_ERROR 50000 - -#endif diff --git a/cpp/common/error/src/Exception.cpp b/cpp/common/error/src/Exception.cpp deleted file mode 100644 index 69e5f135f2..0000000000 --- a/cpp/common/error/src/Exception.cpp +++ /dev/null @@ -1,21 +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 "Exception.h" - -qpid::Exception::~Exception() throw() {} diff --git a/cpp/common/error/src/QpidError.cpp b/cpp/common/error/src/QpidError.cpp deleted file mode 100644 index c8049ab3cb..0000000000 --- a/cpp/common/error/src/QpidError.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 "QpidError.h" -#include - -using namespace qpid; - -QpidError::QpidError(int _code, const std::string& _msg, const std::string& _file, int _line) throw() - : code(_code), msg(_msg), file(_file), line(_line) -{ - std::ostringstream os; - os << "QpidError(" << code << ") " << msg << " (" << file << ":" << line << ")"; - whatStr = os.str(); -} - -QpidError::~QpidError() throw() {} diff --git a/cpp/common/framing/Makefile b/cpp/common/framing/Makefile deleted file mode 100644 index 1dfc286050..0000000000 --- a/cpp/common/framing/Makefile +++ /dev/null @@ -1,28 +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. -# - -.PHONY: all clean test - -all: - @$(MAKE) -C generated all - -test: - @$(MAKE) -C test all - -clean : - @$(MAKE) -C generated clean - @$(MAKE) -C test clean - diff --git a/cpp/common/framing/generated/Makefile b/cpp/common/framing/generated/Makefile deleted file mode 100644 index 12ec402760..0000000000 --- a/cpp/common/framing/generated/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (c) 2006 The Apache Software Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -QPID_HOME = ../../../.. -include ${QPID_HOME}/cpp/options.mk - -STYLESHEET_DIR = stylesheets -JAVA = java -XSLTP = ${TOOLS_DIR}/saxon8.jar - -SPEC = ${SPEC_DIR}/amqp-8.0.xml -STYLESHEETS = $(wildcard stylesheets/*.xsl) - -GENERATED_SOURCES=amqp_methods.cpp # Seed generation - -.PHONY: all clean - -all: ${GENERATED_SOURCES} - -clean : - -@rm -f *.cpp *.h - -${GENERATED_SOURCES}: ${STYLESHEETS} ${SPEC} - ${JAVA} -jar ${XSLTP} -o results.out ${SPEC} ${STYLESHEET_DIR}/code_gen.xsl - ${JAVA} -jar ${XSLTP} -o results.out ${SPEC} ${STYLESHEET_DIR}/framing.xsl - --include $(GENERATED_SOURCES:.cpp=.d) - diff --git a/cpp/common/framing/generated/stylesheets/amqp_client.xsl b/cpp/common/framing/generated/stylesheets/amqp_client.xsl deleted file mode 100644 index 13a912a926..0000000000 --- a/cpp/common/framing/generated/stylesheets/amqp_client.xsl +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - -#ifndef _AMQP_ServerProxy_ -#define _AMQP_ServerProxy_ - -#include "AMQP_ServerOperations.h" -#include "FieldTable.h" -#include "OutputHandler.h" - -namespace qpid { -namespace framing { - -class AMQP_ServerProxy : virtual public AMQP_ServerOperations -{ - OutputHandler* out; - - public: - AMQP_ServerProxy(OutputHandler* _out); - virtual ~AMQP_ServerProxy() {} - - - - /** ===== Class: ===== - - */ - - class : virtual public AMQP_ServerOperations::Handler - { - OutputHandler* out; - - public: - /* Constructors and destructors */ - (OutputHandler* _out); - virtual ~(); - - /* Protocol methods */ - - - - - /** ----- Method: . ----- - - */ - - - /** - Rule "": - */ - - virtual void - ( u_int16_t channel, - - - - - , - - - - ); - - - }; /* class */ - - }; /* class AMQP_ServerProxy */ - -} /* namespace framing */ -} /* namespace qpid */ - -#endif - - - - - - - - - - - -#include "AMQP_ServerProxy.h" - -namespace qpid { -namespace framing { - -AMQP_ServerProxy::AMQP_ServerProxy(OutputHandler* _out) : - out(_out) -{ -} - - - /* ++++++++++ Class: ++++++++++ */ - -AMQP_ServerProxy::::(OutputHandler* _out) : - out(_out) -{ -} - -AMQP_ServerProxy::::~() {} - - - void AMQP_ServerProxy:::: - ( u_int16_t channel - , - - - - - , - - - - ) -{ - out->send( new AMQFrame( channel, - new ( - - - - , - - - ) ) ); -} - - - - - -} /* namespace framing */ -} /* namespace qpid */ - - - - diff --git a/cpp/common/framing/generated/stylesheets/amqp_client_handler_impl.xsl b/cpp/common/framing/generated/stylesheets/amqp_client_handler_impl.xsl deleted file mode 100644 index 0cc34e0ecf..0000000000 --- a/cpp/common/framing/generated/stylesheets/amqp_client_handler_impl.xsl +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - - - - - -#ifndef _AMQP_ClientHandlerImpl_ -#define _AMQP_ClientHandlerImpl_ - -#include "AMQP_ClientOperations.h" -#include "FieldTable.h" - -namespace qpid { -namespace framing { - -class AMQP_ClientHandlerImpl : virtual public AMQP_ClientOperations -{ - - - - - AMQP_ClientOperations::* - Ptr; - - - public: - AMQP_ClientHandlerImpl(); - virtual ~AMQP_ClientHandlerImpl(); - - - - - inline AMQP_ClientOperations:: - * get - () { return Ptr; } - - - - - - - - - - /** - ===== Class: Impl ===== - - */ - - - - class - Impl : virtual public AMQP_ClientOperations:: - { - public: - /* Constructors and destructors */ - Impl(); - virtual ~Impl(); - - /* Protocol methods */ - - - - - - - - - /** - ----- Method: - Impl. ----- - - */ - - - /** - Rule "": - - */ - - - - virtual void - ( u_int16_t channel - - - - , - - - - - , - - - - ); - - - }; /* class Impl */ - - }; /* AMQP_ClientHandlerImpl */ - -} /* namespace framing */ -} /* namespace qpid */ - -#endif - - - - - - - - - -#include "AMQP_ClientHandlerImpl.h" - -namespace qpid { -namespace framing { - -AMQP_ClientHandlerImpl::AMQP_ClientHandlerImpl() : - - - - HandlerPtr( new HandlerImpl() ) - - , - - - -{ -} - -AMQP_ClientHandlerImpl::~AMQP_ClientHandlerImpl() -{ - - delete HandlerPtr; - } - - - - /* ===== Class: HandlerImpl ===== */ - AMQP_ClientHandlerImpl::HandlerImpl:: - HandlerImpl() { } - AMQP_ClientHandlerImpl::HandlerImpl::~ - HandlerImpl() { } - - - void AMQP_ClientHandlerImpl::HandlerImpl:: - ( u_int16_t /*channel*/ - - , - - - - - , - - - ) { } - - - - - -} /* namespace framing */ -} /* namespace qpid */ - - - - diff --git a/cpp/common/framing/generated/stylesheets/amqp_client_operations.xsl b/cpp/common/framing/generated/stylesheets/amqp_client_operations.xsl deleted file mode 100644 index 234b7080ba..0000000000 --- a/cpp/common/framing/generated/stylesheets/amqp_client_operations.xsl +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - - -#ifndef _AMQP_ClientOperations_ -#define _AMQP_ClientOperations_ - -#include "AMQP_Constants.h" -#include "FieldTable.h" - -namespace qpid { -namespace framing { - -class AMQP_ClientOperations -{ - public: - AMQP_ClientOperations() {} - virtual ~AMQP_ClientOperations() {} - inline u_int16_t getAmqpMajor() { return (u_int16_t); } - inline u_int16_t getAmqpMinor() { return (u_int16_t); } - - - - - - - - /** ===== Class: ===== - - */ - - - - class - { - public: - /* Constructors and destructors */ - () {} - virtual ~() {} - - /* Protocol methods */ - - - - - - - - - /** ----- Method: . - ----- - - */ - - - /** - Rule "": - - */ - - - - virtual void - ( u_int16_t channel - - - - , - - - - - , - - - - ) = 0; - - - }; /* class */ - - }; /* class AMQP_ClientOperations */ - -} /* namespace framing */ -} /* namespace qpid */ - -#endif - - - - diff --git a/cpp/common/framing/generated/stylesheets/amqp_consts.xsl b/cpp/common/framing/generated/stylesheets/amqp_consts.xsl deleted file mode 100644 index c1c927f941..0000000000 --- a/cpp/common/framing/generated/stylesheets/amqp_consts.xsl +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#ifndef _AMQP_Constants_ -#define _AMQP_Constants_ - -#include "amqp_types.h" - -namespace qpid { -namespace framing { - -/**** Constants ****/ - - - /* - - */ - - const u_int16_t ; - - - -} /* namespace framing */ -} /* namespace qpid */ - -#endif - - - - diff --git a/cpp/common/framing/generated/stylesheets/amqp_server.xsl b/cpp/common/framing/generated/stylesheets/amqp_server.xsl deleted file mode 100644 index 5ff8994888..0000000000 --- a/cpp/common/framing/generated/stylesheets/amqp_server.xsl +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - - - - -#ifndef _AMQP_ClientProxy_ -#define _AMQP_ClientProxy_ - -#include "AMQP_ClientOperations.h" -#include "FieldTable.h" -#include "OutputHandler.h" - -namespace qpid { -namespace framing { - -class AMQP_ClientProxy : virtual public AMQP_ClientOperations -{ - public: - - AMQP_ClientProxy(OutputHandler* _out); - virtual ~AMQP_ClientProxy() {}; - - - - - - /** ===== Class: ===== - - */ - - class : virtual public AMQP_ClientOperations::Handler - { - OutputHandler* out; - - public: - /* Constructors and destructors */ - (OutputHandler* _out); - virtual ~(); - - /* Protocol methods */ - - - - - /** ----- Method: . ----- - - */ - - - /** - Rule "": - */ - - virtual void - ( u_int16_t channel, - - - - - , - - - - ); - - - }; /* class */ - - - - - ; - - - private: - - OutputHandler* out; - - - - ; - - - - - }; /* class AMQP_ClientProxy */ - -} /* namespace framing */ -} /* namespace qpid */ - -#endif - - - - - - - - - - -#include "AMQP_ClientProxy.h" - -namespace qpid { -namespace framing { - -AMQP_ClientProxy::AMQP_ClientProxy(OutputHandler* _out) : - out(_out), - - - - , - - - -{ -} - - - - /* ++++++++++ Class: ++++++++++ */ - -AMQP_ClientProxy::::(OutputHandler* _out) : - out(_out) -{ -} - -AMQP_ClientProxy::::~() {} - - - void AMQP_ClientProxy:::: - ( u_int16_t channel - , - - - - - , - - - - ) -{ - out->send( new AMQFrame( channel, - new ( - - - - , - - - ) ) ); -} - - - - - - - { - ; - } - - - - -} /* namespace framing */ -} /* namespace qpid */ - - - - diff --git a/cpp/common/framing/generated/stylesheets/amqp_server_handler_impl.xsl b/cpp/common/framing/generated/stylesheets/amqp_server_handler_impl.xsl deleted file mode 100644 index 6450d3fd0c..0000000000 --- a/cpp/common/framing/generated/stylesheets/amqp_server_handler_impl.xsl +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - - - - - -#ifndef _AMQP_ServerHandlerImpl_ -#define _AMQP_ServerHandlerImpl_ - -#include "AMQP_ServerOperations.h" -#include "FieldTable.h" - -namespace qpid { -namespace framing { - -class AMQP_ServerHandlerImpl : virtual public AMQP_ServerOperations -{ - - - - - AMQP_ServerOperations::* - Ptr; - - - public: - AMQP_ServerHandlerImpl(); - virtual ~AMQP_ServerHandlerImpl(); - - - - - virtual inline AMQP_ServerOperations:: - * get - () { return Ptr; } - - - - - - - - - - /** - ===== Class: Impl ===== - - */ - - - - class - Impl : virtual public AMQP_ServerOperations:: - { - public: - /* Constructors and destructors */ - Impl(); - virtual ~Impl(); - - /* Protocol methods */ - - - - - - - - - /** - ----- Method: - Impl. ----- - - */ - - - /** - Rule "": - - */ - - - - virtual void - ( u_int16_t channel - - - - , - - - - - , - - - - ); - - - }; /* class Impl */ - - }; /* AMQP_ServerHandlerImpl */ - -} /* namespace framing */ -} /* namespace qpid */ - -#endif - - - - - - - - - -#include "AMQP_ServerHandlerImpl.h" - -namespace qpid { -namespace framing { - -AMQP_ServerHandlerImpl::AMQP_ServerHandlerImpl() : - - - - HandlerPtr( new HandlerImpl() ) - - , - - - -{ -} - -AMQP_ServerHandlerImpl::~AMQP_ServerHandlerImpl() -{ - - delete HandlerPtr; - } - - - - /* ===== Class: HandlerImpl ===== */ - AMQP_ServerHandlerImpl::HandlerImpl:: - HandlerImpl() { } - AMQP_ServerHandlerImpl::HandlerImpl::~ - HandlerImpl() { } - - - void AMQP_ServerHandlerImpl::HandlerImpl:: - ( u_int16_t /*channel*/ - - , - - - - - , - - - ) { } - - - - - -} /* namespace framing */ -} /* namespace qpid */ - - - - diff --git a/cpp/common/framing/generated/stylesheets/amqp_server_operations.xsl b/cpp/common/framing/generated/stylesheets/amqp_server_operations.xsl deleted file mode 100644 index 4b97700f04..0000000000 --- a/cpp/common/framing/generated/stylesheets/amqp_server_operations.xsl +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - -#ifndef _AMQP_ServerOperations_ -#define _AMQP_ServerOperations_ - -#include "AMQP_Constants.h" -#include "FieldTable.h" - -namespace qpid { -namespace framing { - -class AMQP_ServerOperations -{ - public: - AMQP_ServerOperations() {} - virtual ~AMQP_ServerOperations() {} - inline u_int16_t getAmqpMajor() { return (u_int16_t); } - inline u_int16_t getAmqpMinor() { return (u_int16_t); } - - - - - - - - /** ===== Class: ===== - - */ - - - - class - { - public: - /* Constructors and destructors */ - () {} - virtual ~() {} - - /* Protocol methods */ - - - - - - - - - /** ----- Method: . - ----- - - */ - - - /** - Rule "": - - */ - - - - virtual void - ( u_int16_t channel - - - - , - - - - - , - - - - ) = 0; - - - }; /* class */ - - - - - virtual AMQP_ServerOperations:: - * get - () = 0; - - - }; /* class AMQP_ServerOperations */ - -} /* namespace framing */ -} /* namespace qpid */ - -#endif - - - - diff --git a/cpp/common/framing/generated/stylesheets/code_gen.xsl b/cpp/common/framing/generated/stylesheets/code_gen.xsl deleted file mode 100644 index 5e9f4ef8f0..0000000000 --- a/cpp/common/framing/generated/stylesheets/code_gen.xsl +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cpp/common/framing/generated/stylesheets/code_utils.xsl b/cpp/common/framing/generated/stylesheets/code_utils.xsl deleted file mode 100644 index f4a0f6e5ce..0000000000 --- a/cpp/common/framing/generated/stylesheets/code_utils.xsl +++ /dev/null @@ -1,210 +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. -* -*/ - -/** -* -* NOTE: This file is generated directly from the AMQP XML specification. -* === DO NOT EDIT === -* -*/ - - - - - - - - - - - - - delete_ - return_ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - u_int8_t - u_int16_t - string - string - bool - u_int32_t - u_int64_t - u_int64_t - - FieldTable - - unknown_type /* WARNING: undefined type */ - - - - - - - - & - & - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cpp/common/framing/generated/stylesheets/convert_0.81.xsl b/cpp/common/framing/generated/stylesheets/convert_0.81.xsl deleted file mode 100644 index 9924f165da..0000000000 --- a/cpp/common/framing/generated/stylesheets/convert_0.81.xsl +++ /dev/null @@ -1,407 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - ==================== - Constants - ==================== - - - - - - - - - - ==================== - Domains - ==================== - - - - - - - - - Elementary domains - - bit - bit - single bit - - - octet - octet - single octet - - - short - short - 16-bit integer - - - long - long - 32-bit integer - - - longlong - longlong - 64-bit integer - - - shortstr - shortstr - short string - - - longstr - longstr - long string - - - timestamp - timestamp - 64-bit timestamp - - - table - table - field table - - - - - - ==================== - Classes - ==================== - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -rule__ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -doc_rule__ - - - - - - - - - - - -grammar - - - - - - - - - - - - diff --git a/cpp/common/framing/generated/stylesheets/cpp.xsl b/cpp/common/framing/generated/stylesheets/cpp.xsl deleted file mode 100644 index f9e5ba4141..0000000000 --- a/cpp/common/framing/generated/stylesheets/cpp.xsl +++ /dev/null @@ -1,315 +0,0 @@ - - - - - - - - - - - - - - - - - - -#include "amqp_framing.h" - - - - - - - - - - - - -#include "amqp_types.h" -#include "AMQP_ServerOperations.h" -#include "AMQMethodBody.h" -#include "Buffer.h" -#include "FieldTable.h" - -#ifndef __ -#define __ - -namespace qpid { -namespace framing { - - - - -} -} - -#endif - - - - - - - - -/** - * This class is autogenerated, do not modify. [From ] - */ -class : virtual public AMQMethodBody -{ - - - - ; - - -public: - typedef std::tr1::shared_ptr<> shared_ptr; - - virtual ~() {} - - - inline ; } - - - - inline void print(std::ostream& out) const{ - out << "" - - << ", - ="<< - - - ; - } - - inline u_int16_t amqpClassId() const { - return ; - } - - inline u_int16_t amqpMethodId() const { - return ; - } - - inline u_int32_t bodySize() const { - - - return - - + - - - - ; - - return 0; - - } - - - inline void invoke(AMQP_ServerOperations& target, u_int16_t channel) { - - - ); - - - ; - - } - - - inline void encodeContent(Buffer& buffer) const - { - - u_int8_t flags = 0; - - ; - - - - - ; - - - buffer.putOctet(flags); - - - } - - inline void decodeContent(Buffer& buffer) - { - - - - u_int8_t flags = buffer.getOctet(); - ; - - - ; - - - - } - - - - inline () : - { - } - - - inline () - { - } -}; - - - - - -/** - * This file is autogenerated, do not modify. - */ - -#ifndef AMQ_METHODS_H -#define AMQ_METHODS_H - - -#include ".h" - - -namespace qpid { -namespace framing { - - -const ; - - -AMQMethodBody* createAMQMethodBody(u_int16_t classId, u_int16_t methodId); - -} -} - -#endif - - - - - -#include "amqp_methods.h" -#include "QpidError.h" - -namespace qpid { -namespace framing { -/** - * This method is autogenerated, do not modify. - */ -AMQMethodBody* createAMQMethodBody(u_int16_t classId, u_int16_t methodId){ - switch(classId * 1000 + methodId) - { - - case - - * 1000 + - - : return new - (); - - } - THROW_QPID_ERROR(FRAMING_ERROR, "Unknown method"); -} - -} -} - - - - - -#include "amqp_types.h" -#include "FieldTable.h" - -#ifndef _AMQPServer_ -#define _AMQPServer_ - -namespace qpid { -namespace framing { - -class AMQPServer -{ - public: - - - class { - public: - - - virtual void (u_int16_t channel, ) = 0; - - - virtual void (u_int16_t channel) = 0; - - - virtual ~(){} - }; - - virtual () = 0; - - - virtual ~AMQPServer(){} -}; - -} -} - -#endif - - - -#include "amqp_types.h" -#include "FieldTable.h" - -#ifndef _AMQPClient_ -#define _AMQPClient_ - -namespace qpid { -namespace framing { - -class AMQPClient -{ - public: - - - class { - public: - - - virtual void (u_int16_t channel, ) = 0; - - - virtual void (u_int16_t channel) = 0; - - - virtual ~(){} - }; - - virtual () = 0; - - - - virtual ~AMQPClient(){} -}; - -} -} - -#endif - - - - - diff --git a/cpp/common/framing/generated/stylesheets/framing.xsl b/cpp/common/framing/generated/stylesheets/framing.xsl deleted file mode 100644 index c63e719a77..0000000000 --- a/cpp/common/framing/generated/stylesheets/framing.xsl +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cpp/common/framing/generated/stylesheets/prepare1.xsl b/cpp/common/framing/generated/stylesheets/prepare1.xsl deleted file mode 100644 index 2aeda89677..0000000000 --- a/cpp/common/framing/generated/stylesheets/prepare1.xsl +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - ( - major= - , minor= - ) - - - - - - - - - - - - - - - - - - - - - - - - Could not inherit from ; file not found. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - true - - - - - - - - - - - - - - - - - - - - - - diff --git a/cpp/common/framing/generated/stylesheets/prepare2.xsl b/cpp/common/framing/generated/stylesheets/prepare2.xsl deleted file mode 100644 index 331319de57..0000000000 --- a/cpp/common/framing/generated/stylesheets/prepare2.xsl +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cpp/common/framing/generated/stylesheets/prepare3.xsl b/cpp/common/framing/generated/stylesheets/prepare3.xsl deleted file mode 100644 index 27a4764e4f..0000000000 --- a/cpp/common/framing/generated/stylesheets/prepare3.xsl +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - - - - - - - - - - - - - - - - - - diff --git a/cpp/common/framing/generated/stylesheets/registry.xsl b/cpp/common/framing/generated/stylesheets/registry.xsl deleted file mode 100644 index a818a0a871..0000000000 --- a/cpp/common/framing/generated/stylesheets/registry.xsl +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/cpp/common/framing/generated/stylesheets/utils.xsl b/cpp/common/framing/generated/stylesheets/utils.xsl deleted file mode 100644 index 70743112a9..0000000000 --- a/cpp/common/framing/generated/stylesheets/utils.xsl +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - u_int8_t - u_int16_t - string - string - bool - u_int32_t - u_int64_t - FieldTable - Object /*WARNING: undefined type*/ - - - - - - u_int8_t - u_int16_t - const string& - const string& - bool - u_int32_t - u_int64_t - FieldTable& - Object /*WARNING: undefined type*/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* WARNING: COULD NOT DETERMINE FIELD SIZE */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* WARNING: COULD NOT DETERMINE ENCODER */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* WARNING: COULD NOT DETERMINE DECODER */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cpp/common/framing/inc/AMQBody.h b/cpp/common/framing/inc/AMQBody.h deleted file mode 100644 index a1770820a9..0000000000 --- a/cpp/common/framing/inc/AMQBody.h +++ /dev/null @@ -1,48 +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 "memory.h" -#include "amqp_types.h" -#include "Buffer.h" - -#ifndef _AMQBody_ -#define _AMQBody_ - -namespace qpid { - namespace framing { - - class AMQBody - { - public: - typedef std::tr1::shared_ptr shared_ptr; - - virtual ~AMQBody(); - virtual u_int32_t size() const = 0; - virtual u_int8_t type() const = 0; - virtual void encode(Buffer& buffer) const = 0; - virtual void decode(Buffer& buffer, u_int32_t size) = 0; - virtual void print(std::ostream& out) const; - }; - - std::ostream& operator<<(std::ostream& out, const AMQBody& body) ; - - enum body_types {METHOD_BODY = 1, HEADER_BODY = 2, CONTENT_BODY = 3, HEARTBEAT_BODY = 8}; - } -} - - -#endif diff --git a/cpp/common/framing/inc/AMQContentBody.h b/cpp/common/framing/inc/AMQContentBody.h deleted file mode 100644 index daf7d6cd44..0000000000 --- a/cpp/common/framing/inc/AMQContentBody.h +++ /dev/null @@ -1,50 +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_types.h" -#include "AMQBody.h" -#include "Buffer.h" - -#ifndef _AMQContentBody_ -#define _AMQContentBody_ - -namespace qpid { -namespace framing { - -class AMQContentBody : virtual public AMQBody -{ - string data; - -public: - typedef std::tr1::shared_ptr shared_ptr; - - AMQContentBody(); - AMQContentBody(const string& data); - inline virtual ~AMQContentBody(){} - inline u_int8_t type() const { return CONTENT_BODY; }; - inline string& getData(){ return data; } - u_int32_t size() const; - void encode(Buffer& buffer) const; - void decode(Buffer& buffer, u_int32_t size); - void print(std::ostream& out) const; -}; - -} -} - - -#endif diff --git a/cpp/common/framing/inc/AMQDataBlock.h b/cpp/common/framing/inc/AMQDataBlock.h deleted file mode 100644 index 6c47c78864..0000000000 --- a/cpp/common/framing/inc/AMQDataBlock.h +++ /dev/null @@ -1,39 +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 "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 u_int32_t size() const = 0; -}; - -} -} - - -#endif diff --git a/cpp/common/framing/inc/AMQFrame.h b/cpp/common/framing/inc/AMQFrame.h deleted file mode 100644 index 5656d20377..0000000000 --- a/cpp/common/framing/inc/AMQFrame.h +++ /dev/null @@ -1,61 +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_methods.h" -#include "amqp_types.h" -#include "AMQBody.h" -#include "AMQDataBlock.h" -#include "AMQMethodBody.h" -#include "AMQHeaderBody.h" -#include "AMQContentBody.h" -#include "AMQHeartbeatBody.h" -#include "Buffer.h" - -#ifndef _AMQFrame_ -#define _AMQFrame_ - -namespace qpid { - namespace framing { - - class AMQFrame : virtual public AMQDataBlock - { - u_int16_t channel; - u_int8_t type;//used if the body is decoded separately from the 'head' - AMQBody::shared_ptr body; - - public: - AMQFrame(); - AMQFrame(u_int16_t channel, AMQBody* body); - AMQFrame(u_int16_t channel, AMQBody::shared_ptr& body); - virtual ~AMQFrame(); - virtual void encode(Buffer& buffer); - virtual bool decode(Buffer& buffer); - virtual u_int32_t size() const; - u_int16_t getChannel(); - AMQBody::shared_ptr& getBody(); - - u_int32_t decodeHead(Buffer& buffer); - void decodeBody(Buffer& buffer, uint32_t size); - - friend std::ostream& operator<<(std::ostream& out, const AMQFrame& body); - }; - - } -} - - -#endif diff --git a/cpp/common/framing/inc/AMQHeaderBody.h b/cpp/common/framing/inc/AMQHeaderBody.h deleted file mode 100644 index 4f9cdb571a..0000000000 --- a/cpp/common/framing/inc/AMQHeaderBody.h +++ /dev/null @@ -1,57 +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_types.h" -#include "AMQBody.h" -#include "Buffer.h" -#include "HeaderProperties.h" - -#ifndef _AMQHeaderBody_ -#define _AMQHeaderBody_ - -namespace qpid { -namespace framing { - -class AMQHeaderBody : virtual public AMQBody -{ - HeaderProperties* properties; - u_int16_t weight; - u_int64_t contentSize; - - void createProperties(int classId); -public: - typedef std::tr1::shared_ptr shared_ptr; - - AMQHeaderBody(int classId); - AMQHeaderBody(); - inline u_int8_t type() const { return HEADER_BODY; } - HeaderProperties* getProperties(){ return properties; } - const HeaderProperties* getProperties() const { return properties; } - inline u_int64_t getContentSize() const { return contentSize; } - inline void setContentSize(u_int64_t _size) { contentSize = _size; } - virtual ~AMQHeaderBody(); - virtual u_int32_t size() const; - virtual void encode(Buffer& buffer) const; - virtual void decode(Buffer& buffer, u_int32_t size); - virtual void print(std::ostream& out) const; -}; - -} -} - - -#endif diff --git a/cpp/common/framing/inc/AMQHeartbeatBody.h b/cpp/common/framing/inc/AMQHeartbeatBody.h deleted file mode 100644 index da612a2a44..0000000000 --- a/cpp/common/framing/inc/AMQHeartbeatBody.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "amqp_types.h" -#include "AMQBody.h" -#include "Buffer.h" - -#ifndef _AMQHeartbeatBody_ -#define _AMQHeartbeatBody_ - -namespace qpid { -namespace framing { - -class AMQHeartbeatBody : virtual public AMQBody -{ -public: - typedef std::tr1::shared_ptr shared_ptr; - - virtual ~AMQHeartbeatBody(); - inline u_int32_t size() const { return 0; } - inline u_int8_t type() const { return HEARTBEAT_BODY; } - inline void encode(Buffer& ) const {} - inline void decode(Buffer& , u_int32_t /*size*/) {} - virtual void print(std::ostream& out) const; -}; - -} -} - -#endif diff --git a/cpp/common/framing/inc/AMQMethodBody.h b/cpp/common/framing/inc/AMQMethodBody.h deleted file mode 100644 index 59d5dd5212..0000000000 --- a/cpp/common/framing/inc/AMQMethodBody.h +++ /dev/null @@ -1,56 +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 "amqp_types.h" -#include "AMQBody.h" -#include "Buffer.h" -#include "AMQP_ServerOperations.h" - -#ifndef _AMQMethodBody_ -#define _AMQMethodBody_ - -namespace qpid { -namespace framing { - -class AMQMethodBody : virtual public AMQBody -{ -public: - typedef std::tr1::shared_ptr shared_ptr; - - inline u_int8_t type() const { return METHOD_BODY; } - inline u_int32_t size() const { return 4 + bodySize(); } - inline virtual ~AMQMethodBody(){} - virtual void print(std::ostream& out) const = 0; - virtual u_int16_t amqpMethodId() const = 0; - virtual u_int16_t amqpClassId() const = 0; - virtual void invoke(AMQP_ServerOperations& target, u_int16_t channel); - virtual void encodeContent(Buffer& buffer) const = 0; - virtual void decodeContent(Buffer& buffer) = 0; - virtual u_int32_t bodySize() const = 0; - void encode(Buffer& buffer) const; - void decode(Buffer& buffer, u_int32_t size); - bool match(AMQMethodBody* other) const; -}; - -std::ostream& operator<<(std::ostream& out, const AMQMethodBody& body); - -} -} - - -#endif diff --git a/cpp/common/framing/inc/BasicHeaderProperties.h b/cpp/common/framing/inc/BasicHeaderProperties.h deleted file mode 100644 index c32612221b..0000000000 --- a/cpp/common/framing/inc/BasicHeaderProperties.h +++ /dev/null @@ -1,93 +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_types.h" -#include "amqp_methods.h" -#include "Buffer.h" -#include "HeaderProperties.h" - -#ifndef _BasicHeaderProperties_ -#define _BasicHeaderProperties_ - -namespace qpid { -namespace framing { - - //TODO: This could be easily generated from the spec - class BasicHeaderProperties : public HeaderProperties - { - string contentType; - string contentEncoding; - FieldTable headers; - u_int8_t deliveryMode; - u_int8_t priority; - string correlationId; - string replyTo; - string expiration; - string messageId; - u_int64_t timestamp; - string type; - string userId; - string appId; - string clusterId; - - u_int16_t getFlags() const; - - public: - BasicHeaderProperties(); - virtual ~BasicHeaderProperties(); - virtual u_int32_t size() const; - virtual void encode(Buffer& buffer) const; - virtual void decode(Buffer& buffer, u_int32_t size); - - inline virtual u_int8_t classId(){ return BASIC; } - - inline string& getContentType(){ return contentType; } - inline string& getContentEncoding(){ return contentEncoding; } - inline FieldTable& getHeaders(){ return headers; } - inline u_int8_t getDeliveryMode(){ return deliveryMode; } - inline u_int8_t getPriority(){ return priority; } - inline string& getCorrelationId(){return correlationId; } - inline string& getReplyTo(){ return replyTo; } - inline string& getExpiration(){ return expiration; } - inline string& getMessageId(){return messageId; } - inline u_int64_t getTimestamp(){ return timestamp; } - inline string& getType(){ return type; } - inline string& getUserId(){ return userId; } - inline string& getAppId(){ return appId; } - inline string& getClusterId(){ return clusterId; } - - void inline setContentType(string& _type){ contentType = _type; } - void inline setContentEncoding(string& encoding){ contentEncoding = encoding; } - void inline setHeaders(FieldTable& _headers){ headers = _headers; } - void inline setDeliveryMode(u_int8_t mode){ deliveryMode = mode; } - void inline setPriority(u_int8_t _priority){ priority = _priority; } - void inline setCorrelationId(string& _correlationId){ correlationId = _correlationId; } - void inline setReplyTo(string& _replyTo){ replyTo = _replyTo;} - void inline setExpiration(string& _expiration){ expiration = _expiration; } - void inline setMessageId(string& _messageId){ messageId = _messageId; } - void inline setTimestamp(u_int64_t _timestamp){ timestamp = _timestamp; } - void inline setType(string& _type){ type = _type; } - void inline setUserId(string& _userId){ userId = _userId; } - void inline setAppId(string& _appId){appId = _appId; } - void inline setClusterId(string& _clusterId){ clusterId = _clusterId; } - }; - -} -} - - -#endif diff --git a/cpp/common/framing/inc/BodyHandler.h b/cpp/common/framing/inc/BodyHandler.h deleted file mode 100644 index a4aee2709e..0000000000 --- a/cpp/common/framing/inc/BodyHandler.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include - -#ifndef _BodyHandler_ -#define _BodyHandler_ - -#include "AMQMethodBody.h" -#include "AMQHeaderBody.h" -#include "AMQContentBody.h" -#include "AMQHeartbeatBody.h" - -namespace qpid { -namespace framing { - - class BodyHandler{ - public: - virtual ~BodyHandler(); - virtual void handleMethod(AMQMethodBody::shared_ptr body) = 0; - virtual void handleHeader(AMQHeaderBody::shared_ptr body) = 0; - virtual void handleContent(AMQContentBody::shared_ptr body) = 0; - virtual void handleHeartbeat(AMQHeartbeatBody::shared_ptr body) = 0; - - void handleBody(AMQBody::shared_ptr& body); - }; - - class UnknownBodyType{ - public: - const u_int16_t type; - inline UnknownBodyType(u_int16_t _type) : type(_type){} - }; -} -} - - -#endif diff --git a/cpp/common/framing/inc/Buffer.h b/cpp/common/framing/inc/Buffer.h deleted file mode 100644 index 4d3d503b00..0000000000 --- a/cpp/common/framing/inc/Buffer.h +++ /dev/null @@ -1,78 +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_types.h" - -#ifndef _Buffer_ -#define _Buffer_ - -namespace qpid { -namespace framing { - -class FieldTable; - -class Buffer -{ - const u_int32_t size; - char* data; - u_int32_t position; - u_int32_t limit; - u_int32_t r_position; - u_int32_t r_limit; - -public: - - Buffer(u_int32_t size); - ~Buffer(); - - void flip(); - void clear(); - void compact(); - void record(); - void restore(); - u_int32_t available(); - char* start(); - void move(u_int32_t bytes); - - void putOctet(u_int8_t i); - void putShort(u_int16_t i); - void putLong(u_int32_t i); - void putLongLong(u_int64_t i); - - u_int8_t getOctet(); - u_int16_t getShort(); - u_int32_t getLong(); - u_int64_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 putRawData(const string& s); - void getRawData(string& s, u_int32_t size); - -}; - -} -} - - -#endif diff --git a/cpp/common/framing/inc/FieldTable.h b/cpp/common/framing/inc/FieldTable.h deleted file mode 100644 index 7da914968e..0000000000 --- a/cpp/common/framing/inc/FieldTable.h +++ /dev/null @@ -1,78 +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 "amqp_types.h" - -#ifndef _FieldTable_ -#define _FieldTable_ - -namespace qpid { -namespace framing { - -class Value; -class Buffer; - -class FieldTable -{ - public: - typedef std::tr1::shared_ptr ValuePtr; - typedef std::tr1::unordered_map ValueMap; - - ~FieldTable(); - u_int32_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, u_int64_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; - u_int64_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/cpp/common/framing/inc/HeaderProperties.h b/cpp/common/framing/inc/HeaderProperties.h deleted file mode 100644 index f84345c203..0000000000 --- a/cpp/common/framing/inc/HeaderProperties.h +++ /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 "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 u_int8_t classId() = 0; - virtual u_int32_t size() const = 0; - virtual void encode(Buffer& buffer) const = 0; - virtual void decode(Buffer& buffer, u_int32_t size) = 0; - }; -} -} - - -#endif diff --git a/cpp/common/framing/inc/InitiationHandler.h b/cpp/common/framing/inc/InitiationHandler.h deleted file mode 100644 index 7b1fb36e2d..0000000000 --- a/cpp/common/framing/inc/InitiationHandler.h +++ /dev/null @@ -1,38 +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 - -#ifndef _InitiationHandler_ -#define _InitiationHandler_ - -#include "ProtocolInitiation.h" - -namespace qpid { -namespace framing { - - class InitiationHandler{ - public: - virtual ~InitiationHandler(); - virtual void initiated(ProtocolInitiation* header) = 0; - }; - -} -} - - -#endif diff --git a/cpp/common/framing/inc/InputHandler.h b/cpp/common/framing/inc/InputHandler.h deleted file mode 100644 index 927bd97ab4..0000000000 --- a/cpp/common/framing/inc/InputHandler.h +++ /dev/null @@ -1,38 +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 - -#ifndef _InputHandler_ -#define _InputHandler_ - -#include "AMQFrame.h" - -namespace qpid { -namespace framing { - - class InputHandler{ - public: - virtual ~InputHandler(); - virtual void received(AMQFrame* frame) = 0; - }; - -} -} - - -#endif diff --git a/cpp/common/framing/inc/OutputHandler.h b/cpp/common/framing/inc/OutputHandler.h deleted file mode 100644 index afc8d7f257..0000000000 --- a/cpp/common/framing/inc/OutputHandler.h +++ /dev/null @@ -1,38 +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 - -#ifndef _OutputHandler_ -#define _OutputHandler_ - -#include "AMQFrame.h" - -namespace qpid { -namespace framing { - - class OutputHandler{ - public: - virtual ~OutputHandler(); - virtual void send(AMQFrame* frame) = 0; - }; - -} -} - - -#endif diff --git a/cpp/common/framing/inc/ProtocolInitiation.h b/cpp/common/framing/inc/ProtocolInitiation.h deleted file mode 100644 index ab9734e6b3..0000000000 --- a/cpp/common/framing/inc/ProtocolInitiation.h +++ /dev/null @@ -1,48 +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_types.h" -#include "Buffer.h" -#include "AMQDataBlock.h" - -#ifndef _ProtocolInitiation_ -#define _ProtocolInitiation_ - -namespace qpid { -namespace framing { - -class ProtocolInitiation : virtual public AMQDataBlock -{ - u_int8_t pmajor; - u_int8_t pminor; - -public: - ProtocolInitiation(); - ProtocolInitiation(u_int8_t major, u_int8_t minor); - virtual ~ProtocolInitiation(); - virtual void encode(Buffer& buffer); - virtual bool decode(Buffer& buffer); - inline virtual u_int32_t size() const { return 8; } - inline u_int8_t getMajor(){ return pmajor; } - inline u_int8_t getMinor(){ return pminor; } -}; - -} -} - - -#endif diff --git a/cpp/common/framing/inc/Value.h b/cpp/common/framing/inc/Value.h deleted file mode 100644 index fe939e8758..0000000000 --- a/cpp/common/framing/inc/Value.h +++ /dev/null @@ -1,160 +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 "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 { - u_int32_t value; - u_int8_t decimals; - - Decimal(u_int32_t value_=0, u_int8_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 u_int32_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 u_int32_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 u_int32_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(u_int64_t v) : ValueOps(v){} - TimeValue(){} - virtual u_int32_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(u_int32_t value_=0, u_int8_t decimals_=0) : - ValueOps(Decimal(value_, decimals_)){} - virtual u_int32_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 u_int32_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 u_int32_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; -}; - -}} // qpid::framing - -#endif diff --git a/cpp/common/framing/inc/amqp_framing.h b/cpp/common/framing/inc/amqp_framing.h deleted file mode 100644 index adb0045ee5..0000000000 --- a/cpp/common/framing/inc/amqp_framing.h +++ /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 "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_methods.h" -#include "InputHandler.h" -#include "OutputHandler.h" -#include "InitiationHandler.h" -#include "ProtocolInitiation.h" -#include "BasicHeaderProperties.h" diff --git a/cpp/common/framing/inc/amqp_types.h b/cpp/common/framing/inc/amqp_types.h deleted file mode 100644 index 6f8ef0862a..0000000000 --- a/cpp/common/framing/inc/amqp_types.h +++ /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 -#ifdef _WINDOWS -#include "windows.h" -typedef unsigned char u_int8_t; -typedef unsigned short u_int16_t; -typedef unsigned int u_int32_t; -typedef unsigned __int64 u_int64_t; -#endif -#ifndef _WINDOWS -#include "sys/types.h" -#endif - -#ifndef AMQP_TYPES_H -#define AMQP_TYPES_H - - -typedef std::string string; - -#endif diff --git a/cpp/common/framing/src/AMQBody.cpp b/cpp/common/framing/src/AMQBody.cpp deleted file mode 100644 index 08f0b1d7ca..0000000000 --- a/cpp/common/framing/src/AMQBody.cpp +++ /dev/null @@ -1,33 +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 "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() {} - -void qpid::framing::AMQBody::print(std::ostream& out) const { - out << "unknown body"; -} diff --git a/cpp/common/framing/src/AMQContentBody.cpp b/cpp/common/framing/src/AMQContentBody.cpp deleted file mode 100644 index 1be8867d53..0000000000 --- a/cpp/common/framing/src/AMQContentBody.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 "AMQContentBody.h" -#include - -qpid::framing::AMQContentBody::AMQContentBody(){ -} - -qpid::framing::AMQContentBody::AMQContentBody(const string& _data) : data(_data){ -} - -u_int32_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, u_int32_t _size){ - buffer.getRawData(data, _size); -} - -void qpid::framing::AMQContentBody::print(std::ostream& out) const -{ - out << "content (" << size() << " bytes)"; -} diff --git a/cpp/common/framing/src/AMQFrame.cpp b/cpp/common/framing/src/AMQFrame.cpp deleted file mode 100644 index 487ab1a443..0000000000 --- a/cpp/common/framing/src/AMQFrame.cpp +++ /dev/null @@ -1,115 +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 "QpidError.h" - -using namespace qpid::framing; - -AMQFrame::AMQFrame(){} - -AMQFrame::AMQFrame(u_int16_t _channel, AMQBody* _body) : channel(_channel), body(_body){} - -AMQFrame::AMQFrame(u_int16_t _channel, AMQBody::shared_ptr& _body) : channel(_channel), body(_body){} - -AMQFrame::~AMQFrame(){ -} - -u_int16_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); -} - -AMQBody::shared_ptr createMethodBody(Buffer& buffer){ - u_int16_t classId = buffer.getShort(); - u_int16_t methodId = buffer.getShort(); - AMQBody::shared_ptr body(createAMQMethodBody(classId, methodId)); - return body; -} - -u_int32_t AMQFrame::size() const{ - if(!body.get()) THROW_QPID_ERROR(INTERNAL_ERROR, "Attempt to get size of frame with no body set!"); - 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(); - u_int32_t bufSize = decodeHead(buffer); - - if(buffer.available() < bufSize + 1){ - buffer.restore(); - return false; - } - decodeBody(buffer, bufSize); - u_int8_t end = buffer.getOctet(); - if(end != 0xCE) THROW_QPID_ERROR(FRAMING_ERROR, "Frame end not found"); - return true; -} - -u_int32_t AMQFrame::decodeHead(Buffer& buffer){ - type = buffer.getOctet(); - channel = buffer.getShort(); - return buffer.getLong(); -} - -void AMQFrame::decodeBody(Buffer& buffer, uint32_t bufSize) -{ - switch(type) - { - case METHOD_BODY: - body = createMethodBody(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: - string msg("Unknown body type: "); - msg += type; - THROW_QPID_ERROR(FRAMING_ERROR, msg); - } - body->decode(buffer, bufSize); -} - -std::ostream& qpid::framing::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; -} - diff --git a/cpp/common/framing/src/AMQHeaderBody.cpp b/cpp/common/framing/src/AMQHeaderBody.cpp deleted file mode 100644 index dce5f1fd54..0000000000 --- a/cpp/common/framing/src/AMQHeaderBody.cpp +++ /dev/null @@ -1,73 +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 "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; -} - -u_int32_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, u_int32_t bufSize){ - u_int16_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, content_size=" << getContentSize() - << " (" << size() << " bytes)" << ", headers=" ; - // TODO aconway 2006-09-26: Hack to see headers. - // Should write proper op << for BasicHeaderProperties. - // - const BasicHeaderProperties* props = - dynamic_cast(getProperties()); - // TODO aconway 2006-09-26: Lose the static cast, fix BasicHeaderProperties - if (props) out << const_cast(props)->getHeaders(); -} diff --git a/cpp/common/framing/src/AMQHeartbeatBody.cpp b/cpp/common/framing/src/AMQHeartbeatBody.cpp deleted file mode 100644 index 15cbfeda48..0000000000 --- a/cpp/common/framing/src/AMQHeartbeatBody.cpp +++ /dev/null @@ -1,26 +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 "AMQHeartbeatBody.h" -#include - -qpid::framing::AMQHeartbeatBody::~AMQHeartbeatBody() {} - -void qpid::framing::AMQHeartbeatBody::print(std::ostream& out) const { - out << "heartbeat"; -} diff --git a/cpp/common/framing/src/AMQMethodBody.cpp b/cpp/common/framing/src/AMQMethodBody.cpp deleted file mode 100644 index 7455050377..0000000000 --- a/cpp/common/framing/src/AMQMethodBody.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 "AMQMethodBody.h" -#include "QpidError.h" - -void qpid::framing::AMQMethodBody::encode(Buffer& buffer) const{ - buffer.putShort(amqpClassId()); - buffer.putShort(amqpMethodId()); - encodeContent(buffer); -} - -void qpid::framing::AMQMethodBody::decode(Buffer& buffer, u_int32_t /*size*/){ - decodeContent(buffer); -} - -bool qpid::framing::AMQMethodBody::match(AMQMethodBody* other) const{ - return other != 0 && other->amqpClassId() == amqpClassId() && other->amqpMethodId() == amqpMethodId(); -} - -void qpid::framing::AMQMethodBody::invoke(AMQP_ServerOperations& /*target*/, u_int16_t /*channel*/){ - THROW_QPID_ERROR(PROTOCOL_ERROR, "Method not supported by AMQP Server."); -} - - -std::ostream& qpid::framing::operator<<(std::ostream& out, const AMQMethodBody& m){ - m.print(out); - return out; -} diff --git a/cpp/common/framing/src/BasicHeaderProperties.cpp b/cpp/common/framing/src/BasicHeaderProperties.cpp deleted file mode 100644 index c9153665d5..0000000000 --- a/cpp/common/framing/src/BasicHeaderProperties.cpp +++ /dev/null @@ -1,100 +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 "BasicHeaderProperties.h" - -//TODO: This could be easily generated from the spec - -qpid::framing::BasicHeaderProperties::BasicHeaderProperties() : deliveryMode(0), priority(0), timestamp(0){} -qpid::framing::BasicHeaderProperties::~BasicHeaderProperties(){} - -u_int32_t qpid::framing::BasicHeaderProperties::size() const{ - u_int32_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{ - u_int16_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, u_int32_t /*size*/){ - u_int16_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 = 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); -} - -u_int16_t qpid::framing::BasicHeaderProperties::getFlags() const{ - u_int16_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/cpp/common/framing/src/BodyHandler.cpp b/cpp/common/framing/src/BodyHandler.cpp deleted file mode 100644 index b428c62637..0000000000 --- a/cpp/common/framing/src/BodyHandler.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "memory.h" -#include "BodyHandler.h" - -using namespace qpid::framing; -using namespace std::tr1; - -BodyHandler::~BodyHandler() {} - -void BodyHandler::handleBody(AMQBody::shared_ptr& body){ - - switch(body->type()) - { - - case METHOD_BODY: - handleMethod(dynamic_pointer_cast(body)); - break; - - case HEADER_BODY: - handleHeader(dynamic_pointer_cast(body)); - break; - - case CONTENT_BODY: - handleContent(dynamic_pointer_cast(body)); - break; - - case HEARTBEAT_BODY: - handleHeartbeat(dynamic_pointer_cast(body)); - break; - - default: - throw UnknownBodyType(body->type()); - } - -} diff --git a/cpp/common/framing/src/Buffer.cpp b/cpp/common/framing/src/Buffer.cpp deleted file mode 100644 index 87aa1df7e9..0000000000 --- a/cpp/common/framing/src/Buffer.cpp +++ /dev/null @@ -1,168 +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 "Buffer.h" -#include "FieldTable.h" - -qpid::framing::Buffer::Buffer(u_int32_t _size) : size(_size), position(0), limit(_size){ - data = new char[size]; -} - -qpid::framing::Buffer::~Buffer(){ - 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(){ - u_int32_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; -} - -u_int32_t qpid::framing::Buffer::available(){ - return limit - position; -} - -char* qpid::framing::Buffer::start(){ - return data + position; -} - -void qpid::framing::Buffer::move(u_int32_t bytes){ - position += bytes; -} - -void qpid::framing::Buffer::putOctet(u_int8_t i){ - data[position++] = i; -} - -void qpid::framing::Buffer::putShort(u_int16_t i){ - u_int16_t b = i; - data[position++] = (u_int8_t) (0xFF & (b >> 8)); - data[position++] = (u_int8_t) (0xFF & b); -} - -void qpid::framing::Buffer::putLong(u_int32_t i){ - u_int32_t b = i; - data[position++] = (u_int8_t) (0xFF & (b >> 24)); - data[position++] = (u_int8_t) (0xFF & (b >> 16)); - data[position++] = (u_int8_t) (0xFF & (b >> 8)); - data[position++] = (u_int8_t) (0xFF & b); -} - -void qpid::framing::Buffer::putLongLong(u_int64_t i){ - u_int32_t hi = i >> 32; - u_int32_t lo = i; - putLong(hi); - putLong(lo); -} - -u_int8_t qpid::framing::Buffer::getOctet(){ - return (u_int8_t) data[position++]; -} - -u_int16_t qpid::framing::Buffer::getShort(){ - u_int16_t hi = (unsigned char) data[position++]; - hi = hi << 8; - hi |= (unsigned char) data[position++]; - return hi; -} - -u_int32_t qpid::framing::Buffer::getLong(){ - u_int32_t a = (unsigned char) data[position++]; - u_int32_t b = (unsigned char) data[position++]; - u_int32_t c = (unsigned char) data[position++]; - u_int32_t d = (unsigned char) data[position++]; - a = a << 24; - a |= b << 16; - a |= c << 8; - a |= d; - return a; -} - -u_int64_t qpid::framing::Buffer::getLongLong(){ - u_int64_t hi = getLong(); - u_int64_t lo = getLong(); - hi = hi << 32; - return hi | lo; -} - - -void qpid::framing::Buffer::putShortString(const string& s){ - u_int8_t len = s.length(); - putOctet(len); - s.copy(data + position, len); - position += len; -} - -void qpid::framing::Buffer::putLongString(const string& s){ - u_int32_t len = s.length(); - putLong(len); - s.copy(data + position, len); - position += len; -} - -void qpid::framing::Buffer::getShortString(string& s){ - u_int8_t len = getOctet(); - s.assign(data + position, len); - position += len; -} - -void qpid::framing::Buffer::getLongString(string& s){ - u_int32_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::putRawData(const string& s){ - u_int32_t len = s.length(); - s.copy(data + position, len); - position += len; -} - -void qpid::framing::Buffer::getRawData(string& s, u_int32_t len){ - s.assign(data + position, len); - position += len; -} diff --git a/cpp/common/framing/src/FieldTable.cpp b/cpp/common/framing/src/FieldTable.cpp deleted file mode 100644 index 088c8fb500..0000000000 --- a/cpp/common/framing/src/FieldTable.cpp +++ /dev/null @@ -1,147 +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 "FieldTable.h" -#include "QpidError.h" -#include "Buffer.h" -#include "Value.h" -#include - -namespace qpid { -namespace framing { - -FieldTable::~FieldTable() {} - -u_int32_t FieldTable::size() const { - u_int32_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 << "field_table{"; - 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, u_int64_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 <> u_int64_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); -} - -u_int64_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){ - u_int32_t len = buffer.getLong(); - u_int32_t available = buffer.available(); - if (available < len) - THROW_QPID_ERROR(FRAMING_ERROR, "Not enough data for field table."); - u_int32_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/cpp/common/framing/src/InitiationHandler.cpp b/cpp/common/framing/src/InitiationHandler.cpp deleted file mode 100644 index 9c18facf44..0000000000 --- a/cpp/common/framing/src/InitiationHandler.cpp +++ /dev/null @@ -1,21 +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 "InitiationHandler.h" - -qpid::framing::InitiationHandler::~InitiationHandler() {} diff --git a/cpp/common/framing/src/InputHandler.cpp b/cpp/common/framing/src/InputHandler.cpp deleted file mode 100644 index 7116caa24a..0000000000 --- a/cpp/common/framing/src/InputHandler.cpp +++ /dev/null @@ -1,21 +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 "InputHandler.h" - -qpid::framing::InputHandler::~InputHandler() {} diff --git a/cpp/common/framing/src/OutputHandler.cpp b/cpp/common/framing/src/OutputHandler.cpp deleted file mode 100644 index 8d99b4ef92..0000000000 --- a/cpp/common/framing/src/OutputHandler.cpp +++ /dev/null @@ -1,21 +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 "OutputHandler.h" - -qpid::framing::OutputHandler::~OutputHandler() {} diff --git a/cpp/common/framing/src/ProtocolInitiation.cpp b/cpp/common/framing/src/ProtocolInitiation.cpp deleted file mode 100644 index 6806d73b55..0000000000 --- a/cpp/common/framing/src/ProtocolInitiation.cpp +++ /dev/null @@ -1,53 +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 "ProtocolInitiation.h" - -qpid::framing::ProtocolInitiation::ProtocolInitiation(){} - -qpid::framing::ProtocolInitiation::ProtocolInitiation(u_int8_t _major, u_int8_t _minor) : pmajor(_major), pminor(_minor){} - -qpid::framing::ProtocolInitiation::~ProtocolInitiation(){} - -void qpid::framing::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(pmajor); - buffer.putOctet(pminor); -} - -bool qpid::framing::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 - pmajor = buffer.getOctet(); - pminor = 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 diff --git a/cpp/common/framing/src/Value.cpp b/cpp/common/framing/src/Value.cpp deleted file mode 100644 index 1c210fdb12..0000000000 --- a/cpp/common/framing/src/Value.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "Value.h" -#include "Buffer.h" -#include "FieldTable.h" -#include "QpidError.h" - -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((u_int32_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; - u_int8_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; - default: - THROW_QPID_ERROR(FRAMING_ERROR, "Unknown field table value type"); - } - 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/cpp/common/framing/test/BodyHandlerTest.cpp b/cpp/common/framing/test/BodyHandlerTest.cpp deleted file mode 100644 index 1cad6afe02..0000000000 --- a/cpp/common/framing/test/BodyHandlerTest.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include "amqp_framing.h" -#include "qpid_test_plugin.h" -using namespace qpid::framing; - -class BodyHandlerTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(BodyHandlerTest); - CPPUNIT_TEST(testMethod); - CPPUNIT_TEST(testHeader); - CPPUNIT_TEST(testContent); - CPPUNIT_TEST(testHeartbeat); - CPPUNIT_TEST_SUITE_END(); -private: - - class TestBodyHandler : public BodyHandler{ - AMQMethodBody* const method; - AMQHeaderBody* const header; - AMQContentBody* const content; - AMQHeartbeatBody* const heartbeat; - - public: - - TestBodyHandler(AMQMethodBody* _method) : method(_method), header(0), content(0), heartbeat(0){} - TestBodyHandler(AMQHeaderBody* _header) : method(0), header(_header), content(0), heartbeat(0){} - TestBodyHandler(AMQContentBody* _content) : method(0), header(0), content(_content), heartbeat(0){} - TestBodyHandler(AMQHeartbeatBody* _heartbeat) : method(0), header(0), content(0), heartbeat(_heartbeat){} - - virtual void handleMethod(AMQMethodBody::shared_ptr body){ - CPPUNIT_ASSERT(method); - CPPUNIT_ASSERT_EQUAL(method, body.get()); - } - virtual void handleHeader(AMQHeaderBody::shared_ptr body){ - CPPUNIT_ASSERT(header); - CPPUNIT_ASSERT_EQUAL(header, body.get()); - } - virtual void handleContent(AMQContentBody::shared_ptr body){ - CPPUNIT_ASSERT(content); - CPPUNIT_ASSERT_EQUAL(content, body.get()); - } - virtual void handleHeartbeat(AMQHeartbeatBody::shared_ptr body){ - CPPUNIT_ASSERT(heartbeat); - CPPUNIT_ASSERT_EQUAL(heartbeat, body.get()); - } - }; - -public: - - void testMethod() - { - AMQMethodBody* method = new QueueDeclareBody(); - AMQFrame frame(0, method); - TestBodyHandler handler(method); - handler.handleBody(frame.getBody()); - } - - void testHeader() - { - AMQHeaderBody* header = new AMQHeaderBody(); - AMQFrame frame(0, header); - TestBodyHandler handler(header); - handler.handleBody(frame.getBody()); - } - - void testContent() - { - AMQContentBody* content = new AMQContentBody(); - AMQFrame frame(0, content); - TestBodyHandler handler(content); - handler.handleBody(frame.getBody()); - } - - void testHeartbeat() - { - AMQHeartbeatBody* heartbeat = new AMQHeartbeatBody(); - AMQFrame frame(0, heartbeat); - TestBodyHandler handler(heartbeat); - handler.handleBody(frame.getBody()); - } -}; - - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(BodyHandlerTest); - diff --git a/cpp/common/framing/test/Makefile b/cpp/common/framing/test/Makefile deleted file mode 100644 index 487b8d537b..0000000000 --- a/cpp/common/framing/test/Makefile +++ /dev/null @@ -1,21 +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. -# - -QPID_HOME = ../../../.. -LDLIBS=-lapr-1 -lcppunit $(COMMON_LIB) -INCLUDES=$(TEST_INCLUDES) -I ../generated -include ${QPID_HOME}/cpp/test_plugins.mk - diff --git a/cpp/common/framing/test/field_table_test.cpp b/cpp/common/framing/test/field_table_test.cpp deleted file mode 100644 index 535f7f4a08..0000000000 --- a/cpp/common/framing/test/field_table_test.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 "amqp_framing.h" -#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/cpp/common/framing/test/framing_test.cpp b/cpp/common/framing/test/framing_test.cpp deleted file mode 100644 index 8c69f8718a..0000000000 --- a/cpp/common/framing/test/framing_test.cpp +++ /dev/null @@ -1,144 +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_framing.h" -#include "ConnectionRedirectBody.h" -#include -#include -#include -#include - -using namespace qpid::framing; - -// TODO aconway 2006-09-12: Why do we need explicit qpid::framing:: below? - -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(ConnectionRedirectBody); - CPPUNIT_TEST(BasicConsumeOkBody); - CPPUNIT_TEST_SUITE_END(); - - private: - Buffer buffer; - - public: - - FramingTest() : buffer(100) {} - - void testBasicQosBody() - { - BasicQosBody in(0xCAFEBABE, 0xABBA, true); - in.encodeContent(buffer); - buffer.flip(); - BasicQosBody out; - out.decodeContent(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - void testConnectionSecureBody() - { - std::string s = "security credential"; - ConnectionSecureBody in(s); - in.encodeContent(buffer); - buffer.flip(); - ConnectionSecureBody out; - out.decodeContent(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - void testConnectionRedirectBody() - { - std::string a = "hostA"; - std::string b = "hostB"; - qpid::framing::ConnectionRedirectBody in(a, b); - in.encodeContent(buffer); - buffer.flip(); - qpid::framing::ConnectionRedirectBody out; - out.decodeContent(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - void testAccessRequestBody() - { - std::string s = "text"; - AccessRequestBody in(s, true, false, true, false, true); - in.encodeContent(buffer); - buffer.flip(); - AccessRequestBody out; - out.decodeContent(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - void testBasicConsumeBody() - { - std::string q = "queue"; - std::string t = "tag"; - BasicConsumeBody in(0, q, t, false, true, false, false); - in.encodeContent(buffer); - buffer.flip(); - BasicConsumeBody out; - out.decodeContent(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - - void ConnectionRedirectBody() - { - std::string a = "hostA"; - std::string b = "hostB"; - AMQFrame in(999, new qpid::framing::ConnectionRedirectBody(a, b)); - in.encode(buffer); - buffer.flip(); - AMQFrame out; - out.decode(buffer); - CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); - } - - void BasicConsumeOkBody() - { - std::string s = "hostA"; - AMQFrame in(999, new qpid::framing::BasicConsumeOkBody(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)); - } - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(FramingTest); - - - diff --git a/cpp/common/framing/test/header_test.cpp b/cpp/common/framing/test/header_test.cpp deleted file mode 100644 index f98dd5d108..0000000000 --- a/cpp/common/framing/test/header_test.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 -#include "amqp_framing.h" -#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: - - // TODO aconway 2006-09-12: Need more detailed tests, - // need tests to assert something! - // - 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"); - u_int8_t deliveryMode(2); - u_int8_t priority(3); - string correlationId("abc"); - string replyTo("no-address"); - string expiration("why is this a string?"); - string messageId("xyz"); - u_int64_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"); - u_int8_t deliveryMode(5); - u_int8_t priority(6); - string expiration("Z"); - u_int64_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/cpp/common/io/Makefile b/cpp/common/io/Makefile deleted file mode 100644 index 617b91448a..0000000000 --- a/cpp/common/io/Makefile +++ /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. - # - -QPID_HOME = ../../.. -include ${QPID_HOME}/cpp/options.mk -SOURCES := $(wildcard src/*.cpp) -OBJECTS := $(subst .cpp,.o,$(SOURCES)) -DEPS := $(subst .cpp,.d,$(SOURCES)) - -.PHONY: all clean - -all: ${OBJECTS} - --include $(DEPS) - -clean : - -@rm -f ${OBJECTS} src/*.d - diff --git a/cpp/common/io/inc/APRConnector.h b/cpp/common/io/inc/APRConnector.h deleted file mode 100644 index c6ed887f78..0000000000 --- a/cpp/common/io/inc/APRConnector.h +++ /dev/null @@ -1,95 +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. - * - */ -#ifndef _APRConnector_ -#define _APRConnector_ - -#include "apr_network_io.h" -#include "apr_time.h" - -#include "InputHandler.h" -#include "OutputHandler.h" -#include "InitiationHandler.h" -#include "ProtocolInitiation.h" -#include "ShutdownHandler.h" -#include "Thread.h" -#include "ThreadFactory.h" -#include "Connector.h" -#include "APRMonitor.h" - -namespace qpid { -namespace io { - - class APRConnector : public virtual qpid::framing::OutputHandler, - public virtual Connector, - private virtual qpid::concurrent::Runnable - { - const bool debug; - const int receive_buffer_size; - const int send_buffer_size; - - bool closed; - - apr_time_t lastIn; - apr_time_t lastOut; - apr_interval_time_t timeout; - u_int32_t idleIn; - u_int32_t idleOut; - - TimeoutHandler* timeoutHandler; - ShutdownHandler* shutdownHandler; - qpid::framing::InputHandler* input; - qpid::framing::InitiationHandler* initialiser; - qpid::framing::OutputHandler* output; - - qpid::framing::Buffer inbuf; - qpid::framing::Buffer outbuf; - - qpid::concurrent::APRMonitor* writeLock; - qpid::concurrent::ThreadFactory* threadFactory; - qpid::concurrent::Thread* receiver; - - apr_pool_t* pool; - apr_socket_t* socket; - - void checkIdle(apr_status_t status); - void writeBlock(qpid::framing::AMQDataBlock* data); - void writeToSocket(char* data, size_t available); - void setSocketTimeout(); - - void run(); - - public: - APRConnector(bool debug = false, u_int32_t buffer_size = 1024); - virtual ~APRConnector(); - virtual void connect(const std::string& host, int port); - virtual void init(qpid::framing::ProtocolInitiation* header); - virtual void close(); - virtual void setInputHandler(qpid::framing::InputHandler* handler); - virtual void setTimeoutHandler(TimeoutHandler* handler); - virtual void setShutdownHandler(ShutdownHandler* handler); - virtual qpid::framing::OutputHandler* getOutputHandler(); - virtual void send(qpid::framing::AMQFrame* frame); - virtual void setReadTimeout(u_int16_t timeout); - virtual void setWriteTimeout(u_int16_t timeout); - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/APRSocket.h b/cpp/common/io/inc/APRSocket.h deleted file mode 100644 index 610cf0e175..0000000000 --- a/cpp/common/io/inc/APRSocket.h +++ /dev/null @@ -1,45 +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. - * - */ -#ifndef _APRSocket_ -#define _APRSocket_ - -#include "apr_network_io.h" -#include "Buffer.h" - -namespace qpid { -namespace io { - - 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(); - u_int8_t read(); - ~APRSocket(); - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/Acceptor.h b/cpp/common/io/inc/Acceptor.h deleted file mode 100644 index d7313b84db..0000000000 --- a/cpp/common/io/inc/Acceptor.h +++ /dev/null @@ -1,53 +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. - * - */ -#ifndef _Acceptor_ -#define _Acceptor_ - -#include "SessionHandlerFactory.h" - -namespace qpid { -namespace io { - - class Acceptor - { - public: - /** - * Bind to port. - * @param port Port to bind to, 0 to bind to dynamically chosen port. - * @return The local bound port. - */ - virtual int16_t bind(int16_t port) = 0; - - /** - * Run the acceptor. - */ - virtual void run(SessionHandlerFactory* factory) = 0; - - /** - * Shut down the acceptor. - */ - virtual void shutdown() = 0; - - virtual ~Acceptor(); - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/BlockingAPRAcceptor.h b/cpp/common/io/inc/BlockingAPRAcceptor.h deleted file mode 100644 index bd069ed8db..0000000000 --- a/cpp/common/io/inc/BlockingAPRAcceptor.h +++ /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. - * - */ -#ifndef _BlockingAPRAcceptor_ -#define _BlockingAPRAcceptor_ - -#include -#include "apr_network_io.h" -#include "apr_poll.h" -#include "apr_time.h" - -#include "Acceptor.h" -#include "APRMonitor.h" -#include "BlockingAPRSessionContext.h" -#include "Runnable.h" -#include "SessionContext.h" -#include "SessionHandlerFactory.h" -#include "Thread.h" -#include "ThreadFactory.h" -#include "ThreadPool.h" - -namespace qpid { -namespace io { - - class BlockingAPRAcceptor : public virtual Acceptor - { - typedef std::vector::iterator iterator; - - const bool debug; - apr_pool_t* apr_pool; - qpid::concurrent::ThreadFactory* threadFactory; - std::vector sessions; - apr_socket_t* socket; - const int connectionBacklog; - volatile bool running; - - public: - BlockingAPRAcceptor(bool debug = false, int connectionBacklog = 10); - virtual int16_t bind(int16_t port); - virtual int16_t getPort() const; - virtual void run(SessionHandlerFactory* factory); - virtual void shutdown(); - virtual ~BlockingAPRAcceptor(); - void closed(BlockingAPRSessionContext* session); - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/BlockingAPRSessionContext.h b/cpp/common/io/inc/BlockingAPRSessionContext.h deleted file mode 100644 index 038ebd6662..0000000000 --- a/cpp/common/io/inc/BlockingAPRSessionContext.h +++ /dev/null @@ -1,94 +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. - * - */ -#ifndef _BlockingAPRSessionContext_ -#define _BlockingAPRSessionContext_ - -#include -#include - -#include "apr_network_io.h" -#include "apr_time.h" - -#include "AMQFrame.h" -#include "APRMonitor.h" -#include "Buffer.h" -#include "Runnable.h" -#include "SessionContext.h" -#include "SessionHandler.h" -#include "SessionHandlerFactory.h" -#include "ShutdownHandler.h" -#include "Thread.h" -#include "ThreadFactory.h" - -namespace qpid { -namespace io { - - class BlockingAPRAcceptor; - - class BlockingAPRSessionContext : public virtual SessionContext - { - class Reader : public virtual qpid::concurrent::Runnable{ - BlockingAPRSessionContext* parent; - public: - inline Reader(BlockingAPRSessionContext* p) : parent(p){} - inline virtual void run(){ parent->read(); } - inline virtual ~Reader(){} - }; - - class Writer : public virtual qpid::concurrent::Runnable{ - BlockingAPRSessionContext* parent; - public: - inline Writer(BlockingAPRSessionContext* p) : parent(p){} - inline virtual void run(){ parent->write(); } - inline virtual ~Writer(){} - }; - - apr_socket_t* socket; - const bool debug; - SessionHandler* handler; - BlockingAPRAcceptor* acceptor; - std::queue outframes; - qpid::framing::Buffer inbuf; - qpid::framing::Buffer outbuf; - qpid::concurrent::APRMonitor outlock; - Reader* reader; - Writer* writer; - qpid::concurrent::Thread* rThread; - qpid::concurrent::Thread* wThread; - - volatile bool closed; - - void read(); - void write(); - public: - BlockingAPRSessionContext(apr_socket_t* socket, - qpid::concurrent::ThreadFactory* factory, - BlockingAPRAcceptor* acceptor, - bool debug = false); - ~BlockingAPRSessionContext(); - virtual void send(qpid::framing::AMQFrame* frame); - virtual void close(); - void shutdown(); - void init(SessionHandler* handler); - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/Connector.h b/cpp/common/io/inc/Connector.h deleted file mode 100644 index 52684329f1..0000000000 --- a/cpp/common/io/inc/Connector.h +++ /dev/null @@ -1,56 +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. - * - */ -#ifndef _Connector_ -#define _Connector_ - -#include "InputHandler.h" -#include "OutputHandler.h" -#include "InitiationHandler.h" -#include "ProtocolInitiation.h" -#include "ShutdownHandler.h" -#include "TimeoutHandler.h" - -namespace qpid { -namespace io { - - class Connector - { - public: - virtual void connect(const std::string& host, int port) = 0; - virtual void init(qpid::framing::ProtocolInitiation* header) = 0; - virtual void close() = 0; - virtual void setInputHandler(qpid::framing::InputHandler* handler) = 0; - virtual void setTimeoutHandler(TimeoutHandler* handler) = 0; - virtual void setShutdownHandler(ShutdownHandler* handler) = 0; - virtual qpid::framing::OutputHandler* getOutputHandler() = 0; - /** - * Set the timeout for reads, in secs. - */ - virtual void setReadTimeout(u_int16_t timeout) = 0; - /** - * Set the timeout for writes, in secs. - */ - virtual void setWriteTimeout(u_int16_t timeout) = 0; - virtual ~Connector(){} - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/ConnectorImpl.h b/cpp/common/io/inc/ConnectorImpl.h deleted file mode 100644 index 1abb72f32a..0000000000 --- a/cpp/common/io/inc/ConnectorImpl.h +++ /dev/null @@ -1,53 +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. - * - */ -#ifndef _APRConnectorImpl_ -#define _APRConnectorImpl_ - -#ifdef _USE_APR_IO_ -#include "APRConnector.h" -#else -#include "LConnector.h" -#endif - -namespace qpid { -namespace io { - -#ifdef _USE_APR_IO_ - class ConnectorImpl : public virtual APRConnector - { - - public: - ConnectorImpl(bool _debug = false, u_int32_t buffer_size = 1024):APRConnector(_debug,buffer_size){}; - virtual ~ConnectorImpl(){}; - }; -#else - class ConnectorImpl : public virtual LConnector - { - - public: - ConnectorImpl(bool _debug = false, u_int32_t buffer_size = 1024):LConnector(_debug, buffer_size){}; - virtual ~ConnectorImpl(){}; - }; - -#endif - -} -} - - -#endif diff --git a/cpp/common/io/inc/LConnector.h b/cpp/common/io/inc/LConnector.h deleted file mode 100644 index 59d95a6b57..0000000000 --- a/cpp/common/io/inc/LConnector.h +++ /dev/null @@ -1,48 +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. - * - */ -#ifndef _LConnector_ -#define _LConnector_ - - -#include "InputHandler.h" -#include "OutputHandler.h" -#include "InitiationHandler.h" -#include "ProtocolInitiation.h" -#include "Thread.h" -#include "ThreadFactory.h" -#include "Connector.h" - -namespace qpid { -namespace io { - - class LConnector : public virtual qpid::framing::OutputHandler, - public virtual Connector, - private virtual qpid::concurrent::Runnable - { - - public: - LConnector(bool debug = false, u_int32_t buffer_size = 1024){}; - virtual ~LConnector(){}; - - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/LFAcceptor.h b/cpp/common/io/inc/LFAcceptor.h deleted file mode 100644 index 9a40eed222..0000000000 --- a/cpp/common/io/inc/LFAcceptor.h +++ /dev/null @@ -1,74 +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. - * - */ -#ifndef _LFAcceptor_ -#define _LFAcceptor_ - -#include -#include "apr_network_io.h" -#include "apr_poll.h" -#include "apr_time.h" - -#include "Acceptor.h" -#include "APRMonitor.h" -#include "APRThreadFactory.h" -#include "APRThreadPool.h" -#include "LFProcessor.h" -#include "LFSessionContext.h" -#include "Runnable.h" -#include "SessionContext.h" -#include "SessionHandlerFactory.h" -#include "Thread.h" - -namespace qpid { -namespace io { - - class LFAcceptor : public virtual Acceptor - { - class APRPool{ - public: - apr_pool_t* pool; - APRPool(); - ~APRPool(); - }; - - APRPool aprPool; - LFProcessor processor; - apr_socket_t* socket; - const int max_connections_per_processor; - const bool debug; - const int connectionBacklog; - - volatile bool running; - - public: - LFAcceptor(bool debug = false, - int connectionBacklog = 10, - int worker_threads = 5, - int max_connections_per_processor = 500); - virtual int16_t bind(int16_t port); - virtual int16_t getPort() const; - virtual void run(SessionHandlerFactory* factory); - virtual void shutdown(); - virtual ~LFAcceptor(); - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/LFProcessor.h b/cpp/common/io/inc/LFProcessor.h deleted file mode 100644 index 25a3c8626c..0000000000 --- a/cpp/common/io/inc/LFProcessor.h +++ /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. - * - */ -#ifndef _LFProcessor_ -#define _LFProcessor_ - -#include "apr_poll.h" -#include -#include -#include "APRMonitor.h" -#include "APRThreadFactory.h" -#include "Runnable.h" - -namespace qpid { -namespace io { - - 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::concurrent::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::concurrent::Thread** const workers; - qpid::concurrent::APRMonitor leadLock; - qpid::concurrent::APRMonitor countLock; - qpid::concurrent::APRThreadFactory factory; - 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/cpp/common/io/inc/LFSessionContext.h b/cpp/common/io/inc/LFSessionContext.h deleted file mode 100644 index d07c8910d3..0000000000 --- a/cpp/common/io/inc/LFSessionContext.h +++ /dev/null @@ -1,88 +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. - * - */ -#ifndef _LFSessionContext_ -#define _LFSessionContext_ - -#include - -#include "apr_network_io.h" -#include "apr_poll.h" -#include "apr_time.h" - -#include "AMQFrame.h" -#include "APRMonitor.h" -#include "APRSocket.h" -#include "Buffer.h" -#include "LFProcessor.h" -#include "SessionContext.h" -#include "SessionHandler.h" - -namespace qpid { -namespace io { - - - class LFSessionContext : public virtual SessionContext - { - const bool debug; - APRSocket socket; - bool initiated; - - qpid::framing::Buffer in; - qpid::framing::Buffer out; - - SessionHandler* handler; - LFProcessor* const processor; - - apr_pollfd_t fd; - - std::queue framesToWrite; - qpid::concurrent::APRMonitor writeLock; - - bool processing; - bool closing; - - //these are just for debug, as a crude way of detecting concurrent access - volatile unsigned int reading; - volatile unsigned int writing; - - static qpid::concurrent::APRMonitor 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); - ~LFSessionContext(); - virtual void send(qpid::framing::AMQFrame* frame); - virtual void close(); - void read(); - void write(); - void init(SessionHandler* 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/cpp/common/io/inc/SessionContext.h b/cpp/common/io/inc/SessionContext.h deleted file mode 100644 index f223a70daa..0000000000 --- a/cpp/common/io/inc/SessionContext.h +++ /dev/null @@ -1,37 +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. - * - */ -#ifndef _SessionContext_ -#define _SessionContext_ - -#include "OutputHandler.h" - -namespace qpid { -namespace io { - - class SessionContext : public virtual qpid::framing::OutputHandler - { - public: - virtual void close() = 0; - virtual ~SessionContext(){} - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/SessionHandler.h b/cpp/common/io/inc/SessionHandler.h deleted file mode 100644 index 21a992ab65..0000000000 --- a/cpp/common/io/inc/SessionHandler.h +++ /dev/null @@ -1,42 +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. - * - */ -#ifndef _SessionHandler_ -#define _SessionHandler_ - -#include "InputHandler.h" -#include "InitiationHandler.h" -#include "ProtocolInitiation.h" -#include "TimeoutHandler.h" - -namespace qpid { -namespace io { - - class SessionHandler : public virtual qpid::framing::InitiationHandler, - public virtual qpid::framing::InputHandler, - public virtual TimeoutHandler - { - public: - virtual void closed() = 0; - virtual ~SessionHandler(){} - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/SessionHandlerFactory.h b/cpp/common/io/inc/SessionHandlerFactory.h deleted file mode 100644 index 67d968b72e..0000000000 --- a/cpp/common/io/inc/SessionHandlerFactory.h +++ /dev/null @@ -1,38 +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. - * - */ -#ifndef _SessionHandlerFactory_ -#define _SessionHandlerFactory_ - -#include "SessionContext.h" -#include "SessionHandler.h" - -namespace qpid { -namespace io { - - class SessionHandlerFactory - { - public: - virtual SessionHandler* create(SessionContext* ctxt) = 0; - virtual ~SessionHandlerFactory(){} - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/SessionManager.h b/cpp/common/io/inc/SessionManager.h deleted file mode 100644 index 30c5208532..0000000000 --- a/cpp/common/io/inc/SessionManager.h +++ /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. - * - */ -#ifndef _SessionManager_ -#define _SessionManager_ - -#include "SessionContext.h" -#include "SessionHandler.h" - -namespace qpid { -namespace io { - - class SessionManager - { - public: - virtual SessionHandler* init(SessionContext* ctxt) = 0; - virtual void close(SessionContext* ctxt) = 0; - virtual void updateInterest(SessionContext* ctxt, bool read, bool write) = 0; - virtual ~SessionManager(){} - }; - -} -} - - -#endif diff --git a/cpp/common/io/inc/ShutdownHandler.h b/cpp/common/io/inc/ShutdownHandler.h deleted file mode 100644 index 186d9eeca4..0000000000 --- a/cpp/common/io/inc/ShutdownHandler.h +++ /dev/null @@ -1,34 +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. - * - */ -#ifndef _ShutdownHandler_ -#define _ShutdownHandler_ - -namespace qpid { -namespace io { - - class ShutdownHandler - { - public: - virtual void shutdown() = 0; - virtual ~ShutdownHandler(){} - }; - -} -} - -#endif diff --git a/cpp/common/io/inc/TimeoutHandler.h b/cpp/common/io/inc/TimeoutHandler.h deleted file mode 100644 index c92220fd6e..0000000000 --- a/cpp/common/io/inc/TimeoutHandler.h +++ /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. - * - */ -#ifndef _TimeoutHandler_ -#define _TimeoutHandler_ - -namespace qpid { -namespace io { - - class TimeoutHandler - { - public: - virtual void idleOut() = 0; - virtual void idleIn() = 0; - virtual ~TimeoutHandler(){} - }; - -} -} - - -#endif diff --git a/cpp/common/io/src/APRConnector.cpp b/cpp/common/io/src/APRConnector.cpp deleted file mode 100644 index 5f3bfd6957..0000000000 --- a/cpp/common/io/src/APRConnector.cpp +++ /dev/null @@ -1,201 +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 "APRBase.h" -#include "APRConnector.h" -#include "APRThreadFactory.h" -#include "QpidError.h" - -using namespace qpid::io; -using namespace qpid::concurrent; -using namespace qpid::framing; -using qpid::QpidError; - -APRConnector::APRConnector(bool _debug, u_int32_t buffer_size) : - debug(_debug), - receive_buffer_size(buffer_size), - send_buffer_size(buffer_size), - closed(true), - lastIn(0), lastOut(0), - timeout(0), - idleIn(0), idleOut(0), - timeoutHandler(0), - shutdownHandler(0), - inbuf(receive_buffer_size), - outbuf(send_buffer_size){ - - APRBase::increment(); - - CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); - CHECK_APR_SUCCESS(apr_socket_create(&socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, pool)); - - threadFactory = new APRThreadFactory(); - writeLock = new APRMonitor(); -} - -APRConnector::~APRConnector(){ - delete receiver; - delete writeLock; - delete threadFactory; - apr_pool_destroy(pool); - - APRBase::decrement(); -} - -void APRConnector::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, pool)); - CHECK_APR_SUCCESS(apr_socket_connect(socket, address)); - closed = false; - - receiver = threadFactory->create(this); - receiver->start(); -} - -void APRConnector::init(ProtocolInitiation* header){ - writeBlock(header); - delete header; -} - -void APRConnector::close(){ - closed = true; - CHECK_APR_SUCCESS(apr_socket_close(socket)); - receiver->join(); -} - -void APRConnector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void APRConnector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -OutputHandler* APRConnector::getOutputHandler(){ - return this; -} - -void APRConnector::send(AMQFrame* frame){ - writeBlock(frame); - if(debug) std::cout << "SENT: " << *frame << std::endl; - delete frame; -} - -void APRConnector::writeBlock(AMQDataBlock* data){ - writeLock->acquire(); - data->encode(outbuf); - - //transfer data to wire - outbuf.flip(); - writeToSocket(outbuf.start(), outbuf.available()); - outbuf.clear(); - writeLock->release(); -} - -void APRConnector::writeToSocket(char* data, size_t available){ - apr_size_t bytes(available); - apr_size_t written(0); - while(written < available && !closed){ - apr_status_t status = apr_socket_send(socket, data + written, &bytes); - if(status == APR_TIMEUP){ - std::cout << "Write request timed out." << std::endl; - } - if(bytes == 0){ - std::cout << "Write request wrote 0 bytes." << std::endl; - } - lastOut = apr_time_as_msec(apr_time_now()); - written += bytes; - bytes = available - written; - } -} - -void APRConnector::checkIdle(apr_status_t status){ - if(timeoutHandler){ - apr_time_t now = apr_time_as_msec(apr_time_now()); - if(APR_STATUS_IS_TIMEUP(status)){ - if(idleIn && (now - lastIn > idleIn)){ - timeoutHandler->idleIn(); - } - }else if(APR_STATUS_IS_EOF(status)){ - closed = true; - CHECK_APR_SUCCESS(apr_socket_close(socket)); - if(shutdownHandler) shutdownHandler->shutdown(); - }else{ - lastIn = now; - } - if(idleOut && (now - lastOut > idleOut)){ - timeoutHandler->idleOut(); - } - } -} - -void APRConnector::setReadTimeout(u_int16_t t){ - idleIn = t * 1000;//t is in secs - if(idleIn && (!timeout || idleIn < timeout)){ - timeout = idleIn; - setSocketTimeout(); - } - -} - -void APRConnector::setWriteTimeout(u_int16_t t){ - idleOut = t * 1000;//t is in secs - if(idleOut && (!timeout || idleOut < timeout)){ - timeout = idleOut; - setSocketTimeout(); - } -} - -void APRConnector::setSocketTimeout(){ - //interval is in microseconds, timeout in milliseconds - //want the interval to be a bit shorter than the timeout, hence multiply - //by 800 rather than 1000. - apr_interval_time_t interval(timeout * 800); - apr_socket_timeout_set(socket, interval); -} - -void APRConnector::setTimeoutHandler(TimeoutHandler* handler){ - timeoutHandler = handler; -} - -void APRConnector::run(){ - try{ - while(!closed){ - apr_size_t bytes(inbuf.available()); - if(bytes < 1){ - THROW_QPID_ERROR(INTERNAL_ERROR, "Frame exceeds buffer size."); - } - checkIdle(apr_socket_recv(socket, inbuf.start(), &bytes)); - - if(bytes > 0){ - inbuf.move(bytes); - inbuf.flip();//position = 0, limit = total data read - - AMQFrame frame; - 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(QpidError error){ - std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; - } -} diff --git a/cpp/common/io/src/APRSocket.cpp b/cpp/common/io/src/APRSocket.cpp deleted file mode 100644 index 1ef7e270a3..0000000000 --- a/cpp/common/io/src/APRSocket.cpp +++ /dev/null @@ -1,78 +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 "APRBase.h" -#include "APRSocket.h" -#include -#include - -using namespace qpid::io; -using namespace qpid::framing; -using namespace qpid::concurrent; - -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_status_t s = apr_socket_send(socket, buffer.start(), &bytes); - // TODO aconway 2006-10-05: better error handling - assert(s == 0); - 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(){ - return !closed; -} - -u_int8_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/cpp/common/io/src/Acceptor.cpp b/cpp/common/io/src/Acceptor.cpp deleted file mode 100644 index d1825c78fa..0000000000 --- a/cpp/common/io/src/Acceptor.cpp +++ /dev/null @@ -1,21 +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 "Acceptor.h" - -qpid::io::Acceptor::~Acceptor() {} diff --git a/cpp/common/io/src/BlockingAPRAcceptor.cpp b/cpp/common/io/src/BlockingAPRAcceptor.cpp deleted file mode 100644 index 4c55b9e2c8..0000000000 --- a/cpp/common/io/src/BlockingAPRAcceptor.cpp +++ /dev/null @@ -1,101 +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 "BlockingAPRAcceptor.h" -#include "APRBase.h" -#include "APRThreadFactory.h" - -using namespace qpid::concurrent; -using namespace qpid::framing; -using namespace qpid::io; - -BlockingAPRAcceptor::BlockingAPRAcceptor(bool _debug, int c) : - debug(_debug), - threadFactory(new APRThreadFactory()), - connectionBacklog(c) -{ - APRBase::increment(); - CHECK_APR_SUCCESS(apr_pool_create(&apr_pool, NULL)); -} - -int16_t BlockingAPRAcceptor::bind(int16_t _port){ - apr_sockaddr_t* address; - CHECK_APR_SUCCESS(apr_sockaddr_info_get(&address, APR_ANYADDR, APR_UNSPEC, _port, APR_IPV4_ADDR_OK, apr_pool)); - CHECK_APR_SUCCESS(apr_socket_create(&socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, apr_pool)); - CHECK_APR_SUCCESS(apr_socket_bind(socket, address)); - CHECK_APR_SUCCESS(apr_socket_listen(socket, connectionBacklog)); - return getPort(); -} - -int16_t BlockingAPRAcceptor::getPort() const { - apr_sockaddr_t* address; - CHECK_APR_SUCCESS(apr_socket_addr_get(&address, APR_LOCAL, socket)); - return address->port; -} - -void BlockingAPRAcceptor::run(SessionHandlerFactory* factory) -{ - running = true; - std::cout << "Listening on port " << getPort() << "..." << std::endl; - while(running){ - apr_socket_t* client; - apr_status_t status = apr_socket_accept(&client, socket, apr_pool); - if(status == APR_SUCCESS){ - //configure socket: - CHECK_APR_SUCCESS(apr_socket_timeout_set(client, 1000000/* i.e. 1 sec*/)); - 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)); - - BlockingAPRSessionContext* session = new BlockingAPRSessionContext(client, threadFactory, this, debug); - session->init(factory->create(session)); - sessions.push_back(session); - }else{ - running = false; - if(status != APR_EINTR){ - std::cout << "ERROR: " << get_desc(status) << std::endl; - } - } - } - shutdown(); -} - -void BlockingAPRAcceptor::shutdown() -{ - // TODO aconway 2006-10-12: Not thread safe. - if (running) - { - running = false; - apr_socket_close(socket); // Don't check, exception safety. - for(iterator i = sessions.begin(); i < sessions.end(); i++){ - (*i)->shutdown(); - } - } -} - -BlockingAPRAcceptor::~BlockingAPRAcceptor(){ - delete threadFactory; - apr_pool_destroy(apr_pool); - APRBase::decrement(); -} - - -void BlockingAPRAcceptor::closed(BlockingAPRSessionContext* session){ - sessions.erase(find(sessions.begin(), sessions.end(), session)); -} - diff --git a/cpp/common/io/src/BlockingAPRSessionContext.cpp b/cpp/common/io/src/BlockingAPRSessionContext.cpp deleted file mode 100644 index 6d1dc3470c..0000000000 --- a/cpp/common/io/src/BlockingAPRSessionContext.cpp +++ /dev/null @@ -1,178 +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 "BlockingAPRSessionContext.h" -#include "BlockingAPRAcceptor.h" -#include "APRBase.h" -#include "QpidError.h" - -using namespace qpid::concurrent; -using namespace qpid::framing; -using namespace qpid::io; - - -BlockingAPRSessionContext::BlockingAPRSessionContext(apr_socket_t* _socket, - ThreadFactory* factory, - BlockingAPRAcceptor* _acceptor, - bool _debug) - : socket(_socket), - debug(_debug), - handler(0), - acceptor(_acceptor), - inbuf(65536), - outbuf(65536), - closed(false){ - - reader = new Reader(this); - writer = new Writer(this); - - rThread = factory->create(reader); - wThread = factory->create(writer); -} - -BlockingAPRSessionContext::~BlockingAPRSessionContext(){ - delete reader; - delete writer; - - delete rThread; - delete wThread; - - delete handler; -} - -void BlockingAPRSessionContext::read(){ - try{ - bool initiated(false); - while(!closed){ - apr_size_t bytes(inbuf.available()); - if(bytes < 1){ - THROW_QPID_ERROR(INTERNAL_ERROR, "Frame exceeds buffer size."); - } - apr_status_t s = apr_socket_recv(socket, inbuf.start(), &bytes); - if(APR_STATUS_IS_TIMEUP(s)){ - //timed out, check closed on loop - }else if(APR_STATUS_IS_EOF(s) || bytes == 0){ - closed = true; - }else{ - inbuf.move(bytes); - inbuf.flip(); - - if(!initiated){ - ProtocolInitiation* protocolInit = new ProtocolInitiation(); - if(protocolInit->decode(inbuf)){ - handler->initiated(protocolInit); - if(debug) std::cout << "RECV: [" << &socket << "]: Initialised " << std::endl; - initiated = true; - } - }else{ - AMQFrame frame; - while(frame.decode(inbuf)){ - if(debug) std::cout << "RECV: [" << &socket << "]:" << frame << std::endl; - handler->received(&frame); - } - } - //need to compact buffer to preserve any 'extra' data - inbuf.compact(); - } - } - - //close socket - }catch(qpid::QpidError error){ - std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; - } -} - -void BlockingAPRSessionContext::write(){ - while(!closed){ - //get next frame - outlock.acquire(); - while(outframes.empty() && !closed){ - outlock.wait(); - } - if(!closed){ - AMQFrame* frame = outframes.front(); - outframes.pop(); - outlock.release(); - - //encode - frame->encode(outbuf); - if(debug) std::cout << "SENT [" << &socket << "]:" << *frame << std::endl; - delete frame; - outbuf.flip(); - - //write from outbuf to socket - char* data = outbuf.start(); - const int available = outbuf.available(); - int written = 0; - apr_size_t bytes = available; - while(available > written){ - apr_status_t s = apr_socket_send(socket, data + written, &bytes); - assert(s == 0); // TODO aconway 2006-10-05: Error Handling. - written += bytes; - bytes = available - written; - } - outbuf.clear(); - }else{ - outlock.release(); - } - } -} - -void BlockingAPRSessionContext::send(AMQFrame* frame){ - if(!closed){ - outlock.acquire(); - bool was_empty(outframes.empty()); - outframes.push(frame); - if(was_empty){ - outlock.notify(); - } - outlock.release(); - }else{ - std::cout << "WARNING: Session closed[" << &socket << "], dropping frame. " << &frame << std::endl; - } -} - -void BlockingAPRSessionContext::init(SessionHandler* _handler){ - handler = _handler; - rThread->start(); - wThread->start(); -} - -void BlockingAPRSessionContext::close(){ - closed = true; - wThread->join(); - CHECK_APR_SUCCESS(apr_socket_close(socket)); - if(debug) std::cout << "RECV: [" << &socket << "]: Closed " << std::endl; - handler->closed(); - acceptor->closed(this); - delete this; -} - -void BlockingAPRSessionContext::shutdown(){ - closed = true; - outlock.acquire(); - outlock.notify(); - outlock.release(); - - wThread->join(); - CHECK_APR_SUCCESS(apr_socket_close(socket)); - rThread->join(); - handler->closed(); - delete this; -} diff --git a/cpp/common/io/src/LFAcceptor.cpp b/cpp/common/io/src/LFAcceptor.cpp deleted file mode 100644 index 86f382afac..0000000000 --- a/cpp/common/io/src/LFAcceptor.cpp +++ /dev/null @@ -1,94 +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 "LFAcceptor.h" -#include "APRBase.h" - -using namespace qpid::concurrent; -using namespace qpid::io; - -LFAcceptor::LFAcceptor(bool _debug, int c, int worker_threads, int m) : - processor(aprPool.pool, worker_threads, 1000, 5000000), - max_connections_per_processor(m), - debug(_debug), - connectionBacklog(c) -{ } - - -int16_t LFAcceptor::bind(int16_t _port){ - apr_sockaddr_t* address; - CHECK_APR_SUCCESS(apr_sockaddr_info_get(&address, APR_ANYADDR, APR_UNSPEC, _port, APR_IPV4_ADDR_OK, aprPool.pool)); - CHECK_APR_SUCCESS(apr_socket_create(&socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, aprPool.pool)); - 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, connectionBacklog)); - return getPort(); -} - -int16_t LFAcceptor::getPort() const { - apr_sockaddr_t* address; - CHECK_APR_SUCCESS(apr_socket_addr_get(&address, APR_LOCAL, socket)); - return address->port; -} - -void LFAcceptor::run(SessionHandlerFactory* 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.pool); - 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.pool, client, &processor, debug); - session->init(factory->create(session)); - }else{ - running = false; - if(status != APR_EINTR){ - std::cout << "ERROR: " << get_desc(status) << std::endl; - } - } - } - shutdown(); -} - -void LFAcceptor::shutdown() { - // TODO aconway 2006-10-12: Cleanup, this is not thread safe. - if (running) { - running = false; - processor.stop(); - CHECK_APR_SUCCESS(apr_socket_close(socket)); - } -} - - -LFAcceptor::~LFAcceptor(){} - -LFAcceptor::APRPool::APRPool(){ - APRBase::increment(); - CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); -} - -LFAcceptor::APRPool::~APRPool(){ - apr_pool_destroy(pool); - APRBase::decrement(); -} diff --git a/cpp/common/io/src/LFProcessor.cpp b/cpp/common/io/src/LFProcessor.cpp deleted file mode 100644 index 65d7451767..0000000000 --- a/cpp/common/io/src/LFProcessor.cpp +++ /dev/null @@ -1,193 +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 "LFProcessor.h" -#include "APRBase.h" -#include "LFSessionContext.h" -#include "QpidError.h" -#include - -using namespace qpid::io; -using namespace qpid::concurrent; -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)); - //create & start the required number of threads - for(int i = 0; i < workerCount; i++){ - workers[i] = factory.create(this); - } -} - - -LFProcessor::~LFProcessor(){ - if (!stopped) stop(); - for(int i = 0; i < workerCount; i++){ - delete workers[i]; - } - delete[] workers; - CHECK_APR_SUCCESS(apr_pollset_destroy(pollset)); -} - -void LFProcessor::start(){ - for(int i = 0; i < workerCount; i++){ - workers[i]->start(); - } -} - -void LFProcessor::add(const apr_pollfd_t* const fd){ - CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd)); - countLock.acquire(); - sessions.push_back(reinterpret_cast(fd->client_data)); - count++; - countLock.release(); -} - -void LFProcessor::remove(const apr_pollfd_t* const fd){ - CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd)); - countLock.acquire(); - sessions.erase(find(sessions.begin(), sessions.end(), reinterpret_cast(fd->client_data))); - count--; - countLock.release(); -} - -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(){ - Locker locker(countLock); - return count == size; -} - -bool LFProcessor::empty(){ - Locker locker(countLock); - return count == 0; -} - -void LFProcessor::poll(){ - apr_status_t status; - do{ - current = 0; - if(!stopped){ - status = apr_pollset_poll(pollset, timeout, &signalledCount, &signalledFDs); - } - }while(status != APR_SUCCESS && !stopped); -} - -void LFProcessor::run(){ - try{ - while(!stopped){ - leadLock.acquire(); - waitToLead(); - if(!stopped){ - const apr_pollfd_t* evt = getNextEvent(); - if(evt){ - LFSessionContext* session = reinterpret_cast(evt->client_data); - session->startProcessing(); - - relinquishLead(); - leadLock.release(); - - //process event: - if(evt->rtnevents & APR_POLLIN) session->read(); - if(evt->rtnevents & APR_POLLOUT) session->write(); - - if(session->isClosed()){ - session->handleClose(); - countLock.acquire(); - sessions.erase(find(sessions.begin(), sessions.end(), session)); - count--; - countLock.release(); - }else{ - session->stopProcessing(); - } - - }else{ - leadLock.release(); - } - }else{ - leadLock.release(); - } - } - }catch(QpidError error){ - std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << 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; - leadLock.acquire(); - leadLock.notifyAll(); - leadLock.release(); - - for(int i = 0; i < workerCount; i++){ - workers[i]->join(); - } - - for(iterator i = sessions.begin(); i < sessions.end(); i++){ - (*i)->shutdown(); - } -} - diff --git a/cpp/common/io/src/LFSessionContext.cpp b/cpp/common/io/src/LFSessionContext.cpp deleted file mode 100644 index 7b8208f704..0000000000 --- a/cpp/common/io/src/LFSessionContext.cpp +++ /dev/null @@ -1,189 +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 "LFSessionContext.h" -#include "APRBase.h" -#include "QpidError.h" -#include - -using namespace qpid::concurrent; -using namespace qpid::io; -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(32768), - out(32768), - processor(_processor), - processing(false), - closing(false), - reading(0), - writing(0) -{ - - 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(){ - assert(!reading); // No concurrent read. - reading = APRThread::currentThread(); - - socket.read(in); - in.flip(); - if(initiated){ - AMQFrame frame; - while(frame.decode(in)){ - if(debug) log("RECV", &frame); - handler->received(&frame); - } - }else{ - ProtocolInitiation protocolInit; - if(protocolInit.decode(in)){ - handler->initiated(&protocolInit); - initiated = true; - if(debug) std::cout << "INIT [" << &socket << "]" << std::endl; - } - } - in.compact(); - - reading = 0; -} - -void LFSessionContext::write(){ - assert(!writing); // No concurrent writes. - writing = APRThread::currentThread(); - - bool done = isClosed(); - while(!done){ - if(out.available() > 0){ - socket.write(out); - if(out.available() > 0){ - writing = 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? - writeLock.acquire(); - 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; - - writing = 0; - - if(closing){ - socket.close(); - } - } - writeLock.release(); - } - } -} - -void LFSessionContext::send(AMQFrame* frame){ - writeLock.acquire(); - if(!closing){ - framesToWrite.push(frame); - if(!(fd.reqevents & APR_POLLOUT)){ - fd.reqevents |= APR_POLLOUT; - if(!processing){ - processor->update(&fd); - } - } - } - writeLock.release(); -} - -void LFSessionContext::startProcessing(){ - writeLock.acquire(); - processing = true; - processor->deactivate(&fd); - writeLock.release(); -} - -void LFSessionContext::stopProcessing(){ - writeLock.acquire(); - processor->reactivate(&fd); - processing = false; - writeLock.release(); -} - -void LFSessionContext::close(){ - closing = true; - writeLock.acquire(); - if(!processing){ - //allow pending frames to be written to socket - fd.reqevents = APR_POLLOUT; - processor->update(&fd); - } - writeLock.release(); -} - -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(SessionHandler* _handler){ - handler = _handler; - processor->add(&fd); -} - -void LFSessionContext::log(const std::string& desc, AMQFrame* const frame){ - logLock.acquire(); - std::cout << desc << " [" << &socket << "]: " << *frame << std::endl; - logLock.release(); -} - -APRMonitor LFSessionContext::logLock; diff --git a/cpp/common/utils/inc/memory.h b/cpp/common/utils/inc/memory.h deleted file mode 100644 index 2d65877adb..0000000000 --- a/cpp/common/utils/inc/memory.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __UTIL_MEMORY__ -#define __UTIL_MEMORY__ - -#if __GNUC__ < 4 - #include "boost/shared_ptr.hpp" - namespace std { - namespace tr1 { - using boost::shared_ptr; - using boost::dynamic_pointer_cast; - using boost::static_pointer_cast; - } - } -#else - #include -#endif -#endif - diff --git a/cpp/common/utils/src/Makefile b/cpp/common/utils/src/Makefile deleted file mode 100644 index b0ab76973c..0000000000 --- a/cpp/common/utils/src/Makefile +++ /dev/null @@ -1,37 +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. - # - -QPID_HOME = ../../../.. -include $(QPID_HOME)/cpp/options.mk -INCLUDES=$(TEST_INCLUDES) - -##### Targets ##### -# Add additional source files to SOURCE LIST to include them in the build. -COMMON_SOURCE_LIST = logger.cpp - -COMMON_OBJ_LIST = $(COMMON_SOURCE_LIST:.cpp=.o) -LOGGER_TEST_EXE = logger_test - - -.PHONY: all clean - -all: $(LOGGER_TEST_EXE) - -$(LOGGER_TEST_EXE) : $(COMMON_OBJ_LIST) $(LOGGER_TEST_EXE).o - $(CXX) -o $@ $^ -l apr-1 -L /usr/local/apr/lib/ - -clean: - -@rm -f $(LOGGER_TEST_EXE) $(LOGGER_TEST_EXE).o $(COMMON_OBJ_LIST) test_log.txt *~ ../inc/*~ diff --git a/cpp/etc/stylesheets/amqp_client.xsl b/cpp/etc/stylesheets/amqp_client.xsl new file mode 100644 index 0000000000..4673d44316 --- /dev/null +++ b/cpp/etc/stylesheets/amqp_client.xsl @@ -0,0 +1,155 @@ + + + + + + + + + + + +#ifndef _AMQP_ServerProxy_ +#define _AMQP_ServerProxy_ + +#include "AMQP_ServerOperations.h" +#include "qpid/framing/FieldTable.h" +#include "qpid/framing/OutputHandler.h" + +namespace qpid { +namespace framing { + +class AMQP_ServerProxy : virtual public AMQP_ServerOperations +{ + OutputHandler* out; + + public: + AMQP_ServerProxy(OutputHandler* _out); + virtual ~AMQP_ServerProxy() {} + + + + /** ===== Class: ===== + + */ + + class : virtual public AMQP_ServerOperations::Handler + { + OutputHandler* out; + + public: + /* Constructors and destructors */ + (OutputHandler* _out); + virtual ~(); + + /* Protocol methods */ + + + + + /** ----- Method: . ----- + + */ + + + /** + Rule "": + */ + + virtual void + ( u_int16_t channel, + + + + + , + + + + ); + + + }; /* class */ + + }; /* class AMQP_ServerProxy */ + +} /* namespace framing */ +} /* namespace qpid */ + +#endif + + + + + + + + + + + +#include "AMQP_ServerProxy.h" + +namespace qpid { +namespace framing { + +AMQP_ServerProxy::AMQP_ServerProxy(OutputHandler* _out) : + out(_out) +{ +} + + + /* ++++++++++ Class: ++++++++++ */ + +AMQP_ServerProxy::::(OutputHandler* _out) : + out(_out) +{ +} + +AMQP_ServerProxy::::~() {} + + + void AMQP_ServerProxy:::: + ( u_int16_t channel + , + + + + + , + + + + ) +{ + out->send( new AMQFrame( channel, + new ( + + + + , + + + ) ) ); +} + + + + + +} /* namespace framing */ +} /* namespace qpid */ + + + + diff --git a/cpp/etc/stylesheets/amqp_client_handler_impl.xsl b/cpp/etc/stylesheets/amqp_client_handler_impl.xsl new file mode 100644 index 0000000000..cc636ea846 --- /dev/null +++ b/cpp/etc/stylesheets/amqp_client_handler_impl.xsl @@ -0,0 +1,187 @@ + + + + + + + + + + + +#ifndef _AMQP_ClientHandlerImpl_ +#define _AMQP_ClientHandlerImpl_ + +#include "AMQP_ClientOperations.h" +#include "qpid/framing/FieldTable.h" + +namespace qpid { +namespace framing { + +class AMQP_ClientHandlerImpl : virtual public AMQP_ClientOperations +{ + + + + + AMQP_ClientOperations::* + Ptr; + + + public: + AMQP_ClientHandlerImpl(); + virtual ~AMQP_ClientHandlerImpl(); + + + + + inline AMQP_ClientOperations:: + * get + () { return Ptr; } + + + + + + + + + + /** + ===== Class: Impl ===== + + */ + + + + class + Impl : virtual public AMQP_ClientOperations:: + { + public: + /* Constructors and destructors */ + Impl(); + virtual ~Impl(); + + /* Protocol methods */ + + + + + + + + + /** + ----- Method: + Impl. ----- + + */ + + + /** + Rule "": + + */ + + + + virtual void + ( u_int16_t channel + + + + , + + + + + , + + + + ); + + + }; /* class Impl */ + + }; /* AMQP_ClientHandlerImpl */ + +} /* namespace framing */ +} /* namespace qpid */ + +#endif + + + + + + + + + +#include "AMQP_ClientHandlerImpl.h" + +namespace qpid { +namespace framing { + +AMQP_ClientHandlerImpl::AMQP_ClientHandlerImpl() : + + + + HandlerPtr( new HandlerImpl() ) + + , + + + +{ +} + +AMQP_ClientHandlerImpl::~AMQP_ClientHandlerImpl() +{ + + delete HandlerPtr; + } + + + + /* ===== Class: HandlerImpl ===== */ + AMQP_ClientHandlerImpl::HandlerImpl:: + HandlerImpl() { } + AMQP_ClientHandlerImpl::HandlerImpl::~ + HandlerImpl() { } + + + void AMQP_ClientHandlerImpl::HandlerImpl:: + ( u_int16_t /*channel*/ + + , + + + + + , + + + ) { } + + + + + +} /* namespace framing */ +} /* namespace qpid */ + + + + diff --git a/cpp/etc/stylesheets/amqp_client_operations.xsl b/cpp/etc/stylesheets/amqp_client_operations.xsl new file mode 100644 index 0000000000..ee87cac56a --- /dev/null +++ b/cpp/etc/stylesheets/amqp_client_operations.xsl @@ -0,0 +1,105 @@ + + + + + + + + + + + +#ifndef _AMQP_ClientOperations_ +#define _AMQP_ClientOperations_ + +#include "AMQP_Constants.h" +#include "qpid/framing/FieldTable.h" + +namespace qpid { +namespace framing { + +class AMQP_ClientOperations +{ + public: + AMQP_ClientOperations() {} + virtual ~AMQP_ClientOperations() {} + inline u_int16_t getAmqpMajor() { return (u_int16_t); } + inline u_int16_t getAmqpMinor() { return (u_int16_t); } + + + + + + + + /** ===== Class: ===== + + */ + + + + class + { + public: + /* Constructors and destructors */ + () {} + virtual ~() {} + + /* Protocol methods */ + + + + + + + + + /** ----- Method: . + ----- + + */ + + + /** + Rule "": + + */ + + + + virtual void + ( u_int16_t channel + + + + , + + + + + , + + + + ) = 0; + + + }; /* class */ + + }; /* class AMQP_ClientOperations */ + +} /* namespace framing */ +} /* namespace qpid */ + +#endif + + + + diff --git a/cpp/etc/stylesheets/amqp_consts.xsl b/cpp/etc/stylesheets/amqp_consts.xsl new file mode 100644 index 0000000000..783f9f5271 --- /dev/null +++ b/cpp/etc/stylesheets/amqp_consts.xsl @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#ifndef _AMQP_Constants_ +#define _AMQP_Constants_ + +#include "qpid/framing/amqp_types.h" + +namespace qpid { +namespace framing { + +/**** Constants ****/ + + + /* + + */ + + const u_int16_t ; + + + +} /* namespace framing */ +} /* namespace qpid */ + +#endif + + + + diff --git a/cpp/etc/stylesheets/amqp_server.xsl b/cpp/etc/stylesheets/amqp_server.xsl new file mode 100644 index 0000000000..ee50d7f331 --- /dev/null +++ b/cpp/etc/stylesheets/amqp_server.xsl @@ -0,0 +1,187 @@ + + + + + + + + + + +#ifndef _AMQP_ClientProxy_ +#define _AMQP_ClientProxy_ + +#include "AMQP_ClientOperations.h" +#include "qpid/framing/FieldTable.h" +#include "qpid/framing/OutputHandler.h" + +namespace qpid { +namespace framing { + +class AMQP_ClientProxy : virtual public AMQP_ClientOperations +{ + public: + + AMQP_ClientProxy(OutputHandler* _out); + virtual ~AMQP_ClientProxy() {}; + + + + + + /** ===== Class: ===== + + */ + + class : virtual public AMQP_ClientOperations::Handler + { + OutputHandler* out; + + public: + /* Constructors and destructors */ + (OutputHandler* _out); + virtual ~(); + + /* Protocol methods */ + + + + + /** ----- Method: . ----- + + */ + + + /** + Rule "": + */ + + virtual void + ( u_int16_t channel, + + + + + , + + + + ); + + + }; /* class */ + + + + + ; + + + private: + + OutputHandler* out; + + + + ; + + + + + }; /* class AMQP_ClientProxy */ + +} /* namespace framing */ +} /* namespace qpid */ + +#endif + + + + + + + + + + +#include "AMQP_ClientProxy.h" + +namespace qpid { +namespace framing { + +AMQP_ClientProxy::AMQP_ClientProxy(OutputHandler* _out) : + out(_out), + + + + , + + + +{ +} + + + + /* ++++++++++ Class: ++++++++++ */ + +AMQP_ClientProxy::::(OutputHandler* _out) : + out(_out) +{ +} + +AMQP_ClientProxy::::~() {} + + + void AMQP_ClientProxy:::: + ( u_int16_t channel + , + + + + + , + + + + ) +{ + out->send( new AMQFrame( channel, + new ( + + + + , + + + ) ) ); +} + + + + + + + { + ; + } + + + + +} /* namespace framing */ +} /* namespace qpid */ + + + + diff --git a/cpp/etc/stylesheets/amqp_server_handler_impl.xsl b/cpp/etc/stylesheets/amqp_server_handler_impl.xsl new file mode 100644 index 0000000000..c55e3f7cd1 --- /dev/null +++ b/cpp/etc/stylesheets/amqp_server_handler_impl.xsl @@ -0,0 +1,187 @@ + + + + + + + + + + + +#ifndef _AMQP_ServerHandlerImpl_ +#define _AMQP_ServerHandlerImpl_ + +#include "AMQP_ServerOperations.h" +#include "qpid/framing/FieldTable.h" + +namespace qpid { +namespace framing { + +class AMQP_ServerHandlerImpl : virtual public AMQP_ServerOperations +{ + + + + + AMQP_ServerOperations::* + Ptr; + + + public: + AMQP_ServerHandlerImpl(); + virtual ~AMQP_ServerHandlerImpl(); + + + + + virtual inline AMQP_ServerOperations:: + * get + () { return Ptr; } + + + + + + + + + + /** + ===== Class: Impl ===== + + */ + + + + class + Impl : virtual public AMQP_ServerOperations:: + { + public: + /* Constructors and destructors */ + Impl(); + virtual ~Impl(); + + /* Protocol methods */ + + + + + + + + + /** + ----- Method: + Impl. ----- + + */ + + + /** + Rule "": + + */ + + + + virtual void + ( u_int16_t channel + + + + , + + + + + , + + + + ); + + + }; /* class Impl */ + + }; /* AMQP_ServerHandlerImpl */ + +} /* namespace framing */ +} /* namespace qpid */ + +#endif + + + + + + + + + +#include "AMQP_ServerHandlerImpl.h" + +namespace qpid { +namespace framing { + +AMQP_ServerHandlerImpl::AMQP_ServerHandlerImpl() : + + + + HandlerPtr( new HandlerImpl() ) + + , + + + +{ +} + +AMQP_ServerHandlerImpl::~AMQP_ServerHandlerImpl() +{ + + delete HandlerPtr; + } + + + + /* ===== Class: HandlerImpl ===== */ + AMQP_ServerHandlerImpl::HandlerImpl:: + HandlerImpl() { } + AMQP_ServerHandlerImpl::HandlerImpl::~ + HandlerImpl() { } + + + void AMQP_ServerHandlerImpl::HandlerImpl:: + ( u_int16_t /*channel*/ + + , + + + + + , + + + ) { } + + + + + +} /* namespace framing */ +} /* namespace qpid */ + + + + diff --git a/cpp/etc/stylesheets/amqp_server_operations.xsl b/cpp/etc/stylesheets/amqp_server_operations.xsl new file mode 100644 index 0000000000..aad474295c --- /dev/null +++ b/cpp/etc/stylesheets/amqp_server_operations.xsl @@ -0,0 +1,113 @@ + + + + + + + + + + + +#ifndef _AMQP_ServerOperations_ +#define _AMQP_ServerOperations_ + +#include "AMQP_Constants.h" +#include "qpid/framing/FieldTable.h" + +namespace qpid { +namespace framing { + +class AMQP_ServerOperations +{ + public: + AMQP_ServerOperations() {} + virtual ~AMQP_ServerOperations() {} + inline u_int16_t getAmqpMajor() { return (u_int16_t); } + inline u_int16_t getAmqpMinor() { return (u_int16_t); } + + + + + + + + /** ===== Class: ===== + + */ + + + + class + { + public: + /* Constructors and destructors */ + () {} + virtual ~() {} + + /* Protocol methods */ + + + + + + + + + /** ----- Method: . + ----- + + */ + + + /** + Rule "": + + */ + + + + virtual void + ( u_int16_t channel + + + + , + + + + + , + + + + ) = 0; + + + }; /* class */ + + + + + virtual AMQP_ServerOperations:: + * get + () = 0; + + + }; /* class AMQP_ServerOperations */ + +} /* namespace framing */ +} /* namespace qpid */ + +#endif + + + + diff --git a/cpp/etc/stylesheets/code_gen.xsl b/cpp/etc/stylesheets/code_gen.xsl new file mode 100644 index 0000000000..5e9f4ef8f0 --- /dev/null +++ b/cpp/etc/stylesheets/code_gen.xsl @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp/etc/stylesheets/code_utils.xsl b/cpp/etc/stylesheets/code_utils.xsl new file mode 100644 index 0000000000..f4a0f6e5ce --- /dev/null +++ b/cpp/etc/stylesheets/code_utils.xsl @@ -0,0 +1,210 @@ + + + + + /** +* +* 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. +* +*/ + +/** +* +* NOTE: This file is generated directly from the AMQP XML specification. +* === DO NOT EDIT === +* +*/ + + + + + + + + + + + + + delete_ + return_ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + u_int8_t + u_int16_t + string + string + bool + u_int32_t + u_int64_t + u_int64_t + + FieldTable + + unknown_type /* WARNING: undefined type */ + + + + + + + + & + & + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp/etc/stylesheets/convert_0.81.xsl b/cpp/etc/stylesheets/convert_0.81.xsl new file mode 100644 index 0000000000..9924f165da --- /dev/null +++ b/cpp/etc/stylesheets/convert_0.81.xsl @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + + + + + + + + + ==================== + Constants + ==================== + + + + + + + + + + ==================== + Domains + ==================== + + + + + + + + + Elementary domains + + bit + bit + single bit + + + octet + octet + single octet + + + short + short + 16-bit integer + + + long + long + 32-bit integer + + + longlong + longlong + 64-bit integer + + + shortstr + shortstr + short string + + + longstr + longstr + long string + + + timestamp + timestamp + 64-bit timestamp + + + table + table + field table + + + + + + ==================== + Classes + ==================== + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +rule__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +doc_rule__ + + + + + + + + + + + +grammar + + + + + + + + + + + + diff --git a/cpp/etc/stylesheets/cpp.xsl b/cpp/etc/stylesheets/cpp.xsl new file mode 100644 index 0000000000..51facee294 --- /dev/null +++ b/cpp/etc/stylesheets/cpp.xsl @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + + +#include "qpid/framing/amqp_framing.h" + + + + + + + + + + + + +#include "qpid/framing/amqp_types.h" +#include "AMQP_ServerOperations.h" +#include "qpid/framing/AMQMethodBody.h" +#include "qpid/framing/Buffer.h" +#include "qpid/framing/FieldTable.h" + +#ifndef __ +#define __ + +namespace qpid { +namespace framing { + + + + +} +} + +#endif + + + + + + + + +/** + * This class is autogenerated, do not modify. [From ] + */ +class : virtual public AMQMethodBody +{ + + + + ; + + +public: + typedef std::tr1::shared_ptr<> shared_ptr; + + virtual ~() {} + + + inline ; } + + + + inline void print(std::ostream& out) const{ + out << "" + + << ", + ="<< + + + ; + } + + inline u_int16_t amqpClassId() const { + return ; + } + + inline u_int16_t amqpMethodId() const { + return ; + } + + inline u_int32_t bodySize() const { + + + return + + + + + + + ; + + return 0; + + } + + + inline void invoke(AMQP_ServerOperations& target, u_int16_t channel) { + + + ); + + + ; + + } + + + inline void encodeContent(Buffer& buffer) const + { + + u_int8_t flags = 0; + + ; + + + + + ; + + + buffer.putOctet(flags); + + + } + + inline void decodeContent(Buffer& buffer) + { + + + + u_int8_t flags = buffer.getOctet(); + ; + + + ; + + + + } + + + + inline () : + { + } + + + inline () + { + } +}; + + + + + +/** + * This file is autogenerated, do not modify. + */ + +#ifndef AMQ_METHODS_H +#define AMQ_METHODS_H + + +#include ".h" + + +namespace qpid { +namespace framing { + + +const ; + + +AMQMethodBody* createAMQMethodBody(u_int16_t classId, u_int16_t methodId); + +} +} + +#endif + + + + + +#include "amqp_methods.h" +#include "qpid/QpidError.h" + +namespace qpid { +namespace framing { +/** + * This method is autogenerated, do not modify. + */ +AMQMethodBody* createAMQMethodBody(u_int16_t classId, u_int16_t methodId){ + switch(classId * 1000 + methodId) + { + + case + + * 1000 + + + : return new + (); + + } + THROW_QPID_ERROR(FRAMING_ERROR, "Unknown method"); +} + +} +} + + + + + +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/FieldTable.h" + +#ifndef _AMQPServer_ +#define _AMQPServer_ + +namespace qpid { +namespace framing { + +class AMQPServer +{ + public: + + + class { + public: + + + virtual void (u_int16_t channel, ) = 0; + + + virtual void (u_int16_t channel) = 0; + + + virtual ~(){} + }; + + virtual () = 0; + + + virtual ~AMQPServer(){} +}; + +} +} + +#endif + + + +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/FieldTable.h" + +#ifndef _AMQPClient_ +#define _AMQPClient_ + +namespace qpid { +namespace framing { + +class AMQPClient +{ + public: + + + class { + public: + + + virtual void (u_int16_t channel, ) = 0; + + + virtual void (u_int16_t channel) = 0; + + + virtual ~(){} + }; + + virtual () = 0; + + + + virtual ~AMQPClient(){} +}; + +} +} + +#endif + + + + + diff --git a/cpp/etc/stylesheets/framing.xsl b/cpp/etc/stylesheets/framing.xsl new file mode 100644 index 0000000000..c63e719a77 --- /dev/null +++ b/cpp/etc/stylesheets/framing.xsl @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp/etc/stylesheets/prepare1.xsl b/cpp/etc/stylesheets/prepare1.xsl new file mode 100644 index 0000000000..2aeda89677 --- /dev/null +++ b/cpp/etc/stylesheets/prepare1.xsl @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + ( + major= + , minor= + ) + + + + + + + + + + + + + + + + + + + + + + + + Could not inherit from ; file not found. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp/etc/stylesheets/prepare2.xsl b/cpp/etc/stylesheets/prepare2.xsl new file mode 100644 index 0000000000..331319de57 --- /dev/null +++ b/cpp/etc/stylesheets/prepare2.xsl @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp/etc/stylesheets/prepare3.xsl b/cpp/etc/stylesheets/prepare3.xsl new file mode 100644 index 0000000000..27a4764e4f --- /dev/null +++ b/cpp/etc/stylesheets/prepare3.xsl @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp/etc/stylesheets/registry.xsl b/cpp/etc/stylesheets/registry.xsl new file mode 100644 index 0000000000..a818a0a871 --- /dev/null +++ b/cpp/etc/stylesheets/registry.xsl @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/cpp/etc/stylesheets/utils.xsl b/cpp/etc/stylesheets/utils.xsl new file mode 100644 index 0000000000..70743112a9 --- /dev/null +++ b/cpp/etc/stylesheets/utils.xsl @@ -0,0 +1,194 @@ + + + + + + + + + + u_int8_t + u_int16_t + string + string + bool + u_int32_t + u_int64_t + FieldTable + Object /*WARNING: undefined type*/ + + + + + + u_int8_t + u_int16_t + const string& + const string& + bool + u_int32_t + u_int64_t + FieldTable& + Object /*WARNING: undefined type*/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /* WARNING: COULD NOT DETERMINE FIELD SIZE */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /* WARNING: COULD NOT DETERMINE ENCODER */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /* WARNING: COULD NOT DETERMINE DECODER */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp/options.mk b/cpp/options.mk index 093017a1ed..d8214f36d5 100644 --- a/cpp/options.mk +++ b/cpp/options.mk @@ -14,25 +14,19 @@ # limitations under the License. # -# Directories -SPEC_DIR = ${QPID_HOME}/specs -QPID_CPP_HOME = ${QPID_HOME}/cpp -COMMON_HOME = ${QPID_CPP_HOME}/common -TOOLS_DIR = ${QPID_CPP_HOME}/tools -LIB_DIR = ${QPID_CPP_HOME}/lib -BIN_DIR = ${QPID_CPP_HOME}/bin -APR_HOME = /usr/local/apr -# Compile flags -DEBUG = -ggdb3 -O0 -OPTIMIZE = +## External dependencies: + +# Add location for headers and libraries of any external dependencies here +EXTRA_INCLUDES := -I/usr/local/apr/include/apr-1 +EXTRA_LIBDIRS := -L/usr/local/apr/lib + +## Compile flags + +DEBUG := -ggdb3 + # _USE_APR_IO_ set when APR IO build is desired. -DEFINES = -D _USE_APR_IO_ -APR_INCLUDES=-I ${APR_HOME}/include/apr-1/ -COMMON_INCLUDES = -I ${COMMON_HOME}/framing/inc -I ${COMMON_HOME}/framing/generated -I ${COMMON_HOME}/concurrent/inc -I ${COMMON_HOME}/io/inc -I ${COMMON_HOME}/error/inc -I $(COMMON_HOME)/utils/inc ${APR_INCLUDES} -SRC_INCLUDES = $(COMMON_INCLUDES) -I inc -TEST_INCLUDES = $(COMMON_INCLUDES) -I ../inc -I $(QPID_CPP_HOME)/test/include -INCLUDES=$(SRC_INCLUDES) # Default to src +DEFINES := -D _USE_APR_IO_ # Warnings: Enable as many as possible, keep the code clean. Please # do not disable warnings or remove -Werror without discussing on @@ -41,21 +35,9 @@ INCLUDES=$(SRC_INCLUDES) # Default to src # The following warnings deliberately omitted, they warn on valid code. # -Wno-unreachable-code -Wpadded # -WARN = -Werror -pedantic -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wno-long-long -Wvolatile-register-var -Winvalid-pch -Winline - -CXXFLAGS = $(DEBUG) $(OPTIMIZE) $(DEFINES) $(WARN) -MMD -fpic $(INCLUDES) - -# General link flags -LDFLAGS= -L $(LIB_DIR) -L ${APR_HOME}/lib $(RPATH) - -# TODO aconway 2006-09-12: This is not something we want in a release -# but it's useful for development. -RPATH= -Wl,-rpath,$(CURDIR)/$(LIB_DIR) - -# Libraries and executables. Use absolute paths so exes can find -# libs wherever they are run. TODO: Proper library management. -BROKER=$(BIN_DIR)/qpidd -BROKER_LIB=$(CURDIR)/$(LIB_DIR)/libqpid_broker.so.1.0 -COMMON_LIB=$(CURDIR)/$(LIB_DIR)/libqpid_common.so.1.0 -CLIENT_LIB=$(CURDIR)/$(LIB_DIR)/libqpid_client.so.1.0 - +WARN := -Werror -pedantic -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wno-long-long -Wvolatile-register-var -Winvalid-pch -Winline +INCLUDES := -Isrc -Igen $(EXTRA_INCLUDES) +CXXFLAGS := $(DEBUG) $(DEFINES) $(WARN) -MMD -fpic $(INCLUDES) +## Link flags +# Allow exes to find libs without env changes. Remove for release builds. +LDFLAGS := -Llib $(EXTRA_LIBDIRS) diff --git a/cpp/qpidd/Makefile b/cpp/qpidd/Makefile deleted file mode 100644 index f2dca4df3b..0000000000 --- a/cpp/qpidd/Makefile +++ /dev/null @@ -1,42 +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. -# - -# -# Build qpidd broker daemon executable. -# - -QPID_HOME = ../.. -include $(QPID_HOME)/cpp/options.mk -TARGET=$(BROKER) -SOURCES= $(wildcard src/*.cpp) -OBJECTS= $(subst .cpp,.o,$(SOURCES)) - - -.PHONY: all clean test - -all: $(TARGET) - -test: - @$(MAKE) -C test all - -clean: - -@rm -f $(OBJECTS) src/*.d $(TARGET) - @$(MAKE) -C test clean - -$(TARGET): $(OBJECTS) - $(CXX) -o $@ $(OBJECTS) $(LDFLAGS) -lapr-1 $(COMMON_LIB) $(BROKER_LIB) - --include $(SOURCES:.cpp=.d) diff --git a/cpp/qpidd/src/qpidd.cpp b/cpp/qpidd/src/qpidd.cpp deleted file mode 100644 index 51be80d51d..0000000000 --- a/cpp/qpidd/src/qpidd.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 "../../broker/inc/../../broker/inc/Broker.h" -#include "../../broker/inc/Broker.h" -#include "../../broker/inc/Configuration.h" -#include "../../broker/inc/SessionHandlerFactoryImpl.h" -#include "Acceptor.h" -#include "QpidError.h" -#include "apr_signal.h" -#include -#include - -using namespace qpid::broker; -using namespace qpid::io; - -void handle_signal(int /*signal*/){ - std::cout << "Shutting down..." << std::endl; -} - -int main(int argc, char** argv) -{ - Configuration config; - try { - config.parse(argc, argv); - if(config.isHelp()){ - config.usage(); - }else{ - apr_signal(SIGINT, handle_signal); - Broker::shared_ptr broker = Broker::create(config); - broker->run(); - } - return 0; - } catch(std::exception e) { - std::cout << e.what() << std::endl; - } - return 1; -} diff --git a/cpp/src/memory.h b/cpp/src/memory.h new file mode 100644 index 0000000000..2d65877adb --- /dev/null +++ b/cpp/src/memory.h @@ -0,0 +1,17 @@ +#ifndef __UTIL_MEMORY__ +#define __UTIL_MEMORY__ + +#if __GNUC__ < 4 + #include "boost/shared_ptr.hpp" + namespace std { + namespace tr1 { + using boost::shared_ptr; + using boost::dynamic_pointer_cast; + using boost::static_pointer_cast; + } + } +#else + #include +#endif +#endif + diff --git a/cpp/src/qpid/Exception.cpp b/cpp/src/qpid/Exception.cpp new file mode 100644 index 0000000000..f89972f02b --- /dev/null +++ b/cpp/src/qpid/Exception.cpp @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qpid/Exception.h" + +qpid::Exception::~Exception() throw() {} diff --git a/cpp/src/qpid/Exception.h b/cpp/src/qpid/Exception.h new file mode 100644 index 0000000000..709538c851 --- /dev/null +++ b/cpp/src/qpid/Exception.h @@ -0,0 +1,46 @@ +#ifndef _Exception_ +#define _Exception_ + +/* + * + * 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 +{ + /** + * 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() : whatStr(str) {} + Exception(const char* str) throw() : whatStr(str) {} + virtual ~Exception() throw(); + + const char* what() const throw() { return whatStr.c_str(); } + virtual std::string toString() const throw() { return whatStr; } + }; +} + +#endif /*!_Exception_*/ diff --git a/cpp/src/qpid/QpidError.cpp b/cpp/src/qpid/QpidError.cpp new file mode 100644 index 0000000000..c1d33c9583 --- /dev/null +++ b/cpp/src/qpid/QpidError.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 "qpid/QpidError.h" +#include + +using namespace qpid; + +QpidError::QpidError(int _code, const std::string& _msg, const std::string& _file, int _line) throw() + : code(_code), msg(_msg), file(_file), line(_line) +{ + std::ostringstream os; + os << "QpidError(" << code << ") " << msg << " (" << file << ":" << line << ")"; + whatStr = os.str(); +} + +QpidError::~QpidError() throw() {} diff --git a/cpp/src/qpid/QpidError.h b/cpp/src/qpid/QpidError.h new file mode 100644 index 0000000000..98a2efff15 --- /dev/null +++ b/cpp/src/qpid/QpidError.h @@ -0,0 +1,46 @@ +#ifndef __QpidError__ +#define __QpidError__ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include "qpid/Exception.h" + +namespace qpid { + + class QpidError : public Exception { + public: + const int code; + const std::string msg; + const std::string file; + const int line; + + QpidError(int _code, const std::string& _msg, const std::string& _file, int _line) throw(); + ~QpidError() throw(); + }; + +#define THROW_QPID_ERROR(A, B) throw QpidError(A, B, __FILE__, __LINE__) + +} + +#define PROTOCOL_ERROR 10000 +#define APR_ERROR 20000 +#define FRAMING_ERROR 30000 +#define CLIENT_ERROR 40000 +#define INTERNAL_ERROR 50000 + +#endif diff --git a/cpp/src/qpid/broker/AutoDelete.cpp b/cpp/src/qpid/broker/AutoDelete.cpp new file mode 100644 index 0000000000..22076e9e0c --- /dev/null +++ b/cpp/src/qpid/broker/AutoDelete.cpp @@ -0,0 +1,93 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/AutoDelete.h" + +using namespace qpid::broker; + +AutoDelete::AutoDelete(QueueRegistry* const _registry, u_int32_t _period) : registry(_registry), + period(_period), + stopped(true), + runner(0){} + +void AutoDelete::add(Queue::shared_ptr const queue){ + lock.acquire(); + queues.push(queue); + lock.release(); +} + +Queue::shared_ptr const AutoDelete::pop(){ + Queue::shared_ptr next; + lock.acquire(); + if(!queues.empty()){ + next = queues.front(); + queues.pop(); + } + lock.release(); + 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.acquire(); + while(!stopped){ + process(); + monitor.wait(period); + } + monitor.release(); +} + +void AutoDelete::start(){ + monitor.acquire(); + if(stopped){ + runner = factory.create(this); + stopped = false; + monitor.release(); + runner->start(); + }else{ + monitor.release(); + } +} + +void AutoDelete::stop(){ + monitor.acquire(); + if(!stopped){ + stopped = true; + monitor.notify(); + monitor.release(); + runner->join(); + delete runner; + }else{ + monitor.release(); + } +} diff --git a/cpp/src/qpid/broker/AutoDelete.h b/cpp/src/qpid/broker/AutoDelete.h new file mode 100644 index 0000000000..77a5a338e3 --- /dev/null +++ b/cpp/src/qpid/broker/AutoDelete.h @@ -0,0 +1,54 @@ +/* + * + * 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. + * + */ +#ifndef _AutoDelete_ +#define _AutoDelete_ + +#include +#include +#include "./qpid/concurrent/MonitorImpl.h" +#include "./qpid/broker/Queue.h" +#include "./qpid/broker/QueueRegistry.h" +#include "./qpid/concurrent/ThreadFactoryImpl.h" + +namespace qpid { + namespace broker{ + class AutoDelete : private virtual qpid::concurrent::Runnable{ + qpid::concurrent::ThreadFactoryImpl factory; + qpid::concurrent::MonitorImpl lock; + qpid::concurrent::MonitorImpl monitor; + std::queue queues; + QueueRegistry* const registry; + const u_int32_t period; + volatile bool stopped; + qpid::concurrent::Thread* runner; + + Queue::shared_ptr const pop(); + void process(); + virtual void run(); + + public: + AutoDelete(QueueRegistry* const registry, u_int32_t period); + void add(Queue::shared_ptr const); + void start(); + void stop(); + }; + } +} + + +#endif diff --git a/cpp/src/qpid/broker/Binding.h b/cpp/src/qpid/broker/Binding.h new file mode 100644 index 0000000000..4202d390c3 --- /dev/null +++ b/cpp/src/qpid/broker/Binding.h @@ -0,0 +1,35 @@ +/* + * + * 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. + * + */ +#ifndef _Binding_ +#define _Binding_ + +#include "./qpid/framing/FieldTable.h" + +namespace qpid { + namespace broker { + class Binding{ + public: + virtual void cancel() = 0; + virtual ~Binding(){} + }; + } +} + + +#endif + diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp new file mode 100644 index 0000000000..27ce840d01 --- /dev/null +++ b/cpp/src/qpid/broker/Broker.cpp @@ -0,0 +1,84 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include "./qpid/broker/Broker.h" +#include "./qpid/io/Acceptor.h" +#include "./qpid/broker/Configuration.h" +#include "./qpid/QpidError.h" +#include "./qpid/broker/SessionHandlerFactoryImpl.h" +#include "./qpid/io/BlockingAPRAcceptor.h" +#include "./qpid/io/LFAcceptor.h" + + +using namespace qpid::broker; +using namespace qpid::io; + +namespace { + Acceptor* createAcceptor(const Configuration& config){ + const string type(config.getAcceptor()); + if("blocking" == type){ + std::cout << "Using blocking acceptor " << std::endl; + return new BlockingAPRAcceptor(config.isTrace(), config.getConnectionBacklog()); + }else if("non-blocking" == type){ + std::cout << "Using non-blocking acceptor " << std::endl; + return new LFAcceptor(config.isTrace(), + config.getConnectionBacklog(), + config.getWorkerThreads(), + config.getMaxConnections()); + } + throw Configuration::ParseException("Unrecognised acceptor: " + type); + } +} + +Broker::Broker(const Configuration& config) : + acceptor(createAcceptor(config)), + port(config.getPort()), + isBound(false) {} + +Broker::shared_ptr Broker::create(int port) +{ + Configuration config; + config.setPort(port); + return create(config); +} + +Broker::shared_ptr Broker::create(const Configuration& config) { + return Broker::shared_ptr(new Broker(config)); +} + +int16_t Broker::bind() +{ + if (!isBound) { + port = acceptor->bind(port); + } + return port; +} + +void Broker::run() { + bind(); + acceptor->run(&factory); +} + +void Broker::shutdown() { + acceptor->shutdown(); +} + +Broker::~Broker() { } + +const int16_t Broker::DEFAULT_PORT(5672); diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h new file mode 100644 index 0000000000..3423dc0910 --- /dev/null +++ b/cpp/src/qpid/broker/Broker.h @@ -0,0 +1,86 @@ +#ifndef _Broker_ +#define _Broker_ + +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "./qpid/io/Acceptor.h" +#include "./qpid/broker/Configuration.h" +#include "./qpid/concurrent/Runnable.h" +#include "./qpid/broker/SessionHandlerFactoryImpl.h" +#include +#include + +namespace qpid { + namespace broker { + /** + * A broker instance. + */ + class Broker : public qpid::concurrent::Runnable, private boost::noncopyable { + Broker(const Configuration& config); // Private, use create() + std::auto_ptr acceptor; + SessionHandlerFactoryImpl factory; + int16_t port; + bool isBound; + + public: + static const int16_t DEFAULT_PORT; + + virtual ~Broker(); + typedef std::tr1::shared_ptr shared_ptr; + + /** + * Create a broker. + * @param port Port to listen on or 0 to pick a port dynamically. + */ + static shared_ptr create(int port = DEFAULT_PORT); + + /** + * Create a broker from a Configuration. + */ + static shared_ptr create(const Configuration& config); + + /** + * Bind to the listening port. + * @return The port number bound. + */ + virtual int16_t bind(); + + /** + * 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() { return port; } + + /** + * 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(); + }; + } +} + + + +#endif /*!_Broker_*/ diff --git a/cpp/src/qpid/broker/Channel.cpp b/cpp/src/qpid/broker/Channel.cpp new file mode 100644 index 0000000000..8d1cce9f1b --- /dev/null +++ b/cpp/src/qpid/broker/Channel.cpp @@ -0,0 +1,256 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/Channel.h" +#include "./qpid/QpidError.h" +#include +#include +#include + +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::concurrent; + + +Channel::Channel(OutputHandler* _out, int _id, u_int32_t _framesize) : + id(_id), + out(_out), + deliveryTag(1), + transactional(false), + prefetchSize(0), + prefetchCount(0), + outstandingSize(0), + outstandingCount(0), + framesize(_framesize), + tagGenerator("sgen"){} + +Channel::~Channel(){ +} + +bool Channel::exists(const string& consumerTag){ + return consumers.find(consumerTag) != consumers.end(); +} + +void Channel::consume(string& tag, Queue::shared_ptr queue, bool acks, bool exclusive, ConnectionToken* const connection){ + if(tag.empty()) tag = tagGenerator.generate(); + + ConsumerImpl* c(new ConsumerImpl(this, tag, queue, connection, acks)); + try{ + queue->consume(c, exclusive);//may throw exception + consumers[tag] = c; + }catch(ExclusiveAccessException& e){ + delete c; + throw e; + } +} + +void Channel::cancel(consumer_iterator i){ + ConsumerImpl* c = i->second; + consumers.erase(i); + if(c){ + c->cancel(); + delete c; + } +} + +void Channel::cancel(const string& tag){ + consumer_iterator i = consumers.find(tag); + if(i != consumers.end()){ + cancel(i); + } +} + +void Channel::close(){ + //cancel all consumers + for(consumer_iterator i = consumers.begin(); i != consumers.end(); i = consumers.begin() ){ + cancel(i); + } +} + +void Channel::begin(){ + transactional = true; +} + +void Channel::commit(){ + +} + +void Channel::rollback(){ + +} + +void Channel::deliver(Message::shared_ptr& msg, string& consumerTag, Queue::shared_ptr& queue, bool ackExpected){ + Locker locker(deliveryLock); + + u_int64_t myDeliveryTag = deliveryTag++; + if(ackExpected){ + unacknowledged.push_back(AckRecord(msg, queue, consumerTag, myDeliveryTag)); + outstandingSize += msg->contentSize(); + outstandingCount++; + } + //send deliver method, header and content(s) + msg->deliver(out, id, consumerTag, myDeliveryTag, framesize); +} + +bool Channel::checkPrefetch(Message::shared_ptr& msg){ + Locker locker(deliveryLock); + bool countOk = !prefetchCount || prefetchCount > unacknowledged.size(); + bool sizeOk = !prefetchSize || prefetchSize > msg->contentSize() + outstandingSize || unacknowledged.empty(); + return countOk && sizeOk; +} + +Channel::ConsumerImpl::ConsumerImpl(Channel* _parent, 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; +} + +void Channel::ConsumerImpl::cancel(){ + if(queue) queue->cancel(this); +} + +void Channel::ConsumerImpl::requestDispatch(){ + if(blocked) queue->dispatch(); +} + +void Channel::checkMessage(const std::string& text){ + if(!message.get()){ + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, text); + } +} + +void Channel::handlePublish(Message* msg){ + if(message.get()){ + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got publish before previous content was completed."); + } + message = Message::shared_ptr(msg); +} + +void Channel::ack(u_int64_t _deliveryTag, bool multiple){ + Locker locker(deliveryLock);//need to synchronize with possible concurrent delivery + + ack_iterator i = find_if(unacknowledged.begin(), unacknowledged.end(), MatchAck(_deliveryTag)); + if(i == unacknowledged.end()){ + throw InvalidAckException(); + }else if(multiple){ + unacknowledged.erase(unacknowledged.begin(), ++i); + //recompute prefetch outstanding (note: messages delivered through get are ignored) + CalculatePrefetch calc(for_each(unacknowledged.begin(), unacknowledged.end(), CalculatePrefetch())); + outstandingSize = calc.getSize(); + outstandingCount = calc.getCount(); + }else{ + if(!i->pull){ + outstandingSize -= i->msg->contentSize(); + outstandingCount--; + } + unacknowledged.erase(i); + } + + //if the prefetch limit had previously been reached, there may + //be messages that can be now be delivered + for(consumer_iterator j = consumers.begin(); j != consumers.end(); j++){ + j->second->requestDispatch(); + } +} + +void Channel::recover(bool requeue){ + Locker locker(deliveryLock);//need to synchronize with possible concurrent delivery + + if(requeue){ + outstandingSize = 0; + outstandingCount = 0; + ack_iterator start(unacknowledged.begin()); + ack_iterator end(unacknowledged.end()); + for_each(start, end, Requeue()); + unacknowledged.erase(start, end); + }else{ + for_each(unacknowledged.begin(), unacknowledged.end(), Redeliver(this)); + } +} + +bool Channel::get(Queue::shared_ptr queue, bool ackExpected){ + Message::shared_ptr msg = queue->dequeue(); + if(msg){ + Locker locker(deliveryLock); + u_int64_t myDeliveryTag = deliveryTag++; + msg->sendGetOk(out, id, queue->getMessageCount() + 1, myDeliveryTag, framesize); + if(ackExpected){ + unacknowledged.push_back(AckRecord(msg, queue, myDeliveryTag)); + } + return true; + }else{ + return false; + } +} + +Channel::MatchAck::MatchAck(u_int64_t _tag) : tag(_tag) {} + +bool Channel::MatchAck::operator()(AckRecord& record) const{ + return tag == record.deliveryTag; +} + +void Channel::Requeue::operator()(AckRecord& record) const{ + record.msg->redeliver(); + record.queue->deliver(record.msg); +} + +Channel::Redeliver::Redeliver(Channel* const _channel) : channel(_channel) {} + +void Channel::Redeliver::operator()(AckRecord& record) const{ + if(record.pull){ + //if message was originally sent as response to get, we must requeue it + record.msg->redeliver(); + record.queue->deliver(record.msg); + }else{ + record.msg->deliver(channel->out, channel->id, record.consumerTag, record.deliveryTag, channel->framesize); + } +} + +Channel::CalculatePrefetch::CalculatePrefetch() : size(0){} + +void Channel::CalculatePrefetch::operator()(AckRecord& record){ + if(!record.pull){ + //ignore messages that were sent in response to get when calculating prefetch + size += record.msg->contentSize(); + count++; + } +} + +u_int32_t Channel::CalculatePrefetch::getSize(){ + return size; +} + +u_int16_t Channel::CalculatePrefetch::getCount(){ + return count; +} diff --git a/cpp/src/qpid/broker/Channel.h b/cpp/src/qpid/broker/Channel.h new file mode 100644 index 0000000000..a20f4d9599 --- /dev/null +++ b/cpp/src/qpid/broker/Channel.h @@ -0,0 +1,199 @@ +/* + * + * 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. + * + */ +#ifndef _Channel_ +#define _Channel_ + +#include +#include +#include "./qpid/framing/AMQContentBody.h" +#include "./qpid/framing/AMQHeaderBody.h" +#include "qpid/framing/BasicPublishBody.h" +#include "./qpid/broker/Binding.h" +#include "./qpid/broker/Consumer.h" +#include "./qpid/broker/Message.h" +#include "./qpid/concurrent/MonitorImpl.h" +#include "./qpid/broker/NameGenerator.h" +#include "./qpid/framing/OutputHandler.h" +#include "./qpid/broker/Queue.h" + +namespace qpid { + namespace broker { + /** + * Maintains state for an AMQP channel. Handles incoming and + * outgoing messages for that channel. + */ + class Channel{ + private: + class ConsumerImpl : public virtual Consumer{ + Channel* parent; + string tag; + Queue::shared_ptr queue; + ConnectionToken* const connection; + const bool ackExpected; + bool blocked; + public: + ConsumerImpl(Channel* parent, string& tag, Queue::shared_ptr queue, ConnectionToken* const connection, bool ack); + virtual bool deliver(Message::shared_ptr& msg); + void cancel(); + void requestDispatch(); + }; + + typedef std::map::iterator consumer_iterator; + + struct AckRecord{ + Message::shared_ptr msg; + Queue::shared_ptr queue; + string consumerTag; + u_int64_t deliveryTag; + bool pull; + + AckRecord(Message::shared_ptr _msg, + Queue::shared_ptr _queue, + const string _consumerTag, + const u_int64_t _deliveryTag) : msg(_msg), + queue(_queue), + consumerTag(_consumerTag), + deliveryTag(_deliveryTag), + pull(false){} + + AckRecord(Message::shared_ptr _msg, + Queue::shared_ptr _queue, + const u_int64_t _deliveryTag) : msg(_msg), + queue(_queue), + consumerTag(""), + deliveryTag(_deliveryTag), + pull(true){} + }; + + typedef std::vector::iterator ack_iterator; + + class MatchAck{ + const u_int64_t tag; + public: + MatchAck(u_int64_t tag); + bool operator()(AckRecord& record) const; + }; + + class Requeue{ + public: + void operator()(AckRecord& record) const; + }; + + class Redeliver{ + Channel* const channel; + public: + Redeliver(Channel* const channel); + void operator()(AckRecord& record) const; + }; + + class CalculatePrefetch{ + u_int32_t size; + u_int16_t count; + public: + CalculatePrefetch(); + void operator()(AckRecord& record); + u_int32_t getSize(); + u_int16_t getCount(); + }; + + const int id; + qpid::framing::OutputHandler* out; + u_int64_t deliveryTag; + Queue::shared_ptr defaultQueue; + bool transactional; + std::map consumers; + u_int32_t prefetchSize; + u_int16_t prefetchCount; + u_int32_t outstandingSize; + u_int16_t outstandingCount; + u_int32_t framesize; + Message::shared_ptr message; + NameGenerator tagGenerator; + std::vector unacknowledged; + qpid::concurrent::MonitorImpl deliveryLock; + + void deliver(Message::shared_ptr& msg, string& tag, Queue::shared_ptr& queue, bool ackExpected); + void checkMessage(const std::string& text); + bool checkPrefetch(Message::shared_ptr& msg); + void cancel(consumer_iterator consumer); + + template Operation processMessage(Operation route){ + if(message->isComplete()){ + route(message); + message.reset(); + } + return route; + } + + + public: + Channel(qpid::framing::OutputHandler* out, int id, u_int32_t framesize); + ~Channel(); + inline void setDefaultQueue(Queue::shared_ptr queue){ defaultQueue = queue; } + inline Queue::shared_ptr getDefaultQueue(){ return defaultQueue; } + inline u_int32_t setPrefetchSize(u_int32_t size){ return prefetchSize = size; } + inline u_int16_t setPrefetchCount(u_int16_t count){ return prefetchCount = count; } + bool exists(const string& consumerTag); + void consume(string& tag, Queue::shared_ptr queue, bool acks, bool exclusive, ConnectionToken* const connection = 0); + void cancel(const string& tag); + bool get(Queue::shared_ptr queue, bool ackExpected); + void begin(); + void close(); + void commit(); + void rollback(); + void ack(u_int64_t deliveryTag, bool multiple); + void recover(bool requeue); + + /** + * Handles the initial publish request though a + * channel. The header and (if applicable) content will be + * accumulated through calls to handleHeader() and + * handleContent() + */ + void handlePublish(Message* msg); + + /** + * A template method that handles a received header and if + * there is no content routes it using the functor passed + * in. + */ + template Operation handleHeader(qpid::framing::AMQHeaderBody::shared_ptr header, Operation route){ + checkMessage("Invalid message sequence: got header before publish."); + message->setHeader(header); + return processMessage(route); + } + + /** + * A template method that handles a received content and + * if this completes the message, routes it using the + * functor passed in. + */ + template Operation handleContent(qpid::framing::AMQContentBody::shared_ptr content, Operation route){ + checkMessage("Invalid message sequence: got content before publish."); + message->addContent(content); + return processMessage(route); + } + + }; + + struct InvalidAckException{}; + } +} + + +#endif diff --git a/cpp/src/qpid/broker/Configuration.cpp b/cpp/src/qpid/broker/Configuration.cpp new file mode 100644 index 0000000000..d4b27e4dd2 --- /dev/null +++ b/cpp/src/qpid/broker/Configuration.cpp @@ -0,0 +1,196 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/Configuration.h" +#include + +using namespace qpid::broker; +using namespace std; + +Configuration::Configuration() : + trace('t', "trace", "Print incoming & outgoing frames to the console (default=false)", false), + port('p', "port", "Sets the port to listen on (default=5672)", 5672), + workerThreads("worker-threads", "Sets the number of worker threads to use (default=5). Only valid for non-blocking acceptor.", 5), + maxConnections("max-connections", "Sets the maximum number of connections the broker can accept (default=500). Only valid for non-blocking acceptor.", 500), + connectionBacklog("connection-backlog", "Sets the connection backlog for the servers socket (default=10)", 10), + acceptor('a', "acceptor", "Sets the acceptor to use. Currently only two values are recognised, blocking and non-blocking (which is the default)", "non-blocking"), + help("help", "Prints usage information", false) +{ + options.push_back(&trace); + options.push_back(&port); + options.push_back(&workerThreads); + options.push_back(&maxConnections); + options.push_back(&connectionBacklog); + options.push_back(&acceptor); + options.push_back(&help); +} + +Configuration::~Configuration(){} + +void Configuration::parse(int argc, char** argv){ + 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){ + std::cout << "Warning: skipping unrecognised option " << argv[position] << std::endl; + position++; + } + } +} + +void Configuration::usage(){ + for(op_iterator i = options.begin(); i < options.end(); i++){ + (*i)->print(std::cout); + } +} + +bool Configuration::isHelp() const { + return help.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(); +} + +string Configuration::getAcceptor() const { + return acceptor.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 << " or "; + } + 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()); +} + +// 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& _value){ + value = strcasecmp(_value.c_str(), "true") == 0; +} diff --git a/cpp/src/qpid/broker/Configuration.h b/cpp/src/qpid/broker/Configuration.h new file mode 100644 index 0000000000..3785e1bac0 --- /dev/null +++ b/cpp/src/qpid/broker/Configuration.h @@ -0,0 +1,135 @@ +/* + * + * 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. + * + */ +#ifndef _Configuration_ +#define _Configuration_ + +#include +#include +#include +#include "./qpid/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 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 trace; + IntOption port; + IntOption workerThreads; + IntOption maxConnections; + IntOption connectionBacklog; + StringOption acceptor; + BoolOption help; + + typedef std::vector::iterator op_iterator; + std::vector options; + + public: + class ParseException : public Exception { + public: + ParseException(const std::string& msg) : Exception(msg) {} + }; + + + Configuration(); + ~Configuration(); + + void parse(int argc, char** argv); + + bool isHelp() const; + bool isTrace() const; + int getPort() const; + int getWorkerThreads() const; + int getMaxConnections() const; + int getConnectionBacklog() const; + std::string getAcceptor() const; + + void setHelp(bool b) { help.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 setAcceptor(const std::string& val) { acceptor.setValue(val); } + + void usage(); + }; + } +} + + +#endif diff --git a/cpp/src/qpid/broker/ConnectionToken.h b/cpp/src/qpid/broker/ConnectionToken.h new file mode 100644 index 0000000000..1faefec2cc --- /dev/null +++ b/cpp/src/qpid/broker/ConnectionToken.h @@ -0,0 +1,35 @@ +/* + * + * 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. + * + */ +#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/cpp/src/qpid/broker/Consumer.h b/cpp/src/qpid/broker/Consumer.h new file mode 100644 index 0000000000..7d346a4a0a --- /dev/null +++ b/cpp/src/qpid/broker/Consumer.h @@ -0,0 +1,34 @@ +/* + * + * 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. + * + */ +#ifndef _Consumer_ +#define _Consumer_ + +#include "./qpid/broker/Message.h" + +namespace qpid { + namespace broker { + class Consumer{ + public: + virtual bool deliver(Message::shared_ptr& msg) = 0; + virtual ~Consumer(){} + }; + } +} + + +#endif diff --git a/cpp/src/qpid/broker/DirectExchange.cpp b/cpp/src/qpid/broker/DirectExchange.cpp new file mode 100644 index 0000000000..aa90d8dd81 --- /dev/null +++ b/cpp/src/qpid/broker/DirectExchange.cpp @@ -0,0 +1,72 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/DirectExchange.h" +#include "./qpid/broker/ExchangeBinding.h" +#include + +using namespace qpid::broker; +using namespace qpid::framing; + +DirectExchange::DirectExchange(const string& _name) : Exchange(_name) { + +} + +void DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, FieldTable* args){ + lock.acquire(); + std::vector& queues(bindings[routingKey]); + std::vector::iterator i = find(queues.begin(), queues.end(), queue); + if(i == queues.end()){ + bindings[routingKey].push_back(queue); + queue->bound(new ExchangeBinding(this, queue, routingKey, args)); + } + lock.release(); +} + +void DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, FieldTable* /*args*/){ + lock.acquire(); + 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); + } + } + lock.release(); +} + +void DirectExchange::route(Message::shared_ptr& msg, const string& routingKey, FieldTable* /*args*/){ + lock.acquire(); + std::vector& queues(bindings[routingKey]); + int count(0); + for(std::vector::iterator i = queues.begin(); i != queues.end(); i++, count++){ + (*i)->deliver(msg); + } + if(!count){ + std::cout << "WARNING: DirectExchange " << getName() << " could not route message with key " << routingKey << std::endl; + } + lock.release(); +} + +DirectExchange::~DirectExchange(){ + +} + + +const std::string DirectExchange::typeName("direct"); diff --git a/cpp/src/qpid/broker/DirectExchange.h b/cpp/src/qpid/broker/DirectExchange.h new file mode 100644 index 0000000000..ce58a174c6 --- /dev/null +++ b/cpp/src/qpid/broker/DirectExchange.h @@ -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. + * + */ +#ifndef _DirectExchange_ +#define _DirectExchange_ + +#include +#include +#include "./qpid/broker/Exchange.h" +#include "./qpid/framing/FieldTable.h" +#include "./qpid/broker/Message.h" +#include "./qpid/concurrent/MonitorImpl.h" +#include "./qpid/broker/Queue.h" + +namespace qpid { +namespace broker { + class DirectExchange : public virtual Exchange{ + std::map > bindings; + qpid::concurrent::MonitorImpl lock; + + public: + static const std::string typeName; + + DirectExchange(const std::string& name); + + virtual void bind(Queue::shared_ptr queue, const std::string& routingKey, qpid::framing::FieldTable* args); + + virtual void unbind(Queue::shared_ptr queue, const std::string& routingKey, qpid::framing::FieldTable* args); + + virtual void route(Message::shared_ptr& msg, const std::string& routingKey, qpid::framing::FieldTable* args); + + virtual ~DirectExchange(); + }; +} +} + + +#endif diff --git a/cpp/src/qpid/broker/Exchange.h b/cpp/src/qpid/broker/Exchange.h new file mode 100644 index 0000000000..7b8bb1c034 --- /dev/null +++ b/cpp/src/qpid/broker/Exchange.h @@ -0,0 +1,41 @@ +/* + * + * 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. + * + */ +#ifndef _Exchange_ +#define _Exchange_ + +#include "./qpid/framing/FieldTable.h" +#include "./qpid/broker/Message.h" +#include "./qpid/broker/Queue.h" + +namespace qpid { +namespace broker { + class Exchange{ + const std::string name; + public: + explicit Exchange(const std::string& _name) : name(_name) {} + virtual ~Exchange(){} + std::string getName() { return name; } + virtual void bind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args) = 0; + virtual void unbind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args) = 0; + virtual void route(Message::shared_ptr& msg, const string& routingKey, qpid::framing::FieldTable* args) = 0; + }; +} +} + + +#endif diff --git a/cpp/src/qpid/broker/ExchangeBinding.cpp b/cpp/src/qpid/broker/ExchangeBinding.cpp new file mode 100644 index 0000000000..61f44f634c --- /dev/null +++ b/cpp/src/qpid/broker/ExchangeBinding.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 "./qpid/broker/ExchangeBinding.h" +#include "./qpid/broker/Exchange.h" + +using namespace qpid::broker; +using namespace qpid::framing; + +ExchangeBinding::ExchangeBinding(Exchange* _e, Queue::shared_ptr _q, const string& _key, FieldTable* _args) : e(_e), q(_q), key(_key), args(_args){} + +void ExchangeBinding::cancel(){ + e->unbind(q, key, args); + delete this; +} + +ExchangeBinding::~ExchangeBinding(){ +} diff --git a/cpp/src/qpid/broker/ExchangeBinding.h b/cpp/src/qpid/broker/ExchangeBinding.h new file mode 100644 index 0000000000..fda5fab153 --- /dev/null +++ b/cpp/src/qpid/broker/ExchangeBinding.h @@ -0,0 +1,45 @@ +/* + * + * 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. + * + */ +#ifndef _ExchangeBinding_ +#define _ExchangeBinding_ + +#include "./qpid/broker/Binding.h" +#include "./qpid/framing/FieldTable.h" +#include "./qpid/broker/Queue.h" + +namespace qpid { + namespace broker { + class Exchange; + class Queue; + + class ExchangeBinding : public virtual Binding{ + Exchange* e; + Queue::shared_ptr q; + const string key; + qpid::framing::FieldTable* args; + public: + ExchangeBinding(Exchange* _e, Queue::shared_ptr _q, const string& _key, qpid::framing::FieldTable* _args); + virtual void cancel(); + virtual ~ExchangeBinding(); + }; + } +} + + +#endif + diff --git a/cpp/src/qpid/broker/ExchangeRegistry.cpp b/cpp/src/qpid/broker/ExchangeRegistry.cpp new file mode 100644 index 0000000000..0755393e68 --- /dev/null +++ b/cpp/src/qpid/broker/ExchangeRegistry.cpp @@ -0,0 +1,57 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/ExchangeRegistry.h" +#include "./qpid/concurrent/MonitorImpl.h" + +using namespace qpid::broker; +using namespace qpid::concurrent; + +ExchangeRegistry::ExchangeRegistry() : lock(new MonitorImpl()){} + +ExchangeRegistry::~ExchangeRegistry(){ + for (ExchangeMap::iterator i = exchanges.begin(); i != exchanges.end(); ++i) + { + delete i->second; + } + delete lock; +} + +void ExchangeRegistry::declare(Exchange* exchange){ + exchanges[exchange->getName()] = exchange; +} + +void ExchangeRegistry::destroy(const string& name){ + if(exchanges[name]){ + delete exchanges[name]; + exchanges.erase(name); + } +} + +Exchange* ExchangeRegistry::get(const string& name){ + return exchanges[name]; +} + +namespace +{ +const std::string empty; +} + +Exchange* ExchangeRegistry::getDefault() +{ + return get(empty); +} diff --git a/cpp/src/qpid/broker/ExchangeRegistry.h b/cpp/src/qpid/broker/ExchangeRegistry.h new file mode 100644 index 0000000000..7728ed0eff --- /dev/null +++ b/cpp/src/qpid/broker/ExchangeRegistry.h @@ -0,0 +1,44 @@ +/* + * + * 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. + * + */ +#ifndef _ExchangeRegistry_ +#define _ExchangeRegistry_ + +#include +#include "./qpid/broker/Exchange.h" +#include "./qpid/concurrent/Monitor.h" + +namespace qpid { +namespace broker { + class ExchangeRegistry{ + typedef std::map ExchangeMap; + ExchangeMap exchanges; + qpid::concurrent::Monitor* lock; + public: + ExchangeRegistry(); + void declare(Exchange* exchange); + void destroy(const string& name); + Exchange* get(const string& name); + Exchange* getDefault(); + inline qpid::concurrent::Monitor* getLock(){ return lock; } + ~ExchangeRegistry(); + }; +} +} + + +#endif diff --git a/cpp/src/qpid/broker/FanOutExchange.cpp b/cpp/src/qpid/broker/FanOutExchange.cpp new file mode 100644 index 0000000000..1b4e3643d0 --- /dev/null +++ b/cpp/src/qpid/broker/FanOutExchange.cpp @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/FanOutExchange.h" +#include "./qpid/broker/ExchangeBinding.h" +#include + +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::concurrent; + +FanOutExchange::FanOutExchange(const std::string& _name) : Exchange(_name) {} + +void FanOutExchange::bind(Queue::shared_ptr queue, const string& routingKey, FieldTable* args){ + Locker 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); + queue->bound(new ExchangeBinding(this, queue, routingKey, args)); + } +} + +void FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*routingKey*/, FieldTable* /*args*/){ + Locker locker(lock); + Queue::vector::iterator i = std::find(bindings.begin(), bindings.end(), queue); + if (i != bindings.end()) { + bindings.erase(i); + // TODO aconway 2006-09-14: What about the ExchangeBinding object? Don't we have to verify routingKey/args match? + } +} + +void FanOutExchange::route(Message::shared_ptr& msg, const string& /*routingKey*/, FieldTable* /*args*/){ + Locker locker(lock); + for(Queue::vector::iterator i = bindings.begin(); i != bindings.end(); ++i){ + (*i)->deliver(msg); + } +} + +FanOutExchange::~FanOutExchange() {} + +const std::string FanOutExchange::typeName("fanout"); diff --git a/cpp/src/qpid/broker/FanOutExchange.h b/cpp/src/qpid/broker/FanOutExchange.h new file mode 100644 index 0000000000..f79dd28ec5 --- /dev/null +++ b/cpp/src/qpid/broker/FanOutExchange.h @@ -0,0 +1,55 @@ +/* + * + * 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. + * + */ +#ifndef _FanOutExchange_ +#define _FanOutExchange_ + +#include +#include +#include "./qpid/broker/Exchange.h" +#include "./qpid/framing/FieldTable.h" +#include "./qpid/broker/Message.h" +#include "./qpid/concurrent/MonitorImpl.h" +#include "./qpid/broker/Queue.h" + +namespace qpid { +namespace broker { + +class FanOutExchange : public virtual Exchange { + std::vector bindings; + qpid::concurrent::MonitorImpl lock; + + public: + static const std::string typeName; + + FanOutExchange(const std::string& name); + + virtual void bind(Queue::shared_ptr queue, const std::string& routingKey, qpid::framing::FieldTable* args); + + virtual void unbind(Queue::shared_ptr queue, const std::string& routingKey, qpid::framing::FieldTable* args); + + virtual void route(Message::shared_ptr& msg, const std::string& routingKey, qpid::framing::FieldTable* args); + + virtual ~FanOutExchange(); +}; + +} +} + + + +#endif diff --git a/cpp/src/qpid/broker/HeadersExchange.cpp b/cpp/src/qpid/broker/HeadersExchange.cpp new file mode 100644 index 0000000000..35feef22dd --- /dev/null +++ b/cpp/src/qpid/broker/HeadersExchange.cpp @@ -0,0 +1,120 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/HeadersExchange.h" +#include "./qpid/broker/ExchangeBinding.h" +#include "./qpid/framing/Value.h" +#include "./qpid/QpidError.h" +#include + + +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::concurrent; + +// 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, FieldTable* args){ + std::cout << "HeadersExchange::bind" << std::endl; + Locker 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)); + queue->bound(new ExchangeBinding(this, queue, routingKey, args)); +} + +void HeadersExchange::unbind(Queue::shared_ptr queue, const string& /*routingKey*/, FieldTable* args){ + Locker locker(lock); + Bindings::iterator i = + std::find(bindings.begin(),bindings.end(), Binding(*args, queue)); + if (i != bindings.end()) bindings.erase(i); +} + + +void HeadersExchange::route(Message::shared_ptr& msg, const string& /*routingKey*/, FieldTable* args){ + std::cout << "route: " << *args << std::endl; + Locker locker(lock);; + for (Bindings::iterator i = bindings.begin(); i != bindings.end(); ++i) { + if (match(i->first, *args)) i->second->deliver(msg); + } +} + +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/cpp/src/qpid/broker/HeadersExchange.h b/cpp/src/qpid/broker/HeadersExchange.h new file mode 100644 index 0000000000..a330e050f5 --- /dev/null +++ b/cpp/src/qpid/broker/HeadersExchange.h @@ -0,0 +1,60 @@ +/* + * + * 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. + * + */ +#ifndef _HeadersExchange_ +#define _HeadersExchange_ + +#include +#include "./qpid/broker/Exchange.h" +#include "./qpid/framing/FieldTable.h" +#include "./qpid/broker/Message.h" +#include "./qpid/concurrent/MonitorImpl.h" +#include "./qpid/broker/Queue.h" + +namespace qpid { +namespace broker { + + +class HeadersExchange : public virtual Exchange { + typedef std::pair Binding; + typedef std::vector Bindings; + + Bindings bindings; + qpid::concurrent::MonitorImpl lock; + + public: + static const std::string typeName; + + HeadersExchange(const string& name); + + virtual void bind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args); + + virtual void unbind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args); + + virtual void route(Message::shared_ptr& msg, const string& routingKey, qpid::framing::FieldTable* args); + + virtual ~HeadersExchange(); + + static bool match(const qpid::framing::FieldTable& bindArgs, const qpid::framing::FieldTable& msgArgs); +}; + + + +} +} + +#endif diff --git a/cpp/src/qpid/broker/Message.cpp b/cpp/src/qpid/broker/Message.cpp new file mode 100644 index 0000000000..7210ecc2f2 --- /dev/null +++ b/cpp/src/qpid/broker/Message.cpp @@ -0,0 +1,100 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/concurrent/MonitorImpl.h" +#include "./qpid/broker/Message.h" +#include "./qpid/broker/ExchangeRegistry.h" +#include + +using namespace std::tr1;//for *_pointer_cast methods +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::concurrent; + + +Message::Message(const ConnectionToken* const _publisher, + const string& _exchange, const string& _routingKey, + bool _mandatory, bool _immediate) : publisher(_publisher), + exchange(_exchange), + routingKey(_routingKey), + mandatory(_mandatory), + immediate(_immediate), + redelivered(false), + size(0){ + +} + +Message::~Message(){ +} + +void Message::setHeader(AMQHeaderBody::shared_ptr _header){ + this->header = _header; +} + +void Message::addContent(AMQContentBody::shared_ptr data){ + content.push_back(data); + size += data->size(); +} + +bool Message::isComplete(){ + return header.get() && (header->getContentSize() == contentSize()); +} + +void Message::redeliver(){ + redelivered = true; +} + +void Message::deliver(OutputHandler* out, int channel, + const string& consumerTag, u_int64_t deliveryTag, + u_int32_t framesize){ + + out->send(new AMQFrame(channel, new BasicDeliverBody(consumerTag, deliveryTag, redelivered, exchange, routingKey))); + sendContent(out, channel, framesize); +} + +void Message::sendGetOk(OutputHandler* out, + int channel, + u_int32_t messageCount, + u_int64_t deliveryTag, + u_int32_t framesize){ + + out->send(new AMQFrame(channel, new BasicGetOkBody(deliveryTag, redelivered, exchange, routingKey, messageCount))); + sendContent(out, channel, framesize); +} + +void Message::sendContent(OutputHandler* out, int channel, u_int32_t framesize){ + AMQBody::shared_ptr headerBody = static_pointer_cast(header); + out->send(new AMQFrame(channel, headerBody)); + for(content_iterator i = content.begin(); i != content.end(); i++){ + if((*i)->size() > framesize){ + //TODO: need to split it + std::cout << "WARNING: Dropped message. Re-fragmentation not yet implemented." << std::endl; + }else{ + AMQBody::shared_ptr contentBody = static_pointer_cast(*i); + out->send(new AMQFrame(channel, contentBody)); + } + } +} + +BasicHeaderProperties* Message::getHeaderProperties(){ + return dynamic_cast(header->getProperties()); +} + +const ConnectionToken* const Message::getPublisher(){ + return publisher; +} + diff --git a/cpp/src/qpid/broker/Message.h b/cpp/src/qpid/broker/Message.h new file mode 100644 index 0000000000..7ba8767baf --- /dev/null +++ b/cpp/src/qpid/broker/Message.h @@ -0,0 +1,89 @@ +/* + * + * 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. + * + */ +#ifndef _Message_ +#define _Message_ + +#include "./memory.h" +#include "./qpid/framing/AMQContentBody.h" +#include "./qpid/framing/AMQHeaderBody.h" +#include "./qpid/framing/BasicHeaderProperties.h" +#include "./qpid/framing/BasicPublishBody.h" +#include "./qpid/broker/ConnectionToken.h" +#include "./qpid/framing/OutputHandler.h" + +namespace qpid { + namespace broker { + class ExchangeRegistry; + + /** + * Represents an AMQP message, i.e. a header body, a list of + * content bodies and some details about the publication + * request. + */ + class Message{ + typedef std::vector content_list; + typedef content_list::iterator content_iterator; + + const ConnectionToken* const publisher; + const string exchange; + const string routingKey; + const bool mandatory; + const bool immediate; + bool redelivered; + qpid::framing::AMQHeaderBody::shared_ptr header; + content_list content; + u_int64_t size; + + void sendContent(qpid::framing::OutputHandler* out, + int channel, u_int32_t framesize); + + public: + typedef std::tr1::shared_ptr shared_ptr; + + Message(const ConnectionToken* const publisher, + const string& exchange, const string& routingKey, + bool mandatory, bool immediate); + ~Message(); + void setHeader(qpid::framing::AMQHeaderBody::shared_ptr header); + void addContent(qpid::framing::AMQContentBody::shared_ptr data); + bool isComplete(); + const ConnectionToken* const getPublisher(); + + void deliver(qpid::framing::OutputHandler* out, + int channel, + const string& consumerTag, + u_int64_t deliveryTag, + u_int32_t framesize); + void sendGetOk(qpid::framing::OutputHandler* out, + int channel, + u_int32_t messageCount, + u_int64_t deliveryTag, + u_int32_t framesize); + void redeliver(); + + qpid::framing::BasicHeaderProperties* getHeaderProperties(); + const string& getRoutingKey() const { return routingKey; } + const string& getExchange() const { return exchange; } + u_int64_t contentSize() const{ return size; } + + }; + } +} + + +#endif diff --git a/cpp/src/qpid/broker/NameGenerator.cpp b/cpp/src/qpid/broker/NameGenerator.cpp new file mode 100644 index 0000000000..d9b758c5a0 --- /dev/null +++ b/cpp/src/qpid/broker/NameGenerator.cpp @@ -0,0 +1,29 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/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/cpp/src/qpid/broker/NameGenerator.h b/cpp/src/qpid/broker/NameGenerator.h new file mode 100644 index 0000000000..38f3c0a4c1 --- /dev/null +++ b/cpp/src/qpid/broker/NameGenerator.h @@ -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. + * + */ +#ifndef _NameGenerator_ +#define _NameGenerator_ + +#include "./qpid/broker/Message.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/cpp/src/qpid/broker/Queue.cpp b/cpp/src/qpid/broker/Queue.cpp new file mode 100644 index 0000000000..d672074555 --- /dev/null +++ b/cpp/src/qpid/broker/Queue.cpp @@ -0,0 +1,155 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/Queue.h" +#include "./qpid/concurrent/MonitorImpl.h" +#include + +using namespace qpid::broker; +using namespace qpid::concurrent; + +Queue::Queue(const string& _name, bool _durable, u_int32_t _autodelete, const ConnectionToken* const _owner) : + name(_name), + autodelete(_autodelete), + durable(_durable), + owner(_owner), + queueing(false), + dispatching(false), + next(0), + lastUsed(0), + exclusive(0) +{ + if(autodelete) lastUsed = apr_time_as_msec(apr_time_now()); +} + +Queue::~Queue(){ + for(Binding* b = bindings.front(); !bindings.empty(); b = bindings.front()){ + b->cancel(); + bindings.pop(); + } +} + +void Queue::bound(Binding* b){ + bindings.push(b); +} + +void Queue::deliver(Message::shared_ptr& msg){ + Locker locker(lock); + if(queueing || !dispatch(msg)){ + queueing = true; + messages.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(){ + Locker locker(lock); + if(queueing && !dispatching){ + dispatching = true; + return true; + }else{ + return false; + } +} + +void Queue::dispatch(){ + bool proceed = startDispatching(); + while(proceed){ + Locker locker(lock); + if(!messages.empty() && dispatch(messages.front())){ + messages.pop(); + }else{ + dispatching = false; + proceed = false; + queueing = !messages.empty(); + } + } +} + +void Queue::consume(Consumer* c, bool requestExclusive){ + Locker locker(lock); + if(exclusive) throw ExclusiveAccessException(); + if(requestExclusive){ + if(!consumers.empty()) throw ExclusiveAccessException(); + exclusive = c; + } + + if(autodelete && consumers.empty()) lastUsed = 0; + consumers.push_back(c); +} + +void Queue::cancel(Consumer* c){ + Locker locker(lock); + consumers.erase(find(consumers.begin(), consumers.end(), c)); + if(autodelete && consumers.empty()) lastUsed = apr_time_as_msec(apr_time_now()); + if(exclusive == c) exclusive = 0; +} + +Message::shared_ptr Queue::dequeue(){ + Locker locker(lock); + Message::shared_ptr msg; + if(!messages.empty()){ + msg = messages.front(); + messages.pop(); + } + return msg; +} + +u_int32_t Queue::purge(){ + Locker locker(lock); + int count = messages.size(); + while(!messages.empty()) messages.pop(); + return count; +} + +u_int32_t Queue::getMessageCount() const{ + Locker locker(lock); + return messages.size(); +} + +u_int32_t Queue::getConsumerCount() const{ + Locker locker(lock); + return consumers.size(); +} + +bool Queue::canAutoDelete() const{ + Locker locker(lock); + return lastUsed && ((apr_time_as_msec(apr_time_now()) - lastUsed) > autodelete); +} diff --git a/cpp/src/qpid/broker/Queue.h b/cpp/src/qpid/broker/Queue.h new file mode 100644 index 0000000000..6cf9088633 --- /dev/null +++ b/cpp/src/qpid/broker/Queue.h @@ -0,0 +1,106 @@ +/* + * + * 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. + * + */ +#ifndef _Queue_ +#define _Queue_ + +#include +#include +#include "./memory.h" +#include "apr_time.h" +#include "./qpid/framing/amqp_types.h" +#include "./qpid/broker/Binding.h" +#include "./qpid/broker/ConnectionToken.h" +#include "./qpid/broker/Consumer.h" +#include "./qpid/broker/Message.h" +#include "./qpid/concurrent/MonitorImpl.h" + +namespace qpid { + namespace broker { + + /** + * Thrown when exclusive access would be violated. + */ + struct ExclusiveAccessException{}; + + /** + * 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{ + const string name; + const u_int32_t autodelete; + const bool durable; + const ConnectionToken* const owner; + std::vector consumers; + std::queue bindings; + std::queue messages; + bool queueing; + bool dispatching; + int next; + mutable qpid::concurrent::MonitorImpl lock; + apr_time_t lastUsed; + Consumer* exclusive; + + bool startDispatching(); + bool dispatch(Message::shared_ptr& msg); + + public: + + typedef std::tr1::shared_ptr shared_ptr; + + typedef std::vector vector; + + Queue(const string& name, bool durable = false, u_int32_t autodelete = 0, const ConnectionToken* const owner = 0); + ~Queue(); + /** + * Informs the queue of a binding that should be cancelled on + * destruction of the queue. + */ + void bound(Binding* b); + /** + * Delivers a message to the queue from where it will be + * dispatched to immediately to a consumer if one is + * available or stored for dequeue or later dispatch if + * not. + */ + void deliver(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); + Message::shared_ptr dequeue(); + u_int32_t purge(); + u_int32_t getMessageCount() const; + u_int32_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; + }; + } +} + + +#endif diff --git a/cpp/src/qpid/broker/QueueRegistry.cpp b/cpp/src/qpid/broker/QueueRegistry.cpp new file mode 100644 index 0000000000..f2cb46648e --- /dev/null +++ b/cpp/src/qpid/broker/QueueRegistry.cpp @@ -0,0 +1,72 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/QueueRegistry.h" +#include "./qpid/concurrent/MonitorImpl.h" +#include "./qpid/broker/SessionHandlerImpl.h" +#include +#include + +using namespace qpid::broker; +using namespace qpid::concurrent; + +QueueRegistry::QueueRegistry() : counter(1){} + +QueueRegistry::~QueueRegistry(){} + +std::pair +QueueRegistry::declare(const string& declareName, bool durable, u_int32_t autoDelete, const ConnectionToken* owner) +{ + Locker 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, durable, autoDelete, owner)); + queues[name] = queue; + return std::pair(queue, true); + } else { + return std::pair(i->second, false); + } +} + +void QueueRegistry::destroy(const string& name){ + Locker locker(lock); + queues.erase(name); +} + +Queue::shared_ptr QueueRegistry::find(const string& name){ + Locker 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; +} diff --git a/cpp/src/qpid/broker/QueueRegistry.h b/cpp/src/qpid/broker/QueueRegistry.h new file mode 100644 index 0000000000..9e6778153e --- /dev/null +++ b/cpp/src/qpid/broker/QueueRegistry.h @@ -0,0 +1,88 @@ +/* + * + * 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. + * + */ +#ifndef _QueueRegistry_ +#define _QueueRegistry_ + +#include +#include "./qpid/concurrent/MonitorImpl.h" +#include "./qpid/broker/Queue.h" + +namespace qpid { +namespace broker { + +class SessionHandlerImpl; + +/** + * 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(); + ~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, u_int32_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(); + + private: + typedef std::map QueueMap; + QueueMap queues; + qpid::concurrent::MonitorImpl lock; + int counter; + +}; + + +} +} + + +#endif diff --git a/cpp/src/qpid/broker/Router.cpp b/cpp/src/qpid/broker/Router.cpp new file mode 100644 index 0000000000..6a81816aea --- /dev/null +++ b/cpp/src/qpid/broker/Router.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 "./qpid/broker/Router.h" + +using namespace qpid::broker; + +Router::Router(ExchangeRegistry& _registry) : registry(_registry){} + +void Router::operator()(Message::shared_ptr& msg){ + Exchange* exchange = registry.get(msg->getExchange()); + if(exchange){ + exchange->route(msg, msg->getRoutingKey(), &(msg->getHeaderProperties()->getHeaders())); + }else{ + std::cout << "WARNING: Could not route message, unknown exchange: " << msg->getExchange() << std::endl; + } + +} diff --git a/cpp/src/qpid/broker/Router.h b/cpp/src/qpid/broker/Router.h new file mode 100644 index 0000000000..23739e6527 --- /dev/null +++ b/cpp/src/qpid/broker/Router.h @@ -0,0 +1,39 @@ +/* + * + * 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. + * + */ +#ifndef _Router_ +#define _Router_ + +#include "./qpid/broker/ExchangeRegistry.h" +#include "./qpid/broker/Message.h" + +/** + * A routing functor + */ +namespace qpid { + namespace broker { + class Router{ + ExchangeRegistry& registry; + public: + Router(ExchangeRegistry& registry); + void operator()(Message::shared_ptr& msg); + }; + } +} + + +#endif diff --git a/cpp/src/qpid/broker/SessionHandlerFactoryImpl.cpp b/cpp/src/qpid/broker/SessionHandlerFactoryImpl.cpp new file mode 100644 index 0000000000..8afff976e1 --- /dev/null +++ b/cpp/src/qpid/broker/SessionHandlerFactoryImpl.cpp @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/SessionHandlerFactoryImpl.h" +#include "./qpid/broker/SessionHandlerImpl.h" +#include "./qpid/broker/FanOutExchange.h" +#include "./qpid/broker/HeadersExchange.h" + +using namespace qpid::broker; +using namespace qpid::io; + +namespace +{ +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"); +} + +SessionHandlerFactoryImpl::SessionHandlerFactoryImpl(u_int32_t _timeout) : timeout(_timeout), cleaner(&queues, timeout/10){ + exchanges.declare(new DirectExchange(empty)); // Default exchange. + exchanges.declare(new DirectExchange(amq_direct)); + exchanges.declare(new TopicExchange(amq_topic)); + exchanges.declare(new FanOutExchange(amq_fanout)); + exchanges.declare(new HeadersExchange(amq_match)); + cleaner.start(); +} + +SessionHandler* SessionHandlerFactoryImpl::create(SessionContext* ctxt){ + return new SessionHandlerImpl(ctxt, &queues, &exchanges, &cleaner, timeout); +} + +SessionHandlerFactoryImpl::~SessionHandlerFactoryImpl(){ + cleaner.stop(); +} diff --git a/cpp/src/qpid/broker/SessionHandlerFactoryImpl.h b/cpp/src/qpid/broker/SessionHandlerFactoryImpl.h new file mode 100644 index 0000000000..2875cf63e6 --- /dev/null +++ b/cpp/src/qpid/broker/SessionHandlerFactoryImpl.h @@ -0,0 +1,49 @@ +/* + * + * 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. + * + */ +#ifndef _SessionHandlerFactoryImpl_ +#define _SessionHandlerFactoryImpl_ + +#include "./qpid/framing/AMQFrame.h" +#include "./qpid/broker/AutoDelete.h" +#include "./qpid/broker/DirectExchange.h" +#include "./qpid/broker/ExchangeRegistry.h" +#include "./qpid/framing/ProtocolInitiation.h" +#include "./qpid/broker/QueueRegistry.h" +#include "./qpid/io/SessionHandlerFactory.h" +#include "./qpid/io/TimeoutHandler.h" + +namespace qpid { + namespace broker { + + class SessionHandlerFactoryImpl : public virtual qpid::io::SessionHandlerFactory + { + QueueRegistry queues; + ExchangeRegistry exchanges; + const u_int32_t timeout;//timeout for auto-deleted queues (in ms) + AutoDelete cleaner; + public: + SessionHandlerFactoryImpl(u_int32_t timeout = 30000); + virtual qpid::io::SessionHandler* create(qpid::io::SessionContext* ctxt); + virtual ~SessionHandlerFactoryImpl(); + }; + + } +} + + +#endif diff --git a/cpp/src/qpid/broker/SessionHandlerImpl.cpp b/cpp/src/qpid/broker/SessionHandlerImpl.cpp new file mode 100644 index 0000000000..49d43d8f8b --- /dev/null +++ b/cpp/src/qpid/broker/SessionHandlerImpl.cpp @@ -0,0 +1,405 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include "./qpid/broker/SessionHandlerImpl.h" +#include "./qpid/broker/FanOutExchange.h" +#include "./qpid/broker/HeadersExchange.h" +#include "./qpid/broker/Router.h" +#include "./qpid/broker/TopicExchange.h" +#include "assert.h" + +using namespace std::tr1; +using namespace qpid::broker; +using namespace qpid::io; +using namespace qpid::framing; +using namespace qpid::concurrent; + +SessionHandlerImpl::SessionHandlerImpl(SessionContext* _context, + QueueRegistry* _queues, + ExchangeRegistry* _exchanges, + AutoDelete* _cleaner, + const u_int32_t _timeout) : + context(_context), + client(context), + queues(_queues), + exchanges(_exchanges), + cleaner(_cleaner), + timeout(_timeout), + connectionHandler(new ConnectionHandlerImpl(this)), + channelHandler(new ChannelHandlerImpl(this)), + basicHandler(new BasicHandlerImpl(this)), + exchangeHandler(new ExchangeHandlerImpl(this)), + queueHandler(new QueueHandlerImpl(this)), + framemax(65536), + heartbeat(0) {} + +SessionHandlerImpl::~SessionHandlerImpl(){ + // TODO aconway 2006-09-07: Should be auto_ptr or plain members. + delete channelHandler; + delete connectionHandler; + delete basicHandler; + delete exchangeHandler; + delete queueHandler; +} + +Channel* SessionHandlerImpl::getChannel(u_int16_t channel){ + channel_iterator i = channels.find(channel); + if(i == channels.end()){ + throw ConnectionException(504, "Unknown channel: " + channel); + } + return i->second; +} + +Queue::shared_ptr SessionHandlerImpl::getQueue(const string& name, u_int16_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 = queues->find(name); + if (queue == 0) { + throw ChannelException( 404, "Queue not found: " + name); + } + } + return queue; +} + + +Exchange* SessionHandlerImpl::findExchange(const string& name){ + exchanges->getLock()->acquire(); + Exchange* exchange(exchanges->get(name)); + exchanges->getLock()->release(); + return exchange; +} + +void SessionHandlerImpl::received(qpid::framing::AMQFrame* frame){ + u_int16_t channel = frame->getChannel(); + AMQBody::shared_ptr body = frame->getBody(); + AMQMethodBody::shared_ptr method; + + switch(body->type()) + { + case METHOD_BODY: + method = dynamic_pointer_cast(body); + try{ + method->invoke(*this, channel); + }catch(ChannelException& e){ + channels[channel]->close(); + channels.erase(channel); + client.getChannel().close(channel, e.code, e.text, method->amqpClassId(), method->amqpMethodId()); + }catch(ConnectionException& e){ + client.getConnection().close(0, e.code, e.text, method->amqpClassId(), method->amqpMethodId()); + } + break; + + case HEADER_BODY: + this->handleHeader(channel, dynamic_pointer_cast(body)); + break; + + case CONTENT_BODY: + this->handleContent(channel, dynamic_pointer_cast(body)); + break; + + case HEARTBEAT_BODY: + //channel must be 0 + this->handleHeartbeat(dynamic_pointer_cast(body)); + break; + } +} + +void SessionHandlerImpl::initiated(qpid::framing::ProtocolInitiation* /*header*/){ + //send connection start + FieldTable properties; + string mechanisms("PLAIN"); + string locales("en_US"); + client.getConnection().start(0, 8, 0, properties, mechanisms, locales); +} + +void SessionHandlerImpl::idleOut(){ + +} + +void SessionHandlerImpl::idleIn(){ + +} + +void SessionHandlerImpl::closed(){ + for(channel_iterator i = channels.begin(); i != channels.end(); i = channels.begin()){ + Channel* c = i->second; + channels.erase(i); + c->close(); + delete c; + } + for(queue_iterator i = exclusiveQueues.begin(); i < exclusiveQueues.end(); i = exclusiveQueues.begin()){ + string name = (*i)->getName(); + queues->destroy(name); + exclusiveQueues.erase(i); + } +} + +void SessionHandlerImpl::handleHeader(u_int16_t channel, AMQHeaderBody::shared_ptr body){ + getChannel(channel)->handleHeader(body, Router(*exchanges)); +} + +void SessionHandlerImpl::handleContent(u_int16_t channel, AMQContentBody::shared_ptr body){ + getChannel(channel)->handleContent(body, Router(*exchanges)); +} + +void SessionHandlerImpl::handleHeartbeat(AMQHeartbeatBody::shared_ptr /*body*/){ + std::cout << "SessionHandlerImpl::handleHeartbeat()" << std::endl; +} + +void SessionHandlerImpl::ConnectionHandlerImpl::startOk( + u_int16_t /*channel*/, FieldTable& /*clientProperties*/, string& /*mechanism*/, + string& /*response*/, string& /*locale*/){ + + parent->client.getConnection().tune(0, 100, parent->framemax, parent->heartbeat); +} + +void SessionHandlerImpl::ConnectionHandlerImpl::secureOk(u_int16_t /*channel*/, string& /*response*/){} + +void SessionHandlerImpl::ConnectionHandlerImpl::tuneOk(u_int16_t /*channel*/, u_int16_t /*channelmax*/, u_int32_t framemax, u_int16_t heartbeat){ + parent->framemax = framemax; + parent->heartbeat = heartbeat; +} + +void SessionHandlerImpl::ConnectionHandlerImpl::open(u_int16_t /*channel*/, string& /*virtualHost*/, string& /*capabilities*/, bool /*insist*/){ + string knownhosts; + parent->client.getConnection().openOk(0, knownhosts); +} + +void SessionHandlerImpl::ConnectionHandlerImpl::close( + u_int16_t /*channel*/, u_int16_t /*replyCode*/, string& /*replyText*/, + u_int16_t /*classId*/, u_int16_t /*methodId*/) +{ + parent->client.getConnection().closeOk(0); + parent->context->close(); +} + +void SessionHandlerImpl::ConnectionHandlerImpl::closeOk(u_int16_t /*channel*/){ + parent->context->close(); +} + + + +void SessionHandlerImpl::ChannelHandlerImpl::open(u_int16_t channel, string& /*outOfBand*/){ + parent->channels[channel] = new Channel(parent->context, channel, parent->framemax); + parent->client.getChannel().openOk(channel); +} + +void SessionHandlerImpl::ChannelHandlerImpl::flow(u_int16_t /*channel*/, bool /*active*/){} +void SessionHandlerImpl::ChannelHandlerImpl::flowOk(u_int16_t /*channel*/, bool /*active*/){} + +void SessionHandlerImpl::ChannelHandlerImpl::close(u_int16_t channel, u_int16_t /*replyCode*/, string& /*replyText*/, + u_int16_t /*classId*/, u_int16_t /*methodId*/){ + Channel* c = parent->getChannel(channel); + if(c){ + parent->channels.erase(channel); + c->close(); + delete c; + parent->client.getChannel().closeOk(channel); + } +} + +void SessionHandlerImpl::ChannelHandlerImpl::closeOk(u_int16_t /*channel*/){} + + + +void SessionHandlerImpl::ExchangeHandlerImpl::declare(u_int16_t channel, u_int16_t /*ticket*/, string& exchange, string& type, + bool passive, bool /*durable*/, bool /*autoDelete*/, bool /*internal*/, bool nowait, + FieldTable& /*arguments*/){ + + if(!passive && ( + type != TopicExchange::typeName && + type != DirectExchange::typeName && + type != FanOutExchange::typeName && + type != HeadersExchange::typeName + ) + ) + { + throw ChannelException(540, "Exchange type not implemented: " + type); + } + + parent->exchanges->getLock()->acquire(); + if(!parent->exchanges->get(exchange)){ + if(type == TopicExchange::typeName){ + parent->exchanges->declare(new TopicExchange(exchange)); + }else if(type == DirectExchange::typeName){ + parent->exchanges->declare(new DirectExchange(exchange)); + }else if(type == FanOutExchange::typeName){ + parent->exchanges->declare(new DirectExchange(exchange)); + }else if (type == HeadersExchange::typeName) { + parent->exchanges->declare(new HeadersExchange(exchange)); + } + } + parent->exchanges->getLock()->release(); + if(!nowait){ + parent->client.getExchange().declareOk(channel); + } +} + +void SessionHandlerImpl::ExchangeHandlerImpl::delete_(u_int16_t channel, u_int16_t /*ticket*/, string& exchange, bool /*ifUnused*/, bool nowait){ + //TODO: implement unused + parent->exchanges->getLock()->acquire(); + parent->exchanges->destroy(exchange); + parent->exchanges->getLock()->release(); + if(!nowait) parent->client.getExchange().deleteOk(channel); +} + +void SessionHandlerImpl::QueueHandlerImpl::declare(u_int16_t channel, u_int16_t /*ticket*/, string& name, + bool passive, bool durable, bool exclusive, + bool autoDelete, bool nowait, FieldTable& /*arguments*/){ + Queue::shared_ptr queue; + if (passive && !name.empty()) { + queue = parent->getQueue(name, channel); + } else { + std::pair queue_created = parent->queues->declare(name, durable, autoDelete ? parent->timeout : 0, exclusive ? parent : 0); + queue = queue_created.first; + assert(queue); + if (queue_created.second) { // This is a new queue + parent->getChannel(channel)->setDefaultQueue(queue); + //add default binding: + parent->exchanges->getDefault()->bind(queue, name, 0); + if(exclusive){ + parent->exclusiveQueues.push_back(queue); + } else if(autoDelete){ + parent->cleaner->add(queue); + } + } + } + if(exclusive && !queue->isExclusiveOwner(parent)){ + throw ChannelException(405, "Cannot grant exclusive access to queue"); + } + if(!nowait){ + name = queue->getName(); + parent->client.getQueue().declareOk(channel, name, queue->getMessageCount(), queue->getConsumerCount()); + } +} + +void SessionHandlerImpl::QueueHandlerImpl::bind(u_int16_t channel, u_int16_t /*ticket*/, string& queueName, + string& exchangeName, string& routingKey, bool nowait, + FieldTable& arguments){ + + Queue::shared_ptr queue = parent->getQueue(queueName, channel); + Exchange* exchange = parent->exchanges->get(exchangeName); + if(exchange){ + if(routingKey.empty() && queueName.empty()) routingKey = queue->getName(); + exchange->bind(queue, routingKey, &arguments); + if(!nowait) parent->client.getQueue().bindOk(channel); + }else{ + throw ChannelException(404, "Bind failed. No such exchange: " + exchangeName); + } +} + +void SessionHandlerImpl::QueueHandlerImpl::purge(u_int16_t channel, u_int16_t /*ticket*/, string& queueName, bool nowait){ + + Queue::shared_ptr queue = parent->getQueue(queueName, channel); + int count = queue->purge(); + if(!nowait) parent->client.getQueue().purgeOk(channel, count); +} + +void SessionHandlerImpl::QueueHandlerImpl::delete_(u_int16_t channel, u_int16_t /*ticket*/, string& queue, + bool ifUnused, bool ifEmpty, bool nowait){ + ChannelException error(0, ""); + int count(0); + Queue::shared_ptr q = parent->getQueue(queue, channel); + 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(parent)){ + queue_iterator i = find(parent->exclusiveQueues.begin(), parent->exclusiveQueues.end(), q); + if(i < parent->exclusiveQueues.end()) parent->exclusiveQueues.erase(i); + } + count = q->getMessageCount(); + parent->queues->destroy(queue); + } + if(!nowait) parent->client.getQueue().deleteOk(channel, count); +} + + + + +void SessionHandlerImpl::BasicHandlerImpl::qos(u_int16_t channel, u_int32_t prefetchSize, u_int16_t prefetchCount, bool /*global*/){ + //TODO: handle global + parent->getChannel(channel)->setPrefetchSize(prefetchSize); + parent->getChannel(channel)->setPrefetchCount(prefetchCount); + parent->client.getBasic().qosOk(channel); +} + +void SessionHandlerImpl::BasicHandlerImpl::consume(u_int16_t channelId, u_int16_t /*ticket*/, + string& queueName, string& consumerTag, + bool noLocal, bool noAck, bool exclusive, + bool nowait){ + + Queue::shared_ptr queue = parent->getQueue(queueName, channelId); + Channel* channel = parent->channels[channelId]; + if(!consumerTag.empty() && channel->exists(consumerTag)){ + throw ConnectionException(530, "Consumer tags must be unique"); + } + + try{ + channel->consume(consumerTag, queue, !noAck, exclusive, noLocal ? parent : 0); + if(!nowait) parent->client.getBasic().consumeOk(channelId, consumerTag); + + //allow messages to be dispatched if required as there is now a consumer: + queue->dispatch(); + }catch(ExclusiveAccessException& e){ + if(exclusive) throw ChannelException(403, "Exclusive access cannot be granted"); + else throw ChannelException(403, "Access would violate previously granted exclusivity"); + } + +} + +void SessionHandlerImpl::BasicHandlerImpl::cancel(u_int16_t channel, string& consumerTag, bool nowait){ + parent->getChannel(channel)->cancel(consumerTag); + if(!nowait) parent->client.getBasic().cancelOk(channel, consumerTag); +} + +void SessionHandlerImpl::BasicHandlerImpl::publish(u_int16_t channel, u_int16_t /*ticket*/, + string& exchange, string& routingKey, + bool mandatory, bool immediate){ + + Message* msg = new Message(parent, exchange, routingKey, mandatory, immediate); + parent->getChannel(channel)->handlePublish(msg); +} + +void SessionHandlerImpl::BasicHandlerImpl::get(u_int16_t channelId, u_int16_t /*ticket*/, string& queueName, bool noAck){ + Queue::shared_ptr queue = parent->getQueue(queueName, channelId); + if(!parent->getChannel(channelId)->get(queue, !noAck)){ + string clusterId;//not used, part of an imatix hack + parent->client.getBasic().getEmpty(channelId, clusterId); + } +} + +void SessionHandlerImpl::BasicHandlerImpl::ack(u_int16_t channel, u_int64_t deliveryTag, bool multiple){ + try{ + parent->getChannel(channel)->ack(deliveryTag, multiple); + }catch(InvalidAckException& e){ + throw ConnectionException(530, "Received ack for unrecognised delivery tag"); + } +} + +void SessionHandlerImpl::BasicHandlerImpl::reject(u_int16_t /*channel*/, u_int64_t /*deliveryTag*/, bool /*requeue*/){} + +void SessionHandlerImpl::BasicHandlerImpl::recover(u_int16_t channel, bool requeue){ + parent->getChannel(channel)->recover(requeue); +} + diff --git a/cpp/src/qpid/broker/SessionHandlerImpl.h b/cpp/src/qpid/broker/SessionHandlerImpl.h new file mode 100644 index 0000000000..09a4a67e66 --- /dev/null +++ b/cpp/src/qpid/broker/SessionHandlerImpl.h @@ -0,0 +1,233 @@ +/* + * + * 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. + * + */ +#ifndef _SessionHandlerImpl_ +#define _SessionHandlerImpl_ + +#include +#include +#include +#include +#include "./qpid/framing/AMQFrame.h" +#include "qpid/framing/AMQP_ClientProxy.h" +#include "qpid/framing/AMQP_ServerOperations.h" +#include "./qpid/broker/AutoDelete.h" +#include "./qpid/broker/ExchangeRegistry.h" +#include "./qpid/broker/Channel.h" +#include "./qpid/broker/ConnectionToken.h" +#include "./qpid/broker/DirectExchange.h" +#include "./qpid/framing/OutputHandler.h" +#include "./qpid/framing/ProtocolInitiation.h" +#include "./qpid/broker/QueueRegistry.h" +#include "./qpid/io/SessionContext.h" +#include "./qpid/io/SessionHandler.h" +#include "./qpid/io/TimeoutHandler.h" +#include "./qpid/broker/TopicExchange.h" + +namespace qpid { +namespace broker { + +struct ChannelException : public std::exception { + u_int16_t code; + string text; + ChannelException(u_int16_t _code, string _text) : code(_code), text(_text) {} + ~ChannelException() throw() {} + const char* what() const throw() { return text.c_str(); } +}; + +struct ConnectionException : public std::exception { + u_int16_t code; + string text; + ConnectionException(u_int16_t _code, string _text) : code(_code), text(_text) {} + ~ConnectionException() throw() {} + const char* what() const throw() { return text.c_str(); } +}; + +class SessionHandlerImpl : public virtual qpid::io::SessionHandler, + public virtual qpid::framing::AMQP_ServerOperations, + public virtual ConnectionToken +{ + typedef std::map::iterator channel_iterator; + typedef std::vector::iterator queue_iterator; + + qpid::io::SessionContext* context; + qpid::framing::AMQP_ClientProxy client; + QueueRegistry* queues; + ExchangeRegistry* const exchanges; + AutoDelete* const cleaner; + const u_int32_t timeout;//timeout for auto-deleted queues (in ms) + + ConnectionHandler* connectionHandler; + ChannelHandler* channelHandler; + BasicHandler* basicHandler; + ExchangeHandler* exchangeHandler; + QueueHandler* queueHandler; + + std::map channels; + std::vector exclusiveQueues; + + u_int32_t framemax; + u_int16_t heartbeat; + + void handleHeader(u_int16_t channel, qpid::framing::AMQHeaderBody::shared_ptr body); + void handleContent(u_int16_t channel, qpid::framing::AMQContentBody::shared_ptr body); + void handleHeartbeat(qpid::framing::AMQHeartbeatBody::shared_ptr body); + + Channel* getChannel(u_int16_t channel); + /** + * 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 no queue specified and channel has not declared one. + */ + Queue::shared_ptr getQueue(const string& name, u_int16_t channel); + + Exchange* findExchange(const string& name); + + public: + SessionHandlerImpl(qpid::io::SessionContext* context, QueueRegistry* queues, + ExchangeRegistry* exchanges, AutoDelete* cleaner, const u_int32_t timeout); + virtual void received(qpid::framing::AMQFrame* frame); + virtual void initiated(qpid::framing::ProtocolInitiation* header); + virtual void idleOut(); + virtual void idleIn(); + virtual void closed(); + virtual ~SessionHandlerImpl(); + + class ConnectionHandlerImpl : public virtual ConnectionHandler{ + SessionHandlerImpl* parent; + public: + inline ConnectionHandlerImpl(SessionHandlerImpl* _parent) : parent(_parent) {} + + virtual void startOk(u_int16_t channel, qpid::framing::FieldTable& clientProperties, string& mechanism, + string& response, string& locale); + + virtual void secureOk(u_int16_t channel, string& response); + + virtual void tuneOk(u_int16_t channel, u_int16_t channelMax, u_int32_t frameMax, u_int16_t heartbeat); + + virtual void open(u_int16_t channel, string& virtualHost, string& capabilities, bool insist); + + virtual void close(u_int16_t channel, u_int16_t replyCode, string& replyText, u_int16_t classId, + u_int16_t methodId); + + virtual void closeOk(u_int16_t channel); + + virtual ~ConnectionHandlerImpl(){} + }; + + class ChannelHandlerImpl : public virtual ChannelHandler{ + SessionHandlerImpl* parent; + public: + inline ChannelHandlerImpl(SessionHandlerImpl* _parent) : parent(_parent) {} + + virtual void open(u_int16_t channel, string& outOfBand); + + virtual void flow(u_int16_t channel, bool active); + + virtual void flowOk(u_int16_t channel, bool active); + + virtual void close(u_int16_t channel, u_int16_t replyCode, string& replyText, + u_int16_t classId, u_int16_t methodId); + + virtual void closeOk(u_int16_t channel); + + virtual ~ChannelHandlerImpl(){} + }; + + class ExchangeHandlerImpl : public virtual ExchangeHandler{ + SessionHandlerImpl* parent; + public: + inline ExchangeHandlerImpl(SessionHandlerImpl* _parent) : parent(_parent) {} + + virtual void declare(u_int16_t channel, u_int16_t ticket, string& exchange, string& type, + bool passive, bool durable, bool autoDelete, bool internal, bool nowait, + qpid::framing::FieldTable& arguments); + + virtual void delete_(u_int16_t channel, u_int16_t ticket, string& exchange, bool ifUnused, bool nowait); + + virtual ~ExchangeHandlerImpl(){} + }; + + + class QueueHandlerImpl : public virtual QueueHandler{ + SessionHandlerImpl* parent; + public: + inline QueueHandlerImpl(SessionHandlerImpl* _parent) : parent(_parent) {} + + virtual void declare(u_int16_t channel, u_int16_t ticket, string& queue, + bool passive, bool durable, bool exclusive, + bool autoDelete, bool nowait, qpid::framing::FieldTable& arguments); + + virtual void bind(u_int16_t channel, u_int16_t ticket, string& queue, + string& exchange, string& routingKey, bool nowait, + qpid::framing::FieldTable& arguments); + + virtual void purge(u_int16_t channel, u_int16_t ticket, string& queue, + bool nowait); + + virtual void delete_(u_int16_t channel, u_int16_t ticket, string& queue, bool ifUnused, bool ifEmpty, + bool nowait); + + virtual ~QueueHandlerImpl(){} + }; + + class BasicHandlerImpl : public virtual BasicHandler{ + SessionHandlerImpl* parent; + public: + inline BasicHandlerImpl(SessionHandlerImpl* _parent) : parent(_parent) {} + + virtual void qos(u_int16_t channel, u_int32_t prefetchSize, u_int16_t prefetchCount, bool global); + + virtual void consume(u_int16_t channel, u_int16_t ticket, string& queue, string& consumerTag, + bool noLocal, bool noAck, bool exclusive, bool nowait); + + virtual void cancel(u_int16_t channel, string& consumerTag, bool nowait); + + virtual void publish(u_int16_t channel, u_int16_t ticket, string& exchange, string& routingKey, + bool mandatory, bool immediate); + + virtual void get(u_int16_t channel, u_int16_t ticket, string& queue, bool noAck); + + virtual void ack(u_int16_t channel, u_int64_t deliveryTag, bool multiple); + + virtual void reject(u_int16_t channel, u_int64_t deliveryTag, bool requeue); + + virtual void recover(u_int16_t channel, bool requeue); + + virtual ~BasicHandlerImpl(){} + }; + + inline virtual ChannelHandler* getChannelHandler(){ return channelHandler; } + inline virtual ConnectionHandler* getConnectionHandler(){ return connectionHandler; } + inline virtual BasicHandler* getBasicHandler(){ return basicHandler; } + inline virtual ExchangeHandler* getExchangeHandler(){ return exchangeHandler; } + inline virtual QueueHandler* getQueueHandler(){ return queueHandler; } + + inline virtual AccessHandler* getAccessHandler(){ return 0; } + inline virtual FileHandler* getFileHandler(){ return 0; } + inline virtual StreamHandler* getStreamHandler(){ return 0; } + inline virtual TxHandler* getTxHandler(){ return 0; } + inline virtual DtxHandler* getDtxHandler(){ return 0; } + inline virtual TunnelHandler* getTunnelHandler(){ return 0; } +}; + +} +} + + +#endif diff --git a/cpp/src/qpid/broker/TopicExchange.cpp b/cpp/src/qpid/broker/TopicExchange.cpp new file mode 100644 index 0000000000..2affa6057d --- /dev/null +++ b/cpp/src/qpid/broker/TopicExchange.cpp @@ -0,0 +1,163 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "./qpid/broker/TopicExchange.h" +#include "./qpid/broker/ExchangeBinding.h" +#include + +using namespace qpid::broker; +using namespace qpid::framing; + + +// 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; +} + +size_t Tokens::Hash::operator()(const Tokens& p) const { + size_t hash = 0; + for (Tokens::const_iterator i = p.begin(); i != p.end(); ++i) { + hash += std::tr1::hash()(*i); + } + return hash; +} + +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 more efficient Tokens impl that can operate on a string in place. +// +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, FieldTable* args){ + lock.acquire(); + TopicPattern routingPattern(routingKey); + bindings[routingPattern].push_back(queue); + queue->bound(new ExchangeBinding(this, queue, routingKey, args)); + lock.release(); +} + +void TopicExchange::unbind(Queue::shared_ptr queue, const string& routingKey, FieldTable* /*args*/){ + lock.acquire(); + 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); + lock.release(); +} + + +void TopicExchange::route(Message::shared_ptr& msg, const string& routingKey, FieldTable* /*args*/){ + lock.acquire(); + 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++){ + (*j)->deliver(msg); + } + } + } + lock.release(); +} + +TopicExchange::~TopicExchange() {} + +const std::string TopicExchange::typeName("topic"); + + diff --git a/cpp/src/qpid/broker/TopicExchange.h b/cpp/src/qpid/broker/TopicExchange.h new file mode 100644 index 0000000000..8bad7aab4c --- /dev/null +++ b/cpp/src/qpid/broker/TopicExchange.h @@ -0,0 +1,94 @@ +/* + * + * 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. + * + */ +#ifndef _TopicExchange_ +#define _TopicExchange_ + +#include +#include +#include "./qpid/broker/Exchange.h" +#include "./qpid/framing/FieldTable.h" +#include "./qpid/broker/Message.h" +#include "./qpid/concurrent/MonitorImpl.h" +#include "./qpid/broker/Queue.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); } + /** Tokenize s */ + Tokens & operator=(const std::string& s); + + struct Hash { size_t operator()(const Tokens&) const; }; + typedef std::equal_to Equal; +}; + +/** + * 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::tr1::unordered_map BindingMap; + BindingMap bindings; + qpid::concurrent::MonitorImpl lock; + + public: + static const std::string typeName; + + TopicExchange(const string& name); + + virtual void bind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args); + + virtual void unbind(Queue::shared_ptr queue, const string& routingKey, qpid::framing::FieldTable* args); + + virtual void route(Message::shared_ptr& msg, const string& routingKey, qpid::framing::FieldTable* args); + + virtual ~TopicExchange(); +}; + + + +} +} + +#endif diff --git a/cpp/src/qpid/client/Channel.cpp b/cpp/src/qpid/client/Channel.cpp new file mode 100644 index 0000000000..0563dbaaba --- /dev/null +++ b/cpp/src/qpid/client/Channel.cpp @@ -0,0 +1,438 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/client/Channel.h" +#include "qpid/concurrent/MonitorImpl.h" +#include "qpid/concurrent/ThreadFactoryImpl.h" +#include "qpid/client/Message.h" +#include "qpid/QpidError.h" + +using namespace std::tr1;//to use dynamic_pointer_cast +using namespace qpid::client; +using namespace qpid::framing; +using namespace qpid::concurrent; + +Channel::Channel(bool _transactional, u_int16_t _prefetch) : + id(0), + con(0), + dispatcher(0), + out(0), + incoming(0), + closed(true), + prefetch(_prefetch), + transactional(_transactional) +{ + threadFactory = new ThreadFactoryImpl(); + dispatchMonitor = new MonitorImpl(); + retrievalMonitor = new MonitorImpl(); +} + +Channel::~Channel(){ + if(dispatcher){ + stop(); + delete dispatcher; + } + delete retrievalMonitor; + delete dispatchMonitor; + delete threadFactory; +} + +void Channel::setPrefetch(u_int16_t _prefetch){ + prefetch = _prefetch; + if(con != 0 && out != 0){ + setQos(); + } +} + +void Channel::setQos(){ + sendAndReceive(new AMQFrame(id, new BasicQosBody(0, prefetch, false)), basic_qos_ok); + if(transactional){ + sendAndReceive(new AMQFrame(id, new TxSelectBody()), tx_select_ok); + } +} + +void Channel::declareExchange(Exchange& exchange, bool synch){ + string name = exchange.getName(); + string type = exchange.getType(); + FieldTable args; + AMQFrame* frame = new AMQFrame(id, new ExchangeDeclareBody(0, name, type, false, false, false, false, !synch, args)); + if(synch){ + sendAndReceive(frame, exchange_declare_ok); + }else{ + out->send(frame); + } +} + +void Channel::deleteExchange(Exchange& exchange, bool synch){ + string name = exchange.getName(); + AMQFrame* frame = new AMQFrame(id, new ExchangeDeleteBody(0, name, false, !synch)); + if(synch){ + sendAndReceive(frame, exchange_delete_ok); + }else{ + out->send(frame); + } +} + +void Channel::declareQueue(Queue& queue, bool synch){ + string name = queue.getName(); + FieldTable args; + AMQFrame* frame = new AMQFrame(id, new QueueDeclareBody(0, name, false, false, + queue.isExclusive(), + queue.isAutoDelete(), !synch, args)); + if(synch){ + sendAndReceive(frame, queue_declare_ok); + if(queue.getName().length() == 0){ + QueueDeclareOkBody::shared_ptr response = + dynamic_pointer_cast(responses.getResponse()); + queue.setName(response->getQueue()); + } + }else{ + out->send(frame); + } +} + +void Channel::deleteQueue(Queue& queue, bool ifunused, bool ifempty, bool synch){ + //ticket, queue, ifunused, ifempty, nowait + string name = queue.getName(); + AMQFrame* frame = new AMQFrame(id, new QueueDeleteBody(0, name, ifunused, ifempty, !synch)); + if(synch){ + sendAndReceive(frame, queue_delete_ok); + }else{ + out->send(frame); + } +} + +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(); + // TODO aconway 2006-10-10: not const correct, get rid of const_cast. + // + AMQFrame* frame = new AMQFrame(id, new QueueBindBody(0, q, e, key,!synch, const_cast(args))); + if(synch){ + sendAndReceive(frame, queue_bind_ok); + }else{ + out->send(frame); + } +} + +void Channel::consume(Queue& queue, std::string& tag, MessageListener* listener, + int ackMode, bool noLocal, bool synch){ + + string q = queue.getName(); + AMQFrame* frame = new AMQFrame(id, new BasicConsumeBody(0, q, (string&) tag, noLocal, ackMode == NO_ACK, false, !synch)); + if(synch){ + sendAndReceive(frame, basic_consume_ok); + BasicConsumeOkBody::shared_ptr response = dynamic_pointer_cast(responses.getResponse()); + tag = response->getConsumerTag(); + }else{ + out->send(frame); + } + Consumer* c = new Consumer(); + c->listener = listener; + c->ackMode = ackMode; + c->lastDeliveryTag = 0; + consumers[tag] = c; +} + +void Channel::cancel(std::string& tag, bool synch){ + Consumer* c = consumers[tag]; + if(c->ackMode == LAZY_ACK && c->lastDeliveryTag > 0){ + out->send(new AMQFrame(id, new BasicAckBody(c->lastDeliveryTag, true))); + } + + AMQFrame* frame = new AMQFrame(id, new BasicCancelBody((string&) tag, !synch)); + if(synch){ + sendAndReceive(frame, basic_cancel_ok); + }else{ + out->send(frame); + } + consumers.erase(tag); + if(c != 0){ + delete c; + } +} + +void Channel::cancelAll(){ + for(consumer_iterator i = consumers.begin(); i != consumers.end(); i = consumers.begin()){ + Consumer* c = i->second; + if((c->ackMode == LAZY_ACK || c->ackMode == AUTO_ACK) && c->lastDeliveryTag > 0){ + out->send(new AMQFrame(id, new BasicAckBody(c->lastDeliveryTag, true))); + } + consumers.erase(i); + delete c; + } +} + +void Channel::retrieve(Message& msg){ + retrievalMonitor->acquire(); + while(retrieved == 0){ + retrievalMonitor->wait(); + } + + msg.header = retrieved->getHeader(); + msg.deliveryTag = retrieved->getDeliveryTag(); + retrieved->getData(msg.data); + delete retrieved; + retrieved = 0; + + retrievalMonitor->release(); +} + +bool Channel::get(Message& msg, const Queue& queue, int ackMode){ + string name = queue.getName(); + AMQFrame* frame = new AMQFrame(id, new BasicGetBody(0, name, ackMode)); + responses.expect(); + out->send(frame); + responses.waitForResponse(); + AMQMethodBody::shared_ptr response = responses.getResponse(); + if(basic_get_ok.match(response.get())){ + if(incoming != 0){ + std::cout << "Existing message not complete" << std::endl; + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Existing message not complete"); + }else{ + incoming = new IncomingMessage(dynamic_pointer_cast(response)); + } + retrieve(msg); + return true; + }if(basic_get_empty.match(response.get())){ + return false; + }else{ + THROW_QPID_ERROR(PROTOCOL_ERROR + 500, "Unexpected response to basic.get."); + } +} + + +void Channel::publish(Message& msg, const Exchange& exchange, const std::string& routingKey, bool mandatory, bool immediate){ + string e = exchange.getName(); + string key = routingKey; + + out->send(new AMQFrame(id, new BasicPublishBody(0, e, key, mandatory, immediate))); + //break msg up into header frame and content frame(s) and send these + string data = msg.getData(); + msg.header->setContentSize(data.length()); + AMQBody::shared_ptr body(static_pointer_cast(msg.header)); + out->send(new AMQFrame(id, body)); + + int data_length = data.length(); + if(data_length > 0){ + //TODO fragmentation of messages, need to know max frame size for connection + int frag_size = con->getMaxFrameSize() - 4; + if(data_length < frag_size){ + out->send(new AMQFrame(id, new AMQContentBody(data))); + }else{ + int frag_count = data_length / frag_size; + for(int i = 0; i < frag_count; i++){ + int pos = i*frag_size; + int len = i < frag_count - 1 ? frag_size : data_length - pos; + string frag(data.substr(pos, len)); + out->send(new AMQFrame(id, new AMQContentBody(frag))); + } + } + } +} + +void Channel::commit(){ + AMQFrame* frame = new AMQFrame(id, new TxCommitBody()); + sendAndReceive(frame, tx_commit_ok); +} + +void Channel::rollback(){ + AMQFrame* frame = new AMQFrame(id, new TxRollbackBody()); + sendAndReceive(frame, tx_rollback_ok); +} + +void Channel::handleMethod(AMQMethodBody::shared_ptr body){ + //channel.flow, channel.close, basic.deliver, basic.return or a response to a synchronous request + if(responses.isWaiting()){ + responses.signalResponse(body); + }else if(basic_deliver.match(body.get())){ + if(incoming != 0){ + std::cout << "Existing message not complete [deliveryTag=" << incoming->getDeliveryTag() << "]" << std::endl; + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Existing message not complete"); + }else{ + incoming = new IncomingMessage(dynamic_pointer_cast(body)); + } + }else if(basic_return.match(body.get())){ + if(incoming != 0){ + std::cout << "Existing message not complete" << std::endl; + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Existing message not complete"); + }else{ + incoming = new IncomingMessage(dynamic_pointer_cast(body)); + } + }else if(channel_close.match(body.get())){ + con->removeChannel(this); + //need to signal application that channel has been closed through exception + + }else if(channel_flow.match(body.get())){ + + }else{ + //signal error + std::cout << "Unhandled method: " << *body << std::endl; + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Unhandled method"); + } +} + +void Channel::handleHeader(AMQHeaderBody::shared_ptr body){ + if(incoming == 0){ + //handle invalid frame sequence + std::cout << "Invalid message sequence: got header before return or deliver." << std::endl; + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got header before return or deliver."); + }else{ + incoming->setHeader(body); + if(incoming->isComplete()){ + enqueue(); + } + } +} + +void Channel::handleContent(AMQContentBody::shared_ptr body){ + if(incoming == 0){ + //handle invalid frame sequence + std::cout << "Invalid message sequence: got content before return or deliver." << std::endl; + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Invalid message sequence: got content before return or deliver."); + }else{ + incoming->addContent(body); + if(incoming->isComplete()){ + enqueue(); + } + } +} + +void Channel::handleHeartbeat(AMQHeartbeatBody::shared_ptr /*body*/){ + THROW_QPID_ERROR(PROTOCOL_ERROR + 504, "Channel received heartbeat"); +} + +void Channel::start(){ + dispatcher = threadFactory->create(this); + dispatcher->start(); +} + +void Channel::stop(){ + closed = true; + dispatchMonitor->acquire(); + dispatchMonitor->notify(); + dispatchMonitor->release(); + if(dispatcher){ + dispatcher->join(); + } +} + +void Channel::run(){ + dispatch(); +} + +void Channel::enqueue(){ + if(incoming->isResponse()){ + retrievalMonitor->acquire(); + retrieved = incoming; + retrievalMonitor->notify(); + retrievalMonitor->release(); + }else{ + dispatchMonitor->acquire(); + messages.push(incoming); + dispatchMonitor->notify(); + dispatchMonitor->release(); + } + incoming = 0; +} + +IncomingMessage* Channel::dequeue(){ + dispatchMonitor->acquire(); + while(messages.empty() && !closed){ + dispatchMonitor->wait(); + } + IncomingMessage* msg = 0; + if(!messages.empty()){ + msg = messages.front(); + messages.pop(); + } + dispatchMonitor->release(); + return msg; +} + +void Channel::deliver(Consumer* consumer, Message& msg){ + //record delivery tag: + consumer->lastDeliveryTag = msg.getDeliveryTag(); + + //allow registered listener to handle the message + consumer->listener->received(msg); + + //if the handler calls close on the channel or connection while + //handling this message, then consumer will now have been deleted. + if(!closed){ + bool multiple(false); + switch(consumer->ackMode){ + case LAZY_ACK: + multiple = true; + if(++(consumer->count) < prefetch) break; + //else drop-through + case AUTO_ACK: + out->send(new AMQFrame(id, new BasicAckBody(msg.getDeliveryTag(), multiple))); + consumer->lastDeliveryTag = 0; + } + } + + //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 Channel::dispatch(){ + while(!closed){ + IncomingMessage* incomingMsg = dequeue(); + if(incomingMsg){ + //Note: msg is currently only valid for duration of this call + Message msg(incomingMsg->getHeader()); + incomingMsg->getData(msg.data); + if(incomingMsg->isReturn()){ + if(returnsHandler == 0){ + //print warning to log/console + std::cout << "Message returned: " << msg.getData() << std::endl; + }else{ + returnsHandler->returned(msg); + } + }else{ + msg.deliveryTag = incomingMsg->getDeliveryTag(); + std::string tag = incomingMsg->getConsumerTag(); + + if(consumers[tag] == 0){ + //signal error + std::cout << "Unknown consumer: " << tag << std::endl; + }else{ + deliver(consumers[tag], msg); + } + } + delete incomingMsg; + } + } +} + +void Channel::setReturnedMessageHandler(ReturnedMessageHandler* handler){ + returnsHandler = handler; +} + +void Channel::sendAndReceive(AMQFrame* frame, const AMQMethodBody& body){ + responses.expect(); + out->send(frame); + responses.receive(body); +} + +void Channel::close(){ + if(con != 0){ + con->closeChannel(this); + } +} diff --git a/cpp/src/qpid/client/Channel.h b/cpp/src/qpid/client/Channel.h new file mode 100644 index 0000000000..0b60a827b7 --- /dev/null +++ b/cpp/src/qpid/client/Channel.h @@ -0,0 +1,127 @@ +/* + * + * 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 "sys/types.h" + +#ifndef _Channel_ +#define _Channel_ + +#include "qpid/framing/amqp_framing.h" + +#include "qpid/concurrent/ThreadFactory.h" + +#include "qpid/client/Connection.h" +#include "qpid/client/Exchange.h" +#include "qpid/client/IncomingMessage.h" +#include "qpid/client/Message.h" +#include "qpid/client/MessageListener.h" +#include "qpid/client/Queue.h" +#include "qpid/client/ResponseHandler.h" +#include "qpid/client/ReturnedMessageHandler.h" + +namespace qpid { +namespace client { + enum ack_modes {NO_ACK=0, AUTO_ACK=1, LAZY_ACK=2, CLIENT_ACK=3}; + + class Channel : private virtual qpid::framing::BodyHandler, public virtual qpid::concurrent::Runnable{ + struct Consumer{ + MessageListener* listener; + int ackMode; + int count; + u_int64_t lastDeliveryTag; + }; + typedef std::map::iterator consumer_iterator; + + u_int16_t id; + Connection* con; + qpid::concurrent::ThreadFactory* threadFactory; + qpid::concurrent::Thread* dispatcher; + qpid::framing::OutputHandler* out; + IncomingMessage* incoming; + ResponseHandler responses; + std::queue messages;//holds returned messages or those delivered for a consume + IncomingMessage* retrieved;//holds response to basic.get + qpid::concurrent::Monitor* dispatchMonitor; + qpid::concurrent::Monitor* retrievalMonitor; + std::map consumers; + ReturnedMessageHandler* returnsHandler; + bool closed; + + u_int16_t prefetch; + const bool transactional; + + void enqueue(); + void retrieve(Message& msg); + IncomingMessage* dequeue(); + void dispatch(); + void stop(); + void sendAndReceive(qpid::framing::AMQFrame* frame, const qpid::framing::AMQMethodBody& body); + void deliver(Consumer* consumer, Message& msg); + void setQos(); + void cancelAll(); + + virtual void handleMethod(qpid::framing::AMQMethodBody::shared_ptr body); + virtual void handleHeader(qpid::framing::AMQHeaderBody::shared_ptr body); + virtual void handleContent(qpid::framing::AMQContentBody::shared_ptr body); + virtual void handleHeartbeat(qpid::framing::AMQHeartbeatBody::shared_ptr body); + + public: + Channel(bool transactional = false, u_int16_t prefetch = 500); + ~Channel(); + + void declareExchange(Exchange& exchange, bool synch = true); + void deleteExchange(Exchange& exchange, bool synch = true); + void declareQueue(Queue& queue, bool synch = true); + void deleteQueue(Queue& queue, bool ifunused = false, bool ifempty = false, bool synch = true); + void bind(const Exchange& exchange, const Queue& queue, const std::string& key, + const qpid::framing::FieldTable& args, bool synch = true); + void consume(Queue& queue, std::string& tag, MessageListener* listener, + int ackMode = NO_ACK, bool noLocal = false, bool synch = true); + void cancel(std::string& tag, bool synch = true); + bool get(Message& msg, const Queue& queue, int ackMode = NO_ACK); + void publish(Message& msg, const Exchange& exchange, const std::string& routingKey, + bool mandatory = false, bool immediate = false); + + void commit(); + void rollback(); + + void setPrefetch(u_int16_t prefetch); + + /** + * Start message dispatching on a new thread + */ + void start(); + /** + * Do message dispatching on this thread + */ + void run(); + + void close(); + + void setReturnedMessageHandler(ReturnedMessageHandler* handler); + + friend class Connection; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/client/Connection.cpp b/cpp/src/qpid/client/Connection.cpp new file mode 100644 index 0000000000..779480eae9 --- /dev/null +++ b/cpp/src/qpid/client/Connection.cpp @@ -0,0 +1,237 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/client/Connection.h" +#include "qpid/client/Channel.h" +#include "qpid/io/ConnectorImpl.h" +#include "qpid/client/Message.h" +#include "qpid/QpidError.h" +#include + +using namespace qpid::client; +using namespace qpid::framing; +using namespace qpid::io; +using namespace qpid::concurrent; + +u_int16_t Connection::channelIdCounter; + +Connection::Connection(bool debug, u_int32_t _max_frame_size) : max_frame_size(_max_frame_size), closed(true){ + connector = new ConnectorImpl(debug, _max_frame_size); +} + +Connection::~Connection(){ + delete connector; +} + +void Connection::open(const std::string& _host, int _port, const std::string& uid, const std::string& pwd, const std::string& virtualhost){ + host = _host; + port = _port; + connector->setInputHandler(this); + connector->setTimeoutHandler(this); + connector->setShutdownHandler(this); + out = connector->getOutputHandler(); + connector->connect(host, port); + + ProtocolInitiation* header = new ProtocolInitiation(8, 0); + responses.expect(); + connector->init(header); + responses.receive(connection_start); + + FieldTable props; + string mechanism("PLAIN"); + string response = ((char)0) + uid + ((char)0) + pwd; + string locale("en_US"); + responses.expect(); + out->send(new AMQFrame(0, new ConnectionStartOkBody(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 + out->send(new AMQFrame(0, new ConnectionSecureOkBody(response))); + **/ + + responses.receive(connection_tune); + + ConnectionTuneBody::shared_ptr proposal = std::tr1::dynamic_pointer_cast(responses.getResponse()); + out->send(new AMQFrame(0, new ConnectionTuneOkBody(proposal->getChannelMax(), max_frame_size, proposal->getHeartbeat()))); + + u_int16_t heartbeat = proposal->getHeartbeat(); + connector->setReadTimeout(heartbeat * 2); + connector->setWriteTimeout(heartbeat); + + //send connection.open + string capabilities; + string vhost = virtualhost; + responses.expect(); + out->send(new AMQFrame(0, new ConnectionOpenBody(vhost, capabilities, true))); + //receive connection.open-ok (or redirect, but ignore that for now esp. as using force=true). + responses.waitForResponse(); + if(responses.validate(connection_open_ok)){ + //ok + }else if(responses.validate(connection_redirect)){ + //ignore for now + ConnectionRedirectBody::shared_ptr redirect(std::tr1::dynamic_pointer_cast(responses.getResponse())); + std::cout << "Received redirection to " << redirect->getHost() << std::endl; + }else{ + THROW_QPID_ERROR(PROTOCOL_ERROR, "Bad response"); + } + +} + +void Connection::close(){ + if(!closed){ + u_int16_t code(200); + string text("Ok"); + u_int16_t classId(0); + u_int16_t methodId(0); + + sendAndReceive(new AMQFrame(0, new ConnectionCloseBody(code, text, classId, methodId)), connection_close_ok); + connector->close(); + } +} + +void Connection::openChannel(Channel* channel){ + channel->con = this; + channel->id = ++channelIdCounter; + channel->out = out; + channels[channel->id] = channel; + //now send frame to open channel and wait for response + string oob; + channel->sendAndReceive(new AMQFrame(channel->id, new ChannelOpenBody(oob)), channel_open_ok); + channel->setQos(); + channel->closed = false; +} + +void Connection::closeChannel(Channel* channel){ + //send frame to close channel + u_int16_t code(200); + string text("Ok"); + u_int16_t classId(0); + u_int16_t methodId(0); + closeChannel(channel, code, text, classId, methodId); +} + +void Connection::closeChannel(Channel* channel, u_int16_t code, string& text, u_int16_t classId, u_int16_t methodId){ + //send frame to close channel + channel->cancelAll(); + channel->closed = true; + channel->sendAndReceive(new AMQFrame(channel->id, new ChannelCloseBody(code, text, classId, methodId)), channel_close_ok); + channel->con = 0; + channel->out = 0; + removeChannel(channel); +} + +void Connection::removeChannel(Channel* channel){ + //send frame to close channel + + channels.erase(channel->id); + channel->out = 0; + channel->id = 0; + channel->con = 0; +} + +void Connection::received(AMQFrame* frame){ + u_int16_t channelId = frame->getChannel(); + + if(channelId == 0){ + this->handleBody(frame->getBody()); + }else{ + Channel* channel = channels[channelId]; + if(channel == 0){ + error(504, "Unknown channel"); + }else{ + try{ + channel->handleBody(frame->getBody()); + }catch(qpid::QpidError e){ + channelException(channel, dynamic_cast(frame->getBody().get()), e); + } + } + } +} + +void Connection::handleMethod(AMQMethodBody::shared_ptr body){ + //connection.close, basic.deliver, basic.return or a response to a synchronous request + if(responses.isWaiting()){ + responses.signalResponse(body); + }else if(connection_close.match(body.get())){ + //send back close ok + //close socket + ConnectionCloseBody* request = dynamic_cast(body.get()); + std::cout << "Connection closed by server: " << request->getReplyCode() << ":" << request->getReplyText() << std::endl; + connector->close(); + }else{ + std::cout << "Unhandled method for connection: " << *body << std::endl; + error(504, "Unrecognised method", body->amqpClassId(), body->amqpMethodId()); + } +} + +void Connection::handleHeader(AMQHeaderBody::shared_ptr /*body*/){ + error(504, "Channel error: received header body with channel 0."); +} + +void Connection::handleContent(AMQContentBody::shared_ptr /*body*/){ + error(504, "Channel error: received content body with channel 0."); +} + +void Connection::handleHeartbeat(AMQHeartbeatBody::shared_ptr /*body*/){ +} + +void Connection::sendAndReceive(AMQFrame* frame, const AMQMethodBody& body){ + responses.expect(); + out->send(frame); + responses.receive(body); +} + +void Connection::error(int code, const string& msg, int classid, int methodid){ + std::cout << "Connection exception generated: " << code << msg; + if(classid || methodid){ + std::cout << " [" << methodid << ":" << classid << "]"; + } + std::cout << std::endl; + sendAndReceive(new AMQFrame(0, new ConnectionCloseBody(code, msg, classid, methodid)), connection_close_ok); + connector->close(); +} + +void Connection::channelException(Channel* channel, AMQMethodBody* method, QpidError& e){ + std::cout << "Caught error from channel [" << e.code << "] " << e.msg << " (" << e.file << ":" << e.line << ")" << std::endl; + int code = e.code == PROTOCOL_ERROR ? e.code - PROTOCOL_ERROR : 500; + string msg = e.msg; + if(method == 0){ + closeChannel(channel, code, msg); + }else{ + closeChannel(channel, code, msg, method->amqpClassId(), method->amqpMethodId()); + } +} + +void Connection::idleIn(){ + std::cout << "Connection timed out due to abscence of heartbeat." << std::endl; + connector->close(); +} + +void Connection::idleOut(){ + out->send(new AMQFrame(0, new AMQHeartbeatBody())); +} + +void Connection::shutdown(){ + closed = true; + //close all channels + for(iterator i = channels.begin(); i != channels.end(); i++){ + i->second->stop(); + } +} diff --git a/cpp/src/qpid/client/Connection.h b/cpp/src/qpid/client/Connection.h new file mode 100644 index 0000000000..0e8f52e88a --- /dev/null +++ b/cpp/src/qpid/client/Connection.h @@ -0,0 +1,105 @@ +/* + * + * 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 + +#ifndef _Connection_ +#define _Connection_ + +#include "qpid/QpidError.h" +#include "qpid/io/Connector.h" +#include "qpid/io/ShutdownHandler.h" +#include "qpid/io/TimeoutHandler.h" + +#include "qpid/framing/amqp_framing.h" +#include "qpid/client/Exchange.h" +#include "qpid/client/IncomingMessage.h" +#include "qpid/client/Message.h" +#include "qpid/client/MessageListener.h" +#include "qpid/client/Queue.h" +#include "qpid/client/ResponseHandler.h" + +namespace qpid { +namespace client { + + class Channel; + + class Connection : public virtual qpid::framing::InputHandler, + public virtual qpid::io::TimeoutHandler, + public virtual qpid::io::ShutdownHandler, + private virtual qpid::framing::BodyHandler{ + + typedef std::map::iterator iterator; + + static u_int16_t channelIdCounter; + + std::string host; + int port; + const u_int32_t max_frame_size; + std::map channels; + qpid::io::Connector* connector; + qpid::framing::OutputHandler* out; + ResponseHandler responses; + volatile bool closed; + + void channelException(Channel* channel, qpid::framing::AMQMethodBody* body, QpidError& e); + void error(int code, const string& msg, int classid = 0, int methodid = 0); + void closeChannel(Channel* channel, u_int16_t code, string& text, u_int16_t classId = 0, u_int16_t methodId = 0); + void sendAndReceive(qpid::framing::AMQFrame* frame, const qpid::framing::AMQMethodBody& body); + + virtual void handleMethod(qpid::framing::AMQMethodBody::shared_ptr body); + virtual void handleHeader(qpid::framing::AMQHeaderBody::shared_ptr body); + virtual void handleContent(qpid::framing::AMQContentBody::shared_ptr body); + virtual void handleHeartbeat(qpid::framing::AMQHeartbeatBody::shared_ptr body); + + public: + + Connection(bool debug = false, u_int32_t max_frame_size = 65536); + ~Connection(); + void open(const std::string& host, int port = 5672, + const std::string& uid = "guest", const std::string& pwd = "guest", + const std::string& virtualhost = "/"); + void close(); + void openChannel(Channel* channel); + /* + * Requests that the server close this channel, then removes + * the association to the channel from this connection + */ + void closeChannel(Channel* channel); + /* + * Removes the channel from association with this connection, + * without sending a close request to the server. + */ + void removeChannel(Channel* channel); + + virtual void received(qpid::framing::AMQFrame* frame); + + virtual void idleOut(); + virtual void idleIn(); + + virtual void shutdown(); + + inline u_int32_t getMaxFrameSize(){ return max_frame_size; } + }; + + +} +} + + +#endif diff --git a/cpp/src/qpid/client/Exchange.cpp b/cpp/src/qpid/client/Exchange.cpp new file mode 100644 index 0000000000..078f15c3a7 --- /dev/null +++ b/cpp/src/qpid/client/Exchange.cpp @@ -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. + * + */ +#include "qpid/client/Exchange.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_DIRECT_EXCHANGE("amq.direct", DIRECT_EXCHANGE); +const qpid::client::Exchange qpid::client::Exchange::DEFAULT_TOPIC_EXCHANGE("amq.topic", TOPIC_EXCHANGE); +const qpid::client::Exchange qpid::client::Exchange::DEFAULT_HEADERS_EXCHANGE("amq.headers", HEADERS_EXCHANGE); diff --git a/cpp/src/qpid/client/Exchange.h b/cpp/src/qpid/client/Exchange.h new file mode 100644 index 0000000000..66593a41cc --- /dev/null +++ b/cpp/src/qpid/client/Exchange.h @@ -0,0 +1,49 @@ +/* + * + * 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 + +#ifndef _Exchange_ +#define _Exchange_ + +namespace qpid { +namespace client { + + class Exchange{ + const std::string name; + const std::string type; + + public: + + static const std::string DIRECT_EXCHANGE; + static const std::string TOPIC_EXCHANGE; + static const std::string HEADERS_EXCHANGE; + + static const Exchange DEFAULT_DIRECT_EXCHANGE; + static const Exchange DEFAULT_TOPIC_EXCHANGE; + static const Exchange DEFAULT_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/cpp/src/qpid/client/IncomingMessage.cpp b/cpp/src/qpid/client/IncomingMessage.cpp new file mode 100644 index 0000000000..c385430a27 --- /dev/null +++ b/cpp/src/qpid/client/IncomingMessage.cpp @@ -0,0 +1,85 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/client/IncomingMessage.h" +#include "qpid/QpidError.h" +#include + +using namespace qpid::client; +using namespace qpid::framing; + +IncomingMessage::IncomingMessage(BasicDeliverBody::shared_ptr intro) : delivered(intro){} +IncomingMessage::IncomingMessage(BasicReturnBody::shared_ptr intro): returned(intro){} +IncomingMessage::IncomingMessage(BasicGetOkBody::shared_ptr intro): response(intro){} + +IncomingMessage::~IncomingMessage(){ +} + +void IncomingMessage::setHeader(AMQHeaderBody::shared_ptr _header){ + this->header = _header; +} + +void IncomingMessage::addContent(AMQContentBody::shared_ptr _content){ + this->content.push_back(_content); +} + +bool IncomingMessage::isComplete(){ + return header != 0 && header->getContentSize() == contentSize(); +} + +bool IncomingMessage::isReturn(){ + return returned; +} + +bool IncomingMessage::isDelivery(){ + return delivered; +} + +bool IncomingMessage::isResponse(){ + return response; +} + +const string& IncomingMessage::getConsumerTag(){ + if(!isDelivery()) THROW_QPID_ERROR(CLIENT_ERROR, "Consumer tag only valid for delivery"); + return delivered->getConsumerTag(); +} + +u_int64_t IncomingMessage::getDeliveryTag(){ + if(!isDelivery()) THROW_QPID_ERROR(CLIENT_ERROR, "Delivery tag only valid for delivery"); + return delivered->getDeliveryTag(); +} + +AMQHeaderBody::shared_ptr& IncomingMessage::getHeader(){ + return header; +} + +void IncomingMessage::getData(string& s){ + int count(content.size()); + for(int i = 0; i < count; i++){ + if(i == 0) s = content[i]->getData(); + else s += content[i]->getData(); + } +} + +u_int64_t IncomingMessage::contentSize(){ + u_int64_t size(0); + u_int64_t count(content.size()); + for(u_int64_t i = 0; i < count; i++){ + size += content[i]->size(); + } + return size; +} diff --git a/cpp/src/qpid/client/IncomingMessage.h b/cpp/src/qpid/client/IncomingMessage.h new file mode 100644 index 0000000000..fec620066b --- /dev/null +++ b/cpp/src/qpid/client/IncomingMessage.h @@ -0,0 +1,60 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include "qpid/framing/amqp_framing.h" + +#ifndef _IncomingMessage_ +#define _IncomingMessage_ + +#include "qpid/client/Message.h" + +namespace qpid { +namespace client { + + class IncomingMessage{ + //content will be preceded by one of these method frames + qpid::framing::BasicDeliverBody::shared_ptr delivered; + qpid::framing::BasicReturnBody::shared_ptr returned; + qpid::framing::BasicGetOkBody::shared_ptr response; + qpid::framing::AMQHeaderBody::shared_ptr header; + std::vector content; + + u_int64_t contentSize(); + public: + IncomingMessage(qpid::framing::BasicDeliverBody::shared_ptr intro); + IncomingMessage(qpid::framing::BasicReturnBody::shared_ptr intro); + IncomingMessage(qpid::framing::BasicGetOkBody::shared_ptr intro); + ~IncomingMessage(); + void setHeader(qpid::framing::AMQHeaderBody::shared_ptr header); + void addContent(qpid::framing::AMQContentBody::shared_ptr content); + bool isComplete(); + bool isReturn(); + bool isDelivery(); + bool isResponse(); + const string& getConsumerTag();//only relevant if isDelivery() + qpid::framing::AMQHeaderBody::shared_ptr& getHeader(); + u_int64_t getDeliveryTag(); + void getData(string& data); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/client/Message.cpp b/cpp/src/qpid/client/Message.cpp new file mode 100644 index 0000000000..34220b595d --- /dev/null +++ b/cpp/src/qpid/client/Message.cpp @@ -0,0 +1,147 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/client/Message.h" + +using namespace qpid::client; +using namespace qpid::framing; + +Message::Message(){ + header = AMQHeaderBody::shared_ptr(new AMQHeaderBody(BASIC)); +} + +Message::Message(AMQHeaderBody::shared_ptr& _header) : header(_header){ +} + +Message::~Message(){ +} + +BasicHeaderProperties* Message::getHeaderProperties(){ + return dynamic_cast(header->getProperties()); +} + +std::string& Message::getContentType(){ + return getHeaderProperties()->getContentType(); +} + +std::string& Message::getContentEncoding(){ + return getHeaderProperties()->getContentEncoding(); +} + +FieldTable& Message::getHeaders(){ + return getHeaderProperties()->getHeaders(); +} + +u_int8_t Message::getDeliveryMode(){ + return getHeaderProperties()->getDeliveryMode(); +} + +u_int8_t Message::getPriority(){ + return getHeaderProperties()->getPriority(); +} + +std::string& Message::getCorrelationId(){ + return getHeaderProperties()->getCorrelationId(); +} + +std::string& Message::getReplyTo(){ + return getHeaderProperties()->getReplyTo(); +} + +std::string& Message::getExpiration(){ + return getHeaderProperties()->getExpiration(); +} + +std::string& Message::getMessageId(){ + return getHeaderProperties()->getMessageId(); +} + +u_int64_t Message::getTimestamp(){ + return getHeaderProperties()->getTimestamp(); +} + +std::string& Message::getType(){ + return getHeaderProperties()->getType(); +} + +std::string& Message::getUserId(){ + return getHeaderProperties()->getUserId(); +} + +std::string& Message::getAppId(){ + return getHeaderProperties()->getAppId(); +} + +std::string& Message::getClusterId(){ + return getHeaderProperties()->getClusterId(); +} + +void Message::setContentType(std::string& type){ + getHeaderProperties()->setContentType(type); +} + +void Message::setContentEncoding(std::string& encoding){ + getHeaderProperties()->setContentEncoding(encoding); +} + +void Message::setHeaders(FieldTable& headers){ + getHeaderProperties()->setHeaders(headers); +} + +void Message::setDeliveryMode(u_int8_t mode){ + getHeaderProperties()->setDeliveryMode(mode); +} + +void Message::setPriority(u_int8_t priority){ + getHeaderProperties()->setPriority(priority); +} + +void Message::setCorrelationId(std::string& correlationId){ + getHeaderProperties()->setCorrelationId(correlationId); +} + +void Message::setReplyTo(std::string& replyTo){ + getHeaderProperties()->setReplyTo(replyTo); +} + +void Message::setExpiration(std::string& expiration){ + getHeaderProperties()->setExpiration(expiration); +} + +void Message::setMessageId(std::string& messageId){ + getHeaderProperties()->setMessageId(messageId); +} + +void Message::setTimestamp(u_int64_t timestamp){ + getHeaderProperties()->setTimestamp(timestamp); +} + +void Message::setType(std::string& type){ + getHeaderProperties()->setType(type); +} + +void Message::setUserId(std::string& userId){ + getHeaderProperties()->setUserId(userId); +} + +void Message::setAppId(std::string& appId){ + getHeaderProperties()->setAppId(appId); +} + +void Message::setClusterId(std::string& clusterId){ + getHeaderProperties()->setClusterId(clusterId); +} diff --git a/cpp/src/qpid/client/Message.h b/cpp/src/qpid/client/Message.h new file mode 100644 index 0000000000..5b1c1d5de7 --- /dev/null +++ b/cpp/src/qpid/client/Message.h @@ -0,0 +1,86 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include "qpid/framing/amqp_framing.h" + +#ifndef _Message_ +#define _Message_ + + +namespace qpid { +namespace client { + + class Message{ + qpid::framing::AMQHeaderBody::shared_ptr header; + string data; + bool redelivered; + u_int64_t deliveryTag; + + qpid::framing::BasicHeaderProperties* getHeaderProperties(); + Message(qpid::framing::AMQHeaderBody::shared_ptr& header); + public: + Message(); + ~Message(); + + inline std::string getData(){ return data; } + inline void setData(const std::string& _data){ data = _data; } + + inline bool isRedelivered(){ return redelivered; } + inline void setRedelivered(bool _redelivered){ redelivered = _redelivered; } + + inline u_int64_t getDeliveryTag(){ return deliveryTag; } + + std::string& getContentType(); + std::string& getContentEncoding(); + qpid::framing::FieldTable& getHeaders(); + u_int8_t getDeliveryMode(); + u_int8_t getPriority(); + std::string& getCorrelationId(); + std::string& getReplyTo(); + std::string& getExpiration(); + std::string& getMessageId(); + u_int64_t getTimestamp(); + std::string& getType(); + std::string& getUserId(); + std::string& getAppId(); + std::string& getClusterId(); + + void setContentType(std::string& type); + void setContentEncoding(std::string& encoding); + void setHeaders(qpid::framing::FieldTable& headers); + void setDeliveryMode(u_int8_t mode); + void setPriority(u_int8_t priority); + void setCorrelationId(std::string& correlationId); + void setReplyTo(std::string& replyTo); + void setExpiration(std::string& expiration); + void setMessageId(std::string& messageId); + void setTimestamp(u_int64_t timestamp); + void setType(std::string& type); + void setUserId(std::string& userId); + void setAppId(std::string& appId); + void setClusterId(std::string& clusterId); + + + friend class Channel; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/client/MessageListener.cpp b/cpp/src/qpid/client/MessageListener.cpp new file mode 100644 index 0000000000..f3bcb24c1a --- /dev/null +++ b/cpp/src/qpid/client/MessageListener.cpp @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qpid/client/MessageListener.h" + +qpid::client::MessageListener::~MessageListener() {} diff --git a/cpp/src/qpid/client/MessageListener.h b/cpp/src/qpid/client/MessageListener.h new file mode 100644 index 0000000000..a28e26a8d2 --- /dev/null +++ b/cpp/src/qpid/client/MessageListener.h @@ -0,0 +1,38 @@ +/* + * + * 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 + +#ifndef _MessageListener_ +#define _MessageListener_ + +#include "qpid/client/Message.h" + +namespace qpid { +namespace client { + + class MessageListener{ + public: + virtual ~MessageListener(); + virtual void received(Message& msg) = 0; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/client/Queue.cpp b/cpp/src/qpid/client/Queue.cpp new file mode 100644 index 0000000000..dc752c9fb2 --- /dev/null +++ b/cpp/src/qpid/client/Queue.cpp @@ -0,0 +1,47 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/client/Queue.h" + +qpid::client::Queue::Queue() : name(""), autodelete(true), exclusive(true){} + +qpid::client::Queue::Queue(std::string _name) : name(_name), autodelete(false), exclusive(false){} + +qpid::client::Queue::Queue(std::string _name, bool temp) : name(_name), autodelete(temp), exclusive(temp){} + +qpid::client::Queue::Queue(std::string _name, bool _autodelete, bool _exclusive) + : name(_name), autodelete(_autodelete), exclusive(_exclusive){} + +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; +} + + + + diff --git a/cpp/src/qpid/client/Queue.h b/cpp/src/qpid/client/Queue.h new file mode 100644 index 0000000000..e0964af774 --- /dev/null +++ b/cpp/src/qpid/client/Queue.h @@ -0,0 +1,47 @@ +/* + * + * 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 + +#ifndef _Queue_ +#define _Queue_ + +namespace qpid { +namespace client { + + class Queue{ + std::string name; + const bool autodelete; + const bool exclusive; + + public: + + Queue(); + Queue(std::string name); + Queue(std::string name, bool temp); + Queue(std::string name, bool autodelete, bool exclusive); + const std::string& getName() const; + void setName(const std::string&); + bool isAutoDelete() const; + bool isExclusive() const; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/client/ResponseHandler.cpp b/cpp/src/qpid/client/ResponseHandler.cpp new file mode 100644 index 0000000000..ec20dd1a10 --- /dev/null +++ b/cpp/src/qpid/client/ResponseHandler.cpp @@ -0,0 +1,63 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/client/ResponseHandler.h" +#include "qpid/concurrent/MonitorImpl.h" +#include "qpid/QpidError.h" + +qpid::client::ResponseHandler::ResponseHandler() : waiting(false){ + monitor = new qpid::concurrent::MonitorImpl(); +} + +qpid::client::ResponseHandler::~ResponseHandler(){ + delete monitor; +} + +bool qpid::client::ResponseHandler::validate(const qpid::framing::AMQMethodBody& expected){ + return expected.match(response.get()); +} + +void qpid::client::ResponseHandler::waitForResponse(){ + monitor->acquire(); + if(waiting){ + monitor->wait(); + } + monitor->release(); +} + +void qpid::client::ResponseHandler::signalResponse(qpid::framing::AMQMethodBody::shared_ptr _response){ + response = _response; + monitor->acquire(); + waiting = false; + monitor->notify(); + monitor->release(); +} + +void qpid::client::ResponseHandler::receive(const qpid::framing::AMQMethodBody& expected){ + monitor->acquire(); + if(waiting){ + monitor->wait(); + } + monitor->release(); + if(!validate(expected)){ + THROW_QPID_ERROR(PROTOCOL_ERROR, "Protocol Error"); + } +} + +void qpid::client::ResponseHandler::expect(){ + waiting = true; +} diff --git a/cpp/src/qpid/client/ResponseHandler.h b/cpp/src/qpid/client/ResponseHandler.h new file mode 100644 index 0000000000..179daa1f1f --- /dev/null +++ b/cpp/src/qpid/client/ResponseHandler.h @@ -0,0 +1,49 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include "qpid/framing/amqp_framing.h" +#include "qpid/concurrent/Monitor.h" + +#ifndef _ResponseHandler_ +#define _ResponseHandler_ + +namespace qpid { + namespace client { + + class ResponseHandler{ + bool waiting; + qpid::framing::AMQMethodBody::shared_ptr response; + qpid::concurrent::Monitor* monitor; + + public: + ResponseHandler(); + ~ResponseHandler(); + inline bool isWaiting(){ return waiting; } + inline qpid::framing::AMQMethodBody::shared_ptr getResponse(){ return response; } + bool validate(const qpid::framing::AMQMethodBody& expected); + void waitForResponse(); + void signalResponse(qpid::framing::AMQMethodBody::shared_ptr response); + void receive(const qpid::framing::AMQMethodBody& expected); + void expect();//must be called before calling receive + }; + + } +} + + +#endif diff --git a/cpp/src/qpid/client/ReturnedMessageHandler.cpp b/cpp/src/qpid/client/ReturnedMessageHandler.cpp new file mode 100644 index 0000000000..ca6fba2408 --- /dev/null +++ b/cpp/src/qpid/client/ReturnedMessageHandler.cpp @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qpid/client/ReturnedMessageHandler.h" + +qpid::client::ReturnedMessageHandler::~ReturnedMessageHandler() {} diff --git a/cpp/src/qpid/client/ReturnedMessageHandler.h b/cpp/src/qpid/client/ReturnedMessageHandler.h new file mode 100644 index 0000000000..5a4c4d5d1b --- /dev/null +++ b/cpp/src/qpid/client/ReturnedMessageHandler.h @@ -0,0 +1,38 @@ +/* + * + * 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 + +#ifndef _ReturnedMessageHandler_ +#define _ReturnedMessageHandler_ + +#include "qpid/client/Message.h" + +namespace qpid { +namespace client { + + class ReturnedMessageHandler{ + public: + virtual ~ReturnedMessageHandler(); + virtual void returned(Message& msg) = 0; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/APRBase.cpp b/cpp/src/qpid/concurrent/APRBase.cpp new file mode 100644 index 0000000000..514c4d1048 --- /dev/null +++ b/cpp/src/qpid/concurrent/APRBase.cpp @@ -0,0 +1,96 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include "qpid/concurrent/APRBase.h" +#include "qpid/QpidError.h" + +using namespace qpid::concurrent; + +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(); +} + +void qpid::concurrent::check(apr_status_t status, const std::string& file, const int line){ + if (status != APR_SUCCESS){ + const int size = 50; + char tmp[size]; + std::string msg(apr_strerror(status, tmp, size)); + throw QpidError(APR_ERROR + ((int) status), msg, file, line); + } +} + +std::string qpid::concurrent::get_desc(apr_status_t status){ + const int size = 50; + char tmp[size]; + return std::string(apr_strerror(status, tmp, size)); +} + diff --git a/cpp/src/qpid/concurrent/APRBase.h b/cpp/src/qpid/concurrent/APRBase.h new file mode 100644 index 0000000000..e0b526faa1 --- /dev/null +++ b/cpp/src/qpid/concurrent/APRBase.h @@ -0,0 +1,63 @@ +/* + * + * 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. + * + */ +#ifndef _APRBase_ +#define _APRBase_ + +#include +#include "apr_thread_mutex.h" +#include "apr_errno.h" + +namespace qpid { +namespace concurrent { + + /** + * 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 std::string& file, const int line); + std::string get_desc(apr_status_t status); + +#define CHECK_APR_SUCCESS(A) check(A, __FILE__, __LINE__); + +} +} + + + + +#endif diff --git a/cpp/src/qpid/concurrent/APRMonitor.cpp b/cpp/src/qpid/concurrent/APRMonitor.cpp new file mode 100644 index 0000000000..cc5eda800f --- /dev/null +++ b/cpp/src/qpid/concurrent/APRMonitor.cpp @@ -0,0 +1,60 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/concurrent/APRBase.h" +#include "qpid/concurrent/APRMonitor.h" +#include + +qpid::concurrent::APRMonitor::APRMonitor(){ + APRBase::increment(); + CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); + CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, pool)); + CHECK_APR_SUCCESS(apr_thread_cond_create(&condition, pool)); +} + +qpid::concurrent::APRMonitor::~APRMonitor(){ + CHECK_APR_SUCCESS(apr_thread_cond_destroy(condition)); + CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); + apr_pool_destroy(pool); + APRBase::decrement(); +} + +void qpid::concurrent::APRMonitor::wait(){ + CHECK_APR_SUCCESS(apr_thread_cond_wait(condition, mutex)); +} + + +void qpid::concurrent::APRMonitor::wait(u_int64_t time){ + apr_status_t status = apr_thread_cond_timedwait(condition, mutex, time * 1000); + if(!status == APR_TIMEUP) CHECK_APR_SUCCESS(status); +} + +void qpid::concurrent::APRMonitor::notify(){ + CHECK_APR_SUCCESS(apr_thread_cond_signal(condition)); +} + +void qpid::concurrent::APRMonitor::notifyAll(){ + CHECK_APR_SUCCESS(apr_thread_cond_broadcast(condition)); +} + +void qpid::concurrent::APRMonitor::acquire(){ + CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); +} + +void qpid::concurrent::APRMonitor::release(){ + CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); +} diff --git a/cpp/src/qpid/concurrent/APRMonitor.h b/cpp/src/qpid/concurrent/APRMonitor.h new file mode 100644 index 0000000000..e62612b31b --- /dev/null +++ b/cpp/src/qpid/concurrent/APRMonitor.h @@ -0,0 +1,48 @@ +/* + * + * 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. + * + */ +#ifndef _APRMonitor_ +#define _APRMonitor_ + +#include "apr_thread_mutex.h" +#include "apr_thread_cond.h" +#include "qpid/concurrent/Monitor.h" + +namespace qpid { +namespace concurrent { + + class APRMonitor : public virtual Monitor + { + apr_pool_t* pool; + apr_thread_mutex_t* mutex; + apr_thread_cond_t* condition; + + public: + APRMonitor(); + virtual ~APRMonitor(); + virtual void wait(); + virtual void wait(u_int64_t time); + virtual void notify(); + virtual void notifyAll(); + virtual void acquire(); + virtual void release(); + }; +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/APRThread.cpp b/cpp/src/qpid/concurrent/APRThread.cpp new file mode 100644 index 0000000000..6b8ceb720a --- /dev/null +++ b/cpp/src/qpid/concurrent/APRThread.cpp @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/concurrent/APRBase.h" +#include "qpid/concurrent/APRThread.h" +#include "apr_portable.h" + +using namespace qpid::concurrent; + +void* APR_THREAD_FUNC ExecRunnable(apr_thread_t* thread, void *data){ + ((Runnable*) data)->run(); + CHECK_APR_SUCCESS(apr_thread_exit(thread, APR_SUCCESS)); + return NULL; +} + +APRThread::APRThread(apr_pool_t* _pool, Runnable* _runnable) : runnable(_runnable), pool(_pool) {} + +APRThread::~APRThread(){ +} + +void APRThread::start(){ + CHECK_APR_SUCCESS(apr_thread_create(&runner, NULL, ExecRunnable,(void*) runnable, pool)); +} + +void APRThread::join(){ + apr_status_t status; + CHECK_APR_SUCCESS(apr_thread_join(&status, runner)); +} + +void APRThread::interrupt(){ + CHECK_APR_SUCCESS(apr_thread_exit(runner, APR_SUCCESS)); +} + +unsigned int qpid::concurrent::APRThread::currentThread(){ + return apr_os_thread_current(); +} diff --git a/cpp/src/qpid/concurrent/APRThread.h b/cpp/src/qpid/concurrent/APRThread.h new file mode 100644 index 0000000000..2ea88da49c --- /dev/null +++ b/cpp/src/qpid/concurrent/APRThread.h @@ -0,0 +1,48 @@ +/* + * + * 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. + * + */ +#ifndef _APRThread_ +#define _APRThread_ + +#include "apr_thread_proc.h" +#include "qpid/concurrent/APRThread.h" +#include "qpid/concurrent/Runnable.h" +#include "qpid/concurrent/Thread.h" + +namespace qpid { +namespace concurrent { + + class APRThread : public virtual Thread + { + const Runnable* runnable; + apr_pool_t* pool; + apr_thread_t* runner; + + public: + APRThread(apr_pool_t* pool, Runnable* runnable); + virtual ~APRThread(); + virtual void start(); + virtual void join(); + virtual void interrupt(); + static unsigned int currentThread(); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/APRThreadFactory.cpp b/cpp/src/qpid/concurrent/APRThreadFactory.cpp new file mode 100644 index 0000000000..1c99a3da33 --- /dev/null +++ b/cpp/src/qpid/concurrent/APRThreadFactory.cpp @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/concurrent/APRBase.h" +#include "qpid/concurrent/APRThreadFactory.h" + +using namespace qpid::concurrent; + +APRThreadFactory::APRThreadFactory(){ + APRBase::increment(); + CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); +} + +APRThreadFactory::~APRThreadFactory(){ + apr_pool_destroy(pool); + APRBase::decrement(); +} + +Thread* APRThreadFactory::create(Runnable* runnable){ + return new APRThread(pool, runnable); +} diff --git a/cpp/src/qpid/concurrent/APRThreadFactory.h b/cpp/src/qpid/concurrent/APRThreadFactory.h new file mode 100644 index 0000000000..3585fab126 --- /dev/null +++ b/cpp/src/qpid/concurrent/APRThreadFactory.h @@ -0,0 +1,44 @@ +/* + * + * 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. + * + */ +#ifndef _APRThreadFactory_ +#define _APRThreadFactory_ + +#include "apr_thread_proc.h" + +#include "qpid/concurrent/APRThread.h" +#include "qpid/concurrent/Thread.h" +#include "qpid/concurrent/ThreadFactory.h" +#include "qpid/concurrent/Runnable.h" + +namespace qpid { +namespace concurrent { + + class APRThreadFactory : public virtual ThreadFactory + { + apr_pool_t* pool; + public: + APRThreadFactory(); + virtual ~APRThreadFactory(); + virtual Thread* create(Runnable* runnable); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/APRThreadPool.cpp b/cpp/src/qpid/concurrent/APRThreadPool.cpp new file mode 100644 index 0000000000..3222c71b0c --- /dev/null +++ b/cpp/src/qpid/concurrent/APRThreadPool.cpp @@ -0,0 +1,83 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/concurrent/APRThreadFactory.h" +#include "qpid/concurrent/APRThreadPool.h" +#include "qpid/QpidError.h" +#include + +using namespace qpid::concurrent; + +APRThreadPool::APRThreadPool(int _size) : deleteFactory(true), size(_size), factory(new APRThreadFactory()), running(false){ + worker = new Worker(this); +} + +APRThreadPool::APRThreadPool(int _size, ThreadFactory* _factory) : deleteFactory(false), size(_size), factory(_factory), running(false){ + worker = new Worker(this); +} + +APRThreadPool::~APRThreadPool(){ + if(deleteFactory) delete factory; +} + +void APRThreadPool::addTask(Runnable* task){ + lock.acquire(); + tasks.push(task); + lock.notifyAll(); + lock.release(); +} + +void APRThreadPool::runTask(){ + lock.acquire(); + while(tasks.empty()){ + lock.wait(); + } + Runnable* task = tasks.front(); + tasks.pop(); + lock.release(); + try{ + task->run(); + }catch(qpid::QpidError error){ + std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; + } +} + +void APRThreadPool::start(){ + if(!running){ + running = true; + for(int i = 0; i < size; i++){ + Thread* t = factory->create(worker); + t->start(); + threads.push_back(t); + } + } +} + +void APRThreadPool::stop(){ + if(!running){ + running = false; + lock.acquire(); + lock.notifyAll(); + lock.release(); + for(int i = 0; i < size; i++){ + threads[i]->join(); + delete threads[i]; + } + } +} + + diff --git a/cpp/src/qpid/concurrent/APRThreadPool.h b/cpp/src/qpid/concurrent/APRThreadPool.h new file mode 100644 index 0000000000..cab5bcc9ce --- /dev/null +++ b/cpp/src/qpid/concurrent/APRThreadPool.h @@ -0,0 +1,67 @@ +/* + * + * 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. + * + */ +#ifndef _APRThreadPool_ +#define _APRThreadPool_ + +#include +#include +#include "qpid/concurrent/APRMonitor.h" +#include "qpid/concurrent/Thread.h" +#include "qpid/concurrent/ThreadFactory.h" +#include "qpid/concurrent/ThreadPool.h" +#include "qpid/concurrent/Runnable.h" + +namespace qpid { +namespace concurrent { + + class APRThreadPool : public virtual ThreadPool + { + class Worker : public virtual Runnable{ + APRThreadPool* pool; + public: + inline Worker(APRThreadPool* _pool) : pool(_pool){} + inline virtual void run(){ + while(pool->running){ + pool->runTask(); + } + } + }; + const bool deleteFactory; + const int size; + ThreadFactory* factory; + APRMonitor lock; + std::vector threads; + std::queue tasks; + Worker* worker; + volatile bool running; + + void runTask(); + public: + APRThreadPool(int size); + APRThreadPool(int size, ThreadFactory* factory); + virtual void start(); + virtual void stop(); + virtual void addTask(Runnable* task); + virtual ~APRThreadPool(); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/LMonitor.h b/cpp/src/qpid/concurrent/LMonitor.h new file mode 100644 index 0000000000..70e99b9807 --- /dev/null +++ b/cpp/src/qpid/concurrent/LMonitor.h @@ -0,0 +1,44 @@ +/* + * + * 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. + * + */ +#ifndef _LMonitor_ +#define _LMonitor_ + +/* Native Linux Monitor - Based of Kernel patch 19/20 */ + +#include "qpid/concurrent/Monitor.h" + +namespace qpid { +namespace concurrent { + + class LMonitor : public virtual Monitor + { + + public: + LMonitor(); + virtual ~LMonitor(); + virtual void wait(); + virtual void notify(); + virtual void notifyAll(); + virtual void acquire(); + virtual void release(); + }; +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/LThreadFactory.h b/cpp/src/qpid/concurrent/LThreadFactory.h new file mode 100644 index 0000000000..4a573d1bd1 --- /dev/null +++ b/cpp/src/qpid/concurrent/LThreadFactory.h @@ -0,0 +1,37 @@ +/* + * + * 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. + * + */ +#ifndef _LAPRThreadFactory_ +#define _LAPRThreadFactory_ + + +namespace qpid { +namespace concurrent { + + class LThreadFactory + { + public: + LThreadFactory(); + virtual ~LThreadFactory(); + virtual Thread* create(Runnable* runnable); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/LockedQueue.h b/cpp/src/qpid/concurrent/LockedQueue.h new file mode 100644 index 0000000000..e55bd9f25a --- /dev/null +++ b/cpp/src/qpid/concurrent/LockedQueue.h @@ -0,0 +1,68 @@ +/* + * + * 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. + * + */ +#ifndef _LockedQueue_ +#define _LockedQueue_ + +#include +#include "qpid/concurrent/Monitor.h" + +/** + * A threadsafe queue abstraction + */ +namespace qpid { +namespace concurrent { + template class LockedQueue + { + L lock; + std::queue queue; + + public: + void put(T* item); + T* take(); + bool empty(); + }; + + template void LockedQueue::put(T* item){ + lock.acquire(); + queue.push(item); + lock.release(); + } + + template T* LockedQueue::take(){ + lock.acquire(); + T* item = 0; + if(!queue.empty()){ + item = queue.front(); + queue.pop(); + } + lock.release(); + return item; + } + + template bool LockedQueue::empty(){ + lock.acquire(); + bool result = queue.empty(); + lock.release(); + return result; + } + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/Monitor.h b/cpp/src/qpid/concurrent/Monitor.h new file mode 100644 index 0000000000..42e88c0a48 --- /dev/null +++ b/cpp/src/qpid/concurrent/Monitor.h @@ -0,0 +1,59 @@ +/* + * + * 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. + * + */ +#ifndef _Monitor_ +#define _Monitor_ + +#include "qpid/framing/amqp_types.h" + +namespace qpid { +namespace concurrent { + +class Monitor +{ + public: + virtual ~Monitor(){} + virtual void wait() = 0; + virtual void wait(u_int64_t time) = 0; + virtual void notify() = 0; + virtual void notifyAll() = 0; + virtual void acquire() = 0; + virtual void release() = 0; +}; + +/** + * Scoped locker for a monitor. + */ +class Locker +{ + public: + Locker(Monitor& lock_) : lock(lock_) { lock.acquire(); } + ~Locker() { lock.release(); } + + private: + Monitor& lock; + + // private and unimplemented to prevent copying + Locker(const Locker&); + void operator=(const Locker&); +}; + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/MonitorImpl.h b/cpp/src/qpid/concurrent/MonitorImpl.h new file mode 100644 index 0000000000..258ad140b3 --- /dev/null +++ b/cpp/src/qpid/concurrent/MonitorImpl.h @@ -0,0 +1,57 @@ +/* + * + * 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. + * + */ + + +#ifndef _MonitorImpl_ +#define _MonitorImpl_ + +#ifdef _USE_APR_IO_ +#include "qpid/concurrent/APRMonitor.h" +#else /* use POSIX Monitor */ +#include "qpid/concurrent/LMonitor.h" +#endif + + +namespace qpid { +namespace concurrent { + +#ifdef _USE_APR_IO_ + class MonitorImpl : public virtual APRMonitor + { + + public: + MonitorImpl() : APRMonitor(){}; + virtual ~MonitorImpl(){}; + + }; +#else + class MonitorImpl : public virtual LMonitor + { + + public: + MonitorImpl() : LMonitor(){}; + virtual ~MonitorImpl(){}; + + }; +#endif + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/Runnable.cpp b/cpp/src/qpid/concurrent/Runnable.cpp new file mode 100644 index 0000000000..5b18ccfab6 --- /dev/null +++ b/cpp/src/qpid/concurrent/Runnable.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qpid/concurrent/Runnable.h" +qpid::concurrent::Runnable::~Runnable() {} diff --git a/cpp/src/qpid/concurrent/Runnable.h b/cpp/src/qpid/concurrent/Runnable.h new file mode 100644 index 0000000000..9753a1ad0a --- /dev/null +++ b/cpp/src/qpid/concurrent/Runnable.h @@ -0,0 +1,35 @@ +/* + * + * 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. + * + */ +#ifndef _Runnable_ +#define _Runnable_ + +namespace qpid { +namespace concurrent { + + class Runnable + { + public: + virtual ~Runnable(); + virtual void run() = 0; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/TaskQueue.h b/cpp/src/qpid/concurrent/TaskQueue.h new file mode 100644 index 0000000000..4abadd7dc5 --- /dev/null +++ b/cpp/src/qpid/concurrent/TaskQueue.h @@ -0,0 +1,200 @@ +/* + * + * 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. + * + */ +#ifndef _TaskQueue_ +#define _TaskQueue_ + +#include +#include +#include +#include "qpid/concurrent/LockedQueue.h" +#include "qpid/concurrent/Runnable.h" +#include "qpid/concurrent/ThreadPool.h" + +namespace qpid { +namespace concurrent { + template class TaskQueue : public virtual Runnable + { + const int max_iterations_per_run; + L lock; + //LockedQueue queue; + std::queue queue; + ThreadPool* const pool; + T* work; + bool running; + volatile bool stopped; + TaskQueue* next; + + volatile bool inrun; + + bool hasWork(); + void completed(); + + T* take(); + + protected: + /** + * Callback though which the task is executed + */ + virtual void execute(T* t) = 0; + /** + * Allows a task to be completed asynchronously to the + * execute() call if required. + */ + virtual bool isComplete(T* t); + /** + * Should be called to signal completion of a task that was + * signalled as not complete through the isComplete() methods + * return value. This will allow normal processing to resume. + */ + virtual void complete(); + + public: + TaskQueue(ThreadPool* const pool, int max_iterations_per_run = 100); + virtual void run(); + void trigger(); + bool append(T* t); + void stop(bool drain); + inline void setNext(TaskQueue* next){ this->next = next; } + }; + + template TaskQueue::TaskQueue(ThreadPool* const _pool, int _max_iterations_per_run) : + pool(_pool), + max_iterations_per_run(_max_iterations_per_run), + work(0), + running(false), + stopped(false), + next(0), inrun(false){ + } + + template void TaskQueue::run(){ + if(inrun) std::cout << "Already running" << std::endl; + inrun = true; + + bool blocked = false; + int count = max_iterations_per_run; + while(!blocked && hasWork() && count){ + execute(work); + if(isComplete(work)){ + completed(); + }else{ + blocked = true; + } + count--; + } + inrun = false; + + if(!blocked && count == 0){//performed max_iterations_per_run, requeue task to ensure fairness + //running will still be true at this point + lock.acquire(); + running = false; + if(stopped) lock.notify(); + lock.release(); + + trigger(); + }else if(hasWork()){//task was added to queue after we exited the loop above; should not need this? + trigger(); + } + } + + template void TaskQueue::trigger(){ + lock.acquire(); + if(!running){ + running = true; + pool->addTask(this); + } + lock.release(); + } + + template bool TaskQueue::hasWork(){ + lock.acquire(); + if(!work) work = take();//queue.take(); + if(!work){ + running = false; + if(stopped) lock.notify(); + } + lock.release(); + return work; + } + + template bool TaskQueue::append(T* item){ + if(!stopped){ + lock.acquire(); + + //queue.put(item); + queue.push(item); + + if(!running){ + running = true; + pool->addTask(this); + } + lock.release(); + //} + return true; + }else{ + return false; + } + } + + template bool TaskQueue::isComplete(T* item){ + return true;//by default assume all tasks are synchronous w.r.t. execute() + } + + + template void TaskQueue::completed(){ + if(next){ + if(!next->append(work)){ + std::cout << "Warning: dropping task as next queue appears to have stopped." << std::endl; + } + }else{ + delete work; + } + work = 0; + } + + template void TaskQueue::complete(){ + completed(); + lock.acquire(); + running = false; + if(stopped) lock.notify(); + lock.release(); + } + + template void TaskQueue::stop(bool drain){ + //prevent new tasks from being added + stopped = true; + //wait until no longer running + lock.acquire(); + while(running && (drain && hasWork())){ + lock.wait(); + } + lock.release(); + } + + template T* TaskQueue::take(){ + T* item = 0; + if(!queue.empty()){ + item = queue.front(); + queue.pop(); + } + return item; + } +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/Thread.h b/cpp/src/qpid/concurrent/Thread.h new file mode 100644 index 0000000000..6bd2a379ce --- /dev/null +++ b/cpp/src/qpid/concurrent/Thread.h @@ -0,0 +1,37 @@ +/* + * + * 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. + * + */ +#ifndef _Thread_ +#define _Thread_ + +namespace qpid { +namespace concurrent { + + class Thread + { + public: + virtual ~Thread(){} + virtual void start() = 0; + virtual void join() = 0; + virtual void interrupt() = 0; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/ThreadFactory.h b/cpp/src/qpid/concurrent/ThreadFactory.h new file mode 100644 index 0000000000..60c8ad2556 --- /dev/null +++ b/cpp/src/qpid/concurrent/ThreadFactory.h @@ -0,0 +1,38 @@ +/* + * + * 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. + * + */ +#ifndef _ThreadFactory_ +#define _ThreadFactory_ + +#include "qpid/concurrent/Thread.h" +#include "qpid/concurrent/Runnable.h" + +namespace qpid { +namespace concurrent { + + class ThreadFactory + { + public: + virtual ~ThreadFactory(){} + virtual Thread* create(Runnable* runnable) = 0; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/ThreadFactoryImpl.h b/cpp/src/qpid/concurrent/ThreadFactoryImpl.h new file mode 100644 index 0000000000..352b77ac21 --- /dev/null +++ b/cpp/src/qpid/concurrent/ThreadFactoryImpl.h @@ -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. + * + */ +#ifndef _ThreadFactoryImpl_ +#define _ThreadFactoryImpl_ + + +#ifdef _USE_APR_IO_ +#include "qpid/concurrent/APRThreadFactory.h" +#else +#include "qpid/concurrent/LThreadFactory.h" +#endif + + +namespace qpid { +namespace concurrent { + + +#ifdef _USE_APR_IO_ + class ThreadFactoryImpl : public virtual APRThreadFactory + { + public: + ThreadFactoryImpl(): APRThreadFactory() {}; + virtual ~ThreadFactoryImpl() {}; + }; +#else + class ThreadFactoryImpl : public virtual LThreadFactory + { + public: + ThreadFactoryImpl(): LThreadFactory() {}; + virtual ~ThreadFactoryImpl() {}; + }; +#endif +} +} + + +#endif diff --git a/cpp/src/qpid/concurrent/ThreadPool.h b/cpp/src/qpid/concurrent/ThreadPool.h new file mode 100644 index 0000000000..925faa76de --- /dev/null +++ b/cpp/src/qpid/concurrent/ThreadPool.h @@ -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. + * + */ +#ifndef _ThreadPool_ +#define _ThreadPool_ + +#include "qpid/concurrent/Thread.h" +#include "qpid/concurrent/Runnable.h" + +namespace qpid { +namespace concurrent { + + class ThreadPool + { + public: + virtual void start() = 0; + virtual void stop() = 0; + virtual void addTask(Runnable* runnable) = 0; + virtual ~ThreadPool(){} + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/AMQBody.cpp b/cpp/src/qpid/framing/AMQBody.cpp new file mode 100644 index 0000000000..850635af15 --- /dev/null +++ b/cpp/src/qpid/framing/AMQBody.cpp @@ -0,0 +1,33 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qpid/framing/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() {} + +void qpid::framing::AMQBody::print(std::ostream& out) const { + out << "unknown body"; +} diff --git a/cpp/src/qpid/framing/AMQBody.h b/cpp/src/qpid/framing/AMQBody.h new file mode 100644 index 0000000000..1c7f9419ed --- /dev/null +++ b/cpp/src/qpid/framing/AMQBody.h @@ -0,0 +1,48 @@ +/* + * + * 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 "./memory.h" +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/Buffer.h" + +#ifndef _AMQBody_ +#define _AMQBody_ + +namespace qpid { + namespace framing { + + class AMQBody + { + public: + typedef std::tr1::shared_ptr shared_ptr; + + virtual ~AMQBody(); + virtual u_int32_t size() const = 0; + virtual u_int8_t type() const = 0; + virtual void encode(Buffer& buffer) const = 0; + virtual void decode(Buffer& buffer, u_int32_t size) = 0; + virtual void print(std::ostream& out) const; + }; + + std::ostream& operator<<(std::ostream& out, const AMQBody& body) ; + + enum body_types {METHOD_BODY = 1, HEADER_BODY = 2, CONTENT_BODY = 3, HEARTBEAT_BODY = 8}; + } +} + + +#endif diff --git a/cpp/src/qpid/framing/AMQContentBody.cpp b/cpp/src/qpid/framing/AMQContentBody.cpp new file mode 100644 index 0000000000..16a9e492ab --- /dev/null +++ b/cpp/src/qpid/framing/AMQContentBody.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 "qpid/framing/AMQContentBody.h" +#include + +qpid::framing::AMQContentBody::AMQContentBody(){ +} + +qpid::framing::AMQContentBody::AMQContentBody(const string& _data) : data(_data){ +} + +u_int32_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, u_int32_t _size){ + buffer.getRawData(data, _size); +} + +void qpid::framing::AMQContentBody::print(std::ostream& out) const +{ + out << "content (" << size() << " bytes)"; +} diff --git a/cpp/src/qpid/framing/AMQContentBody.h b/cpp/src/qpid/framing/AMQContentBody.h new file mode 100644 index 0000000000..40dd8f159c --- /dev/null +++ b/cpp/src/qpid/framing/AMQContentBody.h @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/AMQBody.h" +#include "qpid/framing/Buffer.h" + +#ifndef _AMQContentBody_ +#define _AMQContentBody_ + +namespace qpid { +namespace framing { + +class AMQContentBody : virtual public AMQBody +{ + string data; + +public: + typedef std::tr1::shared_ptr shared_ptr; + + AMQContentBody(); + AMQContentBody(const string& data); + inline virtual ~AMQContentBody(){} + inline u_int8_t type() const { return CONTENT_BODY; }; + inline string& getData(){ return data; } + u_int32_t size() const; + void encode(Buffer& buffer) const; + void decode(Buffer& buffer, u_int32_t size); + void print(std::ostream& out) const; +}; + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/AMQDataBlock.h b/cpp/src/qpid/framing/AMQDataBlock.h new file mode 100644 index 0000000000..bdb4f55796 --- /dev/null +++ b/cpp/src/qpid/framing/AMQDataBlock.h @@ -0,0 +1,39 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/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 u_int32_t size() const = 0; +}; + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/AMQFrame.cpp b/cpp/src/qpid/framing/AMQFrame.cpp new file mode 100644 index 0000000000..2d89a8a797 --- /dev/null +++ b/cpp/src/qpid/framing/AMQFrame.cpp @@ -0,0 +1,115 @@ + +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/AMQFrame.h" +#include "qpid/QpidError.h" + +using namespace qpid::framing; + +AMQFrame::AMQFrame(){} + +AMQFrame::AMQFrame(u_int16_t _channel, AMQBody* _body) : channel(_channel), body(_body){} + +AMQFrame::AMQFrame(u_int16_t _channel, AMQBody::shared_ptr& _body) : channel(_channel), body(_body){} + +AMQFrame::~AMQFrame(){ +} + +u_int16_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); +} + +AMQBody::shared_ptr createMethodBody(Buffer& buffer){ + u_int16_t classId = buffer.getShort(); + u_int16_t methodId = buffer.getShort(); + AMQBody::shared_ptr body(createAMQMethodBody(classId, methodId)); + return body; +} + +u_int32_t AMQFrame::size() const{ + if(!body.get()) THROW_QPID_ERROR(INTERNAL_ERROR, "Attempt to get size of frame with no body set!"); + 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(); + u_int32_t bufSize = decodeHead(buffer); + + if(buffer.available() < bufSize + 1){ + buffer.restore(); + return false; + } + decodeBody(buffer, bufSize); + u_int8_t end = buffer.getOctet(); + if(end != 0xCE) THROW_QPID_ERROR(FRAMING_ERROR, "Frame end not found"); + return true; +} + +u_int32_t AMQFrame::decodeHead(Buffer& buffer){ + type = buffer.getOctet(); + channel = buffer.getShort(); + return buffer.getLong(); +} + +void AMQFrame::decodeBody(Buffer& buffer, uint32_t bufSize) +{ + switch(type) + { + case METHOD_BODY: + body = createMethodBody(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: + string msg("Unknown body type: "); + msg += type; + THROW_QPID_ERROR(FRAMING_ERROR, msg); + } + body->decode(buffer, bufSize); +} + +std::ostream& qpid::framing::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; +} + diff --git a/cpp/src/qpid/framing/AMQFrame.h b/cpp/src/qpid/framing/AMQFrame.h new file mode 100644 index 0000000000..6f05aef584 --- /dev/null +++ b/cpp/src/qpid/framing/AMQFrame.h @@ -0,0 +1,61 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/amqp_methods.h" +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/AMQBody.h" +#include "qpid/framing/AMQDataBlock.h" +#include "qpid/framing/AMQMethodBody.h" +#include "qpid/framing/AMQHeaderBody.h" +#include "qpid/framing/AMQContentBody.h" +#include "qpid/framing/AMQHeartbeatBody.h" +#include "qpid/framing/Buffer.h" + +#ifndef _AMQFrame_ +#define _AMQFrame_ + +namespace qpid { + namespace framing { + + class AMQFrame : virtual public AMQDataBlock + { + u_int16_t channel; + u_int8_t type;//used if the body is decoded separately from the 'head' + AMQBody::shared_ptr body; + + public: + AMQFrame(); + AMQFrame(u_int16_t channel, AMQBody* body); + AMQFrame(u_int16_t channel, AMQBody::shared_ptr& body); + virtual ~AMQFrame(); + virtual void encode(Buffer& buffer); + virtual bool decode(Buffer& buffer); + virtual u_int32_t size() const; + u_int16_t getChannel(); + AMQBody::shared_ptr& getBody(); + + u_int32_t decodeHead(Buffer& buffer); + void decodeBody(Buffer& buffer, uint32_t size); + + friend std::ostream& operator<<(std::ostream& out, const AMQFrame& body); + }; + + } +} + + +#endif diff --git a/cpp/src/qpid/framing/AMQHeaderBody.cpp b/cpp/src/qpid/framing/AMQHeaderBody.cpp new file mode 100644 index 0000000000..eb360d8bc8 --- /dev/null +++ b/cpp/src/qpid/framing/AMQHeaderBody.cpp @@ -0,0 +1,73 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/AMQHeaderBody.h" +#include "qpid/QpidError.h" +#include "qpid/framing/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; +} + +u_int32_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, u_int32_t bufSize){ + u_int16_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, content_size=" << getContentSize() + << " (" << size() << " bytes)" << ", headers=" ; + // TODO aconway 2006-09-26: Hack to see headers. + // Should write proper op << for BasicHeaderProperties. + // + const BasicHeaderProperties* props = + dynamic_cast(getProperties()); + // TODO aconway 2006-09-26: Lose the static cast, fix BasicHeaderProperties + if (props) out << const_cast(props)->getHeaders(); +} diff --git a/cpp/src/qpid/framing/AMQHeaderBody.h b/cpp/src/qpid/framing/AMQHeaderBody.h new file mode 100644 index 0000000000..4f3804ed75 --- /dev/null +++ b/cpp/src/qpid/framing/AMQHeaderBody.h @@ -0,0 +1,57 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/AMQBody.h" +#include "qpid/framing/Buffer.h" +#include "qpid/framing/HeaderProperties.h" + +#ifndef _AMQHeaderBody_ +#define _AMQHeaderBody_ + +namespace qpid { +namespace framing { + +class AMQHeaderBody : virtual public AMQBody +{ + HeaderProperties* properties; + u_int16_t weight; + u_int64_t contentSize; + + void createProperties(int classId); +public: + typedef std::tr1::shared_ptr shared_ptr; + + AMQHeaderBody(int classId); + AMQHeaderBody(); + inline u_int8_t type() const { return HEADER_BODY; } + HeaderProperties* getProperties(){ return properties; } + const HeaderProperties* getProperties() const { return properties; } + inline u_int64_t getContentSize() const { return contentSize; } + inline void setContentSize(u_int64_t _size) { contentSize = _size; } + virtual ~AMQHeaderBody(); + virtual u_int32_t size() const; + virtual void encode(Buffer& buffer) const; + virtual void decode(Buffer& buffer, u_int32_t size); + virtual void print(std::ostream& out) const; +}; + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/AMQHeartbeatBody.cpp b/cpp/src/qpid/framing/AMQHeartbeatBody.cpp new file mode 100644 index 0000000000..bcac68412b --- /dev/null +++ b/cpp/src/qpid/framing/AMQHeartbeatBody.cpp @@ -0,0 +1,26 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qpid/framing/AMQHeartbeatBody.h" +#include + +qpid::framing::AMQHeartbeatBody::~AMQHeartbeatBody() {} + +void qpid::framing::AMQHeartbeatBody::print(std::ostream& out) const { + out << "heartbeat"; +} diff --git a/cpp/src/qpid/framing/AMQHeartbeatBody.h b/cpp/src/qpid/framing/AMQHeartbeatBody.h new file mode 100644 index 0000000000..9d4c7d5b1a --- /dev/null +++ b/cpp/src/qpid/framing/AMQHeartbeatBody.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/AMQBody.h" +#include "qpid/framing/Buffer.h" + +#ifndef _AMQHeartbeatBody_ +#define _AMQHeartbeatBody_ + +namespace qpid { +namespace framing { + +class AMQHeartbeatBody : virtual public AMQBody +{ +public: + typedef std::tr1::shared_ptr shared_ptr; + + virtual ~AMQHeartbeatBody(); + inline u_int32_t size() const { return 0; } + inline u_int8_t type() const { return HEARTBEAT_BODY; } + inline void encode(Buffer& ) const {} + inline void decode(Buffer& , u_int32_t /*size*/) {} + virtual void print(std::ostream& out) const; +}; + +} +} + +#endif diff --git a/cpp/src/qpid/framing/AMQMethodBody.cpp b/cpp/src/qpid/framing/AMQMethodBody.cpp new file mode 100644 index 0000000000..803bab3517 --- /dev/null +++ b/cpp/src/qpid/framing/AMQMethodBody.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 "qpid/framing/AMQMethodBody.h" +#include "qpid/QpidError.h" + +void qpid::framing::AMQMethodBody::encode(Buffer& buffer) const{ + buffer.putShort(amqpClassId()); + buffer.putShort(amqpMethodId()); + encodeContent(buffer); +} + +void qpid::framing::AMQMethodBody::decode(Buffer& buffer, u_int32_t /*size*/){ + decodeContent(buffer); +} + +bool qpid::framing::AMQMethodBody::match(AMQMethodBody* other) const{ + return other != 0 && other->amqpClassId() == amqpClassId() && other->amqpMethodId() == amqpMethodId(); +} + +void qpid::framing::AMQMethodBody::invoke(AMQP_ServerOperations& /*target*/, u_int16_t /*channel*/){ + THROW_QPID_ERROR(PROTOCOL_ERROR, "Method not supported by AMQP Server."); +} + + +std::ostream& qpid::framing::operator<<(std::ostream& out, const AMQMethodBody& m){ + m.print(out); + return out; +} diff --git a/cpp/src/qpid/framing/AMQMethodBody.h b/cpp/src/qpid/framing/AMQMethodBody.h new file mode 100644 index 0000000000..d22c86918c --- /dev/null +++ b/cpp/src/qpid/framing/AMQMethodBody.h @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/AMQBody.h" +#include "qpid/framing/Buffer.h" +#include "qpid/framing/AMQP_ServerOperations.h" + +#ifndef _AMQMethodBody_ +#define _AMQMethodBody_ + +namespace qpid { +namespace framing { + +class AMQMethodBody : virtual public AMQBody +{ +public: + typedef std::tr1::shared_ptr shared_ptr; + + inline u_int8_t type() const { return METHOD_BODY; } + inline u_int32_t size() const { return 4 + bodySize(); } + inline virtual ~AMQMethodBody(){} + virtual void print(std::ostream& out) const = 0; + virtual u_int16_t amqpMethodId() const = 0; + virtual u_int16_t amqpClassId() const = 0; + virtual void invoke(AMQP_ServerOperations& target, u_int16_t channel); + virtual void encodeContent(Buffer& buffer) const = 0; + virtual void decodeContent(Buffer& buffer) = 0; + virtual u_int32_t bodySize() const = 0; + void encode(Buffer& buffer) const; + void decode(Buffer& buffer, u_int32_t size); + bool match(AMQMethodBody* other) const; +}; + +std::ostream& operator<<(std::ostream& out, const AMQMethodBody& body); + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/BasicHeaderProperties.cpp b/cpp/src/qpid/framing/BasicHeaderProperties.cpp new file mode 100644 index 0000000000..94e2ff3914 --- /dev/null +++ b/cpp/src/qpid/framing/BasicHeaderProperties.cpp @@ -0,0 +1,100 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/BasicHeaderProperties.h" + +//TODO: This could be easily generated from the spec + +qpid::framing::BasicHeaderProperties::BasicHeaderProperties() : deliveryMode(0), priority(0), timestamp(0){} +qpid::framing::BasicHeaderProperties::~BasicHeaderProperties(){} + +u_int32_t qpid::framing::BasicHeaderProperties::size() const{ + u_int32_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{ + u_int16_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, u_int32_t /*size*/){ + u_int16_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 = 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); +} + +u_int16_t qpid::framing::BasicHeaderProperties::getFlags() const{ + u_int16_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/cpp/src/qpid/framing/BasicHeaderProperties.h b/cpp/src/qpid/framing/BasicHeaderProperties.h new file mode 100644 index 0000000000..e82699753b --- /dev/null +++ b/cpp/src/qpid/framing/BasicHeaderProperties.h @@ -0,0 +1,93 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/amqp_methods.h" +#include "qpid/framing/Buffer.h" +#include "qpid/framing/HeaderProperties.h" + +#ifndef _BasicHeaderProperties_ +#define _BasicHeaderProperties_ + +namespace qpid { +namespace framing { + + //TODO: This could be easily generated from the spec + class BasicHeaderProperties : public HeaderProperties + { + string contentType; + string contentEncoding; + FieldTable headers; + u_int8_t deliveryMode; + u_int8_t priority; + string correlationId; + string replyTo; + string expiration; + string messageId; + u_int64_t timestamp; + string type; + string userId; + string appId; + string clusterId; + + u_int16_t getFlags() const; + + public: + BasicHeaderProperties(); + virtual ~BasicHeaderProperties(); + virtual u_int32_t size() const; + virtual void encode(Buffer& buffer) const; + virtual void decode(Buffer& buffer, u_int32_t size); + + inline virtual u_int8_t classId(){ return BASIC; } + + inline string& getContentType(){ return contentType; } + inline string& getContentEncoding(){ return contentEncoding; } + inline FieldTable& getHeaders(){ return headers; } + inline u_int8_t getDeliveryMode(){ return deliveryMode; } + inline u_int8_t getPriority(){ return priority; } + inline string& getCorrelationId(){return correlationId; } + inline string& getReplyTo(){ return replyTo; } + inline string& getExpiration(){ return expiration; } + inline string& getMessageId(){return messageId; } + inline u_int64_t getTimestamp(){ return timestamp; } + inline string& getType(){ return type; } + inline string& getUserId(){ return userId; } + inline string& getAppId(){ return appId; } + inline string& getClusterId(){ return clusterId; } + + void inline setContentType(string& _type){ contentType = _type; } + void inline setContentEncoding(string& encoding){ contentEncoding = encoding; } + void inline setHeaders(FieldTable& _headers){ headers = _headers; } + void inline setDeliveryMode(u_int8_t mode){ deliveryMode = mode; } + void inline setPriority(u_int8_t _priority){ priority = _priority; } + void inline setCorrelationId(string& _correlationId){ correlationId = _correlationId; } + void inline setReplyTo(string& _replyTo){ replyTo = _replyTo;} + void inline setExpiration(string& _expiration){ expiration = _expiration; } + void inline setMessageId(string& _messageId){ messageId = _messageId; } + void inline setTimestamp(u_int64_t _timestamp){ timestamp = _timestamp; } + void inline setType(string& _type){ type = _type; } + void inline setUserId(string& _userId){ userId = _userId; } + void inline setAppId(string& _appId){appId = _appId; } + void inline setClusterId(string& _clusterId){ clusterId = _clusterId; } + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/BodyHandler.cpp b/cpp/src/qpid/framing/BodyHandler.cpp new file mode 100644 index 0000000000..f9079c27ea --- /dev/null +++ b/cpp/src/qpid/framing/BodyHandler.cpp @@ -0,0 +1,51 @@ +/* + * + * 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 "./memory.h" +#include "qpid/framing/BodyHandler.h" + +using namespace qpid::framing; +using namespace std::tr1; + +BodyHandler::~BodyHandler() {} + +void BodyHandler::handleBody(AMQBody::shared_ptr& body){ + + switch(body->type()) + { + + case METHOD_BODY: + handleMethod(dynamic_pointer_cast(body)); + break; + + case HEADER_BODY: + handleHeader(dynamic_pointer_cast(body)); + break; + + case CONTENT_BODY: + handleContent(dynamic_pointer_cast(body)); + break; + + case HEARTBEAT_BODY: + handleHeartbeat(dynamic_pointer_cast(body)); + break; + + default: + throw UnknownBodyType(body->type()); + } + +} diff --git a/cpp/src/qpid/framing/BodyHandler.h b/cpp/src/qpid/framing/BodyHandler.h new file mode 100644 index 0000000000..0cd7f7fa11 --- /dev/null +++ b/cpp/src/qpid/framing/BodyHandler.h @@ -0,0 +1,51 @@ +/* + * + * 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 + +#ifndef _BodyHandler_ +#define _BodyHandler_ + +#include "qpid/framing/AMQMethodBody.h" +#include "qpid/framing/AMQHeaderBody.h" +#include "qpid/framing/AMQContentBody.h" +#include "qpid/framing/AMQHeartbeatBody.h" + +namespace qpid { +namespace framing { + + class BodyHandler{ + public: + virtual ~BodyHandler(); + virtual void handleMethod(AMQMethodBody::shared_ptr body) = 0; + virtual void handleHeader(AMQHeaderBody::shared_ptr body) = 0; + virtual void handleContent(AMQContentBody::shared_ptr body) = 0; + virtual void handleHeartbeat(AMQHeartbeatBody::shared_ptr body) = 0; + + void handleBody(AMQBody::shared_ptr& body); + }; + + class UnknownBodyType{ + public: + const u_int16_t type; + inline UnknownBodyType(u_int16_t _type) : type(_type){} + }; +} +} + + +#endif diff --git a/cpp/src/qpid/framing/Buffer.cpp b/cpp/src/qpid/framing/Buffer.cpp new file mode 100644 index 0000000000..b7c17fa86f --- /dev/null +++ b/cpp/src/qpid/framing/Buffer.cpp @@ -0,0 +1,168 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/Buffer.h" +#include "qpid/framing/FieldTable.h" + +qpid::framing::Buffer::Buffer(u_int32_t _size) : size(_size), position(0), limit(_size){ + data = new char[size]; +} + +qpid::framing::Buffer::~Buffer(){ + 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(){ + u_int32_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; +} + +u_int32_t qpid::framing::Buffer::available(){ + return limit - position; +} + +char* qpid::framing::Buffer::start(){ + return data + position; +} + +void qpid::framing::Buffer::move(u_int32_t bytes){ + position += bytes; +} + +void qpid::framing::Buffer::putOctet(u_int8_t i){ + data[position++] = i; +} + +void qpid::framing::Buffer::putShort(u_int16_t i){ + u_int16_t b = i; + data[position++] = (u_int8_t) (0xFF & (b >> 8)); + data[position++] = (u_int8_t) (0xFF & b); +} + +void qpid::framing::Buffer::putLong(u_int32_t i){ + u_int32_t b = i; + data[position++] = (u_int8_t) (0xFF & (b >> 24)); + data[position++] = (u_int8_t) (0xFF & (b >> 16)); + data[position++] = (u_int8_t) (0xFF & (b >> 8)); + data[position++] = (u_int8_t) (0xFF & b); +} + +void qpid::framing::Buffer::putLongLong(u_int64_t i){ + u_int32_t hi = i >> 32; + u_int32_t lo = i; + putLong(hi); + putLong(lo); +} + +u_int8_t qpid::framing::Buffer::getOctet(){ + return (u_int8_t) data[position++]; +} + +u_int16_t qpid::framing::Buffer::getShort(){ + u_int16_t hi = (unsigned char) data[position++]; + hi = hi << 8; + hi |= (unsigned char) data[position++]; + return hi; +} + +u_int32_t qpid::framing::Buffer::getLong(){ + u_int32_t a = (unsigned char) data[position++]; + u_int32_t b = (unsigned char) data[position++]; + u_int32_t c = (unsigned char) data[position++]; + u_int32_t d = (unsigned char) data[position++]; + a = a << 24; + a |= b << 16; + a |= c << 8; + a |= d; + return a; +} + +u_int64_t qpid::framing::Buffer::getLongLong(){ + u_int64_t hi = getLong(); + u_int64_t lo = getLong(); + hi = hi << 32; + return hi | lo; +} + + +void qpid::framing::Buffer::putShortString(const string& s){ + u_int8_t len = s.length(); + putOctet(len); + s.copy(data + position, len); + position += len; +} + +void qpid::framing::Buffer::putLongString(const string& s){ + u_int32_t len = s.length(); + putLong(len); + s.copy(data + position, len); + position += len; +} + +void qpid::framing::Buffer::getShortString(string& s){ + u_int8_t len = getOctet(); + s.assign(data + position, len); + position += len; +} + +void qpid::framing::Buffer::getLongString(string& s){ + u_int32_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::putRawData(const string& s){ + u_int32_t len = s.length(); + s.copy(data + position, len); + position += len; +} + +void qpid::framing::Buffer::getRawData(string& s, u_int32_t len){ + s.assign(data + position, len); + position += len; +} diff --git a/cpp/src/qpid/framing/Buffer.h b/cpp/src/qpid/framing/Buffer.h new file mode 100644 index 0000000000..1698144908 --- /dev/null +++ b/cpp/src/qpid/framing/Buffer.h @@ -0,0 +1,78 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/amqp_types.h" + +#ifndef _Buffer_ +#define _Buffer_ + +namespace qpid { +namespace framing { + +class FieldTable; + +class Buffer +{ + const u_int32_t size; + char* data; + u_int32_t position; + u_int32_t limit; + u_int32_t r_position; + u_int32_t r_limit; + +public: + + Buffer(u_int32_t size); + ~Buffer(); + + void flip(); + void clear(); + void compact(); + void record(); + void restore(); + u_int32_t available(); + char* start(); + void move(u_int32_t bytes); + + void putOctet(u_int8_t i); + void putShort(u_int16_t i); + void putLong(u_int32_t i); + void putLongLong(u_int64_t i); + + u_int8_t getOctet(); + u_int16_t getShort(); + u_int32_t getLong(); + u_int64_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 putRawData(const string& s); + void getRawData(string& s, u_int32_t size); + +}; + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/FieldTable.cpp b/cpp/src/qpid/framing/FieldTable.cpp new file mode 100644 index 0000000000..b4b245292f --- /dev/null +++ b/cpp/src/qpid/framing/FieldTable.cpp @@ -0,0 +1,147 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/FieldTable.h" +#include "qpid/QpidError.h" +#include "qpid/framing/Buffer.h" +#include "qpid/framing/Value.h" +#include + +namespace qpid { +namespace framing { + +FieldTable::~FieldTable() {} + +u_int32_t FieldTable::size() const { + u_int32_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 << "field_table{"; + 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, u_int64_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 <> u_int64_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); +} + +u_int64_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){ + u_int32_t len = buffer.getLong(); + u_int32_t available = buffer.available(); + if (available < len) + THROW_QPID_ERROR(FRAMING_ERROR, "Not enough data for field table."); + u_int32_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/cpp/src/qpid/framing/FieldTable.h b/cpp/src/qpid/framing/FieldTable.h new file mode 100644 index 0000000000..b48b270895 --- /dev/null +++ b/cpp/src/qpid/framing/FieldTable.h @@ -0,0 +1,78 @@ +/* + * + * 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 "qpid/framing/amqp_types.h" + +#ifndef _FieldTable_ +#define _FieldTable_ + +namespace qpid { +namespace framing { + +class Value; +class Buffer; + +class FieldTable +{ + public: + typedef std::tr1::shared_ptr ValuePtr; + typedef std::tr1::unordered_map ValueMap; + + ~FieldTable(); + u_int32_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, u_int64_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; + u_int64_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/cpp/src/qpid/framing/HeaderProperties.h b/cpp/src/qpid/framing/HeaderProperties.h new file mode 100644 index 0000000000..a699c37163 --- /dev/null +++ b/cpp/src/qpid/framing/HeaderProperties.h @@ -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 "qpid/framing/amqp_types.h" +#include "qpid/framing/Buffer.h" + +#ifndef _HeaderProperties_ +#define _HeaderProperties_ + +namespace qpid { +namespace framing { + + enum header_classes{BASIC = 60}; + + class HeaderProperties + { + + public: + inline virtual ~HeaderProperties(){} + virtual u_int8_t classId() = 0; + virtual u_int32_t size() const = 0; + virtual void encode(Buffer& buffer) const = 0; + virtual void decode(Buffer& buffer, u_int32_t size) = 0; + }; +} +} + + +#endif diff --git a/cpp/src/qpid/framing/InitiationHandler.cpp b/cpp/src/qpid/framing/InitiationHandler.cpp new file mode 100644 index 0000000000..7a15864216 --- /dev/null +++ b/cpp/src/qpid/framing/InitiationHandler.cpp @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qpid/framing/InitiationHandler.h" + +qpid::framing::InitiationHandler::~InitiationHandler() {} diff --git a/cpp/src/qpid/framing/InitiationHandler.h b/cpp/src/qpid/framing/InitiationHandler.h new file mode 100644 index 0000000000..da902f0dff --- /dev/null +++ b/cpp/src/qpid/framing/InitiationHandler.h @@ -0,0 +1,38 @@ +/* + * + * 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 + +#ifndef _InitiationHandler_ +#define _InitiationHandler_ + +#include "qpid/framing/ProtocolInitiation.h" + +namespace qpid { +namespace framing { + + class InitiationHandler{ + public: + virtual ~InitiationHandler(); + virtual void initiated(ProtocolInitiation* header) = 0; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/InputHandler.cpp b/cpp/src/qpid/framing/InputHandler.cpp new file mode 100644 index 0000000000..accf68421a --- /dev/null +++ b/cpp/src/qpid/framing/InputHandler.cpp @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qpid/framing/InputHandler.h" + +qpid::framing::InputHandler::~InputHandler() {} diff --git a/cpp/src/qpid/framing/InputHandler.h b/cpp/src/qpid/framing/InputHandler.h new file mode 100644 index 0000000000..e2ad545993 --- /dev/null +++ b/cpp/src/qpid/framing/InputHandler.h @@ -0,0 +1,38 @@ +/* + * + * 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 + +#ifndef _InputHandler_ +#define _InputHandler_ + +#include "qpid/framing/AMQFrame.h" + +namespace qpid { +namespace framing { + + class InputHandler{ + public: + virtual ~InputHandler(); + virtual void received(AMQFrame* frame) = 0; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/OutputHandler.cpp b/cpp/src/qpid/framing/OutputHandler.cpp new file mode 100644 index 0000000000..22de39b82a --- /dev/null +++ b/cpp/src/qpid/framing/OutputHandler.cpp @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qpid/framing/OutputHandler.h" + +qpid::framing::OutputHandler::~OutputHandler() {} diff --git a/cpp/src/qpid/framing/OutputHandler.h b/cpp/src/qpid/framing/OutputHandler.h new file mode 100644 index 0000000000..ed38a321e5 --- /dev/null +++ b/cpp/src/qpid/framing/OutputHandler.h @@ -0,0 +1,38 @@ +/* + * + * 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 + +#ifndef _OutputHandler_ +#define _OutputHandler_ + +#include "qpid/framing/AMQFrame.h" + +namespace qpid { +namespace framing { + + class OutputHandler{ + public: + virtual ~OutputHandler(); + virtual void send(AMQFrame* frame) = 0; + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/ProtocolInitiation.cpp b/cpp/src/qpid/framing/ProtocolInitiation.cpp new file mode 100644 index 0000000000..aebdf6709e --- /dev/null +++ b/cpp/src/qpid/framing/ProtocolInitiation.cpp @@ -0,0 +1,53 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/ProtocolInitiation.h" + +qpid::framing::ProtocolInitiation::ProtocolInitiation(){} + +qpid::framing::ProtocolInitiation::ProtocolInitiation(u_int8_t _major, u_int8_t _minor) : pmajor(_major), pminor(_minor){} + +qpid::framing::ProtocolInitiation::~ProtocolInitiation(){} + +void qpid::framing::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(pmajor); + buffer.putOctet(pminor); +} + +bool qpid::framing::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 + pmajor = buffer.getOctet(); + pminor = 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 diff --git a/cpp/src/qpid/framing/ProtocolInitiation.h b/cpp/src/qpid/framing/ProtocolInitiation.h new file mode 100644 index 0000000000..b0c1338cbf --- /dev/null +++ b/cpp/src/qpid/framing/ProtocolInitiation.h @@ -0,0 +1,48 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/Buffer.h" +#include "qpid/framing/AMQDataBlock.h" + +#ifndef _ProtocolInitiation_ +#define _ProtocolInitiation_ + +namespace qpid { +namespace framing { + +class ProtocolInitiation : virtual public AMQDataBlock +{ + u_int8_t pmajor; + u_int8_t pminor; + +public: + ProtocolInitiation(); + ProtocolInitiation(u_int8_t major, u_int8_t minor); + virtual ~ProtocolInitiation(); + virtual void encode(Buffer& buffer); + virtual bool decode(Buffer& buffer); + inline virtual u_int32_t size() const { return 8; } + inline u_int8_t getMajor(){ return pmajor; } + inline u_int8_t getMinor(){ return pminor; } +}; + +} +} + + +#endif diff --git a/cpp/src/qpid/framing/Value.cpp b/cpp/src/qpid/framing/Value.cpp new file mode 100644 index 0000000000..4a24ab4147 --- /dev/null +++ b/cpp/src/qpid/framing/Value.cpp @@ -0,0 +1,111 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/framing/Value.h" +#include "qpid/framing/Buffer.h" +#include "qpid/framing/FieldTable.h" +#include "qpid/QpidError.h" + +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((u_int32_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; + u_int8_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; + default: + THROW_QPID_ERROR(FRAMING_ERROR, "Unknown field table value type"); + } + 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/cpp/src/qpid/framing/Value.h b/cpp/src/qpid/framing/Value.h new file mode 100644 index 0000000000..3c538719db --- /dev/null +++ b/cpp/src/qpid/framing/Value.h @@ -0,0 +1,160 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include "qpid/framing/amqp_types.h" +#include "qpid/framing/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 { + u_int32_t value; + u_int8_t decimals; + + Decimal(u_int32_t value_=0, u_int8_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 u_int32_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 u_int32_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 u_int32_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(u_int64_t v) : ValueOps(v){} + TimeValue(){} + virtual u_int32_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(u_int32_t value_=0, u_int8_t decimals_=0) : + ValueOps(Decimal(value_, decimals_)){} + virtual u_int32_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 u_int32_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 u_int32_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; +}; + +}} // qpid::framing + +#endif diff --git a/cpp/src/qpid/framing/amqp_framing.h b/cpp/src/qpid/framing/amqp_framing.h new file mode 100644 index 0000000000..34ebf665e7 --- /dev/null +++ b/cpp/src/qpid/framing/amqp_framing.h @@ -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 "qpid/framing/amqp_types.h" +#include "qpid/framing/AMQFrame.h" +#include "qpid/framing/AMQBody.h" +#include "qpid/framing/BodyHandler.h" +#include "qpid/framing/AMQMethodBody.h" +#include "qpid/framing/AMQHeaderBody.h" +#include "qpid/framing/AMQContentBody.h" +#include "qpid/framing/AMQHeartbeatBody.h" +#include "qpid/framing/amqp_methods.h" +#include "qpid/framing/InputHandler.h" +#include "qpid/framing/OutputHandler.h" +#include "qpid/framing/InitiationHandler.h" +#include "qpid/framing/ProtocolInitiation.h" +#include "qpid/framing/BasicHeaderProperties.h" diff --git a/cpp/src/qpid/framing/amqp_types.h b/cpp/src/qpid/framing/amqp_types.h new file mode 100644 index 0000000000..6f8ef0862a --- /dev/null +++ b/cpp/src/qpid/framing/amqp_types.h @@ -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 +#ifdef _WINDOWS +#include "windows.h" +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned int u_int32_t; +typedef unsigned __int64 u_int64_t; +#endif +#ifndef _WINDOWS +#include "sys/types.h" +#endif + +#ifndef AMQP_TYPES_H +#define AMQP_TYPES_H + + +typedef std::string string; + +#endif diff --git a/cpp/src/qpid/io/APRConnector.cpp b/cpp/src/qpid/io/APRConnector.cpp new file mode 100644 index 0000000000..91cf01c842 --- /dev/null +++ b/cpp/src/qpid/io/APRConnector.cpp @@ -0,0 +1,201 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include "qpid/concurrent/APRBase.h" +#include "qpid/io/APRConnector.h" +#include "qpid/concurrent/APRThreadFactory.h" +#include "qpid/QpidError.h" + +using namespace qpid::io; +using namespace qpid::concurrent; +using namespace qpid::framing; +using qpid::QpidError; + +APRConnector::APRConnector(bool _debug, u_int32_t buffer_size) : + debug(_debug), + receive_buffer_size(buffer_size), + send_buffer_size(buffer_size), + closed(true), + lastIn(0), lastOut(0), + timeout(0), + idleIn(0), idleOut(0), + timeoutHandler(0), + shutdownHandler(0), + inbuf(receive_buffer_size), + outbuf(send_buffer_size){ + + APRBase::increment(); + + CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); + CHECK_APR_SUCCESS(apr_socket_create(&socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, pool)); + + threadFactory = new APRThreadFactory(); + writeLock = new APRMonitor(); +} + +APRConnector::~APRConnector(){ + delete receiver; + delete writeLock; + delete threadFactory; + apr_pool_destroy(pool); + + APRBase::decrement(); +} + +void APRConnector::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, pool)); + CHECK_APR_SUCCESS(apr_socket_connect(socket, address)); + closed = false; + + receiver = threadFactory->create(this); + receiver->start(); +} + +void APRConnector::init(ProtocolInitiation* header){ + writeBlock(header); + delete header; +} + +void APRConnector::close(){ + closed = true; + CHECK_APR_SUCCESS(apr_socket_close(socket)); + receiver->join(); +} + +void APRConnector::setInputHandler(InputHandler* handler){ + input = handler; +} + +void APRConnector::setShutdownHandler(ShutdownHandler* handler){ + shutdownHandler = handler; +} + +OutputHandler* APRConnector::getOutputHandler(){ + return this; +} + +void APRConnector::send(AMQFrame* frame){ + writeBlock(frame); + if(debug) std::cout << "SENT: " << *frame << std::endl; + delete frame; +} + +void APRConnector::writeBlock(AMQDataBlock* data){ + writeLock->acquire(); + data->encode(outbuf); + + //transfer data to wire + outbuf.flip(); + writeToSocket(outbuf.start(), outbuf.available()); + outbuf.clear(); + writeLock->release(); +} + +void APRConnector::writeToSocket(char* data, size_t available){ + apr_size_t bytes(available); + apr_size_t written(0); + while(written < available && !closed){ + apr_status_t status = apr_socket_send(socket, data + written, &bytes); + if(status == APR_TIMEUP){ + std::cout << "Write request timed out." << std::endl; + } + if(bytes == 0){ + std::cout << "Write request wrote 0 bytes." << std::endl; + } + lastOut = apr_time_as_msec(apr_time_now()); + written += bytes; + bytes = available - written; + } +} + +void APRConnector::checkIdle(apr_status_t status){ + if(timeoutHandler){ + apr_time_t now = apr_time_as_msec(apr_time_now()); + if(APR_STATUS_IS_TIMEUP(status)){ + if(idleIn && (now - lastIn > idleIn)){ + timeoutHandler->idleIn(); + } + }else if(APR_STATUS_IS_EOF(status)){ + closed = true; + CHECK_APR_SUCCESS(apr_socket_close(socket)); + if(shutdownHandler) shutdownHandler->shutdown(); + }else{ + lastIn = now; + } + if(idleOut && (now - lastOut > idleOut)){ + timeoutHandler->idleOut(); + } + } +} + +void APRConnector::setReadTimeout(u_int16_t t){ + idleIn = t * 1000;//t is in secs + if(idleIn && (!timeout || idleIn < timeout)){ + timeout = idleIn; + setSocketTimeout(); + } + +} + +void APRConnector::setWriteTimeout(u_int16_t t){ + idleOut = t * 1000;//t is in secs + if(idleOut && (!timeout || idleOut < timeout)){ + timeout = idleOut; + setSocketTimeout(); + } +} + +void APRConnector::setSocketTimeout(){ + //interval is in microseconds, timeout in milliseconds + //want the interval to be a bit shorter than the timeout, hence multiply + //by 800 rather than 1000. + apr_interval_time_t interval(timeout * 800); + apr_socket_timeout_set(socket, interval); +} + +void APRConnector::setTimeoutHandler(TimeoutHandler* handler){ + timeoutHandler = handler; +} + +void APRConnector::run(){ + try{ + while(!closed){ + apr_size_t bytes(inbuf.available()); + if(bytes < 1){ + THROW_QPID_ERROR(INTERNAL_ERROR, "Frame exceeds buffer size."); + } + checkIdle(apr_socket_recv(socket, inbuf.start(), &bytes)); + + if(bytes > 0){ + inbuf.move(bytes); + inbuf.flip();//position = 0, limit = total data read + + AMQFrame frame; + 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(QpidError error){ + std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; + } +} diff --git a/cpp/src/qpid/io/APRConnector.h b/cpp/src/qpid/io/APRConnector.h new file mode 100644 index 0000000000..e097fc27eb --- /dev/null +++ b/cpp/src/qpid/io/APRConnector.h @@ -0,0 +1,95 @@ +/* + * + * 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. + * + */ +#ifndef _APRConnector_ +#define _APRConnector_ + +#include "apr_network_io.h" +#include "apr_time.h" + +#include "qpid/framing/InputHandler.h" +#include "qpid/framing/OutputHandler.h" +#include "qpid/framing/InitiationHandler.h" +#include "qpid/framing/ProtocolInitiation.h" +#include "qpid/io/ShutdownHandler.h" +#include "qpid/concurrent/Thread.h" +#include "qpid/concurrent/ThreadFactory.h" +#include "qpid/io/Connector.h" +#include "qpid/concurrent/APRMonitor.h" + +namespace qpid { +namespace io { + + class APRConnector : public virtual qpid::framing::OutputHandler, + public virtual Connector, + private virtual qpid::concurrent::Runnable + { + const bool debug; + const int receive_buffer_size; + const int send_buffer_size; + + bool closed; + + apr_time_t lastIn; + apr_time_t lastOut; + apr_interval_time_t timeout; + u_int32_t idleIn; + u_int32_t idleOut; + + TimeoutHandler* timeoutHandler; + ShutdownHandler* shutdownHandler; + qpid::framing::InputHandler* input; + qpid::framing::InitiationHandler* initialiser; + qpid::framing::OutputHandler* output; + + qpid::framing::Buffer inbuf; + qpid::framing::Buffer outbuf; + + qpid::concurrent::APRMonitor* writeLock; + qpid::concurrent::ThreadFactory* threadFactory; + qpid::concurrent::Thread* receiver; + + apr_pool_t* pool; + apr_socket_t* socket; + + void checkIdle(apr_status_t status); + void writeBlock(qpid::framing::AMQDataBlock* data); + void writeToSocket(char* data, size_t available); + void setSocketTimeout(); + + void run(); + + public: + APRConnector(bool debug = false, u_int32_t buffer_size = 1024); + virtual ~APRConnector(); + virtual void connect(const std::string& host, int port); + virtual void init(qpid::framing::ProtocolInitiation* header); + virtual void close(); + virtual void setInputHandler(qpid::framing::InputHandler* handler); + virtual void setTimeoutHandler(TimeoutHandler* handler); + virtual void setShutdownHandler(ShutdownHandler* handler); + virtual qpid::framing::OutputHandler* getOutputHandler(); + virtual void send(qpid::framing::AMQFrame* frame); + virtual void setReadTimeout(u_int16_t timeout); + virtual void setWriteTimeout(u_int16_t timeout); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/APRSocket.cpp b/cpp/src/qpid/io/APRSocket.cpp new file mode 100644 index 0000000000..c142b04df3 --- /dev/null +++ b/cpp/src/qpid/io/APRSocket.cpp @@ -0,0 +1,78 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/concurrent/APRBase.h" +#include "qpid/io/APRSocket.h" +#include +#include + +using namespace qpid::io; +using namespace qpid::framing; +using namespace qpid::concurrent; + +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_status_t s = apr_socket_send(socket, buffer.start(), &bytes); + // TODO aconway 2006-10-05: better error handling + assert(s == 0); + 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(){ + return !closed; +} + +u_int8_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/cpp/src/qpid/io/APRSocket.h b/cpp/src/qpid/io/APRSocket.h new file mode 100644 index 0000000000..742f958b8a --- /dev/null +++ b/cpp/src/qpid/io/APRSocket.h @@ -0,0 +1,45 @@ +/* + * + * 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. + * + */ +#ifndef _APRSocket_ +#define _APRSocket_ + +#include "apr_network_io.h" +#include "qpid/framing/Buffer.h" + +namespace qpid { +namespace io { + + 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(); + u_int8_t read(); + ~APRSocket(); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/Acceptor.cpp b/cpp/src/qpid/io/Acceptor.cpp new file mode 100644 index 0000000000..6b76bd4da2 --- /dev/null +++ b/cpp/src/qpid/io/Acceptor.cpp @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "qpid/io/Acceptor.h" + +qpid::io::Acceptor::~Acceptor() {} diff --git a/cpp/src/qpid/io/Acceptor.h b/cpp/src/qpid/io/Acceptor.h new file mode 100644 index 0000000000..a7f7ad66f0 --- /dev/null +++ b/cpp/src/qpid/io/Acceptor.h @@ -0,0 +1,53 @@ +/* + * + * 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. + * + */ +#ifndef _Acceptor_ +#define _Acceptor_ + +#include "qpid/io/SessionHandlerFactory.h" + +namespace qpid { +namespace io { + + class Acceptor + { + public: + /** + * Bind to port. + * @param port Port to bind to, 0 to bind to dynamically chosen port. + * @return The local bound port. + */ + virtual int16_t bind(int16_t port) = 0; + + /** + * Run the acceptor. + */ + virtual void run(SessionHandlerFactory* factory) = 0; + + /** + * Shut down the acceptor. + */ + virtual void shutdown() = 0; + + virtual ~Acceptor(); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/BlockingAPRAcceptor.cpp b/cpp/src/qpid/io/BlockingAPRAcceptor.cpp new file mode 100644 index 0000000000..0e1fc535a2 --- /dev/null +++ b/cpp/src/qpid/io/BlockingAPRAcceptor.cpp @@ -0,0 +1,101 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include "qpid/io/BlockingAPRAcceptor.h" +#include "qpid/concurrent/APRBase.h" +#include "qpid/concurrent/APRThreadFactory.h" + +using namespace qpid::concurrent; +using namespace qpid::framing; +using namespace qpid::io; + +BlockingAPRAcceptor::BlockingAPRAcceptor(bool _debug, int c) : + debug(_debug), + threadFactory(new APRThreadFactory()), + connectionBacklog(c) +{ + APRBase::increment(); + CHECK_APR_SUCCESS(apr_pool_create(&apr_pool, NULL)); +} + +int16_t BlockingAPRAcceptor::bind(int16_t _port){ + apr_sockaddr_t* address; + CHECK_APR_SUCCESS(apr_sockaddr_info_get(&address, APR_ANYADDR, APR_UNSPEC, _port, APR_IPV4_ADDR_OK, apr_pool)); + CHECK_APR_SUCCESS(apr_socket_create(&socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, apr_pool)); + CHECK_APR_SUCCESS(apr_socket_bind(socket, address)); + CHECK_APR_SUCCESS(apr_socket_listen(socket, connectionBacklog)); + return getPort(); +} + +int16_t BlockingAPRAcceptor::getPort() const { + apr_sockaddr_t* address; + CHECK_APR_SUCCESS(apr_socket_addr_get(&address, APR_LOCAL, socket)); + return address->port; +} + +void BlockingAPRAcceptor::run(SessionHandlerFactory* factory) +{ + running = true; + std::cout << "Listening on port " << getPort() << "..." << std::endl; + while(running){ + apr_socket_t* client; + apr_status_t status = apr_socket_accept(&client, socket, apr_pool); + if(status == APR_SUCCESS){ + //configure socket: + CHECK_APR_SUCCESS(apr_socket_timeout_set(client, 1000000/* i.e. 1 sec*/)); + 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)); + + BlockingAPRSessionContext* session = new BlockingAPRSessionContext(client, threadFactory, this, debug); + session->init(factory->create(session)); + sessions.push_back(session); + }else{ + running = false; + if(status != APR_EINTR){ + std::cout << "ERROR: " << get_desc(status) << std::endl; + } + } + } + shutdown(); +} + +void BlockingAPRAcceptor::shutdown() +{ + // TODO aconway 2006-10-12: Not thread safe. + if (running) + { + running = false; + apr_socket_close(socket); // Don't check, exception safety. + for(iterator i = sessions.begin(); i < sessions.end(); i++){ + (*i)->shutdown(); + } + } +} + +BlockingAPRAcceptor::~BlockingAPRAcceptor(){ + delete threadFactory; + apr_pool_destroy(apr_pool); + APRBase::decrement(); +} + + +void BlockingAPRAcceptor::closed(BlockingAPRSessionContext* session){ + sessions.erase(find(sessions.begin(), sessions.end(), session)); +} + diff --git a/cpp/src/qpid/io/BlockingAPRAcceptor.h b/cpp/src/qpid/io/BlockingAPRAcceptor.h new file mode 100644 index 0000000000..8c83c726c9 --- /dev/null +++ b/cpp/src/qpid/io/BlockingAPRAcceptor.h @@ -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. + * + */ +#ifndef _BlockingAPRAcceptor_ +#define _BlockingAPRAcceptor_ + +#include +#include "apr_network_io.h" +#include "apr_poll.h" +#include "apr_time.h" + +#include "qpid/io/Acceptor.h" +#include "qpid/concurrent/APRMonitor.h" +#include "qpid/io/BlockingAPRSessionContext.h" +#include "qpid/concurrent/Runnable.h" +#include "qpid/io/SessionContext.h" +#include "qpid/io/SessionHandlerFactory.h" +#include "qpid/concurrent/Thread.h" +#include "qpid/concurrent/ThreadFactory.h" +#include "qpid/concurrent/ThreadPool.h" + +namespace qpid { +namespace io { + + class BlockingAPRAcceptor : public virtual Acceptor + { + typedef std::vector::iterator iterator; + + const bool debug; + apr_pool_t* apr_pool; + qpid::concurrent::ThreadFactory* threadFactory; + std::vector sessions; + apr_socket_t* socket; + const int connectionBacklog; + volatile bool running; + + public: + BlockingAPRAcceptor(bool debug = false, int connectionBacklog = 10); + virtual int16_t bind(int16_t port); + virtual int16_t getPort() const; + virtual void run(SessionHandlerFactory* factory); + virtual void shutdown(); + virtual ~BlockingAPRAcceptor(); + void closed(BlockingAPRSessionContext* session); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/BlockingAPRSessionContext.cpp b/cpp/src/qpid/io/BlockingAPRSessionContext.cpp new file mode 100644 index 0000000000..aee223ca3b --- /dev/null +++ b/cpp/src/qpid/io/BlockingAPRSessionContext.cpp @@ -0,0 +1,178 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include "qpid/io/BlockingAPRSessionContext.h" +#include "qpid/io/BlockingAPRAcceptor.h" +#include "qpid/concurrent/APRBase.h" +#include "qpid/QpidError.h" + +using namespace qpid::concurrent; +using namespace qpid::framing; +using namespace qpid::io; + + +BlockingAPRSessionContext::BlockingAPRSessionContext(apr_socket_t* _socket, + ThreadFactory* factory, + BlockingAPRAcceptor* _acceptor, + bool _debug) + : socket(_socket), + debug(_debug), + handler(0), + acceptor(_acceptor), + inbuf(65536), + outbuf(65536), + closed(false){ + + reader = new Reader(this); + writer = new Writer(this); + + rThread = factory->create(reader); + wThread = factory->create(writer); +} + +BlockingAPRSessionContext::~BlockingAPRSessionContext(){ + delete reader; + delete writer; + + delete rThread; + delete wThread; + + delete handler; +} + +void BlockingAPRSessionContext::read(){ + try{ + bool initiated(false); + while(!closed){ + apr_size_t bytes(inbuf.available()); + if(bytes < 1){ + THROW_QPID_ERROR(INTERNAL_ERROR, "Frame exceeds buffer size."); + } + apr_status_t s = apr_socket_recv(socket, inbuf.start(), &bytes); + if(APR_STATUS_IS_TIMEUP(s)){ + //timed out, check closed on loop + }else if(APR_STATUS_IS_EOF(s) || bytes == 0){ + closed = true; + }else{ + inbuf.move(bytes); + inbuf.flip(); + + if(!initiated){ + ProtocolInitiation* protocolInit = new ProtocolInitiation(); + if(protocolInit->decode(inbuf)){ + handler->initiated(protocolInit); + if(debug) std::cout << "RECV: [" << &socket << "]: Initialised " << std::endl; + initiated = true; + } + }else{ + AMQFrame frame; + while(frame.decode(inbuf)){ + if(debug) std::cout << "RECV: [" << &socket << "]:" << frame << std::endl; + handler->received(&frame); + } + } + //need to compact buffer to preserve any 'extra' data + inbuf.compact(); + } + } + + //close socket + }catch(qpid::QpidError error){ + std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; + } +} + +void BlockingAPRSessionContext::write(){ + while(!closed){ + //get next frame + outlock.acquire(); + while(outframes.empty() && !closed){ + outlock.wait(); + } + if(!closed){ + AMQFrame* frame = outframes.front(); + outframes.pop(); + outlock.release(); + + //encode + frame->encode(outbuf); + if(debug) std::cout << "SENT [" << &socket << "]:" << *frame << std::endl; + delete frame; + outbuf.flip(); + + //write from outbuf to socket + char* data = outbuf.start(); + const int available = outbuf.available(); + int written = 0; + apr_size_t bytes = available; + while(available > written){ + apr_status_t s = apr_socket_send(socket, data + written, &bytes); + assert(s == 0); // TODO aconway 2006-10-05: Error Handling. + written += bytes; + bytes = available - written; + } + outbuf.clear(); + }else{ + outlock.release(); + } + } +} + +void BlockingAPRSessionContext::send(AMQFrame* frame){ + if(!closed){ + outlock.acquire(); + bool was_empty(outframes.empty()); + outframes.push(frame); + if(was_empty){ + outlock.notify(); + } + outlock.release(); + }else{ + std::cout << "WARNING: Session closed[" << &socket << "], dropping frame. " << &frame << std::endl; + } +} + +void BlockingAPRSessionContext::init(SessionHandler* _handler){ + handler = _handler; + rThread->start(); + wThread->start(); +} + +void BlockingAPRSessionContext::close(){ + closed = true; + wThread->join(); + CHECK_APR_SUCCESS(apr_socket_close(socket)); + if(debug) std::cout << "RECV: [" << &socket << "]: Closed " << std::endl; + handler->closed(); + acceptor->closed(this); + delete this; +} + +void BlockingAPRSessionContext::shutdown(){ + closed = true; + outlock.acquire(); + outlock.notify(); + outlock.release(); + + wThread->join(); + CHECK_APR_SUCCESS(apr_socket_close(socket)); + rThread->join(); + handler->closed(); + delete this; +} diff --git a/cpp/src/qpid/io/BlockingAPRSessionContext.h b/cpp/src/qpid/io/BlockingAPRSessionContext.h new file mode 100644 index 0000000000..006b73b55c --- /dev/null +++ b/cpp/src/qpid/io/BlockingAPRSessionContext.h @@ -0,0 +1,94 @@ +/* + * + * 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. + * + */ +#ifndef _BlockingAPRSessionContext_ +#define _BlockingAPRSessionContext_ + +#include +#include + +#include "apr_network_io.h" +#include "apr_time.h" + +#include "qpid/framing/AMQFrame.h" +#include "qpid/concurrent/APRMonitor.h" +#include "qpid/framing/Buffer.h" +#include "qpid/concurrent/Runnable.h" +#include "qpid/io/SessionContext.h" +#include "qpid/io/SessionHandler.h" +#include "qpid/io/SessionHandlerFactory.h" +#include "qpid/io/ShutdownHandler.h" +#include "qpid/concurrent/Thread.h" +#include "qpid/concurrent/ThreadFactory.h" + +namespace qpid { +namespace io { + + class BlockingAPRAcceptor; + + class BlockingAPRSessionContext : public virtual SessionContext + { + class Reader : public virtual qpid::concurrent::Runnable{ + BlockingAPRSessionContext* parent; + public: + inline Reader(BlockingAPRSessionContext* p) : parent(p){} + inline virtual void run(){ parent->read(); } + inline virtual ~Reader(){} + }; + + class Writer : public virtual qpid::concurrent::Runnable{ + BlockingAPRSessionContext* parent; + public: + inline Writer(BlockingAPRSessionContext* p) : parent(p){} + inline virtual void run(){ parent->write(); } + inline virtual ~Writer(){} + }; + + apr_socket_t* socket; + const bool debug; + SessionHandler* handler; + BlockingAPRAcceptor* acceptor; + std::queue outframes; + qpid::framing::Buffer inbuf; + qpid::framing::Buffer outbuf; + qpid::concurrent::APRMonitor outlock; + Reader* reader; + Writer* writer; + qpid::concurrent::Thread* rThread; + qpid::concurrent::Thread* wThread; + + volatile bool closed; + + void read(); + void write(); + public: + BlockingAPRSessionContext(apr_socket_t* socket, + qpid::concurrent::ThreadFactory* factory, + BlockingAPRAcceptor* acceptor, + bool debug = false); + ~BlockingAPRSessionContext(); + virtual void send(qpid::framing::AMQFrame* frame); + virtual void close(); + void shutdown(); + void init(SessionHandler* handler); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/Connector.h b/cpp/src/qpid/io/Connector.h new file mode 100644 index 0000000000..d0a2f470a8 --- /dev/null +++ b/cpp/src/qpid/io/Connector.h @@ -0,0 +1,56 @@ +/* + * + * 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. + * + */ +#ifndef _Connector_ +#define _Connector_ + +#include "qpid/framing/InputHandler.h" +#include "qpid/framing/OutputHandler.h" +#include "qpid/framing/InitiationHandler.h" +#include "qpid/framing/ProtocolInitiation.h" +#include "qpid/io/ShutdownHandler.h" +#include "qpid/io/TimeoutHandler.h" + +namespace qpid { +namespace io { + + class Connector + { + public: + virtual void connect(const std::string& host, int port) = 0; + virtual void init(qpid::framing::ProtocolInitiation* header) = 0; + virtual void close() = 0; + virtual void setInputHandler(qpid::framing::InputHandler* handler) = 0; + virtual void setTimeoutHandler(TimeoutHandler* handler) = 0; + virtual void setShutdownHandler(ShutdownHandler* handler) = 0; + virtual qpid::framing::OutputHandler* getOutputHandler() = 0; + /** + * Set the timeout for reads, in secs. + */ + virtual void setReadTimeout(u_int16_t timeout) = 0; + /** + * Set the timeout for writes, in secs. + */ + virtual void setWriteTimeout(u_int16_t timeout) = 0; + virtual ~Connector(){} + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/ConnectorImpl.h b/cpp/src/qpid/io/ConnectorImpl.h new file mode 100644 index 0000000000..55dcf7a2d4 --- /dev/null +++ b/cpp/src/qpid/io/ConnectorImpl.h @@ -0,0 +1,53 @@ +/* + * + * 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. + * + */ +#ifndef _APRConnectorImpl_ +#define _APRConnectorImpl_ + +#ifdef _USE_APR_IO_ +#include "qpid/io/APRConnector.h" +#else +#include "qpid/io/LConnector.h" +#endif + +namespace qpid { +namespace io { + +#ifdef _USE_APR_IO_ + class ConnectorImpl : public virtual APRConnector + { + + public: + ConnectorImpl(bool _debug = false, u_int32_t buffer_size = 1024):APRConnector(_debug,buffer_size){}; + virtual ~ConnectorImpl(){}; + }; +#else + class ConnectorImpl : public virtual LConnector + { + + public: + ConnectorImpl(bool _debug = false, u_int32_t buffer_size = 1024):LConnector(_debug, buffer_size){}; + virtual ~ConnectorImpl(){}; + }; + +#endif + +} +} + + +#endif diff --git a/cpp/src/qpid/io/LConnector.h b/cpp/src/qpid/io/LConnector.h new file mode 100644 index 0000000000..5fc86597bd --- /dev/null +++ b/cpp/src/qpid/io/LConnector.h @@ -0,0 +1,48 @@ +/* + * + * 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. + * + */ +#ifndef _LConnector_ +#define _LConnector_ + + +#include "qpid/framing/InputHandler.h" +#include "qpid/framing/OutputHandler.h" +#include "qpid/framing/InitiationHandler.h" +#include "qpid/framing/ProtocolInitiation.h" +#include "qpid/concurrent/Thread.h" +#include "qpid/concurrent/ThreadFactory.h" +#include "qpid/io/Connector.h" + +namespace qpid { +namespace io { + + class LConnector : public virtual qpid::framing::OutputHandler, + public virtual Connector, + private virtual qpid::concurrent::Runnable + { + + public: + LConnector(bool debug = false, u_int32_t buffer_size = 1024){}; + virtual ~LConnector(){}; + + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/LFAcceptor.cpp b/cpp/src/qpid/io/LFAcceptor.cpp new file mode 100644 index 0000000000..7e51a550af --- /dev/null +++ b/cpp/src/qpid/io/LFAcceptor.cpp @@ -0,0 +1,94 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/io/LFAcceptor.h" +#include "qpid/concurrent/APRBase.h" + +using namespace qpid::concurrent; +using namespace qpid::io; + +LFAcceptor::LFAcceptor(bool _debug, int c, int worker_threads, int m) : + processor(aprPool.pool, worker_threads, 1000, 5000000), + max_connections_per_processor(m), + debug(_debug), + connectionBacklog(c) +{ } + + +int16_t LFAcceptor::bind(int16_t _port){ + apr_sockaddr_t* address; + CHECK_APR_SUCCESS(apr_sockaddr_info_get(&address, APR_ANYADDR, APR_UNSPEC, _port, APR_IPV4_ADDR_OK, aprPool.pool)); + CHECK_APR_SUCCESS(apr_socket_create(&socket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, aprPool.pool)); + 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, connectionBacklog)); + return getPort(); +} + +int16_t LFAcceptor::getPort() const { + apr_sockaddr_t* address; + CHECK_APR_SUCCESS(apr_socket_addr_get(&address, APR_LOCAL, socket)); + return address->port; +} + +void LFAcceptor::run(SessionHandlerFactory* 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.pool); + 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.pool, client, &processor, debug); + session->init(factory->create(session)); + }else{ + running = false; + if(status != APR_EINTR){ + std::cout << "ERROR: " << get_desc(status) << std::endl; + } + } + } + shutdown(); +} + +void LFAcceptor::shutdown() { + // TODO aconway 2006-10-12: Cleanup, this is not thread safe. + if (running) { + running = false; + processor.stop(); + CHECK_APR_SUCCESS(apr_socket_close(socket)); + } +} + + +LFAcceptor::~LFAcceptor(){} + +LFAcceptor::APRPool::APRPool(){ + APRBase::increment(); + CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); +} + +LFAcceptor::APRPool::~APRPool(){ + apr_pool_destroy(pool); + APRBase::decrement(); +} diff --git a/cpp/src/qpid/io/LFAcceptor.h b/cpp/src/qpid/io/LFAcceptor.h new file mode 100644 index 0000000000..f31b544143 --- /dev/null +++ b/cpp/src/qpid/io/LFAcceptor.h @@ -0,0 +1,74 @@ +/* + * + * 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. + * + */ +#ifndef _LFAcceptor_ +#define _LFAcceptor_ + +#include +#include "apr_network_io.h" +#include "apr_poll.h" +#include "apr_time.h" + +#include "qpid/io/Acceptor.h" +#include "qpid/concurrent/APRMonitor.h" +#include "qpid/concurrent/APRThreadFactory.h" +#include "qpid/concurrent/APRThreadPool.h" +#include "qpid/io/LFProcessor.h" +#include "qpid/io/LFSessionContext.h" +#include "qpid/concurrent/Runnable.h" +#include "qpid/io/SessionContext.h" +#include "qpid/io/SessionHandlerFactory.h" +#include "qpid/concurrent/Thread.h" + +namespace qpid { +namespace io { + + class LFAcceptor : public virtual Acceptor + { + class APRPool{ + public: + apr_pool_t* pool; + APRPool(); + ~APRPool(); + }; + + APRPool aprPool; + LFProcessor processor; + apr_socket_t* socket; + const int max_connections_per_processor; + const bool debug; + const int connectionBacklog; + + volatile bool running; + + public: + LFAcceptor(bool debug = false, + int connectionBacklog = 10, + int worker_threads = 5, + int max_connections_per_processor = 500); + virtual int16_t bind(int16_t port); + virtual int16_t getPort() const; + virtual void run(SessionHandlerFactory* factory); + virtual void shutdown(); + virtual ~LFAcceptor(); + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/LFProcessor.cpp b/cpp/src/qpid/io/LFProcessor.cpp new file mode 100644 index 0000000000..dba5d6c962 --- /dev/null +++ b/cpp/src/qpid/io/LFProcessor.cpp @@ -0,0 +1,193 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/io/LFProcessor.h" +#include "qpid/concurrent/APRBase.h" +#include "qpid/io/LFSessionContext.h" +#include "qpid/QpidError.h" +#include + +using namespace qpid::io; +using namespace qpid::concurrent; +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)); + //create & start the required number of threads + for(int i = 0; i < workerCount; i++){ + workers[i] = factory.create(this); + } +} + + +LFProcessor::~LFProcessor(){ + if (!stopped) stop(); + for(int i = 0; i < workerCount; i++){ + delete workers[i]; + } + delete[] workers; + CHECK_APR_SUCCESS(apr_pollset_destroy(pollset)); +} + +void LFProcessor::start(){ + for(int i = 0; i < workerCount; i++){ + workers[i]->start(); + } +} + +void LFProcessor::add(const apr_pollfd_t* const fd){ + CHECK_APR_SUCCESS(apr_pollset_add(pollset, fd)); + countLock.acquire(); + sessions.push_back(reinterpret_cast(fd->client_data)); + count++; + countLock.release(); +} + +void LFProcessor::remove(const apr_pollfd_t* const fd){ + CHECK_APR_SUCCESS(apr_pollset_remove(pollset, fd)); + countLock.acquire(); + sessions.erase(find(sessions.begin(), sessions.end(), reinterpret_cast(fd->client_data))); + count--; + countLock.release(); +} + +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(){ + Locker locker(countLock); + return count == size; +} + +bool LFProcessor::empty(){ + Locker locker(countLock); + return count == 0; +} + +void LFProcessor::poll(){ + apr_status_t status; + do{ + current = 0; + if(!stopped){ + status = apr_pollset_poll(pollset, timeout, &signalledCount, &signalledFDs); + } + }while(status != APR_SUCCESS && !stopped); +} + +void LFProcessor::run(){ + try{ + while(!stopped){ + leadLock.acquire(); + waitToLead(); + if(!stopped){ + const apr_pollfd_t* evt = getNextEvent(); + if(evt){ + LFSessionContext* session = reinterpret_cast(evt->client_data); + session->startProcessing(); + + relinquishLead(); + leadLock.release(); + + //process event: + if(evt->rtnevents & APR_POLLIN) session->read(); + if(evt->rtnevents & APR_POLLOUT) session->write(); + + if(session->isClosed()){ + session->handleClose(); + countLock.acquire(); + sessions.erase(find(sessions.begin(), sessions.end(), session)); + count--; + countLock.release(); + }else{ + session->stopProcessing(); + } + + }else{ + leadLock.release(); + } + }else{ + leadLock.release(); + } + } + }catch(QpidError error){ + std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << 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; + leadLock.acquire(); + leadLock.notifyAll(); + leadLock.release(); + + for(int i = 0; i < workerCount; i++){ + workers[i]->join(); + } + + for(iterator i = sessions.begin(); i < sessions.end(); i++){ + (*i)->shutdown(); + } +} + diff --git a/cpp/src/qpid/io/LFProcessor.h b/cpp/src/qpid/io/LFProcessor.h new file mode 100644 index 0000000000..e3f533d597 --- /dev/null +++ b/cpp/src/qpid/io/LFProcessor.h @@ -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. + * + */ +#ifndef _LFProcessor_ +#define _LFProcessor_ + +#include "apr_poll.h" +#include +#include +#include "qpid/concurrent/APRMonitor.h" +#include "qpid/concurrent/APRThreadFactory.h" +#include "qpid/concurrent/Runnable.h" + +namespace qpid { +namespace io { + + 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::concurrent::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::concurrent::Thread** const workers; + qpid::concurrent::APRMonitor leadLock; + qpid::concurrent::APRMonitor countLock; + qpid::concurrent::APRThreadFactory factory; + 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/cpp/src/qpid/io/LFSessionContext.cpp b/cpp/src/qpid/io/LFSessionContext.cpp new file mode 100644 index 0000000000..6d6d786841 --- /dev/null +++ b/cpp/src/qpid/io/LFSessionContext.cpp @@ -0,0 +1,189 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/io/LFSessionContext.h" +#include "qpid/concurrent/APRBase.h" +#include "qpid/QpidError.h" +#include + +using namespace qpid::concurrent; +using namespace qpid::io; +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(32768), + out(32768), + processor(_processor), + processing(false), + closing(false), + reading(0), + writing(0) +{ + + 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(){ + assert(!reading); // No concurrent read. + reading = APRThread::currentThread(); + + socket.read(in); + in.flip(); + if(initiated){ + AMQFrame frame; + while(frame.decode(in)){ + if(debug) log("RECV", &frame); + handler->received(&frame); + } + }else{ + ProtocolInitiation protocolInit; + if(protocolInit.decode(in)){ + handler->initiated(&protocolInit); + initiated = true; + if(debug) std::cout << "INIT [" << &socket << "]" << std::endl; + } + } + in.compact(); + + reading = 0; +} + +void LFSessionContext::write(){ + assert(!writing); // No concurrent writes. + writing = APRThread::currentThread(); + + bool done = isClosed(); + while(!done){ + if(out.available() > 0){ + socket.write(out); + if(out.available() > 0){ + writing = 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? + writeLock.acquire(); + 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; + + writing = 0; + + if(closing){ + socket.close(); + } + } + writeLock.release(); + } + } +} + +void LFSessionContext::send(AMQFrame* frame){ + writeLock.acquire(); + if(!closing){ + framesToWrite.push(frame); + if(!(fd.reqevents & APR_POLLOUT)){ + fd.reqevents |= APR_POLLOUT; + if(!processing){ + processor->update(&fd); + } + } + } + writeLock.release(); +} + +void LFSessionContext::startProcessing(){ + writeLock.acquire(); + processing = true; + processor->deactivate(&fd); + writeLock.release(); +} + +void LFSessionContext::stopProcessing(){ + writeLock.acquire(); + processor->reactivate(&fd); + processing = false; + writeLock.release(); +} + +void LFSessionContext::close(){ + closing = true; + writeLock.acquire(); + if(!processing){ + //allow pending frames to be written to socket + fd.reqevents = APR_POLLOUT; + processor->update(&fd); + } + writeLock.release(); +} + +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(SessionHandler* _handler){ + handler = _handler; + processor->add(&fd); +} + +void LFSessionContext::log(const std::string& desc, AMQFrame* const frame){ + logLock.acquire(); + std::cout << desc << " [" << &socket << "]: " << *frame << std::endl; + logLock.release(); +} + +APRMonitor LFSessionContext::logLock; diff --git a/cpp/src/qpid/io/LFSessionContext.h b/cpp/src/qpid/io/LFSessionContext.h new file mode 100644 index 0000000000..fad8736796 --- /dev/null +++ b/cpp/src/qpid/io/LFSessionContext.h @@ -0,0 +1,88 @@ +/* + * + * 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. + * + */ +#ifndef _LFSessionContext_ +#define _LFSessionContext_ + +#include + +#include "apr_network_io.h" +#include "apr_poll.h" +#include "apr_time.h" + +#include "qpid/framing/AMQFrame.h" +#include "qpid/concurrent/APRMonitor.h" +#include "qpid/io/APRSocket.h" +#include "qpid/framing/Buffer.h" +#include "qpid/io/LFProcessor.h" +#include "qpid/io/SessionContext.h" +#include "qpid/io/SessionHandler.h" + +namespace qpid { +namespace io { + + + class LFSessionContext : public virtual SessionContext + { + const bool debug; + APRSocket socket; + bool initiated; + + qpid::framing::Buffer in; + qpid::framing::Buffer out; + + SessionHandler* handler; + LFProcessor* const processor; + + apr_pollfd_t fd; + + std::queue framesToWrite; + qpid::concurrent::APRMonitor writeLock; + + bool processing; + bool closing; + + //these are just for debug, as a crude way of detecting concurrent access + volatile unsigned int reading; + volatile unsigned int writing; + + static qpid::concurrent::APRMonitor 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); + ~LFSessionContext(); + virtual void send(qpid::framing::AMQFrame* frame); + virtual void close(); + void read(); + void write(); + void init(SessionHandler* 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/cpp/src/qpid/io/SessionContext.h b/cpp/src/qpid/io/SessionContext.h new file mode 100644 index 0000000000..b8fa8de62e --- /dev/null +++ b/cpp/src/qpid/io/SessionContext.h @@ -0,0 +1,37 @@ +/* + * + * 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. + * + */ +#ifndef _SessionContext_ +#define _SessionContext_ + +#include "qpid/framing/OutputHandler.h" + +namespace qpid { +namespace io { + + class SessionContext : public virtual qpid::framing::OutputHandler + { + public: + virtual void close() = 0; + virtual ~SessionContext(){} + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/SessionHandler.h b/cpp/src/qpid/io/SessionHandler.h new file mode 100644 index 0000000000..5b4e60213b --- /dev/null +++ b/cpp/src/qpid/io/SessionHandler.h @@ -0,0 +1,42 @@ +/* + * + * 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. + * + */ +#ifndef _SessionHandler_ +#define _SessionHandler_ + +#include "qpid/framing/InputHandler.h" +#include "qpid/framing/InitiationHandler.h" +#include "qpid/framing/ProtocolInitiation.h" +#include "qpid/io/TimeoutHandler.h" + +namespace qpid { +namespace io { + + class SessionHandler : public virtual qpid::framing::InitiationHandler, + public virtual qpid::framing::InputHandler, + public virtual TimeoutHandler + { + public: + virtual void closed() = 0; + virtual ~SessionHandler(){} + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/SessionHandlerFactory.h b/cpp/src/qpid/io/SessionHandlerFactory.h new file mode 100644 index 0000000000..8ed2dffe57 --- /dev/null +++ b/cpp/src/qpid/io/SessionHandlerFactory.h @@ -0,0 +1,38 @@ +/* + * + * 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. + * + */ +#ifndef _SessionHandlerFactory_ +#define _SessionHandlerFactory_ + +#include "qpid/io/SessionContext.h" +#include "qpid/io/SessionHandler.h" + +namespace qpid { +namespace io { + + class SessionHandlerFactory + { + public: + virtual SessionHandler* create(SessionContext* ctxt) = 0; + virtual ~SessionHandlerFactory(){} + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/SessionManager.h b/cpp/src/qpid/io/SessionManager.h new file mode 100644 index 0000000000..e6b17451e4 --- /dev/null +++ b/cpp/src/qpid/io/SessionManager.h @@ -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. + * + */ +#ifndef _SessionManager_ +#define _SessionManager_ + +#include "qpid/io/SessionContext.h" +#include "qpid/io/SessionHandler.h" + +namespace qpid { +namespace io { + + class SessionManager + { + public: + virtual SessionHandler* init(SessionContext* ctxt) = 0; + virtual void close(SessionContext* ctxt) = 0; + virtual void updateInterest(SessionContext* ctxt, bool read, bool write) = 0; + virtual ~SessionManager(){} + }; + +} +} + + +#endif diff --git a/cpp/src/qpid/io/ShutdownHandler.h b/cpp/src/qpid/io/ShutdownHandler.h new file mode 100644 index 0000000000..186d9eeca4 --- /dev/null +++ b/cpp/src/qpid/io/ShutdownHandler.h @@ -0,0 +1,34 @@ +/* + * + * 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. + * + */ +#ifndef _ShutdownHandler_ +#define _ShutdownHandler_ + +namespace qpid { +namespace io { + + class ShutdownHandler + { + public: + virtual void shutdown() = 0; + virtual ~ShutdownHandler(){} + }; + +} +} + +#endif diff --git a/cpp/src/qpid/io/TimeoutHandler.h b/cpp/src/qpid/io/TimeoutHandler.h new file mode 100644 index 0000000000..c92220fd6e --- /dev/null +++ b/cpp/src/qpid/io/TimeoutHandler.h @@ -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. + * + */ +#ifndef _TimeoutHandler_ +#define _TimeoutHandler_ + +namespace qpid { +namespace io { + + class TimeoutHandler + { + public: + virtual void idleOut() = 0; + virtual void idleIn() = 0; + virtual ~TimeoutHandler(){} + }; + +} +} + + +#endif diff --git a/cpp/src/qpidd.cpp b/cpp/src/qpidd.cpp new file mode 100644 index 0000000000..85d337dd93 --- /dev/null +++ b/cpp/src/qpidd.cpp @@ -0,0 +1,48 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "qpid/broker/Broker.h" +#include "qpid/broker/Configuration.h" +#include "apr_signal.h" +#include +#include + +using namespace qpid::broker; +using namespace qpid::io; + +void handle_signal(int /*signal*/){ + std::cout << "Shutting down..." << std::endl; +} + +int main(int argc, char** argv) +{ + Configuration config; + try { + config.parse(argc, argv); + if(config.isHelp()){ + config.usage(); + }else{ + apr_signal(SIGINT, handle_signal); + Broker::shared_ptr broker = Broker::create(config); + broker->run(); + } + return 0; + } catch(std::exception e) { + std::cout << e.what() << std::endl; + } + return 1; +} diff --git a/cpp/test/client/client_test.cpp b/cpp/test/client/client_test.cpp new file mode 100644 index 0000000000..b899d494d7 --- /dev/null +++ b/cpp/test/client/client_test.cpp @@ -0,0 +1,97 @@ +/* + * + * 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 "QpidError.h" +#include "Channel.h" +#include "Connection.h" +#include "FieldTable.h" +#include "Message.h" +#include "MessageListener.h" + +#include "MonitorImpl.h" + + +using namespace qpid::client; +using namespace qpid::concurrent; + +class SimpleListener : public virtual MessageListener{ + Monitor* monitor; + +public: + inline SimpleListener(Monitor* _monitor) : monitor(_monitor){} + + inline virtual void received(Message& /*msg*/){ + std::cout << "Received message " /**<< msg **/<< std::endl; + monitor->acquire(); + monitor->notify(); + monitor->release(); + } +}; + +int main(int argc, char**) +{ + try{ + Connection con(argc > 1); + Channel channel; + Exchange exchange("MyExchange", Exchange::TOPIC_EXCHANGE); + Queue queue("MyQueue", true); + + string host("localhost"); + + con.open(host); + std::cout << "Opened connection." << std::endl; + con.openChannel(&channel); + std::cout << "Opened channel." << std::endl; + channel.declareExchange(exchange); + std::cout << "Declared exchange." << std::endl; + channel.declareQueue(queue); + std::cout << "Declared queue." << std::endl; + qpid::framing::FieldTable args; + channel.bind(exchange, queue, "MyTopic", args); + std::cout << "Bound queue to exchange." << std::endl; + + //set up a message listener + MonitorImpl monitor; + SimpleListener listener(&monitor); + string tag("MyTag"); + channel.consume(queue, tag, &listener); + channel.start(); + std::cout << "Registered consumer." << std::endl; + + Message msg; + string data("MyMessage"); + msg.setData(data); + channel.publish(msg, exchange, "MyTopic"); + std::cout << "Published message." << std::endl; + + monitor.acquire(); + monitor.wait(); + monitor.release(); + + + con.closeChannel(&channel); + std::cout << "Closed channel." << std::endl; + con.close(); + std::cout << "Closed connection." << std::endl; + }catch(qpid::QpidError error){ + std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; + return 1; + } + return 0; +} diff --git a/cpp/test/client/topic_listener.cpp b/cpp/test/client/topic_listener.cpp new file mode 100644 index 0000000000..a1b8e383a0 --- /dev/null +++ b/cpp/test/client/topic_listener.cpp @@ -0,0 +1,180 @@ +/* + * + * 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 "apr_time.h" +#include "QpidError.h" +#include "Channel.h" +#include "Connection.h" +#include "Exchange.h" +#include "MessageListener.h" +#include "Queue.h" + +using namespace qpid::client; + +class Listener : public MessageListener{ + Channel* const channel; + const std::string responseQueue; + const bool transactional; + bool init; + int count; + apr_time_t start; + + void shutdown(); + void report(); +public: + Listener(Channel* channel, const std::string& reponseQueue, bool tx); + virtual void received(Message& msg); +}; + +class Args{ + string host; + int port; + int 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(); + + inline const string& getHost() const { return host;} + inline int getPort() const { return port; } + inline int getAckMode(){ return ackMode; } + inline bool getTransactional() const { return transactional; } + inline int getPrefetch(){ return prefetch; } + inline bool getTrace() const { return trace; } + inline 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()); + 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::DEFAULT_TOPIC_EXCHANGE, control, "topic_control", bindArgs); + //set up listener + Listener listener(&channel, response.getName(), args.getTransactional()); + std::string tag; + channel.consume(control, tag, &listener, args.getAckMode()); + channel.run(); + connection.close(); + }catch(qpid::QpidError error){ + std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; + } + } +} + +Listener::Listener(Channel* _channel, const std::string& _responseq, bool tx) : + channel(_channel), responseQueue(_responseq), transactional(tx), init(false), count(0){} + +void Listener::received(Message& message){ + if(!init){ + start = apr_time_as_msec(apr_time_now()); + count = 0; + init = true; + } + std::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){ + std::cout <<"Received " << count << " messages." << std::endl; + } +} + +void Listener::shutdown(){ + channel->close(); +} + +void Listener::report(){ + apr_time_t finish = apr_time_as_msec(apr_time_now()); + apr_time_t time = finish - start; + std::stringstream reportstr; + reportstr << "Received " << count << " messages in " << time << " ms."; + Message msg; + msg.setData(reportstr.str()); + 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 = atoi(argv[++i]); + }else if("-transactional" == name){ + transactional = true; + }else if("-prefetch" == name){ + prefetch = 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 << " -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 << " -trace" << std::endl; + std::cout << " Indicates that the frames sent and received should be logged" << std::endl; +} diff --git a/cpp/test/client/topic_publisher.cpp b/cpp/test/client/topic_publisher.cpp new file mode 100644 index 0000000000..fc6b7f3b30 --- /dev/null +++ b/cpp/test/client/topic_publisher.cpp @@ -0,0 +1,253 @@ +/* + * + * 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 "unistd.h" +#include "apr_time.h" +#include "MonitorImpl.h" +#include "QpidError.h" +#include "Channel.h" +#include "Connection.h" +#include "Exchange.h" +#include "MessageListener.h" +#include "Queue.h" + +using namespace qpid::client; +using namespace qpid::concurrent; + +class Publisher : public MessageListener{ + Channel* const channel; + const std::string controlTopic; + const bool transactional; + MonitorImpl 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); + apr_time_t publish(int msgs, int listeners, int size); + void terminate(); +}; + +class Args{ + string host; + int port; + int messages; + int subscribers; + int 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(); + + inline const string& getHost() const { return host;} + inline int getPort() const { return port; } + inline int getMessages() const { return messages; } + inline int getSubscribers() const { return subscribers; } + inline int getAckMode(){ return ackMode; } + inline bool getTransactional() const { return transactional; } + inline int getPrefetch(){ return prefetch; } + inline int getBatches(){ return batches; } + inline int getDelay(){ return delay; } + inline int getSize(){ return size; } + inline bool getTrace() const { return trace; } + inline 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()); + 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()); + apr_time_t max(0); + apr_time_t min(0); + apr_time_t sum(0); + for(int i = 0; i < batchSize; i++){ + if(i > 0 && args.getDelay()) sleep(args.getDelay()); + apr_time_t time = publisher.publish(args.getMessages(), args.getSubscribers(), args.getSize()); + if(!max || time > max) max = time; + if(!min || time < min) min = time; + sum += time; + std::cout << "Completed " << (i+1) << " of " << batchSize << " in " << time << "ms" << std::endl; + } + publisher.terminate(); + apr_time_t avg = sum / batchSize; + if(batchSize > 1){ + std::cout << batchSize << " batches completed. avg=" << avg << + ", max=" << max << ", min=" << min << std::endl; + } + channel.close(); + connection.close(); + }catch(qpid::QpidError error){ + std::cout << "Error [" << error.code << "] " << error.msg << " (" << error.file << ":" << error.line << ")" << std::endl; + } + } +} + +Publisher::Publisher(Channel* _channel, const std::string& _controlTopic, bool tx) : + channel(_channel), controlTopic(_controlTopic), transactional(tx){} + +void Publisher::received(Message& msg){ + //count responses and when all are received end the current batch + monitor.acquire(); + if(--count == 0){ + monitor.notify(); + } + std::cout << "Received report: " << msg.getData() << " (" << count << " remaining)." << std::endl; + monitor.release(); +} + +void Publisher::waitForCompletion(int msgs){ + count = msgs; + monitor.wait(); +} + +apr_time_t Publisher::publish(int msgs, int listeners, int size){ + monitor.acquire(); + Message msg; + msg.setData(generateData(size)); + apr_time_t start(apr_time_as_msec(apr_time_now())); + for(int i = 0; i < msgs; i++){ + channel->publish(msg, Exchange::DEFAULT_TOPIC_EXCHANGE, controlTopic); + } + //send report request + Message reportRequest; + reportRequest.getHeaders().setString("TYPE", "REPORT_REQUEST"); + channel->publish(reportRequest, Exchange::DEFAULT_TOPIC_EXCHANGE, controlTopic); + if(transactional){ + channel->commit(); + } + + waitForCompletion(listeners); + monitor.release(); + apr_time_t finish(apr_time_as_msec(apr_time_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::DEFAULT_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 = 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/cpp/test/unit/qpid/broker/ChannelTest.cpp b/cpp/test/unit/qpid/broker/ChannelTest.cpp new file mode 100644 index 0000000000..8d54208f77 --- /dev/null +++ b/cpp/test/unit/qpid/broker/ChannelTest.cpp @@ -0,0 +1,162 @@ +/* + * + * 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 "../../src/qpid/broker/Channel.h" +#include "../../src/qpid/broker/Message.h" +#include +#include +#include + +using namespace std::tr1; +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::concurrent; + +struct DummyRouter{ + Message::shared_ptr last; + + void operator()(Message::shared_ptr& msg){ + last = msg; + } +}; + +struct DummyHandler : OutputHandler{ + std::vector frames; + + virtual void send(AMQFrame* frame){ + frames.push_back(frame); + } +}; + + +class ChannelTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(ChannelTest); + CPPUNIT_TEST(testIncoming); + CPPUNIT_TEST(testConsumerMgmt); + CPPUNIT_TEST(testDeliveryNoAck); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testIncoming(){ + Channel channel(0, 0, 10000); + string routingKey("my_routing_key"); + channel.handlePublish(new Message(0, "test", routingKey, false, false)); + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + header->setContentSize(14); + string data1("abcdefg"); + string data2("hijklmn"); + AMQContentBody::shared_ptr part1(new AMQContentBody(data1)); + AMQContentBody::shared_ptr part2(new AMQContentBody(data2)); + + CPPUNIT_ASSERT(!channel.handleHeader(header, DummyRouter()).last); + CPPUNIT_ASSERT(!channel.handleContent(part1, DummyRouter()).last); + DummyRouter router = channel.handleContent(part2, DummyRouter()); + CPPUNIT_ASSERT(router.last); + CPPUNIT_ASSERT_EQUAL(routingKey, router.last->getRoutingKey()); + } + + void testConsumerMgmt(){ + Queue::shared_ptr queue(new Queue("my_queue")); + Channel channel(0, 0, 0); + CPPUNIT_ASSERT(!channel.exists("my_consumer")); + + ConnectionToken* owner; + 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((u_int32_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((u_int32_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((u_int32_t) 0, queue->getConsumerCount()); + } + + void testDeliveryNoAck(){ + DummyHandler handler; + Channel channel(&handler, 7, 10000); + + Message::shared_ptr msg(new Message(0, "test", "my_routing_key", false, false)); + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + header->setContentSize(14); + msg->setHeader(header); + AMQContentBody::shared_ptr body(new AMQContentBody("abcdefghijklmn")); + msg->addContent(body); + + 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) 3, handler.frames.size()); + CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[0]->getChannel()); + CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[1]->getChannel()); + CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[2]->getChannel()); + BasicDeliverBody::shared_ptr deliver(dynamic_pointer_cast(handler.frames[0]->getBody())); + AMQHeaderBody::shared_ptr contentHeader(dynamic_pointer_cast(handler.frames[1]->getBody())); + AMQContentBody::shared_ptr contentBody(dynamic_pointer_cast(handler.frames[2]->getBody())); + CPPUNIT_ASSERT(deliver); + CPPUNIT_ASSERT(contentHeader); + CPPUNIT_ASSERT(contentBody); + CPPUNIT_ASSERT_EQUAL(string("abcdefghijklmn"), contentBody->getData()); + } + + void testDeliveryAndRecovery(){ + DummyHandler handler; + Channel channel(&handler, 7, 10000); + + Message::shared_ptr msg(new Message(0, "test", "my_routing_key", false, false)); + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + header->setContentSize(14); + msg->setHeader(header); + AMQContentBody::shared_ptr body(new AMQContentBody("abcdefghijklmn")); + msg->addContent(body); + + Queue::shared_ptr queue(new Queue("my_queue")); + ConnectionToken* owner; + string tag("ack"); + channel.consume(tag, queue, true, false, owner); + + queue->deliver(msg); + CPPUNIT_ASSERT_EQUAL((size_t) 3, handler.frames.size()); + CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[0]->getChannel()); + CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[1]->getChannel()); + CPPUNIT_ASSERT_EQUAL((u_int16_t) 7, handler.frames[2]->getChannel()); + BasicDeliverBody::shared_ptr deliver(dynamic_pointer_cast(handler.frames[0]->getBody())); + AMQHeaderBody::shared_ptr contentHeader(dynamic_pointer_cast(handler.frames[1]->getBody())); + AMQContentBody::shared_ptr contentBody(dynamic_pointer_cast(handler.frames[2]->getBody())); + CPPUNIT_ASSERT(deliver); + CPPUNIT_ASSERT(contentHeader); + CPPUNIT_ASSERT(contentBody); + CPPUNIT_ASSERT_EQUAL(string("abcdefghijklmn"), contentBody->getData()); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(ChannelTest); diff --git a/cpp/test/unit/qpid/broker/ExchangeTest.cpp b/cpp/test/unit/qpid/broker/ExchangeTest.cpp new file mode 100644 index 0000000000..3d21cb66f0 --- /dev/null +++ b/cpp/test/unit/qpid/broker/ExchangeTest.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 "../../src/qpid/broker/DirectExchange.h" +#include "../../src/qpid/broker/Exchange.h" +#include "../../src/qpid/broker/Queue.h" +#include "../../src/qpid/broker/TopicExchange.h" +#include +#include + +using namespace qpid::broker; +using namespace qpid::concurrent; + +class ExchangeTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(ExchangeTest); + CPPUNIT_TEST(testMe); + CPPUNIT_TEST_SUITE_END(); + + public: + + // TODO aconway 2006-09-12: Need more detailed tests. + + void testMe() + { + Queue::shared_ptr queue(new Queue("queue", true, true)); + Queue::shared_ptr queue2(new Queue("queue2", true, 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 msg = Message::shared_ptr(new Message(0, "e", "A", true, true)); + topic.route(msg, "abc", 0); + direct.route(msg, "abc", 0); + + // TODO aconway 2006-09-12: TODO Why no assertions? + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(ExchangeTest); diff --git a/cpp/test/unit/qpid/broker/HeadersExchangeTest.cpp b/cpp/test/unit/qpid/broker/HeadersExchangeTest.cpp new file mode 100644 index 0000000000..d8fe71350e --- /dev/null +++ b/cpp/test/unit/qpid/broker/HeadersExchangeTest.cpp @@ -0,0 +1,112 @@ +/* + * + * 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 "../../src/qpid/broker/HeadersExchange.h" +#include "../../src/qpid/framing/FieldTable.h" +#include "../../src/qpid/framing/Value.h" +#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/cpp/test/unit/qpid/broker/Makefile b/cpp/test/unit/qpid/broker/Makefile new file mode 100644 index 0000000000..172ce564bf --- /dev/null +++ b/cpp/test/unit/qpid/broker/Makefile @@ -0,0 +1,20 @@ +# +# 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. +# + +QPID_HOME = ../../.. +LDLIBS=-lapr-1 -lcppunit $(COMMON_LIB) $(BROKER_LIB) +include ${QPID_HOME}/cpp/test_plugins.mk + diff --git a/cpp/test/unit/qpid/broker/MessageTest.cpp b/cpp/test/unit/qpid/broker/MessageTest.cpp new file mode 100644 index 0000000000..f6586f721a --- /dev/null +++ b/cpp/test/unit/qpid/broker/MessageTest.cpp @@ -0,0 +1,54 @@ +/* + * + * 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 "../../src/qpid/concurrent/APRBase.h" +#include "../../src/qpid/broker/Message.h" +#include +#include + +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::concurrent; + +class MessageTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(MessageTest); + CPPUNIT_TEST(testMe); + CPPUNIT_TEST_SUITE_END(); + + public: + + // TODO aconway 2006-09-12: Need more detailed tests, + // need tests to assert something! + // + void testMe() + { + APRBase::increment(); + const int size(10); + for(int i = 0; i < size; i++){ + Message::shared_ptr msg = Message::shared_ptr(new Message(0, "A", "B", true, true)); + msg->setHeader(AMQHeaderBody::shared_ptr(new AMQHeaderBody())); + msg->addContent(AMQContentBody::shared_ptr(new AMQContentBody())); + msg.reset(); + } + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(MessageTest); + diff --git a/cpp/test/unit/qpid/broker/QueueRegistryTest.cpp b/cpp/test/unit/qpid/broker/QueueRegistryTest.cpp new file mode 100644 index 0000000000..96fbc88069 --- /dev/null +++ b/cpp/test/unit/qpid/broker/QueueRegistryTest.cpp @@ -0,0 +1,76 @@ +#include "../../src/qpid/broker/QueueRegistry.h" +#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/cpp/test/unit/qpid/broker/QueueTest.cpp b/cpp/test/unit/qpid/broker/QueueTest.cpp new file mode 100644 index 0000000000..fa6344c265 --- /dev/null +++ b/cpp/test/unit/qpid/broker/QueueTest.cpp @@ -0,0 +1,176 @@ + /* + * + * 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 "../../src/qpid/broker/Queue.h" +#include "../../src/qpid/broker/QueueRegistry.h" +#include +#include + +using namespace qpid::broker; +using namespace qpid::concurrent; + + +class TestBinding : public virtual Binding{ + bool cancelled; + +public: + TestBinding(); + virtual void cancel(); + bool isCancelled(); +}; + +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(testBinding); + CPPUNIT_TEST(testRegistry); + CPPUNIT_TEST(testDequeue); + CPPUNIT_TEST_SUITE_END(); + + public: + void testConsumers(){ + Queue::shared_ptr queue(new Queue("my_queue", true, true)); + + //Test adding consumers: + TestConsumer c1; + TestConsumer c2; + queue->consume(&c1); + queue->consume(&c2); + + CPPUNIT_ASSERT_EQUAL(u_int32_t(2), queue->getConsumerCount()); + + //Test basic delivery: + Message::shared_ptr msg1 = Message::shared_ptr(new Message(0, "e", "A", true, true)); + Message::shared_ptr msg2 = Message::shared_ptr(new Message(0, "e", "B", true, true)); + Message::shared_ptr msg3 = Message::shared_ptr(new Message(0, "e", "C", true, true)); + + 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(u_int32_t(1), queue->getConsumerCount()); + queue->cancel(&c2); + CPPUNIT_ASSERT_EQUAL(u_int32_t(0), queue->getConsumerCount()); + } + + void testBinding(){ + Queue::shared_ptr queue(new Queue("my_queue", true, true)); + //Test bindings: + TestBinding a; + TestBinding b; + queue->bound(&a); + queue->bound(&b); + + queue.reset(); + + CPPUNIT_ASSERT(a.isCancelled()); + CPPUNIT_ASSERT(b.isCancelled()); + } + + 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, true)); + + Message::shared_ptr msg1 = Message::shared_ptr(new Message(0, "e", "A", true, true)); + Message::shared_ptr msg2 = Message::shared_ptr(new Message(0, "e", "B", true, true)); + Message::shared_ptr msg3 = Message::shared_ptr(new Message(0, "e", "C", true, true)); + Message::shared_ptr received; + + queue->deliver(msg1); + queue->deliver(msg2); + queue->deliver(msg3); + + CPPUNIT_ASSERT_EQUAL(u_int32_t(3), queue->getMessageCount()); + + received = queue->dequeue(); + CPPUNIT_ASSERT_EQUAL(msg1.get(), received.get()); + CPPUNIT_ASSERT_EQUAL(u_int32_t(2), queue->getMessageCount()); + + received = queue->dequeue(); + CPPUNIT_ASSERT_EQUAL(msg2.get(), received.get()); + CPPUNIT_ASSERT_EQUAL(u_int32_t(1), queue->getMessageCount()); + + TestConsumer consumer; + queue->consume(&consumer); + queue->dispatch(); + CPPUNIT_ASSERT_EQUAL(msg3.get(), consumer.last.get()); + CPPUNIT_ASSERT_EQUAL(u_int32_t(0), queue->getMessageCount()); + + received = queue->dequeue(); + CPPUNIT_ASSERT(!received); + CPPUNIT_ASSERT_EQUAL(u_int32_t(0), queue->getMessageCount()); + + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(QueueTest); + +//TestBinding +TestBinding::TestBinding() : cancelled(false) {} + +void TestBinding::cancel(){ + CPPUNIT_ASSERT(!cancelled); + cancelled = true; +} + +bool TestBinding::isCancelled(){ + return cancelled; +} + +//TestConsumer +bool TestConsumer::deliver(Message::shared_ptr& msg){ + last = msg; + return true; +} + diff --git a/cpp/test/unit/qpid/broker/RouterTest.cpp b/cpp/test/unit/qpid/broker/RouterTest.cpp new file mode 100644 index 0000000000..7b77162905 --- /dev/null +++ b/cpp/test/unit/qpid/broker/RouterTest.cpp @@ -0,0 +1,86 @@ +/* + * + * 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 "../../src/qpid/broker/Channel.h" +#include "../../src/qpid/broker/Exchange.h" +#include "../../src/qpid/broker/ExchangeRegistry.h" +#include "../../src/qpid/broker/Message.h" +#include "../../src/qpid/broker/Router.h" +#include +#include +#include + +using namespace qpid::broker; +using namespace qpid::framing; +using namespace qpid::concurrent; + +struct TestExchange : public Exchange{ + Message::shared_ptr msg; + string routingKey; + FieldTable* args; + + TestExchange() : Exchange("test"), args(0) {} + + void bind(Queue::shared_ptr /*queue*/, const string& /*routingKey*/, FieldTable* /*args*/){} + + void unbind(Queue::shared_ptr /*queue*/, const string& /*routingKey*/, FieldTable* /*args*/){ } + + void route(Message::shared_ptr& _msg, const string& _routingKey, FieldTable* _args){ + msg = _msg; + routingKey = _routingKey; + args = _args; + } +}; + +class RouterTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(RouterTest); + CPPUNIT_TEST(test); + CPPUNIT_TEST_SUITE_END(); + + public: + + void test() + { + ExchangeRegistry registry; + TestExchange* exchange = new TestExchange(); + registry.declare(exchange); + + string routingKey("my_routing_key"); + string name("name"); + string value("value"); + Message::shared_ptr msg(new Message(0, "test", routingKey, false, false)); + AMQHeaderBody::shared_ptr header(new AMQHeaderBody(BASIC)); + + dynamic_cast(header->getProperties())->getHeaders().setString(name, value); + msg->setHeader(header); + + Router router(registry); + router(msg); + + CPPUNIT_ASSERT(exchange->msg); + CPPUNIT_ASSERT_EQUAL(msg, exchange->msg); + CPPUNIT_ASSERT_EQUAL(routingKey, exchange->msg->getRoutingKey()); + CPPUNIT_ASSERT_EQUAL(routingKey, exchange->routingKey); + CPPUNIT_ASSERT_EQUAL(value, exchange->args->getString(name)); + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(RouterTest); + diff --git a/cpp/test/unit/qpid/broker/TopicExchangeTest.cpp b/cpp/test/unit/qpid/broker/TopicExchangeTest.cpp new file mode 100644 index 0000000000..4066a4709f --- /dev/null +++ b/cpp/test/unit/qpid/broker/TopicExchangeTest.cpp @@ -0,0 +1,184 @@ +#include "../../src/qpid/broker/TopicExchange.h" +#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. +// TODO aconway 2006-09-19: Make it a template and put it in a shared test lib. +// +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/cpp/test/unit/qpid/broker/ValueTest.cpp b/cpp/test/unit/qpid/broker/ValueTest.cpp new file mode 100644 index 0000000000..89444c38cf --- /dev/null +++ b/cpp/test/unit/qpid/broker/ValueTest.cpp @@ -0,0 +1,96 @@ +#include "../../src/qpid/framing/Value.h" +#include + +using namespace qpid::framing; + + +// Allow CPPUNIT_EQUALS to print a Tokens. +// TODO aconway 2006-09-19: Make it a template and put it in a shared test lib. +// +template +CppUnit::OStringStream& operator <<(CppUnit::OStringStream& out, + const ValueOps& v) +{ + out << v.getValue(); + return out; +} + + +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/cpp/test/unit/qpid/framing/BodyHandlerTest.cpp b/cpp/test/unit/qpid/framing/BodyHandlerTest.cpp new file mode 100644 index 0000000000..6b011743c0 --- /dev/null +++ b/cpp/test/unit/qpid/framing/BodyHandlerTest.cpp @@ -0,0 +1,103 @@ +/* + * + * 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 "../../src/qpid/framing/amqp_framing.h" +#include "qpid_test_plugin.h" +using namespace qpid::framing; + +class BodyHandlerTest : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(BodyHandlerTest); + CPPUNIT_TEST(testMethod); + CPPUNIT_TEST(testHeader); + CPPUNIT_TEST(testContent); + CPPUNIT_TEST(testHeartbeat); + CPPUNIT_TEST_SUITE_END(); +private: + + class TestBodyHandler : public BodyHandler{ + AMQMethodBody* const method; + AMQHeaderBody* const header; + AMQContentBody* const content; + AMQHeartbeatBody* const heartbeat; + + public: + + TestBodyHandler(AMQMethodBody* _method) : method(_method), header(0), content(0), heartbeat(0){} + TestBodyHandler(AMQHeaderBody* _header) : method(0), header(_header), content(0), heartbeat(0){} + TestBodyHandler(AMQContentBody* _content) : method(0), header(0), content(_content), heartbeat(0){} + TestBodyHandler(AMQHeartbeatBody* _heartbeat) : method(0), header(0), content(0), heartbeat(_heartbeat){} + + virtual void handleMethod(AMQMethodBody::shared_ptr body){ + CPPUNIT_ASSERT(method); + CPPUNIT_ASSERT_EQUAL(method, body.get()); + } + virtual void handleHeader(AMQHeaderBody::shared_ptr body){ + CPPUNIT_ASSERT(header); + CPPUNIT_ASSERT_EQUAL(header, body.get()); + } + virtual void handleContent(AMQContentBody::shared_ptr body){ + CPPUNIT_ASSERT(content); + CPPUNIT_ASSERT_EQUAL(content, body.get()); + } + virtual void handleHeartbeat(AMQHeartbeatBody::shared_ptr body){ + CPPUNIT_ASSERT(heartbeat); + CPPUNIT_ASSERT_EQUAL(heartbeat, body.get()); + } + }; + +public: + + void testMethod() + { + AMQMethodBody* method = new QueueDeclareBody(); + AMQFrame frame(0, method); + TestBodyHandler handler(method); + handler.handleBody(frame.getBody()); + } + + void testHeader() + { + AMQHeaderBody* header = new AMQHeaderBody(); + AMQFrame frame(0, header); + TestBodyHandler handler(header); + handler.handleBody(frame.getBody()); + } + + void testContent() + { + AMQContentBody* content = new AMQContentBody(); + AMQFrame frame(0, content); + TestBodyHandler handler(content); + handler.handleBody(frame.getBody()); + } + + void testHeartbeat() + { + AMQHeartbeatBody* heartbeat = new AMQHeartbeatBody(); + AMQFrame frame(0, heartbeat); + TestBodyHandler handler(heartbeat); + handler.handleBody(frame.getBody()); + } +}; + + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(BodyHandlerTest); + diff --git a/cpp/test/unit/qpid/framing/Makefile b/cpp/test/unit/qpid/framing/Makefile new file mode 100644 index 0000000000..487b8d537b --- /dev/null +++ b/cpp/test/unit/qpid/framing/Makefile @@ -0,0 +1,21 @@ +# +# 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. +# + +QPID_HOME = ../../../.. +LDLIBS=-lapr-1 -lcppunit $(COMMON_LIB) +INCLUDES=$(TEST_INCLUDES) -I ../generated +include ${QPID_HOME}/cpp/test_plugins.mk + diff --git a/cpp/test/unit/qpid/framing/field_table_test.cpp b/cpp/test/unit/qpid/framing/field_table_test.cpp new file mode 100644 index 0000000000..8f2fe61611 --- /dev/null +++ b/cpp/test/unit/qpid/framing/field_table_test.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 "../../src/qpid/framing/amqp_framing.h" +#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/cpp/test/unit/qpid/framing/framing_test.cpp b/cpp/test/unit/qpid/framing/framing_test.cpp new file mode 100644 index 0000000000..40ce3d97ed --- /dev/null +++ b/cpp/test/unit/qpid/framing/framing_test.cpp @@ -0,0 +1,144 @@ +/* + * + * 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 "../../src/qpid/framing/amqp_framing.h" +#include "ConnectionRedirectBody.h" +#include +#include +#include +#include + +using namespace qpid::framing; + +// TODO aconway 2006-09-12: Why do we need explicit qpid::framing:: below? + +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(ConnectionRedirectBody); + CPPUNIT_TEST(BasicConsumeOkBody); + CPPUNIT_TEST_SUITE_END(); + + private: + Buffer buffer; + + public: + + FramingTest() : buffer(100) {} + + void testBasicQosBody() + { + BasicQosBody in(0xCAFEBABE, 0xABBA, true); + in.encodeContent(buffer); + buffer.flip(); + BasicQosBody out; + out.decodeContent(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + void testConnectionSecureBody() + { + std::string s = "security credential"; + ConnectionSecureBody in(s); + in.encodeContent(buffer); + buffer.flip(); + ConnectionSecureBody out; + out.decodeContent(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + void testConnectionRedirectBody() + { + std::string a = "hostA"; + std::string b = "hostB"; + qpid::framing::ConnectionRedirectBody in(a, b); + in.encodeContent(buffer); + buffer.flip(); + qpid::framing::ConnectionRedirectBody out; + out.decodeContent(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + void testAccessRequestBody() + { + std::string s = "text"; + AccessRequestBody in(s, true, false, true, false, true); + in.encodeContent(buffer); + buffer.flip(); + AccessRequestBody out; + out.decodeContent(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + void testBasicConsumeBody() + { + std::string q = "queue"; + std::string t = "tag"; + BasicConsumeBody in(0, q, t, false, true, false, false); + in.encodeContent(buffer); + buffer.flip(); + BasicConsumeBody out; + out.decodeContent(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + + void ConnectionRedirectBody() + { + std::string a = "hostA"; + std::string b = "hostB"; + AMQFrame in(999, new qpid::framing::ConnectionRedirectBody(a, b)); + in.encode(buffer); + buffer.flip(); + AMQFrame out; + out.decode(buffer); + CPPUNIT_ASSERT_EQUAL(tostring(in), tostring(out)); + } + + void BasicConsumeOkBody() + { + std::string s = "hostA"; + AMQFrame in(999, new qpid::framing::BasicConsumeOkBody(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)); + } + } +}; + +// Make this test suite a plugin. +CPPUNIT_PLUGIN_IMPLEMENT(); +CPPUNIT_TEST_SUITE_REGISTRATION(FramingTest); + + + diff --git a/cpp/test/unit/qpid/framing/header_test.cpp b/cpp/test/unit/qpid/framing/header_test.cpp new file mode 100644 index 0000000000..9268c54272 --- /dev/null +++ b/cpp/test/unit/qpid/framing/header_test.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 +#include "../../src/qpid/framing/amqp_framing.h" +#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: + + // TODO aconway 2006-09-12: Need more detailed tests, + // need tests to assert something! + // + 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"); + u_int8_t deliveryMode(2); + u_int8_t priority(3); + string correlationId("abc"); + string replyTo("no-address"); + string expiration("why is this a string?"); + string messageId("xyz"); + u_int64_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"); + u_int8_t deliveryMode(5); + u_int8_t priority(6); + string expiration("Z"); + u_int64_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/cpp/test_plugins.mk b/cpp/test_plugins.mk deleted file mode 100644 index abac186954..0000000000 --- a/cpp/test_plugins.mk +++ /dev/null @@ -1,42 +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. -# - - -# -# Standard make fragment for building test plugins in a directory. -# - -include ${QPID_HOME}/cpp/options.mk - -SOURCES := $(wildcard *.cpp) -TESTS := $(SOURCES:.cpp=.so) -DEPS= $(SOURCES:.cpp=.d) - -INCLUDES = $(TEST_INCLUDES) - -.PHONY: all clean - -all: $(TESTS) - -clean: - -@rm -f $(TESTS) $(DEPS) - -# Rule to build test plugins from .cpp files. -%.so: %.cpp - $(CXX) -shared -o $@ $< $(CXXFLAGS) $(LDFLAGS) $(LDLIBS) - -# Dependencies --include $(DEPS) -- cgit v1.2.1