summaryrefslogtreecommitdiff
path: root/qpid/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/cpp')
-rw-r--r--qpid/cpp/CMakeLists.txt146
-rw-r--r--qpid/cpp/bindings/qmf/python/Makefile.am2
-rw-r--r--qpid/cpp/bindings/qmf/python/qmf.py4
-rw-r--r--qpid/cpp/bindings/qmf/qmfengine.i35
-rw-r--r--qpid/cpp/bindings/qmf/ruby/Makefile.am7
-rw-r--r--qpid/cpp/bindings/qmf/ruby/qmf.rb321
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/agent_ruby.rb103
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/ruby_console.rb76
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/ruby_console_test.rb194
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/run_interop_tests10
-rw-r--r--qpid/cpp/bindings/qmf/tests/test_base.rb73
-rw-r--r--qpid/cpp/boost-1.32-support/supressions76
-rw-r--r--qpid/cpp/etc/CMakeLists.txt20
-rw-r--r--qpid/cpp/examples/messaging/client.cpp2
-rw-r--r--qpid/cpp/examples/messaging/map_receiver.cpp4
-rw-r--r--qpid/cpp/examples/messaging/map_sender.cpp11
-rw-r--r--qpid/cpp/examples/messaging/queue_listener.cpp4
-rw-r--r--qpid/cpp/examples/messaging/queue_receiver.cpp8
-rw-r--r--qpid/cpp/examples/messaging/queue_sender.cpp15
-rw-r--r--qpid/cpp/examples/messaging/server.cpp8
-rw-r--r--qpid/cpp/examples/messaging/topic_listener.cpp4
-rw-r--r--qpid/cpp/examples/messaging/topic_receiver.cpp4
-rw-r--r--qpid/cpp/examples/qmf-agent/Makefile2
-rw-r--r--qpid/cpp/include/qmf/ConnectionSettings.h121
-rw-r--r--qpid/cpp/include/qmf/ConsoleObject.h94
-rw-r--r--qpid/cpp/include/qmf/engine/Agent.h (renamed from qpid/cpp/src/qmf/AgentEngine.h)34
-rw-r--r--qpid/cpp/include/qmf/engine/ConnectionSettings.h150
-rw-r--r--qpid/cpp/include/qmf/engine/Console.h (renamed from qpid/cpp/src/qmf/ConsoleEngine.h)91
-rw-r--r--qpid/cpp/include/qmf/engine/Event.h (renamed from qpid/cpp/src/qmf/Event.h)6
-rw-r--r--qpid/cpp/include/qmf/engine/Message.h (renamed from qpid/cpp/src/qmf/Message.h)6
-rw-r--r--qpid/cpp/include/qmf/engine/Object.h (renamed from qpid/cpp/src/qmf/Object.h)24
-rw-r--r--qpid/cpp/include/qmf/engine/ObjectId.h (renamed from qpid/cpp/src/qmf/ObjectId.h)20
-rw-r--r--qpid/cpp/include/qmf/engine/QmfEngineImportExport.h33
-rw-r--r--qpid/cpp/include/qmf/engine/Query.h (renamed from qpid/cpp/src/qmf/Query.h)20
-rw-r--r--qpid/cpp/include/qmf/engine/ResilientConnection.h (renamed from qpid/cpp/src/qmf/ResilientConnection.h)10
-rw-r--r--qpid/cpp/include/qmf/engine/Schema.h (renamed from qpid/cpp/src/qmf/Schema.h)69
-rw-r--r--qpid/cpp/include/qmf/engine/Typecode.h (renamed from qpid/cpp/src/qmf/Typecode.h)6
-rw-r--r--qpid/cpp/include/qmf/engine/Value.h (renamed from qpid/cpp/src/qmf/Value.h)20
-rw-r--r--qpid/cpp/include/qpid/client/QueueOptions.h15
-rw-r--r--qpid/cpp/include/qpid/messaging/ListContent.h90
-rw-r--r--qpid/cpp/include/qpid/messaging/ListView.h67
-rw-r--r--qpid/cpp/include/qpid/messaging/MapContent.h90
-rw-r--r--qpid/cpp/include/qpid/messaging/MapView.h70
-rw-r--r--qpid/cpp/include/qpid/messaging/Message.h22
-rw-r--r--qpid/cpp/include/qpid/messaging/MessageContent.h90
-rw-r--r--qpid/cpp/include/qpid/sys/posix/PrivatePosix.h5
-rwxr-xr-xqpid/cpp/include/qpid/sys/windows/IntegerTypes.h4
-rw-r--r--qpid/cpp/managementgen/CMakeLists.txt19
-rw-r--r--qpid/cpp/packaging/NSIS/qpid-icon.icobin0 -> 52972 bytes
-rw-r--r--qpid/cpp/packaging/NSIS/qpid-icon.pngbin0 -> 97992 bytes
-rw-r--r--qpid/cpp/packaging/NSIS/qpid-install-banner.bmpbin0 -> 9742 bytes
-rw-r--r--qpid/cpp/packaging/NSIS/qpid-install-banner.pngbin0 -> 57218 bytes
-rwxr-xr-xqpid/cpp/rubygen/framing.0-10/structs.rb3
-rw-r--r--qpid/cpp/src/CMakeLists.txt277
-rw-r--r--qpid/cpp/src/Makefile.am11
-rw-r--r--qpid/cpp/src/cluster.mk3
-rw-r--r--qpid/cpp/src/qmf.mk120
-rw-r--r--qpid/cpp/src/qmf/ConsoleEngine.cpp1091
-rw-r--r--qpid/cpp/src/qmf/engine/Agent.cpp (renamed from qpid/cpp/src/qmf/AgentEngine.cpp)248
-rw-r--r--qpid/cpp/src/qmf/engine/BrokerProxyImpl.cpp763
-rw-r--r--qpid/cpp/src/qmf/engine/BrokerProxyImpl.h239
-rw-r--r--qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.cpp (renamed from qpid/cpp/src/qmf/ConnectionSettingsImpl.cpp)104
-rw-r--r--qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.h (renamed from qpid/cpp/src/qmf/ConnectionSettingsImpl.h)19
-rw-r--r--qpid/cpp/src/qmf/engine/ConsoleImpl.cpp419
-rw-r--r--qpid/cpp/src/qmf/engine/ConsoleImpl.h145
-rw-r--r--qpid/cpp/src/qmf/engine/MessageImpl.cpp (renamed from qpid/cpp/src/qmf/MessageImpl.cpp)4
-rw-r--r--qpid/cpp/src/qmf/engine/MessageImpl.h (renamed from qpid/cpp/src/qmf/MessageImpl.h)8
-rw-r--r--qpid/cpp/src/qmf/engine/ObjectIdImpl.cpp (renamed from qpid/cpp/src/qmf/ObjectIdImpl.cpp)96
-rw-r--r--qpid/cpp/src/qmf/engine/ObjectIdImpl.h (renamed from qpid/cpp/src/qmf/ObjectIdImpl.h)17
-rw-r--r--qpid/cpp/src/qmf/engine/ObjectImpl.cpp (renamed from qpid/cpp/src/qmf/ObjectImpl.cpp)56
-rw-r--r--qpid/cpp/src/qmf/engine/ObjectImpl.h (renamed from qpid/cpp/src/qmf/ObjectImpl.h)33
-rw-r--r--qpid/cpp/src/qmf/engine/Protocol.cpp (renamed from qpid/cpp/src/qmf/Protocol.cpp)4
-rw-r--r--qpid/cpp/src/qmf/engine/Protocol.h (renamed from qpid/cpp/src/qmf/Protocol.h)6
-rw-r--r--qpid/cpp/src/qmf/engine/QueryImpl.cpp (renamed from qpid/cpp/src/qmf/QueryImpl.cpp)15
-rw-r--r--qpid/cpp/src/qmf/engine/QueryImpl.h (renamed from qpid/cpp/src/qmf/QueryImpl.h)34
-rw-r--r--qpid/cpp/src/qmf/engine/ResilientConnection.cpp (renamed from qpid/cpp/src/qmf/ResilientConnection.cpp)53
-rw-r--r--qpid/cpp/src/qmf/engine/SchemaImpl.cpp (renamed from qpid/cpp/src/qmf/SchemaImpl.cpp)221
-rw-r--r--qpid/cpp/src/qmf/engine/SchemaImpl.h (renamed from qpid/cpp/src/qmf/SchemaImpl.h)75
-rw-r--r--qpid/cpp/src/qmf/engine/SequenceManager.cpp (renamed from qpid/cpp/src/qmf/SequenceManager.cpp)10
-rw-r--r--qpid/cpp/src/qmf/engine/SequenceManager.h (renamed from qpid/cpp/src/qmf/SequenceManager.h)10
-rw-r--r--qpid/cpp/src/qmf/engine/ValueImpl.cpp (renamed from qpid/cpp/src/qmf/ValueImpl.cpp)390
-rw-r--r--qpid/cpp/src/qmf/engine/ValueImpl.h (renamed from qpid/cpp/src/qmf/ValueImpl.h)32
-rw-r--r--qpid/cpp/src/qpid/acl/AclData.cpp109
-rw-r--r--qpid/cpp/src/qpid/agent/ManagementAgentImpl.cpp53
-rw-r--r--qpid/cpp/src/qpid/agent/ManagementAgentImpl.h11
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/Connection.cpp21
-rw-r--r--qpid/cpp/src/qpid/amqp_0_10/Connection.h2
-rw-r--r--qpid/cpp/src/qpid/broker/AclModule.h22
-rw-r--r--qpid/cpp/src/qpid/broker/Broker.cpp16
-rw-r--r--qpid/cpp/src/qpid/broker/Broker.h3
-rw-r--r--qpid/cpp/src/qpid/broker/DirectExchange.cpp33
-rw-r--r--qpid/cpp/src/qpid/broker/DtxAck.cpp22
-rw-r--r--qpid/cpp/src/qpid/broker/Exchange.cpp34
-rw-r--r--qpid/cpp/src/qpid/broker/Exchange.h3
-rw-r--r--qpid/cpp/src/qpid/broker/FanOutExchange.cpp32
-rw-r--r--qpid/cpp/src/qpid/broker/HeadersExchange.cpp29
-rw-r--r--qpid/cpp/src/qpid/broker/Message.cpp110
-rw-r--r--qpid/cpp/src/qpid/broker/Message.h17
-rw-r--r--qpid/cpp/src/qpid/broker/MessageBuilder.cpp3
-rw-r--r--qpid/cpp/src/qpid/broker/MessageStoreModule.cpp6
-rw-r--r--qpid/cpp/src/qpid/broker/MessageStoreModule.h5
-rw-r--r--qpid/cpp/src/qpid/broker/PersistableMessage.cpp31
-rw-r--r--qpid/cpp/src/qpid/broker/PersistableMessage.h21
-rw-r--r--qpid/cpp/src/qpid/broker/Queue.cpp102
-rw-r--r--qpid/cpp/src/qpid/broker/Queue.h17
-rw-r--r--qpid/cpp/src/qpid/broker/QueueEvents.cpp41
-rw-r--r--qpid/cpp/src/qpid/broker/QueueEvents.h4
-rw-r--r--qpid/cpp/src/qpid/broker/QueuePolicy.cpp144
-rw-r--r--qpid/cpp/src/qpid/broker/QueuePolicy.h34
-rw-r--r--qpid/cpp/src/qpid/broker/SemanticState.cpp35
-rw-r--r--qpid/cpp/src/qpid/broker/SemanticState.h2
-rw-r--r--qpid/cpp/src/qpid/broker/SessionAdapter.cpp7
-rw-r--r--qpid/cpp/src/qpid/broker/SessionContext.h3
-rw-r--r--qpid/cpp/src/qpid/broker/SessionState.h2
-rw-r--r--qpid/cpp/src/qpid/broker/SignalHandler.cpp2
-rw-r--r--qpid/cpp/src/qpid/broker/SignalHandler.h3
-rw-r--r--qpid/cpp/src/qpid/broker/TopicExchange.cpp43
-rw-r--r--qpid/cpp/src/qpid/broker/TxAccept.cpp8
-rw-r--r--qpid/cpp/src/qpid/broker/TxPublish.cpp54
-rw-r--r--qpid/cpp/src/qpid/broker/TxPublish.h14
-rw-r--r--qpid/cpp/src/qpid/client/ConnectionHandler.cpp1
-rw-r--r--qpid/cpp/src/qpid/client/ConnectionHandler.h2
-rw-r--r--qpid/cpp/src/qpid/client/ConnectionImpl.cpp6
-rw-r--r--qpid/cpp/src/qpid/client/Connector.cpp82
-rw-r--r--qpid/cpp/src/qpid/client/RdmaConnector.cpp15
-rw-r--r--qpid/cpp/src/qpid/client/Sasl.h1
-rw-r--r--qpid/cpp/src/qpid/client/SaslFactory.cpp13
-rw-r--r--qpid/cpp/src/qpid/client/SessionImpl.cpp18
-rw-r--r--qpid/cpp/src/qpid/client/SessionImpl.h4
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp11
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp11
-rw-r--r--qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp17
-rw-r--r--qpid/cpp/src/qpid/client/windows/SaslFactory.cpp6
-rw-r--r--qpid/cpp/src/qpid/cluster/Cluster.cpp30
-rw-r--r--qpid/cpp/src/qpid/cluster/ErrorCheck.cpp30
-rw-r--r--qpid/cpp/src/qpid/cluster/ErrorCheck.h1
-rw-r--r--qpid/cpp/src/qpid/cluster/Event.cpp9
-rw-r--r--qpid/cpp/src/qpid/cluster/Multicaster.cpp4
-rw-r--r--qpid/cpp/src/qpid/cluster/Multicaster.h3
-rw-r--r--qpid/cpp/src/qpid/cluster/OutputInterceptor.cpp12
-rw-r--r--qpid/cpp/src/qpid/cluster/UpdateClient.cpp9
-rw-r--r--qpid/cpp/src/qpid/cluster/UpdateExchange.h2
-rw-r--r--qpid/cpp/src/qpid/messaging/ListContent.cpp98
-rw-r--r--qpid/cpp/src/qpid/messaging/ListView.cpp63
-rw-r--r--qpid/cpp/src/qpid/messaging/MapContent.cpp87
-rw-r--r--qpid/cpp/src/qpid/messaging/MapView.cpp63
-rw-r--r--qpid/cpp/src/qpid/messaging/Message.cpp28
-rw-r--r--qpid/cpp/src/qpid/messaging/MessageImpl.cpp149
-rw-r--r--qpid/cpp/src/qpid/messaging/MessageImpl.h54
-rw-r--r--qpid/cpp/src/qpid/sys/AsynchIO.h6
-rw-r--r--qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp39
-rw-r--r--qpid/cpp/src/qpid/sys/AsynchIOHandler.h2
-rw-r--r--qpid/cpp/src/qpid/sys/LatencyTracker.h157
-rw-r--r--qpid/cpp/src/qpid/sys/RdmaIOPlugin.cpp20
-rw-r--r--qpid/cpp/src/qpid/sys/Socket.h2
-rw-r--r--qpid/cpp/src/qpid/sys/SocketAddress.h51
-rw-r--r--qpid/cpp/src/qpid/sys/TCPIOPlugin.cpp27
-rw-r--r--qpid/cpp/src/qpid/sys/posix/AsynchIO.cpp31
-rw-r--r--qpid/cpp/src/qpid/sys/posix/Socket.cpp55
-rw-r--r--qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp71
-rw-r--r--qpid/cpp/src/qpid/sys/rdma/RdmaClient.cpp17
-rw-r--r--qpid/cpp/src/qpid/sys/rdma/RdmaIO.cpp5
-rw-r--r--qpid/cpp/src/qpid/sys/rdma/RdmaIO.h9
-rw-r--r--qpid/cpp/src/qpid/sys/rdma/RdmaServer.cpp12
-rw-r--r--qpid/cpp/src/qpid/sys/rdma/rdma_wrap.h9
-rw-r--r--qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp2
-rw-r--r--qpid/cpp/src/qpid/xml/XmlExchange.cpp39
-rw-r--r--qpid/cpp/src/qpidd.cpp34
-rw-r--r--qpid/cpp/src/tests/AsyncCompletion.cpp6
-rw-r--r--qpid/cpp/src/tests/ClusterFixture.h4
-rw-r--r--qpid/cpp/src/tests/ExchangeTest.cpp2
-rw-r--r--qpid/cpp/src/tests/Makefile.am64
-rw-r--r--qpid/cpp/src/tests/MessageUtils.h5
-rw-r--r--qpid/cpp/src/tests/MessagingSessionTests.cpp83
-rw-r--r--qpid/cpp/src/tests/PartialFailure.cpp5
-rw-r--r--qpid/cpp/src/tests/QueuePolicyTest.cpp58
-rw-r--r--qpid/cpp/src/tests/QueueTest.cpp341
-rw-r--r--qpid/cpp/src/tests/TxPublishTest.cpp2
-rwxr-xr-xqpid/cpp/src/tests/acl.py126
-rwxr-xr-xqpid/cpp/src/tests/ais_check35
-rw-r--r--qpid/cpp/src/tests/background.ps121
-rw-r--r--qpid/cpp/src/tests/cluster.mk5
-rwxr-xr-xqpid/cpp/src/tests/cluster_read_credit27
-rw-r--r--qpid/cpp/src/tests/cluster_test.cpp59
-rwxr-xr-xqpid/cpp/src/tests/clustered_replication_test41
-rwxr-xr-xqpid/cpp/src/tests/federated_cluster_test39
-rwxr-xr-xqpid/cpp/src/tests/federated_topic_test17
-rw-r--r--qpid/cpp/src/tests/python_env.sh26
-rwxr-xr-xqpid/cpp/src/tests/python_tests10
-rw-r--r--qpid/cpp/src/tests/python_tests.ps142
-rw-r--r--qpid/cpp/src/tests/qpid_stream.cpp9
-rw-r--r--qpid/cpp/src/tests/quick_topictest.ps111
-rwxr-xr-xqpid/cpp/src/tests/reliable_replication_test14
-rwxr-xr-xqpid/cpp/src/tests/replication_test43
-rwxr-xr-xqpid/cpp/src/tests/ring_queue_test7
-rwxr-xr-xqpid/cpp/src/tests/run_acl_tests4
-rwxr-xr-xqpid/cpp/src/tests/run_cli_tests6
-rwxr-xr-xqpid/cpp/src/tests/run_cluster_test26
-rwxr-xr-xqpid/cpp/src/tests/run_cluster_tests38
-rwxr-xr-xqpid/cpp/src/tests/run_failover_soak24
-rwxr-xr-xqpid/cpp/src/tests/run_federation_tests4
-rw-r--r--qpid/cpp/src/tests/run_federation_tests.ps165
-rwxr-xr-xqpid/cpp/src/tests/run_header_test2
-rw-r--r--qpid/cpp/src/tests/run_header_test.ps133
-rwxr-xr-xqpid/cpp/src/tests/run_long_cluster_tests3
-rwxr-xr-xqpid/cpp/src/tests/run_ring_queue_test5
-rw-r--r--qpid/cpp/src/tests/run_test.ps13
-rw-r--r--qpid/cpp/src/tests/start_broker.ps121
-rwxr-xr-xqpid/cpp/src/tests/start_cluster9
-rw-r--r--qpid/cpp/src/tests/stop_broker.ps117
-rw-r--r--qpid/cpp/src/tests/test_store.cpp3
-rw-r--r--qpid/cpp/src/tests/topictest.ps132
-rw-r--r--qpid/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp17
-rw-r--r--qpid/cpp/src/windows/QpiddBroker.cpp9
214 files changed, 6720 insertions, 4029 deletions
diff --git a/qpid/cpp/CMakeLists.txt b/qpid/cpp/CMakeLists.txt
index de1353bd11..18a7616d99 100644
--- a/qpid/cpp/CMakeLists.txt
+++ b/qpid/cpp/CMakeLists.txt
@@ -23,26 +23,150 @@ if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
+set (QPID_VERSION_MAJOR 0)
+set (QPID_VERSION_MINOR 6)
+set (qpidc_version ${QPID_VERSION_MAJOR}.${QPID_VERSION_MINOR})
+
enable_testing()
include (CTest)
-set (qpidc_version 0.5)
+# When doing installs, there are a number of components that the item can
+# be associated with. Since there may be different sets of components desired
+# for the various platforms, the component names are defined here. When
+# setting the COMPONENT in an install directive, use these to ensure that
+# the item is installed correctly.
+#
+# This section also has all the setup for various packaging-specific options.
+if (WIN32)
+ set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
+ set (CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/packaging/NSIS\\\\qpid-icon.ico")
+ set (CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/packaging/NSIS\\\\qpid-icon.ico")
+ set (CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/packaging/NSIS\\\\qpid-install-banner.bmp")
-# set(CMAKE_INCLUDE_CURRENT_DIR ON)
+ # Install types; these defines the component sets that are installed.
+ # Each component (below) indicates which of these install type(s) it is
+ # included in. The user can refine the components at install time.
+ set (CPACK_ALL_INSTALL_TYPES Broker Development Full)
-add_subdirectory(managementgen)
-# add_subdirectory(etc)
-add_subdirectory(src)
-# add_subdirectory(docs/api)
-# add_subdirectory(docs/man)
+ set (QPID_COMPONENT_COMMON Common)
+ set (CPACK_COMPONENT_COMMON_INSTALL_TYPES Broker Development Full)
+ set (CPACK_COMPONENT_COMMON_DISPLAY_NAME "Required common runtime items")
+ set (CPACK_COMPONENT_COMMON_DESCRIPTION
+ "Run-time library common to all runtime components in Qpid.\n
+ This item is required by both broker and client components.")
+
+ set (QPID_COMPONENT_BROKER Broker)
+ set (CPACK_COMPONENT_BROKER_DEPENDS Common)
+ set (CPACK_COMPONENT_BROKER_INSTALL_TYPES Broker Full)
+ set (CPACK_COMPONENT_BROKER_DISPLAY_NAME "Broker")
+ set (CPACK_COMPONENT_BROKER_DESCRIPTION
+ "Messaging broker; controls message flow within the system.\n
+ At least one broker is required to run any messaging application.")
+
+ set (QPID_COMPONENT_CLIENT Client)
+ set (CPACK_COMPONENT_CLIENT_DEPENDS Common)
+ set (CPACK_COMPONENT_CLIENT_INSTALL_TYPES Development Full)
+ set (CPACK_COMPONENT_CLIENT_DISPLAY_NAME "Client runtime libraries")
+ set (CPACK_COMPONENT_CLIENT_DESCRIPTION
+ "Runtime library components required to build and execute a client application.")
+
+ set (QPID_COMPONENT_CLIENT_INCLUDE ClientInclude)
+ set (CPACK_COMPONENT_CLIENTINCLUDE_INSTALL_TYPES Development Full)
+ set (CPACK_COMPONENT_CLIENTINCLUDE_DISPLAY_NAME
+ "Client programming header files")
+ set (CPACK_COMPONENT_CLIENTINCLUDE_DESCRIPTION
+ "C++ header files required to build any Qpid messaging application.")
+
+ set (QPID_COMPONENT_QMF QMF)
+ set (CPACK_COMPONENT_QMF_INSTALL_TYPES Development Full)
+ set (CPACK_COMPONENT_QMF_DISPLAY_NAME
+ "Qpid Management Framework (QMF)")
+ set (CPACK_COMPONENT_QMF_DESCRIPTION
+ "QMF Agent allows you to embed QMF management in your program.\n
+ QMF Console allows you to build management programs using QMF.")
+
+ set (QPID_INSTALL_BINDIR bin CACHE STRING
+ "Directory to install user executables")
+ set (QPID_INSTALL_CONFDIR conf CACHE STRING
+ "Directory to install configuration files")
+ set (QPID_INSTALL_DATADIR conf CACHE STRING
+ "Directory to install read-only arch.-independent data root")
+ set (QPID_INSTALL_INCLUDEDIR include CACHE STRING
+ "Directory to install programming header files")
+ set (QPID_INSTALL_LIBDIR bin CACHE STRING
+ "Directory to install library files")
+ set (QPID_INSTALL_SBINDIR bin CACHE STRING
+ "Directory to install system admin executables")
+ set (QPIDC_MODULE_DIR plugins/client CACHE STRING
+ "Directory to load client plug-in modules from")
+ set (QPIDD_MODULE_DIR plugins/broker CACHE STRING
+ "Directory to load broker plug-in modules from")
+endif (WIN32)
+if (CMAKE_SYSTEM_NAME STREQUAL Linux)
+ # Set up install locations. Since the Linux install puts some files in
+ # /etc and most in the install location, we need to use a DESTDIR build
+ # rather than the usual simple use of CPACK_INSTALL_PREFIX.
+ set (CPACK_SET_DESTDIR ON)
-# if (WIN32)
-# do something Microsoft specific
-# endif (WIN32)
+ set (QPID_COMPONENT_BROKER runtime)
+ set (QPID_COMPONENT_CLIENT runtime)
+ set (QPID_COMPONENT_COMMON runtime)
+ set (CPACK_COMPONENT_RUNTIME_DISPLAY_NAME
+ "Items required to run broker and/or client programs")
+ set (QPID_COMPONENT_CLIENT_INCLUDE development)
+ set (QPID_COMPONENT_QMF development)
+ set (CPACK_COMPONENT_DEVELOPMENT_DISPLAY_NAME
+ "Items required to build new C++ Qpid client programs")
+
+
+ set (QPID_INSTALL_BINDIR bin CACHE STRING
+ "Directory to install user executables")
+ set (QPID_INSTALL_CONFDIR /etc/qpid CACHE STRING
+ "Directory to install configuration files")
+ set (QPID_INSTALL_DATADIR share/qpid CACHE STRING
+ "Directory to install read-only arch.-independent data root")
+ set (QPID_INSTALL_INCLUDEDIR include CACHE STRING
+ "Directory to install programming header files")
+ set (QPID_INSTALL_LIBDIR lib CACHE STRING
+ "Directory to install library files")
+ set (QPID_INSTALL_SBINDIR sbin CACHE STRING
+ "Directory to install system admin executables")
+ set (QPIDC_MODULE_DIR ${QPID_INSTALL_LIBDIR}/qpid/client CACHE STRING
+ "Directory to load client plug-in modules from")
+ set (QPIDD_MODULE_DIR ${QPID_INSTALL_LIBDIR}/qpid/daemon CACHE STRING
+ "Directory to load broker plug-in modules from")
+endif (CMAKE_SYSTEM_NAME STREQUAL Linux)
+
+set (QPIDC_CONF_FILE ${QPID_INSTALL_CONFDIR}/qpidc.conf CACHE STRING
+ "Name of the Qpid client configuration file")
+set (QPIDD_CONF_FILE ${QPID_INSTALL_CONFDIR}/qpidd.conf CACHE STRING
+ "Name of the Qpid broker configuration file")
install(FILES LICENSE NOTICE README SSL RELEASE_NOTES DESIGN
xml/cluster.xml INSTALL-WINDOWS
- DESTINATION .)
+ DESTINATION ${QPID_INSTALL_DATADIR})
+
+if (WIN32)
+ set (CMAKE_DEBUG_POSTFIX "d")
+endif (WIN32)
+
+# set(CMAKE_INCLUDE_CURRENT_DIR ON)
+add_subdirectory(managementgen)
+add_subdirectory(etc)
+add_subdirectory(src)
+# add_subdirectory(docs/api)
+# add_subdirectory(docs/man)
add_subdirectory(examples)
+
+set(CPACK_PACKAGE_NAME "qpid-cpp")
+set(CPACK_PACKAGE_VENDOR "Apache Software Foundation")
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Apache Qpid C++")
+set(CPACK_PACKAGE_VERSION "${qpidc_version}")
+set(CPACK_PACKAGE_VERSION_MAJOR "${QPID_VERSION_MAJOR}")
+set(CPACK_PACKAGE_VERSION_MINOR "${QPID_VERSION_MINOR}")
+set(CPACK_PACKAGE_VERSION_PATCH "0")
+set(CPACK_PACKAGE_INSTALL_DIRECTORY "qpidc-${qpidc_version}")
+
+include (CPack)
diff --git a/qpid/cpp/bindings/qmf/python/Makefile.am b/qpid/cpp/bindings/qmf/python/Makefile.am
index 55d9079fb7..53303c7be9 100644
--- a/qpid/cpp/bindings/qmf/python/Makefile.am
+++ b/qpid/cpp/bindings/qmf/python/Makefile.am
@@ -38,7 +38,7 @@ lib_LTLIBRARIES = _qmfengine.la
#_qmfengine_la_LDFLAGS = -avoid-version -module -shrext "$(PYTHON_SO)"
#_qmfengine_la_LDFLAGS = -avoid-version -module -shrext ".so"
_qmfengine_la_LDFLAGS = -avoid-version -module -shared
-_qmfengine_la_LIBADD = $(PYTHON_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfagent.la
+_qmfengine_la_LIBADD = $(PYTHON_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmf.la
_qmfengine_la_CXXFLAGS = $(INCLUDES) -I$(srcdir)/qmf -I$(PYTHON_INC)
nodist__qmfengine_la_SOURCES = qmfengine.cpp
diff --git a/qpid/cpp/bindings/qmf/python/qmf.py b/qpid/cpp/bindings/qmf/python/qmf.py
index 4800b327f1..383baad0e3 100644
--- a/qpid/cpp/bindings/qmf/python/qmf.py
+++ b/qpid/cpp/bindings/qmf/python/qmf.py
@@ -566,7 +566,7 @@ class Console:
# attr_reader :impl
def initialize(handler=None, kwargs={}):
self._handler = handler
- self.impl = qmfengine.ConsoleEngine()
+ self.impl = qmfengine.Console()
self._event = qmfengine.ConsoleEvent()
self._broker_list = []
@@ -741,7 +741,7 @@ class Agent(ConnectionHandler):
self._agentLabel = label
self._conn = None
self._handler = handler
- self.impl = qmfengine.AgentEngine(self._agentLabel)
+ self.impl = qmfengine.Agent(self._agentLabel)
self._event = qmfengine.AgentEvent()
self._xmtMessage = qmfengine.Message()
diff --git a/qpid/cpp/bindings/qmf/qmfengine.i b/qpid/cpp/bindings/qmf/qmfengine.i
index d3500c9b8f..3477215254 100644
--- a/qpid/cpp/bindings/qmf/qmfengine.i
+++ b/qpid/cpp/bindings/qmf/qmfengine.i
@@ -19,34 +19,35 @@
%{
-#include "qmf/AgentEngine.h"
-#include "qmf/ConsoleEngine.h"
-#include "qmf/ResilientConnection.h"
+#include "qmf/engine/Agent.h"
+#include "qmf/engine/Console.h"
+#include "qmf/engine/ResilientConnection.h"
%}
-%include <qmf/QmfImportExport.h>
-%include <qmf/Query.h>
-%include <qmf/Message.h>
-%include <qmf/AgentEngine.h>
-%include <qmf/ConsoleEngine.h>
-%include <qmf/ConnectionSettings.h>
-%include <qmf/ResilientConnection.h>
-%include <qmf/Typecode.h>
-%include <qmf/Schema.h>
-%include <qmf/Value.h>
-%include <qmf/ObjectId.h>
-%include <qmf/Object.h>
+%include <qmf/engine/QmfEngineImportExport.h>
+%include <qmf/engine/Query.h>
+%include <qmf/engine/Message.h>
+%include <qmf/engine/Agent.h>
+%include <qmf/engine/Console.h>
+%include <qmf/engine/ConnectionSettings.h>
+%include <qmf/engine/ResilientConnection.h>
+%include <qmf/engine/Typecode.h>
+%include <qmf/engine/Schema.h>
+%include <qmf/engine/Value.h>
+%include <qmf/engine/ObjectId.h>
+%include <qmf/engine/Object.h>
%inline {
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
namespace qmf {
+namespace engine {
-
+}
}
}
diff --git a/qpid/cpp/bindings/qmf/ruby/Makefile.am b/qpid/cpp/bindings/qmf/ruby/Makefile.am
index 0537dd1cd8..34096da9ee 100644
--- a/qpid/cpp/bindings/qmf/ruby/Makefile.am
+++ b/qpid/cpp/bindings/qmf/ruby/Makefile.am
@@ -23,23 +23,22 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src
EXTRA_DIST = ruby.i
BUILT_SOURCES = qmfengine.cpp
-generated_file_list = qmfengine.cpp
rubylibdir = $(RUBY_LIB)
dist_rubylib_DATA = qmf.rb
-$(generated_file_list): $(srcdir)/ruby.i $(srcdir)/../qmfengine.i
+qmfengine.cpp: $(srcdir)/ruby.i $(srcdir)/../qmfengine.i
$(SWIG) -ruby -c++ -Wall -I/usr/include $(INCLUDES) $(QPID_CXXFLAGS) -o qmfengine.cpp $(srcdir)/ruby.i
rubylibarchdir = $(RUBY_LIB_ARCH)
rubylibarch_LTLIBRARIES = qmfengine.la
qmfengine_la_LDFLAGS = -avoid-version -module -shrext ".$(RUBY_DLEXT)"
-qmfengine_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfagent.la
+qmfengine_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfengine.la
qmfengine_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH)
nodist_qmfengine_la_SOURCES = qmfengine.cpp
-CLEANFILES = $(generated_file_list)
+CLEANFILES = qmfengine.cpp
endif # HAVE_RUBY_DEVEL
diff --git a/qpid/cpp/bindings/qmf/ruby/qmf.rb b/qpid/cpp/bindings/qmf/ruby/qmf.rb
index 16f1058f4a..fbf95215fd 100644
--- a/qpid/cpp/bindings/qmf/ruby/qmf.rb
+++ b/qpid/cpp/bindings/qmf/ruby/qmf.rb
@@ -60,7 +60,19 @@ module Qmf
raise ArgumentError, "Value for attribute '#{key}' has unsupported type: #{val.class}"
end
- @impl.setAttr(key, v)
+ good = @impl.setAttr(key, v)
+ raise "Invalid attribute '#{key}'" unless good
+ end
+
+ def method_missing(name_in, *args)
+ name = name_in.to_s
+ if name[name.length - 1] == 61
+ attr = name[0..name.length - 2]
+ set_attr(attr, args[0])
+ return
+ end
+
+ super.method_missing(name_in, args)
end
end
@@ -85,12 +97,17 @@ module Qmf
@new_conn_handlers = []
@conn_handlers_to_delete = []
@conn_handlers = []
+ @connected = nil
@thread = Thread.new do
run
end
end
+ def connected?
+ @connected
+ end
+
def kick
@sockEngine.write(".")
@sockEngine.flush
@@ -112,7 +129,6 @@ module Qmf
def run()
eventImpl = Qmfengine::ResilientConnectionEvent.new
- connected = nil
new_handlers = nil
del_handlers = nil
bt_count = 0
@@ -129,7 +145,7 @@ module Qmf
new_handlers.each do |nh|
@conn_handlers << nh
- nh.conn_event_connected() if connected
+ nh.conn_event_connected() if @connected
end
new_handlers = nil
@@ -143,10 +159,10 @@ module Qmf
begin
case eventImpl.kind
when Qmfengine::ResilientConnectionEvent::CONNECTED
- connected = :true
+ @connected = :true
@conn_handlers.each { |h| h.conn_event_connected() }
when Qmfengine::ResilientConnectionEvent::DISCONNECTED
- connected = nil
+ @connected = nil
@conn_handlers.each { |h| h.conn_event_disconnected(eventImpl.errorText) }
when Qmfengine::ResilientConnectionEvent::SESSION_CLOSED
eventImpl.sessionContext.handler.sess_event_session_closed(eventImpl.sessionContext, eventImpl.errorText)
@@ -189,8 +205,16 @@ module Qmf
##==============================================================================
class QmfObject
+ include MonitorMixin
attr_reader :impl, :object_class
def initialize(cls, kwargs={})
+ super()
+ @cv = new_cond
+ @sync_count = 0
+ @sync_result = nil
+ @allow_sets = :false
+ @broker = kwargs[:broker] if kwargs.include?(:broker)
+
if cls:
@object_class = cls
@impl = Qmfengine::Object.new(@object_class.impl)
@@ -204,6 +228,22 @@ module Qmf
return ObjectId.new(@impl.getObjectId)
end
+ def properties
+ list = []
+ @object_class.properties.each do |prop|
+ list << [prop, get_attr(prop.name)]
+ end
+ return list
+ end
+
+ def statistics
+ list = []
+ @object_class.statistics.each do |stat|
+ list << [stat, get_attr(stat.name)]
+ end
+ return list
+ end
+
def get_attr(name)
val = value(name)
case val.getType
@@ -212,7 +252,7 @@ module Qmf
when TYPE_SSTR, TYPE_LSTR then val.asString
when TYPE_ABSTIME then val.asInt64
when TYPE_DELTATIME then val.asUint64
- when TYPE_REF then val.asObjectId
+ when TYPE_REF then ObjectId.new(val.asObjectId)
when TYPE_BOOL then val.asBool
when TYPE_FLOAT then val.asFloat
when TYPE_DOUBLE then val.asDouble
@@ -264,6 +304,103 @@ module Qmf
set_attr(name, get_attr(name) - by)
end
+ def method_missing(name_in, *args)
+ #
+ # Convert the name to a string and determine if it represents an
+ # attribute assignment (i.e. "attr=")
+ #
+ name = name_in.to_s
+ attr_set = (name[name.length - 1] == 61)
+ name = name[0..name.length - 2] if attr_set
+ raise "Sets not permitted on this object" if attr_set && !@allow_sets
+
+ #
+ # If the name matches a property name, set or return the value of the property.
+ #
+ @object_class.properties.each do |prop|
+ if prop.name == name
+ if attr_set
+ return set_attr(name, args[0])
+ else
+ return get_attr(name)
+ end
+ end
+ end
+
+ #
+ # Do the same for statistics
+ #
+ @object_class.statistics.each do |stat|
+ if stat.name == name
+ if attr_set
+ return set_attr(name, args[0])
+ else
+ return get_attr(name)
+ end
+ end
+ end
+
+ #
+ # If we still haven't found a match for the name, check to see if
+ # it matches a method name. If so, marshall the arguments and invoke
+ # the method.
+ #
+ @object_class.methods.each do |method|
+ if method.name == name
+ raise "Sets not permitted on methods" if attr_set
+ timeout = 30
+ synchronize do
+ @sync_count = 1
+ @impl.invokeMethod(name, _marshall(method, args), self)
+ @broker.conn.kick if @broker
+ unless @cv.wait(timeout) { @sync_count == 0 }
+ raise "Timed out waiting for response"
+ end
+ end
+
+ return @sync_result
+ end
+ end
+
+ #
+ # This name means nothing to us, pass it up the line to the parent
+ # class's handler.
+ #
+ super.method_missing(name_in, args)
+ end
+
+ def _method_result(result)
+ synchronize do
+ @sync_result = result
+ @sync_count -= 1
+ @cv.signal
+ end
+ end
+
+ #
+ # Convert a Ruby array of arguments (positional) into a Value object of type "map".
+ #
+ private
+ def _marshall(schema, args)
+ map = Qmfengine::Value.new(TYPE_MAP)
+ schema.arguments.each do |arg|
+ if arg.direction == DIR_IN || arg.direction == DIR_IN_OUT
+ map.insert(arg.name, Qmfengine::Value.new(arg.typecode))
+ end
+ end
+
+ marshalled = Arguments.new(map)
+ idx = 0
+ schema.arguments.each do |arg|
+ if arg.direction == DIR_IN || arg.direction == DIR_IN_OUT
+ marshalled[arg.name] = args[idx] unless args[idx] == nil
+ idx += 1
+ end
+ end
+
+ return marshalled.map
+ end
+
private
def value(name)
val = @impl.getValue(name.to_s)
@@ -277,6 +414,7 @@ module Qmf
class AgentObject < QmfObject
def initialize(cls, kwargs={})
super(cls, kwargs)
+ @allow_sets = :true
end
def destroy
@@ -296,20 +434,22 @@ module Qmf
end
def update()
+ raise "No linkage to broker" unless @broker
+ newer = @broker.console.objects(Query.new(:object_id => object_id))
+ raise "Expected exactly one update for this object" unless newer.size == 1
+ merge_update(newer[0])
end
- def mergeUpdate(newObject)
+ def merge_update(new_object)
+ @impl.merge(new_object.impl)
end
def deleted?()
- @delete_time > 0
+ @impl.isDeleted
end
def index()
end
-
- def method_missing(name, *args)
- end
end
class ObjectId
@@ -323,17 +463,29 @@ module Qmf
end
def object_num_high
- return @impl.getObjectNumHi
+ @impl.getObjectNumHi
end
def object_num_low
- return @impl.getObjectNumLo
+ @impl.getObjectNumLo
+ end
+
+ def broker_bank
+ @impl.getBrokerBank
+ end
+
+ def agent_bank
+ @impl.getAgentBank
end
def ==(other)
return (@impl.getObjectNumHi == other.impl.getObjectNumHi) &&
(@impl.getObjectNumLo == other.impl.getObjectNumLo)
end
+
+ def to_s
+ @impl.str
+ end
end
class Arguments
@@ -362,6 +514,14 @@ module Qmf
@by_hash.each { |k, v| yield(k, v) }
end
+ def method_missing(name, *args)
+ if @by_hash.include?(name.to_s)
+ return @by_hash[name.to_s]
+ end
+
+ super.method_missing(name, args)
+ end
+
def by_key(key)
val = @map.byKey(key)
case val.getType
@@ -370,7 +530,7 @@ module Qmf
when TYPE_SSTR, TYPE_LSTR then val.asString
when TYPE_ABSTIME then val.asInt64
when TYPE_DELTATIME then val.asUint64
- when TYPE_REF then val.asObjectId
+ when TYPE_REF then ObjectId.new(val.asObjectId)
when TYPE_BOOL then val.asBool
when TYPE_FLOAT then val.asFloat
when TYPE_DOUBLE then val.asDouble
@@ -407,6 +567,32 @@ module Qmf
end
end
+ class MethodResponse
+ def initialize(impl)
+ @impl = Qmfengine::MethodResponse.new(impl)
+ end
+
+ def status
+ @impl.getStatus
+ end
+
+ def exception
+ @impl.getException
+ end
+
+ def text
+ exception.asString
+ end
+
+ def args
+ Arguments.new(@impl.getArgs)
+ end
+
+ def method_missing(name, *extra_args)
+ args.__send__(name, extra_args)
+ end
+ end
+
##==============================================================================
## QUERY
##==============================================================================
@@ -421,13 +607,13 @@ module Qmf
if kwargs.include?(:key)
@impl = Qmfengine::Query.new(kwargs[:key])
elsif kwargs.include?(:object_id)
- @impl = Qmfengine::Query.new(kwargs[:object_id])
+ @impl = Qmfengine::Query.new(kwargs[:object_id].impl)
else
package = kwargs[:package] if kwargs.include?(:package)
if kwargs.include?(:class)
@impl = Qmfengine::Query.new(kwargs[:class], package)
else
- raise ArgumentError, "Invalid arguments, use :key or :class[,:package]"
+ raise ArgumentError, "Invalid arguments, use :key, :object_id or :class[,:package]"
end
end
end
@@ -470,6 +656,18 @@ module Qmf
def name
@impl.getName
end
+
+ def direction
+ @impl.getDirection
+ end
+
+ def typecode
+ @impl.getType
+ end
+
+ def to_s
+ name
+ end
end
class SchemaMethod
@@ -496,6 +694,10 @@ module Qmf
def name
@impl.getName
end
+
+ def to_s
+ name
+ end
end
class SchemaProperty
@@ -516,6 +718,10 @@ module Qmf
def name
@impl.getName
end
+
+ def to_s
+ name
+ end
end
class SchemaStatistic
@@ -533,6 +739,10 @@ module Qmf
def name
@impl.getName
end
+
+ def to_s
+ name
+ end
end
class SchemaClassKey
@@ -541,12 +751,16 @@ module Qmf
@impl = i
end
- def get_package()
- @impl.getPackageName()
+ def package_name
+ @impl.getPackageName
+ end
+
+ def class_name
+ @impl.getClassName
end
- def get_class()
- @impl.getClassName()
+ def to_s
+ @impl.asString
end
end
@@ -590,7 +804,15 @@ module Qmf
@impl.addMethod(meth.impl)
end
- def name
+ def class_key
+ SchemaClassKey.new(@impl.getClassKey)
+ end
+
+ def package_name
+ @impl.getClassKey.getPackageName
+ end
+
+ def class_name
@impl.getClassKey.getClassName
end
end
@@ -643,7 +865,7 @@ module Qmf
def initialize(handler = nil, kwargs={})
super()
@handler = handler
- @impl = Qmfengine::ConsoleEngine.new
+ @impl = Qmfengine::Console.new
@event = Qmfengine::ConsoleEvent.new
@broker_list = []
@cv = new_cond
@@ -662,7 +884,7 @@ module Qmf
@broker_list.delete(broker)
end
- def get_packages()
+ def packages()
plist = []
count = @impl.packageCount
for i in 0...count
@@ -671,7 +893,7 @@ module Qmf
return plist
end
- def get_classes(package, kind=CLASS_OBJECT)
+ def classes(package, kind=CLASS_OBJECT)
clist = []
count = @impl.classCount(package)
for i in 0...count
@@ -708,7 +930,7 @@ module Qmf
end
end
- def get_agents(broker = nil)
+ def agents(broker = nil)
blist = []
if broker
blist << broker
@@ -727,11 +949,17 @@ module Qmf
return agents
end
- def get_objects(query, kwargs = {})
+ def objects(query, kwargs = {})
timeout = 30
+ kwargs.merge!(query) if query.class == Hash
+
if kwargs.include?(:timeout)
timeout = kwargs[:timeout]
+ kwargs.delete(:timeout)
end
+
+ query = Query.new(kwargs) if query.class == Hash
+
synchronize do
@sync_count = 1
@sync_result = []
@@ -745,6 +973,18 @@ module Qmf
end
end
+ # Return one and only one object or nil.
+ def object(query, kwargs = {})
+ objs = objects(query, kwargs)
+ return objs.length == 1 ? objs[0] : nil
+ end
+
+ # Return the first of potentially many objects.
+ def first_object(query, kwargs = {})
+ objs = objects(query, kwargs)
+ return objs.length > 0 ? objs[0] : nil
+ end
+
def _get_result(list, context)
synchronize do
list.each do |item|
@@ -769,15 +1009,20 @@ module Qmf
valid = @impl.getEvent(@event)
while valid
count += 1
- puts "Console Event: #{@event.kind}"
case @event.kind
when Qmfengine::ConsoleEvent::AGENT_ADDED
+ @handler.agent_added(AgentProxy.new(@event.agent, nil)) if @handler
when Qmfengine::ConsoleEvent::AGENT_DELETED
+ @handler.agent_deleted(AgentProxy.new(@event.agent, nil)) if @handler
when Qmfengine::ConsoleEvent::NEW_PACKAGE
+ @handler.new_package(@event.name) if @handler
when Qmfengine::ConsoleEvent::NEW_CLASS
+ @handler.new_class(SchemaClassKey.new(@event.classKey)) if @handler
when Qmfengine::ConsoleEvent::OBJECT_UPDATE
+ @handler.object_update(ConsoleObject.new(nil, :impl => @event.object), @event.hasProps, @event.hasStats) if @handler
when Qmfengine::ConsoleEvent::EVENT_RECEIVED
when Qmfengine::ConsoleEvent::AGENT_HEARTBEAT
+ @handler.agent_heartbeat(AgentProxy.new(@event.agent, nil), @event.timestamp) if @handler
when Qmfengine::ConsoleEvent::METHOD_RESPONSE
end
@impl.popEvent
@@ -798,14 +1043,23 @@ module Qmf
def label
@impl.getLabel
end
+
+ def broker_bank
+ @impl.getBrokerBank
+ end
+
+ def agent_bank
+ @impl.getAgentBank
+ end
end
class Broker < ConnectionHandler
include MonitorMixin
- attr_reader :impl
+ attr_reader :impl, :conn, :console, :broker_bank
def initialize(console, conn)
super()
+ @broker_bank = 1
@console = console
@conn = conn
@session = nil
@@ -825,7 +1079,7 @@ module Qmf
@operational = :false
end
- def waitForStable(timeout = nil)
+ def wait_for_stable(timeout = nil)
synchronize do
return if @stable
if timeout
@@ -850,7 +1104,6 @@ module Qmf
valid = @impl.getEvent(@event)
while valid
count += 1
- puts "Broker Event: #{@event.kind}"
case @event.kind
when Qmfengine::BrokerEvent::BROKER_INFO
when Qmfengine::BrokerEvent::DECLARE_QUEUE
@@ -871,9 +1124,12 @@ module Qmf
when Qmfengine::BrokerEvent::QUERY_COMPLETE
result = []
for idx in 0...@event.queryResponse.getObjectCount
- result << ConsoleObject.new(nil, :impl => @event.queryResponse.getObject(idx))
+ result << ConsoleObject.new(nil, :impl => @event.queryResponse.getObject(idx), :broker => self)
end
@console._get_result(result, @event.context)
+ when Qmfengine::BrokerEvent::METHOD_RESPONSE
+ obj = @event.context
+ obj._method_result(MethodResponse.new(@event.methodResponse))
end
@impl.popEvent
valid = @impl.getEvent(@event)
@@ -946,7 +1202,7 @@ module Qmf
end
@conn = nil
@handler = handler
- @impl = Qmfengine::AgentEngine.new(@agentLabel)
+ @impl = Qmfengine::Agent.new(@agentLabel)
@event = Qmfengine::AgentEvent.new
@xmtMessage = Qmfengine::Message.new
end
@@ -1050,5 +1306,4 @@ module Qmf
do_events
end
end
-
end
diff --git a/qpid/cpp/bindings/qmf/tests/agent_ruby.rb b/qpid/cpp/bindings/qmf/tests/agent_ruby.rb
index 67591319ee..426a284e7d 100755
--- a/qpid/cpp/bindings/qmf/tests/agent_ruby.rb
+++ b/qpid/cpp/bindings/qmf/tests/agent_ruby.rb
@@ -40,6 +40,9 @@ class Model
@parent_class.add_property(Qmf::SchemaProperty.new("int16val", Qmf::TYPE_INT16))
@parent_class.add_property(Qmf::SchemaProperty.new("int8val", Qmf::TYPE_INT8))
+ @parent_class.add_property(Qmf::SchemaProperty.new("sstrval", Qmf::TYPE_SSTR))
+ @parent_class.add_property(Qmf::SchemaProperty.new("lstrval", Qmf::TYPE_LSTR))
+
@parent_class.add_statistic(Qmf::SchemaStatistic.new("queryCount", Qmf::TYPE_UINT32, :unit => "query", :desc => "Query count"))
method = Qmf::SchemaMethod.new("echo", :desc => "Check responsiveness of the agent object")
@@ -50,6 +53,14 @@ class Model
method.add_argument(Qmf::SchemaArgument.new("test", Qmf::TYPE_SSTR, :dir => Qmf::DIR_IN))
@parent_class.add_method(method)
+ method = Qmf::SchemaMethod.new("set_short_string", :desc => "Set the short string value in the object")
+ method.add_argument(Qmf::SchemaArgument.new("value", Qmf::TYPE_SSTR, :dir => Qmf::DIR_IN_OUT))
+ @parent_class.add_method(method)
+
+ method = Qmf::SchemaMethod.new("set_long_string", :desc => "Set the long string value in the object")
+ method.add_argument(Qmf::SchemaArgument.new("value", Qmf::TYPE_LSTR, :dir => Qmf::DIR_IN_OUT))
+ @parent_class.add_method(method)
+
method = Qmf::SchemaMethod.new("create_child", :desc => "Create a new child object")
method.add_argument(Qmf::SchemaArgument.new("child_name", Qmf::TYPE_LSTR, :dir => Qmf::DIR_IN))
method.add_argument(Qmf::SchemaArgument.new("child_ref", Qmf::TYPE_REF, :dir => Qmf::DIR_OUT))
@@ -84,68 +95,74 @@ class App < Qmf::AgentHandler
def method_call(context, name, object_id, args, userId)
# puts "Method: user=#{userId} context=#{context} method=#{name} object_num=#{object_id.object_num_low if object_id} args=#{args}"
+ retCode = 0
+ retText = "OK"
+
if name == "echo"
@agent.method_response(context, 0, "OK", args)
elsif name == "set_numerics"
- retCode = 0
- retText = "OK"
if args['test'] == "big"
- @parent.set_attr("uint64val", 0x9494949449494949)
- @parent.set_attr("uint32val", 0xa5a55a5a)
- @parent.set_attr("uint16val", 0xb66b)
- @parent.set_attr("uint8val", 0xc7)
+ @parent.uint64val = 0x9494949449494949
+ @parent.uint32val = 0xa5a55a5a
+ @parent.uint16val = 0xb66b
+ @parent.uint8val = 0xc7
- @parent.set_attr("int64val", 1000000000000000000)
- @parent.set_attr("int32val", 1000000000)
- @parent.set_attr("int16val", 10000)
- @parent.set_attr("int8val", 100)
+ @parent.int64val = 1000000000000000000
+ @parent.int32val = 1000000000
+ @parent.int16val = 10000
+ @parent.int8val = 100
elsif args['test'] == "small"
- @parent.set_attr("uint64val", 4)
- @parent.set_attr("uint32val", 5)
- @parent.set_attr("uint16val", 6)
- @parent.set_attr("uint8val", 7)
+ @parent.uint64val = 4
+ @parent.uint32val = 5
+ @parent.uint16val = 6
+ @parent.uint8val = 7
- @parent.set_attr("int64val", 8)
- @parent.set_attr("int32val", 9)
- @parent.set_attr("int16val", 10)
- @parent.set_attr("int8val", 11)
+ @parent.int64val = 8
+ @parent.int32val = 9
+ @parent.int16val = 10
+ @parent.int8val = 11
elsif args['test'] == "negative"
- @parent.set_attr("uint64val", 0)
- @parent.set_attr("uint32val", 0)
- @parent.set_attr("uint16val", 0)
- @parent.set_attr("uint8val", 0)
+ @parent.uint64val = 0
+ @parent.uint32val = 0
+ @parent.uint16val = 0
+ @parent.uint8val = 0
- @parent.set_attr("int64val", -10000000000)
- @parent.set_attr("int32val", -100000)
- @parent.set_attr("int16val", -1000)
- @parent.set_attr("int8val", -100)
+ @parent.int64val = -10000000000
+ @parent.int32val = -100000
+ @parent.int16val = -1000
+ @parent.int8val = -100
else
retCode = 1
retText = "Invalid argument value for test"
end
- @agent.method_response(context, retCode, retText, args)
+ elsif name == "set_short_string"
+ @parent.sstrval = args['value']
+
+ elsif name == "set_long_string"
+ @parent.lstrval = args['value']
elsif name == "create_child"
oid = @agent.alloc_object_id(2)
args['child_ref'] = oid
@child = Qmf::AgentObject.new(@model.child_class)
- @child.set_attr("name", args.by_key("child_name"))
+ @child.name = args.by_key("child_name")
@child.set_object_id(oid)
- @agent.method_response(context, 0, "OK", args)
elsif name == "probe_userid"
args['userid'] = userId
- @agent.method_response(context, 0, "OK", args)
else
- @agent.method_response(context, 1, "Unimplemented Method: #{name}", args)
+ retCode = 1
+ retText = "Unimplemented Method: #{name}"
end
+
+ @agent.method_response(context, retCode, retText, args)
end
def main
@@ -161,18 +178,18 @@ class App < Qmf::AgentHandler
@agent.set_connection(@connection)
@parent = Qmf::AgentObject.new(@model.parent_class)
- @parent.set_attr("name", "Parent One")
- @parent.set_attr("state", "OPERATIONAL")
-
- @parent.set_attr("uint64val", 0)
- @parent.set_attr("uint32val", 0)
- @parent.set_attr("uint16val", 0)
- @parent.set_attr("uint8val", 0)
-
- @parent.set_attr("int64val", 0)
- @parent.set_attr("int32val", 0)
- @parent.set_attr("int16val", 0)
- @parent.set_attr("int8val", 0)
+ @parent.name = "Parent One"
+ @parent.state = "OPERATIONAL"
+
+ @parent.uint64val = 0
+ @parent.uint32val = 0
+ @parent.uint16val = 0
+ @parent.uint8val = 0
+
+ @parent.int64val = 0
+ @parent.int32val = 0
+ @parent.int16val = 0
+ @parent.int8val = 0
@parent_oid = @agent.alloc_object_id(1)
@parent.set_object_id(@parent_oid)
diff --git a/qpid/cpp/bindings/qmf/tests/ruby_console.rb b/qpid/cpp/bindings/qmf/tests/ruby_console.rb
index c071829f09..0fa856c724 100755
--- a/qpid/cpp/bindings/qmf/tests/ruby_console.rb
+++ b/qpid/cpp/bindings/qmf/tests/ruby_console.rb
@@ -24,13 +24,46 @@ require 'socket'
class App < Qmf::ConsoleHandler
+ def agent_added(agent)
+ puts "AgentAdded: #{agent.label} broker=#{agent.broker_bank} agent=#{agent.agent_bank}"
+ end
+
+ def agent_deleted(agent)
+ puts "AgentDeleted: #{agent.label}"
+ end
+
+ def new_package(package)
+ puts "NewPackage: #{package}"
+ end
+
+ def new_class(class_key)
+ puts "NewClass: #{class_key}"
+ end
+
+ def object_update(object, hasProps, hasStats)
+ puts "ObjectUpdate: #{object.object_class.class_name} props=#{hasProps} stats=#{hasStats}"
+ puts " broker-bank=#{object.object_id.broker_bank}"
+ puts " agent-bank=#{object.object_id.agent_bank}"
+ puts " package=#{object.object_class.package_name}"
+ end
+
+ def event_received(event); end
+
+ def agent_heartbeat(agent, timestamp)
+ puts "AgentHeartbeat: #{agent.label} time=#{timestamp/1000000000}"
+ end
+
+ def method_response(resp); end
+ def broker_info(broker); end
+
+
def dump_schema
- packages = @qmfc.get_packages
+ packages = @qmfc.packages
puts "----- Packages -----"
packages.each do |p|
puts p
puts " ----- Object Classes -----"
- classes = @qmfc.get_classes(p)
+ classes = @qmfc.classes(p)
classes.each do |c|
puts " #{c.name}"
@@ -59,7 +92,7 @@ class App < Qmf::ConsoleHandler
end
puts " ----- Event Classes -----"
- classes = @qmfc.get_classes(p, Qmf::CLASS_EVENT)
+ classes = @qmfc.classes(p, Qmf::CLASS_EVENT)
classes.each do |c|
puts " #{c.name}"
puts " ---- Args ----"
@@ -74,17 +107,17 @@ class App < Qmf::ConsoleHandler
def main
@settings = Qmf::ConnectionSettings.new
- @settings.set_attr("host", ARGV[0]) if ARGV.size > 0
- @settings.set_attr("port", ARGV[1].to_i) if ARGV.size > 1
+ @settings.host = ARGV[0] if ARGV.size > 0
+ @settings.port = ARGV[1].to_i if ARGV.size > 1
@connection = Qmf::Connection.new(@settings)
- @qmfc = Qmf::Console.new
+ @qmfc = Qmf::Console.new(self)
@broker = @qmfc.add_connection(@connection)
- @broker.waitForStable
+ @broker.wait_for_stable
- dump_schema
+ ##dump_schema
- agents = @qmfc.get_agents()
+ agents = @qmfc.agents()
puts "---- Agents ----"
agents.each do |a|
puts " => #{a.label}"
@@ -92,13 +125,30 @@ class App < Qmf::ConsoleHandler
puts "----"
for idx in 0...20
- blist = @qmfc.get_objects(Qmf::Query.new(:class => "broker"))
+ blist = @qmfc.objects(Qmf::Query.new(:class => "broker"))
puts "---- Brokers ----"
blist.each do |b|
puts " ---- Broker ----"
- puts " systemRef: #{b.get_attr('systemRef')}"
- puts " port : #{b.get_attr('port')}"
- puts " uptime : #{b.get_attr('uptime') / 1000000000}"
+ puts " systemRef: #{b.systemRef}"
+ puts " port : #{b.port}"
+ puts " uptime : #{b.uptime / 1000000000}"
+ puts " properties : #{b.properties}"
+ puts " statistics : #{b.statistics}"
+
+ for rep in 0...1
+ puts " Pinging..."
+ ret = b.echo(45, 'text string')
+ puts " status=#{ret.status} text=#{ret.exception.asString} seq=#{ret.args.sequence} body=#{ret.args.body}"
+ end
+ end
+ puts "----"
+
+ qlist = @qmfc.objects(Qmf::Query.new(:package => "org.apache.qpid.broker",
+ :class => "queue"))
+ puts "---- Queues ----"
+ qlist.each do |q|
+ puts " ---- Queue ----"
+ puts " name : #{q.name}"
end
puts "----"
sleep(5)
diff --git a/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb b/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb
new file mode 100755
index 0000000000..b72c8e3806
--- /dev/null
+++ b/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb
@@ -0,0 +1,194 @@
+#!/usr/bin/ruby
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require 'test_base'
+
+class ConsoleTest < ConsoleTestBase
+
+ def test_A_agent_presence
+ assert(@connection.connected?, "Connection not connected")
+
+ agents = []
+ count = 0
+ while agents.size == 0
+ agents = @qmfc.objects(Qmf::Query.new(:class => "agent"))
+ sleep(1)
+ count += 1
+ fail("Timed out waiting for remote agent") if count > 10
+ end
+
+ agentList = @qmfc.agents
+ assert_equal(agentList.size, 2, "Number of agents reported by Console")
+ end
+
+ def test_A_connection_settings
+ begin
+ @settings.bogusAttribute = 25
+ fail("Connection settings accepted bogus attribute")
+ rescue
+ end
+ end
+
+ def test_B_basic_method_invocation
+ parent = @qmfc.object(:class => "parent")
+ assert(parent, "Number of 'parent' objects")
+ for seq in 0...10
+ result = parent.echo(seq)
+ assert_equal(result.status, 0, "Method Response Status")
+ assert_equal(result.text, "OK", "Method Response Text")
+ assert_equal(result.args.sequence, seq, "Echo Response Sequence")
+ end
+
+ result = parent.set_numerics("bogus")
+ assert_equal(result.status, 1)
+ assert_equal(result.text, "Invalid argument value for test")
+ end
+
+ def test_C_basic_types_numeric_big
+ parent = @qmfc.object(:class =>"parent")
+ assert(parent, "Number of parent objects")
+
+ result = parent.set_numerics("big")
+ assert_equal(result.status, 0, "Method Response Status")
+ assert_equal(result.text, "OK", "Method Response Text")
+
+ parent.update
+
+ assert_equal(parent.uint64val, 0x9494949449494949)
+ assert_equal(parent.uint32val, 0xA5A55A5A)
+ assert_equal(parent.uint16val, 0xB66B)
+ assert_equal(parent.uint8val, 0xC7)
+
+ assert_equal(parent.int64val, 1000000000000000000)
+ assert_equal(parent.int32val, 1000000000)
+ assert_equal(parent.int16val, 10000)
+ assert_equal(parent.int8val, 100)
+ end
+
+ def test_C_basic_types_numeric_small
+ parent = @qmfc.object(:class =>"parent")
+ assert(parent, "Number of parent objects")
+
+ result = parent.set_numerics("small")
+ assert_equal(result.status, 0, "Method Response Status")
+ assert_equal(result.text, "OK", "Method Response Text")
+
+ parent.update
+
+ assert_equal(parent.uint64val, 4)
+ assert_equal(parent.uint32val, 5)
+ assert_equal(parent.uint16val, 6)
+ assert_equal(parent.uint8val, 7)
+
+ assert_equal(parent.int64val, 8)
+ assert_equal(parent.int32val, 9)
+ assert_equal(parent.int16val, 10)
+ assert_equal(parent.int8val, 11)
+ end
+
+ def test_C_basic_types_numeric_negative
+ parent = @qmfc.object(:class =>"parent")
+ assert(parent, "Number of parent objects")
+
+ result = parent.set_numerics("negative")
+ assert_equal(result.status, 0, "Method Response Status")
+ assert_equal(result.text, "OK", "Method Response Text")
+
+ parent.update
+
+ assert_equal(parent.uint64val, 0)
+ assert_equal(parent.uint32val, 0)
+ assert_equal(parent.uint16val, 0)
+ assert_equal(parent.uint8val, 0)
+
+ assert_equal(parent.int64val, -10000000000)
+ assert_equal(parent.int32val, -100000)
+ assert_equal(parent.int16val, -1000)
+ assert_equal(parent.int8val, -100)
+ end
+
+ def test_C_basic_types_string_short
+ parent = @qmfc.object(:class =>"parent")
+ assert(parent, "Number of parent objects")
+
+ strings = []
+ strings << ""
+ strings << "A"
+ strings << "BC"
+ strings << "DEF"
+ strings << "GHIJKLMNOPQRSTUVWXYZ"
+ big = "a"
+ for i in 0...270
+ big << "X"
+ end
+ strings << big
+
+ strings.each do |str|
+ result = parent.set_short_string(str)
+ assert_equal(result.status, 0, "Method Response Status")
+ compare = str
+ compare = compare[0..254] if compare.size > 255
+ assert_equal(result.args.value, compare, "Value returned by method")
+ parent.update
+ assert_equal(parent.sstrval, compare, "Value stored in the object")
+ end
+ end
+
+ def test_C_basic_types_string_long
+ parent = @qmfc.object(:class =>"parent")
+ assert(parent, "Number of parent objects")
+
+ strings = []
+ strings << ""
+ strings << "A"
+ strings << "BC"
+ strings << "DEF"
+ strings << "GHIJKLMNOPQRSTUVWXYZ"
+ big = "a"
+ for i in 0...270
+ big << "X"
+ end
+ strings << big
+
+ strings.each do |str|
+ result = parent.set_long_string(str)
+ assert_equal(result.status, 0, "Method Response Status")
+ assert_equal(result.args.value, str, "Value returned by method")
+ parent.update
+ assert_equal(parent.lstrval, str, "Value stored in the object")
+ end
+ end
+
+ def test_D_userid_for_method
+ parent = @qmfc.object(:class => "parent")
+ assert(parent, "Number of parent objects")
+
+ result = parent.probe_userid
+ assert_equal(result.status, 0, "Method Response Status")
+ assert_equal(result.args.userid, "anonymous")
+ end
+
+end
+
+app = ConsoleTest.new
+
+
+
diff --git a/qpid/cpp/bindings/qmf/tests/run_interop_tests b/qpid/cpp/bindings/qmf/tests/run_interop_tests
index 01d7221ac6..b5545d736d 100755
--- a/qpid/cpp/bindings/qmf/tests/run_interop_tests
+++ b/qpid/cpp/bindings/qmf/tests/run_interop_tests
@@ -88,11 +88,19 @@ if test -d ${PYTHON_DIR} ; then
echo " Ruby agent started at pid $AGENT_PID"
${PYTHON_DIR}/qpid-python-test -m python_console -b localhost:$BROKER_PORT $@
RETCODE=$?
- stop_ruby_agent
if test x$RETCODE != x0; then
echo "FAIL qmf interop tests (Ruby Agent)";
TESTS_FAILED=1
fi
+
+ echo " Ruby Agent (external storage) vs. Ruby Console"
+ ruby -I${MY_DIR} -I${MY_DIR}/../ruby -I${RUBY_LIB_DIR} ${MY_DIR}/ruby_console_test.rb localhost $BROKER_PORT $@
+ RETCODE=$?
+ stop_ruby_agent
+ if test x$RETCODE != x0; then
+ echo "FAIL qmf interop tests (Ruby Console/Ruby Agent)";
+ TESTS_FAILED=1
+ fi
fi
# Also against the Pure-Python console:
diff --git a/qpid/cpp/bindings/qmf/tests/test_base.rb b/qpid/cpp/bindings/qmf/tests/test_base.rb
new file mode 100644
index 0000000000..cb7fd9d4f9
--- /dev/null
+++ b/qpid/cpp/bindings/qmf/tests/test_base.rb
@@ -0,0 +1,73 @@
+#!/usr/bin/ruby
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require 'qmf'
+require 'socket'
+
+class ConsoleTestBase < Qmf::ConsoleHandler
+ def initialize
+ @settings = Qmf::ConnectionSettings.new
+ @settings.host = ARGV[0] if ARGV.size > 0
+ @settings.port = ARGV[1].to_i if ARGV.size > 1
+ @connection = Qmf::Connection.new(@settings)
+ @qmfc = Qmf::Console.new
+
+ @broker = @qmfc.add_connection(@connection)
+ @broker.wait_for_stable
+
+ tests = []
+ methods.each do |m|
+ name = m.to_s
+ tests << name if name[0..4] == "test_"
+ end
+
+ failures = 0
+
+ tests.sort.each do |t|
+ begin
+ print "#{t}..."
+ $stdout.flush
+ send(t)
+ puts " Pass"
+ rescue
+ puts " Fail: #{$!}"
+ failures += 1
+ end
+ end
+
+ @qmfc.del_connection(@broker)
+ exit(1) if failures > 0
+ end
+
+ def assert_equal(left, right, in_text=nil)
+ text = " (#{in_text})" if in_text
+ raise "Assertion failed: #{left} != #{right}#{text}" unless left == right
+ end
+
+ def assert(condition, in_text=nil)
+ text = " (#{in_text})" if in_text
+ raise "Assertion failed: #{left} != #{right}#{text}" unless condition
+ end
+
+ def fail(text)
+ raise text
+ end
+end
diff --git a/qpid/cpp/boost-1.32-support/supressions b/qpid/cpp/boost-1.32-support/supressions
index 0747e32cc7..c2b4392566 100644
--- a/qpid/cpp/boost-1.32-support/supressions
+++ b/qpid/cpp/boost-1.32-support/supressions
@@ -789,3 +789,79 @@
fun:getaddrinfo
fun:_ZNK4qpid3sys6Socket7connectERKSst
}
+{
+ dl 0
+ Memcheck:Leak
+ fun:*dl*
+}
+
+{
+ dl 1
+ Memcheck:Leak
+ fun:*
+ fun:*dl*
+}
+
+{
+ dl 2
+ fun:*
+ fun:*
+ Memcheck:Leak
+ fun:*dl*
+}
+
+{
+ Znwm
+ Memcheck:Leak
+ fun:_Znwm
+}
+
+{
+ Znwj
+ Memcheck:Leak
+ fun:_Znwj
+}
+
+{
+ Znaj
+ Memcheck:Leak
+ fun:_Znaj
+}
+
+{
+ libc res nsend
+ Memcheck:Leak
+ fun:malloc
+ fun:__libc_res_nsend
+}
+
+{
+ new exitfn
+ Memcheck:Leak
+ fun:malloc
+ fun:__new_exitfn
+}
+
+{
+ pthread mutex unlock
+ Memcheck:Param
+ futex(uaddr2)
+ fun:__lll_mutex_unlock_wake
+ fun:pthread_mutex_unlock
+}
+
+{
+ sasl 1
+ Memcheck:Leak
+ fun:*
+ fun:sasl*
+}
+
+{
+ sasl 2
+ Memcheck:Leak
+ fun:*
+ obj:*
+ fun:sasl*
+}
+
diff --git a/qpid/cpp/etc/CMakeLists.txt b/qpid/cpp/etc/CMakeLists.txt
new file mode 100644
index 0000000000..03121b364a
--- /dev/null
+++ b/qpid/cpp/etc/CMakeLists.txt
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+install(FILES qpidd.conf qpidc.conf DESTINATION ${QPID_INSTALL_CONFDIR})
diff --git a/qpid/cpp/examples/messaging/client.cpp b/qpid/cpp/examples/messaging/client.cpp
index 45c065880b..de6d7768df 100644
--- a/qpid/cpp/examples/messaging/client.cpp
+++ b/qpid/cpp/examples/messaging/client.cpp
@@ -63,7 +63,7 @@ int main(int argc, char** argv) {
request.setContent(s[i]);
sender.send(request);
Message response = receiver.fetch();
- std::cout << request.getContent().asString() << " -> " << response.getContent().asString() << std::endl;
+ std::cout << request.getContent() << " -> " << response.getContent() << std::endl;
}
connection.close();
return 0;
diff --git a/qpid/cpp/examples/messaging/map_receiver.cpp b/qpid/cpp/examples/messaging/map_receiver.cpp
index e6557b1560..f97c44eebd 100644
--- a/qpid/cpp/examples/messaging/map_receiver.cpp
+++ b/qpid/cpp/examples/messaging/map_receiver.cpp
@@ -20,6 +20,7 @@
*/
#include <qpid/messaging/Connection.h>
+#include <qpid/messaging/MapView.h>
#include <qpid/messaging/Message.h>
#include <qpid/messaging/Receiver.h>
#include <qpid/messaging/Session.h>
@@ -42,7 +43,8 @@ int main(int argc, char** argv) {
Session session = connection.newSession();
Receiver receiver = session.createReceiver("message_queue");
Message message = receiver.fetch();
- std::cout << message.getContent().asMap() << std::endl;
+ MapView content(message);
+ std::cout << content << std::endl;
session.acknowledge();
receiver.cancel();
connection.close();
diff --git a/qpid/cpp/examples/messaging/map_sender.cpp b/qpid/cpp/examples/messaging/map_sender.cpp
index 9301c1fe1f..02c6433836 100644
--- a/qpid/cpp/examples/messaging/map_sender.cpp
+++ b/qpid/cpp/examples/messaging/map_sender.cpp
@@ -20,6 +20,7 @@
*/
#include <qpid/messaging/Connection.h>
+#include <qpid/messaging/MapContent.h>
#include <qpid/messaging/Message.h>
#include <qpid/messaging/Sender.h>
#include <qpid/messaging/Session.h>
@@ -43,14 +44,16 @@ int main(int argc, char** argv) {
Sender sender = session.createSender("message_queue");
Message message;
- message.getContent()["id"] = 987654321;
- message.getContent()["name"] = "Widget";
- message.getContent()["price"] = 0.99;//bad use of floating point number, just an example!
+ MapContent content(message);
+ content["id"] = 987654321;
+ content["name"] = "Widget";
+ content["price"] = 0.99;//bad use of floating point number, just an example!
Variant::List colours;
colours.push_back(Variant("red"));
colours.push_back(Variant("green"));
colours.push_back(Variant("white"));
- message.getContent()["colours"] = colours;
+ content["colours"] = colours;
+ content.encode();
sender.send(message);
session.sync();
diff --git a/qpid/cpp/examples/messaging/queue_listener.cpp b/qpid/cpp/examples/messaging/queue_listener.cpp
index 099e8e145a..92a0eed5ed 100644
--- a/qpid/cpp/examples/messaging/queue_listener.cpp
+++ b/qpid/cpp/examples/messaging/queue_listener.cpp
@@ -47,8 +47,8 @@ bool Listener::isFinished() { return finished; }
void Listener::received(Message& message)
{
- std::cout << "Message: " << message.getContent().asString() << std::endl;
- if (message.getContent().asString() == "That's all, folks!") {
+ std::cout << "Message: " << message.getContent() << std::endl;
+ if (message.getContent() == "That's all, folks!") {
std::cout << "Shutting down listener" << std::endl;
receiver.cancel();
finished = true;
diff --git a/qpid/cpp/examples/messaging/queue_receiver.cpp b/qpid/cpp/examples/messaging/queue_receiver.cpp
index 83a44b2ca9..40f863eb30 100644
--- a/qpid/cpp/examples/messaging/queue_receiver.cpp
+++ b/qpid/cpp/examples/messaging/queue_receiver.cpp
@@ -24,16 +24,10 @@
#include <qpid/messaging/Receiver.h>
#include <qpid/messaging/Session.h>
-#include <cstdlib>
#include <iostream>
-#include <sstream>
-
using namespace qpid::messaging;
-using std::stringstream;
-using std::string;
-
int main(int argc, char** argv) {
const char* url = argc>1 ? argv[1] : "amqp:tcp:127.0.0.1:5672";
@@ -47,7 +41,7 @@ int main(int argc, char** argv) {
Message message = receiver.fetch();
std::cout << "Message: " << message.getContent() << std::endl;
session.acknowledge();
- if (message.getContent().asString() == "That's all, folks!") {
+ if (message.getContent() == "That's all, folks!") {
std::cout << "Cancelling receiver" << std::endl;
receiver.cancel();
break;
diff --git a/qpid/cpp/examples/messaging/queue_sender.cpp b/qpid/cpp/examples/messaging/queue_sender.cpp
index 637e7eb8e4..1396e26d5c 100644
--- a/qpid/cpp/examples/messaging/queue_sender.cpp
+++ b/qpid/cpp/examples/messaging/queue_sender.cpp
@@ -26,14 +26,10 @@
#include <cstdlib>
#include <iostream>
-
#include <sstream>
using namespace qpid::messaging;
-using std::stringstream;
-using std::string;
-
int main(int argc, char** argv) {
const char* url = argc>1 ? argv[1] : "amqp:tcp:127.0.0.1:5672";
int count = argc>2 ? atoi(argv[2]) : 10;
@@ -45,14 +41,13 @@ int main(int argc, char** argv) {
// Now send some messages ...
for (int i=0; i<count; i++) {
- Message message;
- message.getContent() << "Message " << i;
- sender.send(message);
+ std::stringstream content;
+ content << "Message " << i;
+ sender.send(Message(content.str()));
}
- // And send a final message to indicate termination.
- Message message("That's all, folks!");
- sender.send(message);
+ // And send a final message to indicate termination.
+ sender.send(Message("That's all, folks!"));
session.sync();
connection.close();
return 0;
diff --git a/qpid/cpp/examples/messaging/server.cpp b/qpid/cpp/examples/messaging/server.cpp
index 38f4601ff6..024832f914 100644
--- a/qpid/cpp/examples/messaging/server.cpp
+++ b/qpid/cpp/examples/messaging/server.cpp
@@ -51,17 +51,17 @@ int main(int argc, char** argv) {
const Address& address = request.getReplyTo();
if (address) {
Sender sender = session.createSender(address);
- std::string s = request.getContent().asString();
+ std::string s = request.getContent();
std::transform(s.begin(), s.end(), s.begin(), toupper);
Message response(s);
sender.send(response);
std::cout << "Processed request: "
- << request.getContent().asString()
+ << request.getContent()
<< " -> "
- << response.getContent().asString() << std::endl;
+ << response.getContent() << std::endl;
session.acknowledge();
} else {
- std::cerr << "Error: no reply address specified for request: " << request.getContent().asString() << std::endl;
+ std::cerr << "Error: no reply address specified for request: " << request.getContent() << std::endl;
session.reject(request);
}
}
diff --git a/qpid/cpp/examples/messaging/topic_listener.cpp b/qpid/cpp/examples/messaging/topic_listener.cpp
index 700e03cdf9..ba999c03a7 100644
--- a/qpid/cpp/examples/messaging/topic_listener.cpp
+++ b/qpid/cpp/examples/messaging/topic_listener.cpp
@@ -48,8 +48,8 @@ bool Listener::isFinished() { return finished; }
void Listener::received(Message& message)
{
- std::cout << "Message: " << message.getContent().asString() << std::endl;
- if (message.getContent().asString() == "That's all, folks!") {
+ std::cout << "Message: " << message.getContent() << std::endl;
+ if (message.getContent() == "That's all, folks!") {
std::cout << "Shutting down listener" << std::endl;
receiver.cancel();
finished = true;
diff --git a/qpid/cpp/examples/messaging/topic_receiver.cpp b/qpid/cpp/examples/messaging/topic_receiver.cpp
index 063f0d9cb0..7352a91b30 100644
--- a/qpid/cpp/examples/messaging/topic_receiver.cpp
+++ b/qpid/cpp/examples/messaging/topic_receiver.cpp
@@ -47,8 +47,8 @@ int main(int argc, char** argv) {
Receiver receiver = session.createReceiver(Address("news_service", "topic"), filter);
while (true) {
Message message = receiver.fetch();
- std::cout << "Message: " << message.getContent().asString() << std::endl;
- if (message.getContent().asString() == "That's all, folks!") {
+ std::cout << "Message: " << message.getContent() << std::endl;
+ if (message.getContent() == "That's all, folks!") {
std::cout << "Cancelling receiver" << std::endl;
receiver.cancel();
break;
diff --git a/qpid/cpp/examples/qmf-agent/Makefile b/qpid/cpp/examples/qmf-agent/Makefile
index e652edb1a2..5b1afc4b01 100644
--- a/qpid/cpp/examples/qmf-agent/Makefile
+++ b/qpid/cpp/examples/qmf-agent/Makefile
@@ -27,7 +27,7 @@ CC = gcc
LIB_DIR = $(QPID_DIR)/cpp/src/.libs
CC_INCLUDES = -I$(SRC_DIR) -I$(QPID_DIR)/cpp/include -I$(GEN_DIR)
CC_FLAGS = -g -O3
-LD_FLAGS = -lqmfagent -lqmfcommon -L$(LIB_DIR)
+LD_FLAGS = -lqmf -L$(LIB_DIR)
SPEC_DIR = $(QPID_DIR)/specs
MGEN_DIR = $(QPID_DIR)/cpp/managementgen
MGEN = $(MGEN_DIR)/qmf-gen
diff --git a/qpid/cpp/include/qmf/ConnectionSettings.h b/qpid/cpp/include/qmf/ConnectionSettings.h
index 9bd6922a56..11af73d797 100644
--- a/qpid/cpp/include/qmf/ConnectionSettings.h
+++ b/qpid/cpp/include/qmf/ConnectionSettings.h
@@ -20,124 +20,13 @@
* under the License.
*/
-#include "qmf/QmfImportExport.h"
-#include "qpid/sys/IntegerTypes.h"
-
namespace qmf {
+ namespace engine {
+ class ConnectionSettings;
+ }
- class ConnectionSettingsImpl;
- class Value;
-
- /**
- * Settings for AMQP connections to the broker.
- *
- * \ingroup qmfapi
- */
- class ConnectionSettings {
- public:
-
- ConnectionSettings(const ConnectionSettings& copy);
-
- /**
- * Create a set of default connection settings.
- *
- * If no further attributes are set, the settings will cause a connection to be made to
- * the default broker (on localhost or at a host/port supplied by service discovery) and
- * authentication will be the best-available (GSSAPI/Kerberos, Anonymous, Plain with prompts
- * for username and password).
- */
- QMF_EXTERN ConnectionSettings();
-
- /**
- * Create a set of connection settings by URL.
- *
- * @param url Universal resource locator describing the broker address and additional attributes.
- *
- * The URL is of the form:
- * amqp[s]://host[:port][?key=value[&key=value]*]
- *
- * For example:
- * amqp://localhost
- * amqp://broker?transport=rdma&authmech=GSSAPI&authservice=qpidd
- * amqps://broker?authmech=PLAIN&authuser=guest&authpass=guest
- */
- QMF_EXTERN ConnectionSettings(const char* url);
-
- /**
- * Destroy the connection settings object.
- */
- QMF_EXTERN ~ConnectionSettings();
-
- /**
- * Set an attribute to control connection setup.
- *
- * @param key A null-terminated string that is an attribute name.
- *
- * @param value Reference to a value to be stored as the attribute. The type of the value
- * is specific to the key.
- */
- QMF_EXTERN void setAttr(const char* key, const Value& value);
-
- /**
- * Get the value of an attribute.
- *
- * @param key A null-terminated attribute name.
- *
- * @return The value associated with the attribute name.
- */
- QMF_EXTERN Value getAttr(const char* key) const;
-
- /**
- * Get the attribute string (the portion of the URL following the '?') for the settings.
- *
- * @return A pointer to the attribute string. If the content of this string needs to be
- * available beyond the scope of the calling function, it should be copied. The
- * returned pointer may become invalid if the set of attributes is changed.
- */
- QMF_EXTERN const char* getAttrString() const;
-
- /**
- * Shortcuts for setting the transport for the connection.
- *
- * @param port The port value for the connection address.
- */
- QMF_EXTERN void transportTcp(uint16_t port = 5672);
- QMF_EXTERN void transportSsl(uint16_t port = 5671);
- QMF_EXTERN void transportRdma(uint16_t port = 5672);
-
- /**
- * Shortcuts for setting authentication mechanisms.
- *
- * @param username Null-terminated authentication user name.
- *
- * @param password Null-terminated authentication password.
- *
- * @param serviceName Null-terminated GSSAPI service name (Kerberos service principal)
- *
- * @param minSsf Minimum security factor for connections. 0 = encryption not required.
- *
- * @param maxSsf Maximum security factor for connections. 0 = encryption not permitted.
- */
- QMF_EXTERN void authAnonymous(const char* username = 0);
- QMF_EXTERN void authPlain(const char* username = 0, const char* password = 0);
- QMF_EXTERN void authGssapi(const char* serviceName, uint32_t minSsf = 0, uint32_t maxSsf = 256);
-
- /**
- * Shortcut for setting connection retry attributes.
- *
- * @param delayMin Minimum delay (in seconds) between connection attempts.
- *
- * @param delaxMax Maximum delay (in seconds) between connection attempts.
- *
- * @param delayFactor Factor to multiply the delay by between failed connection attempts.
- */
- QMF_EXTERN void setRetry(int delayMin = 1, int delayMax = 128, int delayFactor = 2);
-
- private:
- friend class ResilientConnectionImpl;
- ConnectionSettingsImpl* impl;
- };
-
+ typedef class engine::ConnectionSettings ConnectionSettings;
}
#endif
+
diff --git a/qpid/cpp/include/qmf/ConsoleObject.h b/qpid/cpp/include/qmf/ConsoleObject.h
new file mode 100644
index 0000000000..acbc285e05
--- /dev/null
+++ b/qpid/cpp/include/qmf/ConsoleObject.h
@@ -0,0 +1,94 @@
+#ifndef _QmfConsoleObject_
+#define _QmfConsoleObject_
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "qmf/QmfImportExport.h"
+
+namespace qmf {
+
+ class ConsoleObjectImpl;
+ class SchemaObjectClass;
+ class ObjectId;
+ class Value;
+
+ /**
+ * ConsoleObject is an extension of Object with console-specific methods added.
+ *
+ * \ingroup qmfapi
+ */
+ class ConsoleObject : public Object {
+ public:
+ /**
+ * Create a new Object of a specific type.
+ *
+ * @param type Pointer to the schema class to use as a type for this object.
+ */
+ QMF_EXTERN ConsoleObject(const SchemaObjectClass* type);
+
+ /**
+ * Destroy the object.
+ */
+ QMF_EXTERN virtual ~ConsoleObject();
+
+ /**
+ *
+ */
+ QMF_EXTERN const SchemaObjectClass* getSchema() const;
+
+ /**
+ *
+ */
+ QMF_EXTERN ObjectId* getObjectId() const;
+
+ /**
+ *
+ */
+ QMF_EXTERN uint64_t getCurrentTime() const;
+ QMF_EXTERN uint64_t getCreateTime() const;
+ QMF_EXTERN uint64_t getDeleteTime() const;
+
+ /**
+ *
+ */
+ QMF_EXTERN bool isDeleted() const;
+
+ /**
+ *
+ */
+ QMF_EXTERN void update();
+
+ /**
+ *
+ */
+ QMF_EXTERN void invokeMethod(const char* name, const Value* arguments, MethodResult& result);
+
+ /**
+ *
+ */
+ QMF_EXTERN uint32_t invokeMethodAsync(const char* name, const Value* arguments = 0);
+
+ private:
+ ConsoleObjectImpl* impl;
+ };
+
+}
+
+#endif
diff --git a/qpid/cpp/src/qmf/AgentEngine.h b/qpid/cpp/include/qmf/engine/Agent.h
index c88ef33657..71abf82254 100644
--- a/qpid/cpp/src/qmf/AgentEngine.h
+++ b/qpid/cpp/include/qmf/engine/Agent.h
@@ -1,5 +1,5 @@
-#ifndef _QmfAgentEngine_
-#define _QmfAgentEngine_
+#ifndef _QmfEngineAgent_
+#define _QmfEngineAgent_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,15 +20,16 @@
* under the License.
*/
-#include <qmf/Schema.h>
-#include <qmf/ObjectId.h>
-#include <qmf/Object.h>
-#include <qmf/Event.h>
-#include <qmf/Query.h>
-#include <qmf/Value.h>
-#include <qmf/Message.h>
+#include <qmf/engine/Schema.h>
+#include <qmf/engine/ObjectId.h>
+#include <qmf/engine/Object.h>
+#include <qmf/engine/Event.h>
+#include <qmf/engine/Query.h>
+#include <qmf/engine/Value.h>
+#include <qmf/engine/Message.h>
namespace qmf {
+namespace engine {
/**
* AgentEvent
@@ -61,18 +62,18 @@ namespace qmf {
Value* arguments; // Method parameters (METHOD_CALL)
char* exchange; // Exchange for bind (BIND, UNBIND)
char* bindingKey; // Key for bind (BIND, UNBIND)
- SchemaObjectClass* objectClass; // (METHOD_CALL)
+ const SchemaObjectClass* objectClass; // (METHOD_CALL)
};
- class AgentEngineImpl;
+ class AgentImpl;
/**
- * AgentEngine - Protocol engine for the QMF agent
+ * Agent - Protocol engine for the QMF agent
*/
- class AgentEngine {
+ class Agent {
public:
- AgentEngine(char* label, bool internalStore=true);
- ~AgentEngine();
+ Agent(char* label, bool internalStore=true);
+ ~Agent();
/**
* Configure the directory path for storing persistent data.
@@ -199,9 +200,10 @@ namespace qmf {
void raiseEvent(Event& event);
private:
- AgentEngineImpl* impl;
+ AgentImpl* impl;
};
}
+}
#endif
diff --git a/qpid/cpp/include/qmf/engine/ConnectionSettings.h b/qpid/cpp/include/qmf/engine/ConnectionSettings.h
new file mode 100644
index 0000000000..36312400b1
--- /dev/null
+++ b/qpid/cpp/include/qmf/engine/ConnectionSettings.h
@@ -0,0 +1,150 @@
+#ifndef _QmfEngineConnectionSettings_
+#define _QmfEngineConnectionSettings_
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "qmf/engine/QmfEngineImportExport.h"
+#include "qpid/sys/IntegerTypes.h"
+
+namespace qmf {
+namespace engine {
+
+ class ConnectionSettingsImpl;
+ class Value;
+
+ /**
+ * Settings for AMQP connections to the broker.
+ *
+ * \ingroup qmfapi
+ */
+ class ConnectionSettings {
+ public:
+
+ /**
+ * Create a set of default connection settings.
+ *
+ * If no further attributes are set, the settings will cause a connection to be made to
+ * the default broker (on localhost or at a host/port supplied by service discovery) and
+ * authentication will be the best-available (GSSAPI/Kerberos, Anonymous, Plain with prompts
+ * for username and password).
+ */
+ QMFE_EXTERN ConnectionSettings();
+
+ /**
+ * Create a set of connection settings by URL.
+ *
+ * @param url Universal resource locator describing the broker address and additional attributes.
+ *
+ * The URL is of the form:
+ * amqp[s]://host[:port][?key=value[&key=value]*]
+ *
+ * For example:
+ * amqp://localhost
+ * amqp://broker?transport=rdma&authmech=GSSAPI&authservice=qpidd
+ * amqps://broker?authmech=PLAIN&authuser=guest&authpass=guest
+ */
+ QMFE_EXTERN ConnectionSettings(const char* url);
+
+ /**
+ * Copy Constructor.
+ */
+ ConnectionSettings(const ConnectionSettings& from);
+
+ /**
+ * Destroy the connection settings object.
+ */
+ QMFE_EXTERN ~ConnectionSettings();
+
+ /**
+ * Set an attribute to control connection setup.
+ *
+ * @param key A null-terminated string that is an attribute name.
+ *
+ * @param value Reference to a value to be stored as the attribute. The type of the value
+ * is specific to the key.
+ *
+ * @return True if success, False if invalid attribute
+ */
+ QMFE_EXTERN bool setAttr(const char* key, const Value& value);
+
+ /**
+ * Get the value of an attribute.
+ *
+ * @param key A null-terminated attribute name.
+ *
+ * @return The value associated with the attribute name.
+ */
+ QMFE_EXTERN Value getAttr(const char* key) const;
+
+ /**
+ * Get the attribute string (the portion of the URL following the '?') for the settings.
+ *
+ * @return A pointer to the attribute string. If the content of this string needs to be
+ * available beyond the scope of the calling function, it should be copied. The
+ * returned pointer may become invalid if the set of attributes is changed.
+ */
+ QMFE_EXTERN const char* getAttrString() const;
+
+ /**
+ * Shortcuts for setting the transport for the connection.
+ *
+ * @param port The port value for the connection address.
+ */
+ QMFE_EXTERN void transportTcp(uint16_t port = 5672);
+ QMFE_EXTERN void transportSsl(uint16_t port = 5671);
+ QMFE_EXTERN void transportRdma(uint16_t port = 5672);
+
+ /**
+ * Shortcuts for setting authentication mechanisms.
+ *
+ * @param username Null-terminated authentication user name.
+ *
+ * @param password Null-terminated authentication password.
+ *
+ * @param serviceName Null-terminated GSSAPI service name (Kerberos service principal)
+ *
+ * @param minSsf Minimum security factor for connections. 0 = encryption not required.
+ *
+ * @param maxSsf Maximum security factor for connections. 0 = encryption not permitted.
+ */
+ QMFE_EXTERN void authAnonymous(const char* username = 0);
+ QMFE_EXTERN void authPlain(const char* username = 0, const char* password = 0);
+ QMFE_EXTERN void authGssapi(const char* serviceName, uint32_t minSsf = 0, uint32_t maxSsf = 256);
+
+ /**
+ * Shortcut for setting connection retry attributes.
+ *
+ * @param delayMin Minimum delay (in seconds) between connection attempts.
+ *
+ * @param delaxMax Maximum delay (in seconds) between connection attempts.
+ *
+ * @param delayFactor Factor to multiply the delay by between failed connection attempts.
+ */
+ QMFE_EXTERN void setRetry(int delayMin = 1, int delayMax = 128, int delayFactor = 2);
+
+ private:
+ friend class ResilientConnectionImpl;
+ ConnectionSettingsImpl* impl;
+ };
+
+}
+}
+
+#endif
diff --git a/qpid/cpp/src/qmf/ConsoleEngine.h b/qpid/cpp/include/qmf/engine/Console.h
index 457e83ad58..ce72360da7 100644
--- a/qpid/cpp/src/qmf/ConsoleEngine.h
+++ b/qpid/cpp/include/qmf/engine/Console.h
@@ -1,5 +1,5 @@
-#ifndef _QmfConsoleEngine_
-#define _QmfConsoleEngine_
+#ifndef _QmfEngineConsole_
+#define _QmfEngineConsole_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,39 +20,42 @@
* under the License.
*/
-#include <qmf/ResilientConnection.h>
-#include <qmf/Schema.h>
-#include <qmf/ObjectId.h>
-#include <qmf/Object.h>
-#include <qmf/Event.h>
-#include <qmf/Query.h>
-#include <qmf/Value.h>
-#include <qmf/Message.h>
+#include <qmf/engine/ResilientConnection.h>
+#include <qmf/engine/Schema.h>
+#include <qmf/engine/ObjectId.h>
+#include <qmf/engine/Object.h>
+#include <qmf/engine/Event.h>
+#include <qmf/engine/Query.h>
+#include <qmf/engine/Value.h>
+#include <qmf/engine/Message.h>
namespace qmf {
+namespace engine {
- class ConsoleEngine;
- class ConsoleEngineImpl;
+ class Console;
+ struct ConsoleImpl;
class BrokerProxyImpl;
class AgentProxy;
- class AgentProxyImpl;
- class MethodResponseImpl;
- class QueryResponseImpl;
- class QueryContext;
+ struct AgentProxyImpl;
+ struct MethodResponseImpl;
+ struct QueryResponseImpl;
+ struct QueryContext;
/**
*
*/
class MethodResponse {
public:
- MethodResponse(MethodResponseImpl* impl);
+ MethodResponse(const MethodResponse& from);
~MethodResponse();
uint32_t getStatus() const;
const Value* getException() const;
const Value* getArgs() const;
private:
- friend class ConsoleEngineImpl;
+ friend struct MethodResponseImpl;
+ friend struct ConsoleImpl;
+ MethodResponse(MethodResponseImpl* impl);
MethodResponseImpl* impl;
};
@@ -61,7 +64,6 @@ namespace qmf {
*/
class QueryResponse {
public:
- QueryResponse(QueryResponseImpl* impl);
~QueryResponse();
uint32_t getStatus() const;
const Value* getException() const;
@@ -69,7 +71,9 @@ namespace qmf {
const Object* getObject(uint32_t idx) const;
private:
- friend class QueryContext;
+ friend struct QueryResponseImpl;
+ friend struct QueryContext;
+ QueryResponse(QueryResponseImpl* impl);
QueryResponseImpl *impl;
};
@@ -84,21 +88,20 @@ namespace qmf {
NEW_CLASS = 4,
OBJECT_UPDATE = 5,
EVENT_RECEIVED = 7,
- AGENT_HEARTBEAT = 8,
- METHOD_RESPONSE = 9
+ AGENT_HEARTBEAT = 8
};
EventKind kind;
AgentProxy* agent; // (AGENT_[ADDED|DELETED|HEARTBEAT])
char* name; // (NEW_PACKAGE)
- SchemaClassKey* classKey; // (NEW_CLASS)
+ const SchemaClassKey* classKey; // (NEW_CLASS)
Object* object; // (OBJECT_UPDATE)
void* context; // (OBJECT_UPDATE)
Event* event; // (EVENT_RECEIVED)
uint64_t timestamp; // (AGENT_HEARTBEAT)
- uint32_t methodHandle; // (METHOD_RESPONSE)
- MethodResponse* methodResponse; // (METHOD_RESPONSE)
QueryResponse* queryResponse; // (QUERY_COMPLETE)
+ bool hasProps;
+ bool hasStats;
};
/**
@@ -113,15 +116,17 @@ namespace qmf {
UNBIND = 14,
SETUP_COMPLETE = 15,
STABLE = 16,
- QUERY_COMPLETE = 17
+ QUERY_COMPLETE = 17,
+ METHOD_RESPONSE = 18
};
EventKind kind;
- char* name; // ([DECLARE|DELETE]_QUEUE, [UN]BIND)
- char* exchange; // ([UN]BIND)
- char* bindingKey; // ([UN]BIND)
- void* context; // (QUERY_COMPLETE)
- QueryResponse* queryResponse; // (QUERY_COMPLETE)
+ char* name; // ([DECLARE|DELETE]_QUEUE, [UN]BIND)
+ char* exchange; // ([UN]BIND)
+ char* bindingKey; // ([UN]BIND)
+ void* context; // (QUERY_COMPLETE, METHOD_RESPONSE)
+ QueryResponse* queryResponse; // (QUERY_COMPLETE)
+ MethodResponse* methodResponse; // (METHOD_RESPONSE)
};
/**
@@ -129,12 +134,17 @@ namespace qmf {
*/
class AgentProxy {
public:
- AgentProxy(AgentProxyImpl* impl);
~AgentProxy();
const char* getLabel() const;
+ uint32_t getBrokerBank() const;
+ uint32_t getAgentBank() const;
private:
+ friend struct StaticContext;
+ friend struct QueryContext;
+ friend struct AgentProxyImpl;
friend class BrokerProxyImpl;
+ AgentProxy(AgentProxyImpl* impl);
AgentProxyImpl* impl;
};
@@ -143,7 +153,7 @@ namespace qmf {
*/
class BrokerProxy {
public:
- BrokerProxy(ConsoleEngine& console);
+ BrokerProxy(Console& console);
~BrokerProxy();
void sessionOpened(SessionHandle& sh);
@@ -162,7 +172,8 @@ namespace qmf {
void sendQuery(const Query& query, void* context, const AgentProxy* agent = 0);
private:
- friend class ConsoleEngineImpl;
+ friend struct ConsoleImpl;
+ friend struct StaticContext;
BrokerProxyImpl* impl;
};
@@ -180,10 +191,10 @@ namespace qmf {
userBindings(false) {}
};
- class ConsoleEngine {
+ class Console {
public:
- ConsoleEngine(const ConsoleSettings& settings = ConsoleSettings());
- ~ConsoleEngine();
+ Console(const ConsoleSettings& settings = ConsoleSettings());
+ ~Console();
bool getEvent(ConsoleEvent& event) const;
void popEvent();
@@ -213,10 +224,12 @@ namespace qmf {
private:
friend class BrokerProxyImpl;
- friend class AgentProxyImpl;
- ConsoleEngineImpl* impl;
+ friend struct AgentProxyImpl;
+ friend struct StaticContext;
+ ConsoleImpl* impl;
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/Event.h b/qpid/cpp/include/qmf/engine/Event.h
index f20c6d2fb1..50ab5c1200 100644
--- a/qpid/cpp/src/qmf/Event.h
+++ b/qpid/cpp/include/qmf/engine/Event.h
@@ -1,5 +1,5 @@
-#ifndef _QmfEvent_
-#define _QmfEvent_
+#ifndef _QmfEngineEvent_
+#define _QmfEngineEvent_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,10 +21,12 @@
*/
namespace qmf {
+namespace engine {
class Event {
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/Message.h b/qpid/cpp/include/qmf/engine/Message.h
index 52b8ba72d3..1e95cc6afe 100644
--- a/qpid/cpp/src/qmf/Message.h
+++ b/qpid/cpp/include/qmf/engine/Message.h
@@ -1,5 +1,5 @@
-#ifndef _QmfMessage_
-#define _QmfMessage_
+#ifndef _QmfEngineMessage_
+#define _QmfEngineMessage_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -23,6 +23,7 @@
#include "qpid/sys/IntegerTypes.h"
namespace qmf {
+namespace engine {
struct Message {
char* body;
@@ -35,5 +36,6 @@ namespace qmf {
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/Object.h b/qpid/cpp/include/qmf/engine/Object.h
index 9cb3224d9b..ad67cfdb95 100644
--- a/qpid/cpp/src/qmf/Object.h
+++ b/qpid/cpp/include/qmf/engine/Object.h
@@ -1,5 +1,5 @@
-#ifndef _QmfObject_
-#define _QmfObject_
+#ifndef _QmfEngineObject_
+#define _QmfEngineObject_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,17 +20,17 @@
* under the License.
*/
-#include <qmf/Schema.h>
-#include <qmf/ObjectId.h>
-#include <qmf/Value.h>
+#include <qmf/engine/Schema.h>
+#include <qmf/engine/ObjectId.h>
+#include <qmf/engine/Value.h>
namespace qmf {
+namespace engine {
struct ObjectImpl;
class Object {
public:
Object(const SchemaObjectClass* type);
- Object(ObjectImpl* impl);
Object(const Object& from);
virtual ~Object();
@@ -38,11 +38,19 @@ namespace qmf {
const ObjectId* getObjectId() const;
void setObjectId(ObjectId* oid);
const SchemaObjectClass* getClass() const;
- Value* getValue(char* key) const;
-
+ Value* getValue(const char* key) const;
+ void invokeMethod(const char* methodName, const Value* inArgs, void* context) const;
+ bool isDeleted() const;
+ void merge(const Object& from);
+
+ private:
+ friend struct ObjectImpl;
+ friend class AgentImpl;
+ Object(ObjectImpl* impl);
ObjectImpl* impl;
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/ObjectId.h b/qpid/cpp/include/qmf/engine/ObjectId.h
index e894e0b39c..2055972c00 100644
--- a/qpid/cpp/src/qmf/ObjectId.h
+++ b/qpid/cpp/include/qmf/engine/ObjectId.h
@@ -1,5 +1,5 @@
-#ifndef _QmfObjectId_
-#define _QmfObjectId_
+#ifndef _QmfEngineObjectId_
+#define _QmfEngineObjectId_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -23,6 +23,7 @@
#include <qpid/sys/IntegerTypes.h>
namespace qmf {
+namespace engine {
// TODO: Add to/from string and << operator
@@ -31,13 +32,17 @@ namespace qmf {
public:
ObjectId();
ObjectId(const ObjectId& from);
- ObjectId(ObjectIdImpl* impl);
~ObjectId();
uint64_t getObjectNum() const;
uint32_t getObjectNumHi() const;
uint32_t getObjectNumLo() const;
bool isDurable() const;
+ const char* str() const;
+ uint8_t getFlags() const;
+ uint16_t getSequence() const;
+ uint32_t getBrokerBank() const;
+ uint32_t getAgentBank() const;
bool operator==(const ObjectId& other) const;
bool operator<(const ObjectId& other) const;
@@ -45,9 +50,18 @@ namespace qmf {
bool operator<=(const ObjectId& other) const;
bool operator>=(const ObjectId& other) const;
+ private:
+ friend struct ObjectIdImpl;
+ friend struct ObjectImpl;
+ friend class BrokerProxyImpl;
+ friend struct QueryImpl;
+ friend struct ValueImpl;
+ friend class AgentImpl;
+ ObjectId(ObjectIdImpl* impl);
ObjectIdImpl* impl;
};
}
+}
#endif
diff --git a/qpid/cpp/include/qmf/engine/QmfEngineImportExport.h b/qpid/cpp/include/qmf/engine/QmfEngineImportExport.h
new file mode 100644
index 0000000000..70164c749f
--- /dev/null
+++ b/qpid/cpp/include/qmf/engine/QmfEngineImportExport.h
@@ -0,0 +1,33 @@
+#ifndef QMF_ENGINE_IMPORT_EXPORT_H
+#define QMF_ENGINE_IMPORT_EXPORT_H
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
+# if defined(QMF_EXPORT) || defined (qmfcommon_EXPORTS)
+# define QMFE_EXTERN __declspec(dllexport)
+# else
+# define QMFE_EXTERN __declspec(dllimport)
+# endif
+#else
+# define QMFE_EXTERN
+#endif
+
+#endif
diff --git a/qpid/cpp/src/qmf/Query.h b/qpid/cpp/include/qmf/engine/Query.h
index 875749862e..1b11ea83f2 100644
--- a/qpid/cpp/src/qmf/Query.h
+++ b/qpid/cpp/include/qmf/engine/Query.h
@@ -1,5 +1,5 @@
-#ifndef _QmfQuery_
-#define _QmfQuery_
+#ifndef _QmfEngineQuery_
+#define _QmfEngineQuery_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,16 +20,17 @@
* under the License.
*/
-#include <qmf/ObjectId.h>
-#include <qmf/Value.h>
+#include <qmf/engine/ObjectId.h>
+#include <qmf/engine/Value.h>
namespace qmf {
+namespace engine {
- struct Object;
+ class Object;
struct QueryElementImpl;
struct QueryImpl;
struct QueryExpressionImpl;
- struct SchemaClassKey;
+ class SchemaClassKey;
enum ValueOper {
O_EQ = 1,
@@ -77,7 +78,7 @@ namespace qmf {
Query(const char* className, const char* packageName);
Query(const SchemaClassKey* key);
Query(const ObjectId* oid);
- Query(QueryImpl* impl);
+ Query(const Query& from);
~Query();
void setSelect(const QueryOperand* criterion);
@@ -96,9 +97,14 @@ namespace qmf {
const char* getOrderBy() const;
bool getDecreasing() const;
+ private:
+ friend struct QueryImpl;
+ friend class BrokerProxyImpl;
+ Query(QueryImpl* impl);
QueryImpl* impl;
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/ResilientConnection.h b/qpid/cpp/include/qmf/engine/ResilientConnection.h
index 03f1b9c0d5..359c8ea6ff 100644
--- a/qpid/cpp/src/qmf/ResilientConnection.h
+++ b/qpid/cpp/include/qmf/engine/ResilientConnection.h
@@ -1,5 +1,5 @@
-#ifndef _QmfResilientConnection_
-#define _QmfResilientConnection_
+#ifndef _QmfEngineResilientConnection_
+#define _QmfEngineResilientConnection_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,11 +20,12 @@
* under the License.
*/
-#include <qmf/Message.h>
-#include <qmf/ConnectionSettings.h>
+#include <qmf/engine/Message.h>
+#include <qmf/engine/ConnectionSettings.h>
#include <string>
namespace qmf {
+namespace engine {
class ResilientConnectionImpl;
@@ -158,6 +159,7 @@ namespace qmf {
ResilientConnectionImpl* impl;
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/Schema.h b/qpid/cpp/include/qmf/engine/Schema.h
index 1123acc3b8..16f11a83f9 100644
--- a/qpid/cpp/src/qmf/Schema.h
+++ b/qpid/cpp/include/qmf/engine/Schema.h
@@ -1,5 +1,5 @@
-#ifndef _QmfSchema_
-#define _QmfSchema_
+#ifndef _QmfEngineSchema_
+#define _QmfEngineSchema_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,10 +20,11 @@
* under the License.
*/
-#include <qmf/Typecode.h>
+#include <qmf/engine/Typecode.h>
#include <qpid/sys/IntegerTypes.h>
namespace qmf {
+namespace engine {
enum Access { ACCESS_READ_CREATE = 1, ACCESS_READ_WRITE = 2, ACCESS_READ_ONLY = 3 };
enum Direction { DIR_IN = 1, DIR_OUT = 2, DIR_IN_OUT = 3 };
@@ -42,7 +43,7 @@ namespace qmf {
class SchemaArgument {
public:
SchemaArgument(const char* name, Typecode typecode);
- SchemaArgument(SchemaArgumentImpl* impl);
+ SchemaArgument(const SchemaArgument& from);
~SchemaArgument();
void setDirection(Direction dir);
void setUnit(const char* val);
@@ -53,6 +54,11 @@ namespace qmf {
const char* getUnit() const;
const char* getDesc() const;
+ private:
+ friend struct SchemaArgumentImpl;
+ friend struct SchemaMethodImpl;
+ friend struct SchemaEventClassImpl;
+ SchemaArgument(SchemaArgumentImpl* impl);
SchemaArgumentImpl* impl;
};
@@ -61,15 +67,20 @@ namespace qmf {
class SchemaMethod {
public:
SchemaMethod(const char* name);
- SchemaMethod(SchemaMethodImpl* impl);
+ SchemaMethod(const SchemaMethod& from);
~SchemaMethod();
- void addArgument(const SchemaArgument& argument);
+ void addArgument(const SchemaArgument* argument);
void setDesc(const char* desc);
const char* getName() const;
const char* getDesc() const;
int getArgumentCount() const;
const SchemaArgument* getArgument(int idx) const;
+ private:
+ friend struct SchemaMethodImpl;
+ friend struct SchemaObjectClassImpl;
+ friend class AgentImpl;
+ SchemaMethod(SchemaMethodImpl* impl);
SchemaMethodImpl* impl;
};
@@ -78,7 +89,7 @@ namespace qmf {
class SchemaProperty {
public:
SchemaProperty(const char* name, Typecode typecode);
- SchemaProperty(SchemaPropertyImpl* impl);
+ SchemaProperty(const SchemaProperty& from);
~SchemaProperty();
void setAccess(Access access);
void setIndex(bool val);
@@ -93,6 +104,10 @@ namespace qmf {
const char* getUnit() const;
const char* getDesc() const;
+ private:
+ friend struct SchemaPropertyImpl;
+ friend struct SchemaObjectClassImpl;
+ SchemaProperty(SchemaPropertyImpl* impl);
SchemaPropertyImpl* impl;
};
@@ -101,7 +116,7 @@ namespace qmf {
class SchemaStatistic {
public:
SchemaStatistic(const char* name, Typecode typecode);
- SchemaStatistic(SchemaStatisticImpl* impl);
+ SchemaStatistic(const SchemaStatistic& from);
~SchemaStatistic();
void setUnit(const char* val);
void setDesc(const char* desc);
@@ -110,6 +125,10 @@ namespace qmf {
const char* getUnit() const;
const char* getDesc() const;
+ private:
+ friend struct SchemaStatisticImpl;
+ friend struct SchemaObjectClassImpl;
+ SchemaStatistic(SchemaStatisticImpl* impl);
SchemaStatisticImpl* impl;
};
@@ -117,13 +136,22 @@ namespace qmf {
*/
class SchemaClassKey {
public:
- SchemaClassKey(SchemaClassKeyImpl* impl);
+ SchemaClassKey(const SchemaClassKey& from);
~SchemaClassKey();
const char* getPackageName() const;
const char* getClassName() const;
const uint8_t* getHash() const;
+ const char* asString() const;
+
+ bool operator==(const SchemaClassKey& other) const;
+ bool operator<(const SchemaClassKey& other) const;
+ private:
+ friend struct SchemaClassKeyImpl;
+ friend class BrokerProxyImpl;
+ friend struct ConsoleImpl;
+ SchemaClassKey(SchemaClassKeyImpl* impl);
SchemaClassKeyImpl* impl;
};
@@ -132,11 +160,11 @@ namespace qmf {
class SchemaObjectClass {
public:
SchemaObjectClass(const char* package, const char* name);
- SchemaObjectClass(SchemaObjectClassImpl* impl);
+ SchemaObjectClass(const SchemaObjectClass& from);
~SchemaObjectClass();
- void addProperty(const SchemaProperty& property);
- void addStatistic(const SchemaStatistic& statistic);
- void addMethod(const SchemaMethod& method);
+ void addProperty(const SchemaProperty* property);
+ void addStatistic(const SchemaStatistic* statistic);
+ void addMethod(const SchemaMethod* method);
const SchemaClassKey* getClassKey() const;
int getPropertyCount() const;
@@ -146,6 +174,11 @@ namespace qmf {
const SchemaStatistic* getStatistic(int idx) const;
const SchemaMethod* getMethod(int idx) const;
+ private:
+ friend struct SchemaObjectClassImpl;
+ friend class BrokerProxyImpl;
+ friend class AgentImpl;
+ SchemaObjectClass(SchemaObjectClassImpl* impl);
SchemaObjectClassImpl* impl;
};
@@ -154,18 +187,24 @@ namespace qmf {
class SchemaEventClass {
public:
SchemaEventClass(const char* package, const char* name);
- SchemaEventClass(SchemaEventClassImpl* impl);
+ SchemaEventClass(const SchemaEventClass& from);
~SchemaEventClass();
- void addArgument(const SchemaArgument& argument);
+ void addArgument(const SchemaArgument* argument);
void setDesc(const char* desc);
const SchemaClassKey* getClassKey() const;
int getArgumentCount() const;
const SchemaArgument* getArgument(int idx) const;
+ private:
+ friend struct SchemaEventClassImpl;
+ friend class BrokerProxyImpl;
+ friend class AgentImpl;
+ SchemaEventClass(SchemaEventClassImpl* impl);
SchemaEventClassImpl* impl;
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/Typecode.h b/qpid/cpp/include/qmf/engine/Typecode.h
index 94614d2977..613f96a483 100644
--- a/qpid/cpp/src/qmf/Typecode.h
+++ b/qpid/cpp/include/qmf/engine/Typecode.h
@@ -1,5 +1,5 @@
-#ifndef _QmfTypecode_
-#define _QmfTypecode_
+#ifndef _QmfEngineTypecode_
+#define _QmfEngineTypecode_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,6 +21,7 @@
*/
namespace qmf {
+namespace engine {
enum Typecode {
TYPE_UINT8 = 1,
@@ -46,6 +47,7 @@ namespace qmf {
TYPE_ARRAY = 22
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/Value.h b/qpid/cpp/include/qmf/engine/Value.h
index bb946d31d3..8eae382caf 100644
--- a/qpid/cpp/src/qmf/Value.h
+++ b/qpid/cpp/include/qmf/engine/Value.h
@@ -1,5 +1,5 @@
-#ifndef _QmfValue_
-#define _QmfValue_
+#ifndef _QmfEngineValue_
+#define _QmfEngineValue_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,10 +20,11 @@
* under the License.
*/
-#include <qmf/ObjectId.h>
-#include <qmf/Typecode.h>
+#include <qmf/engine/ObjectId.h>
+#include <qmf/engine/Typecode.h>
namespace qmf {
+namespace engine {
class Object;
struct ValueImpl;
@@ -31,8 +32,8 @@ namespace qmf {
class Value {
public:
// Value();
+ Value(const Value& from);
Value(Typecode t, Typecode arrayType = TYPE_UINT8);
- Value(ValueImpl* impl);
~Value();
Typecode getType() const;
@@ -80,7 +81,7 @@ namespace qmf {
void setUuid(const uint8_t* val);
bool isObject() const;
- Object* asObject() const;
+ const Object* asObject() const;
void setObject(Object* val);
bool isMap() const;
@@ -105,9 +106,16 @@ namespace qmf {
void appendToArray(Value* val);
void deleteArrayItem(uint32_t idx);
+ private:
+ friend struct ValueImpl;
+ friend class BrokerProxyImpl;
+ friend struct ObjectImpl;
+ friend class AgentImpl;
+ Value(ValueImpl* impl);
ValueImpl* impl;
};
}
+}
#endif
diff --git a/qpid/cpp/include/qpid/client/QueueOptions.h b/qpid/cpp/include/qpid/client/QueueOptions.h
index 9418cb092d..f8a4963f06 100644
--- a/qpid/cpp/include/qpid/client/QueueOptions.h
+++ b/qpid/cpp/include/qpid/client/QueueOptions.h
@@ -90,7 +90,22 @@ class QueueOptions: public framing::FieldTable
* Turns on event generation for this queue (either enqueue only
* or for enqueue and dequeue events); the events can then be
* processed by a regsitered broker plugin.
+ *
+ * DEPRECATED
+ *
+ * This is confusing to anyone who sees only the function call
+ * and not the variable name / doxygen. Consider the following call:
+ *
+ * options.enableQueueEvents(false);
+ *
+ * It looks like it disables queue events, but what it really does is
+ * enable both enqueue and dequeue events.
+ *
+ * Use setInt() instead:
+ *
+ * options.setInt("qpid.queue_event_generation", 2);
*/
+
QPID_CLIENT_EXTERN void enableQueueEvents(bool enqueueOnly);
static QPID_CLIENT_EXTERN const std::string strMaxCountKey;
diff --git a/qpid/cpp/include/qpid/messaging/ListContent.h b/qpid/cpp/include/qpid/messaging/ListContent.h
new file mode 100644
index 0000000000..1c4e13716d
--- /dev/null
+++ b/qpid/cpp/include/qpid/messaging/ListContent.h
@@ -0,0 +1,90 @@
+#ifndef QPID_MESSAGING_LISTCONTENT_H
+#define QPID_MESSAGING_LISTCONTENT_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/client/ClientImportExport.h"
+#include "Variant.h"
+
+namespace qpid {
+namespace messaging {
+
+class ListContentImpl;
+class Message;
+
+/**
+ * Allows message content to be manipulated as a list.
+ */
+class ListContent
+{
+ public:
+ typedef Variant::List::iterator iterator;
+ typedef Variant::List::reverse_iterator reverse_iterator;
+ typedef Variant::List::const_iterator const_iterator;
+ typedef Variant::List::const_reverse_iterator const_reverse_iterator;
+
+ QPID_CLIENT_EXTERN ListContent(Message&);
+ QPID_CLIENT_EXTERN ~ListContent();
+
+ QPID_CLIENT_EXTERN const_iterator begin() const;
+ QPID_CLIENT_EXTERN iterator begin();
+ QPID_CLIENT_EXTERN const_iterator end() const;
+ QPID_CLIENT_EXTERN iterator end();
+ QPID_CLIENT_EXTERN const_reverse_iterator rbegin() const;
+ QPID_CLIENT_EXTERN reverse_iterator rbegin();
+ QPID_CLIENT_EXTERN const_reverse_iterator rend() const;
+ QPID_CLIENT_EXTERN reverse_iterator rend();
+
+ QPID_CLIENT_EXTERN bool empty() const;
+ QPID_CLIENT_EXTERN size_t size() const;
+
+ QPID_CLIENT_EXTERN const Variant& front() const;
+ QPID_CLIENT_EXTERN Variant& front();
+ QPID_CLIENT_EXTERN const Variant& back() const;
+ QPID_CLIENT_EXTERN Variant& back();
+
+ QPID_CLIENT_EXTERN void push_front(const Variant&);
+ QPID_CLIENT_EXTERN void push_back(const Variant&);
+
+ QPID_CLIENT_EXTERN void pop_front();
+ QPID_CLIENT_EXTERN void pop_back();
+
+ QPID_CLIENT_EXTERN iterator insert(iterator position, const Variant&);
+ QPID_CLIENT_EXTERN void insert(iterator position, size_t n, const Variant&);
+ QPID_CLIENT_EXTERN iterator erase(iterator position);
+ QPID_CLIENT_EXTERN iterator erase(iterator first, iterator last);
+ QPID_CLIENT_EXTERN void clear();
+
+ QPID_CLIENT_EXTERN void encode();
+
+ QPID_CLIENT_EXTERN const Variant::List& asList() const;
+ QPID_CLIENT_EXTERN Variant::List& asList();
+ private:
+ ListContentImpl* impl;
+
+ QPID_CLIENT_EXTERN ListContent& operator=(const ListContent&);
+};
+
+QPID_CLIENT_EXTERN std::ostream& operator<<(std::ostream& out, const ListContent& m);
+
+}} // namespace qpid::messaging
+
+#endif /*!QPID_MESSAGING_LISTCONTENT_H*/
diff --git a/qpid/cpp/include/qpid/messaging/ListView.h b/qpid/cpp/include/qpid/messaging/ListView.h
new file mode 100644
index 0000000000..4970a20072
--- /dev/null
+++ b/qpid/cpp/include/qpid/messaging/ListView.h
@@ -0,0 +1,67 @@
+#ifndef QPID_MESSAGING_LISTVIEW_H
+#define QPID_MESSAGING_LISTVIEW_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/ClientImportExport.h"
+#include "Variant.h"
+
+namespace qpid {
+namespace messaging {
+
+class ListViewImpl;
+class Message;
+
+/**
+ * Provides a view of message content as a list
+ */
+class ListView
+{
+ public:
+ typedef Variant::List::const_iterator const_iterator;
+ typedef Variant::List::const_reverse_iterator const_reverse_iterator;
+
+ QPID_CLIENT_EXTERN ListView(const Message&);
+ QPID_CLIENT_EXTERN ~ListView();
+ QPID_CLIENT_EXTERN ListView& operator=(const ListView&);
+
+ QPID_CLIENT_EXTERN const_iterator begin() const;
+ QPID_CLIENT_EXTERN const_iterator end() const;
+ QPID_CLIENT_EXTERN const_reverse_iterator rbegin() const;
+ QPID_CLIENT_EXTERN const_reverse_iterator rend() const;
+
+ QPID_CLIENT_EXTERN bool empty() const;
+ QPID_CLIENT_EXTERN size_t size() const;
+
+ QPID_CLIENT_EXTERN const Variant& front() const;
+ QPID_CLIENT_EXTERN const Variant& back() const;
+
+ QPID_CLIENT_EXTERN const Variant::List& asList() const;
+ private:
+ ListViewImpl* impl;
+};
+
+QPID_CLIENT_EXTERN std::ostream& operator<<(std::ostream& out, const ListView& m);
+
+}} // namespace qpid::messaging
+
+#endif /*!QPID_MESSAGING_LISTVIEW_H*/
diff --git a/qpid/cpp/include/qpid/messaging/MapContent.h b/qpid/cpp/include/qpid/messaging/MapContent.h
new file mode 100644
index 0000000000..b05cb31295
--- /dev/null
+++ b/qpid/cpp/include/qpid/messaging/MapContent.h
@@ -0,0 +1,90 @@
+#ifndef QPID_MESSAGING_MAPCONTENT_H
+#define QPID_MESSAGING_MAPCONTENT_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/client/ClientImportExport.h"
+#include "Variant.h"
+#include <map>
+#include <string>
+
+namespace qpid {
+namespace messaging {
+
+class MapContentImpl;
+class Message;
+
+/**
+ * Allows message content to be manipulated as a map
+ */
+class MapContent
+{
+ public:
+ typedef std::string key_type;
+ typedef std::pair<std::string, Variant> value_type;
+ typedef std::map<key_type, Variant>::const_iterator const_iterator;
+ typedef std::map<key_type, Variant>::iterator iterator;
+ typedef std::map<key_type, Variant>::const_reverse_iterator const_reverse_iterator;
+ typedef std::map<key_type, Variant>::reverse_iterator reverse_iterator;
+
+ QPID_CLIENT_EXTERN MapContent(Message&);
+ QPID_CLIENT_EXTERN ~MapContent();
+
+ QPID_CLIENT_EXTERN const_iterator begin() const;
+ QPID_CLIENT_EXTERN const_iterator end() const;
+ QPID_CLIENT_EXTERN const_reverse_iterator rbegin() const;
+ QPID_CLIENT_EXTERN const_reverse_iterator rend() const;
+ QPID_CLIENT_EXTERN iterator begin();
+ QPID_CLIENT_EXTERN iterator end();
+ QPID_CLIENT_EXTERN reverse_iterator rbegin();
+ QPID_CLIENT_EXTERN reverse_iterator rend();
+
+ QPID_CLIENT_EXTERN bool empty() const;
+ QPID_CLIENT_EXTERN size_t size() const;
+
+ QPID_CLIENT_EXTERN const_iterator find(const key_type&) const;
+ QPID_CLIENT_EXTERN iterator find(const key_type&);
+ QPID_CLIENT_EXTERN const Variant& operator[](const key_type&) const;
+ QPID_CLIENT_EXTERN Variant& operator[](const key_type&);
+
+ QPID_CLIENT_EXTERN std::pair<iterator,bool> insert(const value_type&);
+ QPID_CLIENT_EXTERN iterator insert(iterator position, const value_type&);
+ QPID_CLIENT_EXTERN void erase(iterator position);
+ QPID_CLIENT_EXTERN void erase(iterator first, iterator last);
+ QPID_CLIENT_EXTERN size_t erase(const key_type&);
+ QPID_CLIENT_EXTERN void clear();
+
+ QPID_CLIENT_EXTERN void encode();
+
+ QPID_CLIENT_EXTERN const std::map<key_type, Variant>& asMap() const;
+ QPID_CLIENT_EXTERN std::map<key_type, Variant>& asMap();
+ private:
+ MapContentImpl* impl;
+
+ QPID_CLIENT_EXTERN MapContent& operator=(const MapContent&);
+};
+
+QPID_CLIENT_EXTERN std::ostream& operator<<(std::ostream& out, const MapContent& m);
+
+}} // namespace qpid::messaging
+
+#endif /*!QPID_MESSAGING_MAPCONTENT_H*/
diff --git a/qpid/cpp/include/qpid/messaging/MapView.h b/qpid/cpp/include/qpid/messaging/MapView.h
new file mode 100644
index 0000000000..910dfca5c2
--- /dev/null
+++ b/qpid/cpp/include/qpid/messaging/MapView.h
@@ -0,0 +1,70 @@
+#ifndef QPID_MESSAGING_MAPVIEW_H
+#define QPID_MESSAGING_MAPVIEW_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/client/ClientImportExport.h"
+#include "Variant.h"
+#include <map>
+#include <string>
+
+namespace qpid {
+namespace messaging {
+
+class MapViewImpl;
+class Message;
+
+/**
+ * Provides a view of message content as a list
+ */
+class MapView
+{
+ public:
+ typedef std::string key_type;
+ typedef std::pair<key_type, Variant> value_type;
+ typedef std::map<key_type, Variant>::const_iterator const_iterator;
+ typedef std::map<key_type, Variant>::const_reverse_iterator const_reverse_iterator;
+
+ QPID_CLIENT_EXTERN MapView(const Message&);
+ QPID_CLIENT_EXTERN ~MapView();
+ QPID_CLIENT_EXTERN MapView& operator=(const MapView&);
+
+ QPID_CLIENT_EXTERN const_iterator begin() const;
+ QPID_CLIENT_EXTERN const_iterator end() const;
+ QPID_CLIENT_EXTERN const_reverse_iterator rbegin() const;
+ QPID_CLIENT_EXTERN const_reverse_iterator rend() const;
+
+ QPID_CLIENT_EXTERN bool empty() const;
+ QPID_CLIENT_EXTERN size_t size() const;
+
+ QPID_CLIENT_EXTERN const_iterator find(const key_type&) const;
+ QPID_CLIENT_EXTERN const Variant& operator[](const key_type&) const;
+
+ QPID_CLIENT_EXTERN const std::map<key_type, Variant>& asMap() const;
+ private:
+ MapViewImpl* impl;
+};
+
+QPID_CLIENT_EXTERN std::ostream& operator<<(std::ostream& out, const MapView& m);
+
+}} // namespace qpid::messaging
+
+#endif /*!QPID_MESSAGING_MAPVIEW_H*/
diff --git a/qpid/cpp/include/qpid/messaging/Message.h b/qpid/cpp/include/qpid/messaging/Message.h
index e68d8a1141..4477d5a2e9 100644
--- a/qpid/cpp/include/qpid/messaging/Message.h
+++ b/qpid/cpp/include/qpid/messaging/Message.h
@@ -24,7 +24,6 @@
#include <string>
#include "qpid/messaging/Variant.h"
-#include "qpid/messaging/MessageContent.h"
#include "qpid/client/ClientImportExport.h"
namespace qpid {
@@ -62,22 +61,11 @@ class Message
QPID_CLIENT_EXTERN const VariantMap& getHeaders() const;
QPID_CLIENT_EXTERN VariantMap& getHeaders();
- QPID_CLIENT_EXTERN const std::string& getBytes() const;
- QPID_CLIENT_EXTERN std::string& getBytes();
- QPID_CLIENT_EXTERN void setBytes(const std::string&);
- QPID_CLIENT_EXTERN void setBytes(const char* chars, size_t count);
- QPID_CLIENT_EXTERN const char* getRawContent() const;
- QPID_CLIENT_EXTERN size_t getContentSize() const;
-
-
- QPID_CLIENT_EXTERN MessageContent& getContent();
- QPID_CLIENT_EXTERN const MessageContent& getContent() const;
- QPID_CLIENT_EXTERN void setContent(const std::string& s);
- QPID_CLIENT_EXTERN void setContent(const Variant::Map&);
- QPID_CLIENT_EXTERN void setContent(const Variant::List&);
-
- QPID_CLIENT_EXTERN void encode(Codec&);
- QPID_CLIENT_EXTERN void decode(Codec&);
+ QPID_CLIENT_EXTERN const std::string& getContent() const;
+ QPID_CLIENT_EXTERN std::string& getContent();
+ QPID_CLIENT_EXTERN void setContent(const std::string&);
+ QPID_CLIENT_EXTERN void setContent(const char* chars, size_t count);
+ QPID_CLIENT_EXTERN void getContent(std::pair<const char*, size_t>& content) const;
private:
MessageImpl* impl;
diff --git a/qpid/cpp/include/qpid/messaging/MessageContent.h b/qpid/cpp/include/qpid/messaging/MessageContent.h
deleted file mode 100644
index 7c3a636c07..0000000000
--- a/qpid/cpp/include/qpid/messaging/MessageContent.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef QPID_MESSAGING_MESSAGECONTENT_H
-#define QPID_MESSAGING_MESSAGECONTENT_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/messaging/Variant.h"
-#include <string>
-#include "qpid/client/ClientImportExport.h"
-
-namespace qpid {
-namespace messaging {
-
-/**
- *
- */
-class MessageContent
-{
- public:
- QPID_CLIENT_EXTERN virtual ~MessageContent() {}
-
- virtual const std::string& asString() const = 0;
- virtual std::string& asString() = 0;
-
- virtual const char* asChars() const = 0;
- virtual size_t size() const = 0;
-
- virtual const Variant::Map& asMap() const = 0;
- virtual Variant::Map& asMap() = 0;
- virtual bool isMap() const = 0;
-
- virtual const Variant::List& asList() const = 0;
- virtual Variant::List& asList() = 0;
- virtual bool isList() const = 0;
-
- virtual void clear() = 0;
-
- virtual Variant& operator[](const std::string&) = 0;
-
-
- virtual std::ostream& print(std::ostream& out) const = 0;
-
-
- //operator<< for variety of types... (is this a good idea?)
- virtual MessageContent& operator<<(const std::string&) = 0;
- virtual MessageContent& operator<<(const char*) = 0;
- virtual MessageContent& operator<<(bool) = 0;
- virtual MessageContent& operator<<(int8_t) = 0;
- virtual MessageContent& operator<<(int16_t) = 0;
- virtual MessageContent& operator<<(int32_t) = 0;
- virtual MessageContent& operator<<(int64_t) = 0;
- virtual MessageContent& operator<<(uint8_t) = 0;
- virtual MessageContent& operator<<(uint16_t) = 0;
- virtual MessageContent& operator<<(uint32_t) = 0;
- virtual MessageContent& operator<<(uint64_t) = 0;
- virtual MessageContent& operator<<(double) = 0;
- virtual MessageContent& operator<<(float) = 0;
-
- //assignment from string, map and list
- virtual MessageContent& operator=(const std::string&) = 0;
- virtual MessageContent& operator=(const char*) = 0;
- virtual MessageContent& operator=(const Variant::Map&) = 0;
- virtual MessageContent& operator=(const Variant::List&) = 0;
-
- private:
-};
-
-QPID_CLIENT_EXTERN std::ostream& operator<<(std::ostream& out, const MessageContent& content);
-
-}} // namespace qpid::messaging
-
-#endif /*!QPID_MESSAGING_MESSAGECONTENT_H*/
diff --git a/qpid/cpp/include/qpid/sys/posix/PrivatePosix.h b/qpid/cpp/include/qpid/sys/posix/PrivatePosix.h
index 6ffd3d8383..79cb950275 100644
--- a/qpid/cpp/include/qpid/sys/posix/PrivatePosix.h
+++ b/qpid/cpp/include/qpid/sys/posix/PrivatePosix.h
@@ -27,6 +27,7 @@
struct timespec;
struct timeval;
+struct addrinfo;
namespace qpid {
namespace sys {
@@ -36,6 +37,10 @@ struct timespec& toTimespec(struct timespec& ts, const Duration& t);
struct timeval& toTimeval(struct timeval& tv, const Duration& t);
Duration toTime(const struct timespec& ts);
+// Private SocketAddress details
+class SocketAddress;
+const struct addrinfo& getAddrInfo(const SocketAddress&);
+
// Private fd related implementation details
class IOHandlePrivate {
public:
diff --git a/qpid/cpp/include/qpid/sys/windows/IntegerTypes.h b/qpid/cpp/include/qpid/sys/windows/IntegerTypes.h
index 47b1d16a76..7b2c57ad8e 100755
--- a/qpid/cpp/include/qpid/sys/windows/IntegerTypes.h
+++ b/qpid/cpp/include/qpid/sys/windows/IntegerTypes.h
@@ -21,6 +21,8 @@
*
*/
+#include <BaseTsd.h> /* Windows system types */
+
typedef unsigned char uint8_t;
typedef char int8_t;
typedef unsigned short uint16_t;
@@ -32,7 +34,7 @@ typedef __int64 int64_t;
// Visual Studio doesn't define other common types, so set them up here too.
typedef int pid_t;
-typedef int ssize_t;
+typedef SSIZE_T ssize_t;
typedef unsigned int uint;
#endif /*!QPID_SYS_WINDOWS_INTEGERTYPES_H*/
diff --git a/qpid/cpp/managementgen/CMakeLists.txt b/qpid/cpp/managementgen/CMakeLists.txt
index 8d053e3e08..2511b745a3 100644
--- a/qpid/cpp/managementgen/CMakeLists.txt
+++ b/qpid/cpp/managementgen/CMakeLists.txt
@@ -20,18 +20,7 @@ project(qpidc-qmfgen)
cmake_minimum_required(VERSION 2.4.0 FATAL_ERROR)
install(PROGRAMS qmf-gen DESTINATION managementgen
- COMPONENT all-source)
-install(FILES qmfgen/__init__.py
- qmfgen/generate.py
- qmfgen/schema.py
- qmfgen/templates/Args.h
- qmfgen/templates/Class.cpp
- qmfgen/templates/Class.h
- qmfgen/templates/Event.cpp
- qmfgen/templates/Event.h
- qmfgen/templates/Makefile.mk
- qmfgen/templates/Package.cpp
- qmfgen/templates/Package.h
- qmfgen/management-types.xml
- DESTINATION managementgen
- COMPONENT all-source)
+ COMPONENT ${QPID_COMPONENT_QMF})
+install(DIRECTORY qmfgen DESTINATION managementgen
+ COMPONENT ${QPID_COMPONENT_QMF}
+ PATTERN ".svn" EXCLUDE PATTERN "*.pyc" EXCLUDE)
diff --git a/qpid/cpp/packaging/NSIS/qpid-icon.ico b/qpid/cpp/packaging/NSIS/qpid-icon.ico
new file mode 100644
index 0000000000..112f5d8f1f
--- /dev/null
+++ b/qpid/cpp/packaging/NSIS/qpid-icon.ico
Binary files differ
diff --git a/qpid/cpp/packaging/NSIS/qpid-icon.png b/qpid/cpp/packaging/NSIS/qpid-icon.png
new file mode 100644
index 0000000000..d9bcc5657f
--- /dev/null
+++ b/qpid/cpp/packaging/NSIS/qpid-icon.png
Binary files differ
diff --git a/qpid/cpp/packaging/NSIS/qpid-install-banner.bmp b/qpid/cpp/packaging/NSIS/qpid-install-banner.bmp
new file mode 100644
index 0000000000..1dac04c685
--- /dev/null
+++ b/qpid/cpp/packaging/NSIS/qpid-install-banner.bmp
Binary files differ
diff --git a/qpid/cpp/packaging/NSIS/qpid-install-banner.png b/qpid/cpp/packaging/NSIS/qpid-install-banner.png
new file mode 100644
index 0000000000..be70d02ee6
--- /dev/null
+++ b/qpid/cpp/packaging/NSIS/qpid-install-banner.png
Binary files differ
diff --git a/qpid/cpp/rubygen/framing.0-10/structs.rb b/qpid/cpp/rubygen/framing.0-10/structs.rb
index 809e453381..c3684aea66 100755
--- a/qpid/cpp/rubygen/framing.0-10/structs.rb
+++ b/qpid/cpp/rubygen/framing.0-10/structs.rb
@@ -381,9 +381,10 @@ EOS
else
inheritance = ": public AMQMethodBody"
end
+ else
+ public_api("qpid/framing/#{classname}.h") # Non-method structs are public
end
- public_api("qpid/framing/#{classname}.h")
h_file("qpid/framing/#{classname}.h") {
if (s.kind_of? AmqpMethod)
gen <<EOS
diff --git a/qpid/cpp/src/CMakeLists.txt b/qpid/cpp/src/CMakeLists.txt
index 786facced9..6deacbbece 100644
--- a/qpid/cpp/src/CMakeLists.txt
+++ b/qpid/cpp/src/CMakeLists.txt
@@ -118,19 +118,6 @@ if (ENABLE_VALGRIND AND NOT VALGRIND)
message(STATUS "Can't locate the valgrind command; no run-time error detection")
endif (ENABLE_VALGRIND AND NOT VALGRIND)
-set(QPIDC_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib CACHE STRING
- "Directory to install library files")
-set(QPIDC_INSTALL_CONFDIR ${CMAKE_INSTALL_PREFIX}/etc CACHE STRING
- "Directory to install configuration files")
-set(QPIDC_MODULE_DIR ${QPIDC_INSTALL_LIBDIR}/qpid/client CACHE STRING
- "Directory to load client plug-in modules from")
-set(QPIDD_MODULE_DIR ${QPIDC_INSTALL_LIBDIR}/qpid/daemon CACHE STRING
- "Directory to load broker plug-in modules from")
-set(QPIDC_CONF_FILE ${QPIDC_INSTALL_CONFDIR}/qpid/qpidc.conf CACHE STRING
- "Name of the Qpid client configuration file")
-set(QPIDD_CONF_FILE ${QPIDC_INSTALL_CONFDIR}/qpid/qpidd.conf CACHE STRING
- "Name of the Qpid broker configuration file")
-
option(ENABLE_WARNINGS "Enable lots of compiler warnings (recommended)" ON)
if (ENABLE_WARNINGS AND CMAKE_COMPILER_IS_GNUCXX)
# Warnings: Enable as many as possible, keep the code clean. Please
@@ -272,6 +259,9 @@ if (BUILD_XML)
PREFIX ""
LINK_FLAGS -Wl,--no-undefined)
endif (CMAKE_COMPILER_IS_GNUCXX)
+ install (TARGETS xml RUNTIME
+ DESTINATION ${QPIDD_MODULE_DIR}
+ COMPONENT ${QPID_COMPONENT_BROKER})
set(xml_tests XmlClientSessionTest)
@@ -301,6 +291,9 @@ if (BUILD_ACL)
PREFIX ""
LINK_FLAGS -Wl,--no-undefined)
endif (CMAKE_COMPILER_IS_GNUCXX)
+ install (TARGETS acl
+ DESTINATION ${QPIDD_MODULE_DIR}
+ COMPONENT ${QPID_COMPONENT_BROKER})
endif (BUILD_ACL)
# Check for optional cluster support requirements
@@ -329,7 +322,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
)
endif (MSVC)
- set (libqpidcommon_platform_SOURCES
+ set (qpidcommon_platform_SOURCES
qpid/log/windows/SinkOptions.cpp
qpid/sys/windows/AsynchIO.cpp
qpid/sys/windows/FileSysDir.cpp
@@ -346,15 +339,22 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
qpid/sys/windows/Time.cpp
qpid/sys/windows/uuid.cpp
)
- set (libqpidcommon_platform_LIBS
+ set (qpidcommon_platform_LIBS
rpcrt4 ws2_32
)
- set (libqpidbroker_platform_SOURCES
+ set (qpidcommon_platform_INSTALL_HEADERS
+ ../include/qpid/sys/windows/Condition.h
+ ../include/qpid/sys/windows/IntegerTypes.h
+ ../include/qpid/sys/windows/Mutex.h
+ ../include/qpid/sys/windows/Time.h
+ ../include/qpid/sys/windows/check.h
+ )
+ set (qpidbroker_platform_SOURCES
qpid/broker/windows/BrokerDefaults.cpp
qpid/broker/windows/SaslAuthenticator.cpp
)
- set (libqpidclient_platform_SOURCES
+ set (qpidclient_platform_SOURCES
qpid/client/windows/SaslFactory.cpp
)
@@ -375,7 +375,7 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
set (qpid_poller_module qpid/sys/solaris/ECFPoller.cpp)
endif (CMAKE_SYSTEM_NAME STREQUAL SunOS)
- set (libqpidcommon_platform_SOURCES
+ set (qpidcommon_platform_SOURCES
qpid/sys/posix/AsynchIO.cpp
qpid/sys/posix/Fork.cpp
qpid/sys/posix/FileSysDir.cpp
@@ -394,14 +394,22 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
${qpid_poller_module}
)
- set (libqpidcommon_platform_LIBS
+ set (qpidcommon_platform_LIBS
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
uuid
${CMAKE_DL_LIBS}
)
+ set (qpidcommon_platform_INSTALL_HEADERS
+ ../include/qpid/sys/posix/Condition.h
+ ../include/qpid/sys/posix/IntegerTypes.h
+ ../include/qpid/sys/posix/Mutex.h
+ ../include/qpid/sys/posix/PrivatePosix.h
+ ../include/qpid/sys/posix/Time.h
+ ../include/qpid/sys/posix/check.h
+ )
- set (libqpidbroker_platform_SOURCES
+ set (qpidbroker_platform_SOURCES
qpid/broker/Daemon.cpp
qpid/broker/SaslAuthenticator.cpp
qpid/broker/SignalHandler.h
@@ -409,7 +417,7 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
qpid/broker/posix/BrokerDefaults.cpp
)
- set (libqpidclient_platform_SOURCES
+ set (qpidclient_platform_SOURCES
qpid/client/SaslFactory.cpp
)
@@ -418,9 +426,9 @@ else (CMAKE_SYSTEM_NAME STREQUAL Windows)
)
endif (CMAKE_SYSTEM_NAME STREQUAL Windows)
-set (libqpidcommon_SOURCES
+set (qpidcommon_SOURCES
${rgen_framing_srcs}
- ${libqpidcommon_platform_SOURCES}
+ ${qpidcommon_platform_SOURCES}
${qpidcommon_sasl_source}
qpid/assert.cpp
qpid/Address.cpp
@@ -476,19 +484,23 @@ set (libqpidcommon_SOURCES
qpid/sys/Shlib.cpp
qpid/sys/Timer.cpp
)
-add_library (qpidcommon SHARED ${libqpidcommon_SOURCES})
+
+add_library (qpidcommon SHARED ${qpidcommon_SOURCES})
if (CLOCK_GETTIME_IN_RT)
- set (libqpidcommon_platform_LIBS ${libqpidcommon_platform_LIBS} rt)
+ set (qpidcommon_platform_LIBS ${qpidcommon_platform_LIBS} rt)
endif (CLOCK_GETTIME_IN_RT)
target_link_libraries (qpidcommon
- ${libqpidcommon_platform_LIBS}
+ ${qpidcommon_platform_LIBS}
${qpidcommon_sasl_lib})
set_target_properties (qpidcommon PROPERTIES
VERSION ${qpidc_version})
+install (TARGETS qpidcommon
+ DESTINATION ${QPID_INSTALL_LIBDIR}
+ COMPONENT ${QPID_COMPONENT_COMMON})
-set (libqpidclient_SOURCES
+set (qpidclient_SOURCES
${rgen_client_srcs}
- ${libqpidclient_platform_SOURCES}
+ ${qpidclient_platform_SOURCES}
qpid/client/Bounds.cpp
qpid/client/Completion.cpp
qpid/client/Connection.cpp
@@ -527,6 +539,10 @@ set (libqpidclient_SOURCES
qpid/messaging/Connection.cpp
qpid/messaging/ConnectionImpl.h
qpid/messaging/Filter.cpp
+ qpid/messaging/ListContent.cpp
+ qpid/messaging/ListView.cpp
+ qpid/messaging/MapContent.cpp
+ qpid/messaging/MapView.cpp
qpid/messaging/Message.cpp
qpid/messaging/MessageImpl.h
qpid/messaging/MessageImpl.cpp
@@ -558,13 +574,100 @@ set (libqpidclient_SOURCES
qpid/client/amqp0_10/SenderImpl.h
qpid/client/amqp0_10/SenderImpl.cpp
)
-add_library (qpidclient SHARED ${libqpidclient_SOURCES})
+set (qpidclient_INSTALL_HEADERS
+ ../include/qpid/Address.h
+ ../include/qpid/CommonImportExport.h
+ ../include/qpid/Exception.h
+ ../include/qpid/InlineAllocator.h
+ ../include/qpid/InlineVector.h
+ ../include/qpid/Msg.h
+ ../include/qpid/Options.h
+ ../include/qpid/RangeSet.h
+ ../include/qpid/SessionId.h
+ ../include/qpid/Url.h
+ ../include/qpid/client/AsyncSession.h
+ ../include/qpid/client/ClientImportExport.h
+ ../include/qpid/client/Completion.h
+ ../include/qpid/client/Connection.h
+ ../include/qpid/client/ConnectionSettings.h
+ ../include/qpid/client/FailoverManager.h
+ ../include/qpid/client/FlowControl.h
+ ../include/qpid/client/Future.h
+ ../include/qpid/client/FutureCompletion.h
+ ../include/qpid/client/FutureResult.h
+ ../include/qpid/client/Handle.h
+ ../include/qpid/client/LocalQueue.h
+ ../include/qpid/client/Message.h
+ ../include/qpid/client/MessageListener.h
+ ../include/qpid/client/MessageReplayTracker.h
+ ../include/qpid/client/QueueOptions.h
+ ../include/qpid/client/Session.h
+ ../include/qpid/client/SessionBase_0_10.h
+ ../include/qpid/client/Subscription.h
+ ../include/qpid/client/SubscriptionManager.h
+ ../include/qpid/client/SubscriptionSettings.h
+ ../include/qpid/client/TypedResult.h
+ ../include/qpid/framing/Array.h
+ ../include/qpid/framing/Buffer.h
+ ../include/qpid/framing/FieldTable.h
+ ../include/qpid/framing/FieldValue.h
+ ../include/qpid/framing/List.h
+ ../include/qpid/framing/ProtocolVersion.h
+ ../include/qpid/framing/SequenceNumber.h
+ ../include/qpid/framing/SequenceSet.h
+ ../include/qpid/framing/StructHelper.h
+ ../include/qpid/framing/Uuid.h
+ ../include/qpid/framing/amqp_types.h
+ ../include/qpid/framing/amqp_types_full.h
+ ../include/qpid/log/Logger.h
+ ../include/qpid/log/Options.h
+ ../include/qpid/log/Selector.h
+ ../include/qpid/log/SinkOptions.h
+ ../include/qpid/log/Statement.h
+ ../include/qpid/management/Args.h
+ ../include/qpid/management/Manageable.h
+ ../include/qpid/management/ManagementEvent.h
+ ../include/qpid/management/ManagementObject.h
+ ../include/qpid/sys/Condition.h
+ ../include/qpid/sys/IOHandle.h
+ ../include/qpid/sys/IntegerTypes.h
+ ../include/qpid/sys/Monitor.h
+ ../include/qpid/sys/Mutex.h
+ ../include/qpid/sys/Runnable.h
+ ../include/qpid/sys/StrError.h
+ ../include/qpid/sys/SystemInfo.h
+ ../include/qpid/sys/Thread.h
+ ../include/qpid/sys/Time.h
+ ../include/qpid/messaging/Address.h
+ ../include/qpid/messaging/Connection.h
+ ../include/qpid/messaging/Codec.h
+ ../include/qpid/messaging/Filter.h
+ ../include/qpid/messaging/ListContent.h
+ ../include/qpid/messaging/ListView.h
+ ../include/qpid/messaging/MapContent.h
+ ../include/qpid/messaging/MapView.h
+ ../include/qpid/messaging/Message.h
+ ../include/qpid/messaging/MessageListener.h
+ ../include/qpid/messaging/Sender.h
+ ../include/qpid/messaging/Receiver.h
+ ../include/qpid/messaging/Session.h
+ ../include/qpid/messaging/Variant.h
+ ../include/qpid/client/amqp0_10/Codecs.h
+)
+
+add_library (qpidclient SHARED ${qpidclient_SOURCES})
target_link_libraries (qpidclient qpidcommon)
set_target_properties (qpidclient PROPERTIES VERSION ${qpidc_version})
-
-set (libqpidbroker_SOURCES
+install (TARGETS qpidclient
+ DESTINATION ${QPID_INSTALL_LIBDIR}
+ COMPONENT ${QPID_COMPONENT_CLIENT})
+install (DIRECTORY ../include/qpid DESTINATION ${QPID_INSTALL_INCLUDEDIR}
+ COMPONENT ${QPID_COMPONENT_CLIENT_INCLUDE}
+ PATTERN ".svn" EXCLUDE)
+
+set (qpidbroker_SOURCES
${mgen_broker_cpp}
- ${libqpidbroker_platform_SOURCES}
+ ${qpidbroker_platform_SOURCES}
qpid/amqp_0_10/Connection.h
qpid/amqp_0_10/Connection.cpp
qpid/broker/Broker.cpp
@@ -629,12 +732,15 @@ set (libqpidbroker_SOURCES
qpid/management/ManagementExchange.cpp
qpid/sys/TCPIOPlugin.cpp
)
-add_library (qpidbroker SHARED ${libqpidbroker_SOURCES})
+add_library (qpidbroker SHARED ${qpidbroker_SOURCES})
target_link_libraries (qpidbroker qpidcommon)
set_target_properties (qpidbroker PROPERTIES VERSION ${qpidc_version})
if (MSVC)
set_target_properties (qpidbroker PROPERTIES COMPILE_FLAGS /wd4290)
endif (MSVC)
+install (TARGETS qpidbroker LIBRARY
+ DESTINATION ${QPID_INSTALL_LIBDIR}
+ COMPONENT ${QPID_COMPONENT_BROKER})
set (qpidd_SOURCES
${qpidd_platform_SOURCES}
@@ -644,53 +750,65 @@ set (qpidd_SOURCES
add_executable (qpidd ${qpidd_SOURCES})
target_link_libraries (qpidd qpidbroker qpidcommon ${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_FILESYSTEM_LIBRARY})
+install (TARGETS qpidd RUNTIME
+ DESTINATION ${QPID_INSTALL_BINDIR}
+ COMPONENT ${QPID_COMPONENT_BROKER})
-# QMF agent library
-#module_hdr += \
-# qpid/agent/ManagementAgent.h \
-# qpid/agent/ManagementAgentImpl.h
-set (qmfagent_SOURCES
- qmf/AgentEngine.cpp
- qmf/AgentEngine.h
+# QMF library
+# Library Version Information (CURRENT.REVISION.AGE):
+#
+# CURRENT => API/ABI version. Bump this if the interface changes
+# REVISION => Version of underlying implementation.
+# Bump if implementation changes but API/ABI doesn't
+# AGE => Number of API/ABI versions this is backward compatible with
+set (qmf_version 1.0.0)
+set (qmfengine_version 1.0.0)
+
+set (qmf_SOURCES
qpid/agent/ManagementAgentImpl.cpp
qpid/agent/ManagementAgentImpl.h
)
-add_library (qmfagent SHARED ${qmfagent_SOURCES})
-target_link_libraries (qmfagent qmfcommon)
-set_target_properties (qmfagent PROPERTIES
- VERSION ${qpidc_version})
-
-set (qmfcommon_SOURCES
- qmf/ConnectionSettingsImpl.cpp
- qmf/ConnectionSettingsImpl.h
- qmf/ConsoleEngine.h
- qmf/Event.h
- qmf/Message.h
- qmf/MessageImpl.cpp
- qmf/MessageImpl.h
- qmf/Object.h
- qmf/ObjectId.h
- qmf/ObjectIdImpl.cpp
- qmf/ObjectIdImpl.h
- qmf/ObjectImpl.cpp
- qmf/ObjectImpl.h
- qmf/Query.h
- qmf/QueryImpl.cpp
- qmf/QueryImpl.h
- qmf/ResilientConnection.cpp
- qmf/ResilientConnection.h
- qmf/Schema.h
- qmf/SchemaImpl.cpp
- qmf/SchemaImpl.h
- qmf/Typecode.h
- qmf/Value.h
- qmf/ValueImpl.cpp
- qmf/ValueImpl.h
+add_library (qmf SHARED ${qmf_SOURCES})
+target_link_libraries (qmf qmfengine)
+set_target_properties (qmf PROPERTIES
+ VERSION ${qmf_version})
+install (TARGETS qmf LIBRARY
+ DESTINATION ${QPID_INSTALL_LIBDIR}
+ COMPONENT ${QPID_COMPONENT_QMF})
+
+set (qmfengine_SOURCES
+ qmf/engine/Agent.cpp
+ qmf/engine/BrokerProxyImpl.cpp
+ qmf/engine/BrokerProxyImpl.h
+ qmf/engine/ConnectionSettingsImpl.cpp
+ qmf/engine/ConnectionSettingsImpl.h
+ qmf/engine/ConsoleImpl.cpp
+ qmf/engine/ConsoleImpl.h
+ qmf/engine/MessageImpl.cpp
+ qmf/engine/MessageImpl.h
+ qmf/engine/ObjectIdImpl.cpp
+ qmf/engine/ObjectIdImpl.h
+ qmf/engine/ObjectImpl.cpp
+ qmf/engine/ObjectImpl.h
+ qmf/engine/Protocol.cpp
+ qmf/engine/Protocol.h
+ qmf/engine/QueryImpl.cpp
+ qmf/engine/QueryImpl.h
+ qmf/engine/ResilientConnection.cpp
+ qmf/engine/SequenceManager.cpp
+ qmf/engine/SequenceManager.h
+ qmf/engine/SchemaImpl.cpp
+ qmf/engine/SchemaImpl.h
+ qmf/engine/ValueImpl.cpp
+ qmf/engine/ValueImpl.h
)
-add_library (qmfcommon SHARED ${qmfcommon_SOURCES})
-target_link_libraries (qmfcommon qpidclient)
-set_target_properties (qmfcommon PROPERTIES
- VERSION ${qpidc_version})
+add_library (qmfengine SHARED ${qmfengine_SOURCES})
+target_link_libraries (qmfengine qpidclient)
+set_target_properties (qmfengine PROPERTIES
+ VERSION ${qmfengine_version})
+install (TARGETS qmfengine
+ DESTINATION ${QPID_INSTALL_LIBDIR}
+ COMPONENT ${QPID_COMPONENT_QMF})
# QMF console library
#module_hdr += \
@@ -737,6 +855,9 @@ add_library (qmfconsole SHARED ${qmfconsole_SOURCES})
target_link_libraries (qmfconsole qpidclient)
set_target_properties (qmfconsole PROPERTIES
VERSION ${qpidc_version})
+install (TARGETS qmfconsole
+ DESTINATION ${QPID_INSTALL_LIBDIR}
+ COMPONENT ${QPID_COMPONENT_QMF})
# A queue event listener plugin that creates messages on a replication
# queue corresponding to enqueue and dequeue events:
@@ -752,6 +873,9 @@ if (CMAKE_COMPILER_IS_GNUCXX)
set_target_properties(replicating_listener PROPERTIES
LINK_FLAGS -Wl,--no-undefined)
endif (CMAKE_COMPILER_IS_GNUCXX)
+install (TARGETS replicating_listener
+ DESTINATION ${QPIDD_MODULE_DIR}
+ COMPONENT ${QPID_COMPONENT_BROKER})
# A custom exchange plugin that allows an exchange to be created that
# can process the messages from a replication queue (populated on the
@@ -769,6 +893,9 @@ if (CMAKE_COMPILER_IS_GNUCXX)
set_target_properties(replicating_exchange PROPERTIES
LINK_FLAGS -Wl,--no-undefined)
endif (CMAKE_COMPILER_IS_GNUCXX)
+install (TARGETS replicating_exchange
+ DESTINATION ${QPIDD_MODULE_DIR}
+ COMPONENT ${QPID_COMPONENT_BROKER})
# This is only really needed until all the trunk builds (Linux, UNIX, Windows)
# are all on cmake only. This is because cmake builds always have a config.h
diff --git a/qpid/cpp/src/Makefile.am b/qpid/cpp/src/Makefile.am
index 4988f3f031..a6b90d7bde 100644
--- a/qpid/cpp/src/Makefile.am
+++ b/qpid/cpp/src/Makefile.am
@@ -144,6 +144,7 @@ libqpidcommon_la_SOURCES += \
qpid/log/posix/SinkOptions.cpp \
qpid/sys/posix/IOHandle.cpp \
qpid/sys/posix/Socket.cpp \
+ qpid/sys/posix/SocketAddress.cpp \
qpid/sys/posix/AsynchIO.cpp \
qpid/sys/posix/FileSysDir.cpp \
qpid/sys/posix/LockFile.cpp \
@@ -456,6 +457,7 @@ libqpidcommon_la_SOURCES += \
qpid/sys/Shlib.h \
qpid/sys/ShutdownHandler.h \
qpid/sys/Socket.h \
+ qpid/sys/SocketAddress.h \
qpid/sys/StateMonitor.h \
qpid/sys/TimeoutHandler.h \
qpid/sys/Timer.cpp \
@@ -686,6 +688,10 @@ libqpidclient_la_SOURCES = \
qpid/messaging/Address.cpp \
qpid/messaging/Connection.cpp \
qpid/messaging/Filter.cpp \
+ qpid/messaging/ListContent.cpp \
+ qpid/messaging/ListView.cpp \
+ qpid/messaging/MapContent.cpp \
+ qpid/messaging/MapView.cpp \
qpid/messaging/Message.cpp \
qpid/messaging/MessageImpl.h \
qpid/messaging/MessageImpl.cpp \
@@ -790,8 +796,11 @@ nobase_include_HEADERS += \
../include/qpid/messaging/Connection.h \
../include/qpid/messaging/Codec.h \
../include/qpid/messaging/Filter.h \
+ ../include/qpid/messaging/ListContent.h \
+ ../include/qpid/messaging/ListView.h \
+ ../include/qpid/messaging/MapContent.h \
+ ../include/qpid/messaging/MapView.h \
../include/qpid/messaging/Message.h \
- ../include/qpid/messaging/MessageContent.h \
../include/qpid/messaging/MessageListener.h \
../include/qpid/messaging/Sender.h \
../include/qpid/messaging/Receiver.h \
diff --git a/qpid/cpp/src/cluster.mk b/qpid/cpp/src/cluster.mk
index d90a06e1e2..1a8812d169 100644
--- a/qpid/cpp/src/cluster.mk
+++ b/qpid/cpp/src/cluster.mk
@@ -82,8 +82,7 @@ cluster_la_SOURCES = \
qpid/cluster/PollerDispatch.h \
qpid/cluster/ProxyInputHandler.h \
qpid/cluster/Quorum.h \
- qpid/cluster/types.h \
- qpid/sys/LatencyTracker.h
+ qpid/cluster/types.h
cluster_la_LIBADD= -lcpg $(libcman) libqpidbroker.la libqpidclient.la
cluster_la_CXXFLAGS = $(AM_CXXFLAGS) -fno-strict-aliasing
diff --git a/qpid/cpp/src/qmf.mk b/qpid/cpp/src/qmf.mk
index 54110ebaf7..2d034cf7c4 100644
--- a/qpid/cpp/src/qmf.mk
+++ b/qpid/cpp/src/qmf.mk
@@ -20,12 +20,14 @@
#
# qmf library makefile fragment, to be included in Makefile.am
#
-lib_LTLIBRARIES += \
- libqmfcommon.la \
- libqmfagent.la
+lib_LTLIBRARIES += \
+ libqmf.la \
+ libqmfengine.la
-# Public header files
-nobase_include_HEADERS += \
+#
+# Public headers for the QMF API
+#
+QMF_API = \
../include/qpid/agent/ManagementAgent.h \
../include/qpid/agent/QmfAgentImportExport.h \
../include/qmf/Agent.h \
@@ -34,42 +36,78 @@ nobase_include_HEADERS += \
../include/qmf/ConnectionSettings.h \
../include/qmf/AgentObject.h
-libqmfcommon_la_SOURCES = \
- qmf/ConnectionSettingsImpl.cpp \
- qmf/ConnectionSettingsImpl.h \
- qmf/ConsoleEngine.cpp \
- qmf/ConsoleEngine.h \
- qmf/Event.h \
- qmf/Message.h \
- qmf/MessageImpl.cpp \
- qmf/MessageImpl.h \
- qmf/Object.h \
- qmf/ObjectId.h \
- qmf/ObjectIdImpl.cpp \
- qmf/ObjectIdImpl.h \
- qmf/ObjectImpl.cpp \
- qmf/ObjectImpl.h \
- qmf/Protocol.cpp \
- qmf/Protocol.h \
- qmf/Query.h \
- qmf/QueryImpl.cpp \
- qmf/QueryImpl.h \
- qmf/ResilientConnection.cpp \
- qmf/ResilientConnection.h \
- qmf/SequenceManager.cpp \
- qmf/SequenceManager.h \
- qmf/Schema.h \
- qmf/SchemaImpl.cpp \
- qmf/SchemaImpl.h \
- qmf/Typecode.h \
- qmf/Value.h \
- qmf/ValueImpl.cpp \
- qmf/ValueImpl.h
+#
+# Public headers for the QMF Engine API
+#
+QMF_ENGINE_API = \
+ ../include/qmf/engine/Agent.h \
+ ../include/qmf/engine/ConnectionSettings.h \
+ ../include/qmf/engine/Console.h \
+ ../include/qmf/engine/Event.h \
+ ../include/qmf/engine/Message.h \
+ ../include/qmf/engine/Object.h \
+ ../include/qmf/engine/ObjectId.h \
+ ../include/qmf/engine/QmfEngineImportExport.h \
+ ../include/qmf/engine/Query.h \
+ ../include/qmf/engine/ResilientConnection.h \
+ ../include/qmf/engine/Schema.h \
+ ../include/qmf/engine/Typecode.h \
+ ../include/qmf/engine/Value.h
+
+# Public header files
+nobase_include_HEADERS += \
+ $(QMF_API) \
+ $(QMF_ENGINE_API)
-libqmfagent_la_SOURCES = \
- qmf/AgentEngine.cpp \
- qmf/AgentEngine.h \
- qpid/agent/ManagementAgentImpl.cpp \
+libqmf_la_SOURCES = \
+ $(QMF_API) \
+ qpid/agent/ManagementAgentImpl.cpp \
qpid/agent/ManagementAgentImpl.h
-libqmfagent_la_LIBADD = libqpidclient.la libqmfcommon.la
+libqmfengine_la_SOURCES = \
+ $(QMF_ENGINE_API) \
+ qmf/engine/Agent.cpp \
+ qmf/engine/BrokerProxyImpl.cpp \
+ qmf/engine/BrokerProxyImpl.h \
+ qmf/engine/ConnectionSettingsImpl.cpp \
+ qmf/engine/ConnectionSettingsImpl.h \
+ qmf/engine/ConsoleImpl.cpp \
+ qmf/engine/ConsoleImpl.h \
+ qmf/engine/MessageImpl.cpp \
+ qmf/engine/MessageImpl.h \
+ qmf/engine/ObjectIdImpl.cpp \
+ qmf/engine/ObjectIdImpl.h \
+ qmf/engine/ObjectImpl.cpp \
+ qmf/engine/ObjectImpl.h \
+ qmf/engine/Protocol.cpp \
+ qmf/engine/Protocol.h \
+ qmf/engine/QueryImpl.cpp \
+ qmf/engine/QueryImpl.h \
+ qmf/engine/ResilientConnection.cpp \
+ qmf/engine/SequenceManager.cpp \
+ qmf/engine/SequenceManager.h \
+ qmf/engine/SchemaImpl.cpp \
+ qmf/engine/SchemaImpl.h \
+ qmf/engine/ValueImpl.cpp \
+ qmf/engine/ValueImpl.h
+
+libqmf_la_LIBADD = libqmfengine.la
+libqmfengine_la_LIBADD = libqpidclient.la
+
+# Library Version Information:
+#
+# CURRENT => API/ABI version. Bump this if the interface changes
+# REVISION => Version of underlying implementation.
+# Bump if implementation changes but API/ABI doesn't
+# AGE => Number of API/ABI versions this is backward compatible with
+#
+QMF_CURRENT = 1
+QMF_REVISION = 0
+QMF_AGE = 0
+
+QMF_ENGINE_CURRENT = 1
+QMF_ENGINE_REVISION = 0
+QMF_ENGINE_AGE = 0
+
+libqmf_la_LDFLAGS = -version-info $(QMF_CURRENT):$(QMF_REVISION):$(QMF_AGE)
+libqmfengine_la_LDFLAGS = -version-info $(QMF_ENGINE_CURRENT):$(QMF_ENGINE_REVISION):$(QMF_ENGINE_AGE)
diff --git a/qpid/cpp/src/qmf/ConsoleEngine.cpp b/qpid/cpp/src/qmf/ConsoleEngine.cpp
deleted file mode 100644
index e7991328ee..0000000000
--- a/qpid/cpp/src/qmf/ConsoleEngine.cpp
+++ /dev/null
@@ -1,1091 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/ConsoleEngine.h"
-#include "qmf/MessageImpl.h"
-#include "qmf/SchemaImpl.h"
-#include "qmf/Typecode.h"
-#include "qmf/ObjectImpl.h"
-#include "qmf/ObjectIdImpl.h"
-#include "qmf/QueryImpl.h"
-#include "qmf/ValueImpl.h"
-#include "qmf/Protocol.h"
-#include "qmf/SequenceManager.h"
-#include <qpid/framing/Buffer.h>
-#include <qpid/framing/Uuid.h>
-#include <qpid/framing/FieldTable.h>
-#include <qpid/framing/FieldValue.h>
-#include <qpid/sys/Mutex.h>
-#include <qpid/log/Statement.h>
-#include <qpid/sys/Time.h>
-#include <qpid/sys/SystemInfo.h>
-#include <string.h>
-#include <string>
-#include <deque>
-#include <map>
-#include <vector>
-#include <iostream>
-#include <fstream>
-#include <boost/shared_ptr.hpp>
-
-using namespace std;
-using namespace qmf;
-using namespace qpid::framing;
-using namespace qpid::sys;
-
-namespace qmf {
-
- struct MethodResponseImpl {
- typedef boost::shared_ptr<MethodResponseImpl> Ptr;
- MethodResponse* envelope;
- uint32_t status;
- auto_ptr<Value> exception;
- auto_ptr<Value> arguments;
-
- MethodResponseImpl(Buffer& buf);
- ~MethodResponseImpl() { delete envelope; }
- uint32_t getStatus() const { return status; }
- const Value* getException() const { return exception.get(); }
- const Value* getArgs() const { return arguments.get(); }
- };
-
- struct QueryResponseImpl {
- typedef boost::shared_ptr<QueryResponseImpl> Ptr;
- QueryResponse *envelope;
- uint32_t status;
- auto_ptr<Value> exception;
- vector<ObjectImpl::Ptr> results;
-
- QueryResponseImpl() : envelope(new QueryResponse(this)), status(0) {}
- ~QueryResponseImpl() { delete envelope; }
- uint32_t getStatus() const { return status; }
- const Value* getException() const { return exception.get(); }
- uint32_t getObjectCount() const { return results.size(); }
- const Object* getObject(uint32_t idx) const;
- };
-
- struct ConsoleEventImpl {
- typedef boost::shared_ptr<ConsoleEventImpl> Ptr;
- ConsoleEvent::EventKind kind;
- boost::shared_ptr<AgentProxyImpl> agent;
- string name;
- boost::shared_ptr<SchemaClassKey> classKey;
- Object* object;
- void* context;
- Event* event;
- uint64_t timestamp;
- uint32_t methodHandle;
- MethodResponseImpl::Ptr methodResponse;
-
- ConsoleEventImpl(ConsoleEvent::EventKind k) :
- kind(k), object(0), context(0), event(0), timestamp(0), methodHandle(0) {}
- ~ConsoleEventImpl() {}
- ConsoleEvent copy();
- };
-
- struct BrokerEventImpl {
- typedef boost::shared_ptr<BrokerEventImpl> Ptr;
- BrokerEvent::EventKind kind;
- string name;
- string exchange;
- string bindingKey;
- void* context;
- QueryResponseImpl::Ptr queryResponse;
-
- BrokerEventImpl(BrokerEvent::EventKind k) : kind(k) {}
- ~BrokerEventImpl() {}
- BrokerEvent copy();
- };
-
- struct AgentProxyImpl {
- typedef boost::shared_ptr<AgentProxyImpl> Ptr;
- AgentProxy* envelope;
- ConsoleEngineImpl* console;
- BrokerProxyImpl* broker;
- uint32_t agentBank;
- string label;
-
- AgentProxyImpl(ConsoleEngineImpl* c, BrokerProxyImpl* b, uint32_t ab, const string& l) :
- envelope(new AgentProxy(this)), console(c), broker(b), agentBank(ab), label(l) {}
- ~AgentProxyImpl() {}
- const string& getLabel() const { return label; }
- };
-
- class BrokerProxyImpl {
- public:
- typedef boost::shared_ptr<BrokerProxyImpl> Ptr;
-
- BrokerProxyImpl(BrokerProxy* e, ConsoleEngine& _console);
- ~BrokerProxyImpl() {}
-
- void sessionOpened(SessionHandle& sh);
- void sessionClosed();
- void startProtocol();
-
- void sendBufferLH(Buffer& buf, const string& destination, const string& routingKey);
- void handleRcvMessage(Message& message);
- bool getXmtMessage(Message& item) const;
- void popXmt();
-
- bool getEvent(BrokerEvent& event) const;
- void popEvent();
-
- uint32_t agentCount() const;
- const AgentProxy* getAgent(uint32_t idx) const;
- void sendQuery(const Query& query, void* context, const AgentProxy* agent);
- void sendGetRequestLH(SequenceContext::Ptr queryContext, const Query& query, const AgentProxyImpl* agent);
-
- void addBinding(const string& exchange, const string& key);
- void staticRelease() { decOutstanding(); }
-
- private:
- friend class StaticContext;
- friend class QueryContext;
- mutable Mutex lock;
- BrokerProxy* envelope;
- ConsoleEngineImpl* console;
- string queueName;
- Uuid brokerId;
- SequenceManager seqMgr;
- uint32_t requestsOutstanding;
- bool topicBound;
- vector<AgentProxyImpl::Ptr> agentList;
- deque<MessageImpl::Ptr> xmtQueue;
- deque<BrokerEventImpl::Ptr> eventQueue;
-
-# define MA_BUFFER_SIZE 65536
- char outputBuffer[MA_BUFFER_SIZE];
-
- BrokerEventImpl::Ptr eventDeclareQueue(const string& queueName);
- BrokerEventImpl::Ptr eventBind(const string& exchange, const string& queue, const string& key);
- BrokerEventImpl::Ptr eventSetupComplete();
- BrokerEventImpl::Ptr eventStable();
- BrokerEventImpl::Ptr eventQueryComplete(void* context, QueryResponseImpl::Ptr response);
-
- void handleBrokerResponse(Buffer& inBuffer, uint32_t seq);
- void handlePackageIndication(Buffer& inBuffer, uint32_t seq);
- void handleCommandComplete(Buffer& inBuffer, uint32_t seq);
- void handleClassIndication(Buffer& inBuffer, uint32_t seq);
- void handleMethodResponse(Buffer& inBuffer, uint32_t seq);
- void handleHeartbeatIndication(Buffer& inBuffer, uint32_t seq);
- void handleEventIndication(Buffer& inBuffer, uint32_t seq);
- void handleSchemaResponse(Buffer& inBuffer, uint32_t seq);
- ObjectImpl::Ptr handleObjectIndication(Buffer& inBuffer, uint32_t seq, bool prop, bool stat);
- void incOutstandingLH();
- void decOutstanding();
- };
-
- struct StaticContext : public SequenceContext {
- StaticContext(BrokerProxyImpl& b) : broker(b) {}
- ~StaticContext() {}
- void reserve() {}
- void release() { broker.staticRelease(); }
- bool handleMessage(uint8_t opcode, uint32_t sequence, Buffer& buffer);
- BrokerProxyImpl& broker;
- };
-
- struct QueryContext : public SequenceContext {
- QueryContext(BrokerProxyImpl& b, void* u) :
- broker(b), userContext(u), requestsOutstanding(0), queryResponse(new QueryResponseImpl()) {}
- ~QueryContext() {}
- void reserve();
- void release();
- bool handleMessage(uint8_t opcode, uint32_t sequence, Buffer& buffer);
-
- mutable Mutex lock;
- BrokerProxyImpl& broker;
- void* userContext;
- uint32_t requestsOutstanding;
- QueryResponseImpl::Ptr queryResponse;
- };
-
- class ConsoleEngineImpl {
- public:
- ConsoleEngineImpl(ConsoleEngine* e, const ConsoleSettings& settings = ConsoleSettings());
- ~ConsoleEngineImpl();
-
- bool getEvent(ConsoleEvent& event) const;
- void popEvent();
-
- void addConnection(BrokerProxy& broker, void* context);
- void delConnection(BrokerProxy& broker);
-
- uint32_t packageCount() const;
- const string& getPackageName(uint32_t idx) const;
-
- uint32_t classCount(const char* packageName) const;
- const SchemaClassKey* getClass(const char* packageName, uint32_t idx) const;
-
- ClassKind getClassKind(const SchemaClassKey* key) const;
- const SchemaObjectClass* getObjectClass(const SchemaClassKey* key) const;
- const SchemaEventClass* getEventClass(const SchemaClassKey* key) const;
-
- void bindPackage(const char* packageName);
- void bindClass(const SchemaClassKey* key);
- void bindClass(const char* packageName, const char* className);
-
- /*
- void startSync(const Query& query, void* context, SyncQuery& sync);
- void touchSync(SyncQuery& sync);
- void endSync(SyncQuery& sync);
- */
-
- private:
- friend class BrokerProxyImpl;
- ConsoleEngine* envelope;
- const ConsoleSettings& settings;
- mutable Mutex lock;
- deque<ConsoleEventImpl::Ptr> eventQueue;
- vector<BrokerProxyImpl*> brokerList;
- vector<pair<string, string> > bindingList; // exchange/key (empty exchange => QMF_EXCHANGE)
-
- // Declare a compare class for the class maps that compares the dereferenced
- // class key pointers. The default behavior would be to compare the pointer
- // addresses themselves.
- struct KeyCompare {
- bool operator()(const SchemaClassKeyImpl* left, const SchemaClassKeyImpl* right) const {
- return *left < *right;
- }
- };
-
- typedef map<const SchemaClassKeyImpl*, SchemaObjectClassImpl::Ptr, KeyCompare> ObjectClassList;
- typedef map<const SchemaClassKeyImpl*, SchemaEventClassImpl::Ptr, KeyCompare> EventClassList;
- typedef map<string, pair<ObjectClassList, EventClassList> > PackageList;
-
- PackageList packages;
-
- void learnPackage(const string& packageName);
- void learnClass(SchemaObjectClassImpl::Ptr cls);
- void learnClass(SchemaEventClassImpl::Ptr cls);
- bool haveClass(const SchemaClassKeyImpl& key) const;
- SchemaObjectClassImpl::Ptr getSchema(const SchemaClassKeyImpl& key) const;
- };
-}
-
-namespace {
- const char* QMF_EXCHANGE = "qpid.management";
- const char* DIR_EXCHANGE = "amq.direct";
- const char* BROKER_KEY = "broker";
- const char* BROKER_PACKAGE = "org.apache.qpid.broker";
- const char* AGENT_CLASS = "agent";
- const char* BROKER_AGENT_KEY = "agent.1.0";
-}
-
-const Object* QueryResponseImpl::getObject(uint32_t idx) const
-{
- vector<ObjectImpl::Ptr>::const_iterator iter = results.begin();
-
- while (idx > 0) {
- if (iter == results.end())
- return 0;
- iter++;
- idx--;
- }
-
- return (*iter)->envelope;
-}
-
-#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());}
-
-ConsoleEvent ConsoleEventImpl::copy()
-{
- ConsoleEvent item;
-
- ::memset(&item, 0, sizeof(ConsoleEvent));
- item.kind = kind;
- item.agent = agent.get() ? agent->envelope : 0;
- item.classKey = classKey.get();
- item.object = object;
- item.context = context;
- item.event = event;
- item.timestamp = timestamp;
- item.methodHandle = methodHandle;
- item.methodResponse = methodResponse.get() ? methodResponse->envelope : 0;
-
- STRING_REF(name);
-
- return item;
-}
-
-BrokerEvent BrokerEventImpl::copy()
-{
- BrokerEvent item;
-
- ::memset(&item, 0, sizeof(BrokerEvent));
- item.kind = kind;
-
- STRING_REF(name);
- STRING_REF(exchange);
- STRING_REF(bindingKey);
- item.context = context;
- item.queryResponse = queryResponse.get() ? queryResponse->envelope : 0;
-
- return item;
-}
-
-BrokerProxyImpl::BrokerProxyImpl(BrokerProxy* e, ConsoleEngine& _console) :
- envelope(e), console(_console.impl)
-{
- stringstream qn;
- qpid::TcpAddress addr;
-
- SystemInfo::getLocalHostname(addr);
- qn << "qmfc-" << SystemInfo::getProcessName() << "-" << addr << "-" << SystemInfo::getProcessId();
- queueName = qn.str();
-
- seqMgr.setUnsolicitedContext(SequenceContext::Ptr(new StaticContext(*this)));
-}
-
-void BrokerProxyImpl::sessionOpened(SessionHandle& /*sh*/)
-{
- Mutex::ScopedLock _lock(lock);
- agentList.clear();
- eventQueue.clear();
- xmtQueue.clear();
- eventQueue.push_back(eventDeclareQueue(queueName));
- eventQueue.push_back(eventBind(DIR_EXCHANGE, queueName, queueName));
- eventQueue.push_back(eventSetupComplete());
-
- // TODO: Store session handle
-}
-
-void BrokerProxyImpl::sessionClosed()
-{
- Mutex::ScopedLock _lock(lock);
- agentList.clear();
- eventQueue.clear();
- xmtQueue.clear();
-}
-
-void BrokerProxyImpl::startProtocol()
-{
- Mutex::ScopedLock _lock(lock);
- char rawbuffer[512];
- Buffer buffer(rawbuffer, 512);
-
- agentList.push_back(AgentProxyImpl::Ptr(new AgentProxyImpl(console, this, 0, "Agent embedded in broker")));
-
- requestsOutstanding = 1;
- topicBound = false;
- uint32_t sequence(seqMgr.reserve());
- Protocol::encodeHeader(buffer, Protocol::OP_BROKER_REQUEST, sequence);
- sendBufferLH(buffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT BrokerRequest seq=" << sequence);
-}
-
-void BrokerProxyImpl::sendBufferLH(Buffer& buf, const string& destination, const string& routingKey)
-{
- uint32_t length = buf.getPosition();
- MessageImpl::Ptr message(new MessageImpl);
-
- buf.reset();
- buf.getRawData(message->body, length);
- message->destination = destination;
- message->routingKey = routingKey;
- message->replyExchange = DIR_EXCHANGE;
- message->replyKey = queueName;
-
- xmtQueue.push_back(message);
-}
-
-void BrokerProxyImpl::handleRcvMessage(Message& message)
-{
- Buffer inBuffer(message.body, message.length);
- uint8_t opcode;
- uint32_t sequence;
-
- while (Protocol::checkHeader(inBuffer, &opcode, &sequence))
- seqMgr.dispatch(opcode, sequence, inBuffer);
-}
-
-bool BrokerProxyImpl::getXmtMessage(Message& item) const
-{
- Mutex::ScopedLock _lock(lock);
- if (xmtQueue.empty())
- return false;
- item = xmtQueue.front()->copy();
- return true;
-}
-
-void BrokerProxyImpl::popXmt()
-{
- Mutex::ScopedLock _lock(lock);
- if (!xmtQueue.empty())
- xmtQueue.pop_front();
-}
-
-bool BrokerProxyImpl::getEvent(BrokerEvent& event) const
-{
- Mutex::ScopedLock _lock(lock);
- if (eventQueue.empty())
- return false;
- event = eventQueue.front()->copy();
- return true;
-}
-
-void BrokerProxyImpl::popEvent()
-{
- Mutex::ScopedLock _lock(lock);
- if (!eventQueue.empty())
- eventQueue.pop_front();
-}
-
-uint32_t BrokerProxyImpl::agentCount() const
-{
- Mutex::ScopedLock _lock(lock);
- return agentList.size();
-}
-
-const AgentProxy* BrokerProxyImpl::getAgent(uint32_t idx) const
-{
- Mutex::ScopedLock _lock(lock);
- for (vector<AgentProxyImpl::Ptr>::const_iterator iter = agentList.begin();
- iter != agentList.end(); iter++)
- if (idx-- == 0)
- return (*iter)->envelope;
- return 0;
-}
-
-void BrokerProxyImpl::sendQuery(const Query& query, void* context, const AgentProxy* agent)
-{
- SequenceContext::Ptr queryContext(new QueryContext(*this, context));
- Mutex::ScopedLock _lock(lock);
- if (agent != 0) {
- sendGetRequestLH(queryContext, query, agent->impl);
- } else {
- // TODO (optimization) only send queries to agents that have the requested class+package
- for (vector<AgentProxyImpl::Ptr>::const_iterator iter = agentList.begin();
- iter != agentList.end(); iter++) {
- sendGetRequestLH(queryContext, query, (*iter).get());
- }
- }
-}
-
-void BrokerProxyImpl::sendGetRequestLH(SequenceContext::Ptr queryContext, const Query& query, const AgentProxyImpl* agent)
-{
- stringstream key;
- Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
- uint32_t sequence(seqMgr.reserve(queryContext));
-
- Protocol::encodeHeader(outBuffer, Protocol::OP_GET_QUERY, sequence);
- query.impl->encode(outBuffer);
- key << "agent.1." << agent->agentBank;
- sendBufferLH(outBuffer, QMF_EXCHANGE, key.str());
- QPID_LOG(trace, "SENT GetQuery seq=" << sequence << " key=" << key.str());
-}
-
-void BrokerProxyImpl::addBinding(const string& exchange, const string& key)
-{
- eventQueue.push_back(eventBind(exchange, queueName, key));
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventDeclareQueue(const string& queueName)
-{
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::DECLARE_QUEUE));
- event->name = queueName;
- return event;
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventBind(const string& exchange, const string& queue, const string& key)
-{
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::BIND));
- event->name = queue;
- event->exchange = exchange;
- event->bindingKey = key;
-
- return event;
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventSetupComplete()
-{
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::SETUP_COMPLETE));
- return event;
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventStable()
-{
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::STABLE));
- return event;
-}
-
-BrokerEventImpl::Ptr BrokerProxyImpl::eventQueryComplete(void* context, QueryResponseImpl::Ptr response)
-{
- BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::QUERY_COMPLETE));
- event->context = context;
- event->queryResponse = response;
- return event;
-}
-
-void BrokerProxyImpl::handleBrokerResponse(Buffer& inBuffer, uint32_t seq)
-{
- brokerId.decode(inBuffer);
- QPID_LOG(trace, "RCVD BrokerResponse seq=" << seq << " brokerId=" << brokerId);
- Mutex::ScopedLock _lock(lock);
- Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
- uint32_t sequence(seqMgr.reserve());
- incOutstandingLH();
- Protocol::encodeHeader(outBuffer, Protocol::OP_PACKAGE_REQUEST, sequence);
- sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT PackageRequest seq=" << sequence);
-}
-
-void BrokerProxyImpl::handlePackageIndication(Buffer& inBuffer, uint32_t seq)
-{
- string package;
-
- inBuffer.getShortString(package);
- QPID_LOG(trace, "RCVD PackageIndication seq=" << seq << " package=" << package);
- console->learnPackage(package);
-
- Mutex::ScopedLock _lock(lock);
- Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
- uint32_t sequence(seqMgr.reserve());
- incOutstandingLH();
- Protocol::encodeHeader(outBuffer, Protocol::OP_CLASS_QUERY, sequence);
- outBuffer.putShortString(package);
- sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT ClassQuery seq=" << sequence << " package=" << package);
-}
-
-void BrokerProxyImpl::handleCommandComplete(Buffer& inBuffer, uint32_t seq)
-{
- string text;
- uint32_t code = inBuffer.getLong();
- inBuffer.getShortString(text);
- QPID_LOG(trace, "RCVD CommandComplete seq=" << seq << " code=" << code << " text=" << text);
-}
-
-void BrokerProxyImpl::handleClassIndication(Buffer& inBuffer, uint32_t seq)
-{
- uint8_t kind = inBuffer.getOctet();
- SchemaClassKeyImpl classKey(inBuffer);
-
- QPID_LOG(trace, "RCVD ClassIndication seq=" << seq << " kind=" << (int) kind << " key=" << classKey.str());
-
- if (!console->haveClass(classKey)) {
- Mutex::ScopedLock _lock(lock);
- incOutstandingLH();
- Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
- uint32_t sequence(seqMgr.reserve());
- Protocol::encodeHeader(outBuffer, Protocol::OP_SCHEMA_REQUEST, sequence);
- classKey.encode(outBuffer);
- sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY);
- QPID_LOG(trace, "SENT SchemaRequest seq=" << sequence <<" key=" << classKey.str());
- }
-}
-
-void BrokerProxyImpl::handleMethodResponse(Buffer& /*inBuffer*/, uint32_t /*seq*/)
-{
- // TODO
-}
-
-void BrokerProxyImpl::handleHeartbeatIndication(Buffer& /*inBuffer*/, uint32_t /*seq*/)
-{
- // TODO
-}
-
-void BrokerProxyImpl::handleEventIndication(Buffer& /*inBuffer*/, uint32_t /*seq*/)
-{
- // TODO
-}
-
-void BrokerProxyImpl::handleSchemaResponse(Buffer& inBuffer, uint32_t seq)
-{
- SchemaObjectClassImpl::Ptr oClassPtr;
- SchemaEventClassImpl::Ptr eClassPtr;
- uint8_t kind = inBuffer.getOctet();
- const SchemaClassKeyImpl* key;
- if (kind == CLASS_OBJECT) {
- oClassPtr.reset(new SchemaObjectClassImpl(inBuffer));
- console->learnClass(oClassPtr);
- key = oClassPtr->getClassKey()->impl;
- QPID_LOG(trace, "RCVD SchemaResponse seq=" << seq << " kind=object key=" << key->str());
-
- //
- // If we have just learned about the org.apache.qpid.broker:agent class, send a get
- // request for the current list of agents so we can have it on-hand before we declare
- // this session "stable".
- //
- if (key->getClassName() == AGENT_CLASS && key->getPackageName() == BROKER_PACKAGE) {
- Mutex::ScopedLock _lock(lock);
- incOutstandingLH();
- Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
- uint32_t sequence(seqMgr.reserve());
- Protocol::encodeHeader(outBuffer, Protocol::OP_GET_QUERY, sequence);
- FieldTable ft;
- ft.setString("_class", AGENT_CLASS);
- ft.setString("_package", BROKER_PACKAGE);
- ft.encode(outBuffer);
- sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_AGENT_KEY);
- QPID_LOG(trace, "SENT GetQuery seq=" << sequence << " key=" << BROKER_AGENT_KEY);
- }
- } else if (kind == CLASS_EVENT) {
- eClassPtr.reset(new SchemaEventClassImpl(inBuffer));
- console->learnClass(eClassPtr);
- key = eClassPtr->getClassKey()->impl;
- QPID_LOG(trace, "RCVD SchemaResponse seq=" << seq << " kind=event key=" << key->str());
- }
- else {
- QPID_LOG(error, "BrokerProxyImpl::handleSchemaResponse received unknown class kind: " << (int) kind);
- }
-}
-
-ObjectImpl::Ptr BrokerProxyImpl::handleObjectIndication(Buffer& inBuffer, uint32_t seq, bool prop, bool stat)
-{
- SchemaClassKeyImpl classKey(inBuffer);
- QPID_LOG(trace, "RCVD ObjectIndication seq=" << seq << " key=" << classKey.str());
-
- SchemaObjectClassImpl::Ptr schema = console->getSchema(classKey);
- if (schema.get() == 0) {
- QPID_LOG(trace, "No Schema Found for ObjectIndication. seq=" << seq << " key=" << classKey.str());
- return ObjectImpl::Ptr();
- }
-
- return ObjectImpl::Ptr(new ObjectImpl(schema->envelope, inBuffer, prop, stat, true));
-}
-
-void BrokerProxyImpl::incOutstandingLH()
-{
- requestsOutstanding++;
-}
-
-void BrokerProxyImpl::decOutstanding()
-{
- Mutex::ScopedLock _lock(lock);
- requestsOutstanding--;
- if (requestsOutstanding == 0 && !topicBound) {
- topicBound = true;
- for (vector<pair<string, string> >::const_iterator iter = console->bindingList.begin();
- iter != console->bindingList.end(); iter++) {
- string exchange(iter->first.empty() ? QMF_EXCHANGE : iter->first);
- string key(iter->second);
- eventQueue.push_back(eventBind(exchange, queueName, key));
- }
- eventQueue.push_back(eventStable());
- }
-}
-
-MethodResponseImpl::MethodResponseImpl(Buffer& buf) : envelope(new MethodResponse(this))
-{
- string text;
-
- status = buf.getLong();
- buf.getMediumString(text);
- exception.reset(new Value(TYPE_LSTR));
- exception->setString(text.c_str());
-
- // TODO: Parse schema-specific output arguments.
- arguments.reset(new Value(TYPE_MAP));
-}
-
-bool StaticContext::handleMessage(uint8_t opcode, uint32_t sequence, Buffer& buffer)
-{
- bool completeContext = false;
- if (opcode == Protocol::OP_BROKER_RESPONSE) {
- broker.handleBrokerResponse(buffer, sequence);
- completeContext = true;
- }
- else if (opcode == Protocol::OP_COMMAND_COMPLETE) {
- broker.handleCommandComplete(buffer, sequence);
- completeContext = true;
- }
- else if (opcode == Protocol::OP_SCHEMA_RESPONSE) {
- broker.handleSchemaResponse(buffer, sequence);
- completeContext = true;
- }
- else if (opcode == Protocol::OP_PACKAGE_INDICATION)
- broker.handlePackageIndication(buffer, sequence);
- else if (opcode == Protocol::OP_CLASS_INDICATION)
- broker.handleClassIndication(buffer, sequence);
- else if (opcode == Protocol::OP_HEARTBEAT_INDICATION)
- broker.handleHeartbeatIndication(buffer, sequence);
- else if (opcode == Protocol::OP_EVENT_INDICATION)
- broker.handleEventIndication(buffer, sequence);
- else if (opcode == Protocol::OP_PROPERTY_INDICATION)
- broker.handleObjectIndication(buffer, sequence, true, false);
- else if (opcode == Protocol::OP_STATISTIC_INDICATION)
- broker.handleObjectIndication(buffer, sequence, false, true);
- else if (opcode == Protocol::OP_OBJECT_INDICATION)
- broker.handleObjectIndication(buffer, sequence, true, true);
- else {
- QPID_LOG(trace, "StaticContext::handleMessage invalid opcode: " << opcode);
- completeContext = true;
- }
-
- return completeContext;
-}
-
-void QueryContext::reserve()
-{
- Mutex::ScopedLock _lock(lock);
- requestsOutstanding++;
-}
-
-void QueryContext::release()
-{
- Mutex::ScopedLock _lock(lock);
- if (--requestsOutstanding == 0) {
- broker.eventQueue.push_back(broker.eventQueryComplete(userContext, queryResponse));
- }
-}
-
-bool QueryContext::handleMessage(uint8_t opcode, uint32_t sequence, Buffer& buffer)
-{
- bool completeContext = false;
- ObjectImpl::Ptr object;
-
- if (opcode == Protocol::OP_COMMAND_COMPLETE) {
- broker.handleCommandComplete(buffer, sequence);
- completeContext = true;
- }
- else if (opcode == Protocol::OP_OBJECT_INDICATION) {
- object = broker.handleObjectIndication(buffer, sequence, true, true);
- if (object.get() != 0)
- queryResponse->results.push_back(object);
- }
- else {
- QPID_LOG(trace, "QueryContext::handleMessage invalid opcode: " << opcode);
- completeContext = true;
- }
-
- return completeContext;
-}
-
-ConsoleEngineImpl::ConsoleEngineImpl(ConsoleEngine* e, const ConsoleSettings& s) :
- envelope(e), settings(s)
-{
- bindingList.push_back(pair<string, string>(string(), "schema.#"));
- if (settings.rcvObjects && settings.rcvEvents && settings.rcvHeartbeats && !settings.userBindings) {
- bindingList.push_back(pair<string, string>(string(), "console.#"));
- } else {
- if (settings.rcvObjects && !settings.userBindings)
- bindingList.push_back(pair<string, string>(string(), "console.obj.#"));
- else
- bindingList.push_back(pair<string, string>(string(), "console.obj.*.*.org.apache.qpid.broker.agent"));
- if (settings.rcvEvents)
- bindingList.push_back(pair<string, string>(string(), "console.event.#"));
- if (settings.rcvHeartbeats)
- bindingList.push_back(pair<string, string>(string(), "console.heartbeat.#"));
- }
-}
-
-ConsoleEngineImpl::~ConsoleEngineImpl()
-{
- // This function intentionally left blank.
-}
-
-bool ConsoleEngineImpl::getEvent(ConsoleEvent& event) const
-{
- Mutex::ScopedLock _lock(lock);
- if (eventQueue.empty())
- return false;
- event = eventQueue.front()->copy();
- return true;
-}
-
-void ConsoleEngineImpl::popEvent()
-{
- Mutex::ScopedLock _lock(lock);
- if (!eventQueue.empty())
- eventQueue.pop_front();
-}
-
-void ConsoleEngineImpl::addConnection(BrokerProxy& broker, void* /*context*/)
-{
- Mutex::ScopedLock _lock(lock);
- brokerList.push_back(broker.impl);
-}
-
-void ConsoleEngineImpl::delConnection(BrokerProxy& broker)
-{
- Mutex::ScopedLock _lock(lock);
- for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
- iter != brokerList.end(); iter++)
- if (*iter == broker.impl) {
- brokerList.erase(iter);
- break;
- }
-}
-
-uint32_t ConsoleEngineImpl::packageCount() const
-{
- Mutex::ScopedLock _lock(lock);
- return packages.size();
-}
-
-const string& ConsoleEngineImpl::getPackageName(uint32_t idx) const
-{
- const static string empty;
-
- Mutex::ScopedLock _lock(lock);
- if (idx >= packages.size())
- return empty;
-
- PackageList::const_iterator iter = packages.begin();
- for (uint32_t i = 0; i < idx; i++) iter++;
- return iter->first;
-}
-
-uint32_t ConsoleEngineImpl::classCount(const char* packageName) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(packageName);
- if (pIter == packages.end())
- return 0;
-
- const ObjectClassList& oList = pIter->second.first;
- const EventClassList& eList = pIter->second.second;
-
- return oList.size() + eList.size();
-}
-
-const SchemaClassKey* ConsoleEngineImpl::getClass(const char* packageName, uint32_t idx) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(packageName);
- if (pIter == packages.end())
- return 0;
-
- const ObjectClassList& oList = pIter->second.first;
- const EventClassList& eList = pIter->second.second;
- uint32_t count = 0;
-
- for (ObjectClassList::const_iterator oIter = oList.begin();
- oIter != oList.end(); oIter++) {
- if (count == idx)
- return oIter->second->getClassKey();
- count++;
- }
-
- for (EventClassList::const_iterator eIter = eList.begin();
- eIter != eList.end(); eIter++) {
- if (count == idx)
- return eIter->second->getClassKey();
- count++;
- }
-
- return 0;
-}
-
-ClassKind ConsoleEngineImpl::getClassKind(const SchemaClassKey* key) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return CLASS_OBJECT;
-
- const EventClassList& eList = pIter->second.second;
- if (eList.find(key->impl) != eList.end())
- return CLASS_EVENT;
- return CLASS_OBJECT;
-}
-
-const SchemaObjectClass* ConsoleEngineImpl::getObjectClass(const SchemaClassKey* key) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return 0;
-
- const ObjectClassList& oList = pIter->second.first;
- ObjectClassList::const_iterator iter = oList.find(key->impl);
- if (iter == oList.end())
- return 0;
- return iter->second->envelope;
-}
-
-const SchemaEventClass* ConsoleEngineImpl::getEventClass(const SchemaClassKey* key) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return 0;
-
- const EventClassList& eList = pIter->second.second;
- EventClassList::const_iterator iter = eList.find(key->impl);
- if (iter == eList.end())
- return 0;
- return iter->second->envelope;
-}
-
-void ConsoleEngineImpl::bindPackage(const char* packageName)
-{
- stringstream key;
- key << "console.obj.*.*." << packageName << ".#";
- Mutex::ScopedLock _lock(lock);
- bindingList.push_back(pair<string, string>(string(), key.str()));
- for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
- iter != brokerList.end(); iter++)
- (*iter)->addBinding(QMF_EXCHANGE, key.str());
-}
-
-void ConsoleEngineImpl::bindClass(const SchemaClassKey* classKey)
-{
- stringstream key;
- key << "console.obj.*.*." << classKey->getPackageName() << "." << classKey->getClassName() << ".#";
- Mutex::ScopedLock _lock(lock);
- bindingList.push_back(pair<string, string>(string(), key.str()));
- for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
- iter != brokerList.end(); iter++)
- (*iter)->addBinding(QMF_EXCHANGE, key.str());
-}
-
-void ConsoleEngineImpl::bindClass(const char* packageName, const char* className)
-{
- stringstream key;
- key << "console.obj.*.*." << packageName << "." << className << ".#";
- Mutex::ScopedLock _lock(lock);
- bindingList.push_back(pair<string, string>(string(), key.str()));
- for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
- iter != brokerList.end(); iter++)
- (*iter)->addBinding(QMF_EXCHANGE, key.str());
-}
-
-/*
-void ConsoleEngineImpl::startSync(const Query& query, void* context, SyncQuery& sync)
-{
-}
-
-void ConsoleEngineImpl::touchSync(SyncQuery& sync)
-{
-}
-
-void ConsoleEngineImpl::endSync(SyncQuery& sync)
-{
-}
-*/
-
-void ConsoleEngineImpl::learnPackage(const string& packageName)
-{
- Mutex::ScopedLock _lock(lock);
- if (packages.find(packageName) == packages.end())
- packages.insert(pair<string, pair<ObjectClassList, EventClassList> >
- (packageName, pair<ObjectClassList, EventClassList>(ObjectClassList(), EventClassList())));
-}
-
-void ConsoleEngineImpl::learnClass(SchemaObjectClassImpl::Ptr cls)
-{
- Mutex::ScopedLock _lock(lock);
- const SchemaClassKey* key = cls->getClassKey();
- PackageList::iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return;
-
- ObjectClassList& list = pIter->second.first;
- if (list.find(key->impl) == list.end())
- list[key->impl] = cls;
-}
-
-void ConsoleEngineImpl::learnClass(SchemaEventClassImpl::Ptr cls)
-{
- Mutex::ScopedLock _lock(lock);
- const SchemaClassKey* key = cls->getClassKey();
- PackageList::iterator pIter = packages.find(key->getPackageName());
- if (pIter == packages.end())
- return;
-
- EventClassList& list = pIter->second.second;
- if (list.find(key->impl) == list.end())
- list[key->impl] = cls;
-}
-
-bool ConsoleEngineImpl::haveClass(const SchemaClassKeyImpl& key) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(key.getPackageName());
- if (pIter == packages.end())
- return false;
-
- const ObjectClassList& oList = pIter->second.first;
- const EventClassList& eList = pIter->second.second;
-
- return oList.find(&key) != oList.end() || eList.find(&key) != eList.end();
-}
-
-SchemaObjectClassImpl::Ptr ConsoleEngineImpl::getSchema(const SchemaClassKeyImpl& key) const
-{
- Mutex::ScopedLock _lock(lock);
- PackageList::const_iterator pIter = packages.find(key.getPackageName());
- if (pIter == packages.end())
- return SchemaObjectClassImpl::Ptr();
-
- const ObjectClassList& oList = pIter->second.first;
- ObjectClassList::const_iterator iter = oList.find(&key);
- if (iter == oList.end())
- return SchemaObjectClassImpl::Ptr();
-
- return iter->second;
-}
-
-//==================================================================
-// Wrappers
-//==================================================================
-
-AgentProxy::AgentProxy(AgentProxyImpl* i) : impl(i) {}
-AgentProxy::~AgentProxy() { delete impl; }
-const char* AgentProxy::getLabel() const { return impl->getLabel().c_str(); }
-
-BrokerProxy::BrokerProxy(ConsoleEngine& console) : impl(new BrokerProxyImpl(this, console)) {}
-BrokerProxy::~BrokerProxy() { delete impl; }
-void BrokerProxy::sessionOpened(SessionHandle& sh) { impl->sessionOpened(sh); }
-void BrokerProxy::sessionClosed() { impl->sessionClosed(); }
-void BrokerProxy::startProtocol() { impl->startProtocol(); }
-void BrokerProxy::handleRcvMessage(Message& message) { impl->handleRcvMessage(message); }
-bool BrokerProxy::getXmtMessage(Message& item) const { return impl->getXmtMessage(item); }
-void BrokerProxy::popXmt() { impl->popXmt(); }
-bool BrokerProxy::getEvent(BrokerEvent& event) const { return impl->getEvent(event); }
-void BrokerProxy::popEvent() { impl->popEvent(); }
-uint32_t BrokerProxy::agentCount() const { return impl->agentCount(); }
-const AgentProxy* BrokerProxy::getAgent(uint32_t idx) const { return impl->getAgent(idx); }
-void BrokerProxy::sendQuery(const Query& query, void* context, const AgentProxy* agent) { impl->sendQuery(query, context, agent); }
-
-MethodResponse::MethodResponse(MethodResponseImpl* i) : impl(i) {}
-MethodResponse::~MethodResponse() {}
-uint32_t MethodResponse::getStatus() const { return impl->getStatus(); }
-const Value* MethodResponse::getException() const { return impl->getException(); }
-const Value* MethodResponse::getArgs() const { return impl->getArgs(); }
-
-QueryResponse::QueryResponse(QueryResponseImpl* i) : impl(i) {}
-QueryResponse::~QueryResponse() {}
-uint32_t QueryResponse::getStatus() const { return impl->getStatus(); }
-const Value* QueryResponse::getException() const { return impl->getException(); }
-uint32_t QueryResponse::getObjectCount() const { return impl->getObjectCount(); }
-const Object* QueryResponse::getObject(uint32_t idx) const { return impl->getObject(idx); }
-
-ConsoleEngine::ConsoleEngine(const ConsoleSettings& settings) : impl(new ConsoleEngineImpl(this, settings)) {}
-ConsoleEngine::~ConsoleEngine() { delete impl; }
-bool ConsoleEngine::getEvent(ConsoleEvent& event) const { return impl->getEvent(event); }
-void ConsoleEngine::popEvent() { impl->popEvent(); }
-void ConsoleEngine::addConnection(BrokerProxy& broker, void* context) { impl->addConnection(broker, context); }
-void ConsoleEngine::delConnection(BrokerProxy& broker) { impl->delConnection(broker); }
-uint32_t ConsoleEngine::packageCount() const { return impl->packageCount(); }
-const char* ConsoleEngine::getPackageName(uint32_t idx) const { return impl->getPackageName(idx).c_str(); }
-uint32_t ConsoleEngine::classCount(const char* packageName) const { return impl->classCount(packageName); }
-const SchemaClassKey* ConsoleEngine::getClass(const char* packageName, uint32_t idx) const { return impl->getClass(packageName, idx); }
-ClassKind ConsoleEngine::getClassKind(const SchemaClassKey* key) const { return impl->getClassKind(key); }
-const SchemaObjectClass* ConsoleEngine::getObjectClass(const SchemaClassKey* key) const { return impl->getObjectClass(key); }
-const SchemaEventClass* ConsoleEngine::getEventClass(const SchemaClassKey* key) const { return impl->getEventClass(key); }
-void ConsoleEngine::bindPackage(const char* packageName) { impl->bindPackage(packageName); }
-void ConsoleEngine::bindClass(const SchemaClassKey* key) { impl->bindClass(key); }
-void ConsoleEngine::bindClass(const char* packageName, const char* className) { impl->bindClass(packageName, className); }
-//void ConsoleEngine::startSync(const Query& query, void* context, SyncQuery& sync) { impl->startSync(query, context, sync); }
-//void ConsoleEngine::touchSync(SyncQuery& sync) { impl->touchSync(sync); }
-//void ConsoleEngine::endSync(SyncQuery& sync) { impl->endSync(sync); }
-
-
diff --git a/qpid/cpp/src/qmf/AgentEngine.cpp b/qpid/cpp/src/qmf/engine/Agent.cpp
index 9ea3be5907..c5d1bff2e0 100644
--- a/qpid/cpp/src/qmf/AgentEngine.cpp
+++ b/qpid/cpp/src/qmf/engine/Agent.cpp
@@ -17,15 +17,15 @@
* under the License.
*/
-#include "qmf/AgentEngine.h"
-#include "qmf/MessageImpl.h"
-#include "qmf/SchemaImpl.h"
-#include "qmf/Typecode.h"
-#include "qmf/ObjectImpl.h"
-#include "qmf/ObjectIdImpl.h"
-#include "qmf/QueryImpl.h"
-#include "qmf/ValueImpl.h"
-#include "qmf/Protocol.h"
+#include "qmf/engine/Agent.h"
+#include "qmf/engine/MessageImpl.h"
+#include "qmf/engine/SchemaImpl.h"
+#include "qmf/engine/Typecode.h"
+#include "qmf/engine/ObjectImpl.h"
+#include "qmf/engine/ObjectIdImpl.h"
+#include "qmf/engine/QueryImpl.h"
+#include "qmf/engine/ValueImpl.h"
+#include "qmf/engine/Protocol.h"
#include <qpid/framing/Buffer.h>
#include <qpid/framing/Uuid.h>
#include <qpid/framing/FieldTable.h>
@@ -40,13 +40,15 @@
#include <iostream>
#include <fstream>
#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
using namespace qpid::framing;
using namespace qpid::sys;
namespace qmf {
+namespace engine {
struct AgentEventImpl {
typedef boost::shared_ptr<AgentEventImpl> Ptr;
@@ -61,7 +63,7 @@ namespace qmf {
boost::shared_ptr<Value> arguments;
string exchange;
string bindingKey;
- SchemaObjectClass* objectClass;
+ const SchemaObjectClass* objectClass;
AgentEventImpl(AgentEvent::EventKind k) :
kind(k), sequence(0), object(0), objectClass(0) {}
@@ -74,14 +76,14 @@ namespace qmf {
uint32_t sequence;
string exchange;
string key;
- SchemaMethodImpl* schemaMethod;
+ const SchemaMethod* schemaMethod;
AgentQueryContext() : schemaMethod(0) {}
};
- class AgentEngineImpl {
+ class AgentImpl : public boost::noncopyable {
public:
- AgentEngineImpl(char* label, bool internalStore);
- ~AgentEngineImpl();
+ AgentImpl(char* label, bool internalStore);
+ ~AgentImpl();
void setStoreDir(const char* path);
void setTransferDir(const char* path);
@@ -163,8 +165,8 @@ namespace qmf {
}
};
- typedef map<AgentClassKey, SchemaObjectClassImpl*, AgentClassKeyComp> ObjectClassMap;
- typedef map<AgentClassKey, SchemaEventClassImpl*, AgentClassKeyComp> EventClassMap;
+ typedef map<AgentClassKey, SchemaObjectClass*, AgentClassKeyComp> ObjectClassMap;
+ typedef map<AgentClassKey, SchemaEventClass*, AgentClassKeyComp> EventClassMap;
struct ClassMaps {
ObjectClassMap objectClasses;
@@ -180,7 +182,7 @@ namespace qmf {
boost::shared_ptr<ObjectId> oid);
AgentEventImpl::Ptr eventMethod(uint32_t num, const string& userId, const string& method,
boost::shared_ptr<ObjectId> oid, boost::shared_ptr<Value> argMap,
- SchemaObjectClass* objectClass);
+ const SchemaObjectClass* objectClass);
void sendBufferLH(Buffer& buf, const string& destination, const string& routingKey);
void sendPackageIndicationLH(const string& packageName);
@@ -198,10 +200,11 @@ namespace qmf {
void handleConsoleAddedIndication();
};
}
+}
-const char* AgentEngineImpl::QMF_EXCHANGE = "qpid.management";
-const char* AgentEngineImpl::DIR_EXCHANGE = "amq.direct";
-const char* AgentEngineImpl::BROKER_KEY = "broker";
+const char* AgentImpl::QMF_EXCHANGE = "qpid.management";
+const char* AgentImpl::DIR_EXCHANGE = "amq.direct";
+const char* AgentImpl::BROKER_KEY = "broker";
#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());}
@@ -227,7 +230,7 @@ AgentEvent AgentEventImpl::copy()
return item;
}
-AgentEngineImpl::AgentEngineImpl(char* _label, bool i) :
+AgentImpl::AgentImpl(char* _label, bool i) :
label(_label), queueName("qmfa-"), internalStore(i), nextTransientId(1),
requestedBrokerBank(0), requestedAgentBank(0),
assignedBrokerBank(0), assignedAgentBank(0),
@@ -236,11 +239,11 @@ AgentEngineImpl::AgentEngineImpl(char* _label, bool i) :
queueName += label;
}
-AgentEngineImpl::~AgentEngineImpl()
+AgentImpl::~AgentImpl()
{
}
-void AgentEngineImpl::setStoreDir(const char* path)
+void AgentImpl::setStoreDir(const char* path)
{
Mutex::ScopedLock _lock(lock);
if (path)
@@ -249,7 +252,7 @@ void AgentEngineImpl::setStoreDir(const char* path)
storeDir.clear();
}
-void AgentEngineImpl::setTransferDir(const char* path)
+void AgentImpl::setTransferDir(const char* path)
{
Mutex::ScopedLock _lock(lock);
if (path)
@@ -258,7 +261,7 @@ void AgentEngineImpl::setTransferDir(const char* path)
transferDir.clear();
}
-void AgentEngineImpl::handleRcvMessage(Message& message)
+void AgentImpl::handleRcvMessage(Message& message)
{
Buffer inBuffer(message.body, message.length);
uint8_t opcode;
@@ -274,13 +277,13 @@ void AgentEngineImpl::handleRcvMessage(Message& message)
else if (opcode == Protocol::OP_GET_QUERY) handleGetQuery(inBuffer, sequence, replyToKey, userId);
else if (opcode == Protocol::OP_METHOD_REQUEST) handleMethodRequest(inBuffer, sequence, replyToKey, userId);
else {
- QPID_LOG(error, "AgentEngineImpl::handleRcvMessage invalid opcode=" << opcode);
+ QPID_LOG(error, "AgentImpl::handleRcvMessage invalid opcode=" << opcode);
break;
}
}
}
-bool AgentEngineImpl::getXmtMessage(Message& item) const
+bool AgentImpl::getXmtMessage(Message& item) const
{
Mutex::ScopedLock _lock(lock);
if (xmtQueue.empty())
@@ -289,14 +292,14 @@ bool AgentEngineImpl::getXmtMessage(Message& item) const
return true;
}
-void AgentEngineImpl::popXmt()
+void AgentImpl::popXmt()
{
Mutex::ScopedLock _lock(lock);
if (!xmtQueue.empty())
xmtQueue.pop_front();
}
-bool AgentEngineImpl::getEvent(AgentEvent& event) const
+bool AgentImpl::getEvent(AgentEvent& event) const
{
Mutex::ScopedLock _lock(lock);
if (eventQueue.empty())
@@ -305,14 +308,14 @@ bool AgentEngineImpl::getEvent(AgentEvent& event) const
return true;
}
-void AgentEngineImpl::popEvent()
+void AgentImpl::popEvent()
{
Mutex::ScopedLock _lock(lock);
if (!eventQueue.empty())
eventQueue.pop_front();
}
-void AgentEngineImpl::newSession()
+void AgentImpl::newSession()
{
Mutex::ScopedLock _lock(lock);
eventQueue.clear();
@@ -322,7 +325,7 @@ void AgentEngineImpl::newSession()
eventQueue.push_back(eventSetupComplete());
}
-void AgentEngineImpl::startProtocol()
+void AgentImpl::startProtocol()
{
Mutex::ScopedLock _lock(lock);
char rawbuffer[512];
@@ -338,7 +341,7 @@ void AgentEngineImpl::startProtocol()
" reqAgent=" << requestedAgentBank);
}
-void AgentEngineImpl::heartbeat()
+void AgentImpl::heartbeat()
{
Mutex::ScopedLock _lock(lock);
Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
@@ -351,7 +354,7 @@ void AgentEngineImpl::heartbeat()
QPID_LOG(trace, "SENT HeartbeatIndication");
}
-void AgentEngineImpl::methodResponse(uint32_t sequence, uint32_t status, char* text,
+void AgentImpl::methodResponse(uint32_t sequence, uint32_t status, char* text,
const Value& argMap)
{
Mutex::ScopedLock _lock(lock);
@@ -366,15 +369,15 @@ void AgentEngineImpl::methodResponse(uint32_t sequence, uint32_t status, char* t
buffer.putLong(status);
buffer.putMediumString(text);
if (status == 0) {
- for (vector<SchemaArgumentImpl*>::const_iterator aIter = context->schemaMethod->arguments.begin();
- aIter != context->schemaMethod->arguments.end(); aIter++) {
- const SchemaArgumentImpl* schemaArg = *aIter;
- if (schemaArg->dir == DIR_OUT || schemaArg->dir == DIR_IN_OUT) {
- if (argMap.keyInMap(schemaArg->name.c_str())) {
- const Value* val = argMap.byKey(schemaArg->name.c_str());
+ for (vector<const SchemaArgument*>::const_iterator aIter = context->schemaMethod->impl->arguments.begin();
+ aIter != context->schemaMethod->impl->arguments.end(); aIter++) {
+ const SchemaArgument* schemaArg = *aIter;
+ if (schemaArg->getDirection() == DIR_OUT || schemaArg->getDirection() == DIR_IN_OUT) {
+ if (argMap.keyInMap(schemaArg->getName())) {
+ const Value* val = argMap.byKey(schemaArg->getName());
val->impl->encode(buffer);
} else {
- Value val(schemaArg->typecode);
+ Value val(schemaArg->getType());
val.impl->encode(buffer);
}
}
@@ -384,7 +387,7 @@ void AgentEngineImpl::methodResponse(uint32_t sequence, uint32_t status, char* t
QPID_LOG(trace, "SENT MethodResponse seq=" << context->sequence << " status=" << status << " text=" << text);
}
-void AgentEngineImpl::queryResponse(uint32_t sequence, Object& object, bool prop, bool stat)
+void AgentImpl::queryResponse(uint32_t sequence, Object& object, bool prop, bool stat)
{
Mutex::ScopedLock _lock(lock);
map<uint32_t, AgentQueryContext::Ptr>::iterator iter = contextMap.find(sequence);
@@ -406,7 +409,7 @@ void AgentEngineImpl::queryResponse(uint32_t sequence, Object& object, bool prop
QPID_LOG(trace, "SENT ContentIndication seq=" << context->sequence);
}
-void AgentEngineImpl::queryComplete(uint32_t sequence)
+void AgentImpl::queryComplete(uint32_t sequence)
{
Mutex::ScopedLock _lock(lock);
map<uint32_t, AgentQueryContext::Ptr>::iterator iter = contextMap.find(sequence);
@@ -418,69 +421,67 @@ void AgentEngineImpl::queryComplete(uint32_t sequence)
sendCommandCompleteLH(context->exchange, context->key, context->sequence, 0, "OK");
}
-void AgentEngineImpl::registerClass(SchemaObjectClass* cls)
+void AgentImpl::registerClass(SchemaObjectClass* cls)
{
Mutex::ScopedLock _lock(lock);
- SchemaObjectClassImpl* impl = cls->impl;
- map<string, ClassMaps>::iterator iter = packages.find(impl->package);
+ map<string, ClassMaps>::iterator iter = packages.find(cls->getClassKey()->getPackageName());
if (iter == packages.end()) {
- packages[impl->package] = ClassMaps();
- iter = packages.find(impl->getClassKey()->getPackageName());
+ packages[cls->getClassKey()->getPackageName()] = ClassMaps();
+ iter = packages.find(cls->getClassKey()->getPackageName());
// TODO: Indicate this package if connected
}
- AgentClassKey key(impl->getClassKey()->getClassName(), impl->getClassKey()->getHash());
- iter->second.objectClasses[key] = impl;
+ AgentClassKey key(cls->getClassKey()->getClassName(), cls->getClassKey()->getHash());
+ iter->second.objectClasses[key] = cls;
// TODO: Indicate this schema if connected.
}
-void AgentEngineImpl::registerClass(SchemaEventClass* cls)
+void AgentImpl::registerClass(SchemaEventClass* cls)
{
Mutex::ScopedLock _lock(lock);
- SchemaEventClassImpl* impl = cls->impl;
- map<string, ClassMaps>::iterator iter = packages.find(impl->package);
+ map<string, ClassMaps>::iterator iter = packages.find(cls->getClassKey()->getPackageName());
if (iter == packages.end()) {
- packages[impl->package] = ClassMaps();
- iter = packages.find(impl->getClassKey()->getPackageName());
+ packages[cls->getClassKey()->getPackageName()] = ClassMaps();
+ iter = packages.find(cls->getClassKey()->getPackageName());
// TODO: Indicate this package if connected
}
- AgentClassKey key(impl->getClassKey()->getClassName(), impl->getClassKey()->getHash());
- iter->second.eventClasses[key] = impl;
+ AgentClassKey key(cls->getClassKey()->getClassName(), cls->getClassKey()->getHash());
+ iter->second.eventClasses[key] = cls;
// TODO: Indicate this schema if connected.
}
-const ObjectId* AgentEngineImpl::addObject(Object&, uint64_t)
+const ObjectId* AgentImpl::addObject(Object&, uint64_t)
{
Mutex::ScopedLock _lock(lock);
return 0;
}
-const ObjectId* AgentEngineImpl::allocObjectId(uint64_t persistId)
+const ObjectId* AgentImpl::allocObjectId(uint64_t persistId)
{
Mutex::ScopedLock _lock(lock);
uint16_t sequence = persistId ? 0 : bootSequence;
uint64_t objectNum = persistId ? persistId : nextObjectId++;
- ObjectIdImpl* oid = new ObjectIdImpl(&attachment, 0, sequence, objectNum);
- return oid->envelope;
+ ObjectId* oid = ObjectIdImpl::factory(&attachment, 0, sequence, objectNum);
+ return oid;
}
-const ObjectId* AgentEngineImpl::allocObjectId(uint32_t persistIdLo, uint32_t persistIdHi)
+const ObjectId* AgentImpl::allocObjectId(uint32_t persistIdLo, uint32_t persistIdHi)
{
return allocObjectId(((uint64_t) persistIdHi) << 32 | (uint64_t) persistIdLo);
}
-void AgentEngineImpl::raiseEvent(Event&)
+void AgentImpl::raiseEvent(Event&)
{
Mutex::ScopedLock _lock(lock);
}
-AgentEventImpl::Ptr AgentEngineImpl::eventDeclareQueue(const string& name)
+AgentEventImpl::Ptr AgentImpl::eventDeclareQueue(const string& name)
{
AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::DECLARE_QUEUE));
event->name = name;
@@ -488,7 +489,7 @@ AgentEventImpl::Ptr AgentEngineImpl::eventDeclareQueue(const string& name)
return event;
}
-AgentEventImpl::Ptr AgentEngineImpl::eventBind(const string& exchange, const string& queue,
+AgentEventImpl::Ptr AgentImpl::eventBind(const string& exchange, const string& queue,
const string& key)
{
AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::BIND));
@@ -499,13 +500,13 @@ AgentEventImpl::Ptr AgentEngineImpl::eventBind(const string& exchange, const str
return event;
}
-AgentEventImpl::Ptr AgentEngineImpl::eventSetupComplete()
+AgentEventImpl::Ptr AgentImpl::eventSetupComplete()
{
AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::SETUP_COMPLETE));
return event;
}
-AgentEventImpl::Ptr AgentEngineImpl::eventQuery(uint32_t num, const string& userId, const string& package,
+AgentEventImpl::Ptr AgentImpl::eventQuery(uint32_t num, const string& userId, const string& package,
const string& cls, boost::shared_ptr<ObjectId> oid)
{
AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::GET_QUERY));
@@ -518,9 +519,9 @@ AgentEventImpl::Ptr AgentEngineImpl::eventQuery(uint32_t num, const string& user
return event;
}
-AgentEventImpl::Ptr AgentEngineImpl::eventMethod(uint32_t num, const string& userId, const string& method,
+AgentEventImpl::Ptr AgentImpl::eventMethod(uint32_t num, const string& userId, const string& method,
boost::shared_ptr<ObjectId> oid, boost::shared_ptr<Value> argMap,
- SchemaObjectClass* objectClass)
+ const SchemaObjectClass* objectClass)
{
AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::METHOD_CALL));
event->sequence = num;
@@ -532,7 +533,7 @@ AgentEventImpl::Ptr AgentEngineImpl::eventMethod(uint32_t num, const string& use
return event;
}
-void AgentEngineImpl::sendBufferLH(Buffer& buf, const string& destination, const string& routingKey)
+void AgentImpl::sendBufferLH(Buffer& buf, const string& destination, const string& routingKey)
{
uint32_t length = buf.getPosition();
MessageImpl::Ptr message(new MessageImpl);
@@ -547,7 +548,7 @@ void AgentEngineImpl::sendBufferLH(Buffer& buf, const string& destination, const
xmtQueue.push_back(message);
}
-void AgentEngineImpl::sendPackageIndicationLH(const string& packageName)
+void AgentImpl::sendPackageIndicationLH(const string& packageName)
{
Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
Protocol::encodeHeader(buffer, Protocol::OP_PACKAGE_INDICATION);
@@ -556,7 +557,7 @@ void AgentEngineImpl::sendPackageIndicationLH(const string& packageName)
QPID_LOG(trace, "SENT PackageIndication: package_name=" << packageName);
}
-void AgentEngineImpl::sendClassIndicationLH(ClassKind kind, const string& packageName, const AgentClassKey& key)
+void AgentImpl::sendClassIndicationLH(ClassKind kind, const string& packageName, const AgentClassKey& key)
{
Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
Protocol::encodeHeader(buffer, Protocol::OP_CLASS_INDICATION);
@@ -568,7 +569,7 @@ void AgentEngineImpl::sendClassIndicationLH(ClassKind kind, const string& packag
QPID_LOG(trace, "SENT ClassIndication: package_name=" << packageName << " class_name=" << key.name);
}
-void AgentEngineImpl::sendCommandCompleteLH(const string& exchange, const string& replyToKey,
+void AgentImpl::sendCommandCompleteLH(const string& exchange, const string& replyToKey,
uint32_t sequence, uint32_t code, const string& text)
{
Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
@@ -579,7 +580,7 @@ void AgentEngineImpl::sendCommandCompleteLH(const string& exchange, const string
QPID_LOG(trace, "SENT CommandComplete: seq=" << sequence << " code=" << code << " text=" << text);
}
-void AgentEngineImpl::sendMethodErrorLH(uint32_t sequence, const string& key, uint32_t code, const string& text)
+void AgentImpl::sendMethodErrorLH(uint32_t sequence, const string& key, uint32_t code, const string& text)
{
Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
Protocol::encodeHeader(buffer, Protocol::OP_METHOD_RESPONSE, sequence);
@@ -605,7 +606,7 @@ void AgentEngineImpl::sendMethodErrorLH(uint32_t sequence, const string& key, ui
QPID_LOG(trace, "SENT MethodResponse: errorCode=" << code << " text=" << fulltext);
}
-void AgentEngineImpl::handleAttachResponse(Buffer& inBuffer)
+void AgentImpl::handleAttachResponse(Buffer& inBuffer)
{
Mutex::ScopedLock _lock(lock);
@@ -652,17 +653,17 @@ void AgentEngineImpl::handleAttachResponse(Buffer& inBuffer)
}
}
-void AgentEngineImpl::handlePackageRequest(Buffer&)
+void AgentImpl::handlePackageRequest(Buffer&)
{
Mutex::ScopedLock _lock(lock);
}
-void AgentEngineImpl::handleClassQuery(Buffer&)
+void AgentImpl::handleClassQuery(Buffer&)
{
Mutex::ScopedLock _lock(lock);
}
-void AgentEngineImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence,
+void AgentImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence,
const string& replyExchange, const string& replyKey)
{
Mutex::ScopedLock _lock(lock);
@@ -688,10 +689,10 @@ void AgentEngineImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence,
ClassMaps cMap = pIter->second;
ObjectClassMap::iterator ocIter = cMap.objectClasses.find(key);
if (ocIter != cMap.objectClasses.end()) {
- SchemaObjectClassImpl* oImpl = ocIter->second;
+ SchemaObjectClass* oImpl = ocIter->second;
Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
Protocol::encodeHeader(buffer, Protocol::OP_SCHEMA_RESPONSE, sequence);
- oImpl->encode(buffer);
+ oImpl->impl->encode(buffer);
sendBufferLH(buffer, rExchange, rKey);
QPID_LOG(trace, "SENT SchemaResponse: (object) package=" << packageName << " class=" << key.name);
return;
@@ -699,10 +700,10 @@ void AgentEngineImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence,
EventClassMap::iterator ecIter = cMap.eventClasses.find(key);
if (ecIter != cMap.eventClasses.end()) {
- SchemaEventClassImpl* eImpl = ecIter->second;
+ SchemaEventClass* eImpl = ecIter->second;
Buffer buffer(outputBuffer, MA_BUFFER_SIZE);
Protocol::encodeHeader(buffer, Protocol::OP_SCHEMA_RESPONSE, sequence);
- eImpl->encode(buffer);
+ eImpl->impl->encode(buffer);
sendBufferLH(buffer, rExchange, rKey);
QPID_LOG(trace, "SENT SchemaResponse: (event) package=" << packageName << " class=" << key.name);
return;
@@ -711,7 +712,7 @@ void AgentEngineImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence,
sendCommandCompleteLH(rExchange, rKey, sequence, 1, "class not found");
}
-void AgentEngineImpl::handleGetQuery(Buffer& inBuffer, uint32_t sequence, const string& replyTo, const string& userId)
+void AgentImpl::handleGetQuery(Buffer& inBuffer, uint32_t sequence, const string& replyTo, const string& userId)
{
Mutex::ScopedLock _lock(lock);
FieldTable ft;
@@ -763,13 +764,12 @@ void AgentEngineImpl::handleGetQuery(Buffer& inBuffer, uint32_t sequence, const
eventQueue.push_back(eventQuery(contextNum, userId, pname, cname, oid));
}
-void AgentEngineImpl::handleMethodRequest(Buffer& buffer, uint32_t sequence, const string& replyTo, const string& userId)
+void AgentImpl::handleMethodRequest(Buffer& buffer, uint32_t sequence, const string& replyTo, const string& userId)
{
Mutex::ScopedLock _lock(lock);
string pname;
string method;
- ObjectIdImpl* oidImpl = new ObjectIdImpl(buffer);
- boost::shared_ptr<ObjectId> oid(oidImpl->envelope);
+ boost::shared_ptr<ObjectId> oid(ObjectIdImpl::factory(buffer));
buffer.getShortString(pname);
AgentClassKey classKey(buffer);
buffer.getShortString(method);
@@ -788,29 +788,29 @@ void AgentEngineImpl::handleMethodRequest(Buffer& buffer, uint32_t sequence, con
return;
}
- const SchemaObjectClassImpl* schema = cIter->second;
- vector<SchemaMethodImpl*>::const_iterator mIter = schema->methods.begin();
- for (; mIter != schema->methods.end(); mIter++) {
- if ((*mIter)->name == method)
+ const SchemaObjectClass* schema = cIter->second;
+ vector<const SchemaMethod*>::const_iterator mIter = schema->impl->methods.begin();
+ for (; mIter != schema->impl->methods.end(); mIter++) {
+ if ((*mIter)->getName() == method)
break;
}
- if (mIter == schema->methods.end()) {
+ if (mIter == schema->impl->methods.end()) {
sendMethodErrorLH(sequence, replyTo, MERR_UNKNOWN_METHOD, method);
return;
}
- SchemaMethodImpl* schemaMethod = *mIter;
+ const SchemaMethod* schemaMethod = *mIter;
boost::shared_ptr<Value> argMap(new Value(TYPE_MAP));
- ValueImpl* value;
- for (vector<SchemaArgumentImpl*>::const_iterator aIter = schemaMethod->arguments.begin();
- aIter != schemaMethod->arguments.end(); aIter++) {
- const SchemaArgumentImpl* schemaArg = *aIter;
- if (schemaArg->dir == DIR_IN || schemaArg->dir == DIR_IN_OUT)
- value = new ValueImpl(schemaArg->typecode, buffer);
+ Value* value;
+ for (vector<const SchemaArgument*>::const_iterator aIter = schemaMethod->impl->arguments.begin();
+ aIter != schemaMethod->impl->arguments.end(); aIter++) {
+ const SchemaArgument* schemaArg = *aIter;
+ if (schemaArg->getDirection() == DIR_IN || schemaArg->getDirection() == DIR_IN_OUT)
+ value = ValueImpl::factory(schemaArg->getType(), buffer);
else
- value = new ValueImpl(schemaArg->typecode);
- argMap->insert(schemaArg->name.c_str(), value->envelope);
+ value = ValueImpl::factory(schemaArg->getType());
+ argMap->insert(schemaArg->getName(), value);
}
AgentQueryContext::Ptr context(new AgentQueryContext);
@@ -821,10 +821,10 @@ void AgentEngineImpl::handleMethodRequest(Buffer& buffer, uint32_t sequence, con
context->schemaMethod = schemaMethod;
contextMap[contextNum] = context;
- eventQueue.push_back(eventMethod(contextNum, userId, method, oid, argMap, schema->envelope));
+ eventQueue.push_back(eventMethod(contextNum, userId, method, oid, argMap, schema));
}
-void AgentEngineImpl::handleConsoleAddedIndication()
+void AgentImpl::handleConsoleAddedIndication()
{
Mutex::ScopedLock _lock(lock);
}
@@ -833,25 +833,25 @@ void AgentEngineImpl::handleConsoleAddedIndication()
// Wrappers
//==================================================================
-AgentEngine::AgentEngine(char* label, bool internalStore) { impl = new AgentEngineImpl(label, internalStore); }
-AgentEngine::~AgentEngine() { delete impl; }
-void AgentEngine::setStoreDir(const char* path) { impl->setStoreDir(path); }
-void AgentEngine::setTransferDir(const char* path) { impl->setTransferDir(path); }
-void AgentEngine::handleRcvMessage(Message& message) { impl->handleRcvMessage(message); }
-bool AgentEngine::getXmtMessage(Message& item) const { return impl->getXmtMessage(item); }
-void AgentEngine::popXmt() { impl->popXmt(); }
-bool AgentEngine::getEvent(AgentEvent& event) const { return impl->getEvent(event); }
-void AgentEngine::popEvent() { impl->popEvent(); }
-void AgentEngine::newSession() { impl->newSession(); }
-void AgentEngine::startProtocol() { impl->startProtocol(); }
-void AgentEngine::heartbeat() { impl->heartbeat(); }
-void AgentEngine::methodResponse(uint32_t sequence, uint32_t status, char* text, const Value& arguments) { impl->methodResponse(sequence, status, text, arguments); }
-void AgentEngine::queryResponse(uint32_t sequence, Object& object, bool prop, bool stat) { impl->queryResponse(sequence, object, prop, stat); }
-void AgentEngine::queryComplete(uint32_t sequence) { impl->queryComplete(sequence); }
-void AgentEngine::registerClass(SchemaObjectClass* cls) { impl->registerClass(cls); }
-void AgentEngine::registerClass(SchemaEventClass* cls) { impl->registerClass(cls); }
-const ObjectId* AgentEngine::addObject(Object& obj, uint64_t persistId) { return impl->addObject(obj, persistId); }
-const ObjectId* AgentEngine::allocObjectId(uint64_t persistId) { return impl->allocObjectId(persistId); }
-const ObjectId* AgentEngine::allocObjectId(uint32_t persistIdLo, uint32_t persistIdHi) { return impl->allocObjectId(persistIdLo, persistIdHi); }
-void AgentEngine::raiseEvent(Event& event) { impl->raiseEvent(event); }
+Agent::Agent(char* label, bool internalStore) { impl = new AgentImpl(label, internalStore); }
+Agent::~Agent() { delete impl; }
+void Agent::setStoreDir(const char* path) { impl->setStoreDir(path); }
+void Agent::setTransferDir(const char* path) { impl->setTransferDir(path); }
+void Agent::handleRcvMessage(Message& message) { impl->handleRcvMessage(message); }
+bool Agent::getXmtMessage(Message& item) const { return impl->getXmtMessage(item); }
+void Agent::popXmt() { impl->popXmt(); }
+bool Agent::getEvent(AgentEvent& event) const { return impl->getEvent(event); }
+void Agent::popEvent() { impl->popEvent(); }
+void Agent::newSession() { impl->newSession(); }
+void Agent::startProtocol() { impl->startProtocol(); }
+void Agent::heartbeat() { impl->heartbeat(); }
+void Agent::methodResponse(uint32_t sequence, uint32_t status, char* text, const Value& arguments) { impl->methodResponse(sequence, status, text, arguments); }
+void Agent::queryResponse(uint32_t sequence, Object& object, bool prop, bool stat) { impl->queryResponse(sequence, object, prop, stat); }
+void Agent::queryComplete(uint32_t sequence) { impl->queryComplete(sequence); }
+void Agent::registerClass(SchemaObjectClass* cls) { impl->registerClass(cls); }
+void Agent::registerClass(SchemaEventClass* cls) { impl->registerClass(cls); }
+const ObjectId* Agent::addObject(Object& obj, uint64_t persistId) { return impl->addObject(obj, persistId); }
+const ObjectId* Agent::allocObjectId(uint64_t persistId) { return impl->allocObjectId(persistId); }
+const ObjectId* Agent::allocObjectId(uint32_t persistIdLo, uint32_t persistIdHi) { return impl->allocObjectId(persistIdLo, persistIdHi); }
+void Agent::raiseEvent(Event& event) { impl->raiseEvent(event); }
diff --git a/qpid/cpp/src/qmf/engine/BrokerProxyImpl.cpp b/qpid/cpp/src/qmf/engine/BrokerProxyImpl.cpp
new file mode 100644
index 0000000000..1a2b3e6555
--- /dev/null
+++ b/qpid/cpp/src/qmf/engine/BrokerProxyImpl.cpp
@@ -0,0 +1,763 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "qmf/engine/BrokerProxyImpl.h"
+#include "qmf/engine/ConsoleImpl.h"
+#include "qmf/engine/Protocol.h"
+#include "qpid/Address.h"
+#include "qpid/sys/SystemInfo.h"
+#include <qpid/log/Statement.h>
+#include <qpid/StringUtils.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+using namespace qmf::engine;
+using namespace qpid::framing;
+using namespace qpid::sys;
+
+namespace {
+ const char* QMF_EXCHANGE = "qpid.management";
+ const char* DIR_EXCHANGE = "amq.direct";
+ const char* BROKER_KEY = "broker";
+ const char* BROKER_PACKAGE = "org.apache.qpid.broker";
+ const char* AGENT_CLASS = "agent";
+ const char* BROKER_AGENT_KEY = "agent.1.0";
+}
+
+const Object* QueryResponseImpl::getObject(uint32_t idx) const
+{
+ vector<ObjectPtr>::const_iterator iter = results.begin();
+
+ while (idx > 0) {
+ if (iter == results.end())
+ return 0;
+ iter++;
+ idx--;
+ }
+
+ return iter->get();
+}
+
+#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());}
+
+BrokerEvent BrokerEventImpl::copy()
+{
+ BrokerEvent item;
+
+ ::memset(&item, 0, sizeof(BrokerEvent));
+ item.kind = kind;
+
+ STRING_REF(name);
+ STRING_REF(exchange);
+ STRING_REF(bindingKey);
+ item.context = context;
+ item.queryResponse = queryResponse.get();
+ item.methodResponse = methodResponse.get();
+
+ return item;
+}
+
+BrokerProxyImpl::BrokerProxyImpl(BrokerProxy& pub, Console& _console) : publicObject(pub), console(_console)
+{
+ stringstream qn;
+ qpid::TcpAddress addr;
+
+ SystemInfo::getLocalHostname(addr);
+ qn << "qmfc-" << SystemInfo::getProcessName() << "-" << addr << "-" << SystemInfo::getProcessId();
+ queueName = qn.str();
+
+ seqMgr.setUnsolicitedContext(SequenceContext::Ptr(new StaticContext(*this)));
+}
+
+void BrokerProxyImpl::sessionOpened(SessionHandle& /*sh*/)
+{
+ Mutex::ScopedLock _lock(lock);
+ agentList.clear();
+ eventQueue.clear();
+ xmtQueue.clear();
+ eventQueue.push_back(eventDeclareQueue(queueName));
+ eventQueue.push_back(eventBind(DIR_EXCHANGE, queueName, queueName));
+ eventQueue.push_back(eventSetupComplete());
+
+ // TODO: Store session handle
+}
+
+void BrokerProxyImpl::sessionClosed()
+{
+ Mutex::ScopedLock _lock(lock);
+ agentList.clear();
+ eventQueue.clear();
+ xmtQueue.clear();
+}
+
+void BrokerProxyImpl::startProtocol()
+{
+ AgentProxyPtr agent(AgentProxyImpl::factory(console, publicObject, 0, "Agent embedded in broker"));
+ {
+ Mutex::ScopedLock _lock(lock);
+ char rawbuffer[512];
+ Buffer buffer(rawbuffer, 512);
+
+ agentList[0] = agent;
+
+ requestsOutstanding = 1;
+ topicBound = false;
+ uint32_t sequence(seqMgr.reserve());
+ Protocol::encodeHeader(buffer, Protocol::OP_BROKER_REQUEST, sequence);
+ sendBufferLH(buffer, QMF_EXCHANGE, BROKER_KEY);
+ QPID_LOG(trace, "SENT BrokerRequest seq=" << sequence);
+ }
+
+ console.impl->eventAgentAdded(agent);
+}
+
+void BrokerProxyImpl::sendBufferLH(Buffer& buf, const string& destination, const string& routingKey)
+{
+ uint32_t length = buf.getPosition();
+ MessageImpl::Ptr message(new MessageImpl);
+
+ buf.reset();
+ buf.getRawData(message->body, length);
+ message->destination = destination;
+ message->routingKey = routingKey;
+ message->replyExchange = DIR_EXCHANGE;
+ message->replyKey = queueName;
+
+ xmtQueue.push_back(message);
+}
+
+void BrokerProxyImpl::handleRcvMessage(Message& message)
+{
+ Buffer inBuffer(message.body, message.length);
+ uint8_t opcode;
+ uint32_t sequence;
+
+ while (Protocol::checkHeader(inBuffer, &opcode, &sequence))
+ seqMgr.dispatch(opcode, sequence, message.routingKey ? string(message.routingKey) : string(), inBuffer);
+}
+
+bool BrokerProxyImpl::getXmtMessage(Message& item) const
+{
+ Mutex::ScopedLock _lock(lock);
+ if (xmtQueue.empty())
+ return false;
+ item = xmtQueue.front()->copy();
+ return true;
+}
+
+void BrokerProxyImpl::popXmt()
+{
+ Mutex::ScopedLock _lock(lock);
+ if (!xmtQueue.empty())
+ xmtQueue.pop_front();
+}
+
+bool BrokerProxyImpl::getEvent(BrokerEvent& event) const
+{
+ Mutex::ScopedLock _lock(lock);
+ if (eventQueue.empty())
+ return false;
+ event = eventQueue.front()->copy();
+ return true;
+}
+
+void BrokerProxyImpl::popEvent()
+{
+ Mutex::ScopedLock _lock(lock);
+ if (!eventQueue.empty())
+ eventQueue.pop_front();
+}
+
+uint32_t BrokerProxyImpl::agentCount() const
+{
+ Mutex::ScopedLock _lock(lock);
+ return agentList.size();
+}
+
+const AgentProxy* BrokerProxyImpl::getAgent(uint32_t idx) const
+{
+ Mutex::ScopedLock _lock(lock);
+ for (map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.begin();
+ iter != agentList.end(); iter++)
+ if (idx-- == 0)
+ return iter->second.get();
+ return 0;
+}
+
+void BrokerProxyImpl::sendQuery(const Query& query, void* context, const AgentProxy* agent)
+{
+ SequenceContext::Ptr queryContext(new QueryContext(*this, context));
+ Mutex::ScopedLock _lock(lock);
+ if (agent != 0) {
+ sendGetRequestLH(queryContext, query, agent);
+ } else {
+ // TODO (optimization) only send queries to agents that have the requested class+package
+ for (map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.begin();
+ iter != agentList.end(); iter++) {
+ sendGetRequestLH(queryContext, query, iter->second.get());
+ }
+ }
+}
+
+void BrokerProxyImpl::sendGetRequestLH(SequenceContext::Ptr queryContext, const Query& query, const AgentProxy* agent)
+{
+ stringstream key;
+ Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
+ uint32_t sequence(seqMgr.reserve(queryContext));
+ agent->impl->addSequence(sequence);
+
+ Protocol::encodeHeader(outBuffer, Protocol::OP_GET_QUERY, sequence);
+ query.impl->encode(outBuffer);
+ key << "agent.1." << agent->impl->agentBank;
+ sendBufferLH(outBuffer, QMF_EXCHANGE, key.str());
+ QPID_LOG(trace, "SENT GetQuery seq=" << sequence << " key=" << key.str());
+}
+
+string BrokerProxyImpl::encodeMethodArguments(const SchemaMethod* schema, const Value* argmap, Buffer& buffer)
+{
+ int argCount = schema->getArgumentCount();
+
+ if (argmap == 0 || !argmap->isMap())
+ return string("Arguments must be in a map value");
+
+ for (int aIdx = 0; aIdx < argCount; aIdx++) {
+ const SchemaArgument* arg(schema->getArgument(aIdx));
+ if (arg->getDirection() == DIR_IN || arg->getDirection() == DIR_IN_OUT) {
+ if (argmap->keyInMap(arg->getName())) {
+ const Value* argVal(argmap->byKey(arg->getName()));
+ if (argVal->getType() != arg->getType())
+ return string("Argument is the wrong type: ") + arg->getName();
+ argVal->impl->encode(buffer);
+ } else {
+ Value defaultValue(arg->getType());
+ defaultValue.impl->encode(buffer);
+ }
+ }
+ }
+
+ return string();
+}
+
+void BrokerProxyImpl::sendMethodRequest(ObjectId* oid, const SchemaObjectClass* cls,
+ const string& methodName, const Value* args, void* userContext)
+{
+ int methodCount = cls->getMethodCount();
+ int idx;
+ for (idx = 0; idx < methodCount; idx++) {
+ const SchemaMethod* method = cls->getMethod(idx);
+ if (string(method->getName()) == methodName) {
+ Mutex::ScopedLock _lock(lock);
+ SequenceContext::Ptr methodContext(new MethodContext(*this, userContext, method));
+ stringstream key;
+ Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
+ uint32_t sequence(seqMgr.reserve(methodContext));
+
+ Protocol::encodeHeader(outBuffer, Protocol::OP_METHOD_REQUEST, sequence);
+ oid->impl->encode(outBuffer);
+ cls->getClassKey()->impl->encode(outBuffer);
+ outBuffer.putShortString(methodName);
+
+ string argErrorString = encodeMethodArguments(method, args, outBuffer);
+ if (argErrorString.empty()) {
+ key << "agent.1." << oid->impl->getAgentBank();
+ sendBufferLH(outBuffer, QMF_EXCHANGE, key.str());
+ QPID_LOG(trace, "SENT MethodRequest seq=" << sequence << " method=" << methodName << " key=" << key.str());
+ } else {
+ MethodResponsePtr argError(MethodResponseImpl::factory(1, argErrorString));
+ eventQueue.push_back(eventMethodResponse(userContext, argError));
+ }
+ return;
+ }
+ }
+
+ MethodResponsePtr error(MethodResponseImpl::factory(1, string("Unknown method: ") + methodName));
+ Mutex::ScopedLock _lock(lock);
+ eventQueue.push_back(eventMethodResponse(userContext, error));
+}
+
+void BrokerProxyImpl::addBinding(const string& exchange, const string& key)
+{
+ Mutex::ScopedLock _lock(lock);
+ eventQueue.push_back(eventBind(exchange, queueName, key));
+}
+
+BrokerEventImpl::Ptr BrokerProxyImpl::eventDeclareQueue(const string& queueName)
+{
+ BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::DECLARE_QUEUE));
+ event->name = queueName;
+ return event;
+}
+
+BrokerEventImpl::Ptr BrokerProxyImpl::eventBind(const string& exchange, const string& queue, const string& key)
+{
+ BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::BIND));
+ event->name = queue;
+ event->exchange = exchange;
+ event->bindingKey = key;
+
+ return event;
+}
+
+BrokerEventImpl::Ptr BrokerProxyImpl::eventSetupComplete()
+{
+ BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::SETUP_COMPLETE));
+ return event;
+}
+
+BrokerEventImpl::Ptr BrokerProxyImpl::eventStable()
+{
+ QPID_LOG(trace, "Console Link to Broker Stable");
+ BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::STABLE));
+ return event;
+}
+
+BrokerEventImpl::Ptr BrokerProxyImpl::eventQueryComplete(void* context, QueryResponsePtr response)
+{
+ BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::QUERY_COMPLETE));
+ event->context = context;
+ event->queryResponse = response;
+ return event;
+}
+
+BrokerEventImpl::Ptr BrokerProxyImpl::eventMethodResponse(void* context, MethodResponsePtr response)
+{
+ BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::METHOD_RESPONSE));
+ event->context = context;
+ event->methodResponse = response;
+ return event;
+}
+
+void BrokerProxyImpl::handleBrokerResponse(Buffer& inBuffer, uint32_t seq)
+{
+ brokerId.decode(inBuffer);
+ QPID_LOG(trace, "RCVD BrokerResponse seq=" << seq << " brokerId=" << brokerId);
+ Mutex::ScopedLock _lock(lock);
+ Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
+ uint32_t sequence(seqMgr.reserve());
+ incOutstandingLH();
+ Protocol::encodeHeader(outBuffer, Protocol::OP_PACKAGE_REQUEST, sequence);
+ sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY);
+ QPID_LOG(trace, "SENT PackageRequest seq=" << sequence);
+}
+
+void BrokerProxyImpl::handlePackageIndication(Buffer& inBuffer, uint32_t seq)
+{
+ string package;
+
+ inBuffer.getShortString(package);
+ QPID_LOG(trace, "RCVD PackageIndication seq=" << seq << " package=" << package);
+ console.impl->learnPackage(package);
+
+ Mutex::ScopedLock _lock(lock);
+ Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
+ uint32_t sequence(seqMgr.reserve());
+ incOutstandingLH();
+ Protocol::encodeHeader(outBuffer, Protocol::OP_CLASS_QUERY, sequence);
+ outBuffer.putShortString(package);
+ sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY);
+ QPID_LOG(trace, "SENT ClassQuery seq=" << sequence << " package=" << package);
+}
+
+void BrokerProxyImpl::handleCommandComplete(Buffer& inBuffer, uint32_t seq)
+{
+ string text;
+ uint32_t code = inBuffer.getLong();
+ inBuffer.getShortString(text);
+ QPID_LOG(trace, "RCVD CommandComplete seq=" << seq << " code=" << code << " text=" << text);
+}
+
+void BrokerProxyImpl::handleClassIndication(Buffer& inBuffer, uint32_t seq)
+{
+ uint8_t kind = inBuffer.getOctet();
+ auto_ptr<SchemaClassKey> classKey(SchemaClassKeyImpl::factory(inBuffer));
+
+ QPID_LOG(trace, "RCVD ClassIndication seq=" << seq << " kind=" << (int) kind << " key=" << classKey->impl->str());
+
+ if (!console.impl->haveClass(classKey.get())) {
+ Mutex::ScopedLock _lock(lock);
+ incOutstandingLH();
+ Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
+ uint32_t sequence(seqMgr.reserve());
+ Protocol::encodeHeader(outBuffer, Protocol::OP_SCHEMA_REQUEST, sequence);
+ classKey->impl->encode(outBuffer);
+ sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY);
+ QPID_LOG(trace, "SENT SchemaRequest seq=" << sequence <<" key=" << classKey->impl->str());
+ }
+}
+
+MethodResponsePtr BrokerProxyImpl::handleMethodResponse(Buffer& inBuffer, uint32_t seq, const SchemaMethod* schema)
+{
+ MethodResponsePtr response(MethodResponseImpl::factory(inBuffer, schema));
+
+ QPID_LOG(trace, "RCVD MethodResponse seq=" << seq << " status=" << response->getStatus() << " text=" <<
+ response->getException()->asString());
+
+ return response;
+}
+
+void BrokerProxyImpl::handleHeartbeatIndication(Buffer& inBuffer, uint32_t seq, const string& routingKey)
+{
+ vector<string> tokens = qpid::split(routingKey, ".");
+ uint32_t agentBank;
+ uint64_t timestamp;
+
+ if (routingKey.empty() || tokens.size() != 4)
+ agentBank = 0;
+ else
+ agentBank = ::atoi(tokens[3].c_str());
+
+ timestamp = inBuffer.getLongLong();
+ map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.find(agentBank);
+ if (iter != agentList.end()) {
+ console.impl->eventAgentHeartbeat(iter->second, timestamp);
+ }
+ QPID_LOG(trace, "RCVD HeartbeatIndication seq=" << seq << " agentBank=" << agentBank);
+}
+
+void BrokerProxyImpl::handleEventIndication(Buffer& /*inBuffer*/, uint32_t /*seq*/)
+{
+ // TODO
+}
+
+void BrokerProxyImpl::handleSchemaResponse(Buffer& inBuffer, uint32_t seq)
+{
+ SchemaObjectClass* oClassPtr;
+ SchemaEventClass* eClassPtr;
+ uint8_t kind = inBuffer.getOctet();
+ const SchemaClassKey* key;
+ if (kind == CLASS_OBJECT) {
+ oClassPtr = SchemaObjectClassImpl::factory(inBuffer);
+ console.impl->learnClass(oClassPtr);
+ key = oClassPtr->getClassKey();
+ QPID_LOG(trace, "RCVD SchemaResponse seq=" << seq << " kind=object key=" << key->impl->str());
+
+ //
+ // If we have just learned about the org.apache.qpid.broker:agent class, send a get
+ // request for the current list of agents so we can have it on-hand before we declare
+ // this session "stable".
+ //
+ if (key->impl->getClassName() == AGENT_CLASS && key->impl->getPackageName() == BROKER_PACKAGE) {
+ Mutex::ScopedLock _lock(lock);
+ incOutstandingLH();
+ Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
+ uint32_t sequence(seqMgr.reserve());
+ Protocol::encodeHeader(outBuffer, Protocol::OP_GET_QUERY, sequence);
+ FieldTable ft;
+ ft.setString("_class", AGENT_CLASS);
+ ft.setString("_package", BROKER_PACKAGE);
+ ft.encode(outBuffer);
+ sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_AGENT_KEY);
+ QPID_LOG(trace, "SENT GetQuery seq=" << sequence << " key=" << BROKER_AGENT_KEY);
+ }
+ } else if (kind == CLASS_EVENT) {
+ eClassPtr = SchemaEventClassImpl::factory(inBuffer);
+ console.impl->learnClass(eClassPtr);
+ key = eClassPtr->getClassKey();
+ QPID_LOG(trace, "RCVD SchemaResponse seq=" << seq << " kind=event key=" << key->impl->str());
+ }
+ else {
+ QPID_LOG(error, "BrokerProxyImpl::handleSchemaResponse received unknown class kind: " << (int) kind);
+ }
+}
+
+ObjectPtr BrokerProxyImpl::handleObjectIndication(Buffer& inBuffer, uint32_t seq, bool prop, bool stat)
+{
+ auto_ptr<SchemaClassKey> classKey(SchemaClassKeyImpl::factory(inBuffer));
+ QPID_LOG(trace, "RCVD ObjectIndication seq=" << seq << " key=" << classKey->impl->str());
+
+ SchemaObjectClass* schema = console.impl->getSchema(classKey.get());
+ if (schema == 0) {
+ QPID_LOG(trace, "No Schema Found for ObjectIndication. seq=" << seq << " key=" << classKey->impl->str());
+ return ObjectPtr();
+ }
+
+ ObjectPtr optr(ObjectImpl::factory(schema, this, inBuffer, prop, stat, true));
+ if (prop && classKey->impl->getPackageName() == BROKER_PACKAGE && classKey->impl->getClassName() == AGENT_CLASS) {
+ //
+ // We've intercepted information about a remote agent... update the agent list accordingly
+ //
+ updateAgentList(optr);
+ }
+ return optr;
+}
+
+void BrokerProxyImpl::updateAgentList(ObjectPtr obj)
+{
+ Value* value = obj->getValue("agentBank");
+ Mutex::ScopedLock _lock(lock);
+ if (value != 0 && value->isUint()) {
+ uint32_t agentBank = value->asUint();
+ if (obj->isDeleted()) {
+ map<uint32_t, AgentProxyPtr>::iterator iter = agentList.find(agentBank);
+ if (iter != agentList.end()) {
+ AgentProxyPtr agent(iter->second);
+ console.impl->eventAgentDeleted(agent);
+ agentList.erase(agentBank);
+ QPID_LOG(trace, "Agent at bank " << agentBank << " removed from agent list");
+
+ //
+ // Release all sequence numbers for requests in-flight to this agent.
+ // Since the agent is no longer connected, these requests would not
+ // otherwise complete.
+ //
+ agent->impl->releaseInFlight(seqMgr);
+ }
+ } else {
+ Value* str = obj->getValue("label");
+ string label;
+ if (str != 0 && str->isString())
+ label = str->asString();
+ map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.find(agentBank);
+ if (iter == agentList.end()) {
+ AgentProxyPtr agent(AgentProxyImpl::factory(console, publicObject, agentBank, label));
+ agentList[agentBank] = agent;
+ console.impl->eventAgentAdded(agent);
+ QPID_LOG(trace, "Agent '" << label << "' found at bank " << agentBank);
+ }
+ }
+ }
+}
+
+void BrokerProxyImpl::incOutstandingLH()
+{
+ requestsOutstanding++;
+}
+
+void BrokerProxyImpl::decOutstanding()
+{
+ Mutex::ScopedLock _lock(lock);
+ requestsOutstanding--;
+ if (requestsOutstanding == 0 && !topicBound) {
+ topicBound = true;
+ for (vector<pair<string, string> >::const_iterator iter = console.impl->bindingList.begin();
+ iter != console.impl->bindingList.end(); iter++) {
+ string exchange(iter->first.empty() ? QMF_EXCHANGE : iter->first);
+ string key(iter->second);
+ eventQueue.push_back(eventBind(exchange, queueName, key));
+ }
+ eventQueue.push_back(eventStable());
+ }
+}
+
+MethodResponseImpl::MethodResponseImpl(const MethodResponseImpl& from) :
+ status(from.status), schema(from.schema)
+{
+ if (from.exception.get())
+ exception.reset(new Value(*(from.exception)));
+ if (from.arguments.get())
+ arguments.reset(new Value(*(from.arguments)));
+}
+
+MethodResponseImpl::MethodResponseImpl(Buffer& buf, const SchemaMethod* s) : schema(s)
+{
+ string text;
+
+ status = buf.getLong();
+ buf.getMediumString(text);
+ exception.reset(new Value(TYPE_LSTR));
+ exception->setString(text.c_str());
+
+ if (status != 0)
+ return;
+
+ arguments.reset(new Value(TYPE_MAP));
+ int argCount(schema->getArgumentCount());
+ for (int idx = 0; idx < argCount; idx++) {
+ const SchemaArgument* arg = schema->getArgument(idx);
+ if (arg->getDirection() == DIR_OUT || arg->getDirection() == DIR_IN_OUT) {
+ Value* value(ValueImpl::factory(arg->getType(), buf));
+ arguments->insert(arg->getName(), value);
+ }
+ }
+}
+
+MethodResponseImpl::MethodResponseImpl(uint32_t s, const string& text) : schema(0)
+{
+ status = s;
+ exception.reset(new Value(TYPE_LSTR));
+ exception->setString(text.c_str());
+}
+
+MethodResponse* MethodResponseImpl::factory(Buffer& buf, const SchemaMethod* schema)
+{
+ MethodResponseImpl* impl(new MethodResponseImpl(buf, schema));
+ return new MethodResponse(impl);
+}
+
+MethodResponse* MethodResponseImpl::factory(uint32_t status, const std::string& text)
+{
+ MethodResponseImpl* impl(new MethodResponseImpl(status, text));
+ return new MethodResponse(impl);
+}
+
+bool StaticContext::handleMessage(uint8_t opcode, uint32_t sequence, const string& routingKey, Buffer& buffer)
+{
+ ObjectPtr object;
+ bool completeContext = false;
+
+ if (opcode == Protocol::OP_BROKER_RESPONSE) {
+ broker.handleBrokerResponse(buffer, sequence);
+ completeContext = true;
+ }
+ else if (opcode == Protocol::OP_COMMAND_COMPLETE) {
+ broker.handleCommandComplete(buffer, sequence);
+ completeContext = true;
+ }
+ else if (opcode == Protocol::OP_SCHEMA_RESPONSE) {
+ broker.handleSchemaResponse(buffer, sequence);
+ completeContext = true;
+ }
+ else if (opcode == Protocol::OP_PACKAGE_INDICATION)
+ broker.handlePackageIndication(buffer, sequence);
+ else if (opcode == Protocol::OP_CLASS_INDICATION)
+ broker.handleClassIndication(buffer, sequence);
+ else if (opcode == Protocol::OP_HEARTBEAT_INDICATION)
+ broker.handleHeartbeatIndication(buffer, sequence, routingKey);
+ else if (opcode == Protocol::OP_EVENT_INDICATION)
+ broker.handleEventIndication(buffer, sequence);
+ else if (opcode == Protocol::OP_PROPERTY_INDICATION) {
+ object = broker.handleObjectIndication(buffer, sequence, true, false);
+ broker.console.impl->eventObjectUpdate(object, true, false);
+ }
+ else if (opcode == Protocol::OP_STATISTIC_INDICATION) {
+ object = broker.handleObjectIndication(buffer, sequence, false, true);
+ broker.console.impl->eventObjectUpdate(object, false, true);
+ }
+ else if (opcode == Protocol::OP_OBJECT_INDICATION) {
+ object = broker.handleObjectIndication(buffer, sequence, true, true);
+ broker.console.impl->eventObjectUpdate(object, true, true);
+ }
+ else {
+ QPID_LOG(trace, "StaticContext::handleMessage invalid opcode: " << opcode);
+ completeContext = true;
+ }
+
+ return completeContext;
+}
+
+void QueryContext::reserve()
+{
+ Mutex::ScopedLock _lock(lock);
+ requestsOutstanding++;
+}
+
+void QueryContext::release()
+{
+ {
+ Mutex::ScopedLock _lock(lock);
+ if (--requestsOutstanding > 0)
+ return;
+ }
+
+ Mutex::ScopedLock _block(broker.lock);
+ broker.eventQueue.push_back(broker.eventQueryComplete(userContext, queryResponse));
+}
+
+bool QueryContext::handleMessage(uint8_t opcode, uint32_t sequence, const string& /*routingKey*/, Buffer& buffer)
+{
+ bool completeContext = false;
+ ObjectPtr object;
+
+ if (opcode == Protocol::OP_COMMAND_COMPLETE) {
+ broker.handleCommandComplete(buffer, sequence);
+ completeContext = true;
+
+ //
+ // Visit each agent and remove the sequence from that agent's in-flight list.
+ // This could be made more efficient because only one agent will have this sequence
+ // in its list.
+ //
+ map<uint32_t, AgentProxyPtr> copy;
+ {
+ Mutex::ScopedLock _block(broker.lock);
+ copy = broker.agentList;
+ }
+ for (map<uint32_t, AgentProxyPtr>::iterator iter = copy.begin(); iter != copy.end(); iter++)
+ iter->second->impl->delSequence(sequence);
+ }
+ else if (opcode == Protocol::OP_OBJECT_INDICATION) {
+ object = broker.handleObjectIndication(buffer, sequence, true, true);
+ if (object.get() != 0)
+ queryResponse->impl->results.push_back(object);
+ }
+ else {
+ QPID_LOG(trace, "QueryContext::handleMessage invalid opcode: " << opcode);
+ completeContext = true;
+ }
+
+ return completeContext;
+}
+
+void MethodContext::release()
+{
+ Mutex::ScopedLock _block(broker.lock);
+ broker.eventQueue.push_back(broker.eventMethodResponse(userContext, methodResponse));
+}
+
+bool MethodContext::handleMessage(uint8_t opcode, uint32_t sequence, const string& /*routingKey*/, Buffer& buffer)
+{
+ if (opcode == Protocol::OP_METHOD_RESPONSE)
+ methodResponse = broker.handleMethodResponse(buffer, sequence, schema);
+ else
+ QPID_LOG(trace, "QueryContext::handleMessage invalid opcode: " << opcode);
+
+ return true;
+}
+
+
+//==================================================================
+// Wrappers
+//==================================================================
+
+AgentProxy::AgentProxy(AgentProxyImpl* i) : impl(i) {}
+AgentProxy::~AgentProxy() { delete impl; }
+const char* AgentProxy::getLabel() const { return impl->getLabel().c_str(); }
+uint32_t AgentProxy::getBrokerBank() const { return impl->getBrokerBank(); }
+uint32_t AgentProxy::getAgentBank() const { return impl->getAgentBank(); }
+
+BrokerProxy::BrokerProxy(Console& console) : impl(new BrokerProxyImpl(*this, console)) {}
+BrokerProxy::~BrokerProxy() { delete impl; }
+void BrokerProxy::sessionOpened(SessionHandle& sh) { impl->sessionOpened(sh); }
+void BrokerProxy::sessionClosed() { impl->sessionClosed(); }
+void BrokerProxy::startProtocol() { impl->startProtocol(); }
+void BrokerProxy::handleRcvMessage(Message& message) { impl->handleRcvMessage(message); }
+bool BrokerProxy::getXmtMessage(Message& item) const { return impl->getXmtMessage(item); }
+void BrokerProxy::popXmt() { impl->popXmt(); }
+bool BrokerProxy::getEvent(BrokerEvent& event) const { return impl->getEvent(event); }
+void BrokerProxy::popEvent() { impl->popEvent(); }
+uint32_t BrokerProxy::agentCount() const { return impl->agentCount(); }
+const AgentProxy* BrokerProxy::getAgent(uint32_t idx) const { return impl->getAgent(idx); }
+void BrokerProxy::sendQuery(const Query& query, void* context, const AgentProxy* agent) { impl->sendQuery(query, context, agent); }
+
+MethodResponse::MethodResponse(const MethodResponse& from) : impl(new MethodResponseImpl(*(from.impl))) {}
+MethodResponse::MethodResponse(MethodResponseImpl* i) : impl(i) {}
+MethodResponse::~MethodResponse() {}
+uint32_t MethodResponse::getStatus() const { return impl->getStatus(); }
+const Value* MethodResponse::getException() const { return impl->getException(); }
+const Value* MethodResponse::getArgs() const { return impl->getArgs(); }
+
+QueryResponse::QueryResponse(QueryResponseImpl* i) : impl(i) {}
+QueryResponse::~QueryResponse() {}
+uint32_t QueryResponse::getStatus() const { return impl->getStatus(); }
+const Value* QueryResponse::getException() const { return impl->getException(); }
+uint32_t QueryResponse::getObjectCount() const { return impl->getObjectCount(); }
+const Object* QueryResponse::getObject(uint32_t idx) const { return impl->getObject(idx); }
+
diff --git a/qpid/cpp/src/qmf/engine/BrokerProxyImpl.h b/qpid/cpp/src/qmf/engine/BrokerProxyImpl.h
new file mode 100644
index 0000000000..798a5fdc76
--- /dev/null
+++ b/qpid/cpp/src/qmf/engine/BrokerProxyImpl.h
@@ -0,0 +1,239 @@
+#ifndef _QmfEngineBrokerProxyImpl_
+#define _QmfEngineBrokerProxyImpl_
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "qmf/engine/Console.h"
+#include "qmf/engine/ObjectImpl.h"
+#include "qmf/engine/SchemaImpl.h"
+#include "qmf/engine/ValueImpl.h"
+#include "qmf/engine/QueryImpl.h"
+#include "qmf/engine/SequenceManager.h"
+#include "qmf/engine/MessageImpl.h"
+#include "qpid/framing/Buffer.h"
+#include "qpid/framing/Uuid.h"
+#include "qpid/sys/Mutex.h"
+#include "boost/shared_ptr.hpp"
+#include "boost/noncopyable.hpp"
+#include <memory>
+#include <string>
+#include <deque>
+#include <map>
+#include <set>
+#include <vector>
+
+namespace qmf {
+namespace engine {
+
+ typedef boost::shared_ptr<MethodResponse> MethodResponsePtr;
+ struct MethodResponseImpl {
+ uint32_t status;
+ const SchemaMethod* schema;
+ std::auto_ptr<Value> exception;
+ std::auto_ptr<Value> arguments;
+
+ MethodResponseImpl(const MethodResponseImpl& from);
+ MethodResponseImpl(qpid::framing::Buffer& buf, const SchemaMethod* schema);
+ MethodResponseImpl(uint32_t status, const std::string& text);
+ static MethodResponse* factory(qpid::framing::Buffer& buf, const SchemaMethod* schema);
+ static MethodResponse* factory(uint32_t status, const std::string& text);
+ ~MethodResponseImpl() {}
+ uint32_t getStatus() const { return status; }
+ const Value* getException() const { return exception.get(); }
+ const Value* getArgs() const { return arguments.get(); }
+ };
+
+ typedef boost::shared_ptr<QueryResponse> QueryResponsePtr;
+ struct QueryResponseImpl {
+ uint32_t status;
+ std::auto_ptr<Value> exception;
+ std::vector<ObjectPtr> results;
+
+ QueryResponseImpl() : status(0) {}
+ static QueryResponse* factory() {
+ QueryResponseImpl* impl(new QueryResponseImpl());
+ return new QueryResponse(impl);
+ }
+ ~QueryResponseImpl() {}
+ uint32_t getStatus() const { return status; }
+ const Value* getException() const { return exception.get(); }
+ uint32_t getObjectCount() const { return results.size(); }
+ const Object* getObject(uint32_t idx) const;
+ };
+
+ struct BrokerEventImpl {
+ typedef boost::shared_ptr<BrokerEventImpl> Ptr;
+ BrokerEvent::EventKind kind;
+ std::string name;
+ std::string exchange;
+ std::string bindingKey;
+ void* context;
+ QueryResponsePtr queryResponse;
+ MethodResponsePtr methodResponse;
+
+ BrokerEventImpl(BrokerEvent::EventKind k) : kind(k), context(0) {}
+ ~BrokerEventImpl() {}
+ BrokerEvent copy();
+ };
+
+ typedef boost::shared_ptr<AgentProxy> AgentProxyPtr;
+ struct AgentProxyImpl {
+ Console& console;
+ BrokerProxy& broker;
+ uint32_t agentBank;
+ std::string label;
+ std::set<uint32_t> inFlightSequences;
+
+ AgentProxyImpl(Console& c, BrokerProxy& b, uint32_t ab, const std::string& l) : console(c), broker(b), agentBank(ab), label(l) {}
+ static AgentProxy* factory(Console& c, BrokerProxy& b, uint32_t ab, const std::string& l) {
+ AgentProxyImpl* impl(new AgentProxyImpl(c, b, ab, l));
+ return new AgentProxy(impl);
+ }
+ ~AgentProxyImpl() {}
+ const std::string& getLabel() const { return label; }
+ uint32_t getBrokerBank() const { return 1; }
+ uint32_t getAgentBank() const { return agentBank; }
+ void addSequence(uint32_t seq) { inFlightSequences.insert(seq); }
+ void delSequence(uint32_t seq) { inFlightSequences.erase(seq); }
+ void releaseInFlight(SequenceManager& seqMgr) {
+ for (std::set<uint32_t>::iterator iter = inFlightSequences.begin(); iter != inFlightSequences.end(); iter++)
+ seqMgr.release(*iter);
+ inFlightSequences.clear();
+ }
+ };
+
+ class BrokerProxyImpl : public boost::noncopyable {
+ public:
+ BrokerProxyImpl(BrokerProxy& pub, Console& _console);
+ ~BrokerProxyImpl() {}
+
+ void sessionOpened(SessionHandle& sh);
+ void sessionClosed();
+ void startProtocol();
+
+ void sendBufferLH(qpid::framing::Buffer& buf, const std::string& destination, const std::string& routingKey);
+ void handleRcvMessage(Message& message);
+ bool getXmtMessage(Message& item) const;
+ void popXmt();
+
+ bool getEvent(BrokerEvent& event) const;
+ void popEvent();
+
+ uint32_t agentCount() const;
+ const AgentProxy* getAgent(uint32_t idx) const;
+ void sendQuery(const Query& query, void* context, const AgentProxy* agent);
+ void sendGetRequestLH(SequenceContext::Ptr queryContext, const Query& query, const AgentProxy* agent);
+ std::string encodeMethodArguments(const SchemaMethod* schema, const Value* args, qpid::framing::Buffer& buffer);
+ void sendMethodRequest(ObjectId* oid, const SchemaObjectClass* cls, const std::string& method, const Value* args, void* context);
+
+ void addBinding(const std::string& exchange, const std::string& key);
+ void staticRelease() { decOutstanding(); }
+
+ private:
+ friend struct StaticContext;
+ friend struct QueryContext;
+ friend struct MethodContext;
+ BrokerProxy& publicObject;
+ mutable qpid::sys::Mutex lock;
+ Console& console;
+ std::string queueName;
+ qpid::framing::Uuid brokerId;
+ SequenceManager seqMgr;
+ uint32_t requestsOutstanding;
+ bool topicBound;
+ std::map<uint32_t, AgentProxyPtr> agentList;
+ std::deque<MessageImpl::Ptr> xmtQueue;
+ std::deque<BrokerEventImpl::Ptr> eventQueue;
+
+# define MA_BUFFER_SIZE 65536
+ char outputBuffer[MA_BUFFER_SIZE];
+
+ BrokerEventImpl::Ptr eventDeclareQueue(const std::string& queueName);
+ BrokerEventImpl::Ptr eventBind(const std::string& exchange, const std::string& queue, const std::string& key);
+ BrokerEventImpl::Ptr eventSetupComplete();
+ BrokerEventImpl::Ptr eventStable();
+ BrokerEventImpl::Ptr eventQueryComplete(void* context, QueryResponsePtr response);
+ BrokerEventImpl::Ptr eventMethodResponse(void* context, MethodResponsePtr response);
+
+ void handleBrokerResponse(qpid::framing::Buffer& inBuffer, uint32_t seq);
+ void handlePackageIndication(qpid::framing::Buffer& inBuffer, uint32_t seq);
+ void handleCommandComplete(qpid::framing::Buffer& inBuffer, uint32_t seq);
+ void handleClassIndication(qpid::framing::Buffer& inBuffer, uint32_t seq);
+ MethodResponsePtr handleMethodResponse(qpid::framing::Buffer& inBuffer, uint32_t seq, const SchemaMethod* schema);
+ void handleHeartbeatIndication(qpid::framing::Buffer& inBuffer, uint32_t seq, const std::string& routingKey);
+ void handleEventIndication(qpid::framing::Buffer& inBuffer, uint32_t seq);
+ void handleSchemaResponse(qpid::framing::Buffer& inBuffer, uint32_t seq);
+ ObjectPtr handleObjectIndication(qpid::framing::Buffer& inBuffer, uint32_t seq, bool prop, bool stat);
+ void updateAgentList(ObjectPtr obj);
+ void incOutstandingLH();
+ void decOutstanding();
+ };
+
+ //
+ // StaticContext is used to handle:
+ //
+ // 1) Responses to console-level requests (for schema info, etc.)
+ // 2) Unsolicited messages from agents (events, published updates, etc.)
+ //
+ struct StaticContext : public SequenceContext {
+ StaticContext(BrokerProxyImpl& b) : broker(b) {}
+ virtual ~StaticContext() {}
+ void reserve() {}
+ void release() { broker.staticRelease(); }
+ bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer);
+ BrokerProxyImpl& broker;
+ };
+
+ //
+ // QueryContext is used to track and handle responses associated with a single Get Query
+ //
+ struct QueryContext : public SequenceContext {
+ QueryContext(BrokerProxyImpl& b, void* u) :
+ broker(b), userContext(u), requestsOutstanding(0), queryResponse(QueryResponseImpl::factory()) {}
+ virtual ~QueryContext() {}
+ void reserve();
+ void release();
+ bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer);
+
+ mutable qpid::sys::Mutex lock;
+ BrokerProxyImpl& broker;
+ void* userContext;
+ uint32_t requestsOutstanding;
+ QueryResponsePtr queryResponse;
+ };
+
+ struct MethodContext : public SequenceContext {
+ MethodContext(BrokerProxyImpl& b, void* u, const SchemaMethod* s) : broker(b), userContext(u), schema(s) {}
+ virtual ~MethodContext() {}
+ void reserve() {}
+ void release();
+ bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer);
+
+ BrokerProxyImpl& broker;
+ void* userContext;
+ const SchemaMethod* schema;
+ MethodResponsePtr methodResponse;
+ };
+
+}
+}
+
+#endif
+
diff --git a/qpid/cpp/src/qmf/ConnectionSettingsImpl.cpp b/qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.cpp
index 034ab18395..2cd6af10f8 100644
--- a/qpid/cpp/src/qmf/ConnectionSettingsImpl.cpp
+++ b/qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.cpp
@@ -17,11 +17,11 @@
* under the License.
*/
-#include "qmf/ConnectionSettingsImpl.h"
-#include "qmf/Typecode.h"
+#include "qmf/engine/ConnectionSettingsImpl.h"
+#include "qmf/engine/Typecode.h"
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
using namespace qpid;
const string attrProtocol("protocol");
@@ -43,19 +43,20 @@ const string attrMaxSsf("maxSsf");
const string attrRetryDelayMin("retryDelayMin");
const string attrRetryDelayMax("retryDelayMax");
const string attrRetryDelayFactor("retryDelayFactor");
+const string attrSendUserId("sendUserId");
-ConnectionSettingsImpl::ConnectionSettingsImpl(ConnectionSettings* e) :
- envelope(e), retryDelayMin(1), retryDelayMax(64), retryDelayFactor(2)
+ConnectionSettingsImpl::ConnectionSettingsImpl() :
+ retryDelayMin(1), retryDelayMax(64), retryDelayFactor(2), sendUserId(true)
{
}
-ConnectionSettingsImpl::ConnectionSettingsImpl(ConnectionSettings* e, const string& /*url*/) :
- envelope(e), retryDelayMin(1), retryDelayMax(64), retryDelayFactor(2)
+ConnectionSettingsImpl::ConnectionSettingsImpl(const string& /*url*/) :
+ retryDelayMin(1), retryDelayMax(64), retryDelayFactor(2), sendUserId(true)
{
// TODO: Parse the URL
}
-void ConnectionSettingsImpl::setAttr(const string& key, const Value& value)
+bool ConnectionSettingsImpl::setAttr(const string& key, const Value& value)
{
if (key == attrProtocol) clientSettings.protocol = value.asString();
else if (key == attrHost) clientSettings.host = value.asString();
@@ -77,6 +78,10 @@ void ConnectionSettingsImpl::setAttr(const string& key, const Value& value)
else if (key == attrRetryDelayMin) retryDelayMin = value.asUint();
else if (key == attrRetryDelayMax) retryDelayMax = value.asUint();
else if (key == attrRetryDelayFactor) retryDelayFactor = value.asUint();
+ else if (key == attrSendUserId) sendUserId = value.asBool();
+ else
+ return false;
+ return true;
}
Value ConnectionSettingsImpl::getAttr(const string& key) const
@@ -251,73 +256,18 @@ void ConnectionSettingsImpl::getRetrySettings(int* min, int* max, int* factor) c
// Wrappers
//==================================================================
-ConnectionSettings::ConnectionSettings(const ConnectionSettings& from)
-{
- impl = new ConnectionSettingsImpl(*from.impl);
-}
-
-ConnectionSettings::ConnectionSettings()
-{
- impl = new ConnectionSettingsImpl(this);
-}
-
-ConnectionSettings::ConnectionSettings(const char* url)
-{
- impl = new ConnectionSettingsImpl(this, url);
-}
-
-ConnectionSettings::~ConnectionSettings()
-{
- delete impl;
-}
-
-void ConnectionSettings::setAttr(const char* key, const Value& value)
-{
- impl->setAttr(key, value);
-}
-
-Value ConnectionSettings::getAttr(const char* key) const
-{
- return impl->getAttr(key);
-}
-
-const char* ConnectionSettings::getAttrString() const
-{
- return impl->getAttrString().c_str();
-}
-
-void ConnectionSettings::transportTcp(uint16_t port)
-{
- impl->transportTcp(port);
-}
-
-void ConnectionSettings::transportSsl(uint16_t port)
-{
- impl->transportSsl(port);
-}
-
-void ConnectionSettings::transportRdma(uint16_t port)
-{
- impl->transportRdma(port);
-}
-
-void ConnectionSettings::authAnonymous(const char* username)
-{
- impl->authAnonymous(username);
-}
-
-void ConnectionSettings::authPlain(const char* username, const char* password)
-{
- impl->authPlain(username, password);
-}
-
-void ConnectionSettings::authGssapi(const char* serviceName, uint32_t minSsf, uint32_t maxSsf)
-{
- impl->authGssapi(serviceName, minSsf, maxSsf);
-}
-
-void ConnectionSettings::setRetry(int delayMin, int delayMax, int delayFactor)
-{
- impl->setRetry(delayMin, delayMax, delayFactor);
-}
+ConnectionSettings::ConnectionSettings(const ConnectionSettings& from) { impl = new ConnectionSettingsImpl(*from.impl); }
+ConnectionSettings::ConnectionSettings() { impl = new ConnectionSettingsImpl(); }
+ConnectionSettings::ConnectionSettings(const char* url) { impl = new ConnectionSettingsImpl(url); }
+ConnectionSettings::~ConnectionSettings() { delete impl; }
+bool ConnectionSettings::setAttr(const char* key, const Value& value) { return impl->setAttr(key, value); }
+Value ConnectionSettings::getAttr(const char* key) const { return impl->getAttr(key); }
+const char* ConnectionSettings::getAttrString() const { return impl->getAttrString().c_str(); }
+void ConnectionSettings::transportTcp(uint16_t port) { impl->transportTcp(port); }
+void ConnectionSettings::transportSsl(uint16_t port) { impl->transportSsl(port); }
+void ConnectionSettings::transportRdma(uint16_t port) { impl->transportRdma(port); }
+void ConnectionSettings::authAnonymous(const char* username) { impl->authAnonymous(username); }
+void ConnectionSettings::authPlain(const char* username, const char* password) { impl->authPlain(username, password); }
+void ConnectionSettings::authGssapi(const char* serviceName, uint32_t minSsf, uint32_t maxSsf) { impl->authGssapi(serviceName, minSsf, maxSsf); }
+void ConnectionSettings::setRetry(int delayMin, int delayMax, int delayFactor) { impl->setRetry(delayMin, delayMax, delayFactor); }
diff --git a/qpid/cpp/src/qmf/ConnectionSettingsImpl.h b/qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.h
index a177233cf3..98bf87868b 100644
--- a/qpid/cpp/src/qmf/ConnectionSettingsImpl.h
+++ b/qpid/cpp/src/qmf/engine/ConnectionSettingsImpl.h
@@ -1,5 +1,5 @@
-#ifndef _QmfConnectionSettingsImpl_
-#define _QmfConnectionSettingsImpl_
+#ifndef _QmfEngineConnectionSettingsImpl_
+#define _QmfEngineConnectionSettingsImpl_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,27 +20,28 @@
* under the License.
*/
-#include "qmf/ConnectionSettings.h"
-#include "qmf/Value.h"
+#include "qmf/engine/ConnectionSettings.h"
+#include "qmf/engine/Value.h"
#include "qpid/client/ConnectionSettings.h"
#include <string>
#include <map>
namespace qmf {
+namespace engine {
class ConnectionSettingsImpl {
- ConnectionSettings* envelope;
qpid::client::ConnectionSettings clientSettings;
mutable std::string attrString;
int retryDelayMin;
int retryDelayMax;
int retryDelayFactor;
+ bool sendUserId;
public:
- ConnectionSettingsImpl(ConnectionSettings* e);
- ConnectionSettingsImpl(ConnectionSettings* e, const std::string& url);
+ ConnectionSettingsImpl();
+ ConnectionSettingsImpl(const std::string& url);
~ConnectionSettingsImpl() {}
- void setAttr(const std::string& key, const Value& value);
+ bool setAttr(const std::string& key, const Value& value);
Value getAttr(const std::string& key) const;
const std::string& getAttrString() const;
void transportTcp(uint16_t port);
@@ -53,8 +54,10 @@ namespace qmf {
const qpid::client::ConnectionSettings& getClientSettings() const;
void getRetrySettings(int* delayMin, int* delayMax, int* delayFactor) const;
+ bool getSendUserId() const { return sendUserId; }
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/engine/ConsoleImpl.cpp b/qpid/cpp/src/qmf/engine/ConsoleImpl.cpp
new file mode 100644
index 0000000000..c2d1f51f2b
--- /dev/null
+++ b/qpid/cpp/src/qmf/engine/ConsoleImpl.cpp
@@ -0,0 +1,419 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "qmf/engine/ConsoleImpl.h"
+#include "qmf/engine/MessageImpl.h"
+#include "qmf/engine/SchemaImpl.h"
+#include "qmf/engine/Typecode.h"
+#include "qmf/engine/ObjectImpl.h"
+#include "qmf/engine/ObjectIdImpl.h"
+#include "qmf/engine/QueryImpl.h"
+#include "qmf/engine/ValueImpl.h"
+#include "qmf/engine/Protocol.h"
+#include "qmf/engine/SequenceManager.h"
+#include "qmf/engine/BrokerProxyImpl.h"
+#include <qpid/framing/Buffer.h>
+#include <qpid/framing/Uuid.h>
+#include <qpid/framing/FieldTable.h>
+#include <qpid/framing/FieldValue.h>
+#include <qpid/log/Statement.h>
+#include <qpid/sys/Time.h>
+#include <qpid/sys/SystemInfo.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+using namespace qmf::engine;
+using namespace qpid::framing;
+using namespace qpid::sys;
+
+namespace {
+ const char* QMF_EXCHANGE = "qpid.management";
+}
+
+#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());}
+
+ConsoleEvent ConsoleEventImpl::copy()
+{
+ ConsoleEvent item;
+
+ ::memset(&item, 0, sizeof(ConsoleEvent));
+ item.kind = kind;
+ item.agent = agent.get();
+ item.classKey = classKey;
+ item.object = object.get();
+ item.context = context;
+ item.event = event;
+ item.timestamp = timestamp;
+ item.hasProps = hasProps;
+ item.hasStats = hasStats;
+
+ STRING_REF(name);
+
+ return item;
+}
+
+ConsoleImpl::ConsoleImpl(const ConsoleSettings& s) : settings(s)
+{
+ bindingList.push_back(pair<string, string>(string(), "schema.#"));
+ if (settings.rcvObjects && settings.rcvEvents && settings.rcvHeartbeats && !settings.userBindings) {
+ bindingList.push_back(pair<string, string>(string(), "console.#"));
+ } else {
+ if (settings.rcvObjects && !settings.userBindings)
+ bindingList.push_back(pair<string, string>(string(), "console.obj.#"));
+ else
+ bindingList.push_back(pair<string, string>(string(), "console.obj.*.*.org.apache.qpid.broker.agent"));
+ if (settings.rcvEvents)
+ bindingList.push_back(pair<string, string>(string(), "console.event.#"));
+ if (settings.rcvHeartbeats)
+ bindingList.push_back(pair<string, string>(string(), "console.heartbeat.#"));
+ }
+}
+
+ConsoleImpl::~ConsoleImpl()
+{
+ // This function intentionally left blank.
+}
+
+bool ConsoleImpl::getEvent(ConsoleEvent& event) const
+{
+ Mutex::ScopedLock _lock(lock);
+ if (eventQueue.empty())
+ return false;
+ event = eventQueue.front()->copy();
+ return true;
+}
+
+void ConsoleImpl::popEvent()
+{
+ Mutex::ScopedLock _lock(lock);
+ if (!eventQueue.empty())
+ eventQueue.pop_front();
+}
+
+void ConsoleImpl::addConnection(BrokerProxy& broker, void* /*context*/)
+{
+ Mutex::ScopedLock _lock(lock);
+ brokerList.push_back(broker.impl);
+}
+
+void ConsoleImpl::delConnection(BrokerProxy& broker)
+{
+ Mutex::ScopedLock _lock(lock);
+ for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
+ iter != brokerList.end(); iter++)
+ if (*iter == broker.impl) {
+ brokerList.erase(iter);
+ break;
+ }
+}
+
+uint32_t ConsoleImpl::packageCount() const
+{
+ Mutex::ScopedLock _lock(lock);
+ return packages.size();
+}
+
+const string& ConsoleImpl::getPackageName(uint32_t idx) const
+{
+ const static string empty;
+
+ Mutex::ScopedLock _lock(lock);
+ if (idx >= packages.size())
+ return empty;
+
+ PackageList::const_iterator iter = packages.begin();
+ for (uint32_t i = 0; i < idx; i++) iter++;
+ return iter->first;
+}
+
+uint32_t ConsoleImpl::classCount(const char* packageName) const
+{
+ Mutex::ScopedLock _lock(lock);
+ PackageList::const_iterator pIter = packages.find(packageName);
+ if (pIter == packages.end())
+ return 0;
+
+ const ObjectClassList& oList = pIter->second.first;
+ const EventClassList& eList = pIter->second.second;
+
+ return oList.size() + eList.size();
+}
+
+const SchemaClassKey* ConsoleImpl::getClass(const char* packageName, uint32_t idx) const
+{
+ Mutex::ScopedLock _lock(lock);
+ PackageList::const_iterator pIter = packages.find(packageName);
+ if (pIter == packages.end())
+ return 0;
+
+ const ObjectClassList& oList = pIter->second.first;
+ const EventClassList& eList = pIter->second.second;
+ uint32_t count = 0;
+
+ for (ObjectClassList::const_iterator oIter = oList.begin();
+ oIter != oList.end(); oIter++) {
+ if (count == idx)
+ return oIter->second->getClassKey();
+ count++;
+ }
+
+ for (EventClassList::const_iterator eIter = eList.begin();
+ eIter != eList.end(); eIter++) {
+ if (count == idx)
+ return eIter->second->getClassKey();
+ count++;
+ }
+
+ return 0;
+}
+
+ClassKind ConsoleImpl::getClassKind(const SchemaClassKey* key) const
+{
+ Mutex::ScopedLock _lock(lock);
+ PackageList::const_iterator pIter = packages.find(key->getPackageName());
+ if (pIter == packages.end())
+ return CLASS_OBJECT;
+
+ const EventClassList& eList = pIter->second.second;
+ if (eList.find(key) != eList.end())
+ return CLASS_EVENT;
+ return CLASS_OBJECT;
+}
+
+const SchemaObjectClass* ConsoleImpl::getObjectClass(const SchemaClassKey* key) const
+{
+ Mutex::ScopedLock _lock(lock);
+ PackageList::const_iterator pIter = packages.find(key->getPackageName());
+ if (pIter == packages.end())
+ return 0;
+
+ const ObjectClassList& oList = pIter->second.first;
+ ObjectClassList::const_iterator iter = oList.find(key);
+ if (iter == oList.end())
+ return 0;
+ return iter->second;
+}
+
+const SchemaEventClass* ConsoleImpl::getEventClass(const SchemaClassKey* key) const
+{
+ Mutex::ScopedLock _lock(lock);
+ PackageList::const_iterator pIter = packages.find(key->getPackageName());
+ if (pIter == packages.end())
+ return 0;
+
+ const EventClassList& eList = pIter->second.second;
+ EventClassList::const_iterator iter = eList.find(key);
+ if (iter == eList.end())
+ return 0;
+ return iter->second;
+}
+
+void ConsoleImpl::bindPackage(const char* packageName)
+{
+ stringstream key;
+ key << "console.obj.*.*." << packageName << ".#";
+ Mutex::ScopedLock _lock(lock);
+ bindingList.push_back(pair<string, string>(string(), key.str()));
+ for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
+ iter != brokerList.end(); iter++)
+ (*iter)->addBinding(QMF_EXCHANGE, key.str());
+}
+
+void ConsoleImpl::bindClass(const SchemaClassKey* classKey)
+{
+ stringstream key;
+ key << "console.obj.*.*." << classKey->getPackageName() << "." << classKey->getClassName() << ".#";
+ Mutex::ScopedLock _lock(lock);
+ bindingList.push_back(pair<string, string>(string(), key.str()));
+ for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
+ iter != brokerList.end(); iter++)
+ (*iter)->addBinding(QMF_EXCHANGE, key.str());
+}
+
+void ConsoleImpl::bindClass(const char* packageName, const char* className)
+{
+ stringstream key;
+ key << "console.obj.*.*." << packageName << "." << className << ".#";
+ Mutex::ScopedLock _lock(lock);
+ bindingList.push_back(pair<string, string>(string(), key.str()));
+ for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin();
+ iter != brokerList.end(); iter++)
+ (*iter)->addBinding(QMF_EXCHANGE, key.str());
+}
+
+/*
+void ConsoleImpl::startSync(const Query& query, void* context, SyncQuery& sync)
+{
+}
+
+void ConsoleImpl::touchSync(SyncQuery& sync)
+{
+}
+
+void ConsoleImpl::endSync(SyncQuery& sync)
+{
+}
+*/
+
+void ConsoleImpl::learnPackage(const string& packageName)
+{
+ Mutex::ScopedLock _lock(lock);
+ if (packages.find(packageName) == packages.end()) {
+ packages.insert(pair<string, pair<ObjectClassList, EventClassList> >
+ (packageName, pair<ObjectClassList, EventClassList>(ObjectClassList(), EventClassList())));
+ eventNewPackage(packageName);
+ }
+}
+
+void ConsoleImpl::learnClass(SchemaObjectClass* cls)
+{
+ Mutex::ScopedLock _lock(lock);
+ const SchemaClassKey* key = cls->getClassKey();
+ PackageList::iterator pIter = packages.find(key->getPackageName());
+ if (pIter == packages.end())
+ return;
+
+ ObjectClassList& list = pIter->second.first;
+ if (list.find(key) == list.end()) {
+ list[key] = cls;
+ eventNewClass(key);
+ }
+}
+
+void ConsoleImpl::learnClass(SchemaEventClass* cls)
+{
+ Mutex::ScopedLock _lock(lock);
+ const SchemaClassKey* key = cls->getClassKey();
+ PackageList::iterator pIter = packages.find(key->getPackageName());
+ if (pIter == packages.end())
+ return;
+
+ EventClassList& list = pIter->second.second;
+ if (list.find(key) == list.end()) {
+ list[key] = cls;
+ eventNewClass(key);
+ }
+}
+
+bool ConsoleImpl::haveClass(const SchemaClassKey* key) const
+{
+ Mutex::ScopedLock _lock(lock);
+ PackageList::const_iterator pIter = packages.find(key->getPackageName());
+ if (pIter == packages.end())
+ return false;
+
+ const ObjectClassList& oList = pIter->second.first;
+ const EventClassList& eList = pIter->second.second;
+
+ return oList.find(key) != oList.end() || eList.find(key) != eList.end();
+}
+
+SchemaObjectClass* ConsoleImpl::getSchema(const SchemaClassKey* key) const
+{
+ Mutex::ScopedLock _lock(lock);
+ PackageList::const_iterator pIter = packages.find(key->getPackageName());
+ if (pIter == packages.end())
+ return 0;
+
+ const ObjectClassList& oList = pIter->second.first;
+ ObjectClassList::const_iterator iter = oList.find(key);
+ if (iter == oList.end())
+ return 0;
+
+ return iter->second;
+}
+
+void ConsoleImpl::eventAgentAdded(boost::shared_ptr<AgentProxy> agent)
+{
+ ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::AGENT_ADDED));
+ event->agent = agent;
+ Mutex::ScopedLock _lock(lock);
+ eventQueue.push_back(event);
+}
+
+void ConsoleImpl::eventAgentDeleted(boost::shared_ptr<AgentProxy> agent)
+{
+ ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::AGENT_DELETED));
+ event->agent = agent;
+ Mutex::ScopedLock _lock(lock);
+ eventQueue.push_back(event);
+}
+
+void ConsoleImpl::eventNewPackage(const string& packageName)
+{
+ ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::NEW_PACKAGE));
+ event->name = packageName;
+ Mutex::ScopedLock _lock(lock);
+ eventQueue.push_back(event);
+}
+
+void ConsoleImpl::eventNewClass(const SchemaClassKey* key)
+{
+ ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::NEW_CLASS));
+ event->classKey = key;
+ Mutex::ScopedLock _lock(lock);
+ eventQueue.push_back(event);
+}
+
+void ConsoleImpl::eventObjectUpdate(ObjectPtr object, bool prop, bool stat)
+{
+ ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::OBJECT_UPDATE));
+ event->object = object;
+ event->hasProps = prop;
+ event->hasStats = stat;
+ Mutex::ScopedLock _lock(lock);
+ eventQueue.push_back(event);
+}
+
+void ConsoleImpl::eventAgentHeartbeat(boost::shared_ptr<AgentProxy> agent, uint64_t timestamp)
+{
+ ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::AGENT_HEARTBEAT));
+ event->agent = agent;
+ event->timestamp = timestamp;
+ Mutex::ScopedLock _lock(lock);
+ eventQueue.push_back(event);
+}
+
+//==================================================================
+// Wrappers
+//==================================================================
+
+Console::Console(const ConsoleSettings& settings) : impl(new ConsoleImpl(settings)) {}
+Console::~Console() { delete impl; }
+bool Console::getEvent(ConsoleEvent& event) const { return impl->getEvent(event); }
+void Console::popEvent() { impl->popEvent(); }
+void Console::addConnection(BrokerProxy& broker, void* context) { impl->addConnection(broker, context); }
+void Console::delConnection(BrokerProxy& broker) { impl->delConnection(broker); }
+uint32_t Console::packageCount() const { return impl->packageCount(); }
+const char* Console::getPackageName(uint32_t idx) const { return impl->getPackageName(idx).c_str(); }
+uint32_t Console::classCount(const char* packageName) const { return impl->classCount(packageName); }
+const SchemaClassKey* Console::getClass(const char* packageName, uint32_t idx) const { return impl->getClass(packageName, idx); }
+ClassKind Console::getClassKind(const SchemaClassKey* key) const { return impl->getClassKind(key); }
+const SchemaObjectClass* Console::getObjectClass(const SchemaClassKey* key) const { return impl->getObjectClass(key); }
+const SchemaEventClass* Console::getEventClass(const SchemaClassKey* key) const { return impl->getEventClass(key); }
+void Console::bindPackage(const char* packageName) { impl->bindPackage(packageName); }
+void Console::bindClass(const SchemaClassKey* key) { impl->bindClass(key); }
+void Console::bindClass(const char* packageName, const char* className) { impl->bindClass(packageName, className); }
+//void Console::startSync(const Query& query, void* context, SyncQuery& sync) { impl->startSync(query, context, sync); }
+//void Console::touchSync(SyncQuery& sync) { impl->touchSync(sync); }
+//void Console::endSync(SyncQuery& sync) { impl->endSync(sync); }
+
+
diff --git a/qpid/cpp/src/qmf/engine/ConsoleImpl.h b/qpid/cpp/src/qmf/engine/ConsoleImpl.h
new file mode 100644
index 0000000000..8f99c5e6b9
--- /dev/null
+++ b/qpid/cpp/src/qmf/engine/ConsoleImpl.h
@@ -0,0 +1,145 @@
+#ifndef _QmfEngineConsoleEngineImpl_
+#define _QmfEngineConsoleEngineImpl_
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "qmf/engine/Console.h"
+#include "qmf/engine/MessageImpl.h"
+#include "qmf/engine/SchemaImpl.h"
+#include "qmf/engine/Typecode.h"
+#include "qmf/engine/ObjectImpl.h"
+#include "qmf/engine/ObjectIdImpl.h"
+#include "qmf/engine/QueryImpl.h"
+#include "qmf/engine/ValueImpl.h"
+#include "qmf/engine/Protocol.h"
+#include "qmf/engine/SequenceManager.h"
+#include "qmf/engine/BrokerProxyImpl.h"
+#include <qpid/framing/Buffer.h>
+#include <qpid/framing/Uuid.h>
+#include <qpid/framing/FieldTable.h>
+#include <qpid/framing/FieldValue.h>
+#include <qpid/sys/Mutex.h>
+#include <qpid/sys/Time.h>
+#include <qpid/sys/SystemInfo.h>
+#include <string.h>
+#include <string>
+#include <deque>
+#include <map>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+namespace qmf {
+namespace engine {
+
+ struct ConsoleEventImpl {
+ typedef boost::shared_ptr<ConsoleEventImpl> Ptr;
+ ConsoleEvent::EventKind kind;
+ boost::shared_ptr<AgentProxy> agent;
+ std::string name;
+ const SchemaClassKey* classKey;
+ boost::shared_ptr<Object> object;
+ void* context;
+ Event* event;
+ uint64_t timestamp;
+ bool hasProps;
+ bool hasStats;
+
+ ConsoleEventImpl(ConsoleEvent::EventKind k) :
+ kind(k), classKey(0), context(0), event(0), timestamp(0) {}
+ ~ConsoleEventImpl() {}
+ ConsoleEvent copy();
+ };
+
+ class ConsoleImpl : public boost::noncopyable {
+ public:
+ ConsoleImpl(const ConsoleSettings& settings = ConsoleSettings());
+ ~ConsoleImpl();
+
+ bool getEvent(ConsoleEvent& event) const;
+ void popEvent();
+
+ void addConnection(BrokerProxy& broker, void* context);
+ void delConnection(BrokerProxy& broker);
+
+ uint32_t packageCount() const;
+ const std::string& getPackageName(uint32_t idx) const;
+
+ uint32_t classCount(const char* packageName) const;
+ const SchemaClassKey* getClass(const char* packageName, uint32_t idx) const;
+
+ ClassKind getClassKind(const SchemaClassKey* key) const;
+ const SchemaObjectClass* getObjectClass(const SchemaClassKey* key) const;
+ const SchemaEventClass* getEventClass(const SchemaClassKey* key) const;
+
+ void bindPackage(const char* packageName);
+ void bindClass(const SchemaClassKey* key);
+ void bindClass(const char* packageName, const char* className);
+
+ /*
+ void startSync(const Query& query, void* context, SyncQuery& sync);
+ void touchSync(SyncQuery& sync);
+ void endSync(SyncQuery& sync);
+ */
+
+ private:
+ friend class BrokerProxyImpl;
+ friend struct StaticContext;
+ const ConsoleSettings& settings;
+ mutable qpid::sys::Mutex lock;
+ std::deque<ConsoleEventImpl::Ptr> eventQueue;
+ std::vector<BrokerProxyImpl*> brokerList;
+ std::vector<std::pair<std::string, std::string> > bindingList; // exchange/key (empty exchange => QMF_EXCHANGE)
+
+ // Declare a compare class for the class maps that compares the dereferenced
+ // class key pointers. The default behavior would be to compare the pointer
+ // addresses themselves.
+ struct KeyCompare {
+ bool operator()(const SchemaClassKey* left, const SchemaClassKey* right) const {
+ return *left < *right;
+ }
+ };
+
+ typedef std::map<const SchemaClassKey*, SchemaObjectClass*, KeyCompare> ObjectClassList;
+ typedef std::map<const SchemaClassKey*, SchemaEventClass*, KeyCompare> EventClassList;
+ typedef std::map<std::string, std::pair<ObjectClassList, EventClassList> > PackageList;
+
+ PackageList packages;
+
+ void learnPackage(const std::string& packageName);
+ void learnClass(SchemaObjectClass* cls);
+ void learnClass(SchemaEventClass* cls);
+ bool haveClass(const SchemaClassKey* key) const;
+ SchemaObjectClass* getSchema(const SchemaClassKey* key) const;
+
+ void eventAgentAdded(boost::shared_ptr<AgentProxy> agent);
+ void eventAgentDeleted(boost::shared_ptr<AgentProxy> agent);
+ void eventNewPackage(const std::string& packageName);
+ void eventNewClass(const SchemaClassKey* key);
+ void eventObjectUpdate(ObjectPtr object, bool prop, bool stat);
+ void eventAgentHeartbeat(boost::shared_ptr<AgentProxy> agent, uint64_t timestamp);
+ };
+}
+}
+
+#endif
+
diff --git a/qpid/cpp/src/qmf/MessageImpl.cpp b/qpid/cpp/src/qmf/engine/MessageImpl.cpp
index f2625c7202..0047d3eb9d 100644
--- a/qpid/cpp/src/qmf/MessageImpl.cpp
+++ b/qpid/cpp/src/qmf/engine/MessageImpl.cpp
@@ -17,11 +17,11 @@
* under the License.
*/
-#include "qmf/MessageImpl.h"
+#include "qmf/engine/MessageImpl.h"
#include <string.h>
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());}
diff --git a/qpid/cpp/src/qmf/MessageImpl.h b/qpid/cpp/src/qmf/engine/MessageImpl.h
index 137f435699..b91291d2e4 100644
--- a/qpid/cpp/src/qmf/MessageImpl.h
+++ b/qpid/cpp/src/qmf/engine/MessageImpl.h
@@ -1,5 +1,5 @@
-#ifndef _QmfMessageImpl_
-#define _QmfMessageImpl_
+#ifndef _QmfEngineMessageImpl_
+#define _QmfEngineMessageImpl_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,11 +20,12 @@
* under the License.
*/
-#include "qmf/Message.h"
+#include "qmf/engine/Message.h"
#include <string>
#include <boost/shared_ptr.hpp>
namespace qmf {
+namespace engine {
struct MessageImpl {
typedef boost::shared_ptr<MessageImpl> Ptr;
@@ -38,5 +39,6 @@ namespace qmf {
Message copy();
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/ObjectIdImpl.cpp b/qpid/cpp/src/qmf/engine/ObjectIdImpl.cpp
index c0618ccc49..b08ae2756c 100644
--- a/qpid/cpp/src/qmf/ObjectIdImpl.cpp
+++ b/qpid/cpp/src/qmf/engine/ObjectIdImpl.cpp
@@ -17,11 +17,11 @@
* under the License.
*/
-#include "qmf/ObjectIdImpl.h"
+#include "qmf/engine/ObjectIdImpl.h"
#include <stdlib.h>
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
using qpid::framing::Buffer;
@@ -32,13 +32,12 @@ void AgentAttachment::setBanks(uint32_t broker, uint32_t agent)
((uint64_t) (agent & 0x0fffffff));
}
-ObjectIdImpl::ObjectIdImpl(Buffer& buffer) : envelope(new ObjectId(this)), agent(0)
+ObjectIdImpl::ObjectIdImpl(Buffer& buffer) : agent(0)
{
decode(buffer);
}
-ObjectIdImpl::ObjectIdImpl(AgentAttachment* a, uint8_t flags, uint16_t seq, uint64_t object) :
- envelope(new ObjectId(this)), agent(a)
+ObjectIdImpl::ObjectIdImpl(AgentAttachment* a, uint8_t flags, uint16_t seq, uint64_t object) : agent(a)
{
first =
((uint64_t) (flags & 0x0f)) << 60 |
@@ -46,6 +45,18 @@ ObjectIdImpl::ObjectIdImpl(AgentAttachment* a, uint8_t flags, uint16_t seq, uint
second = object;
}
+ObjectId* ObjectIdImpl::factory(Buffer& buffer)
+{
+ ObjectIdImpl* impl(new ObjectIdImpl(buffer));
+ return new ObjectId(impl);
+}
+
+ObjectId* ObjectIdImpl::factory(AgentAttachment* agent, uint8_t flags, uint16_t seq, uint64_t object)
+{
+ ObjectIdImpl* impl(new ObjectIdImpl(agent, flags, seq, object));
+ return new ObjectId(impl);
+}
+
void ObjectIdImpl::decode(Buffer& buffer)
{
first = buffer.getLongLong();
@@ -100,13 +111,14 @@ void ObjectIdImpl::fromString(const std::string& repr)
agent = 0;
}
-std::string ObjectIdImpl::asString() const
+const string& ObjectIdImpl::asString() const
{
stringstream val;
- val << getFlags() << "-" << getSequence() << "-" << getBrokerBank() << "-" <<
+ val << (int) getFlags() << "-" << getSequence() << "-" << getBrokerBank() << "-" <<
getAgentBank() << "-" << getObjectNum();
- return val.str();
+ repr = val.str();
+ return repr;
}
bool ObjectIdImpl::operator==(const ObjectIdImpl& other) const
@@ -135,58 +147,22 @@ bool ObjectIdImpl::operator>(const ObjectIdImpl& other) const
// Wrappers
//==================================================================
-ObjectId::ObjectId() : impl(new ObjectIdImpl(this)) {}
-
+ObjectId::ObjectId() : impl(new ObjectIdImpl()) {}
ObjectId::ObjectId(const ObjectId& from) : impl(new ObjectIdImpl(*(from.impl))) {}
-
ObjectId::ObjectId(ObjectIdImpl* i) : impl(i) {}
+ObjectId::~ObjectId() { delete impl; }
+uint64_t ObjectId::getObjectNum() const { return impl->getObjectNum(); }
+uint32_t ObjectId::getObjectNumHi() const { return impl->getObjectNumHi(); }
+uint32_t ObjectId::getObjectNumLo() const { return impl->getObjectNumLo(); }
+bool ObjectId::isDurable() const { return impl->isDurable(); }
+const char* ObjectId::str() const { return impl->asString().c_str(); }
+uint8_t ObjectId::getFlags() const { return impl->getFlags(); }
+uint16_t ObjectId::getSequence() const { return impl->getSequence(); }
+uint32_t ObjectId::getBrokerBank() const { return impl->getBrokerBank(); }
+uint32_t ObjectId::getAgentBank() const { return impl->getAgentBank(); }
+bool ObjectId::operator==(const ObjectId& other) const { return *impl == *other.impl; }
+bool ObjectId::operator<(const ObjectId& other) const { return *impl < *other.impl; }
+bool ObjectId::operator>(const ObjectId& other) const { return *impl > *other.impl; }
+bool ObjectId::operator<=(const ObjectId& other) const { return !(*impl > *other.impl); }
+bool ObjectId::operator>=(const ObjectId& other) const { return !(*impl < *other.impl); }
-ObjectId::~ObjectId()
-{
- delete impl;
-}
-
-uint64_t ObjectId::getObjectNum() const
-{
- return impl->getObjectNum();
-}
-
-uint32_t ObjectId::getObjectNumHi() const
-{
- return impl->getObjectNumHi();
-}
-
-uint32_t ObjectId::getObjectNumLo() const
-{
- return impl->getObjectNumLo();
-}
-
-bool ObjectId::isDurable() const
-{
- return impl->isDurable();
-}
-
-bool ObjectId::operator==(const ObjectId& other) const
-{
- return *impl == *other.impl;
-}
-
-bool ObjectId::operator<(const ObjectId& other) const
-{
- return *impl < *other.impl;
-}
-
-bool ObjectId::operator>(const ObjectId& other) const
-{
- return *impl > *other.impl;
-}
-
-bool ObjectId::operator<=(const ObjectId& other) const
-{
- return !(*impl > *other.impl);
-}
-
-bool ObjectId::operator>=(const ObjectId& other) const
-{
- return !(*impl < *other.impl);
-}
diff --git a/qpid/cpp/src/qmf/ObjectIdImpl.h b/qpid/cpp/src/qmf/engine/ObjectIdImpl.h
index 38d231237f..d9871ac217 100644
--- a/qpid/cpp/src/qmf/ObjectIdImpl.h
+++ b/qpid/cpp/src/qmf/engine/ObjectIdImpl.h
@@ -1,5 +1,5 @@
-#ifndef _QmfObjectIdImpl_
-#define _QmfObjectIdImpl_
+#ifndef _QmfEngineObjectIdImpl_
+#define _QmfEngineObjectIdImpl_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,10 +20,11 @@
* under the License.
*/
-#include <qmf/ObjectId.h>
+#include <qmf/engine/ObjectId.h>
#include <qpid/framing/Buffer.h>
namespace qmf {
+namespace engine {
struct AgentAttachment {
uint64_t first;
@@ -34,19 +35,22 @@ namespace qmf {
};
struct ObjectIdImpl {
- ObjectId* envelope;
AgentAttachment* agent;
uint64_t first;
uint64_t second;
+ mutable std::string repr;
- ObjectIdImpl(ObjectId* e) : envelope(e), agent(0), first(0), second(0) {}
+ ObjectIdImpl() : agent(0), first(0), second(0) {}
ObjectIdImpl(qpid::framing::Buffer& buffer);
ObjectIdImpl(AgentAttachment* agent, uint8_t flags, uint16_t seq, uint64_t object);
+ static ObjectId* factory(qpid::framing::Buffer& buffer);
+ static ObjectId* factory(AgentAttachment* agent, uint8_t flags, uint16_t seq, uint64_t object);
+
void decode(qpid::framing::Buffer& buffer);
void encode(qpid::framing::Buffer& buffer) const;
void fromString(const std::string& repr);
- std::string asString() const;
+ const std::string& asString() const;
uint8_t getFlags() const { return (first & 0xF000000000000000LL) >> 60; }
uint16_t getSequence() const { return (first & 0x0FFF000000000000LL) >> 48; }
uint32_t getBrokerBank() const { return (first & 0x0000FFFFF0000000LL) >> 28; }
@@ -62,6 +66,7 @@ namespace qmf {
bool operator>(const ObjectIdImpl& other) const;
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/ObjectImpl.cpp b/qpid/cpp/src/qmf/engine/ObjectImpl.cpp
index 1ea2d54527..cae0e0da68 100644
--- a/qpid/cpp/src/qmf/ObjectImpl.cpp
+++ b/qpid/cpp/src/qmf/engine/ObjectImpl.cpp
@@ -17,18 +17,17 @@
* under the License.
*/
-#include "qmf/ObjectImpl.h"
-#include "qmf/ValueImpl.h"
+#include "qmf/engine/ObjectImpl.h"
+#include "qmf/engine/ValueImpl.h"
+#include "qmf/engine/BrokerProxyImpl.h"
#include <qpid/sys/Time.h>
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
using namespace qpid::sys;
using qpid::framing::Buffer;
-ObjectImpl::ObjectImpl(Object* e, const SchemaObjectClass* type) :
- envelope(e), objectClass(type), createTime(uint64_t(Duration(now()))),
- destroyTime(0), lastUpdatedTime(createTime)
+ObjectImpl::ObjectImpl(const SchemaObjectClass* type) : objectClass(type), broker(0), createTime(uint64_t(Duration(now()))), destroyTime(0), lastUpdatedTime(createTime)
{
int propCount = objectClass->getPropertyCount();
int statCount = objectClass->getStatisticCount();
@@ -45,8 +44,8 @@ ObjectImpl::ObjectImpl(Object* e, const SchemaObjectClass* type) :
}
}
-ObjectImpl::ObjectImpl(const SchemaObjectClass* type, Buffer& buffer, bool prop, bool stat, bool managed) :
- envelope(new Object(this)), objectClass(type), createTime(0), destroyTime(0), lastUpdatedTime(0)
+ObjectImpl::ObjectImpl(const SchemaObjectClass* type, BrokerProxyImpl* b, Buffer& buffer, bool prop, bool stat, bool managed) :
+ objectClass(type), broker(b), createTime(0), destroyTime(0), lastUpdatedTime(0)
{
int idx;
@@ -54,7 +53,7 @@ ObjectImpl::ObjectImpl(const SchemaObjectClass* type, Buffer& buffer, bool prop,
lastUpdatedTime = buffer.getLongLong();
createTime = buffer.getLongLong();
destroyTime = buffer.getLongLong();
- objectId.reset(new ObjectIdImpl(buffer));
+ objectId.reset(ObjectIdImpl::factory(buffer));
}
if (prop) {
@@ -66,8 +65,8 @@ ObjectImpl::ObjectImpl(const SchemaObjectClass* type, Buffer& buffer, bool prop,
if (excludes.count(prop->getName()) != 0) {
properties[prop->getName()] = ValuePtr(new Value(prop->getType()));
} else {
- ValueImpl* pval = new ValueImpl(prop->getType(), buffer);
- properties[prop->getName()] = ValuePtr(pval->envelope);
+ Value* pval = ValueImpl::factory(prop->getType(), buffer);
+ properties[prop->getName()] = ValuePtr(pval);
}
}
}
@@ -76,12 +75,18 @@ ObjectImpl::ObjectImpl(const SchemaObjectClass* type, Buffer& buffer, bool prop,
int statCount = objectClass->getStatisticCount();
for (idx = 0; idx < statCount; idx++) {
const SchemaStatistic* stat = objectClass->getStatistic(idx);
- ValueImpl* sval = new ValueImpl(stat->getType(), buffer);
- statistics[stat->getName()] = ValuePtr(sval->envelope);
+ Value* sval = ValueImpl::factory(stat->getType(), buffer);
+ statistics[stat->getName()] = ValuePtr(sval);
}
}
}
+Object* ObjectImpl::factory(const SchemaObjectClass* type, BrokerProxyImpl* b, Buffer& buffer, bool prop, bool stat, bool managed)
+{
+ ObjectImpl* impl(new ObjectImpl(type, b, buffer, prop, stat, managed));
+ return new Object(impl);
+}
+
ObjectImpl::~ObjectImpl()
{
}
@@ -107,6 +112,22 @@ Value* ObjectImpl::getValue(const string& key) const
return 0;
}
+void ObjectImpl::invokeMethod(const string& methodName, const Value* inArgs, void* context) const
+{
+ if (broker != 0 && objectId.get() != 0)
+ broker->sendMethodRequest(objectId.get(), objectClass, methodName, inArgs, context);
+}
+
+void ObjectImpl::merge(const Object& from)
+{
+ for (map<string, ValuePtr>::const_iterator piter = from.impl->properties.begin();
+ piter != from.impl->properties.end(); piter++)
+ properties[piter->first] = piter->second;
+ for (map<string, ValuePtr>::const_iterator siter = from.impl->statistics.begin();
+ siter != from.impl->statistics.end(); siter++)
+ statistics[siter->first] = siter->second;
+}
+
void ObjectImpl::parsePresenceMasks(Buffer& buffer, set<string>& excludeList)
{
int propCount = objectClass->getPropertyCount();
@@ -143,7 +164,7 @@ void ObjectImpl::encodeManagedObjectData(qpid::framing::Buffer& buffer) const
buffer.putLongLong(lastUpdatedTime);
buffer.putLongLong(createTime);
buffer.putLongLong(destroyTime);
- objectId->encode(buffer);
+ objectId->impl->encode(buffer);
}
void ObjectImpl::encodeProperties(qpid::framing::Buffer& buffer) const
@@ -196,7 +217,7 @@ void ObjectImpl::encodeStatistics(qpid::framing::Buffer& buffer) const
// Wrappers
//==================================================================
-Object::Object(const SchemaObjectClass* type) : impl(new ObjectImpl(this, type)) {}
+Object::Object(const SchemaObjectClass* type) : impl(new ObjectImpl(type)) {}
Object::Object(ObjectImpl* i) : impl(i) {}
Object::Object(const Object& from) : impl(new ObjectImpl(*(from.impl))) {}
Object::~Object() { delete impl; }
@@ -204,5 +225,8 @@ void Object::destroy() { impl->destroy(); }
const ObjectId* Object::getObjectId() const { return impl->getObjectId(); }
void Object::setObjectId(ObjectId* oid) { impl->setObjectId(oid); }
const SchemaObjectClass* Object::getClass() const { return impl->getClass(); }
-Value* Object::getValue(char* key) const { return impl->getValue(key); }
+Value* Object::getValue(const char* key) const { return impl->getValue(key); }
+void Object::invokeMethod(const char* m, const Value* a, void* c) const { impl->invokeMethod(m, a, c); }
+bool Object::isDeleted() const { return impl->isDeleted(); }
+void Object::merge(const Object& from) { impl->merge(from); }
diff --git a/qpid/cpp/src/qmf/ObjectImpl.h b/qpid/cpp/src/qmf/engine/ObjectImpl.h
index d69979e0da..ddd20bfea2 100644
--- a/qpid/cpp/src/qmf/ObjectImpl.h
+++ b/qpid/cpp/src/qmf/engine/ObjectImpl.h
@@ -1,5 +1,5 @@
-#ifndef _QmfObjectImpl_
-#define _QmfObjectImpl_
+#ifndef _QmfEngineObjectImpl_
+#define _QmfEngineObjectImpl_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,8 +20,8 @@
* under the License.
*/
-#include <qmf/Object.h>
-#include <qmf/ObjectIdImpl.h>
+#include <qmf/engine/Object.h>
+#include <qmf/engine/ObjectIdImpl.h>
#include <map>
#include <set>
#include <string>
@@ -30,28 +30,38 @@
#include <qpid/sys/Mutex.h>
namespace qmf {
+namespace engine {
+
+ class BrokerProxyImpl;
+
+ typedef boost::shared_ptr<Object> ObjectPtr;
struct ObjectImpl {
- typedef boost::shared_ptr<ObjectImpl> Ptr;
typedef boost::shared_ptr<Value> ValuePtr;
- Object* envelope;
const SchemaObjectClass* objectClass;
- boost::shared_ptr<ObjectIdImpl> objectId;
+ BrokerProxyImpl* broker;
+ boost::shared_ptr<ObjectId> objectId;
uint64_t createTime;
uint64_t destroyTime;
uint64_t lastUpdatedTime;
mutable std::map<std::string, ValuePtr> properties;
mutable std::map<std::string, ValuePtr> statistics;
- ObjectImpl(Object* e, const SchemaObjectClass* type);
- ObjectImpl(const SchemaObjectClass* type, qpid::framing::Buffer& buffer, bool prop, bool stat, bool managed);
+ ObjectImpl(const SchemaObjectClass* type);
+ ObjectImpl(const SchemaObjectClass* type, BrokerProxyImpl* b, qpid::framing::Buffer& buffer,
+ bool prop, bool stat, bool managed);
+ static Object* factory(const SchemaObjectClass* type, BrokerProxyImpl* b, qpid::framing::Buffer& buffer,
+ bool prop, bool stat, bool managed);
~ObjectImpl();
void destroy();
- const ObjectId* getObjectId() const { return objectId.get() ? objectId->envelope : 0; }
- void setObjectId(ObjectId* oid) { objectId.reset(oid->impl); }
+ const ObjectId* getObjectId() const { return objectId.get(); }
+ void setObjectId(ObjectId* oid) { objectId.reset(oid); }
const SchemaObjectClass* getClass() const { return objectClass; }
Value* getValue(const std::string& key) const;
+ void invokeMethod(const std::string& methodName, const Value* inArgs, void* context) const;
+ bool isDeleted() const { return destroyTime != 0; }
+ void merge(const Object& from);
void parsePresenceMasks(qpid::framing::Buffer& buffer, std::set<std::string>& excludeList);
void encodeSchemaKey(qpid::framing::Buffer& buffer) const;
@@ -60,6 +70,7 @@ namespace qmf {
void encodeStatistics(qpid::framing::Buffer& buffer) const;
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/Protocol.cpp b/qpid/cpp/src/qmf/engine/Protocol.cpp
index 0a3beeb276..6061b70a8d 100644
--- a/qpid/cpp/src/qmf/Protocol.cpp
+++ b/qpid/cpp/src/qmf/engine/Protocol.cpp
@@ -17,11 +17,11 @@
* under the License.
*/
-#include "qmf/Protocol.h"
+#include "qmf/engine/Protocol.h"
#include "qpid/framing/Buffer.h"
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
using namespace qpid::framing;
diff --git a/qpid/cpp/src/qmf/Protocol.h b/qpid/cpp/src/qmf/engine/Protocol.h
index d5da08c1db..1cdfa60c84 100644
--- a/qpid/cpp/src/qmf/Protocol.h
+++ b/qpid/cpp/src/qmf/engine/Protocol.h
@@ -1,5 +1,5 @@
-#ifndef _QmfProtocol_
-#define _QmfProtocol_
+#ifndef _QmfEngineProtocol_
+#define _QmfEngineProtocol_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -29,6 +29,7 @@ namespace qpid {
}
namespace qmf {
+namespace engine {
class Protocol {
public:
@@ -62,6 +63,7 @@ namespace qmf {
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/QueryImpl.cpp b/qpid/cpp/src/qmf/engine/QueryImpl.cpp
index f75a9aa5d5..6f2beeee87 100644
--- a/qpid/cpp/src/qmf/QueryImpl.cpp
+++ b/qpid/cpp/src/qmf/engine/QueryImpl.cpp
@@ -17,13 +17,13 @@
* under the License.
*/
-#include "qmf/QueryImpl.h"
-#include "qmf/ObjectIdImpl.h"
+#include "qmf/engine/QueryImpl.h"
+#include "qmf/engine/ObjectIdImpl.h"
#include "qpid/framing/Buffer.h"
#include "qpid/framing/FieldTable.h"
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
using namespace qpid::framing;
bool QueryElementImpl::evaluate(const Object* /*object*/) const
@@ -45,6 +45,12 @@ QueryImpl::QueryImpl(Buffer& buffer)
// TODO
}
+Query* QueryImpl::factory(Buffer& buffer)
+{
+ QueryImpl* impl(new QueryImpl(buffer));
+ return new Query(impl);
+}
+
void QueryImpl::encode(Buffer& buffer) const
{
FieldTable ft;
@@ -69,14 +75,17 @@ QueryElement::QueryElement(const char* attrName, const Value* value, ValueOper o
QueryElement::QueryElement(QueryElementImpl* i) : impl(i) {}
QueryElement::~QueryElement() { delete impl; }
bool QueryElement::evaluate(const Object* object) const { return impl->evaluate(object); }
+
QueryExpression::QueryExpression(ExprOper oper, const QueryOperand* operand1, const QueryOperand* operand2) : impl(new QueryExpressionImpl(oper, operand1, operand2)) {}
QueryExpression::QueryExpression(QueryExpressionImpl* i) : impl(i) {}
QueryExpression::~QueryExpression() { delete impl; }
bool QueryExpression::evaluate(const Object* object) const { return impl->evaluate(object); }
+
Query::Query(const char* className, const char* packageName) : impl(new QueryImpl(className, packageName)) {}
Query::Query(const SchemaClassKey* key) : impl(new QueryImpl(key)) {}
Query::Query(const ObjectId* oid) : impl(new QueryImpl(oid)) {}
Query::Query(QueryImpl* i) : impl(i) {}
+Query::Query(const Query& from) : impl(new QueryImpl(*(from.impl))) {}
Query::~Query() { delete impl; }
void Query::setSelect(const QueryOperand* criterion) { impl->setSelect(criterion); }
void Query::setLimit(uint32_t maxResults) { impl->setLimit(maxResults); }
diff --git a/qpid/cpp/src/qmf/QueryImpl.h b/qpid/cpp/src/qmf/engine/QueryImpl.h
index 4a56a457c0..2c64c6739c 100644
--- a/qpid/cpp/src/qmf/QueryImpl.h
+++ b/qpid/cpp/src/qmf/engine/QueryImpl.h
@@ -1,5 +1,5 @@
-#ifndef _QmfQueryImpl_
-#define _QmfQueryImpl_
+#ifndef _QmfEngineQueryImpl_
+#define _QmfEngineQueryImpl_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,8 +20,8 @@
* under the License.
*/
-#include "qmf/Query.h"
-#include "qmf/Schema.h"
+#include "qmf/engine/Query.h"
+#include "qmf/engine/Schema.h"
#include <string>
#include <boost/shared_ptr.hpp>
@@ -32,41 +32,39 @@ namespace qpid {
}
namespace qmf {
+namespace engine {
struct QueryElementImpl {
- QueryElementImpl(const std::string& a, const Value* v, ValueOper o) :
- envelope(new QueryElement(this)), attrName(a), value(v), oper(o) {}
+ QueryElementImpl(const std::string& a, const Value* v, ValueOper o) : attrName(a), value(v), oper(o) {}
~QueryElementImpl() {}
bool evaluate(const Object* object) const;
- QueryElement* envelope;
std::string attrName;
const Value* value;
ValueOper oper;
};
struct QueryExpressionImpl {
- QueryExpressionImpl(ExprOper o, const QueryOperand* operand1, const QueryOperand* operand2) :
- envelope(new QueryExpression(this)), oper(o), left(operand1), right(operand2) {}
+ QueryExpressionImpl(ExprOper o, const QueryOperand* operand1, const QueryOperand* operand2) : oper(o), left(operand1), right(operand2) {}
~QueryExpressionImpl() {}
bool evaluate(const Object* object) const;
- QueryExpression* envelope;
ExprOper oper;
const QueryOperand* left;
const QueryOperand* right;
};
struct QueryImpl {
- QueryImpl(Query* e) : envelope(e), select(0) {}
- QueryImpl(const std::string& c, const std::string& p) :
- envelope(new Query(this)), packageName(p), className(c) {}
- QueryImpl(const SchemaClassKey* key) :
- envelope(new Query(this)), packageName(key->getPackageName()), className(key->getClassName()) {}
- QueryImpl(const ObjectId* oid) :
- envelope(new Query(this)), oid(new ObjectId(*oid)) {}
+ // Constructors mapped to public
+ QueryImpl(const std::string& c, const std::string& p) : packageName(p), className(c), select(0), resultLimit(0) {}
+ QueryImpl(const SchemaClassKey* key) : packageName(key->getPackageName()), className(key->getClassName()), select(0), resultLimit(0) {}
+ QueryImpl(const ObjectId* oid) : oid(new ObjectId(*oid)), select(0), resultLimit(0) {}
+
+ // Factory constructors
QueryImpl(qpid::framing::Buffer& buffer);
+
~QueryImpl() {};
+ static Query* factory(qpid::framing::Buffer& buffer);
void setSelect(const QueryOperand* criterion) { select = criterion; }
void setLimit(uint32_t maxResults) { resultLimit = maxResults; }
@@ -88,7 +86,6 @@ namespace qmf {
void encode(qpid::framing::Buffer& buffer) const;
- Query* envelope;
std::string packageName;
std::string className;
boost::shared_ptr<ObjectId> oid;
@@ -98,5 +95,6 @@ namespace qmf {
bool orderDecreasing;
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/ResilientConnection.cpp b/qpid/cpp/src/qmf/engine/ResilientConnection.cpp
index 7ec03cf4da..9502130288 100644
--- a/qpid/cpp/src/qmf/ResilientConnection.cpp
+++ b/qpid/cpp/src/qmf/engine/ResilientConnection.cpp
@@ -17,9 +17,9 @@
* under the License.
*/
-#include "qmf/ResilientConnection.h"
-#include "qmf/MessageImpl.h"
-#include "qmf/ConnectionSettingsImpl.h"
+#include "qmf/engine/ResilientConnection.h"
+#include "qmf/engine/MessageImpl.h"
+#include "qmf/engine/ConnectionSettingsImpl.h"
#include <qpid/client/Connection.h>
#include <qpid/client/Session.h>
#include <qpid/client/MessageListener.h>
@@ -38,13 +38,15 @@
#include <vector>
#include <set>
#include <boost/intrusive_ptr.hpp>
+#include <boost/noncopyable.hpp>
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
using namespace qpid;
using qpid::sys::Mutex;
namespace qmf {
+namespace engine {
struct ResilientConnectionEventImpl {
ResilientConnectionEvent::EventKind kind;
void* sessionContext;
@@ -64,20 +66,19 @@ namespace qmf {
client::Connection& connection;
client::Session session;
client::SubscriptionManager* subscriptions;
+ string userId;
void* userContext;
vector<string> dests;
qpid::sys::Thread thread;
- RCSession(ResilientConnectionImpl& ci, const string& n, client::Connection& c, void* uc) :
- connImpl(ci), name(n), connection(c), session(connection.newSession(name)),
- subscriptions(new client::SubscriptionManager(session)), userContext(uc), thread(*this) {}
+ RCSession(ResilientConnectionImpl& ci, const string& n, client::Connection& c, void* uc);
~RCSession();
void received(client::Message& msg);
void run();
void stop();
};
- class ResilientConnectionImpl : public qpid::sys::Runnable {
+ class ResilientConnectionImpl : public qpid::sys::Runnable, public boost::noncopyable {
public:
ResilientConnectionImpl(const ConnectionSettings& settings);
~ResilientConnectionImpl();
@@ -87,7 +88,7 @@ namespace qmf {
void popEvent();
bool createSession(const char* name, void* sessionContext, SessionHandle& handle);
void destroySession(SessionHandle handle);
- void sendMessage(SessionHandle handle, qmf::Message& message);
+ void sendMessage(SessionHandle handle, qmf::engine::Message& message);
void declareQueue(SessionHandle handle, char* queue);
void deleteQueue(SessionHandle handle, char* queue);
void bind(SessionHandle handle, char* exchange, char* queue, char* key);
@@ -120,6 +121,7 @@ namespace qmf {
set<RCSession::Ptr> sessions;
};
}
+}
ResilientConnectionEvent ResilientConnectionEventImpl::copy()
{
@@ -134,6 +136,14 @@ ResilientConnectionEvent ResilientConnectionEventImpl::copy()
return item;
}
+RCSession::RCSession(ResilientConnectionImpl& ci, const string& n, client::Connection& c, void* uc) :
+ connImpl(ci), name(n), connection(c), session(connection.newSession(name)),
+ subscriptions(new client::SubscriptionManager(session)), userContext(uc), thread(*this)
+{
+ const qpid::client::ConnectionSettings& operSettings = connection.getNegotiatedSettings();
+ userId = operSettings.username;
+}
+
RCSession::~RCSession()
{
subscriptions->stop();
@@ -158,18 +168,23 @@ void RCSession::stop()
void RCSession::received(client::Message& msg)
{
- qmf::MessageImpl qmsg;
+ MessageImpl qmsg;
qmsg.body = msg.getData();
- qpid::framing::MessageProperties p = msg.getMessageProperties();
- if (p.hasReplyTo()) {
- const qpid::framing::ReplyTo& rt = p.getReplyTo();
+ qpid::framing::DeliveryProperties dp = msg.getDeliveryProperties();
+ if (dp.hasRoutingKey()) {
+ qmsg.routingKey = dp.getRoutingKey();
+ }
+
+ qpid::framing::MessageProperties mp = msg.getMessageProperties();
+ if (mp.hasReplyTo()) {
+ const qpid::framing::ReplyTo& rt = mp.getReplyTo();
qmsg.replyExchange = rt.getExchange();
qmsg.replyKey = rt.getRoutingKey();
}
- if (p.hasUserId()) {
- qmsg.userId = p.getUserId();
+ if (mp.hasUserId()) {
+ qmsg.userId = mp.getUserId();
}
connImpl.EnqueueEvent(ResilientConnectionEvent::RECV, userContext, qmsg);
@@ -244,7 +259,7 @@ void ResilientConnectionImpl::destroySession(SessionHandle handle)
}
}
-void ResilientConnectionImpl::sendMessage(SessionHandle handle, qmf::Message& message)
+void ResilientConnectionImpl::sendMessage(SessionHandle handle, qmf::engine::Message& message)
{
Mutex::ScopedLock _lock(lock);
RCSession::Ptr sess = RCSession::Ptr((RCSession*) handle.impl);
@@ -253,6 +268,8 @@ void ResilientConnectionImpl::sendMessage(SessionHandle handle, qmf::Message& me
string data(message.body, message.length);
msg.getDeliveryProperties().setRoutingKey(message.routingKey);
msg.getMessageProperties().setReplyTo(qpid::framing::ReplyTo(message.replyExchange, message.replyKey));
+ if (settings.impl->getSendUserId())
+ msg.getMessageProperties().setUserId(sess->userId);
msg.setData(data);
try {
@@ -383,7 +400,7 @@ void ResilientConnectionImpl::sessionClosed(RCSession*)
void ResilientConnectionImpl::EnqueueEvent(ResilientConnectionEvent::EventKind kind,
void* sessionContext,
- const qmf::MessageImpl& message,
+ const MessageImpl& message,
const string& errorText)
{
Mutex::ScopedLock _lock(lock);
@@ -440,7 +457,7 @@ void ResilientConnection::destroySession(SessionHandle handle)
impl->destroySession(handle);
}
-void ResilientConnection::sendMessage(SessionHandle handle, qmf::Message& message)
+void ResilientConnection::sendMessage(SessionHandle handle, qmf::engine::Message& message)
{
impl->sendMessage(handle, message);
}
diff --git a/qpid/cpp/src/qmf/SchemaImpl.cpp b/qpid/cpp/src/qmf/engine/SchemaImpl.cpp
index 3eb14c3952..e366a66826 100644
--- a/qpid/cpp/src/qmf/SchemaImpl.cpp
+++ b/qpid/cpp/src/qmf/engine/SchemaImpl.cpp
@@ -17,7 +17,7 @@
* under the License.
*/
-#include "qmf/SchemaImpl.h"
+#include "qmf/engine/SchemaImpl.h"
#include <qpid/framing/Buffer.h>
#include <qpid/framing/FieldTable.h>
#include <qpid/framing/Uuid.h>
@@ -26,7 +26,7 @@
#include <vector>
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
using qpid::framing::Buffer;
using qpid::framing::FieldTable;
using qpid::framing::Uuid;
@@ -81,7 +81,7 @@ bool SchemaHash::operator>(const SchemaHash& other) const
return ::memcmp(&hash, &other.hash, 16) > 0;
}
-SchemaArgumentImpl::SchemaArgumentImpl(Buffer& buffer) : envelope(new SchemaArgument(this))
+SchemaArgumentImpl::SchemaArgumentImpl(Buffer& buffer)
{
FieldTable map;
map.decode(buffer);
@@ -99,6 +99,12 @@ SchemaArgumentImpl::SchemaArgumentImpl(Buffer& buffer) : envelope(new SchemaArgu
dir = DIR_IN_OUT;
}
+SchemaArgument* SchemaArgumentImpl::factory(Buffer& buffer)
+{
+ SchemaArgumentImpl* impl(new SchemaArgumentImpl(buffer));
+ return new SchemaArgument(impl);
+}
+
void SchemaArgumentImpl::encode(Buffer& buffer) const
{
FieldTable map;
@@ -128,7 +134,7 @@ void SchemaArgumentImpl::updateHash(SchemaHash& hash) const
hash.update(description);
}
-SchemaMethodImpl::SchemaMethodImpl(Buffer& buffer) : envelope(new SchemaMethod(this))
+SchemaMethodImpl::SchemaMethodImpl(Buffer& buffer)
{
FieldTable map;
int argCount;
@@ -139,11 +145,17 @@ SchemaMethodImpl::SchemaMethodImpl(Buffer& buffer) : envelope(new SchemaMethod(t
description = map.getAsString("desc");
for (int idx = 0; idx < argCount; idx++) {
- SchemaArgumentImpl* arg = new SchemaArgumentImpl(buffer);
- addArgument(*arg->envelope);
+ SchemaArgument* arg = SchemaArgumentImpl::factory(buffer);
+ addArgument(arg);
}
}
+SchemaMethod* SchemaMethodImpl::factory(Buffer& buffer)
+{
+ SchemaMethodImpl* impl(new SchemaMethodImpl(buffer));
+ return new SchemaMethod(impl);
+}
+
void SchemaMethodImpl::encode(Buffer& buffer) const
{
FieldTable map;
@@ -154,23 +166,23 @@ void SchemaMethodImpl::encode(Buffer& buffer) const
map.setString("desc", description);
map.encode(buffer);
- for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+ for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
iter != arguments.end(); iter++)
- (*iter)->encode(buffer);
+ (*iter)->impl->encode(buffer);
}
-void SchemaMethodImpl::addArgument(const SchemaArgument& argument)
+void SchemaMethodImpl::addArgument(const SchemaArgument* argument)
{
- arguments.push_back(argument.impl);
+ arguments.push_back(argument);
}
const SchemaArgument* SchemaMethodImpl::getArgument(int idx) const
{
int count = 0;
- for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+ for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
iter != arguments.end(); iter++, count++)
if (idx == count)
- return (*iter)->envelope;
+ return (*iter);
return 0;
}
@@ -178,12 +190,12 @@ void SchemaMethodImpl::updateHash(SchemaHash& hash) const
{
hash.update(name);
hash.update(description);
- for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+ for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
iter != arguments.end(); iter++)
- (*iter)->updateHash(hash);
+ (*iter)->impl->updateHash(hash);
}
-SchemaPropertyImpl::SchemaPropertyImpl(Buffer& buffer) : envelope(new SchemaProperty(this))
+SchemaPropertyImpl::SchemaPropertyImpl(Buffer& buffer)
{
FieldTable map;
map.decode(buffer);
@@ -197,6 +209,12 @@ SchemaPropertyImpl::SchemaPropertyImpl(Buffer& buffer) : envelope(new SchemaProp
description = map.getAsString("desc");
}
+SchemaProperty* SchemaPropertyImpl::factory(Buffer& buffer)
+{
+ SchemaPropertyImpl* impl(new SchemaPropertyImpl(buffer));
+ return new SchemaProperty(impl);
+}
+
void SchemaPropertyImpl::encode(Buffer& buffer) const
{
FieldTable map;
@@ -225,7 +243,7 @@ void SchemaPropertyImpl::updateHash(SchemaHash& hash) const
hash.update(description);
}
-SchemaStatisticImpl::SchemaStatisticImpl(Buffer& buffer) : envelope(new SchemaStatistic(this))
+SchemaStatisticImpl::SchemaStatisticImpl(Buffer& buffer)
{
FieldTable map;
map.decode(buffer);
@@ -236,6 +254,12 @@ SchemaStatisticImpl::SchemaStatisticImpl(Buffer& buffer) : envelope(new SchemaSt
description = map.getAsString("desc");
}
+SchemaStatistic* SchemaStatisticImpl::factory(Buffer& buffer)
+{
+ SchemaStatisticImpl* impl(new SchemaStatisticImpl(buffer));
+ return new SchemaStatistic(impl);
+}
+
void SchemaStatisticImpl::encode(Buffer& buffer) const
{
FieldTable map;
@@ -258,16 +282,26 @@ void SchemaStatisticImpl::updateHash(SchemaHash& hash) const
hash.update(description);
}
-SchemaClassKeyImpl::SchemaClassKeyImpl(const string& p, const string& n, const SchemaHash& h) :
- envelope(new SchemaClassKey(this)), package(p), name(n), hash(h) {}
+SchemaClassKeyImpl::SchemaClassKeyImpl(const string& p, const string& n, const SchemaHash& h) : package(p), name(n), hash(h) {}
-SchemaClassKeyImpl::SchemaClassKeyImpl(Buffer& buffer) :
- envelope(new SchemaClassKey(this)), package(packageContainer), name(nameContainer), hash(hashContainer)
+SchemaClassKeyImpl::SchemaClassKeyImpl(Buffer& buffer) : package(packageContainer), name(nameContainer), hash(hashContainer)
{
buffer.getShortString(packageContainer);
buffer.getShortString(nameContainer);
hashContainer.decode(buffer);
-}
+}
+
+SchemaClassKey* SchemaClassKeyImpl::factory(const string& package, const string& name, const SchemaHash& hash)
+{
+ SchemaClassKeyImpl* impl(new SchemaClassKeyImpl(package, name, hash));
+ return new SchemaClassKey(impl);
+}
+
+SchemaClassKey* SchemaClassKeyImpl::factory(Buffer& buffer)
+{
+ SchemaClassKeyImpl* impl(new SchemaClassKeyImpl(buffer));
+ return new SchemaClassKey(impl);
+}
void SchemaClassKeyImpl::encode(Buffer& buffer) const
{
@@ -292,16 +326,16 @@ bool SchemaClassKeyImpl::operator<(const SchemaClassKeyImpl& other) const
return hash < other.hash;
}
-string SchemaClassKeyImpl::str() const
+const string& SchemaClassKeyImpl::str() const
{
Uuid printableHash(hash.get());
stringstream str;
str << package << ":" << name << "(" << printableHash << ")";
- return str.str();
+ repr = str.str();
+ return repr;
}
-SchemaObjectClassImpl::SchemaObjectClassImpl(Buffer& buffer) :
- envelope(new SchemaObjectClass(this)), hasHash(true), classKey(package, name, hash)
+SchemaObjectClassImpl::SchemaObjectClassImpl(Buffer& buffer) : hasHash(true), classKey(SchemaClassKeyImpl::factory(package, name, hash))
{
buffer.getShortString(package);
buffer.getShortString(name);
@@ -313,21 +347,27 @@ SchemaObjectClassImpl::SchemaObjectClassImpl(Buffer& buffer) :
uint16_t methodCount = buffer.getShort();
for (uint16_t idx = 0; idx < propCount; idx++) {
- SchemaPropertyImpl* property = new SchemaPropertyImpl(buffer);
- addProperty(*property->envelope);
+ const SchemaProperty* property = SchemaPropertyImpl::factory(buffer);
+ addProperty(property);
}
for (uint16_t idx = 0; idx < statCount; idx++) {
- SchemaStatisticImpl* statistic = new SchemaStatisticImpl(buffer);
- addStatistic(*statistic->envelope);
+ const SchemaStatistic* statistic = SchemaStatisticImpl::factory(buffer);
+ addStatistic(statistic);
}
for (uint16_t idx = 0; idx < methodCount; idx++) {
- SchemaMethodImpl* method = new SchemaMethodImpl(buffer);
- addMethod(*method->envelope);
+ SchemaMethod* method = SchemaMethodImpl::factory(buffer);
+ addMethod(method);
}
}
+SchemaObjectClass* SchemaObjectClassImpl::factory(Buffer& buffer)
+{
+ SchemaObjectClassImpl* impl(new SchemaObjectClassImpl(buffer));
+ return new SchemaObjectClass(impl);
+}
+
void SchemaObjectClassImpl::encode(Buffer& buffer) const
{
buffer.putOctet((uint8_t) CLASS_OBJECT);
@@ -339,15 +379,15 @@ void SchemaObjectClassImpl::encode(Buffer& buffer) const
buffer.putShort((uint16_t) statistics.size());
buffer.putShort((uint16_t) methods.size());
- for (vector<SchemaPropertyImpl*>::const_iterator iter = properties.begin();
+ for (vector<const SchemaProperty*>::const_iterator iter = properties.begin();
iter != properties.end(); iter++)
- (*iter)->encode(buffer);
- for (vector<SchemaStatisticImpl*>::const_iterator iter = statistics.begin();
+ (*iter)->impl->encode(buffer);
+ for (vector<const SchemaStatistic*>::const_iterator iter = statistics.begin();
iter != statistics.end(); iter++)
- (*iter)->encode(buffer);
- for (vector<SchemaMethodImpl*>::const_iterator iter = methods.begin();
+ (*iter)->impl->encode(buffer);
+ for (vector<const SchemaMethod*>::const_iterator iter = methods.begin();
iter != methods.end(); iter++)
- (*iter)->encode(buffer);
+ (*iter)->impl->encode(buffer);
}
const SchemaClassKey* SchemaObjectClassImpl::getClassKey() const
@@ -356,67 +396,66 @@ const SchemaClassKey* SchemaObjectClassImpl::getClassKey() const
hasHash = true;
hash.update(package);
hash.update(name);
- for (vector<SchemaPropertyImpl*>::const_iterator iter = properties.begin();
+ for (vector<const SchemaProperty*>::const_iterator iter = properties.begin();
iter != properties.end(); iter++)
- (*iter)->updateHash(hash);
- for (vector<SchemaStatisticImpl*>::const_iterator iter = statistics.begin();
+ (*iter)->impl->updateHash(hash);
+ for (vector<const SchemaStatistic*>::const_iterator iter = statistics.begin();
iter != statistics.end(); iter++)
- (*iter)->updateHash(hash);
- for (vector<SchemaMethodImpl*>::const_iterator iter = methods.begin();
+ (*iter)->impl->updateHash(hash);
+ for (vector<const SchemaMethod*>::const_iterator iter = methods.begin();
iter != methods.end(); iter++)
- (*iter)->updateHash(hash);
+ (*iter)->impl->updateHash(hash);
}
- return classKey.envelope;
+ return classKey.get();
}
-void SchemaObjectClassImpl::addProperty(const SchemaProperty& property)
+void SchemaObjectClassImpl::addProperty(const SchemaProperty* property)
{
- properties.push_back(property.impl);
+ properties.push_back(property);
}
-void SchemaObjectClassImpl::addStatistic(const SchemaStatistic& statistic)
+void SchemaObjectClassImpl::addStatistic(const SchemaStatistic* statistic)
{
- statistics.push_back(statistic.impl);
+ statistics.push_back(statistic);
}
-void SchemaObjectClassImpl::addMethod(const SchemaMethod& method)
+void SchemaObjectClassImpl::addMethod(const SchemaMethod* method)
{
- methods.push_back(method.impl);
+ methods.push_back(method);
}
const SchemaProperty* SchemaObjectClassImpl::getProperty(int idx) const
{
int count = 0;
- for (vector<SchemaPropertyImpl*>::const_iterator iter = properties.begin();
+ for (vector<const SchemaProperty*>::const_iterator iter = properties.begin();
iter != properties.end(); iter++, count++)
if (idx == count)
- return (*iter)->envelope;
+ return *iter;
return 0;
}
const SchemaStatistic* SchemaObjectClassImpl::getStatistic(int idx) const
{
int count = 0;
- for (vector<SchemaStatisticImpl*>::const_iterator iter = statistics.begin();
+ for (vector<const SchemaStatistic*>::const_iterator iter = statistics.begin();
iter != statistics.end(); iter++, count++)
if (idx == count)
- return (*iter)->envelope;
+ return *iter;
return 0;
}
const SchemaMethod* SchemaObjectClassImpl::getMethod(int idx) const
{
int count = 0;
- for (vector<SchemaMethodImpl*>::const_iterator iter = methods.begin();
+ for (vector<const SchemaMethod*>::const_iterator iter = methods.begin();
iter != methods.end(); iter++, count++)
if (idx == count)
- return (*iter)->envelope;
+ return *iter;
return 0;
}
-SchemaEventClassImpl::SchemaEventClassImpl(Buffer& buffer) :
- envelope(new SchemaEventClass(this)), hasHash(true), classKey(package, name, hash)
+SchemaEventClassImpl::SchemaEventClassImpl(Buffer& buffer) : hasHash(true), classKey(SchemaClassKeyImpl::factory(package, name, hash))
{
buffer.getShortString(package);
buffer.getShortString(name);
@@ -426,11 +465,17 @@ SchemaEventClassImpl::SchemaEventClassImpl(Buffer& buffer) :
uint16_t argCount = buffer.getShort();
for (uint16_t idx = 0; idx < argCount; idx++) {
- SchemaArgumentImpl* argument = new SchemaArgumentImpl(buffer);
- addArgument(*argument->envelope);
+ SchemaArgument* argument = SchemaArgumentImpl::factory(buffer);
+ addArgument(argument);
}
}
+SchemaEventClass* SchemaEventClassImpl::factory(Buffer& buffer)
+{
+ SchemaEventClassImpl* impl(new SchemaEventClassImpl(buffer));
+ return new SchemaEventClass(impl);
+}
+
void SchemaEventClassImpl::encode(Buffer& buffer) const
{
buffer.putOctet((uint8_t) CLASS_EVENT);
@@ -439,9 +484,9 @@ void SchemaEventClassImpl::encode(Buffer& buffer) const
hash.encode(buffer);
buffer.putShort((uint16_t) arguments.size());
- for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+ for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
iter != arguments.end(); iter++)
- (*iter)->encode(buffer);
+ (*iter)->impl->encode(buffer);
}
const SchemaClassKey* SchemaEventClassImpl::getClassKey() const
@@ -450,25 +495,25 @@ const SchemaClassKey* SchemaEventClassImpl::getClassKey() const
hasHash = true;
hash.update(package);
hash.update(name);
- for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+ for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
iter != arguments.end(); iter++)
- (*iter)->updateHash(hash);
+ (*iter)->impl->updateHash(hash);
}
- return classKey.envelope;
+ return classKey.get();
}
-void SchemaEventClassImpl::addArgument(const SchemaArgument& argument)
+void SchemaEventClassImpl::addArgument(const SchemaArgument* argument)
{
- arguments.push_back(argument.impl);
+ arguments.push_back(argument);
}
const SchemaArgument* SchemaEventClassImpl::getArgument(int idx) const
{
int count = 0;
- for (vector<SchemaArgumentImpl*>::const_iterator iter = arguments.begin();
+ for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin();
iter != arguments.end(); iter++, count++)
if (idx == count)
- return (*iter)->envelope;
+ return (*iter);
return 0;
}
@@ -477,8 +522,9 @@ const SchemaArgument* SchemaEventClassImpl::getArgument(int idx) const
// Wrappers
//==================================================================
-SchemaArgument::SchemaArgument(const char* name, Typecode typecode) { impl = new SchemaArgumentImpl(this, name, typecode); }
+SchemaArgument::SchemaArgument(const char* name, Typecode typecode) { impl = new SchemaArgumentImpl(name, typecode); }
SchemaArgument::SchemaArgument(SchemaArgumentImpl* i) : impl(i) {}
+SchemaArgument::SchemaArgument(const SchemaArgument& from) : impl(new SchemaArgumentImpl(*(from.impl))) {}
SchemaArgument::~SchemaArgument() { delete impl; }
void SchemaArgument::setDirection(Direction dir) { impl->setDirection(dir); }
void SchemaArgument::setUnit(const char* val) { impl->setUnit(val); }
@@ -488,17 +534,21 @@ Typecode SchemaArgument::getType() const { return impl->getType(); }
Direction SchemaArgument::getDirection() const { return impl->getDirection(); }
const char* SchemaArgument::getUnit() const { return impl->getUnit().c_str(); }
const char* SchemaArgument::getDesc() const { return impl->getDesc().c_str(); }
-SchemaMethod::SchemaMethod(const char* name) { impl = new SchemaMethodImpl(this, name); }
+
+SchemaMethod::SchemaMethod(const char* name) : impl(new SchemaMethodImpl(name)) {}
SchemaMethod::SchemaMethod(SchemaMethodImpl* i) : impl(i) {}
+SchemaMethod::SchemaMethod(const SchemaMethod& from) : impl(new SchemaMethodImpl(*(from.impl))) {}
SchemaMethod::~SchemaMethod() { delete impl; }
-void SchemaMethod::addArgument(const SchemaArgument& argument) { impl->addArgument(argument); }
+void SchemaMethod::addArgument(const SchemaArgument* argument) { impl->addArgument(argument); }
void SchemaMethod::setDesc(const char* desc) { impl->setDesc(desc); }
const char* SchemaMethod::getName() const { return impl->getName().c_str(); }
const char* SchemaMethod::getDesc() const { return impl->getDesc().c_str(); }
int SchemaMethod::getArgumentCount() const { return impl->getArgumentCount(); }
const SchemaArgument* SchemaMethod::getArgument(int idx) const { return impl->getArgument(idx); }
-SchemaProperty::SchemaProperty(const char* name, Typecode typecode) { impl = new SchemaPropertyImpl(this, name, typecode); }
+
+SchemaProperty::SchemaProperty(const char* name, Typecode typecode) : impl(new SchemaPropertyImpl(name, typecode)) {}
SchemaProperty::SchemaProperty(SchemaPropertyImpl* i) : impl(i) {}
+SchemaProperty::SchemaProperty(const SchemaProperty& from) : impl(new SchemaPropertyImpl(*(from.impl))) {}
SchemaProperty::~SchemaProperty() { delete impl; }
void SchemaProperty::setAccess(Access access) { impl->setAccess(access); }
void SchemaProperty::setIndex(bool val) { impl->setIndex(val); }
@@ -512,8 +562,10 @@ bool SchemaProperty::isIndex() const { return impl->isIndex(); }
bool SchemaProperty::isOptional() const { return impl->isOptional(); }
const char* SchemaProperty::getUnit() const { return impl->getUnit().c_str(); }
const char* SchemaProperty::getDesc() const { return impl->getDesc().c_str(); }
-SchemaStatistic::SchemaStatistic(const char* name, Typecode typecode) { impl = new SchemaStatisticImpl(this, name, typecode); }
+
+SchemaStatistic::SchemaStatistic(const char* name, Typecode typecode) : impl(new SchemaStatisticImpl(name, typecode)) {}
SchemaStatistic::SchemaStatistic(SchemaStatisticImpl* i) : impl(i) {}
+SchemaStatistic::SchemaStatistic(const SchemaStatistic& from) : impl(new SchemaStatisticImpl(*(from.impl))) {}
SchemaStatistic::~SchemaStatistic() { delete impl; }
void SchemaStatistic::setUnit(const char* val) { impl->setUnit(val); }
void SchemaStatistic::setDesc(const char* desc) { impl->setDesc(desc); }
@@ -521,17 +573,24 @@ const char* SchemaStatistic::getName() const { return impl->getName().c_str(); }
Typecode SchemaStatistic::getType() const { return impl->getType(); }
const char* SchemaStatistic::getUnit() const { return impl->getUnit().c_str(); }
const char* SchemaStatistic::getDesc() const { return impl->getDesc().c_str(); }
+
SchemaClassKey::SchemaClassKey(SchemaClassKeyImpl* i) : impl(i) {}
+SchemaClassKey::SchemaClassKey(const SchemaClassKey& from) : impl(new SchemaClassKeyImpl(*(from.impl))) {}
SchemaClassKey::~SchemaClassKey() { delete impl; }
const char* SchemaClassKey::getPackageName() const { return impl->getPackageName().c_str(); }
const char* SchemaClassKey::getClassName() const { return impl->getClassName().c_str(); }
const uint8_t* SchemaClassKey::getHash() const { return impl->getHash(); }
-SchemaObjectClass::SchemaObjectClass(const char* package, const char* name) { impl = new SchemaObjectClassImpl(this, package, name); }
+const char* SchemaClassKey::asString() const { return impl->str().c_str(); }
+bool SchemaClassKey::operator==(const SchemaClassKey& other) const { return *impl == *(other.impl); }
+bool SchemaClassKey::operator<(const SchemaClassKey& other) const { return *impl < *(other.impl); }
+
+SchemaObjectClass::SchemaObjectClass(const char* package, const char* name) : impl(new SchemaObjectClassImpl(package, name)) {}
SchemaObjectClass::SchemaObjectClass(SchemaObjectClassImpl* i) : impl(i) {}
+SchemaObjectClass::SchemaObjectClass(const SchemaObjectClass& from) : impl(new SchemaObjectClassImpl(*(from.impl))) {}
SchemaObjectClass::~SchemaObjectClass() { delete impl; }
-void SchemaObjectClass::addProperty(const SchemaProperty& property) { impl->addProperty(property); }
-void SchemaObjectClass::addStatistic(const SchemaStatistic& statistic) { impl->addStatistic(statistic); }
-void SchemaObjectClass::addMethod(const SchemaMethod& method) { impl->addMethod(method); }
+void SchemaObjectClass::addProperty(const SchemaProperty* property) { impl->addProperty(property); }
+void SchemaObjectClass::addStatistic(const SchemaStatistic* statistic) { impl->addStatistic(statistic); }
+void SchemaObjectClass::addMethod(const SchemaMethod* method) { impl->addMethod(method); }
const SchemaClassKey* SchemaObjectClass::getClassKey() const { return impl->getClassKey(); }
int SchemaObjectClass::getPropertyCount() const { return impl->getPropertyCount(); }
int SchemaObjectClass::getStatisticCount() const { return impl->getStatisticCount(); }
@@ -539,10 +598,12 @@ int SchemaObjectClass::getMethodCount() const { return impl->getMethodCount(); }
const SchemaProperty* SchemaObjectClass::getProperty(int idx) const { return impl->getProperty(idx); }
const SchemaStatistic* SchemaObjectClass::getStatistic(int idx) const { return impl->getStatistic(idx); }
const SchemaMethod* SchemaObjectClass::getMethod(int idx) const { return impl->getMethod(idx); }
-SchemaEventClass::SchemaEventClass(const char* package, const char* name) { impl = new SchemaEventClassImpl(this, package, name); }
+
+SchemaEventClass::SchemaEventClass(const char* package, const char* name) : impl(new SchemaEventClassImpl(package, name)) {}
SchemaEventClass::SchemaEventClass(SchemaEventClassImpl* i) : impl(i) {}
+SchemaEventClass::SchemaEventClass(const SchemaEventClass& from) : impl(new SchemaEventClassImpl(*(from.impl))) {}
SchemaEventClass::~SchemaEventClass() { delete impl; }
-void SchemaEventClass::addArgument(const SchemaArgument& argument) { impl->addArgument(argument); }
+void SchemaEventClass::addArgument(const SchemaArgument* argument) { impl->addArgument(argument); }
void SchemaEventClass::setDesc(const char* desc) { impl->setDesc(desc); }
const SchemaClassKey* SchemaEventClass::getClassKey() const { return impl->getClassKey(); }
int SchemaEventClass::getArgumentCount() const { return impl->getArgumentCount(); }
diff --git a/qpid/cpp/src/qmf/SchemaImpl.h b/qpid/cpp/src/qmf/engine/SchemaImpl.h
index 035d99aecd..af3a1d98e4 100644
--- a/qpid/cpp/src/qmf/SchemaImpl.h
+++ b/qpid/cpp/src/qmf/engine/SchemaImpl.h
@@ -1,5 +1,5 @@
-#ifndef _QmfSchemaImpl_
-#define _QmfSchemaImpl_
+#ifndef _QmfEngineSchemaImpl_
+#define _QmfEngineSchemaImpl_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,13 +20,13 @@
* under the License.
*/
-#include "qmf/Schema.h"
-#include <boost/shared_ptr.hpp>
+#include "qmf/engine/Schema.h"
#include <string>
#include <vector>
#include <qpid/framing/Buffer.h>
namespace qmf {
+namespace engine {
// TODO: Destructors for schema classes
// TODO: Add "frozen" attribute for schema classes so they can't be modified after
@@ -52,16 +52,15 @@ namespace qmf {
};
struct SchemaArgumentImpl {
- SchemaArgument* envelope;
std::string name;
Typecode typecode;
Direction dir;
std::string unit;
std::string description;
- SchemaArgumentImpl(SchemaArgument* e, const char* n, Typecode t) :
- envelope(e), name(n), typecode(t), dir(DIR_IN) {}
+ SchemaArgumentImpl(const char* n, Typecode t) : name(n), typecode(t), dir(DIR_IN) {}
SchemaArgumentImpl(qpid::framing::Buffer& buffer);
+ static SchemaArgument* factory(qpid::framing::Buffer& buffer);
void encode(qpid::framing::Buffer& buffer) const;
void setDirection(Direction d) { dir = d; }
void setUnit(const char* val) { unit = val; }
@@ -75,15 +74,15 @@ namespace qmf {
};
struct SchemaMethodImpl {
- SchemaMethod* envelope;
std::string name;
std::string description;
- std::vector<SchemaArgumentImpl*> arguments;
+ std::vector<const SchemaArgument*> arguments;
- SchemaMethodImpl(SchemaMethod* e, const char* n) : envelope(e), name(n) {}
+ SchemaMethodImpl(const char* n) : name(n) {}
SchemaMethodImpl(qpid::framing::Buffer& buffer);
+ static SchemaMethod* factory(qpid::framing::Buffer& buffer);
void encode(qpid::framing::Buffer& buffer) const;
- void addArgument(const SchemaArgument& argument);
+ void addArgument(const SchemaArgument* argument);
void setDesc(const char* desc) { description = desc; }
const std::string& getName() const { return name; }
const std::string& getDesc() const { return description; }
@@ -93,7 +92,6 @@ namespace qmf {
};
struct SchemaPropertyImpl {
- SchemaProperty* envelope;
std::string name;
Typecode typecode;
Access access;
@@ -102,10 +100,9 @@ namespace qmf {
std::string unit;
std::string description;
- SchemaPropertyImpl(SchemaProperty* e, const char* n, Typecode t) :
- envelope(e), name(n), typecode(t), access(ACCESS_READ_ONLY),
- index(false), optional(false) {}
+ SchemaPropertyImpl(const char* n, Typecode t) : name(n), typecode(t), access(ACCESS_READ_ONLY), index(false), optional(false) {}
SchemaPropertyImpl(qpid::framing::Buffer& buffer);
+ static SchemaProperty* factory(qpid::framing::Buffer& buffer);
void encode(qpid::framing::Buffer& buffer) const;
void setAccess(Access a) { access = a; }
void setIndex(bool val) { index = val; }
@@ -123,15 +120,14 @@ namespace qmf {
};
struct SchemaStatisticImpl {
- SchemaStatistic* envelope;
std::string name;
Typecode typecode;
std::string unit;
std::string description;
- SchemaStatisticImpl(SchemaStatistic* e, const char* n, Typecode t) :
- envelope(e), name(n), typecode(t) {}
+ SchemaStatisticImpl(const char* n, Typecode t) : name(n), typecode(t) {}
SchemaStatisticImpl(qpid::framing::Buffer& buffer);
+ static SchemaStatistic* factory(qpid::framing::Buffer& buffer);
void encode(qpid::framing::Buffer& buffer) const;
void setUnit(const char* val) { unit = val; }
void setDesc(const char* desc) { description = desc; }
@@ -143,10 +139,10 @@ namespace qmf {
};
struct SchemaClassKeyImpl {
- const SchemaClassKey* envelope;
const std::string& package;
const std::string& name;
const SchemaHash& hash;
+ mutable std::string repr;
// The *Container elements are only used if there isn't an external place to
// store these values.
@@ -156,6 +152,8 @@ namespace qmf {
SchemaClassKeyImpl(const std::string& package, const std::string& name, const SchemaHash& hash);
SchemaClassKeyImpl(qpid::framing::Buffer& buffer);
+ static SchemaClassKey* factory(const std::string& package, const std::string& name, const SchemaHash& hash);
+ static SchemaClassKey* factory(qpid::framing::Buffer& buffer);
const std::string& getPackageName() const { return package; }
const std::string& getClassName() const { return name; }
@@ -164,28 +162,28 @@ namespace qmf {
void encode(qpid::framing::Buffer& buffer) const;
bool operator==(const SchemaClassKeyImpl& other) const;
bool operator<(const SchemaClassKeyImpl& other) const;
- std::string str() const;
+ const std::string& str() const;
};
struct SchemaObjectClassImpl {
- typedef boost::shared_ptr<SchemaObjectClassImpl> Ptr;
- SchemaObjectClass* envelope;
std::string package;
std::string name;
mutable SchemaHash hash;
mutable bool hasHash;
- SchemaClassKeyImpl classKey;
- std::vector<SchemaPropertyImpl*> properties;
- std::vector<SchemaStatisticImpl*> statistics;
- std::vector<SchemaMethodImpl*> methods;
+ std::auto_ptr<SchemaClassKey> classKey;
+ std::vector<const SchemaProperty*> properties;
+ std::vector<const SchemaStatistic*> statistics;
+ std::vector<const SchemaMethod*> methods;
- SchemaObjectClassImpl(SchemaObjectClass* e, const char* p, const char* n) :
- envelope(e), package(p), name(n), hasHash(false), classKey(package, name, hash) {}
+ SchemaObjectClassImpl(const char* p, const char* n) :
+ package(p), name(n), hasHash(false), classKey(SchemaClassKeyImpl::factory(package, name, hash)) {}
SchemaObjectClassImpl(qpid::framing::Buffer& buffer);
+ static SchemaObjectClass* factory(qpid::framing::Buffer& buffer);
+
void encode(qpid::framing::Buffer& buffer) const;
- void addProperty(const SchemaProperty& property);
- void addStatistic(const SchemaStatistic& statistic);
- void addMethod(const SchemaMethod& method);
+ void addProperty(const SchemaProperty* property);
+ void addStatistic(const SchemaStatistic* statistic);
+ void addMethod(const SchemaMethod* method);
const SchemaClassKey* getClassKey() const;
int getPropertyCount() const { return properties.size(); }
@@ -197,21 +195,21 @@ namespace qmf {
};
struct SchemaEventClassImpl {
- typedef boost::shared_ptr<SchemaEventClassImpl> Ptr;
- SchemaEventClass* envelope;
std::string package;
std::string name;
mutable SchemaHash hash;
mutable bool hasHash;
- SchemaClassKeyImpl classKey;
+ std::auto_ptr<SchemaClassKey> classKey;
std::string description;
- std::vector<SchemaArgumentImpl*> arguments;
+ std::vector<const SchemaArgument*> arguments;
- SchemaEventClassImpl(SchemaEventClass* e, const char* p, const char* n) :
- envelope(e), package(p), name(n), hasHash(false), classKey(package, name, hash) {}
+ SchemaEventClassImpl(const char* p, const char* n) :
+ package(p), name(n), hasHash(false), classKey(SchemaClassKeyImpl::factory(package, name, hash)) {}
SchemaEventClassImpl(qpid::framing::Buffer& buffer);
+ static SchemaEventClass* factory(qpid::framing::Buffer& buffer);
+
void encode(qpid::framing::Buffer& buffer) const;
- void addArgument(const SchemaArgument& argument);
+ void addArgument(const SchemaArgument* argument);
void setDesc(const char* desc) { description = desc; }
const SchemaClassKey* getClassKey() const;
@@ -219,6 +217,7 @@ namespace qmf {
const SchemaArgument* getArgument(int idx) const;
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/SequenceManager.cpp b/qpid/cpp/src/qmf/engine/SequenceManager.cpp
index 3171e66fac..4a4644a8b9 100644
--- a/qpid/cpp/src/qmf/SequenceManager.cpp
+++ b/qpid/cpp/src/qmf/engine/SequenceManager.cpp
@@ -17,10 +17,10 @@
* under the License.
*/
-#include "qmf/SequenceManager.h"
+#include "qmf/engine/SequenceManager.h"
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
using namespace qpid::sys;
SequenceManager::SequenceManager() : nextSequence(1) {}
@@ -68,14 +68,14 @@ void SequenceManager::releaseAll()
contextMap.clear();
}
-void SequenceManager::dispatch(uint8_t opcode, uint32_t sequence, qpid::framing::Buffer& buffer)
+void SequenceManager::dispatch(uint8_t opcode, uint32_t sequence, const string& routingKey, qpid::framing::Buffer& buffer)
{
Mutex::ScopedLock _lock(lock);
bool done;
if (sequence == 0) {
if (unsolicitedContext.get() != 0) {
- done = unsolicitedContext->handleMessage(opcode, sequence, buffer);
+ done = unsolicitedContext->handleMessage(opcode, sequence, routingKey, buffer);
if (done)
unsolicitedContext->release();
}
@@ -85,7 +85,7 @@ void SequenceManager::dispatch(uint8_t opcode, uint32_t sequence, qpid::framing:
map<uint32_t, SequenceContext::Ptr>::iterator iter = contextMap.find(sequence);
if (iter != contextMap.end()) {
if (iter->second != 0) {
- done = iter->second->handleMessage(opcode, sequence, buffer);
+ done = iter->second->handleMessage(opcode, sequence, routingKey, buffer);
if (done) {
iter->second->release();
contextMap.erase(iter);
diff --git a/qpid/cpp/src/qmf/SequenceManager.h b/qpid/cpp/src/qmf/engine/SequenceManager.h
index bbfd0728a7..9e47e38610 100644
--- a/qpid/cpp/src/qmf/SequenceManager.h
+++ b/qpid/cpp/src/qmf/engine/SequenceManager.h
@@ -1,5 +1,5 @@
-#ifndef _QmfSequenceManager_
-#define _QmfSequenceManager_
+#ifndef _QmfEngineSequenceManager_
+#define _QmfEngineSequenceManager_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -31,6 +31,7 @@ namespace qpid {
}
namespace qmf {
+namespace engine {
class SequenceContext {
public:
@@ -39,7 +40,7 @@ namespace qmf {
virtual ~SequenceContext() {}
virtual void reserve() = 0;
- virtual bool handleMessage(uint8_t opcode, uint32_t sequence, qpid::framing::Buffer& buffer) = 0;
+ virtual bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer) = 0;
virtual void release() = 0;
};
@@ -51,7 +52,7 @@ namespace qmf {
uint32_t reserve(SequenceContext::Ptr ctx = SequenceContext::Ptr());
void release(uint32_t sequence);
void releaseAll();
- void dispatch(uint8_t opcode, uint32_t sequence, qpid::framing::Buffer& buffer);
+ void dispatch(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer);
private:
mutable qpid::sys::Mutex lock;
@@ -61,6 +62,7 @@ namespace qmf {
};
}
+}
#endif
diff --git a/qpid/cpp/src/qmf/ValueImpl.cpp b/qpid/cpp/src/qmf/engine/ValueImpl.cpp
index f42c85eb33..f80bdab866 100644
--- a/qpid/cpp/src/qmf/ValueImpl.cpp
+++ b/qpid/cpp/src/qmf/engine/ValueImpl.cpp
@@ -17,14 +17,14 @@
* under the License.
*/
-#include "qmf/ValueImpl.h"
+#include "qmf/engine/ValueImpl.h"
#include <qpid/framing/FieldTable.h>
using namespace std;
-using namespace qmf;
+using namespace qmf::engine;
using qpid::framing::Buffer;
-ValueImpl::ValueImpl(Typecode t, Buffer& buf) : envelope(new Value(this)), typecode(t)
+ValueImpl::ValueImpl(Typecode t, Buffer& buf) : typecode(t)
{
uint64_t first;
uint64_t second;
@@ -42,8 +42,8 @@ ValueImpl::ValueImpl(Typecode t, Buffer& buf) : envelope(new Value(this)), typec
case TYPE_BOOL : value.boolVal = (buf.getOctet() != 0); break;
case TYPE_FLOAT : value.floatVal = buf.getFloat(); break;
case TYPE_DOUBLE : value.doubleVal = buf.getDouble(); break;
- case TYPE_INT8 : value.s32 = (int32_t) buf.getOctet(); break;
- case TYPE_INT16 : value.s32 = (int32_t) buf.getShort(); break;
+ case TYPE_INT8 : value.s32 = (int32_t) ((int8_t) buf.getOctet()); break;
+ case TYPE_INT16 : value.s32 = (int32_t) ((int16_t) buf.getShort()); break;
case TYPE_INT32 : value.s32 = (int32_t) buf.getLong(); break;
case TYPE_INT64 : value.s64 = buf.getLongLong(); break;
case TYPE_UUID : buf.getBin128(value.uuidVal); break;
@@ -67,11 +67,27 @@ ValueImpl::ValueImpl(Typecode t, Buffer& buf) : envelope(new Value(this)), typec
}
}
-ValueImpl::ValueImpl(Typecode t) : envelope(new Value(this)), typecode(t)
+ValueImpl::ValueImpl(Typecode t, Typecode at) : typecode(t), valid(false), arrayTypecode(at)
+{
+}
+
+ValueImpl::ValueImpl(Typecode t) : typecode(t)
{
::memset(&value, 0, sizeof(value));
}
+Value* ValueImpl::factory(Typecode t, Buffer& b)
+{
+ ValueImpl* impl(new ValueImpl(t, b));
+ return new Value(impl);
+}
+
+Value* ValueImpl::factory(Typecode t)
+{
+ ValueImpl* impl(new ValueImpl(t));
+ return new Value(impl);
+}
+
ValueImpl::~ValueImpl()
{
}
@@ -113,9 +129,9 @@ bool ValueImpl::keyInMap(const char* key) const
Value* ValueImpl::byKey(const char* key)
{
if (keyInMap(key)) {
- map<std::string, VPtr>::iterator iter = mapVal.find(key);
+ map<std::string, Value>::iterator iter = mapVal.find(key);
if (iter != mapVal.end())
- return iter->second.get();
+ return &iter->second;
}
return 0;
}
@@ -123,9 +139,9 @@ Value* ValueImpl::byKey(const char* key)
const Value* ValueImpl::byKey(const char* key) const
{
if (keyInMap(key)) {
- map<std::string, VPtr>::const_iterator iter = mapVal.find(key);
+ map<std::string, Value>::const_iterator iter = mapVal.find(key);
if (iter != mapVal.end())
- return iter->second.get();
+ return &iter->second;
}
return 0;
}
@@ -137,12 +153,13 @@ void ValueImpl::deleteKey(const char* key)
void ValueImpl::insert(const char* key, Value* val)
{
- mapVal[key] = VPtr(val);
+ pair<string, Value> entry(key, *val);
+ mapVal.insert(entry);
}
const char* ValueImpl::key(uint32_t idx) const
{
- map<std::string, VPtr>::const_iterator iter = mapVal.begin();
+ map<std::string, Value>::const_iterator iter = mapVal.begin();
for (uint32_t i = 0; i < idx; i++) {
if (iter == mapVal.end())
break;
@@ -186,293 +203,64 @@ void ValueImpl::deleteArrayItem(uint32_t)
// Wrappers
//==================================================================
-Value::Value(Typecode t, Typecode at)
-{
- impl = new ValueImpl(this, t, at);
-}
-
-Value::Value(ValueImpl* i)
-{
- impl = i;
-}
-
-Value::~Value()
-{
- delete impl;
-}
-
-Typecode Value::getType() const
-{
- return impl->getType();
-}
-
-bool Value::isNull() const
-{
- return impl->isNull();
-}
-
-void Value::setNull()
-{
- impl->setNull();
-}
-
-bool Value::isObjectId() const
-{
- return impl->isObjectId();
-}
-
-const ObjectId& Value::asObjectId() const
-{
- return impl->asObjectId();
-}
-
-void Value::setObjectId(const ObjectId& oid)
-{
- impl->setObjectId(oid);
-}
-
-bool Value::isUint() const
-{
- return impl->isUint();
-}
-
-uint32_t Value::asUint() const
-{
- return impl->asUint();
-}
-
-void Value::setUint(uint32_t val)
-{
- impl->setUint(val);
-}
-
-bool Value::isInt() const
-{
- return impl->isInt();
-}
-
-int32_t Value::asInt() const
-{
- return impl->asInt();
-}
-
-void Value::setInt(int32_t val)
-{
- impl->setInt(val);
-}
-
-bool Value::isUint64() const
-{
- return impl->isUint64();
-}
-
-uint64_t Value::asUint64() const
-{
- return impl->asUint64();
-}
-
-void Value::setUint64(uint64_t val)
-{
- impl->setUint64(val);
-}
-
-bool Value::isInt64() const
-{
- return impl->isInt64();
-}
-
-int64_t Value::asInt64() const
-{
- return impl->asInt64();
-}
-
-void Value::setInt64(int64_t val)
-{
- impl->setInt64(val);
-}
-
-bool Value::isString() const
-{
- return impl->isString();
-}
-
-const char* Value::asString() const
-{
- return impl->asString();
-}
-
-void Value::setString(const char* val)
-{
- impl->setString(val);
-}
-
-bool Value::isBool() const
-{
- return impl->isBool();
-}
-
-bool Value::asBool() const
-{
- return impl->asBool();
-}
-
-void Value::setBool(bool val)
-{
- impl->setBool(val);
-}
-
-bool Value::isFloat() const
-{
- return impl->isFloat();
-}
-
-float Value::asFloat() const
-{
- return impl->asFloat();
-}
-
-void Value::setFloat(float val)
-{
- impl->setFloat(val);
-}
-
-bool Value::isDouble() const
-{
- return impl->isDouble();
-}
-
-double Value::asDouble() const
-{
- return impl->asDouble();
-}
-
-void Value::setDouble(double val)
-{
- impl->setDouble(val);
-}
-
-bool Value::isUuid() const
-{
- return impl->isUuid();
-}
-
-const uint8_t* Value::asUuid() const
-{
- return impl->asUuid();
-}
-
-void Value::setUuid(const uint8_t* val)
-{
- impl->setUuid(val);
-}
-
-bool Value::isObject() const
-{
- return impl->isObject();
-}
-
-Object* Value::asObject() const
-{
- return impl->asObject();
-}
-
-void Value::setObject(Object* val)
-{
- impl->setObject(val);
-}
-
-bool Value::isMap() const
-{
- return impl->isMap();
-}
-
-bool Value::keyInMap(const char* key) const
-{
- return impl->keyInMap(key);
-}
-
-Value* Value::byKey(const char* key)
-{
- return impl->byKey(key);
-}
-
-const Value* Value::byKey(const char* key) const
-{
- return impl->byKey(key);
-}
-
-void Value::deleteKey(const char* key)
-{
- impl->deleteKey(key);
-}
-
-void Value::insert(const char* key, Value* val)
-{
- impl->insert(key, val);
-}
-
-uint32_t Value::keyCount() const
-{
- return impl->keyCount();
-}
-
-const char* Value::key(uint32_t idx) const
-{
- return impl->key(idx);
-}
-
-bool Value::isList() const
-{
- return impl->isList();
-}
-
-uint32_t Value::listItemCount() const
-{
- return impl->listItemCount();
-}
-
-Value* Value::listItem(uint32_t idx)
-{
- return impl->listItem(idx);
-}
-
-void Value::appendToList(Value* val)
-{
- impl->appendToList(val);
-}
-
-void Value::deleteListItem(uint32_t idx)
-{
- impl->deleteListItem(idx);
-}
-
-bool Value::isArray() const
-{
- return impl->isArray();
-}
-
-Typecode Value::arrayType() const
-{
- return impl->arrayType();
-}
-
-uint32_t Value::arrayItemCount() const
-{
- return impl->arrayItemCount();
-}
-
-Value* Value::arrayItem(uint32_t idx)
-{
- return impl->arrayItem(idx);
-}
-
-void Value::appendToArray(Value* val)
-{
- impl->appendToArray(val);
-}
-
-void Value::deleteArrayItem(uint32_t idx)
-{
- impl->deleteArrayItem(idx);
-}
+Value::Value(const Value& from) : impl(new ValueImpl(*(from.impl))) {}
+Value::Value(Typecode t, Typecode at) : impl(new ValueImpl(t, at)) {}
+Value::Value(ValueImpl* i) : impl(i) {}
+Value::~Value() { delete impl;}
+
+Typecode Value::getType() const { return impl->getType(); }
+bool Value::isNull() const { return impl->isNull(); }
+void Value::setNull() { impl->setNull(); }
+bool Value::isObjectId() const { return impl->isObjectId(); }
+const ObjectId& Value::asObjectId() const { return impl->asObjectId(); }
+void Value::setObjectId(const ObjectId& oid) { impl->setObjectId(oid); }
+bool Value::isUint() const { return impl->isUint(); }
+uint32_t Value::asUint() const { return impl->asUint(); }
+void Value::setUint(uint32_t val) { impl->setUint(val); }
+bool Value::isInt() const { return impl->isInt(); }
+int32_t Value::asInt() const { return impl->asInt(); }
+void Value::setInt(int32_t val) { impl->setInt(val); }
+bool Value::isUint64() const { return impl->isUint64(); }
+uint64_t Value::asUint64() const { return impl->asUint64(); }
+void Value::setUint64(uint64_t val) { impl->setUint64(val); }
+bool Value::isInt64() const { return impl->isInt64(); }
+int64_t Value::asInt64() const { return impl->asInt64(); }
+void Value::setInt64(int64_t val) { impl->setInt64(val); }
+bool Value::isString() const { return impl->isString(); }
+const char* Value::asString() const { return impl->asString(); }
+void Value::setString(const char* val) { impl->setString(val); }
+bool Value::isBool() const { return impl->isBool(); }
+bool Value::asBool() const { return impl->asBool(); }
+void Value::setBool(bool val) { impl->setBool(val); }
+bool Value::isFloat() const { return impl->isFloat(); }
+float Value::asFloat() const { return impl->asFloat(); }
+void Value::setFloat(float val) { impl->setFloat(val); }
+bool Value::isDouble() const { return impl->isDouble(); }
+double Value::asDouble() const { return impl->asDouble(); }
+void Value::setDouble(double val) { impl->setDouble(val); }
+bool Value::isUuid() const { return impl->isUuid(); }
+const uint8_t* Value::asUuid() const { return impl->asUuid(); }
+void Value::setUuid(const uint8_t* val) { impl->setUuid(val); }
+bool Value::isObject() const { return impl->isObject(); }
+const Object* Value::asObject() const { return impl->asObject(); }
+void Value::setObject(Object* val) { impl->setObject(val); }
+bool Value::isMap() const { return impl->isMap(); }
+bool Value::keyInMap(const char* key) const { return impl->keyInMap(key); }
+Value* Value::byKey(const char* key) { return impl->byKey(key); }
+const Value* Value::byKey(const char* key) const { return impl->byKey(key); }
+void Value::deleteKey(const char* key) { impl->deleteKey(key); }
+void Value::insert(const char* key, Value* val) { impl->insert(key, val); }
+uint32_t Value::keyCount() const { return impl->keyCount(); }
+const char* Value::key(uint32_t idx) const { return impl->key(idx); }
+bool Value::isList() const { return impl->isList(); }
+uint32_t Value::listItemCount() const { return impl->listItemCount(); }
+Value* Value::listItem(uint32_t idx) { return impl->listItem(idx); }
+void Value::appendToList(Value* val) { impl->appendToList(val); }
+void Value::deleteListItem(uint32_t idx) { impl->deleteListItem(idx); }
+bool Value::isArray() const { return impl->isArray(); }
+Typecode Value::arrayType() const { return impl->arrayType(); }
+uint32_t Value::arrayItemCount() const { return impl->arrayItemCount(); }
+Value* Value::arrayItem(uint32_t idx) { return impl->arrayItem(idx); }
+void Value::appendToArray(Value* val) { impl->appendToArray(val); }
+void Value::deleteArrayItem(uint32_t idx) { impl->deleteArrayItem(idx); }
diff --git a/qpid/cpp/src/qmf/ValueImpl.h b/qpid/cpp/src/qmf/engine/ValueImpl.h
index cf33035bf7..b6adae5d93 100644
--- a/qpid/cpp/src/qmf/ValueImpl.h
+++ b/qpid/cpp/src/qmf/engine/ValueImpl.h
@@ -1,5 +1,5 @@
-#ifndef _QmfValueImpl_
-#define _QmfValueImpl_
+#ifndef _QmfEngineValueImpl_
+#define _QmfEngineValueImpl_
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -20,9 +20,9 @@
* under the License.
*/
-#include <qmf/Value.h>
-#include <qmf/ObjectIdImpl.h>
-#include <qmf/Object.h>
+#include <qmf/engine/Value.h>
+#include <qmf/engine/ObjectIdImpl.h>
+#include <qmf/engine/Object.h>
#include <qpid/framing/Buffer.h>
#include <string>
#include <string.h>
@@ -31,22 +31,20 @@
#include <boost/shared_ptr.hpp>
namespace qmf {
+namespace engine {
// TODO: set valid flag on all value settors
// TODO: add a modified flag and accessors
struct ValueImpl {
- typedef boost::shared_ptr<Value> VPtr;
- typedef boost::shared_ptr<Object> OPtr;
- Value* envelope;
const Typecode typecode;
bool valid;
ObjectId refVal;
std::string stringVal;
- OPtr objectVal;
- std::map<std::string, VPtr> mapVal;
- std::vector<VPtr> vectorVal;
+ std::auto_ptr<Object> objectVal;
+ std::map<std::string, Value> mapVal;
+ std::vector<Value> vectorVal;
Typecode arrayTypecode;
union {
@@ -60,10 +58,17 @@ namespace qmf {
uint8_t uuidVal[16];
} value;
- ValueImpl(Value* e, Typecode t, Typecode at) :
- envelope(e), typecode(t), valid(false), arrayTypecode(at) {}
+ ValueImpl(const ValueImpl& from) :
+ typecode(from.typecode), valid(from.valid), refVal(from.refVal), stringVal(from.stringVal),
+ objectVal(from.objectVal.get() ? new Object(*(from.objectVal)) : 0),
+ mapVal(from.mapVal), vectorVal(from.vectorVal), arrayTypecode(from.arrayTypecode),
+ value(from.value) {}
+
+ ValueImpl(Typecode t, Typecode at);
ValueImpl(Typecode t, qpid::framing::Buffer& b);
ValueImpl(Typecode t);
+ static Value* factory(Typecode t, qpid::framing::Buffer& b);
+ static Value* factory(Typecode t);
~ValueImpl();
void encode(qpid::framing::Buffer& b) const;
@@ -139,6 +144,7 @@ namespace qmf {
void deleteArrayItem(uint32_t idx);
};
}
+}
#endif
diff --git a/qpid/cpp/src/qpid/acl/AclData.cpp b/qpid/cpp/src/qpid/acl/AclData.cpp
index 81519c3311..5d7a028736 100644
--- a/qpid/cpp/src/qpid/acl/AclData.cpp
+++ b/qpid/cpp/src/qpid/acl/AclData.cpp
@@ -18,7 +18,8 @@
#include "qpid/acl/AclData.h"
#include "qpid/log/Statement.h"
-
+#include "qpid/sys/IntegerTypes.h"
+#include <boost/lexical_cast.hpp>
namespace qpid {
namespace acl {
@@ -57,14 +58,15 @@ AclResult AclData::lookup(const std::string& id, const Action& action, const Obj
const std::string& name, std::map<Property, std::string>* params) {
QPID_LOG(debug, "ACL: Lookup for id:" << id << " action:" << AclHelper::getActionStr((Action) action)
- << " objectType:" << AclHelper::getObjectTypeStr((ObjectType) objType) << " name:" << name
- << " with params " << AclHelper::propertyMapToString(params));
+ << " objectType:" << AclHelper::getObjectTypeStr((ObjectType) objType) << " name:" << name
+ << " with params " << AclHelper::propertyMapToString(params));
AclResult aclresult = decisionMode;
if (actionList[action] && actionList[action][objType]) {
AclData::actObjItr itrRule = actionList[action][objType]->find(id);
if (itrRule == actionList[action][objType]->end())
itrRule = actionList[action][objType]->find("*");
+
if (itrRule != actionList[action][objType]->end()) {
QPID_LOG(debug, "ACL: checking the following rules for : " << itrRule->first );
@@ -79,25 +81,48 @@ AclResult AclData::lookup(const std::string& id, const Action& action, const Obj
if (pMItr->first == acl::PROP_NAME) {
if (matchProp(pMItr->second, name)){
QPID_LOG(debug, "ACL: name '" << name << "' matched with name '"
- << pMItr->second << "' given in the rule");
- }else{
+ << pMItr->second << "' given in the rule");
+ }else{
match = false;
QPID_LOG(debug, "ACL: name '" << name << "' didn't match with name '"
- << pMItr->second << "' given in the rule");
+ << pMItr->second << "' given in the rule");
}
} else if (params) { //match pMItr against params
propertyMapItr paramItr = params->find(pMItr->first);
if (paramItr == params->end()) {
match = false;
QPID_LOG(debug, "ACL: the given parameter map in lookup doesn't contain the property '"
- << AclHelper::getPropertyStr(pMItr->first) << "'");
- } else if (!matchProp(pMItr->second, paramItr->second)) {
+ << AclHelper::getPropertyStr(pMItr->first) << "'");
+ }else if ( pMItr->first == acl::PROP_MAXQUEUECOUNT || pMItr->first == acl::PROP_MAXQUEUESIZE ) {
+ if ( pMItr->first == paramItr->first ) {
+ uint64_t aclMax = boost::lexical_cast<uint64_t>(pMItr->second);
+ uint64_t paramMax = boost::lexical_cast<uint64_t>(paramItr->second);
+ QPID_LOG(debug, "ACL: Numeric comparison for property " <<
+ AclHelper::getPropertyStr(paramItr->first) <<
+ " (value given in lookup = " <<
+ boost::lexical_cast<std::string>(paramItr->second) <<
+ ", value give in rule = " <<
+ boost::lexical_cast<std::string>(pMItr->second) << " )");
+ if (( aclMax ) && ( paramMax == 0 || paramMax > aclMax)){
+ match = decisionMode == qpid::acl::ALLOW ;
+ QPID_LOG(debug, "ACL: Limit exceeded and match=" <<
+ (match ? "true": "false") <<
+ " as decision mode is " << AclHelper::getAclResultStr(decisionMode));
+ }
+ }
+ }else if (matchProp(pMItr->second, paramItr->second)) {
+ QPID_LOG(debug, "ACL: the pair("
+ << AclHelper::getPropertyStr(paramItr->first) << "," << paramItr->second
+ << ") given in lookup matched the pair("
+ << AclHelper::getPropertyStr(pMItr->first) << "," << pMItr->second << ") given in the rule");
+ } else {
QPID_LOG(debug, "ACL: the pair("
- << AclHelper::getPropertyStr(paramItr->first) << "," << paramItr->second
- << ") given in lookup doesn't match the pair("
- << AclHelper::getPropertyStr(pMItr->first) << "," << pMItr->second << ") given in the rule");
+ << AclHelper::getPropertyStr(paramItr->first) << "," << paramItr->second
+ << ") given in lookup doesn't match the pair("
+ << AclHelper::getPropertyStr(pMItr->first) << "," << pMItr->second << ") given in the rule");
match = false;
- }
+
+ }
}
}
if (match)
@@ -116,37 +141,63 @@ AclResult AclData::lookup(const std::string& id, const Action& action, const Obj
AclResult AclData::lookup(const std::string& id, const Action& action, const ObjectType& objType, const std::string& /*Exchange*/ name, const std::string& RoutingKey)
{
- AclResult aclresult = decisionMode;
+
+ QPID_LOG(debug, "ACL: Lookup for id:" << id << " action:" << AclHelper::getActionStr((Action) action)
+ << " objectType:" << AclHelper::getObjectTypeStr((ObjectType) objType) << " exchange name:" << name
+ << " with routing key " << RoutingKey);
+
+ AclResult aclresult = decisionMode;
- if (actionList[action] && actionList[action][objType]){
- AclData::actObjItr itrRule = actionList[action][objType]->find(id);
- if (itrRule == actionList[action][objType]->end())
+ if (actionList[action] && actionList[action][objType]){
+ AclData::actObjItr itrRule = actionList[action][objType]->find(id);
+
+ if (itrRule == actionList[action][objType]->end())
itrRule = actionList[action][objType]->find("*");
+
if (itrRule != actionList[action][objType]->end() ) {
+ QPID_LOG(debug, "ACL: checking the following rules for : " << itrRule->first );
+
//loop the vector
- for (ruleSetItr i=itrRule->second.begin(); i<itrRule->second.end(); i++) {
-
+ for (ruleSetItr i=itrRule->second.begin(); i<itrRule->second.end(); i++) {
+ QPID_LOG(debug, "ACL: checking rule " << i->toString());
+
// loop the names looking for match
bool match =true;
for (propertyMapItr pMItr = i->props.begin(); (pMItr != i->props.end()) && match; pMItr++)
{
- //match name is exists first
+ //match name is exists first
if (pMItr->first == acl::PROP_NAME){
- if (!matchProp(pMItr->second, name)){
- match= false;
- }
+ if (matchProp(pMItr->second, name)){
+ QPID_LOG(debug, "ACL: name '" << name << "' matched with name '"
+ << pMItr->second << "' given in the rule");
+
+ }else{
+ match= false;
+ QPID_LOG(debug, "ACL: name '" << name << "' didn't match with name '"
+ << pMItr->second << "' given in the rule");
+ }
}else if (pMItr->first == acl::PROP_ROUTINGKEY){
- if (!matchProp(pMItr->second, RoutingKey)){
- match= false;
- }
+ if (matchProp(pMItr->second, RoutingKey)){
+ QPID_LOG(debug, "ACL: name '" << name << "' matched with routing_key '"
+ << pMItr->second << "' given in the rule");
+ }else{
+ match= false;
+ QPID_LOG(debug, "ACL: name '" << name << "' didn't match with routing_key '"
+ << pMItr->second << "' given in the rule");
+ }
}
}
- if (match) return getACLResult(i->logOnly, i->log);
- }
+ if (match){
+ aclresult = getACLResult(i->logOnly, i->log);
+ QPID_LOG(debug,"Successful match, the decision is:" << AclHelper::getAclResultStr(aclresult));
+ return aclresult;
+ }
+ }
}
- }
- return aclresult;
+ }
+ QPID_LOG(debug,"No successful match, defaulting to the decision mode " << AclHelper::getAclResultStr(aclresult));
+ return aclresult;
}
diff --git a/qpid/cpp/src/qpid/agent/ManagementAgentImpl.cpp b/qpid/cpp/src/qpid/agent/ManagementAgentImpl.cpp
index 093e9cea32..f9f39316e2 100644
--- a/qpid/cpp/src/qpid/agent/ManagementAgentImpl.cpp
+++ b/qpid/cpp/src/qpid/agent/ManagementAgentImpl.cpp
@@ -78,7 +78,7 @@ ManagementAgent* ManagementAgent::Singleton::getInstance()
const string ManagementAgentImpl::storeMagicNumber("MA02");
ManagementAgentImpl::ManagementAgentImpl() :
- interval(10), extThread(false),
+ interval(10), extThread(false), pipeHandle(0),
initialized(false), connected(false), lastFailure("never connected"),
clientWasAdded(true), requestedBrokerBank(0), requestedAgentBank(0),
assignedBrokerBank(0), assignedAgentBank(0), bootSequence(0),
@@ -89,13 +89,12 @@ ManagementAgentImpl::ManagementAgentImpl() :
ManagementAgentImpl::~ManagementAgentImpl()
{
+ // shutdown & cleanup all threads
connThreadBody.close();
+ pubThreadBody.close();
- // If the thread is doing work on the connection, we must wait for it to
- // complete before shutting down.
- if (!connThreadBody.isSleeping()) {
- connThread.join();
- }
+ connThread.join();
+ pubThread.join();
// Release the memory associated with stored management objects.
{
@@ -777,6 +776,7 @@ void ManagementAgentImpl::ConnectionThread::run()
static const int delayFactor(2);
int delay(delayMin);
string dest("qmfagent");
+ ConnectionThread::shared_ptr tmp;
sessionId.generate();
queueName << "qmfagent-" << sessionId;
@@ -787,7 +787,7 @@ void ManagementAgentImpl::ConnectionThread::run()
QPID_LOG(debug, "QMF Agent attempting to connect to the broker...");
connection.open(agent.connectionSettings);
session = connection.newSession(queueName.str());
- subscriptions = new client::SubscriptionManager(session);
+ subscriptions.reset(new client::SubscriptionManager(session));
session.queueDeclare(arg::queue=queueName.str(), arg::autoDelete=true,
arg::exclusive=true);
@@ -811,11 +811,12 @@ void ManagementAgentImpl::ConnectionThread::run()
operational = false;
agent.connected = false;
+ tmp = subscriptions;
+ subscriptions.reset();
}
+ tmp.reset(); // frees the subscription outside the lock
delay = delayMin;
connection.close();
- delete subscriptions;
- subscriptions = 0;
}
} catch (exception &e) {
if (delay < delayMax)
@@ -824,14 +825,19 @@ void ManagementAgentImpl::ConnectionThread::run()
}
{
+ // sleep for "delay" seconds, but peridically check if the
+ // agent is shutting down so we don't hang for up to delayMax
+ // seconds during agent shutdown
Mutex::ScopedLock _lock(connLock);
if (shutdown)
return;
sleeping = true;
- {
- Mutex::ScopedUnlock _unlock(connLock);
- ::sleep(delay);
- }
+ int totalSleep = 0;
+ do {
+ Mutex::ScopedUnlock _unlock(connLock);
+ ::sleep(delayMin);
+ totalSleep += delayMin;
+ } while (totalSleep < delay && !shutdown);
sleeping = false;
if (shutdown)
return;
@@ -848,10 +854,12 @@ void ManagementAgentImpl::ConnectionThread::sendBuffer(Buffer& buf,
const string& exchange,
const string& routingKey)
{
+ ConnectionThread::shared_ptr s;
{
Mutex::ScopedLock _lock(connLock);
if (!operational)
return;
+ s = subscriptions;
}
Message msg;
@@ -866,8 +874,8 @@ void ManagementAgentImpl::ConnectionThread::sendBuffer(Buffer& buf,
} catch(exception& e) {
QPID_LOG(error, "Exception caught in sendBuffer: " << e.what());
// Bounce the connection
- if (subscriptions)
- subscriptions->stop();
+ if (s)
+ s->stop();
}
}
@@ -881,12 +889,14 @@ void ManagementAgentImpl::ConnectionThread::bindToBank(uint32_t brokerBank, uint
void ManagementAgentImpl::ConnectionThread::close()
{
+ ConnectionThread::shared_ptr s;
{
Mutex::ScopedLock _lock(connLock);
shutdown = true;
+ s = subscriptions;
}
- if (subscriptions)
- subscriptions->stop();
+ if (s)
+ s->stop();
}
bool ManagementAgentImpl::ConnectionThread::isSleeping() const
@@ -898,8 +908,13 @@ bool ManagementAgentImpl::ConnectionThread::isSleeping() const
void ManagementAgentImpl::PublishThread::run()
{
- while (true) {
+ uint16_t totalSleep;
+
+ while (!shutdown) {
agent.periodicProcessing();
- ::sleep(agent.getInterval());
+ totalSleep = 0;
+ while (totalSleep++ < agent.getInterval() && !shutdown) {
+ ::sleep(1);
+ }
}
}
diff --git a/qpid/cpp/src/qpid/agent/ManagementAgentImpl.h b/qpid/cpp/src/qpid/agent/ManagementAgentImpl.h
index f9cad9ebf5..a876496e98 100644
--- a/qpid/cpp/src/qpid/agent/ManagementAgentImpl.h
+++ b/qpid/cpp/src/qpid/agent/ManagementAgentImpl.h
@@ -163,12 +163,14 @@ class ManagementAgentImpl : public ManagementAgent, public client::MessageListen
friend class ConnectionThread;
class ConnectionThread : public sys::Runnable
{
+ typedef boost::shared_ptr<client::SubscriptionManager> shared_ptr;
+
bool operational;
ManagementAgentImpl& agent;
framing::Uuid sessionId;
client::Connection connection;
client::Session session;
- client::SubscriptionManager* subscriptions;
+ ConnectionThread::shared_ptr subscriptions;
std::stringstream queueName;
mutable sys::Mutex connLock;
bool shutdown;
@@ -176,7 +178,7 @@ class ManagementAgentImpl : public ManagementAgent, public client::MessageListen
void run();
public:
ConnectionThread(ManagementAgentImpl& _agent) :
- operational(false), agent(_agent), subscriptions(0),
+ operational(false), agent(_agent),
shutdown(false), sleeping(false) {}
~ConnectionThread();
void sendBuffer(qpid::framing::Buffer& buf,
@@ -192,8 +194,11 @@ class ManagementAgentImpl : public ManagementAgent, public client::MessageListen
{
ManagementAgentImpl& agent;
void run();
+ bool shutdown;
public:
- PublishThread(ManagementAgentImpl& _agent) : agent(_agent) {}
+ PublishThread(ManagementAgentImpl& _agent) :
+ agent(_agent), shutdown(false) {}
+ void close() { shutdown = true; }
};
ConnectionThread connThreadBody;
diff --git a/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp b/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp
index 96d5146c30..bf2e7d5713 100644
--- a/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp
+++ b/qpid/cpp/src/qpid/amqp_0_10/Connection.cpp
@@ -31,7 +31,7 @@ namespace amqp_0_10 {
using sys::Mutex;
Connection::Connection(sys::OutputControl& o, const std::string& id, bool _isClient)
- : frameQueueClosed(false), output(o), identifier(id), initialized(false),
+ : pushClosed(false), popClosed(false), output(o), identifier(id), initialized(false),
isClient(_isClient), buffered(0), version(0,10)
{}
@@ -61,19 +61,23 @@ size_t Connection::decode(const char* buffer, size_t size) {
}
bool Connection::canEncode() {
- if (!frameQueueClosed) connection->doOutput();
Mutex::ScopedLock l(frameQueueLock);
- return (!isClient && !initialized) || !frameQueue.empty();
+ if (!popClosed) {
+ Mutex::ScopedUnlock u(frameQueueLock);
+ connection->doOutput();
+ }
+ return !popClosed && ((!isClient && !initialized) || !frameQueue.empty());
}
bool Connection::isClosed() const {
Mutex::ScopedLock l(frameQueueLock);
- return frameQueueClosed;
+ return pushClosed && popClosed;
}
size_t Connection::encode(const char* buffer, size_t size) {
{ // Swap frameQueue data into workQueue to avoid holding lock while we encode.
Mutex::ScopedLock l(frameQueueLock);
+ if (popClosed) return 0; // Can't pop any more frames.
assert(workQueue.empty());
workQueue.swap(frameQueue);
}
@@ -102,6 +106,8 @@ size_t Connection::encode(const char* buffer, size_t size) {
// Put back any frames we did not encode.
frameQueue.insert(frameQueue.begin(), workQueue.begin(), workQueue.end());
workQueue.clear();
+ if (frameQueue.empty() && pushClosed)
+ popClosed = true;
}
return out.getPosition();
}
@@ -111,9 +117,10 @@ void Connection::activateOutput() { output.activateOutput(); }
void Connection::giveReadCredit(int32_t credit) { output.giveReadCredit(credit); }
void Connection::close() {
- // Close the output queue.
+ // No more frames can be pushed onto the queue.
+ // Frames aleady on the queue can be popped.
Mutex::ScopedLock l(frameQueueLock);
- frameQueueClosed = true;
+ pushClosed = true;
}
void Connection::closed() {
@@ -123,7 +130,7 @@ void Connection::closed() {
void Connection::send(framing::AMQFrame& f) {
{
Mutex::ScopedLock l(frameQueueLock);
- if (!frameQueueClosed)
+ if (!pushClosed)
frameQueue.push_back(f);
buffered += f.encodedSize();
}
diff --git a/qpid/cpp/src/qpid/amqp_0_10/Connection.h b/qpid/cpp/src/qpid/amqp_0_10/Connection.h
index 6fd51381fc..995d824796 100644
--- a/qpid/cpp/src/qpid/amqp_0_10/Connection.h
+++ b/qpid/cpp/src/qpid/amqp_0_10/Connection.h
@@ -47,7 +47,7 @@ class Connection : public sys::ConnectionCodec,
FrameQueue frameQueue;
FrameQueue workQueue;
- bool frameQueueClosed;
+ bool pushClosed, popClosed;
mutable sys::Mutex frameQueueLock;
sys::OutputControl& output;
std::auto_ptr<sys::ConnectionInputHandler> connection;
diff --git a/qpid/cpp/src/qpid/broker/AclModule.h b/qpid/cpp/src/qpid/broker/AclModule.h
index 536fa21b2b..2f4f7eaacc 100644
--- a/qpid/cpp/src/qpid/broker/AclModule.h
+++ b/qpid/cpp/src/qpid/broker/AclModule.h
@@ -40,7 +40,8 @@ enum Action {ACT_CONSUME, ACT_PUBLISH, ACT_CREATE, ACT_ACCESS, ACT_BIND,
enum Property {PROP_NAME, PROP_DURABLE, PROP_OWNER, PROP_ROUTINGKEY,
PROP_PASSIVE, PROP_AUTODELETE, PROP_EXCLUSIVE, PROP_TYPE,
PROP_ALTERNATE, PROP_QUEUENAME, PROP_SCHEMAPACKAGE,
- PROP_SCHEMACLASS};
+ PROP_SCHEMACLASS, PROP_POLICYTYPE, PROP_MAXQUEUESIZE,
+ PROP_MAXQUEUECOUNT};
enum AclResult {ALLOW, ALLOWLOG, DENY, DENYLOG};
} // namespace acl
@@ -132,6 +133,9 @@ class AclHelper {
if (str.compare("queuename") == 0) return PROP_QUEUENAME;
if (str.compare("schemapackage") == 0) return PROP_SCHEMAPACKAGE;
if (str.compare("schemaclass") == 0) return PROP_SCHEMACLASS;
+ if (str.compare("policytype") == 0) return PROP_POLICYTYPE;
+ if (str.compare("maxqueuesize") == 0) return PROP_MAXQUEUESIZE;
+ if (str.compare("maxqueuecount") == 0) return PROP_MAXQUEUECOUNT;
throw str;
}
static inline std::string getPropertyStr(const Property p) {
@@ -148,6 +152,9 @@ class AclHelper {
case PROP_QUEUENAME: return "queuename";
case PROP_SCHEMAPACKAGE: return "schemapackage";
case PROP_SCHEMACLASS: return "schemaclass";
+ case PROP_POLICYTYPE: return "policytype";
+ case PROP_MAXQUEUESIZE: return "maxqueuesize";
+ case PROP_MAXQUEUECOUNT: return "maxqueuecount";
default: assert(false); // should never get here
}
return "";
@@ -217,11 +224,14 @@ class AclHelper {
// == Queues ==
propSetPtr p4(new propSet);
- p3->insert(PROP_ALTERNATE);
- p3->insert(PROP_PASSIVE);
- p3->insert(PROP_DURABLE);
- p3->insert(PROP_EXCLUSIVE);
- p3->insert(PROP_AUTODELETE);
+ p4->insert(PROP_ALTERNATE);
+ p4->insert(PROP_PASSIVE);
+ p4->insert(PROP_DURABLE);
+ p4->insert(PROP_EXCLUSIVE);
+ p4->insert(PROP_AUTODELETE);
+ p4->insert(PROP_POLICYTYPE);
+ p4->insert(PROP_MAXQUEUESIZE);
+ p4->insert(PROP_MAXQUEUECOUNT);
actionMapPtr a1(new actionMap);
a1->insert(actionPair(ACT_ACCESS, p0));
diff --git a/qpid/cpp/src/qpid/broker/Broker.cpp b/qpid/cpp/src/qpid/broker/Broker.cpp
index 13cf88fb11..4259bb2f31 100644
--- a/qpid/cpp/src/qpid/broker/Broker.cpp
+++ b/qpid/cpp/src/qpid/broker/Broker.cpp
@@ -91,7 +91,8 @@ Broker::Options::Options(const std::string& name) :
queueLimit(100*1048576/*100M default limit*/),
tcpNoDelay(false),
requireEncrypted(false),
- maxSessionRate(0)
+ maxSessionRate(0),
+ asyncQueueEvents(true)
{
int c = sys::SystemInfo::concurrency();
workerThreads=c+1;
@@ -121,7 +122,8 @@ Broker::Options::Options(const std::string& name) :
("tcp-nodelay", optValue(tcpNoDelay), "Set TCP_NODELAY on TCP connections")
("require-encryption", optValue(requireEncrypted), "Only accept connections that are encrypted")
("known-hosts-url", optValue(knownHosts, "URL or 'none'"), "URL to send as 'known-hosts' to clients ('none' implies empty list)")
- ("max-session-rate", optValue(maxSessionRate, "MESSAGES/S"), "Sets the maximum message rate per session (0=unlimited)");
+ ("max-session-rate", optValue(maxSessionRate, "MESSAGES/S"), "Sets the maximum message rate per session (0=unlimited)")
+ ("async-queue-events", optValue(asyncQueueEvents, "yes|no"), "Set Queue Events async, used for services like replication");
}
const std::string empty;
@@ -150,7 +152,7 @@ Broker::Broker(const Broker::Options& conf) :
*this),
managementAgent(conf.enableMgmt ? new ManagementAgent() : 0),
queueCleaner(queues, timer),
- queueEvents(poller),
+ queueEvents(poller,!conf.asyncQueueEvents),
recovery(true),
expiryPolicy(new ExpiryPolicy),
getKnownBrokers(boost::bind(&Broker::getKnownBrokersImpl, this))
@@ -208,8 +210,10 @@ Broker::Broker(const Broker::Options& conf) :
(*i)->earlyInitialize(*this);
// If no plugin store module registered itself, set up the null store.
- if (store.get() == 0)
- setStore (new NullMessageStore());
+ if (store.get() == 0) {
+ boost::shared_ptr<MessageStore> p(new NullMessageStore());
+ setStore (p);
+ }
exchanges.declare(empty, DirectExchange::typeName); // Default exchange.
@@ -296,7 +300,7 @@ boost::intrusive_ptr<Broker> Broker::create(const Options& opts)
return boost::intrusive_ptr<Broker>(new Broker(opts));
}
-void Broker::setStore (MessageStore* _store)
+void Broker::setStore (boost::shared_ptr<MessageStore>& _store)
{
store.reset(new MessageStoreModule (_store));
queues.setStore (store.get());
diff --git a/qpid/cpp/src/qpid/broker/Broker.h b/qpid/cpp/src/qpid/broker/Broker.h
index 0517ceca95..5ca01e0867 100644
--- a/qpid/cpp/src/qpid/broker/Broker.h
+++ b/qpid/cpp/src/qpid/broker/Broker.h
@@ -111,6 +111,7 @@ public:
bool requireEncrypted;
std::string knownHosts;
uint32_t maxSessionRate;
+ bool asyncQueueEvents;
private:
std::string getHome();
@@ -171,7 +172,7 @@ public:
/** Shut down the broker */
virtual void shutdown();
- QPID_BROKER_EXTERN void setStore (MessageStore*);
+ QPID_BROKER_EXTERN void setStore (boost::shared_ptr<MessageStore>& store);
MessageStore& getStore() { return *store; }
void setAcl (AclModule* _acl) {acl = _acl;}
AclModule* getAcl() { return acl; }
diff --git a/qpid/cpp/src/qpid/broker/DirectExchange.cpp b/qpid/cpp/src/qpid/broker/DirectExchange.cpp
index b9f24dee5f..29fe47beac 100644
--- a/qpid/cpp/src/qpid/broker/DirectExchange.cpp
+++ b/qpid/cpp/src/qpid/broker/DirectExchange.cpp
@@ -145,39 +145,12 @@ bool DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, c
void DirectExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/)
{
PreRoute pr(msg, this);
- Queues::ConstPtr p;
+ ConstBindingList b;
{
Mutex::ScopedLock l(lock);
- p = bindings[routingKey].queues.snapshot();
- }
- int count(0);
-
- if (p) {
- for(std::vector<Binding::shared_ptr>::const_iterator i = p->begin(); i != p->end(); i++, count++) {
- msg.deliverTo((*i)->queue);
- if ((*i)->mgmtBinding != 0)
- (*i)->mgmtBinding->inc_msgMatched();
- }
- }
-
- if(!count){
- QPID_LOG(info, "DirectExchange " << getName() << " could not route message with key " << routingKey
- << "; no matching binding found");
- if (mgmtExchange != 0) {
- mgmtExchange->inc_msgDrops();
- mgmtExchange->inc_byteDrops(msg.contentSize());
- }
- } else {
- if (mgmtExchange != 0) {
- mgmtExchange->inc_msgRoutes(count);
- mgmtExchange->inc_byteRoutes(count * msg.contentSize());
- }
- }
-
- if (mgmtExchange != 0) {
- mgmtExchange->inc_msgReceives();
- mgmtExchange->inc_byteReceives(msg.contentSize());
+ b = bindings[routingKey].queues.snapshot();
}
+ doRoute(msg, b);
}
diff --git a/qpid/cpp/src/qpid/broker/DtxAck.cpp b/qpid/cpp/src/qpid/broker/DtxAck.cpp
index b189ef4cdb..bca3f90bbe 100644
--- a/qpid/cpp/src/qpid/broker/DtxAck.cpp
+++ b/qpid/cpp/src/qpid/broker/DtxAck.cpp
@@ -48,12 +48,26 @@ bool DtxAck::prepare(TransactionContext* ctxt) throw()
void DtxAck::commit() throw()
{
- for_each(pending.begin(), pending.end(), mem_fun_ref(&DeliveryRecord::committed));
- pending.clear();
+ try {
+ for_each(pending.begin(), pending.end(), mem_fun_ref(&DeliveryRecord::committed));
+ pending.clear();
+ } catch (const std::exception& e) {
+ QPID_LOG(error, "Failed to commit: " << e.what());
+ } catch(...) {
+ QPID_LOG(error, "Failed to commit (unknown error)");
+ }
+
}
void DtxAck::rollback() throw()
{
- for_each(pending.begin(), pending.end(), mem_fun_ref(&DeliveryRecord::requeue));
- pending.clear();
+ try {
+ for_each(pending.begin(), pending.end(), mem_fun_ref(&DeliveryRecord::requeue));
+ pending.clear();
+ } catch (const std::exception& e) {
+ QPID_LOG(error, "Failed to complete rollback: " << e.what());
+ } catch(...) {
+ QPID_LOG(error, "Failed to complete rollback (unknown error)");
+ }
+
}
diff --git a/qpid/cpp/src/qpid/broker/Exchange.cpp b/qpid/cpp/src/qpid/broker/Exchange.cpp
index 90d81b81c6..757127eef2 100644
--- a/qpid/cpp/src/qpid/broker/Exchange.cpp
+++ b/qpid/cpp/src/qpid/broker/Exchange.cpp
@@ -76,6 +76,40 @@ Exchange::PreRoute::~PreRoute(){
}
}
+void Exchange::doRoute(Deliverable& msg, ConstBindingList b)
+{
+ int count = 0;
+
+ if (b.get()) {
+ // Block the content release if the message is transient AND there is more than one binding
+ if (!msg.getMessage().isPersistent() && b->size() > 1)
+ msg.getMessage().blockContentRelease();
+
+ for(std::vector<Binding::shared_ptr>::const_iterator i = b->begin(); i != b->end(); i++, count++) {
+ msg.deliverTo((*i)->queue);
+ if ((*i)->mgmtBinding != 0)
+ (*i)->mgmtBinding->inc_msgMatched();
+ }
+ }
+
+ if (mgmtExchange != 0)
+ {
+ mgmtExchange->inc_msgReceives ();
+ mgmtExchange->inc_byteReceives (msg.contentSize ());
+ if (count == 0)
+ {
+ //QPID_LOG(warning, "Exchange " << getName() << " could not route message; no matching binding found");
+ mgmtExchange->inc_msgDrops ();
+ mgmtExchange->inc_byteDrops (msg.contentSize ());
+ }
+ else
+ {
+ mgmtExchange->inc_msgRoutes (count);
+ mgmtExchange->inc_byteRoutes (count * msg.contentSize ());
+ }
+ }
+}
+
void Exchange::routeIVE(){
if (ive && lastMsg.get()){
DeliverableMessage dmsg(lastMsg);
diff --git a/qpid/cpp/src/qpid/broker/Exchange.h b/qpid/cpp/src/qpid/broker/Exchange.h
index c1e878200f..9bea376c28 100644
--- a/qpid/cpp/src/qpid/broker/Exchange.h
+++ b/qpid/cpp/src/qpid/broker/Exchange.h
@@ -79,6 +79,9 @@ protected:
Exchange* parent;
};
+ typedef boost::shared_ptr<const std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> > > ConstBindingList;
+ typedef boost::shared_ptr< std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> > > BindingList;
+ void doRoute(Deliverable& msg, ConstBindingList b);
void routeIVE();
diff --git a/qpid/cpp/src/qpid/broker/FanOutExchange.cpp b/qpid/cpp/src/qpid/broker/FanOutExchange.cpp
index e9007ba682..b7d46a33fe 100644
--- a/qpid/cpp/src/qpid/broker/FanOutExchange.cpp
+++ b/qpid/cpp/src/qpid/broker/FanOutExchange.cpp
@@ -106,36 +106,12 @@ bool FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*key*/, cons
return true;
}
-void FanOutExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* /*args*/){
+void FanOutExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* /*args*/)
+{
PreRoute pr(msg, this);
- uint32_t count(0);
-
- BindingsArray::ConstPtr p = bindings.snapshot();
- if (p.get()){
- for(std::vector<Binding::shared_ptr>::const_iterator i = p->begin(); i != p->end(); ++i, count++){
- msg.deliverTo((*i)->queue);
- if ((*i)->mgmtBinding != 0)
- (*i)->mgmtBinding->inc_msgMatched ();
- }
- }
-
- if (mgmtExchange != 0)
- {
- mgmtExchange->inc_msgReceives ();
- mgmtExchange->inc_byteReceives (msg.contentSize ());
- if (count == 0)
- {
- mgmtExchange->inc_msgDrops ();
- mgmtExchange->inc_byteDrops (msg.contentSize ());
- }
- else
- {
- mgmtExchange->inc_msgRoutes (count);
- mgmtExchange->inc_byteRoutes (count * msg.contentSize ());
- }
- }
+ doRoute(msg, bindings.snapshot());
}
-
+
bool FanOutExchange::isBound(Queue::shared_ptr queue, const string* const, const FieldTable* const)
{
BindingsArray::ConstPtr ptr = bindings.snapshot();
diff --git a/qpid/cpp/src/qpid/broker/HeadersExchange.cpp b/qpid/cpp/src/qpid/broker/HeadersExchange.cpp
index c628c44909..a7c90156e1 100644
--- a/qpid/cpp/src/qpid/broker/HeadersExchange.cpp
+++ b/qpid/cpp/src/qpid/broker/HeadersExchange.cpp
@@ -104,7 +104,8 @@ bool HeadersExchange::unbind(Queue::shared_ptr queue, const string& bindingKey,
}
-void HeadersExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* args){
+void HeadersExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* args)
+{
if (!args) {
//can't match if there were no headers passed in
if (mgmtExchange != 0) {
@@ -118,31 +119,17 @@ void HeadersExchange::route(Deliverable& msg, const string& /*routingKey*/, cons
PreRoute pr(msg, this);
- uint32_t count(0);
-
- Bindings::ConstPtr p = bindings.snapshot();
- if (p.get()){
+ ConstBindingList p = bindings.snapshot();
+ BindingList b(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >);
+ if (p.get())
+ {
for (std::vector<Binding::shared_ptr>::const_iterator i = p->begin(); i != p->end(); ++i) {
if (match((*i)->args, *args)) {
- msg.deliverTo((*i)->queue);
- count++;
- if ((*i)->mgmtBinding != 0)
- (*i)->mgmtBinding->inc_msgMatched();
+ b->push_back(*i);
}
}
}
-
- if (mgmtExchange != 0) {
- mgmtExchange->inc_msgReceives();
- mgmtExchange->inc_byteReceives(msg.contentSize());
- if (count == 0) {
- mgmtExchange->inc_msgDrops();
- mgmtExchange->inc_byteDrops(msg.contentSize());
- } else {
- mgmtExchange->inc_msgRoutes(count);
- mgmtExchange->inc_byteRoutes(count * msg.contentSize());
- }
- }
+ doRoute(msg, b);
}
diff --git a/qpid/cpp/src/qpid/broker/Message.cpp b/qpid/cpp/src/qpid/broker/Message.cpp
index 7360010192..e2799b0bff 100644
--- a/qpid/cpp/src/qpid/broker/Message.cpp
+++ b/qpid/cpp/src/qpid/broker/Message.cpp
@@ -49,7 +49,7 @@ TransferAdapter Message::TRANSFER;
Message::Message(const framing::SequenceNumber& id) :
frames(id), persistenceId(0), redelivered(false), loaded(false),
staged(false), forcePersistentPolicy(false), publisher(0), adapter(0),
- expiration(FAR_FUTURE), enqueueCallback(0), dequeueCallback(0) {}
+ expiration(FAR_FUTURE), enqueueCallback(0), dequeueCallback(0), requiredCredit(0) {}
Message::~Message()
{
@@ -98,7 +98,7 @@ const FieldTable* Message::getApplicationHeaders() const
return getAdapter().getApplicationHeaders(frames);
}
-bool Message::isPersistent()
+bool Message::isPersistent() const
{
return (getAdapter().isPersistent(frames) || forcePersistentPolicy);
}
@@ -108,12 +108,16 @@ bool Message::requiresAccept()
return getAdapter().requiresAccept(frames);
}
-uint32_t Message::getRequiredCredit() const
+uint32_t Message::getRequiredCredit()
{
- //add up payload for all header and content frames in the frameset
- SumBodySize sum;
- frames.map_if(sum, TypeFilter2<HEADER_BODY, CONTENT_BODY>());
- return sum.getSize();
+ sys::Mutex::ScopedLock l(lock);
+ if (!requiredCredit) {
+ //add up payload for all header and content frames in the frameset
+ SumBodySize sum;
+ frames.map_if(sum, TypeFilter2<HEADER_BODY, CONTENT_BODY>());
+ requiredCredit = sum.getSize();
+ }
+ return requiredCredit;
}
void Message::encode(framing::Buffer& buffer) const
@@ -181,17 +185,31 @@ void Message::decodeContent(framing::Buffer& buffer)
loaded = true;
}
-void Message::releaseContent(MessageStore* _store)
+void Message::tryReleaseContent()
{
- if (!store) {
- store = _store;
+ if (checkContentReleasable()) {
+ releaseContent();
}
+}
+
+void Message::releaseContent(MessageStore* s)
+{
+ //deprecated, use setStore(store); releaseContent(); instead
+ if (!store) setStore(s);
+ releaseContent();
+}
+
+void Message::releaseContent()
+{
+ sys::Mutex::ScopedLock l(lock);
if (store) {
if (!getPersistenceId()) {
intrusive_ptr<PersistableMessage> pmsg(this);
store->stage(pmsg);
staged = true;
}
+ //ensure required credit is cached before content frames are released
+ getRequiredCredit();
//remove any content frames from the frameset
frames.remove(TypeFilter<CONTENT_BODY>());
setContentReleased();
@@ -211,31 +229,29 @@ void Message::destroy()
bool Message::getContentFrame(const Queue& queue, AMQFrame& frame, uint16_t maxContentSize, uint64_t offset) const
{
- if (isContentReleased()) {
- intrusive_ptr<const PersistableMessage> pmsg(this);
-
- bool done = false;
- string& data = frame.castBody<AMQContentBody>()->getData();
- store->loadContent(queue, pmsg, data, offset, maxContentSize);
- done = data.size() < maxContentSize;
- frame.setBof(false);
- frame.setEof(true);
- QPID_LOG(debug, "loaded frame" << frame);
- if (offset > 0) {
- frame.setBos(false);
- }
- if (!done) {
- frame.setEos(false);
- } else return false;
- return true;
+ intrusive_ptr<const PersistableMessage> pmsg(this);
+
+ bool done = false;
+ string& data = frame.castBody<AMQContentBody>()->getData();
+ store->loadContent(queue, pmsg, data, offset, maxContentSize);
+ done = data.size() < maxContentSize;
+ frame.setBof(false);
+ frame.setEof(true);
+ QPID_LOG(debug, "loaded frame" << frame);
+ if (offset > 0) {
+ frame.setBos(false);
}
- else return false;
+ if (!done) {
+ frame.setEos(false);
+ } else return false;
+ return true;
}
void Message::sendContent(const Queue& queue, framing::FrameHandler& out, uint16_t maxFrameSize) const
{
+ sys::Mutex::ScopedLock l(lock);
if (isContentReleased() && !frames.isComplete()) {
-
+ sys::Mutex::ScopedUnlock u(lock);
uint16_t maxContentSize = maxFrameSize - AMQFrame::frameOverhead();
bool morecontent = true;
for (uint64_t offset = 0; morecontent; offset += maxContentSize)
@@ -373,28 +389,36 @@ void Message::setReplacementMessage(boost::intrusive_ptr<Message> msg, const Que
}
void Message::allEnqueuesComplete() {
- MessageCallback* cb = 0;
- {
- sys::Mutex::ScopedLock l(lock);
- std::swap(cb, enqueueCallback);
- }
+ sys::Mutex::ScopedLock l(callbackLock);
+ MessageCallback* cb = enqueueCallback;
if (cb && *cb) (*cb)(intrusive_ptr<Message>(this));
}
void Message::allDequeuesComplete() {
- MessageCallback* cb = 0;
- {
- sys::Mutex::ScopedLock l(lock);
- std::swap(cb, dequeueCallback);
- }
+ sys::Mutex::ScopedLock l(callbackLock);
+ MessageCallback* cb = dequeueCallback;
if (cb && *cb) (*cb)(intrusive_ptr<Message>(this));
}
-void Message::setEnqueueCompleteCallback(MessageCallback& cb) { enqueueCallback = &cb; }
-void Message::resetEnqueueCompleteCallback() { enqueueCallback = 0; }
+void Message::setEnqueueCompleteCallback(MessageCallback& cb) {
+ sys::Mutex::ScopedLock l(callbackLock);
+ enqueueCallback = &cb;
+}
+
+void Message::resetEnqueueCompleteCallback() {
+ sys::Mutex::ScopedLock l(callbackLock);
+ enqueueCallback = 0;
+}
-void Message::setDequeueCompleteCallback(MessageCallback& cb) { dequeueCallback = &cb; }
-void Message::resetDequeueCompleteCallback() { dequeueCallback = 0; }
+void Message::setDequeueCompleteCallback(MessageCallback& cb) {
+ sys::Mutex::ScopedLock l(callbackLock);
+ dequeueCallback = &cb;
+}
+
+void Message::resetDequeueCompleteCallback() {
+ sys::Mutex::ScopedLock l(callbackLock);
+ dequeueCallback = 0;
+}
framing::FieldTable& Message::getOrInsertHeaders()
{
diff --git a/qpid/cpp/src/qpid/broker/Message.h b/qpid/cpp/src/qpid/broker/Message.h
index e4d09b1042..3894960c95 100644
--- a/qpid/cpp/src/qpid/broker/Message.h
+++ b/qpid/cpp/src/qpid/broker/Message.h
@@ -74,7 +74,7 @@ public:
bool isImmediate() const;
QPID_BROKER_EXTERN const framing::FieldTable* getApplicationHeaders() const;
framing::FieldTable& getOrInsertHeaders();
- QPID_BROKER_EXTERN bool isPersistent();
+ QPID_BROKER_EXTERN bool isPersistent() const;
bool requiresAccept();
QPID_BROKER_EXTERN void setTimestamp(const boost::intrusive_ptr<ExpiryPolicy>& e);
@@ -108,7 +108,7 @@ public:
return frames.isA<T>();
}
- uint32_t getRequiredCredit() const;
+ uint32_t getRequiredCredit();
void encode(framing::Buffer& buffer) const;
void encodeContent(framing::Buffer& buffer) const;
@@ -129,12 +129,9 @@ public:
QPID_BROKER_EXTERN void decodeHeader(framing::Buffer& buffer);
QPID_BROKER_EXTERN void decodeContent(framing::Buffer& buffer);
- /**
- * Releases the in-memory content data held by this
- * message. Must pass in a store from which the data can
- * be reloaded.
- */
- void releaseContent(MessageStore* store);
+ void QPID_BROKER_EXTERN tryReleaseContent();
+ void releaseContent();
+ void releaseContent(MessageStore* s);//deprecated, use 'setStore(store); releaseContent();' instead
void destroy();
bool getContentFrame(const Queue& queue, framing::AMQFrame& frame, uint16_t maxContentSize, uint64_t offset) const;
@@ -187,8 +184,12 @@ public:
mutable Replacement replacement;
mutable boost::intrusive_ptr<Message> empty;
+
+ sys::Mutex callbackLock;
MessageCallback* enqueueCallback;
MessageCallback* dequeueCallback;
+
+ uint32_t requiredCredit;
static std::string updateDestination;
};
diff --git a/qpid/cpp/src/qpid/broker/MessageBuilder.cpp b/qpid/cpp/src/qpid/broker/MessageBuilder.cpp
index 14b233fd6c..b1a2b77b05 100644
--- a/qpid/cpp/src/qpid/broker/MessageBuilder.cpp
+++ b/qpid/cpp/src/qpid/broker/MessageBuilder.cpp
@@ -80,7 +80,7 @@ void MessageBuilder::handle(AMQFrame& frame)
&& !NullMessageStore::isNullStore(store)
&& message->getExchangeName() != QPID_MANAGEMENT /* don't stage mgnt messages */)
{
- message->releaseContent(store);
+ message->releaseContent();
staging = true;
}
}
@@ -96,6 +96,7 @@ void MessageBuilder::end()
void MessageBuilder::start(const SequenceNumber& id)
{
message = intrusive_ptr<Message>(new Message(id));
+ message->setStore(store);
state = METHOD;
staging = false;
}
diff --git a/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp b/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp
index 0b8a5db1c7..5f7cceebd3 100644
--- a/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp
+++ b/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp
@@ -32,11 +32,11 @@ using qpid::framing::FieldTable;
namespace qpid {
namespace broker {
-MessageStoreModule::MessageStoreModule(MessageStore* _store) : store(_store) {}
+MessageStoreModule::MessageStoreModule(boost::shared_ptr<MessageStore>& _store)
+ : store(_store) {}
MessageStoreModule::~MessageStoreModule()
{
- delete store;
}
bool MessageStoreModule::init(const Options*) { return true; }
@@ -173,7 +173,7 @@ void MessageStoreModule::collectPreparedXids(std::set<std::string>& xids)
bool MessageStoreModule::isNull() const
{
- return NullMessageStore::isNullStore(store);
+ return NullMessageStore::isNullStore(store.get());
}
}} // namespace qpid::broker
diff --git a/qpid/cpp/src/qpid/broker/MessageStoreModule.h b/qpid/cpp/src/qpid/broker/MessageStoreModule.h
index 02cbd13cf1..56b5a3c1ae 100644
--- a/qpid/cpp/src/qpid/broker/MessageStoreModule.h
+++ b/qpid/cpp/src/qpid/broker/MessageStoreModule.h
@@ -26,6 +26,7 @@
#include "qpid/broker/RecoveryManager.h"
#include <boost/intrusive_ptr.hpp>
+#include <boost/shared_ptr.hpp>
namespace qpid {
namespace broker {
@@ -35,9 +36,9 @@ namespace broker {
*/
class MessageStoreModule : public MessageStore
{
- MessageStore* store;
+ boost::shared_ptr<MessageStore> store;
public:
- MessageStoreModule(MessageStore* store);
+ MessageStoreModule(boost::shared_ptr<MessageStore>& store);
bool init(const Options* options);
void truncateInit(const bool pushDownStoreFiles = false);
diff --git a/qpid/cpp/src/qpid/broker/PersistableMessage.cpp b/qpid/cpp/src/qpid/broker/PersistableMessage.cpp
index 2ef223aa81..303a0501f4 100644
--- a/qpid/cpp/src/qpid/broker/PersistableMessage.cpp
+++ b/qpid/cpp/src/qpid/broker/PersistableMessage.cpp
@@ -36,7 +36,6 @@ PersistableMessage::~PersistableMessage() {}
PersistableMessage::PersistableMessage() :
asyncEnqueueCounter(0),
asyncDequeueCounter(0),
- contentReleased(false),
store(0)
{}
@@ -59,9 +58,15 @@ void PersistableMessage::flush()
}
}
-void PersistableMessage::setContentReleased() {contentReleased = true; }
+void PersistableMessage::setContentReleased()
+{
+ contentReleaseState.released = true;
+}
-bool PersistableMessage::isContentReleased()const { return contentReleased; }
+bool PersistableMessage::isContentReleased() const
+{
+ return contentReleaseState.released;
+}
bool PersistableMessage::isEnqueueComplete() {
sys::ScopedLock<sys::Mutex> l(asyncEnqueueLock);
@@ -153,6 +158,26 @@ void PersistableMessage::dequeueAsync() {
asyncDequeueCounter++;
}
+PersistableMessage::ContentReleaseState::ContentReleaseState() : blocked(false), requested(false), released(false) {}
+
+void PersistableMessage::setStore(MessageStore* s)
+{
+ store = s;
+}
+
+void PersistableMessage::requestContentRelease()
+{
+ contentReleaseState.requested = true;
+}
+void PersistableMessage::blockContentRelease()
+{
+ contentReleaseState.blocked = true;
+}
+bool PersistableMessage::checkContentReleasable()
+{
+ return contentReleaseState.requested && !contentReleaseState.blocked;
+}
+
}}
diff --git a/qpid/cpp/src/qpid/broker/PersistableMessage.h b/qpid/cpp/src/qpid/broker/PersistableMessage.h
index 0274b41375..2576e266d2 100644
--- a/qpid/cpp/src/qpid/broker/PersistableMessage.h
+++ b/qpid/cpp/src/qpid/broker/PersistableMessage.h
@@ -68,8 +68,16 @@ class PersistableMessage : public Persistable
void enqueueAsync();
void dequeueAsync();
- bool contentReleased;
syncList synclist;
+ struct ContentReleaseState
+ {
+ bool blocked;
+ bool requested;
+ bool released;
+
+ ContentReleaseState();
+ };
+ ContentReleaseState contentReleaseState;
protected:
/** Called when all enqueues are complete for this message. */
@@ -96,8 +104,15 @@ class PersistableMessage : public Persistable
void flush();
- bool isContentReleased() const;
-
+ bool QPID_BROKER_EXTERN isContentReleased() const;
+
+ void QPID_BROKER_EXTERN setStore(MessageStore*);
+ void requestContentRelease();
+ void blockContentRelease();
+ bool checkContentReleasable();
+
+ virtual QPID_BROKER_EXTERN bool isPersistent() const = 0;
+
QPID_BROKER_EXTERN bool isEnqueueComplete();
QPID_BROKER_EXTERN void enqueueComplete();
diff --git a/qpid/cpp/src/qpid/broker/Queue.cpp b/qpid/cpp/src/qpid/broker/Queue.cpp
index b2a8e223c5..86de96468d 100644
--- a/qpid/cpp/src/qpid/broker/Queue.cpp
+++ b/qpid/cpp/src/qpid/broker/Queue.cpp
@@ -181,6 +181,8 @@ void Queue::deliver(boost::intrusive_ptr<Message>& msg){
void Queue::recover(boost::intrusive_ptr<Message>& msg){
+ if (policy.get()) policy->recoverEnqueued(msg);
+
push(msg, true);
if (store){
// setup synclist for recovered messages, so they don't get re-stored on lastNodeFailure
@@ -206,11 +208,10 @@ void Queue::process(boost::intrusive_ptr<Message>& msg){
}
void Queue::requeue(const QueuedMessage& msg){
- if (!isEnqueued(msg)) return;
-
QueueListeners::NotificationSet copy;
{
Mutex::ScopedLock locker(messageLock);
+ if (!isEnqueued(msg)) return;
msg.payload->enqueueComplete(); // mark the message as enqueued
messages.push_front(msg);
listeners.populate(copy);
@@ -563,16 +564,10 @@ void Queue::popMsg(QueuedMessage& qmsg)
}
void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){
- Messages dequeues;
QueueListeners::NotificationSet copy;
{
Mutex::ScopedLock locker(messageLock);
QueuedMessage qm(this, msg, ++sequence);
- if (policy.get()) {
- policy->tryEnqueue(qm);
- //depending on policy, may have some dequeues
- if (!isRecovery) pendingDequeues.swap(dequeues);
- }
if (insertSeqNo) msg->getOrInsertHeaders().setInt64(seqNoKey, sequence);
LVQ::iterator i;
@@ -606,12 +601,11 @@ void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){
if (eventMgr) eventMgr->enqueued(qm);
else QPID_LOG(warning, "Enqueue manager not set, events not generated for " << getName());
}
+ if (policy.get()) {
+ policy->enqueued(qm);
+ }
}
copy.notify();
- if (!dequeues.empty()) {
- //depending on policy, may have some dequeues
- for_each(dequeues.begin(), dequeues.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1));
- }
}
QueuedMessage Queue::getFront()
@@ -697,8 +691,19 @@ void Queue::setLastNodeFailure()
}
// return true if store exists,
-bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message> msg)
+bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message> msg, bool suppressPolicyCheck)
{
+ if (policy.get() && !suppressPolicyCheck) {
+ Messages dequeues;
+ {
+ Mutex::ScopedLock locker(messageLock);
+ policy->tryEnqueue(msg);
+ policy->getPendingDequeues(dequeues);
+ }
+ //depending on policy, may have some dequeues that need to performed without holding the lock
+ for_each(dequeues.begin(), dequeues.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1));
+ }
+
if (inLastNodeFailure && persistLastNode){
msg->forcePersistent();
}
@@ -707,15 +712,27 @@ bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message> msg)
msg->addTraceId(traceId);
}
- if (msg->isPersistent() && store) {
+ if ((msg->isPersistent() || msg->checkContentReleasable()) && store) {
msg->enqueueAsync(shared_from_this(), store); //increment to async counter -- for message sent to more than one queue
boost::intrusive_ptr<PersistableMessage> pmsg = boost::static_pointer_cast<PersistableMessage>(msg);
store->enqueue(ctxt, pmsg, *this);
return true;
}
+ if (!store) {
+ //Messages enqueued on a transient queue should be prevented
+ //from having their content released as it may not be
+ //recoverable by these queue for delivery
+ msg->blockContentRelease();
+ }
return false;
}
+void Queue::enqueueAborted(boost::intrusive_ptr<Message> msg)
+{
+ Mutex::ScopedLock locker(messageLock);
+ if (policy.get()) policy->enqueueAborted(msg);
+}
+
// return true if store exists,
bool Queue::dequeue(TransactionContext* ctxt, const QueuedMessage& msg)
{
@@ -726,7 +743,7 @@ bool Queue::dequeue(TransactionContext* ctxt, const QueuedMessage& msg)
dequeued(msg);
}
}
- if (msg.payload->isPersistent() && store) {
+ if ((msg.payload->isPersistent() || msg.payload->checkContentReleasable()) && store) {
msg.payload->dequeueAsync(shared_from_this(), store); //increment to async counter -- for message sent to more than one queue
boost::intrusive_ptr<PersistableMessage> pmsg = boost::static_pointer_cast<PersistableMessage>(msg.payload);
store->dequeue(ctxt, pmsg, *this);
@@ -781,22 +798,37 @@ void Queue::create(const FieldTable& _settings)
void Queue::configure(const FieldTable& _settings, bool recovering)
{
- setPolicy(QueuePolicy::createQueuePolicy(_settings));
+
+ eventMode = _settings.getAsInt(qpidQueueEventGeneration);
+
+ if (QueuePolicy::getType(_settings) == QueuePolicy::FLOW_TO_DISK &&
+ (!store || NullMessageStore::isNullStore(store) || (eventMode && eventMgr && !eventMgr->isSync()) )) {
+ if ( NullMessageStore::isNullStore(store)) {
+ QPID_LOG(warning, "Flow to disk not valid for non-persisted queue:" << getName());
+ } else if (eventMgr && !eventMgr->isSync() ) {
+ QPID_LOG(warning, "Flow to disk not valid with async Queue Events:" << getName());
+ }
+ FieldTable copy(_settings);
+ copy.erase(QueuePolicy::typeKey);
+ setPolicy(QueuePolicy::createQueuePolicy(getName(), copy));
+ } else {
+ setPolicy(QueuePolicy::createQueuePolicy(getName(), _settings));
+ }
//set this regardless of owner to allow use of no-local with exclusive consumers also
noLocal = _settings.get(qpidNoLocal);
- QPID_LOG(debug, "Configured queue with no-local=" << noLocal);
+ QPID_LOG(debug, "Configured queue " << getName() << " with no-local=" << noLocal);
lastValueQueue= _settings.get(qpidLastValueQueue);
- if (lastValueQueue) QPID_LOG(debug, "Configured queue as Last Value Queue");
+ if (lastValueQueue) QPID_LOG(debug, "Configured queue as Last Value Queue for: " << getName());
lastValueQueueNoBrowse = _settings.get(qpidLastValueQueueNoBrowse);
if (lastValueQueueNoBrowse){
- QPID_LOG(debug, "Configured queue as Last Value Queue No Browse");
+ QPID_LOG(debug, "Configured queue as Last Value Queue No Browse for: " << getName());
lastValueQueue = lastValueQueueNoBrowse;
}
persistLastNode= _settings.get(qpidPersistLastNode);
- if (persistLastNode) QPID_LOG(debug, "Configured queue to Persist data if cluster fails to one node");
+ if (persistLastNode) QPID_LOG(debug, "Configured queue to Persist data if cluster fails to one node for: " << getName());
traceId = _settings.getAsString(qpidTraceIdentity);
std::string excludeList = _settings.getAsString(qpidTraceExclude);
@@ -806,8 +838,6 @@ void Queue::configure(const FieldTable& _settings, bool recovering)
QPID_LOG(debug, "Configured queue " << getName() << " with qpid.trace.id='" << traceId
<< "' and qpid.trace.exclude='"<< excludeList << "' i.e. " << traceExclude.size() << " elements");
- eventMode = _settings.getAsInt(qpidQueueEventGeneration);
-
FieldTable::ValuePtr p =_settings.get(qpidInsertSequenceNumbers);
if (p && p->convertsTo<std::string>()) insertSequenceNumbers(p->get<std::string>());
@@ -975,19 +1005,6 @@ void Queue::setExternalQueueStore(ExternalQueueStore* inst) {
}
}
-bool Queue::releaseMessageContent(const QueuedMessage& m)
-{
- if (store && !NullMessageStore::isNullStore(store)) {
- QPID_LOG(debug, "Message " << m.position << " on " << name << " released from memory");
- m.payload->releaseContent(store);
- return true;
- } else {
- QPID_LOG(warning, "Message " << m.position << " on " << name
- << " cannot be released from memory as the queue is not durable");
- return false;
- }
-}
-
ManagementObject* Queue::GetManagementObject (void) const
{
return (ManagementObject*) mgmtObject;
@@ -1044,11 +1061,12 @@ void Queue::insertSequenceNumbers(const std::string& key)
void Queue::enqueued(const QueuedMessage& m)
{
if (m.payload) {
- if (policy.get()) policy->tryEnqueue(m);
- mgntEnqStats(m.payload);
- if (m.payload->isPersistent()) {
- enqueue ( 0, m.payload );
+ if (policy.get()) {
+ policy->recoverEnqueued(m.payload);
+ policy->enqueued(m);
}
+ mgntEnqStats(m.payload);
+ enqueue ( 0, m.payload, true );
} else {
QPID_LOG(warning, "Queue informed of enqueued message that has no payload");
}
@@ -1059,10 +1077,4 @@ bool Queue::isEnqueued(const QueuedMessage& msg)
return !policy.get() || policy->isEnqueued(msg);
}
-void Queue::addPendingDequeue(const QueuedMessage& msg)
-{
- //assumes lock is held - true at present but rather nasty as this is a public method
- pendingDequeues.push_back(msg);
-}
-
QueueListeners& Queue::getListeners() { return listeners; }
diff --git a/qpid/cpp/src/qpid/broker/Queue.h b/qpid/cpp/src/qpid/broker/Queue.h
index 77799fd967..661e46f619 100644
--- a/qpid/cpp/src/qpid/broker/Queue.h
+++ b/qpid/cpp/src/qpid/broker/Queue.h
@@ -239,7 +239,8 @@ namespace qpid {
QPID_BROKER_EXTERN void setLastNodeFailure();
QPID_BROKER_EXTERN void clearLastNodeFailure();
- bool enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message> msg);
+ bool enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message> msg, bool suppressPolicyCheck = false);
+ void enqueueAborted(boost::intrusive_ptr<Message> msg);
/**
* dequeue from store (only done once messages is acknowledged)
*/
@@ -315,8 +316,6 @@ namespace qpid {
bindings.eachBinding(f);
}
- bool releaseMessageContent(const QueuedMessage&);
-
void popMsg(QueuedMessage& qmsg);
/** Set the position sequence number for the next message on the queue.
@@ -335,18 +334,6 @@ namespace qpid {
*/
void recoveryComplete();
- /**
- * This is a hack to avoid deadlocks in durable ring
- * queues. It is used for dequeueing messages in response
- * to an enqueue while avoid holding lock over call to
- * store.
- *
- * Assumes messageLock is held - true for curent use case
- * (QueuePolicy::tryEnqueue()) but rather nasty as this is a public
- * method
- **/
- void addPendingDequeue(const QueuedMessage &msg);
-
// For cluster update
QueueListeners& getListeners();
};
diff --git a/qpid/cpp/src/qpid/broker/QueueEvents.cpp b/qpid/cpp/src/qpid/broker/QueueEvents.cpp
index 6df869673d..bba054b0b8 100644
--- a/qpid/cpp/src/qpid/broker/QueueEvents.cpp
+++ b/qpid/cpp/src/qpid/broker/QueueEvents.cpp
@@ -25,25 +25,41 @@
namespace qpid {
namespace broker {
-QueueEvents::QueueEvents(const boost::shared_ptr<sys::Poller>& poller) :
- eventQueue(boost::bind(&QueueEvents::handle, this, _1), poller), enabled(true)
+QueueEvents::QueueEvents(const boost::shared_ptr<sys::Poller>& poller, bool isSync) :
+ eventQueue(boost::bind(&QueueEvents::handle, this, _1), poller), enabled(true), sync(isSync)
{
- eventQueue.start();
+ if (!sync) eventQueue.start();
}
QueueEvents::~QueueEvents()
{
- eventQueue.stop();
+ if (!sync) eventQueue.stop();
}
void QueueEvents::enqueued(const QueuedMessage& m)
{
- if (enabled) eventQueue.push(Event(ENQUEUE, m));
+ if (enabled) {
+ Event enq(ENQUEUE, m);
+ if (sync) {
+ for (Listeners::iterator j = listeners.begin(); j != listeners.end(); j++)
+ j->second(enq);
+ } else {
+ eventQueue.push(enq);
+ }
+ }
}
void QueueEvents::dequeued(const QueuedMessage& m)
{
- if (enabled) eventQueue.push(Event(DEQUEUE, m));
+ if (enabled) {
+ Event deq(DEQUEUE, m);
+ if (sync) {
+ for (Listeners::iterator j = listeners.begin(); j != listeners.end(); j++)
+ j->second(deq);
+ } else {
+ eventQueue.push(Event(DEQUEUE, m));
+ }
+ }
}
void QueueEvents::registerListener(const std::string& id, const EventListener& listener)
@@ -70,15 +86,16 @@ QueueEvents::EventQueue::Batch::const_iterator
QueueEvents::handle(const EventQueue::Batch& events) {
qpid::sys::Mutex::ScopedLock l(lock);
for (EventQueue::Batch::const_iterator i = events.begin(); i != events.end(); ++i) {
- for (Listeners::iterator j = listeners.begin(); j != listeners.end(); j++)
- j->second(*i);
+ for (Listeners::iterator j = listeners.begin(); j != listeners.end(); j++) {
+ j->second(*i);
+ }
}
return events.end();
}
void QueueEvents::shutdown()
{
- if (!eventQueue.empty() && !listeners.empty()) eventQueue.shutdown();
+ if (!sync && !eventQueue.empty() && !listeners.empty()) eventQueue.shutdown();
}
void QueueEvents::enable()
@@ -93,6 +110,12 @@ void QueueEvents::disable()
QPID_LOG(debug, "Queue events disabled");
}
+bool QueueEvents::isSync()
+{
+ return sync;
+}
+
+
QueueEvents::Event::Event(EventType t, const QueuedMessage& m) : type(t), msg(m) {}
diff --git a/qpid/cpp/src/qpid/broker/QueueEvents.h b/qpid/cpp/src/qpid/broker/QueueEvents.h
index 6826c6e79a..c42752133e 100644
--- a/qpid/cpp/src/qpid/broker/QueueEvents.h
+++ b/qpid/cpp/src/qpid/broker/QueueEvents.h
@@ -54,7 +54,7 @@ class QueueEvents
typedef boost::function<void (Event)> EventListener;
- QPID_BROKER_EXTERN QueueEvents(const boost::shared_ptr<sys::Poller>& poller);
+ QPID_BROKER_EXTERN QueueEvents(const boost::shared_ptr<sys::Poller>& poller, bool isSync = false);
QPID_BROKER_EXTERN ~QueueEvents();
QPID_BROKER_EXTERN void enqueued(const QueuedMessage&);
QPID_BROKER_EXTERN void dequeued(const QueuedMessage&);
@@ -65,6 +65,7 @@ class QueueEvents
void disable();
//process all outstanding events
QPID_BROKER_EXTERN void shutdown();
+ QPID_BROKER_EXTERN bool isSync();
private:
typedef qpid::sys::PollableQueue<Event> EventQueue;
typedef std::map<std::string, EventListener> Listeners;
@@ -73,6 +74,7 @@ class QueueEvents
Listeners listeners;
volatile bool enabled;
qpid::sys::Mutex lock;//protect listeners from concurrent access
+ bool sync;
EventQueue::Batch::const_iterator handle(const EventQueue::Batch& e);
diff --git a/qpid/cpp/src/qpid/broker/QueuePolicy.cpp b/qpid/cpp/src/qpid/broker/QueuePolicy.cpp
index 39afe90134..a8aa674c53 100644
--- a/qpid/cpp/src/qpid/broker/QueuePolicy.cpp
+++ b/qpid/cpp/src/qpid/broker/QueuePolicy.cpp
@@ -28,8 +28,8 @@
using namespace qpid::broker;
using namespace qpid::framing;
-QueuePolicy::QueuePolicy(uint32_t _maxCount, uint64_t _maxSize, const std::string& _type) :
- maxCount(_maxCount), maxSize(_maxSize), type(_type), count(0), size(0), policyExceeded(false) {}
+QueuePolicy::QueuePolicy(const std::string& _name, uint32_t _maxCount, uint64_t _maxSize, const std::string& _type) :
+ maxCount(_maxCount), maxSize(_maxSize), type(_type), count(0), size(0), policyExceeded(false), name(_name) {}
void QueuePolicy::enqueued(uint64_t _size)
{
@@ -39,18 +39,15 @@ void QueuePolicy::enqueued(uint64_t _size)
void QueuePolicy::dequeued(uint64_t _size)
{
- //Note: underflow detection is not reliable in the face of
- //concurrent updates (at present locking in Queue.cpp prevents
- //these anyway); updates are atomic and are safe regardless.
if (maxCount) {
- if (count.get() > 0) {
+ if (count > 0) {
--count;
} else {
throw Exception(QPID_MSG("Attempted count underflow on dequeue(" << _size << "): " << *this));
}
}
if (maxSize) {
- if (_size > size.get()) {
+ if (_size > size) {
throw Exception(QPID_MSG("Attempted size underflow on dequeue(" << _size << "): " << *this));
} else {
size -= _size;
@@ -58,47 +55,47 @@ void QueuePolicy::dequeued(uint64_t _size)
}
}
-bool QueuePolicy::checkLimit(const QueuedMessage& m)
+bool QueuePolicy::checkLimit(boost::intrusive_ptr<Message> m)
{
- bool sizeExceeded = maxSize && (size.get() + m.payload->contentSize()) > maxSize;
- bool countExceeded = maxCount && (count.get() + 1) > maxCount;
+ bool sizeExceeded = maxSize && (size + m->contentSize()) > maxSize;
+ bool countExceeded = maxCount && (count + 1) > maxCount;
bool exceeded = sizeExceeded || countExceeded;
if (exceeded) {
if (!policyExceeded) {
- policyExceeded = true;
- if (m.queue) {
- if (sizeExceeded) QPID_LOG(info, "Queue cumulative message size exceeded policy for " << m.queue->getName());
- if (countExceeded) QPID_LOG(info, "Queue message count exceeded policy for " << m.queue->getName());
- }
+ policyExceeded = true;
+ if (sizeExceeded) QPID_LOG(info, "Queue cumulative message size exceeded policy for " << name);
+ if (countExceeded) QPID_LOG(info, "Queue message count exceeded policy for " << name);
}
} else {
if (policyExceeded) {
policyExceeded = false;
- if (m.queue) {
- QPID_LOG(info, "Queue cumulative message size and message count within policy for " << m.queue->getName());
- }
+ QPID_LOG(info, "Queue cumulative message size and message count within policy for " << name);
}
}
return !exceeded;
}
-void QueuePolicy::tryEnqueue(const QueuedMessage& m)
+void QueuePolicy::tryEnqueue(boost::intrusive_ptr<Message> m)
{
if (checkLimit(m)) {
- enqueued(m);
+ enqueued(m->contentSize());
} else {
- std::string queue = m.queue ? m.queue->getName() : std::string("unknown queue");
- throw ResourceLimitExceededException(
- QPID_MSG("Policy exceeded on " << queue << " by message " << m.position
- << " of size " << m.payload->contentSize() << " , policy: " << *this));
+ throw ResourceLimitExceededException(QPID_MSG("Policy exceeded on " << name << ", policy: " << *this));
}
}
-void QueuePolicy::enqueued(const QueuedMessage& m)
+void QueuePolicy::recoverEnqueued(boost::intrusive_ptr<Message> m)
{
- enqueued(m.payload->contentSize());
+ enqueued(m->contentSize());
}
+void QueuePolicy::enqueueAborted(boost::intrusive_ptr<Message> m)
+{
+ dequeued(m->contentSize());
+}
+
+void QueuePolicy::enqueued(const QueuedMessage&) {}
+
void QueuePolicy::dequeued(const QueuedMessage& m)
{
dequeued(m.payload->contentSize());
@@ -132,7 +129,7 @@ std::string QueuePolicy::getType(const FieldTable& settings)
std::transform(t.begin(), t.end(), t.begin(), tolower);
if (t == REJECT || t == FLOW_TO_DISK || t == RING || t == RING_STRICT) return t;
}
- return FLOW_TO_DISK;
+ return REJECT;
}
void QueuePolicy::setDefaultMaxSize(uint64_t s)
@@ -140,6 +137,7 @@ void QueuePolicy::setDefaultMaxSize(uint64_t s)
defaultMaxSize = s;
}
+void QueuePolicy::getPendingDequeues(Messages&) {}
@@ -148,8 +146,8 @@ void QueuePolicy::encode(Buffer& buffer) const
{
buffer.putLong(maxCount);
buffer.putLongLong(maxSize);
- buffer.putLong(count.get());
- buffer.putLongLong(size.get());
+ buffer.putLong(count);
+ buffer.putLongLong(size);
}
void QueuePolicy::decode ( Buffer& buffer )
@@ -179,16 +177,18 @@ const std::string QueuePolicy::RING("ring");
const std::string QueuePolicy::RING_STRICT("ring_strict");
uint64_t QueuePolicy::defaultMaxSize(0);
-FlowToDiskPolicy::FlowToDiskPolicy(uint32_t _maxCount, uint64_t _maxSize) :
- QueuePolicy(_maxCount, _maxSize, FLOW_TO_DISK) {}
+FlowToDiskPolicy::FlowToDiskPolicy(const std::string& _name, uint32_t _maxCount, uint64_t _maxSize) :
+ QueuePolicy(_name, _maxCount, _maxSize, FLOW_TO_DISK) {}
-bool FlowToDiskPolicy::checkLimit(const QueuedMessage& m)
+bool FlowToDiskPolicy::checkLimit(boost::intrusive_ptr<Message> m)
{
- return QueuePolicy::checkLimit(m) || m.queue->releaseMessageContent(m);
+ if (!QueuePolicy::checkLimit(m)) m->requestContentRelease();
+ return true;
}
-RingQueuePolicy::RingQueuePolicy(uint32_t _maxCount, uint64_t _maxSize, const std::string& _type) :
- QueuePolicy(_maxCount, _maxSize, _type), strict(_type == RING_STRICT) {}
+RingQueuePolicy::RingQueuePolicy(const std::string& _name,
+ uint32_t _maxCount, uint64_t _maxSize, const std::string& _type) :
+ QueuePolicy(_name, _maxCount, _maxSize, _type), strict(_type == RING_STRICT) {}
bool before(const QueuedMessage& a, const QueuedMessage& b)
{
@@ -197,15 +197,12 @@ bool before(const QueuedMessage& a, const QueuedMessage& b)
void RingQueuePolicy::enqueued(const QueuedMessage& m)
{
- QueuePolicy::enqueued(m);
- qpid::sys::Mutex::ScopedLock l(lock);
//need to insert in correct location based on position
queue.insert(lower_bound(queue.begin(), queue.end(), m, before), m);
}
void RingQueuePolicy::dequeued(const QueuedMessage& m)
{
- qpid::sys::Mutex::ScopedLock l(lock);
//find and remove m from queue
if (find(m, pendingDequeues, true) || find(m, queue, true)) {
//now update count and size
@@ -215,49 +212,32 @@ void RingQueuePolicy::dequeued(const QueuedMessage& m)
bool RingQueuePolicy::isEnqueued(const QueuedMessage& m)
{
- qpid::sys::Mutex::ScopedLock l(lock);
//for non-strict ring policy, a message can be replaced (and
//therefore dequeued) before it is accepted or released by
//subscriber; need to detect this
return find(m, pendingDequeues, false) || find(m, queue, false);
}
-bool RingQueuePolicy::checkLimit(const QueuedMessage& m)
+bool RingQueuePolicy::checkLimit(boost::intrusive_ptr<Message> m)
{
if (QueuePolicy::checkLimit(m)) return true;//if haven't hit limit, ok to accept
QueuedMessage oldest;
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- if (queue.empty()) {
- QPID_LOG(debug, "Message too large for ring queue "
- << (m.queue ? m.queue->getName() : std::string("unknown queue"))
- << " [" << *this << "] "
- << ": message size = " << m.payload->contentSize() << " bytes");
- return false;
- }
- oldest = queue.front();
+ if (queue.empty()) {
+ QPID_LOG(debug, "Message too large for ring queue " << name
+ << " [" << *this << "] "
+ << ": message size = " << m->contentSize() << " bytes");
+ return false;
}
+ oldest = queue.front();
if (oldest.queue->acquire(oldest) || !strict) {
- {
- //TODO: fix this! In the current code, this method is
- //only ever called with the Queue lock already taken. This
- //should not be relied upon going forward however and
- //clearly the locking in this class is insufficient as
- //there is no guarantee that the message previously atthe
- //front is still there.
- qpid::sys::Mutex::ScopedLock l(lock);
- queue.pop_front();
- pendingDequeues.push_back(oldest);
- }
- oldest.queue->addPendingDequeue(oldest);
- QPID_LOG(debug, "Ring policy triggered in queue "
- << (m.queue ? m.queue->getName() : std::string("unknown queue"))
- << ": removed message " << oldest.position << " to make way for " << m.position);
+ queue.pop_front();
+ pendingDequeues.push_back(oldest);
+ QPID_LOG(debug, "Ring policy triggered in " << name
+ << ": removed message " << oldest.position << " to make way for new message");
return true;
} else {
- QPID_LOG(debug, "Ring policy could not be triggered in queue "
- << (m.queue ? m.queue->getName() : std::string("unknown queue"))
+ QPID_LOG(debug, "Ring policy could not be triggered in " << name
<< ": oldest message (seq-no=" << oldest.position << ") has been delivered but not yet acknowledged or requeued");
//in strict mode, if oldest message has been delivered (hence
//cannot be acquired) but not yet acked, it should not be
@@ -266,6 +246,11 @@ bool RingQueuePolicy::checkLimit(const QueuedMessage& m)
}
}
+void RingQueuePolicy::getPendingDequeues(Messages& result)
+{
+ result = pendingDequeues;
+}
+
bool RingQueuePolicy::find(const QueuedMessage& m, Messages& q, bool remove)
{
for (Messages::iterator i = q.begin(); i != q.end(); i++) {
@@ -277,25 +262,36 @@ bool RingQueuePolicy::find(const QueuedMessage& m, Messages& q, bool remove)
return false;
}
+std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(uint32_t maxCount, uint64_t maxSize, const std::string& type)
+{
+ return createQueuePolicy("<unspecified>", maxCount, maxSize, type);
+}
+
std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const qpid::framing::FieldTable& settings)
{
+ return createQueuePolicy("<unspecified>", settings);
+}
+
+std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const std::string& name, const qpid::framing::FieldTable& settings)
+{
uint32_t maxCount = getInt(settings, maxCountKey, 0);
uint32_t maxSize = getInt(settings, maxSizeKey, defaultMaxSize);
if (maxCount || maxSize) {
- return createQueuePolicy(maxCount, maxSize, getType(settings));
+ return createQueuePolicy(name, maxCount, maxSize, getType(settings));
} else {
return std::auto_ptr<QueuePolicy>();
}
}
-std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(uint32_t maxCount, uint64_t maxSize, const std::string& type)
+std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const std::string& name,
+ uint32_t maxCount, uint64_t maxSize, const std::string& type)
{
if (type == RING || type == RING_STRICT) {
- return std::auto_ptr<QueuePolicy>(new RingQueuePolicy(maxCount, maxSize, type));
+ return std::auto_ptr<QueuePolicy>(new RingQueuePolicy(name, maxCount, maxSize, type));
} else if (type == FLOW_TO_DISK) {
- return std::auto_ptr<QueuePolicy>(new FlowToDiskPolicy(maxCount, maxSize));
+ return std::auto_ptr<QueuePolicy>(new FlowToDiskPolicy(name, maxCount, maxSize));
} else {
- return std::auto_ptr<QueuePolicy>(new QueuePolicy(maxCount, maxSize, type));
+ return std::auto_ptr<QueuePolicy>(new QueuePolicy(name, maxCount, maxSize, type));
}
}
@@ -305,10 +301,10 @@ namespace qpid {
std::ostream& operator<<(std::ostream& out, const QueuePolicy& p)
{
- if (p.maxSize) out << "size: max=" << p.maxSize << ", current=" << p.size.get();
+ if (p.maxSize) out << "size: max=" << p.maxSize << ", current=" << p.size;
else out << "size: unlimited";
out << "; ";
- if (p.maxCount) out << "count: max=" << p.maxCount << ", current=" << p.count.get();
+ if (p.maxCount) out << "count: max=" << p.maxCount << ", current=" << p.count;
else out << "count: unlimited";
out << "; type=" << p.type;
return out;
diff --git a/qpid/cpp/src/qpid/broker/QueuePolicy.h b/qpid/cpp/src/qpid/broker/QueuePolicy.h
index 54745876d5..b2937e94c7 100644
--- a/qpid/cpp/src/qpid/broker/QueuePolicy.h
+++ b/qpid/cpp/src/qpid/broker/QueuePolicy.h
@@ -40,14 +40,14 @@ class QueuePolicy
uint32_t maxCount;
uint64_t maxSize;
const std::string type;
- qpid::sys::AtomicValue<uint32_t> count;
- qpid::sys::AtomicValue<uint64_t> size;
+ uint32_t count;
+ uint64_t size;
bool policyExceeded;
static int getInt(const qpid::framing::FieldTable& settings, const std::string& key, int defaultValue);
- static std::string getType(const qpid::framing::FieldTable& settings);
public:
+ typedef std::deque<QueuedMessage> Messages;
static QPID_BROKER_EXTERN const std::string maxCountKey;
static QPID_BROKER_EXTERN const std::string maxSizeKey;
static QPID_BROKER_EXTERN const std::string typeKey;
@@ -57,27 +57,34 @@ class QueuePolicy
static QPID_BROKER_EXTERN const std::string RING_STRICT;
virtual ~QueuePolicy() {}
- QPID_BROKER_EXTERN void tryEnqueue(const QueuedMessage&);
+ QPID_BROKER_EXTERN void tryEnqueue(boost::intrusive_ptr<Message> msg);
+ QPID_BROKER_EXTERN void recoverEnqueued(boost::intrusive_ptr<Message> msg);
+ QPID_BROKER_EXTERN void enqueueAborted(boost::intrusive_ptr<Message> msg);
+ virtual void enqueued(const QueuedMessage&);
virtual void dequeued(const QueuedMessage&);
virtual bool isEnqueued(const QueuedMessage&);
- virtual bool checkLimit(const QueuedMessage&);
QPID_BROKER_EXTERN void update(qpid::framing::FieldTable& settings);
uint32_t getMaxCount() const { return maxCount; }
uint64_t getMaxSize() const { return maxSize; }
void encode(framing::Buffer& buffer) const;
void decode ( framing::Buffer& buffer );
uint32_t encodedSize() const;
+ virtual void getPendingDequeues(Messages& result);
-
+ static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(const std::string& name, const qpid::framing::FieldTable& settings);
+ static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize, const std::string& type = REJECT);
static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(const qpid::framing::FieldTable& settings);
static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(uint32_t maxCount, uint64_t maxSize, const std::string& type = REJECT);
+ static std::string getType(const qpid::framing::FieldTable& settings);
static void setDefaultMaxSize(uint64_t);
friend QPID_BROKER_EXTERN std::ostream& operator<<(std::ostream&,
const QueuePolicy&);
protected:
- QueuePolicy(uint32_t maxCount, uint64_t maxSize, const std::string& type = REJECT);
+ const std::string name;
- virtual void enqueued(const QueuedMessage&);
+ QueuePolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize, const std::string& type = REJECT);
+
+ virtual bool checkLimit(boost::intrusive_ptr<Message> msg);
void enqueued(uint64_t size);
void dequeued(uint64_t size);
};
@@ -86,21 +93,20 @@ class QueuePolicy
class FlowToDiskPolicy : public QueuePolicy
{
public:
- FlowToDiskPolicy(uint32_t maxCount, uint64_t maxSize);
- bool checkLimit(const QueuedMessage&);
+ FlowToDiskPolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize);
+ bool checkLimit(boost::intrusive_ptr<Message> msg);
};
class RingQueuePolicy : public QueuePolicy
{
public:
- RingQueuePolicy(uint32_t maxCount, uint64_t maxSize, const std::string& type = RING);
+ RingQueuePolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize, const std::string& type = RING);
void enqueued(const QueuedMessage&);
void dequeued(const QueuedMessage&);
bool isEnqueued(const QueuedMessage&);
- bool checkLimit(const QueuedMessage&);
+ bool checkLimit(boost::intrusive_ptr<Message> msg);
+ void getPendingDequeues(Messages& result);
private:
- typedef std::deque<QueuedMessage> Messages;
- qpid::sys::Mutex lock;
Messages pendingDequeues;
Messages queue;
const bool strict;
diff --git a/qpid/cpp/src/qpid/broker/SemanticState.cpp b/qpid/cpp/src/qpid/broker/SemanticState.cpp
index bdd5f33601..7e3090bf17 100644
--- a/qpid/cpp/src/qpid/broker/SemanticState.cpp
+++ b/qpid/cpp/src/qpid/broker/SemanticState.cpp
@@ -65,7 +65,7 @@ SemanticState::SemanticState(DeliveryAdapter& da, SessionContext& ss)
tagGenerator("sgen"),
dtxSelected(false),
authMsg(getSession().getBroker().getOptions().auth && !getSession().getConnection().isFederationLink()),
- userID(getSession().getConnection().getUserId().substr(0,getSession().getConnection().getUserId().find('@')))
+ userID(getSession().getConnection().getUserId())
{
acl = getSession().getBroker().getAcl();
}
@@ -302,6 +302,18 @@ bool SemanticState::ConsumerImpl::accept(intrusive_ptr<Message> msg)
return !blocked;
}
+namespace {
+struct ConsumerName {
+ const SemanticState::ConsumerImpl& consumer;
+ ConsumerName(const SemanticState::ConsumerImpl& ci) : consumer(ci) {}
+};
+
+ostream& operator<<(ostream& o, const ConsumerName& pc) {
+ return o << pc.consumer.getName() << " on "
+ << pc.consumer.getParent().getSession().getSessionId();
+}
+}
+
void SemanticState::ConsumerImpl::allocateCredit(intrusive_ptr<Message>& msg)
{
uint32_t originalMsgCredit = msgCredit;
@@ -312,7 +324,7 @@ void SemanticState::ConsumerImpl::allocateCredit(intrusive_ptr<Message>& msg)
if (byteCredit != 0xFFFFFFFF) {
byteCredit -= msg->getRequiredCredit();
}
- QPID_LOG(debug, "Credit allocated for '" << name << "' on " << parent
+ QPID_LOG(debug, "Credit allocated for " << ConsumerName(*this)
<< ", was " << " bytes: " << originalByteCredit << " msgs: " << originalMsgCredit
<< " now bytes: " << byteCredit << " msgs: " << msgCredit);
@@ -320,15 +332,13 @@ void SemanticState::ConsumerImpl::allocateCredit(intrusive_ptr<Message>& msg)
bool SemanticState::ConsumerImpl::checkCredit(intrusive_ptr<Message>& msg)
{
- if (msgCredit == 0 || (byteCredit != 0xFFFFFFFF && byteCredit < msg->getRequiredCredit())) {
- QPID_LOG(debug, "Not enough credit for '" << name << "' on " << parent
- << ", bytes: " << byteCredit << " msgs: " << msgCredit);
- return false;
- } else {
- QPID_LOG(debug, "Credit available for '" << name << "' on " << parent
- << " bytes: " << byteCredit << " msgs: " << msgCredit);
- return true;
- }
+ bool enoughCredit = msgCredit > 0 &&
+ (byteCredit == 0xFFFFFFFF || byteCredit >= msg->getRequiredCredit());
+ QPID_LOG(debug, (enoughCredit ? "Sufficient credit for " : "Insufficient credit for ")
+ << ConsumerName(*this)
+ << ", have bytes: " << byteCredit << " msgs: " << msgCredit
+ << ", need " << msg->getRequiredCredit() << " bytes");
+ return enoughCredit;
}
SemanticState::ConsumerImpl::~ConsumerImpl() {}
@@ -356,6 +366,9 @@ void SemanticState::handle(intrusive_ptr<Message> msg) {
} else {
DeliverableMessage deliverable(msg);
route(msg, deliverable);
+ if (msg->checkContentReleasable()) {
+ msg->releaseContent();
+ }
}
}
diff --git a/qpid/cpp/src/qpid/broker/SemanticState.h b/qpid/cpp/src/qpid/broker/SemanticState.h
index da8383fc12..89fe7b83dd 100644
--- a/qpid/cpp/src/qpid/broker/SemanticState.h
+++ b/qpid/cpp/src/qpid/broker/SemanticState.h
@@ -129,6 +129,7 @@ class SemanticState : private boost::noncopyable {
const framing::FieldTable& getArguments() const { return arguments; }
SemanticState& getParent() { return *parent; }
+ const SemanticState& getParent() const { return *parent; }
};
private:
@@ -163,6 +164,7 @@ class SemanticState : private boost::noncopyable {
~SemanticState();
SessionContext& getSession() { return session; }
+ const SessionContext& getSession() const { return session; }
ConsumerImpl& find(const std::string& destination);
diff --git a/qpid/cpp/src/qpid/broker/SessionAdapter.cpp b/qpid/cpp/src/qpid/broker/SessionAdapter.cpp
index a1ad5a0a30..2ac6d66e62 100644
--- a/qpid/cpp/src/qpid/broker/SessionAdapter.cpp
+++ b/qpid/cpp/src/qpid/broker/SessionAdapter.cpp
@@ -337,6 +337,10 @@ void SessionAdapter::QueueHandlerImpl::declare(const string& name, const string&
params.insert(make_pair(acl::PROP_DURABLE, std::string(durable ? _TRUE : _FALSE)));
params.insert(make_pair(acl::PROP_EXCLUSIVE, std::string(exclusive ? _TRUE : _FALSE)));
params.insert(make_pair(acl::PROP_AUTODELETE, std::string(autoDelete ? _TRUE : _FALSE)));
+ params.insert(make_pair(acl::PROP_POLICYTYPE, arguments.getAsString("qpid.policy_type")));
+ params.insert(make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast<string>(arguments.getAsInt("qpid.max_count"))));
+ params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast<string>(arguments.getAsInt64("qpid.max_size"))));
+
if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_QUEUE,name,&params) )
throw NotAllowedException(QPID_MSG("ACL denied queue create request from " << getConnection().getUserId()));
}
@@ -472,8 +476,7 @@ SessionAdapter::MessageHandlerImpl::subscribe(const string& queueName,
AclModule* acl = getBroker().getAcl();
if (acl)
- {
- // add flags as needed
+ {
if (!acl->authorise(getConnection().getUserId(),acl::ACT_CONSUME,acl::OBJ_QUEUE,queueName,NULL) )
throw NotAllowedException(QPID_MSG("ACL denied Queue subscribe request from " << getConnection().getUserId()));
}
diff --git a/qpid/cpp/src/qpid/broker/SessionContext.h b/qpid/cpp/src/qpid/broker/SessionContext.h
index cfdbd100c3..afbbb2cc22 100644
--- a/qpid/cpp/src/qpid/broker/SessionContext.h
+++ b/qpid/cpp/src/qpid/broker/SessionContext.h
@@ -28,7 +28,7 @@
#include "qpid/sys/OutputControl.h"
#include "qpid/broker/ConnectionState.h"
#include "qpid/broker/OwnershipToken.h"
-
+#include "qpid/SessionId.h"
#include <boost/noncopyable.hpp>
@@ -45,6 +45,7 @@ class SessionContext : public OwnershipToken, public sys::OutputControl
virtual framing::AMQP_ClientProxy& getProxy() = 0;
virtual Broker& getBroker() = 0;
virtual uint16_t getChannel() const = 0;
+ virtual const SessionId& getSessionId() const = 0;
};
}} // namespace qpid::broker
diff --git a/qpid/cpp/src/qpid/broker/SessionState.h b/qpid/cpp/src/qpid/broker/SessionState.h
index 67fd4f4f38..eade93ddaa 100644
--- a/qpid/cpp/src/qpid/broker/SessionState.h
+++ b/qpid/cpp/src/qpid/broker/SessionState.h
@@ -118,6 +118,8 @@ class SessionState : public qpid::SessionState,
bool processSendCredit(uint32_t msgs);
+ const SessionId& getSessionId() const { return getId(); }
+
private:
void handleCommand(framing::AMQMethodBody* method, const framing::SequenceNumber& id);
diff --git a/qpid/cpp/src/qpid/broker/SignalHandler.cpp b/qpid/cpp/src/qpid/broker/SignalHandler.cpp
index f4a3822554..b565cfd419 100644
--- a/qpid/cpp/src/qpid/broker/SignalHandler.cpp
+++ b/qpid/cpp/src/qpid/broker/SignalHandler.cpp
@@ -38,6 +38,8 @@ void SignalHandler::setBroker(const boost::intrusive_ptr<Broker>& b) {
signal(SIGCHLD,SIG_IGN);
}
+void SignalHandler::shutdown() { shutdownHandler(0); }
+
void SignalHandler::shutdownHandler(int) {
if (broker.get()) {
broker->shutdown();
diff --git a/qpid/cpp/src/qpid/broker/SignalHandler.h b/qpid/cpp/src/qpid/broker/SignalHandler.h
index d2cdfae07c..bbe831b61d 100644
--- a/qpid/cpp/src/qpid/broker/SignalHandler.h
+++ b/qpid/cpp/src/qpid/broker/SignalHandler.h
@@ -38,6 +38,9 @@ class SignalHandler
/** Set the broker to be shutdown on signals */
static void setBroker(const boost::intrusive_ptr<Broker>& broker);
+ /** Initiate shut-down of broker */
+ static void shutdown();
+
private:
static void shutdownHandler(int);
static boost::intrusive_ptr<Broker> broker;
diff --git a/qpid/cpp/src/qpid/broker/TopicExchange.cpp b/qpid/cpp/src/qpid/broker/TopicExchange.cpp
index 6bf0b104ea..cb04742677 100644
--- a/qpid/cpp/src/qpid/broker/TopicExchange.cpp
+++ b/qpid/cpp/src/qpid/broker/TopicExchange.cpp
@@ -293,44 +293,23 @@ bool TopicExchange::isBound(Queue::shared_ptr queue, const string& pattern)
return q != qv.end();
}
-void TopicExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/){
+void TopicExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/)
+{
Binding::vector mb;
+ BindingList b(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >);
PreRoute pr(msg, this);
- uint32_t count(0);
-
{
- RWlock::ScopedRlock l(lock);
- for (BindingMap::iterator i = bindings.begin(); i != bindings.end(); ++i) {
- if (match(i->first, routingKey)) {
- Binding::vector& qv(i->second.bindingVector);
- for(Binding::vector::iterator j = qv.begin(); j != qv.end(); j++, count++){
- mb.push_back(*j);
+ RWlock::ScopedRlock l(lock);
+ for (BindingMap::iterator i = bindings.begin(); i != bindings.end(); ++i) {
+ if (match(i->first, routingKey)) {
+ Binding::vector& qv(i->second.bindingVector);
+ for(Binding::vector::iterator j = qv.begin(); j != qv.end(); j++){
+ b->push_back(*j);
+ }
}
}
}
- }
-
- for (Binding::vector::iterator j = mb.begin(); j != mb.end(); ++j) {
- msg.deliverTo((*j)->queue);
- if ((*j)->mgmtBinding != 0)
- (*j)->mgmtBinding->inc_msgMatched ();
- }
-
- if (mgmtExchange != 0)
- {
- mgmtExchange->inc_msgReceives ();
- mgmtExchange->inc_byteReceives (msg.contentSize ());
- if (count == 0)
- {
- mgmtExchange->inc_msgDrops ();
- mgmtExchange->inc_byteDrops (msg.contentSize ());
- }
- else
- {
- mgmtExchange->inc_msgRoutes (count);
- mgmtExchange->inc_byteRoutes (count * msg.contentSize ());
- }
- }
+ doRoute(msg, b);
}
bool TopicExchange::isBound(Queue::shared_ptr queue, const string* const routingKey, const FieldTable* const)
diff --git a/qpid/cpp/src/qpid/broker/TxAccept.cpp b/qpid/cpp/src/qpid/broker/TxAccept.cpp
index e47ac84990..928ac12c10 100644
--- a/qpid/cpp/src/qpid/broker/TxAccept.cpp
+++ b/qpid/cpp/src/qpid/broker/TxAccept.cpp
@@ -88,7 +88,13 @@ bool TxAccept::prepare(TransactionContext* ctxt) throw()
void TxAccept::commit() throw()
{
- ops.commit();
+ try {
+ ops.commit();
+ } catch (const std::exception& e) {
+ QPID_LOG(error, "Failed to commit: " << e.what());
+ } catch(...) {
+ QPID_LOG(error, "Failed to commit (unknown error)");
+ }
}
void TxAccept::rollback() throw() {}
diff --git a/qpid/cpp/src/qpid/broker/TxPublish.cpp b/qpid/cpp/src/qpid/broker/TxPublish.cpp
index 17b99fd883..4b083033ea 100644
--- a/qpid/cpp/src/qpid/broker/TxPublish.cpp
+++ b/qpid/cpp/src/qpid/broker/TxPublish.cpp
@@ -26,9 +26,14 @@ using namespace qpid::broker;
TxPublish::TxPublish(intrusive_ptr<Message> _msg) : msg(_msg) {}
-bool TxPublish::prepare(TransactionContext* ctxt) throw(){
+bool TxPublish::prepare(TransactionContext* ctxt) throw()
+{
try{
- for_each(queues.begin(), queues.end(), Prepare(ctxt, msg));
+ while (!queues.empty()) {
+ prepare(ctxt, queues.front());
+ prepared.push_back(queues.front());
+ queues.pop_front();
+ }
return true;
}catch(const std::exception& e){
QPID_LOG(error, "Failed to prepare: " << e.what());
@@ -38,11 +43,30 @@ bool TxPublish::prepare(TransactionContext* ctxt) throw(){
return false;
}
-void TxPublish::commit() throw(){
- for_each(queues.begin(), queues.end(), Commit(msg));
+void TxPublish::commit() throw()
+{
+ try {
+ for_each(prepared.begin(), prepared.end(), Commit(msg));
+ if (msg->checkContentReleasable()) {
+ msg->releaseContent();
+ }
+ } catch (const std::exception& e) {
+ QPID_LOG(error, "Failed to commit: " << e.what());
+ } catch(...) {
+ QPID_LOG(error, "Failed to commit (unknown error)");
+ }
}
-void TxPublish::rollback() throw(){
+void TxPublish::rollback() throw()
+{
+ try {
+ for_each(prepared.begin(), prepared.end(), Rollback(msg));
+ } catch (const std::exception& e) {
+ QPID_LOG(error, "Failed to complete rollback: " << e.what());
+ } catch(...) {
+ QPID_LOG(error, "Failed to complete rollback (unknown error)");
+ }
+
}
void TxPublish::deliverTo(const boost::shared_ptr<Queue>& queue){
@@ -54,16 +78,14 @@ void TxPublish::deliverTo(const boost::shared_ptr<Queue>& queue){
}
}
-TxPublish::Prepare::Prepare(TransactionContext* _ctxt, intrusive_ptr<Message>& _msg)
- : ctxt(_ctxt), msg(_msg){}
-
-void TxPublish::Prepare::operator()(const boost::shared_ptr<Queue>& queue){
+void TxPublish::prepare(TransactionContext* ctxt, const boost::shared_ptr<Queue> queue)
+{
if (!queue->enqueue(ctxt, msg)){
/**
- * if not store then mark message for ack and deleivery once
- * commit happens, as async IO will never set it when no store
- * exists
- */
+ * if not store then mark message for ack and deleivery once
+ * commit happens, as async IO will never set it when no store
+ * exists
+ */
msg->enqueueComplete();
}
}
@@ -74,6 +96,12 @@ void TxPublish::Commit::operator()(const boost::shared_ptr<Queue>& queue){
queue->process(msg);
}
+TxPublish::Rollback::Rollback(intrusive_ptr<Message>& _msg) : msg(_msg){}
+
+void TxPublish::Rollback::operator()(const boost::shared_ptr<Queue>& queue){
+ queue->enqueueAborted(msg);
+}
+
uint64_t TxPublish::contentSize ()
{
return msg->contentSize ();
diff --git a/qpid/cpp/src/qpid/broker/TxPublish.h b/qpid/cpp/src/qpid/broker/TxPublish.h
index d5cf5639c4..b6ab9767ab 100644
--- a/qpid/cpp/src/qpid/broker/TxPublish.h
+++ b/qpid/cpp/src/qpid/broker/TxPublish.h
@@ -47,23 +47,25 @@ namespace qpid {
* dispatch or to be added to the in-memory queue.
*/
class TxPublish : public TxOp, public Deliverable{
- class Prepare{
- TransactionContext* ctxt;
+
+ class Commit{
boost::intrusive_ptr<Message>& msg;
public:
- Prepare(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg);
+ Commit(boost::intrusive_ptr<Message>& msg);
void operator()(const boost::shared_ptr<Queue>& queue);
};
-
- class Commit{
+ class Rollback{
boost::intrusive_ptr<Message>& msg;
public:
- Commit(boost::intrusive_ptr<Message>& msg);
+ Rollback(boost::intrusive_ptr<Message>& msg);
void operator()(const boost::shared_ptr<Queue>& queue);
};
boost::intrusive_ptr<Message> msg;
std::list<Queue::shared_ptr> queues;
+ std::list<Queue::shared_ptr> prepared;
+
+ void prepare(TransactionContext* ctxt, boost::shared_ptr<Queue>);
public:
QPID_BROKER_EXTERN TxPublish(boost::intrusive_ptr<Message> msg);
diff --git a/qpid/cpp/src/qpid/client/ConnectionHandler.cpp b/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
index 9b2f662c8e..bb348675c6 100644
--- a/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
+++ b/qpid/cpp/src/qpid/client/ConnectionHandler.cpp
@@ -257,6 +257,7 @@ void ConnectionHandler::openOk ( const Array& knownBrokers )
knownBrokersUrls.push_back(Url((*i)->get<std::string>()));
if (sasl.get()) {
securityLayer = sasl->getSecurityLayer(maxFrameSize);
+ operUserId = sasl->getUserId();
}
setState(OPEN);
QPID_LOG(debug, "Known-brokers for connection: " << log::formatList(knownBrokersUrls));
diff --git a/qpid/cpp/src/qpid/client/ConnectionHandler.h b/qpid/cpp/src/qpid/client/ConnectionHandler.h
index b1fd5be7c3..e9cc5194ae 100644
--- a/qpid/cpp/src/qpid/client/ConnectionHandler.h
+++ b/qpid/cpp/src/qpid/client/ConnectionHandler.h
@@ -71,6 +71,7 @@ class ConnectionHandler : private StateManager,
std::auto_ptr<Sasl> sasl;
std::auto_ptr<qpid::sys::SecurityLayer> securityLayer;
boost::intrusive_ptr<qpid::sys::TimerTask> rcvTimeoutTask;
+ std::string operUserId;
void checkState(STATES s, const std::string& msg);
@@ -120,6 +121,7 @@ public:
std::vector<Url> knownBrokersUrls;
static framing::connection::CloseCode convert(uint16_t replyCode);
+ const std::string& getUserId() const { return operUserId; }
};
}}
diff --git a/qpid/cpp/src/qpid/client/ConnectionImpl.cpp b/qpid/cpp/src/qpid/client/ConnectionImpl.cpp
index 45ad819ebd..c56d6a6807 100644
--- a/qpid/cpp/src/qpid/client/ConnectionImpl.cpp
+++ b/qpid/cpp/src/qpid/client/ConnectionImpl.cpp
@@ -151,6 +151,12 @@ void ConnectionImpl::open()
handler.waitForOpen();
+ // If the SASL layer has provided an "operational" userId for the connection,
+ // put it in the negotiated settings.
+ const std::string& userId(handler.getUserId());
+ if (!userId.empty())
+ handler.username = userId;
+
//enable security layer if one has been negotiated:
std::auto_ptr<SecurityLayer> securityLayer = handler.getSecurityLayer();
if (securityLayer.get()) {
diff --git a/qpid/cpp/src/qpid/client/Connector.cpp b/qpid/cpp/src/qpid/client/Connector.cpp
index f69032b26d..fbb571d40a 100644
--- a/qpid/cpp/src/qpid/client/Connector.cpp
+++ b/qpid/cpp/src/qpid/client/Connector.cpp
@@ -51,10 +51,10 @@ using boost::str;
// Stuff for the registry of protocol connectors (maybe should be moved to its own file)
namespace {
typedef std::map<std::string, Connector::Factory*> ProtocolRegistry;
-
+
ProtocolRegistry& theProtocolRegistry() {
static ProtocolRegistry protocolRegistry;
-
+
return protocolRegistry;
}
}
@@ -93,7 +93,7 @@ class TCPConnector : public Connector, public sys::Codec, private sys::Runnable
size_t lastEof; // Position after last EOF in frames
uint64_t currentSize;
Bounds* bounds;
-
+
framing::ProtocolVersion version;
bool initiated;
bool closed;
@@ -118,16 +118,17 @@ class TCPConnector : public Connector, public sys::Codec, private sys::Runnable
void run();
void handleClosed();
bool closeInternal();
-
+
+ void connected(const Socket&);
+ void connectFailed(const std::string& msg);
bool readbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*);
void writebuff(qpid::sys::AsynchIO&);
void writeDataBlock(const framing::AMQDataBlock& data);
void eof(qpid::sys::AsynchIO&);
boost::weak_ptr<ConnectionImpl> impl;
-
+
void connect(const std::string& host, int port);
- void init();
void close();
void send(framing::AMQFrame& frame);
void abort();
@@ -142,7 +143,6 @@ class TCPConnector : public Connector, public sys::Codec, private sys::Runnable
size_t decode(const char* buffer, size_t size);
size_t encode(const char* buffer, size_t size);
bool canEncode();
-
public:
TCPConnector(framing::ProtocolVersion pVersion,
@@ -163,6 +163,11 @@ namespace {
} init;
}
+struct TCPConnector::Buff : public AsynchIO::BufferBase {
+ Buff(size_t size) : AsynchIO::BufferBase(new char[size], size) {}
+ ~Buff() { delete [] bytes;}
+};
+
TCPConnector::TCPConnector(ProtocolVersion ver,
const ConnectionSettings& settings,
ConnectionImpl* cimpl)
@@ -189,15 +194,19 @@ TCPConnector::~TCPConnector() {
void TCPConnector::connect(const std::string& host, int port){
Mutex::ScopedLock l(lock);
assert(closed);
- try {
- socket.connect(host, port);
- } catch (const std::exception& /*e*/) {
- socket.close();
- throw;
- }
-
- identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress());
+ assert(joined);
poller = Poller::shared_ptr(new Poller);
+ AsynchConnector::create(socket,
+ poller,
+ host, port,
+ boost::bind(&TCPConnector::connected, this, _1),
+ boost::bind(&TCPConnector::connectFailed, this, _3));
+ closed = false;
+ joined = false;
+ receiver = Thread(this);
+}
+
+void TCPConnector::connected(const Socket&) {
aio = AsynchIO::create(socket,
boost::bind(&TCPConnector::readbuff, this, _1, _2),
boost::bind(&TCPConnector::eof, this, _1),
@@ -205,16 +214,23 @@ void TCPConnector::connect(const std::string& host, int port){
0, // closed
0, // nobuffs
boost::bind(&TCPConnector::writebuff, this, _1));
- closed = false;
-}
+ for (int i = 0; i < 32; i++) {
+ aio->queueReadBuffer(new Buff(maxFrameSize));
+ }
+ aio->start(poller);
-void TCPConnector::init(){
- Mutex::ScopedLock l(lock);
- assert(joined);
+ identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress());
ProtocolInitiation init(version);
writeDataBlock(init);
- joined = false;
- receiver = Thread(this);
+}
+
+void TCPConnector::connectFailed(const std::string& msg) {
+ QPID_LOG(warning, "Connecting failed: " << msg);
+ closed = true;
+ poller->shutdown();
+ closeInternal();
+ if (shutdownHandler)
+ shutdownHandler->shutdown();
}
bool TCPConnector::closeInternal() {
@@ -235,7 +251,7 @@ bool TCPConnector::closeInternal() {
receiver.join();
return ret;
}
-
+
void TCPConnector::close() {
closeInternal();
}
@@ -243,7 +259,13 @@ void TCPConnector::close() {
void TCPConnector::abort() {
// Can't abort a closed connection
if (!closed) {
- aio->requestCallback(boost::bind(&TCPConnector::eof, this, _1));
+ if (aio) {
+ // Established connection
+ aio->requestCallback(boost::bind(&TCPConnector::eof, this, _1));
+ } else {
+ // We're still connecting
+ connectFailed("Connection timedout");
+ }
}
}
@@ -288,18 +310,13 @@ void TCPConnector::handleClosed() {
shutdownHandler->shutdown();
}
-struct TCPConnector::Buff : public AsynchIO::BufferBase {
- Buff(size_t size) : AsynchIO::BufferBase(new char[size], size) {}
- ~Buff() { delete [] bytes;}
-};
-
void TCPConnector::writebuff(AsynchIO& /*aio*/)
{
Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this;
if (codec->canEncode()) {
std::auto_ptr<AsynchIO::BufferBase> buffer = std::auto_ptr<AsynchIO::BufferBase>(aio->getQueuedBuffer());
if (!buffer.get()) buffer = std::auto_ptr<AsynchIO::BufferBase>(new Buff(maxFrameSize));
-
+
size_t encoded = codec->encode(buffer->bytes, buffer->byteCount);
buffer->dataStart = 0;
@@ -395,11 +412,6 @@ void TCPConnector::run() {
try {
Dispatcher d(poller);
- for (int i = 0; i < 32; i++) {
- aio->queueReadBuffer(new Buff(maxFrameSize));
- }
-
- aio->start(poller);
d.run();
} catch (const std::exception& e) {
QPID_LOG(error, QPID_MSG("FAIL " << identifier << ": " << e.what()));
diff --git a/qpid/cpp/src/qpid/client/RdmaConnector.cpp b/qpid/cpp/src/qpid/client/RdmaConnector.cpp
index 0aefcc04cf..0692c3d85c 100644
--- a/qpid/cpp/src/qpid/client/RdmaConnector.cpp
+++ b/qpid/cpp/src/qpid/client/RdmaConnector.cpp
@@ -167,20 +167,9 @@ void RdmaConnector::connect(const std::string& host, int port){
assert(joined);
poller = Poller::shared_ptr(new Poller);
- // This stuff needs to abstracted out of here to a platform specific file
- ::addrinfo *res;
- ::addrinfo hints;
- hints.ai_flags = 0;
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
- int n = ::getaddrinfo(host.c_str(), boost::lexical_cast<std::string>(port).c_str(), &hints, &res);
- if (n<0) {
- throw Exception(QPID_MSG("Cannot resolve " << host << ": " << ::gai_strerror(n)));
- }
-
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
Rdma::Connector* c = new Rdma::Connector(
- *res->ai_addr,
+ sa,
Rdma::ConnectionParams(maxFrameSize, Rdma::DEFAULT_WR_ENTRIES),
boost::bind(&RdmaConnector::connected, this, poller, _1, _2),
boost::bind(&RdmaConnector::connectionError, this, poller, _1, _2),
diff --git a/qpid/cpp/src/qpid/client/Sasl.h b/qpid/cpp/src/qpid/client/Sasl.h
index 9dc5817f3d..d773609655 100644
--- a/qpid/cpp/src/qpid/client/Sasl.h
+++ b/qpid/cpp/src/qpid/client/Sasl.h
@@ -45,6 +45,7 @@ class Sasl
virtual std::string start(const std::string& mechanisms) = 0;
virtual std::string step(const std::string& challenge) = 0;
virtual std::string getMechanism() = 0;
+ virtual std::string getUserId() = 0;
virtual std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(uint16_t maxFrameSize) = 0;
virtual ~Sasl() {}
};
diff --git a/qpid/cpp/src/qpid/client/SaslFactory.cpp b/qpid/cpp/src/qpid/client/SaslFactory.cpp
index 884f527f01..2258163ec8 100644
--- a/qpid/cpp/src/qpid/client/SaslFactory.cpp
+++ b/qpid/cpp/src/qpid/client/SaslFactory.cpp
@@ -82,6 +82,7 @@ class CyrusSasl : public Sasl
std::string start(const std::string& mechanisms);
std::string step(const std::string& challenge);
std::string getMechanism();
+ std::string getUserId();
std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize);
private:
sasl_conn_t* conn;
@@ -266,6 +267,18 @@ std::string CyrusSasl::getMechanism()
return mechanism;
}
+std::string CyrusSasl::getUserId()
+{
+ int propResult;
+ const void* operName;
+
+ propResult = sasl_getprop(conn, SASL_USERNAME, &operName);
+ if (propResult == SASL_OK)
+ return std::string((const char*) operName);
+
+ return std::string();
+}
+
void CyrusSasl::interact(sasl_interact_t* client_interact)
{
diff --git a/qpid/cpp/src/qpid/client/SessionImpl.cpp b/qpid/cpp/src/qpid/client/SessionImpl.cpp
index 8ead44a172..32541dceac 100644
--- a/qpid/cpp/src/qpid/client/SessionImpl.cpp
+++ b/qpid/cpp/src/qpid/client/SessionImpl.cpp
@@ -64,7 +64,8 @@ SessionImpl::SessionImpl(const std::string& name, boost::shared_ptr<ConnectionIm
proxy(ioHandler),
nextIn(0),
nextOut(0),
- sendMsgCredit(0)
+ sendMsgCredit(0),
+ doClearDeliveryPropertiesExchange(true)
{
channel.next = connectionShared.get();
}
@@ -396,11 +397,16 @@ void SessionImpl::sendContent(const MethodContent& content)
{
AMQFrame header(content.getHeader());
- // Client is not allowed to set the delivery-properties.exchange.
- AMQHeaderBody* headerp = static_cast<AMQHeaderBody*>(header.getBody());
- if (headerp && headerp->get<DeliveryProperties>())
- headerp->get<DeliveryProperties>(true)->clearExchangeFlag();
-
+ // doClearDeliveryPropertiesExchange is set by cluster update client so
+ // it can send messages with delivery-properties.exchange set.
+ //
+ if (doClearDeliveryPropertiesExchange) {
+ // Normal client is not allowed to set the delivery-properties.exchange
+ // so clear it here.
+ AMQHeaderBody* headerp = static_cast<AMQHeaderBody*>(header.getBody());
+ if (headerp && headerp->get<DeliveryProperties>())
+ headerp->get<DeliveryProperties>(true)->clearExchangeFlag();
+ }
header.setFirstSegment(false);
uint64_t data_length = content.getData().length();
if(data_length > 0){
diff --git a/qpid/cpp/src/qpid/client/SessionImpl.h b/qpid/cpp/src/qpid/client/SessionImpl.h
index 49d268c44d..0624bb8b3c 100644
--- a/qpid/cpp/src/qpid/client/SessionImpl.h
+++ b/qpid/cpp/src/qpid/client/SessionImpl.h
@@ -130,6 +130,8 @@ public:
*/
boost::shared_ptr<ConnectionImpl> getConnection();
+ void setDoClearDeliveryPropertiesExchange(bool b=true) { doClearDeliveryPropertiesExchange = b; }
+
private:
enum State {
INACTIVE,
@@ -243,6 +245,8 @@ private:
// Only keep track of message credit
sys::Semaphore* sendMsgCredit;
+ bool doClearDeliveryPropertiesExchange;
+
friend class client::SessionHandler;
};
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp b/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
index 9b9f06ec57..f51a96efd9 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
+++ b/qpid/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
@@ -362,21 +362,12 @@ void QueueSink::send(qpid::client::AsyncSession& session, const std::string&, Ou
void QueueSink::cancel(qpid::client::AsyncSession&, const std::string&) {}
-template <class T> void encode(qpid::messaging::Message& from)
-{
- T codec;
- from.encode(codec);
- from.setContentType(T::contentType);
-}
-
void translate(const Variant::Map& from, FieldTable& to);//implementation in Codecs.cpp
void convert(qpid::messaging::Message& from, qpid::client::Message& to)
{
//TODO: need to avoid copying as much as possible
- if (from.getContent().isList()) encode<ListCodec>(from);
- if (from.getContent().isMap()) encode<MapCodec>(from);
- to.setData(from.getBytes());
+ to.setData(from.getContent());
to.getDeliveryProperties().setRoutingKey(from.getSubject());
//TODO: set other delivery properties
to.getMessageProperties().setContentType(from.getContentType());
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp b/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
index d22208368b..8e060c62d7 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
+++ b/qpid/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
@@ -269,18 +269,9 @@ void populate(qpid::messaging::Message& message, FrameSet& command)
//e.g. for rejecting.
MessageImplAccess::get(message).setInternalId(command.getId());
- command.getContent(message.getBytes());
+ command.getContent(message.getContent());
populateHeaders(message, command.getHeaders());
-
- //decode content if necessary
- if (message.getContentType() == ListCodec::contentType) {
- ListCodec codec;
- message.decode(codec);
- } else if (message.getContentType() == MapCodec::contentType) {
- MapCodec codec;
- message.decode(codec);
- }
}
diff --git a/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp b/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
index 716f955f98..cbc95b44fb 100644
--- a/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
+++ b/qpid/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
@@ -33,24 +33,11 @@ namespace amqp0_10 {
using qpid::messaging::Address;
using qpid::messaging::MessageImplAccess;
-template <class T> void encode(const qpid::messaging::Message& from, qpid::client::Message& to)
-{
- T codec;
- MessageImplAccess::get(from).getEncodedContent(codec, to.getData());
- to.getMessageProperties().setContentType(T::contentType);
-}
-
void OutgoingMessage::convert(const qpid::messaging::Message& from)
{
//TODO: need to avoid copying as much as possible
- if (from.getContent().isList()) {
- encode<ListCodec>(from, message);
- } else if (from.getContent().isMap()) {
- encode<MapCodec>(from, message);
- } else {
- message.setData(from.getBytes());
- message.getMessageProperties().setContentType(from.getContentType());
- }
+ message.setData(from.getContent());
+ message.getMessageProperties().setContentType(from.getContentType());
const Address& address = from.getReplyTo();
if (!address.value.empty()) {
message.getMessageProperties().setReplyTo(AddressResolution::convert(address));
diff --git a/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp b/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp
index 58956609a4..3a662463c1 100644
--- a/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp
+++ b/qpid/cpp/src/qpid/client/windows/SaslFactory.cpp
@@ -43,6 +43,7 @@ class WindowsSasl : public Sasl
std::string start(const std::string& mechanisms);
std::string step(const std::string& challenge);
std::string getMechanism();
+ std::string getUserId();
std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize);
private:
ConnectionSettings settings;
@@ -131,6 +132,11 @@ std::string WindowsSasl::getMechanism()
return mechanism;
}
+std::string WindowsSasl::getUserId()
+{
+ return std::string(); // TODO - when GSSAPI is supported, return userId for connection.
+}
+
std::auto_ptr<SecurityLayer> WindowsSasl::getSecurityLayer(uint16_t maxFrameSize)
{
return std::auto_ptr<SecurityLayer>(0);
diff --git a/qpid/cpp/src/qpid/cluster/Cluster.cpp b/qpid/cpp/src/qpid/cluster/Cluster.cpp
index e35d3e4175..0706fc72e8 100644
--- a/qpid/cpp/src/qpid/cluster/Cluster.cpp
+++ b/qpid/cpp/src/qpid/cluster/Cluster.cpp
@@ -99,6 +99,7 @@
#include "qpid/broker/Connection.h"
#include "qpid/broker/QueueRegistry.h"
#include "qpid/broker/SessionState.h"
+#include "qpid/broker/SignalHandler.h"
#include "qpid/framing/AMQFrame.h"
#include "qpid/framing/AMQP_AllOperations.h"
#include "qpid/framing/AllInvoker.h"
@@ -120,7 +121,6 @@
#include "qpid/management/ManagementAgent.h"
#include "qpid/memory.h"
#include "qpid/sys/Thread.h"
-#include "qpid/sys/LatencyTracker.h"
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
@@ -144,12 +144,16 @@ using qpid::management::Manageable;
using qpid::management::Args;
namespace _qmf = ::qmf::org::apache::qpid::cluster;
-/** NOTE: increment this number whenever any incompatible changes in
+/**
+ * NOTE: must increment this number whenever any incompatible changes in
* cluster protocol/behavior are made. It allows early detection and
* sensible reporting of an attempt to mix different versions in a
* cluster.
+ *
+ * Currently use SVN revision to avoid clashes with versions from
+ * different branches.
*/
-const uint32_t Cluster::CLUSTER_VERSION = 2;
+const uint32_t Cluster::CLUSTER_VERSION = 820783;
struct ClusterDispatcher : public framing::AMQP_AllOperations::ClusterHandler {
qpid::cluster::Cluster& cluster;
@@ -308,7 +312,7 @@ void Cluster::leave(Lock&) {
// Finalize connections now now to avoid problems later in destructor.
LEAVE_TRY(localConnections.clear());
LEAVE_TRY(connections.clear());
- LEAVE_TRY(broker.shutdown());
+ LEAVE_TRY(broker::SignalHandler::shutdown());
}
}
@@ -324,20 +328,14 @@ void Cluster::deliver(
MemberId from(nodeid, pid);
framing::Buffer buf(static_cast<char*>(msg), msg_len);
Event e(Event::decodeCopy(from, buf));
- LATENCY_TRACK(if (e.getConnectionId().getMember() == self) mcast.cpgLatency.finish());
deliverEvent(e);
}
-LATENCY_TRACK(sys::LatencyTracker<const char*> eventQueueLatencyTracker("EventQueue");)
- LATENCY_TRACK(sys::LatencyTracker<const AMQBody*> frameQueueLatencyTracker("FrameQueue");)
-
- void Cluster::deliverEvent(const Event& e) {
- LATENCY_TRACK(eventQueueLatencyTracker.start(e.getData());)
- deliverEventQueue.push(e);
+void Cluster::deliverEvent(const Event& e) {
+ deliverEventQueue.push(e);
}
void Cluster::deliverFrame(const EventFrame& e) {
- LATENCY_TRACK(frameQueueLatencyTracker.start(e.frame.getBody()));
deliverFrameQueue.push(e);
}
@@ -350,7 +348,6 @@ const ClusterUpdateOfferBody* castUpdateOffer(const framing::AMQBody* body) {
// Handler for deliverEventQueue.
// This thread decodes frames from events.
void Cluster::deliveredEvent(const Event& e) {
- LATENCY_TRACK(eventQueueLatencyTracker.finish(e.getData()));
if (e.isCluster()) {
QPID_LOG(trace, *this << " DLVR: " << e);
EventFrame ef(e, e.getFrame());
@@ -396,13 +393,9 @@ void Cluster::flagError(
error.error(connection, type, map.getFrameSeq(), map.getMembers(), msg);
}
-LATENCY_TRACK(sys::LatencyTracker<const AMQBody*> doOutputTracker("DoOutput");)
-
// Handler for deliverFrameQueue.
// This thread executes the main logic.
- void Cluster::deliveredFrame(const EventFrame& efConst) {
- LATENCY_TRACK(frameQueueLatencyTracker.finish(e.frame.getBody()));
- LATENCY_TRACK(if (e.frame.getBody()->type() == CONTENT_BODY) doOutputTracker.start(e.frame.getBody()));
+void Cluster::deliveredFrame(const EventFrame& efConst) {
Mutex::ScopedLock l(lock);
if (state == LEFT) return;
EventFrame e(efConst);
@@ -434,7 +427,6 @@ void Cluster::processFrame(const EventFrame& e, Lock& l) {
throw Exception(QPID_MSG("Invalid cluster control"));
}
else if (state >= CATCHUP) {
- LATENCY_TRACK(LatencyScope ls(processLatency));
map.incrementFrameSeq();
ConnectionPtr connection = getConnection(e, l);
if (connection) {
diff --git a/qpid/cpp/src/qpid/cluster/ErrorCheck.cpp b/qpid/cpp/src/qpid/cluster/ErrorCheck.cpp
index 35be055d06..5b7011047b 100644
--- a/qpid/cpp/src/qpid/cluster/ErrorCheck.cpp
+++ b/qpid/cpp/src/qpid/cluster/ErrorCheck.cpp
@@ -45,7 +45,8 @@ ostream& operator<<(ostream& o, const ErrorCheck::MemberSet& ms) {
}
void ErrorCheck::error(
- Connection& c, ErrorType t, framing::SequenceNumber seq, const MemberSet& ms, const std::string& msg)
+ Connection& c, ErrorType t, framing::SequenceNumber seq, const MemberSet& ms,
+ const std::string& msg)
{
// Detected a local error, inform cluster and set error state.
assert(t != ERROR_TYPE_NONE); // Must be an error.
@@ -54,10 +55,11 @@ void ErrorCheck::error(
unresolved = ms;
frameSeq = seq;
connection = &c;
- QPID_LOG(error, cluster
- << (type == ERROR_TYPE_SESSION ? " channel" : " connection")
- << " error " << frameSeq << " on " << c << ": " << msg
- << " must be resolved with: " << unresolved);
+ message = msg;
+ QPID_LOG(debug, cluster<< (type == ERROR_TYPE_SESSION ? " channel" : " connection")
+ << " error " << frameSeq << " on " << c
+ << " must be resolved with: " << unresolved
+ << ": " << message);
mcast.mcastControl(
ClusterErrorCheckBody(ProtocolVersion(), type, frameSeq), cluster.getId());
// If there are already frames queued up by a previous error, review
@@ -84,13 +86,15 @@ ErrorCheck::FrameQueue::iterator ErrorCheck::review(const FrameQueue::iterator&
if (errorCheck->getFrameSeq() == frameSeq) { // Addresses current error
next = frames.erase(i); // Drop matching error check controls
if (errorCheck->getType() < type) { // my error is worse than his
- QPID_LOG(critical, cluster << " error " << frameSeq
- << " did not occur on " << i->getMemberId());
- throw Exception(QPID_MSG("Error " << frameSeq
- << " did not occur on all members"));
+ QPID_LOG(critical, cluster
+ << " local error " << frameSeq << " did not occur on member "
+ << i->getMemberId()
+ << ": " << message);
+ throw Exception(
+ QPID_MSG("local error did not occur on all cluster members " << ": " << message));
}
else { // his error is worse/same as mine.
- QPID_LOG(info, cluster << " error " << frameSeq
+ QPID_LOG(debug, cluster << " error " << frameSeq
<< " resolved with " << i->getMemberId());
unresolved.erase(i->getMemberId());
checkResolved();
@@ -128,10 +132,10 @@ ErrorCheck::FrameQueue::iterator ErrorCheck::review(const FrameQueue::iterator&
void ErrorCheck::checkResolved() {
if (unresolved.empty()) { // No more potentially conflicted members, we're clear.
type = ERROR_TYPE_NONE;
- QPID_LOG(info, cluster << " error " << frameSeq << " resolved.");
+ QPID_LOG(debug, cluster << " error " << frameSeq << " resolved.");
}
else
- QPID_LOG(info, cluster << " error " << frameSeq
+ QPID_LOG(debug, cluster << " error " << frameSeq
<< " must be resolved with " << unresolved);
}
@@ -146,7 +150,7 @@ void ErrorCheck::respondNone(const MemberId& from, uint8_t type, framing::Sequen
// Don't respond to non-errors or to my own errors.
if (type == ERROR_TYPE_NONE || from == cluster.getId())
return;
- QPID_LOG(info, cluster << " error " << frameSeq << " did not occur locally.");
+ QPID_LOG(debug, cluster << " error " << frameSeq << " did not occur locally.");
mcast.mcastControl(
ClusterErrorCheckBody(ProtocolVersion(), ERROR_TYPE_NONE, frameSeq),
cluster.getId()
diff --git a/qpid/cpp/src/qpid/cluster/ErrorCheck.h b/qpid/cpp/src/qpid/cluster/ErrorCheck.h
index 09028391ac..c975b9af64 100644
--- a/qpid/cpp/src/qpid/cluster/ErrorCheck.h
+++ b/qpid/cpp/src/qpid/cluster/ErrorCheck.h
@@ -84,6 +84,7 @@ class ErrorCheck
SequenceNumber frameSeq;
ErrorType type;
Connection* connection;
+ std::string message;
};
}} // namespace qpid::cluster
diff --git a/qpid/cpp/src/qpid/cluster/Event.cpp b/qpid/cpp/src/qpid/cluster/Event.cpp
index 30866d3154..4831e7eabe 100644
--- a/qpid/cpp/src/qpid/cluster/Event.cpp
+++ b/qpid/cpp/src/qpid/cluster/Event.cpp
@@ -38,9 +38,6 @@ const size_t EventHeader::HEADER_SIZE =
sizeof(uint8_t) + // type
sizeof(uint64_t) + // connection pointer only, CPG provides member ID.
sizeof(uint32_t) // payload size
-#ifdef QPID_LATENCY_METRIC
- + sizeof(int64_t) // timestamp
-#endif
;
EventHeader::EventHeader(EventType t, const ConnectionId& c, size_t s)
@@ -61,9 +58,6 @@ void EventHeader::decode(const MemberId& m, framing::Buffer& buf) {
throw Exception("Invalid multicast event type");
connectionId = ConnectionId(m, buf.getLongLong());
size = buf.getLong();
-#ifdef QPID_LATENCY_METRIC
- latency_metric_timestamp = buf.getLongLong();
-#endif
}
Event Event::decodeCopy(const MemberId& m, framing::Buffer& buf) {
@@ -97,9 +91,6 @@ void EventHeader::encode(Buffer& b) const {
b.putOctet(type);
b.putLongLong(connectionId.getNumber());
b.putLong(size);
-#ifdef QPID_LATENCY_METRIC
- b.putLongLong(latency_metric_timestamp);
-#endif
}
// Encode my header in my buffer.
diff --git a/qpid/cpp/src/qpid/cluster/Multicaster.cpp b/qpid/cpp/src/qpid/cluster/Multicaster.cpp
index 7e97963318..72fc1533f8 100644
--- a/qpid/cpp/src/qpid/cluster/Multicaster.cpp
+++ b/qpid/cpp/src/qpid/cluster/Multicaster.cpp
@@ -31,9 +31,6 @@ namespace cluster {
Multicaster::Multicaster(Cpg& cpg_,
const boost::shared_ptr<sys::Poller>& poller,
boost::function<void()> onError_) :
-#if defined (QPID_LATENCY_TRACKER)
- cpgLatency("CPG"),
-#endif
onError(onError_), cpg(cpg_),
queue(boost::bind(&Multicaster::sendMcast, this, _1), poller),
holding(true)
@@ -61,7 +58,6 @@ void Multicaster::mcastBuffer(const char* data, size_t size, const ConnectionId&
void Multicaster::mcast(const Event& e) {
{
sys::Mutex::ScopedLock l(lock);
- LATENCY_TRACK(cpgLatency.start());
if (e.isConnection() && holding) {
holdingQueue.push_back(e);
return;
diff --git a/qpid/cpp/src/qpid/cluster/Multicaster.h b/qpid/cpp/src/qpid/cluster/Multicaster.h
index f2ee5099bb..c1a0ddffc6 100644
--- a/qpid/cpp/src/qpid/cluster/Multicaster.h
+++ b/qpid/cpp/src/qpid/cluster/Multicaster.h
@@ -26,7 +26,6 @@
#include "qpid/cluster/Event.h"
#include "qpid/sys/PollableQueue.h"
#include "qpid/sys/Mutex.h"
-#include "qpid/sys/LatencyTracker.h"
#include <boost/shared_ptr.hpp>
#include <deque>
@@ -58,8 +57,6 @@ class Multicaster
/** End holding mode, held events are mcast */
void release();
- LATENCY_TRACK(sys::LatencyCounter cpgLatency;)
-
private:
typedef sys::PollableQueue<Event> PollableEventQueue;
typedef std::deque<Event> PlainEventQueue;
diff --git a/qpid/cpp/src/qpid/cluster/OutputInterceptor.cpp b/qpid/cpp/src/qpid/cluster/OutputInterceptor.cpp
index cb8f01386c..cb75fe5561 100644
--- a/qpid/cpp/src/qpid/cluster/OutputInterceptor.cpp
+++ b/qpid/cpp/src/qpid/cluster/OutputInterceptor.cpp
@@ -24,7 +24,6 @@
#include "qpid/framing/ClusterConnectionDeliverDoOutputBody.h"
#include "qpid/framing/AMQFrame.h"
#include "qpid/log/Statement.h"
-#include "qpid/sys/LatencyTracker.h"
#include <boost/current_function.hpp>
@@ -40,16 +39,9 @@ OutputInterceptor::OutputInterceptor(Connection& p, sys::ConnectionOutputHandler
: parent(p), closing(false), next(&h), sendMax(1), sent(0), sentDoOutput(false)
{}
-#if defined QPID_LATENCY_TRACKER
-extern sys::LatencyTracker<const AMQBody*> doOutputTracker;
-#endif
-
void OutputInterceptor::send(framing::AMQFrame& f) {
- LATENCY_TRACK(doOutputTracker.finish(f.getBody()));
- {
- sys::Mutex::ScopedLock l(lock);
- next->send(f);
- }
+ sys::Mutex::ScopedLock l(lock);
+ next->send(f);
}
void OutputInterceptor::activateOutput() {
diff --git a/qpid/cpp/src/qpid/cluster/UpdateClient.cpp b/qpid/cpp/src/qpid/cluster/UpdateClient.cpp
index 2e557f2ab6..d6df8bd5ac 100644
--- a/qpid/cpp/src/qpid/cluster/UpdateClient.cpp
+++ b/qpid/cpp/src/qpid/cluster/UpdateClient.cpp
@@ -209,9 +209,16 @@ class MessageUpdater {
ClusterConnectionProxy(session).expiryId(*expiryId);
}
+ // We can't send a broker::Message via the normal client API,
+ // and it would be expensive to copy it into a client::Message
+ // so we go a bit under the client API covers here.
+ //
SessionBase_0_10Access sb(session);
+ // Disable client code that clears the delivery-properties.exchange
+ sb.get()->setDoClearDeliveryPropertiesExchange(false);
framing::MessageTransferBody transfer(
- framing::ProtocolVersion(), UpdateClient::UPDATE, message::ACCEPT_MODE_NONE, message::ACQUIRE_MODE_PRE_ACQUIRED);
+ framing::ProtocolVersion(), UpdateClient::UPDATE, message::ACCEPT_MODE_NONE,
+ message::ACQUIRE_MODE_PRE_ACQUIRED);
sb.get()->send(transfer, message.payload->getFrames(), !message.payload->isContentReleased());
if (message.payload->isContentReleased()){
diff --git a/qpid/cpp/src/qpid/cluster/UpdateExchange.h b/qpid/cpp/src/qpid/cluster/UpdateExchange.h
index 194a3d386d..00a92c7f1e 100644
--- a/qpid/cpp/src/qpid/cluster/UpdateExchange.h
+++ b/qpid/cpp/src/qpid/cluster/UpdateExchange.h
@@ -30,7 +30,7 @@ namespace qpid {
namespace cluster {
/**
- * A keyless exchange (like fanout exchange) that does not modify deliver-properties.exchange
+ * A keyless exchange (like fanout exchange) that does not modify delivery-properties.exchange
* on messages.
*/
class UpdateExchange : public broker::FanOutExchange
diff --git a/qpid/cpp/src/qpid/messaging/ListContent.cpp b/qpid/cpp/src/qpid/messaging/ListContent.cpp
new file mode 100644
index 0000000000..0c3ca5fc62
--- /dev/null
+++ b/qpid/cpp/src/qpid/messaging/ListContent.cpp
@@ -0,0 +1,98 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/messaging/ListContent.h"
+#include "qpid/messaging/Message.h"
+#include "qpid/client/amqp0_10/Codecs.h"
+
+namespace qpid {
+namespace messaging {
+
+class ListContentImpl : public Variant
+{
+ Message* msg;
+ public:
+ ListContentImpl(Message& m) : Variant(Variant::List()), msg(&m)
+ {
+ if (msg->getContent().size()) {
+ qpid::client::amqp0_10::ListCodec codec;
+ codec.decode(msg->getContent(), *this);
+ }
+ }
+
+ void encode()
+ {
+ qpid::client::amqp0_10::ListCodec codec;
+ codec.encode(*this, msg->getContent());
+ }
+};
+
+ListContent::ListContent(Message& m) : impl(new ListContentImpl(m)) {}
+ListContent::~ListContent() { delete impl; }
+ListContent& ListContent::operator=(const ListContent& l) { *impl = *l.impl; return *this; }
+
+ListContent::const_iterator ListContent::begin() const { return impl->asList().begin(); }
+ListContent::const_iterator ListContent::end() const { return impl->asList().end(); }
+ListContent::const_reverse_iterator ListContent::rbegin() const { return impl->asList().rbegin(); }
+ListContent::const_reverse_iterator ListContent::rend() const { return impl->asList().rend(); }
+
+ListContent::iterator ListContent::begin() { return impl->asList().begin(); }
+ListContent::iterator ListContent::end() { return impl->asList().end(); }
+ListContent::reverse_iterator ListContent::rbegin() { return impl->asList().rbegin(); }
+ListContent::reverse_iterator ListContent::rend() { return impl->asList().rend(); }
+
+bool ListContent::empty() const { return impl->asList().empty(); }
+size_t ListContent::size() const { return impl->asList().size(); }
+
+const Variant& ListContent::front() const { return impl->asList().front(); }
+Variant& ListContent::front() { return impl->asList().front(); }
+const Variant& ListContent::back() const { return impl->asList().back(); }
+Variant& ListContent::back() { return impl->asList().back(); }
+
+void ListContent::push_front(const Variant& v) { impl->asList().push_front(v); }
+void ListContent::push_back(const Variant& v) { impl->asList().push_back(v); }
+
+void ListContent::pop_front() { impl->asList().pop_front(); }
+void ListContent::pop_back() { impl->asList().pop_back(); }
+
+ListContent::iterator ListContent::insert(iterator position, const Variant& v)
+{
+ return impl->asList().insert(position, v);
+}
+void ListContent::insert(iterator position, size_t n, const Variant& v)
+{
+ impl->asList().insert(position, n, v);
+}
+ListContent::iterator ListContent::erase(iterator position) { return impl->asList().erase(position); }
+ListContent::iterator ListContent::erase(iterator first, iterator last) { return impl->asList().erase(first, last); }
+void ListContent::clear() { impl->asList().clear(); }
+
+void ListContent::encode() { impl->encode(); }
+
+const Variant::List& ListContent::asList() const { return impl->asList(); }
+Variant::List& ListContent::asList() { return impl->asList(); }
+
+std::ostream& operator<<(std::ostream& out, const ListContent& m)
+{
+ out << m.asList();
+ return out;
+}
+
+}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/ListView.cpp b/qpid/cpp/src/qpid/messaging/ListView.cpp
new file mode 100644
index 0000000000..b717d157fa
--- /dev/null
+++ b/qpid/cpp/src/qpid/messaging/ListView.cpp
@@ -0,0 +1,63 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/messaging/ListView.h"
+#include "qpid/messaging/Message.h"
+#include "qpid/client/amqp0_10/Codecs.h"
+
+namespace qpid {
+namespace messaging {
+
+class ListViewImpl : public Variant
+{
+ public:
+ ListViewImpl(const Message& msg) : Variant(Variant::List())
+ {
+ if (msg.getContent().size()) {
+ qpid::client::amqp0_10::ListCodec codec;
+ codec.decode(msg.getContent(), *this);
+ }
+ }
+};
+
+ListView::ListView(const Message& m) :impl(new ListViewImpl(m)) {}
+ListView::~ListView() { delete impl; }
+ListView& ListView::operator=(const ListView& l) { *impl = *l.impl; return *this; }
+
+ListView::const_iterator ListView::begin() const { return impl->asList().begin(); }
+ListView::const_iterator ListView::end() const { return impl->asList().end(); }
+ListView::const_reverse_iterator ListView::rbegin() const { return impl->asList().rbegin(); }
+ListView::const_reverse_iterator ListView::rend() const { return impl->asList().rend(); }
+
+bool ListView::empty() const { return impl->asList().empty(); }
+size_t ListView::size() const { return impl->asList().size(); }
+
+const Variant& ListView::front() const { return impl->asList().front(); }
+const Variant& ListView::back() const { return impl->asList().back(); }
+
+const Variant::List& ListView::asList() const { return impl->asList(); }
+
+std::ostream& operator<<(std::ostream& out, const ListView& m)
+{
+ out << m.asList();
+ return out;
+}
+
+}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/MapContent.cpp b/qpid/cpp/src/qpid/messaging/MapContent.cpp
new file mode 100644
index 0000000000..c653561fc9
--- /dev/null
+++ b/qpid/cpp/src/qpid/messaging/MapContent.cpp
@@ -0,0 +1,87 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/messaging/MapContent.h"
+#include "qpid/messaging/Message.h"
+#include "qpid/client/amqp0_10/Codecs.h"
+
+namespace qpid {
+namespace messaging {
+
+class MapContentImpl : public Variant
+{
+ Message* msg;
+ public:
+ MapContentImpl(Message& m) : Variant(Variant::Map()), msg(&m)
+ {
+ if (msg->getContent().size()) {
+ qpid::client::amqp0_10::MapCodec codec;
+ codec.decode(msg->getContent(), *this);
+ }
+ }
+
+ void encode()
+ {
+ qpid::client::amqp0_10::MapCodec codec;
+ codec.encode(*this, msg->getContent());
+ }
+};
+
+MapContent::MapContent(Message& m) : impl(new MapContentImpl(m)) {}
+MapContent::~MapContent() { delete impl; }
+MapContent& MapContent::operator=(const MapContent& m) { *impl = *m.impl; return *this; }
+
+MapContent::const_iterator MapContent::begin() const { return impl->asMap().begin(); }
+MapContent::const_iterator MapContent::end() const { return impl->asMap().end(); }
+MapContent::const_reverse_iterator MapContent::rbegin() const { return impl->asMap().rbegin(); }
+MapContent::const_reverse_iterator MapContent::rend() const { return impl->asMap().rend(); }
+MapContent::iterator MapContent::begin() { return impl->asMap().begin(); }
+MapContent::iterator MapContent::end() { return impl->asMap().end(); }
+MapContent::reverse_iterator MapContent::rbegin() { return impl->asMap().rbegin(); }
+MapContent::reverse_iterator MapContent::rend() { return impl->asMap().rend(); }
+
+bool MapContent::empty() const { return impl->asMap().empty(); }
+size_t MapContent::size() const { return impl->asMap().size(); }
+
+MapContent::const_iterator MapContent::find(const key_type& key) const { return impl->asMap().find(key); }
+MapContent::iterator MapContent::find(const key_type& key) { return impl->asMap().find(key); }
+const Variant& MapContent::operator[](const key_type& key) const { return impl->asMap()[key]; }
+Variant& MapContent::operator[](const key_type& key) { return impl->asMap()[key]; }
+
+std::pair<MapContent::iterator,bool> MapContent::insert(const value_type& item) { return impl->asMap().insert(item); }
+MapContent::iterator MapContent::insert(iterator position, const value_type& item) { return impl->asMap().insert(position, item); }
+void MapContent::erase(iterator position) { impl->asMap().erase(position); }
+void MapContent::erase(iterator first, iterator last) { impl->asMap().erase(first, last); }
+size_t MapContent::erase(const key_type& key) { return impl->asMap().erase(key); }
+void MapContent::clear() { impl->asMap().clear(); }
+
+void MapContent::encode() { impl->encode(); }
+
+const std::map<MapContent::key_type, Variant>& MapContent::asMap() const { return impl->asMap(); }
+std::map<MapContent::key_type, Variant>& MapContent::asMap() { return impl->asMap(); }
+
+
+std::ostream& operator<<(std::ostream& out, const MapContent& m)
+{
+ out << m.asMap();
+ return out;
+}
+
+}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/MapView.cpp b/qpid/cpp/src/qpid/messaging/MapView.cpp
new file mode 100644
index 0000000000..ffa6e91a16
--- /dev/null
+++ b/qpid/cpp/src/qpid/messaging/MapView.cpp
@@ -0,0 +1,63 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/messaging/MapView.h"
+#include "qpid/messaging/Message.h"
+#include "qpid/client/amqp0_10/Codecs.h"
+
+namespace qpid {
+namespace messaging {
+
+class MapViewImpl : public Variant
+{
+ public:
+ MapViewImpl(const Message& msg) : Variant(Variant::Map())
+ {
+ if (msg.getContent().size()) {
+ qpid::client::amqp0_10::MapCodec codec;
+ codec.decode(msg.getContent(), *this);
+ }
+ }
+};
+
+MapView::MapView(const Message& m) : impl(new MapViewImpl(m)) {}
+MapView::~MapView() { delete impl; }
+MapView& MapView::operator=(const MapView& m) { *impl = *m.impl; return *this; }
+
+MapView::const_iterator MapView::begin() const { return impl->asMap().begin(); }
+MapView::const_iterator MapView::end() const { return impl->asMap().end(); }
+MapView::const_reverse_iterator MapView::rbegin() const { return impl->asMap().rbegin(); }
+MapView::const_reverse_iterator MapView::rend() const { return impl->asMap().rend(); }
+
+bool MapView::empty() const { return impl->asMap().empty(); }
+size_t MapView::size() const { return impl->asMap().size(); }
+
+MapView::const_iterator MapView::find(const key_type& key) const { return impl->asMap().find(key); }
+const Variant& MapView::operator[](const key_type& key) const { return impl->asMap()[key]; }
+
+const std::map<MapView::key_type, Variant>& MapView::asMap() const { return impl->asMap(); }
+
+std::ostream& operator<<(std::ostream& out, const MapView& m)
+{
+ out << m.asMap();
+ return out;
+}
+
+}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/Message.cpp b/qpid/cpp/src/qpid/messaging/Message.cpp
index 1d844b3027..fb4e800eaa 100644
--- a/qpid/cpp/src/qpid/messaging/Message.cpp
+++ b/qpid/cpp/src/qpid/messaging/Message.cpp
@@ -27,7 +27,7 @@ namespace messaging {
Message::Message(const std::string& bytes) : impl(new MessageImpl(bytes)) {}
Message::Message(const char* bytes, size_t count) : impl(new MessageImpl(bytes, count)) {}
-Message::Message(const Message& m) : impl(new MessageImpl(m.getBytes())) {}
+Message::Message(const Message& m) : impl(new MessageImpl(m.getContent())) {}
Message::~Message() { delete impl; }
Message& Message::operator=(const Message& m) { *impl = *m.impl; return *this; }
@@ -44,27 +44,15 @@ const std::string& Message::getContentType() const { return impl->getContentType
const VariantMap& Message::getHeaders() const { return impl->getHeaders(); }
VariantMap& Message::getHeaders() { return impl->getHeaders(); }
-void Message::setBytes(const std::string& c) { impl->setBytes(c); }
-void Message::setBytes(const char* chars, size_t count) { impl->setBytes(chars, count); }
-const std::string& Message::getBytes() const { return impl->getBytes(); }
-std::string& Message::getBytes() { return impl->getBytes(); }
+void Message::setContent(const std::string& c) { impl->setBytes(c); }
+void Message::setContent(const char* chars, size_t count) { impl->setBytes(chars, count); }
+const std::string& Message::getContent() const { return impl->getBytes(); }
+std::string& Message::getContent() { return impl->getBytes(); }
-const char* Message::getRawContent() const { return impl->getBytes().data(); }
-size_t Message::getContentSize() const { return impl->getBytes().size(); }
-
-MessageContent& Message::getContent() { return *impl; }
-const MessageContent& Message::getContent() const { return *impl; }
-void Message::setContent(const std::string& s) { *impl = s; }
-void Message::setContent(const Variant::Map& m) { *impl = m; }
-void Message::setContent(const Variant::List& l) { *impl = l; }
-
-void Message::encode(Codec& codec) { impl->encode(codec); }
-
-void Message::decode(Codec& codec) { impl->decode(codec); }
-
-std::ostream& operator<<(std::ostream& out, const MessageContent& content)
+void Message::getContent(std::pair<const char*, size_t>& content) const
{
- return content.print(out);
+ content.first = impl->getBytes().data();
+ content.second = impl->getBytes().size();
}
}} // namespace qpid::messaging
diff --git a/qpid/cpp/src/qpid/messaging/MessageImpl.cpp b/qpid/cpp/src/qpid/messaging/MessageImpl.cpp
index 5df9218e03..e17fccd64f 100644
--- a/qpid/cpp/src/qpid/messaging/MessageImpl.cpp
+++ b/qpid/cpp/src/qpid/messaging/MessageImpl.cpp
@@ -28,8 +28,8 @@ namespace {
const std::string EMPTY_STRING = "";
}
-MessageImpl::MessageImpl(const std::string& c) : bytes(c), type(VAR_VOID), internalId(0) {}
-MessageImpl::MessageImpl(const char* chars, size_t count) : bytes(chars, count), type(VAR_VOID), internalId(0) {}
+MessageImpl::MessageImpl(const std::string& c) : bytes(c), internalId(0) {}
+MessageImpl::MessageImpl(const char* chars, size_t count) : bytes(chars, count), internalId(0) {}
void MessageImpl::setReplyTo(const Address& d) { replyTo = d; }
const Address& MessageImpl::getReplyTo() const { return replyTo; }
@@ -44,155 +44,14 @@ const VariantMap& MessageImpl::getHeaders() const { return headers; }
VariantMap& MessageImpl::getHeaders() { return headers; }
//should these methods be on MessageContent?
-void MessageImpl::setBytes(const std::string& c) { clear(); bytes = c; }
-void MessageImpl::setBytes(const char* chars, size_t count) { clear(); bytes.assign(chars, count); }
+void MessageImpl::setBytes(const std::string& c) { bytes = c; }
+void MessageImpl::setBytes(const char* chars, size_t count) { bytes.assign(chars, count); }
const std::string& MessageImpl::getBytes() const { return bytes; }
std::string& MessageImpl::getBytes() { return bytes; }
-
-Variant& MessageImpl::operator[](const std::string& key) { return asMap()[key]; }
-
-std::ostream& MessageImpl::print(std::ostream& out) const
-{
- if (type == VAR_MAP) {
- return out << content.asMap();
- } else if (type == VAR_LIST) {
- return out << content.asList();
- } else {
- return out << bytes;
- }
-}
-
-template <class T> MessageContent& MessageImpl::append(T& t)
-{
- if (type == VAR_VOID) {
- //TODO: this is inefficient, probably want to hold on to the stream object
- std::stringstream s;
- s << bytes;
- s << t;
- bytes = s.str();
- } else if (type == VAR_LIST) {
- content.asList().push_back(Variant(t));
- } else {
- throw InvalidConversion("<< operator only valid on strings and lists");
- }
- return *this;
-}
-
-MessageContent& MessageImpl::operator<<(const std::string& v) { return append(v); }
-MessageContent& MessageImpl::operator<<(const char* v) { return append(v); }
-MessageContent& MessageImpl::operator<<(bool v) { return append(v); }
-MessageContent& MessageImpl::operator<<(int8_t v) { return append(v); }
-MessageContent& MessageImpl::operator<<(int16_t v) { return append(v); }
-MessageContent& MessageImpl::operator<<(int32_t v) { return append(v); }
-MessageContent& MessageImpl::operator<<(int64_t v) { return append(v); }
-MessageContent& MessageImpl::operator<<(uint8_t v) { return append(v); }
-MessageContent& MessageImpl::operator<<(uint16_t v) { return append(v); }
-MessageContent& MessageImpl::operator<<(uint32_t v) { return append(v); }
-MessageContent& MessageImpl::operator<<(uint64_t v) { return append(v); }
-MessageContent& MessageImpl::operator<<(double v) { return append(v); }
-MessageContent& MessageImpl::operator<<(float v) { return append(v); }
-MessageContent& MessageImpl::operator=(const std::string& s)
-{
- type = VAR_VOID;
- bytes = s;
- return *this;
-}
-MessageContent& MessageImpl::operator=(const char* c)
-{
- type = VAR_VOID;
- bytes = c;
- return *this;
-}
-MessageContent& MessageImpl::operator=(const Variant::Map& m)
-{
- type = VAR_MAP;
- content = m;
- return *this;
-}
-
-MessageContent& MessageImpl::operator=(const Variant::List& l)
-{
- type = VAR_LIST;
- content = l;
- return *this;
-}
-
-void MessageImpl::encode(Codec& codec)
-{
- if (content.getType() != VAR_VOID) {
- bytes = EMPTY_STRING;
- codec.encode(content, bytes);
- }
-}
-
-void MessageImpl::getEncodedContent(Codec& codec, std::string& out) const
-{
- if (content.getType() != VAR_VOID) {
- codec.encode(content, out);
- } else {
- out = bytes;
- }
-}
-
-void MessageImpl::decode(Codec& codec)
-{
- codec.decode(bytes, content);
- if (content.getType() == VAR_MAP) type = VAR_MAP;
- else if (content.getType() == VAR_LIST) type = VAR_LIST;
- else type = VAR_VOID;//TODO: what if codec set some type other than map or list??
-}
-
void MessageImpl::setInternalId(qpid::framing::SequenceNumber i) { internalId = i; }
qpid::framing::SequenceNumber MessageImpl::getInternalId() { return internalId; }
-bool MessageImpl::isVoid() const { return type == VAR_VOID; }
-
-const std::string& MessageImpl::asString() const
-{
- if (isVoid()) return getBytes();
- else return content.getString();//will throw an error
-}
-std::string& MessageImpl::asString()
-{
- if (isVoid()) return getBytes();
- else return content.getString();//will throw an error
-}
-
-const char* MessageImpl::asChars() const
-{
- if (!isVoid()) throw InvalidConversion("Content is of structured type.");
- return bytes.data();
-}
-size_t MessageImpl::size() const
-{
- return bytes.size();
-}
-
-const Variant::Map& MessageImpl::asMap() const { return content.asMap(); }
-Variant::Map& MessageImpl::asMap()
-{
- if (isVoid()) {
- content = Variant::Map();
- type = VAR_MAP;
- }
- return content.asMap();
-}
-bool MessageImpl::isMap() const { return type == VAR_MAP; }
-
-const Variant::List& MessageImpl::asList() const { return content.asList(); }
-Variant::List& MessageImpl::asList()
-{
- if (isVoid()) {
- content = Variant::List();
- type = VAR_LIST;
- }
- return content.asList();
-}
-bool MessageImpl::isList() const { return type == VAR_LIST; }
-
-void MessageImpl::clear() { bytes = EMPTY_STRING; content.reset(); type = VAR_VOID; }
-
MessageImpl& MessageImplAccess::get(Message& msg)
{
return *msg.impl;
diff --git a/qpid/cpp/src/qpid/messaging/MessageImpl.h b/qpid/cpp/src/qpid/messaging/MessageImpl.h
index 1173e7570a..4939cdc5cc 100644
--- a/qpid/cpp/src/qpid/messaging/MessageImpl.h
+++ b/qpid/cpp/src/qpid/messaging/MessageImpl.h
@@ -22,15 +22,13 @@
*
*/
#include "qpid/messaging/Address.h"
-#include "qpid/messaging/Codec.h"
-#include "qpid/messaging/MessageContent.h"
#include "qpid/messaging/Variant.h"
#include "qpid/framing/SequenceNumber.h"
namespace qpid {
namespace messaging {
-struct MessageImpl : MessageContent
+struct MessageImpl
{
Address replyTo;
std::string subject;
@@ -38,8 +36,6 @@ struct MessageImpl : MessageContent
Variant::Map headers;
std::string bytes;
- Variant content;//used only for LIST and MAP
- VariantType type;//if LIST, MAP content holds the value; if VOID bytes holds the value
qpid::framing::SequenceNumber internalId;
@@ -66,54 +62,6 @@ struct MessageImpl : MessageContent
void setInternalId(qpid::framing::SequenceNumber id);
qpid::framing::SequenceNumber getInternalId();
- bool isVoid() const;
-
- const std::string& asString() const;
- std::string& asString();
-
- const char* asChars() const;
- size_t size() const;
-
- const Variant::Map& asMap() const;
- Variant::Map& asMap();
- bool isMap() const;
-
- const Variant::List& asList() const;
- Variant::List& asList();
- bool isList() const;
-
- void clear();
-
- void getEncodedContent(Codec& codec, std::string&) const;
- void encode(Codec& codec);
- void decode(Codec& codec);
-
- Variant& operator[](const std::string&);
-
- std::ostream& print(std::ostream& out) const;
-
- //operator<< for variety of types...
- MessageContent& operator<<(const std::string&);
- MessageContent& operator<<(const char*);
- MessageContent& operator<<(bool);
- MessageContent& operator<<(int8_t);
- MessageContent& operator<<(int16_t);
- MessageContent& operator<<(int32_t);
- MessageContent& operator<<(int64_t);
- MessageContent& operator<<(uint8_t);
- MessageContent& operator<<(uint16_t);
- MessageContent& operator<<(uint32_t);
- MessageContent& operator<<(uint64_t);
- MessageContent& operator<<(double);
- MessageContent& operator<<(float);
-
- //assignment from string, map and list
- MessageContent& operator=(const std::string&);
- MessageContent& operator=(const char*);
- MessageContent& operator=(const Variant::Map&);
- MessageContent& operator=(const Variant::List&);
-
- template <class T> MessageContent& append(T& t);
};
class Message;
diff --git a/qpid/cpp/src/qpid/sys/AsynchIO.h b/qpid/cpp/src/qpid/sys/AsynchIO.h
index fb02183359..419770568a 100644
--- a/qpid/cpp/src/qpid/sys/AsynchIO.h
+++ b/qpid/cpp/src/qpid/sys/AsynchIO.h
@@ -57,7 +57,7 @@ public:
class AsynchConnector {
public:
typedef boost::function1<void, const Socket&> ConnectedCallback;
- typedef boost::function2<void, int, std::string> FailedCallback;
+ typedef boost::function3<void, const Socket&, int, const std::string&> FailedCallback;
// Call create() to allocate a new AsynchConnector object with the
// specified poller, addressing, and callbacks.
@@ -70,7 +70,7 @@ public:
std::string hostname,
uint16_t port,
ConnectedCallback connCb,
- FailedCallback failCb = 0);
+ FailedCallback failCb);
protected:
AsynchConnector() {}
@@ -108,7 +108,7 @@ class AsynchIO {
public:
typedef AsynchIOBufferBase BufferBase;
- typedef boost::function2<bool, AsynchIO&, BufferBase*> ReadCallback;
+ typedef boost::function2<void, AsynchIO&, BufferBase*> ReadCallback;
typedef boost::function1<void, AsynchIO&> EofCallback;
typedef boost::function1<void, AsynchIO&> DisconnectCallback;
typedef boost::function2<void, AsynchIO&, const Socket&> ClosedCallback;
diff --git a/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp b/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp
index 8094abd43d..eb0f213547 100644
--- a/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp
+++ b/qpid/cpp/src/qpid/sys/AsynchIOHandler.cpp
@@ -103,10 +103,31 @@ void AsynchIOHandler::giveReadCredit(int32_t credit) {
aio->startReading();
}
-bool AsynchIOHandler::readbuff(AsynchIO& , AsynchIO::BufferBase* buff) {
+void AsynchIOHandler::readbuff(AsynchIO& , AsynchIO::BufferBase* buff) {
if (readError) {
- return false;
+ return;
+ }
+
+ // Check here for read credit
+ if (readCredit.get() != InfiniteCredit) {
+ if (readCredit.get() == 0) {
+ // FIXME aconway 2009-10-01: Workaround to avoid "false wakeups".
+ // readbuff is sometimes called with no credit.
+ // This should be fixed somewhere else to avoid such calls.
+ aio->unread(buff);
+ return;
+ }
+ // TODO In theory should be able to use an atomic operation before taking the lock
+ // but in practice there seems to be an unexplained race in that case
+ ScopedLock<Mutex> l(creditLock);
+ if (--readCredit == 0) {
+ assert(readCredit.get() >= 0);
+ if (readCredit.get() == 0) {
+ aio->stopReading();
+ }
+ }
}
+
size_t decoded = 0;
if (codec) { // Already initiated
try {
@@ -149,20 +170,6 @@ bool AsynchIOHandler::readbuff(AsynchIO& , AsynchIO::BufferBase* buff) {
// Give whole buffer back to aio subsystem
aio->queueReadBuffer(buff);
}
- // Check here for read credit
- if (readCredit.get() != InfiniteCredit) {
- // TODO In theory should be able to use an atomic operation before taking the lock
- // but in practice there seems to be an unexplained race in that case
- ScopedLock<Mutex> l(creditLock);
- if (--readCredit == 0) {
- assert(readCredit.get() >= 0);
- if (readCredit.get() == 0) {
- aio->stopReading();
- return false;
- }
- }
- }
- return true;
}
void AsynchIOHandler::eof(AsynchIO&) {
diff --git a/qpid/cpp/src/qpid/sys/AsynchIOHandler.h b/qpid/cpp/src/qpid/sys/AsynchIOHandler.h
index 9785f445a4..e1885bac79 100644
--- a/qpid/cpp/src/qpid/sys/AsynchIOHandler.h
+++ b/qpid/cpp/src/qpid/sys/AsynchIOHandler.h
@@ -65,7 +65,7 @@ class AsynchIOHandler : public OutputControl {
QPID_COMMON_EXTERN void giveReadCredit(int32_t credit);
// Input side
- QPID_COMMON_EXTERN bool readbuff(AsynchIO& aio, AsynchIOBufferBase* buff);
+ QPID_COMMON_EXTERN void readbuff(AsynchIO& aio, AsynchIOBufferBase* buff);
QPID_COMMON_EXTERN void eof(AsynchIO& aio);
QPID_COMMON_EXTERN void disconnect(AsynchIO& aio);
diff --git a/qpid/cpp/src/qpid/sys/LatencyTracker.h b/qpid/cpp/src/qpid/sys/LatencyTracker.h
deleted file mode 100644
index 3294528ff6..0000000000
--- a/qpid/cpp/src/qpid/sys/LatencyTracker.h
+++ /dev/null
@@ -1,157 +0,0 @@
-#ifndef QPID_SYS_LATENCYTRACKER_H
-#define QPID_SYS_LATENCYTRACKER_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/sys/Time.h"
-#include <string>
-#include <limits>
-#include <map>
-
-namespace qpid {
-namespace sys {
-
-/**@file Tools for measuring latency. NOT SUITABLE FOR PROUDCTION BUILDS.
- * Uses should be compiled only if QPID_LATENCY_TRACKER is defined.
- * See the convenience macros at the end of this file.
- */
-
-/** Used by LatencyCounter and LatencyTracker below */
-class LatencyStatistic {
- public:
- LatencyStatistic(std::string name_) : name(name_), count(0), total(0), min(std::numeric_limits<int64_t>::max()), max(0) {}
- ~LatencyStatistic() { print(); }
-
- void record(Duration d) {
- total += d;
- ++count;
- if (d > max) max=d;
- if (d < min) min=d;
- }
-
- void print() {
- if (count) {
- double meanMsec = (double(total)/count)/TIME_MSEC;
- printf("\n==== Latency metric %s: samples=%lu mean=%fms (%f-%f)\n", name.c_str(), count, meanMsec, double(min)/TIME_MSEC, double(max)/TIME_MSEC);
- }
- else
- printf("\n==== Latency metric %s: no samples.\n", name.c_str());
- }
-
- private:
- std::string name;
- unsigned long count;
- int64_t total, min, max;
-};
-
-/** Measure delay between seeing the same value at start and finish. */
-template <class T> class LatencyTracker {
- public:
- LatencyTracker(std::string name) : measuring(false), stat(name) {}
-
- void start(T value) {
- sys::Mutex::ScopedLock l(lock);
- if (!measuring) {
- measureAt = value;
- measuring = true;
- startTime = AbsTime::now();
- }
- }
-
- void finish(T value) {
- sys::Mutex::ScopedLock l(lock);
- if(measuring && measureAt == value) {
- stat.record(Duration(startTime, AbsTime::now()));
- measuring = false;
- }
- }
-
- private:
- sys::Mutex lock;
- bool measuring;
- T measureAt;
- AbsTime startTime;
- LatencyStatistic stat;
-};
-
-
-/** Measures delay between the nth call to start and the nth call to finish.
- * E.g. to measure latency between sending & receiving an ordered stream of messages.
- */
-class LatencyCounter {
- public:
- LatencyCounter(std::string name) : measuring(false), startCount(0), finishCount(0), stat(name) {}
-
- void start() {
- sys::Mutex::ScopedLock l(lock);
- if (!measuring) {
- measureAt = startCount;
- measuring = true;
- startTime = AbsTime::now();
- }
- ++startCount;
- }
-
- void finish() {
- sys::Mutex::ScopedLock l(lock);
- if (measuring && measureAt == finishCount) {
- stat.record(Duration(startTime, AbsTime::now()));
- measuring = false;
- }
- ++finishCount;
- }
-
- private:
- sys::Mutex lock;
- bool measuring;
- uint64_t startCount, finishCount, measureAt;
- AbsTime startTime;
- LatencyStatistic stat;
-};
-
-/** Measures time spent in a scope. */
-class LatencyScope {
- public:
- LatencyScope(LatencyStatistic& s) : stat(s), startTime(AbsTime::now()) {}
-
- ~LatencyScope() {
- sys::Mutex::ScopedLock l(lock);
- stat.record(Duration(startTime, AbsTime::now()));
- }
-
- private:
- sys::Mutex lock;
- LatencyStatistic& stat;
- AbsTime startTime;
-};
-
-
-/** Macros to wrap latency tracking so disabled unless QPID_LATENCY_TRACKER is defined */
-
-#if defined(QPID_LATENCY_TRACKER)
-#define LATENCY_TRACK(X) X
-#else
-#define LATENCY_TRACK(X)
-#endif
-}} // namespace qpid::sys
-
-#endif /*!QPID_SYS_LATENCYTRACKER_H*/
diff --git a/qpid/cpp/src/qpid/sys/RdmaIOPlugin.cpp b/qpid/cpp/src/qpid/sys/RdmaIOPlugin.cpp
index 6eafb6cf0b..28ff140237 100644
--- a/qpid/cpp/src/qpid/sys/RdmaIOPlugin.cpp
+++ b/qpid/cpp/src/qpid/sys/RdmaIOPlugin.cpp
@@ -29,6 +29,7 @@
#include "qpid/sys/OutputControl.h"
#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
#include <memory>
#include <netdb.h>
@@ -304,8 +305,9 @@ void RdmaIOProtocolFactory::accept(Poller::shared_ptr poller, ConnectionCodec::F
sin.sin_port = htons(listeningPort);
sin.sin_addr.s_addr = INADDR_ANY;
+ SocketAddress sa("",boost::lexical_cast<std::string>(listeningPort));
listener.reset(
- new Rdma::Listener((const sockaddr&)(sin),
+ new Rdma::Listener(sa,
Rdma::ConnectionParams(65536, Rdma::DEFAULT_WR_ENTRIES),
boost::bind(&RdmaIOProtocolFactory::established, this, poller, _1),
boost::bind(&RdmaIOProtocolFactory::connectionError, this, _1, _2),
@@ -331,24 +333,14 @@ void RdmaIOProtocolFactory::connected(Poller::shared_ptr poller, Rdma::Connectio
void RdmaIOProtocolFactory::connect(
Poller::shared_ptr poller,
- const std::string& host, int16_t p,
+ const std::string& host, int16_t port,
ConnectionCodec::Factory* f,
ConnectFailedCallback failed)
{
- ::addrinfo *res;
- ::addrinfo hints = {};
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
- stringstream ss; ss << p;
- string port = ss.str();
- int n = ::getaddrinfo(host.c_str(), port.c_str(), &hints, &res);
- if (n<0) {
- throw Exception(QPID_MSG("Rdma: Cannot resolve " << host << ": " << ::gai_strerror(n)));
- }
-
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
Rdma::Connector* c =
new Rdma::Connector(
- *res->ai_addr,
+ sa,
Rdma::ConnectionParams(8000, Rdma::DEFAULT_WR_ENTRIES),
boost::bind(&RdmaIOProtocolFactory::connected, this, poller, _1, _2, f),
boost::bind(&RdmaIOProtocolFactory::connectionError, this, _1, _2),
diff --git a/qpid/cpp/src/qpid/sys/Socket.h b/qpid/cpp/src/qpid/sys/Socket.h
index f389e99cb8..d108402682 100644
--- a/qpid/cpp/src/qpid/sys/Socket.h
+++ b/qpid/cpp/src/qpid/sys/Socket.h
@@ -31,6 +31,7 @@ namespace qpid {
namespace sys {
class Duration;
+class SocketAddress;
class Socket : public IOHandle
{
@@ -48,6 +49,7 @@ public:
void setNonblocking() const;
QPID_COMMON_EXTERN void connect(const std::string& host, uint16_t port) const;
+ QPID_COMMON_EXTERN void connect(const SocketAddress&) const;
QPID_COMMON_EXTERN void close() const;
diff --git a/qpid/cpp/src/qpid/sys/SocketAddress.h b/qpid/cpp/src/qpid/sys/SocketAddress.h
new file mode 100644
index 0000000000..fcb9c81d43
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/SocketAddress.h
@@ -0,0 +1,51 @@
+#ifndef _sys_SocketAddress_h
+#define _sys_SocketAddress_h
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/sys/IntegerTypes.h"
+#include "qpid/CommonImportExport.h"
+#include <string>
+
+struct addrinfo;
+
+namespace qpid {
+namespace sys {
+
+class SocketAddress {
+ friend const ::addrinfo& getAddrInfo(const SocketAddress&);
+
+public:
+ /** Create a SocketAddress from hostname and port*/
+ QPID_COMMON_EXTERN SocketAddress(const std::string& host, const std::string& port);
+ QPID_COMMON_EXTERN ~SocketAddress();
+
+ std::string asString() const;
+
+private:
+ std::string host;
+ std::string port;
+ ::addrinfo* addrInfo;
+};
+
+}}
+#endif /*!_sys_SocketAddress_h*/
diff --git a/qpid/cpp/src/qpid/sys/TCPIOPlugin.cpp b/qpid/cpp/src/qpid/sys/TCPIOPlugin.cpp
index b456beb098..3377be98f1 100644
--- a/qpid/cpp/src/qpid/sys/TCPIOPlugin.cpp
+++ b/qpid/cpp/src/qpid/sys/TCPIOPlugin.cpp
@@ -46,7 +46,7 @@ class AsynchIOProtocolFactory : public ProtocolFactory {
void accept(Poller::shared_ptr, ConnectionCodec::Factory*);
void connect(Poller::shared_ptr, const std::string& host, int16_t port,
ConnectionCodec::Factory*,
- boost::function2<void, int, std::string> failed);
+ ConnectFailedCallback);
uint16_t getPort() const;
std::string getHost() const;
@@ -54,6 +54,7 @@ class AsynchIOProtocolFactory : public ProtocolFactory {
private:
void established(Poller::shared_ptr, const Socket&, ConnectionCodec::Factory*,
bool isClient);
+ void connectFailed(const Socket&, int, const std::string&, ConnectFailedCallback);
};
// Static instance to initialise plugin
@@ -118,6 +119,15 @@ void AsynchIOProtocolFactory::accept(Poller::shared_ptr poller,
acceptor->start(poller);
}
+void AsynchIOProtocolFactory::connectFailed(
+ const Socket& s, int ec, const std::string& emsg,
+ ConnectFailedCallback failedCb)
+{
+ failedCb(ec, emsg);
+ s.close();
+ delete &s;
+}
+
void AsynchIOProtocolFactory::connect(
Poller::shared_ptr poller,
const std::string& host, int16_t port,
@@ -131,13 +141,14 @@ void AsynchIOProtocolFactory::connect(
// is no longer needed.
Socket* socket = new Socket();
- AsynchConnector::create (*socket,
- poller,
- host,
- port,
- boost::bind(&AsynchIOProtocolFactory::established,
- this, poller, _1, fact, true),
- failed);
+ AsynchConnector::create(*socket,
+ poller,
+ host,
+ port,
+ boost::bind(&AsynchIOProtocolFactory::established,
+ this, poller, _1, fact, true),
+ boost::bind(&AsynchIOProtocolFactory::connectFailed,
+ this, _1, _2, _3, failed));
}
}} // namespace qpid::sys
diff --git a/qpid/cpp/src/qpid/sys/posix/AsynchIO.cpp b/qpid/cpp/src/qpid/sys/posix/AsynchIO.cpp
index 8545ebd9cb..c042dcef01 100644
--- a/qpid/cpp/src/qpid/sys/posix/AsynchIO.cpp
+++ b/qpid/cpp/src/qpid/sys/posix/AsynchIO.cpp
@@ -21,6 +21,7 @@
#include "qpid/sys/AsynchIO.h"
#include "qpid/sys/Socket.h"
+#include "qpid/sys/SocketAddress.h"
#include "qpid/sys/Poller.h"
#include "qpid/sys/DispatchHandle.h"
#include "qpid/sys/Time.h"
@@ -37,6 +38,7 @@
#include <string.h>
#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
using namespace qpid::sys;
@@ -161,11 +163,12 @@ class AsynchConnector : public qpid::sys::AsynchConnector,
private:
void connComplete(DispatchHandle& handle);
- void failure(int, std::string);
+ void failure(int, const std::string&);
private:
ConnectedCallback connCallback;
FailedCallback failCallback;
+ std::string errMsg;
const Socket& socket;
public:
@@ -174,7 +177,7 @@ public:
std::string hostname,
uint16_t port,
ConnectedCallback connCb,
- FailedCallback failCb = 0);
+ FailedCallback failCb);
};
AsynchConnector::AsynchConnector(const Socket& s,
@@ -192,12 +195,17 @@ AsynchConnector::AsynchConnector(const Socket& s,
socket(s)
{
socket.setNonblocking();
+ SocketAddress sa(hostname, boost::lexical_cast<std::string>(port));
try {
- socket.connect(hostname, port);
- startWatch(poller);
+ socket.connect(sa);
} catch(std::exception& e) {
- failure(-1, std::string(e.what()));
+ // Defer reporting failure
+ startWatch(poller);
+ errMsg = e.what();
+ DispatchHandle::call(boost::bind(&AsynchConnector::failure, this, -1, errMsg));
+ return;
}
+ startWatch(poller);
}
void AsynchConnector::connComplete(DispatchHandle& h)
@@ -209,17 +217,13 @@ void AsynchConnector::connComplete(DispatchHandle& h)
connCallback(socket);
DispatchHandle::doDelete();
} else {
- failure(errCode, std::string(strError(errCode)));
+ failure(errCode, strError(errCode));
}
}
-void AsynchConnector::failure(int errCode, std::string message)
+void AsynchConnector::failure(int errCode, const std::string& message)
{
- if (failCallback)
- failCallback(errCode, message);
-
- socket.close();
- delete &socket;
+ failCallback(socket, errCode, message);
DispatchHandle::doDelete();
}
@@ -467,7 +471,8 @@ void AsynchIO::readable(DispatchHandle& h) {
threadReadTotal += rc;
readTotal += rc;
- if (!readCallback(*this, buff)) {
+ readCallback(*this, buff);
+ if (readingStopped) {
// We have been flow controlled.
break;
}
diff --git a/qpid/cpp/src/qpid/sys/posix/Socket.cpp b/qpid/cpp/src/qpid/sys/posix/Socket.cpp
index 31044be9ca..02004b1999 100644
--- a/qpid/cpp/src/qpid/sys/posix/Socket.cpp
+++ b/qpid/cpp/src/qpid/sys/posix/Socket.cpp
@@ -21,6 +21,7 @@
#include "qpid/sys/Socket.h"
+#include "qpid/sys/SocketAddress.h"
#include "qpid/sys/posix/check.h"
#include "qpid/sys/posix/PrivatePosix.h"
@@ -36,6 +37,7 @@
#include <iostream>
#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
namespace qpid {
namespace sys {
@@ -126,42 +128,23 @@ void Socket::setNonblocking() const {
QPID_POSIX_CHECK(::fcntl(impl->fd, F_SETFL, O_NONBLOCK));
}
-namespace {
-const char* h_errstr(int e) {
- switch (e) {
- case HOST_NOT_FOUND: return "Host not found";
- case NO_ADDRESS: return "Name does not have an IP address";
- case TRY_AGAIN: return "A temporary error occurred on an authoritative name server.";
- case NO_RECOVERY: return "Non-recoverable name server error";
- default: return "Unknown error";
- }
-}
+void Socket::connect(const std::string& host, uint16_t port) const
+{
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
+ connect(sa);
}
-void Socket::connect(const std::string& host, uint16_t p) const
+void Socket::connect(const SocketAddress& addr) const
{
- std::stringstream portstream;
- portstream << p;
- std::string port = portstream.str();
- connectname = host + ":" + port;
+ connectname = addr.asString();
const int& socket = impl->fd;
- ::addrinfo *res;
- ::addrinfo hints;
- ::memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET; // In order to allow AF_INET6 we'd have to change createTcp() as well
- hints.ai_socktype = SOCK_STREAM;
- int n = ::getaddrinfo(host.c_str(), port.c_str(), &hints, &res);
- if (n != 0)
- throw Exception(QPID_MSG("Cannot resolve " << host << ": " << ::gai_strerror(n)));
// TODO the correct thing to do here is loop on failure until you've used all the returned addresses
- if ((::connect(socket, res->ai_addr, res->ai_addrlen) < 0) &&
+ if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) < 0) &&
(errno != EINPROGRESS)) {
- ::freeaddrinfo(res);
- throw qpid::Exception(QPID_MSG(strError(errno) << ": " << host << ":" << port));
+ throw Exception(QPID_MSG(strError(errno) << ": " << connectname));
}
- ::freeaddrinfo(res);
}
void
@@ -178,15 +161,14 @@ int Socket::listen(uint16_t port, int backlog) const
const int& socket = impl->fd;
int yes=1;
QPID_POSIX_CHECK(setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)));
- struct sockaddr_in name;
- name.sin_family = AF_INET;
- name.sin_port = htons(port);
- name.sin_addr.s_addr = 0;
- if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) < 0)
+
+ SocketAddress sa("", boost::lexical_cast<std::string>(port));
+ if (::bind(socket, getAddrInfo(sa).ai_addr, getAddrInfo(sa).ai_addrlen) < 0)
throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(errno)));
if (::listen(socket, backlog) < 0)
throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(errno)));
-
+
+ struct sockaddr_in name;
socklen_t namelen = sizeof(name);
if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0)
throw QPID_POSIX_ERROR(errno);
@@ -226,9 +208,10 @@ std::string Socket::getPeername() const
std::string Socket::getPeerAddress() const
{
- if (!connectname.empty())
- return std::string (connectname);
- return getName(impl->fd, false, true);
+ if (connectname.empty()) {
+ connectname = getName(impl->fd, false, true);
+ }
+ return connectname;
}
std::string Socket::getLocalAddress() const
diff --git a/qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp b/qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp
new file mode 100644
index 0000000000..fe8812299c
--- /dev/null
+++ b/qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp
@@ -0,0 +1,71 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/sys/SocketAddress.h"
+
+#include "qpid/sys/posix/check.h"
+
+#include <sys/socket.h>
+#include <string.h>
+#include <netdb.h>
+
+namespace qpid {
+namespace sys {
+
+SocketAddress::SocketAddress(const std::string& host0, const std::string& port0) :
+ host(host0),
+ port(port0),
+ addrInfo(0)
+{
+ ::addrinfo hints;
+ ::memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET; // In order to allow AF_INET6 we'd have to change createTcp() as well
+ hints.ai_socktype = SOCK_STREAM;
+
+ const char* node = 0;
+ if (host.empty()) {
+ hints.ai_flags |= AI_PASSIVE;
+ } else {
+ node = host.c_str();
+ }
+ const char* service = port.empty() ? "0" : port.c_str();
+
+ int n = ::getaddrinfo(node, service, &hints, &addrInfo);
+ if (n != 0)
+ throw Exception(QPID_MSG("Cannot resolve " << host << ": " << ::gai_strerror(n)));
+}
+
+SocketAddress::~SocketAddress()
+{
+ ::freeaddrinfo(addrInfo);
+}
+
+std::string SocketAddress::asString() const
+{
+ return host + ":" + port;
+}
+
+const ::addrinfo& getAddrInfo(const SocketAddress& sa)
+{
+ return *sa.addrInfo;
+}
+
+}}
diff --git a/qpid/cpp/src/qpid/sys/rdma/RdmaClient.cpp b/qpid/cpp/src/qpid/sys/rdma/RdmaClient.cpp
index 9da6c835ce..d39f7885a5 100644
--- a/qpid/cpp/src/qpid/sys/rdma/RdmaClient.cpp
+++ b/qpid/cpp/src/qpid/sys/rdma/RdmaClient.cpp
@@ -40,6 +40,7 @@ using std::rand;
using qpid::sys::Poller;
using qpid::sys::Dispatcher;
+using qpid::sys::SocketAddress;
using qpid::sys::AbsTime;
using qpid::sys::Duration;
using qpid::sys::TIME_SEC;
@@ -154,18 +155,8 @@ using namespace qpid::tests;
int main(int argc, char* argv[]) {
vector<string> args(&argv[0], &argv[argc]);
- ::addrinfo *res;
- ::addrinfo hints = {};
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
+ string host = args[1];
string port = (args.size() < 3) ? "20079" : args[2];
- int n = ::getaddrinfo(args[1].c_str(), port.c_str(), &hints, &res);
- if (n<0) {
- cerr << "Can't find information for: " << args[1] << "\n";
- return 1;
- } else {
- cout << "Connecting to: " << args[1] << ":" << port <<"\n";
- }
if (args.size() > 3)
msgsize = atoi(args[3].c_str());
@@ -181,8 +172,10 @@ int main(int argc, char* argv[]) {
boost::shared_ptr<Poller> p(new Poller());
Dispatcher d(p);
+ SocketAddress sa(host, port);
+ cout << "Connecting to: " << sa.asString() <<"\n";
Rdma::Connector c(
- *res->ai_addr,
+ sa,
Rdma::ConnectionParams(msgsize, Rdma::DEFAULT_WR_ENTRIES),
boost::bind(&connected, p, _1, _2),
boost::bind(&connectionError, p, _1, _2),
diff --git a/qpid/cpp/src/qpid/sys/rdma/RdmaIO.cpp b/qpid/cpp/src/qpid/sys/rdma/RdmaIO.cpp
index 491c1612fd..8d06fccba1 100644
--- a/qpid/cpp/src/qpid/sys/rdma/RdmaIO.cpp
+++ b/qpid/cpp/src/qpid/sys/rdma/RdmaIO.cpp
@@ -26,6 +26,7 @@
#include <iostream>
#include <boost/bind.hpp>
+using qpid::sys::SocketAddress;
using qpid::sys::DispatchHandle;
using qpid::sys::Poller;
@@ -461,7 +462,7 @@ namespace Rdma {
}
Listener::Listener(
- const sockaddr& src,
+ const SocketAddress& src,
const ConnectionParams& cp,
EstablishedCallback ec,
ErrorCallback errc,
@@ -541,7 +542,7 @@ namespace Rdma {
}
Connector::Connector(
- const sockaddr& dst,
+ const SocketAddress& dst,
const ConnectionParams& cp,
ConnectedCallback cc,
ErrorCallback errc,
diff --git a/qpid/cpp/src/qpid/sys/rdma/RdmaIO.h b/qpid/cpp/src/qpid/sys/rdma/RdmaIO.h
index 697d9387ce..12a1b98d24 100644
--- a/qpid/cpp/src/qpid/sys/rdma/RdmaIO.h
+++ b/qpid/cpp/src/qpid/sys/rdma/RdmaIO.h
@@ -27,6 +27,7 @@
#include "qpid/sys/Dispatcher.h"
#include "qpid/sys/DispatchHandle.h"
#include "qpid/sys/Mutex.h"
+#include "qpid/sys/SocketAddress.h"
#include <netinet/in.h>
@@ -173,14 +174,14 @@ namespace Rdma {
class Listener : public ConnectionManager
{
- sockaddr src_addr;
+ qpid::sys::SocketAddress src_addr;
ConnectionParams checkConnectionParams;
ConnectionRequestCallback connectionRequestCallback;
EstablishedCallback establishedCallback;
public:
Listener(
- const sockaddr& src,
+ const qpid::sys::SocketAddress& src,
const ConnectionParams& cp,
EstablishedCallback ec,
ErrorCallback errc,
@@ -198,14 +199,14 @@ namespace Rdma {
class Connector : public ConnectionManager
{
- sockaddr dst_addr;
+ qpid::sys::SocketAddress dst_addr;
ConnectionParams connectionParams;
RejectedCallback rejectedCallback;
ConnectedCallback connectedCallback;
public:
Connector(
- const sockaddr& dst,
+ const qpid::sys::SocketAddress& dst,
const ConnectionParams& cp,
ConnectedCallback cc,
ErrorCallback errc,
diff --git a/qpid/cpp/src/qpid/sys/rdma/RdmaServer.cpp b/qpid/cpp/src/qpid/sys/rdma/RdmaServer.cpp
index 07d6379362..4c11ba23eb 100644
--- a/qpid/cpp/src/qpid/sys/rdma/RdmaServer.cpp
+++ b/qpid/cpp/src/qpid/sys/rdma/RdmaServer.cpp
@@ -35,6 +35,7 @@ using std::string;
using std::cout;
using std::cerr;
+using qpid::sys::SocketAddress;
using qpid::sys::Poller;
using qpid::sys::Dispatcher;
@@ -144,20 +145,15 @@ using namespace qpid::tests;
int main(int argc, char* argv[]) {
vector<string> args(&argv[0], &argv[argc]);
- ::sockaddr_in sin;
-
- int port = (args.size() < 2) ? 20079 : atoi(args[1].c_str());
+ std::string port = (args.size() < 2) ? "20079" : args[1];
cout << "Listening on port: " << port << "\n";
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- sin.sin_addr.s_addr = INADDR_ANY;
-
try {
boost::shared_ptr<Poller> p(new Poller());
Dispatcher d(p);
- Rdma::Listener a((const sockaddr&)(sin),
+ SocketAddress sa("", port);
+ Rdma::Listener a(sa,
Rdma::ConnectionParams(16384, Rdma::DEFAULT_WR_ENTRIES),
boost::bind(connected, p, _1),
connectionError,
diff --git a/qpid/cpp/src/qpid/sys/rdma/rdma_wrap.h b/qpid/cpp/src/qpid/sys/rdma/rdma_wrap.h
index aa2e516e6b..e11497dc02 100644
--- a/qpid/cpp/src/qpid/sys/rdma/rdma_wrap.h
+++ b/qpid/cpp/src/qpid/sys/rdma/rdma_wrap.h
@@ -350,9 +350,9 @@ namespace Rdma {
return ConnectionEvent(e);
}
- void bind(sockaddr& src_addr) const {
+ void bind(qpid::sys::SocketAddress& src_addr) const {
assert(id.get());
- CHECK(::rdma_bind_addr(id.get(), &src_addr));
+ CHECK(::rdma_bind_addr(id.get(), getAddrInfo(src_addr).ai_addr));
}
void listen(int backlog = DEFAULT_BACKLOG) const {
@@ -361,12 +361,11 @@ namespace Rdma {
}
void resolve_addr(
- sockaddr& dst_addr,
- sockaddr* src_addr = 0,
+ qpid::sys::SocketAddress& dst_addr,
int timeout_ms = DEFAULT_TIMEOUT) const
{
assert(id.get());
- CHECK(::rdma_resolve_addr(id.get(), src_addr, &dst_addr, timeout_ms));
+ CHECK(::rdma_resolve_addr(id.get(), 0, getAddrInfo(dst_addr).ai_addr, timeout_ms));
}
void resolve_route(int timeout_ms = DEFAULT_TIMEOUT) const {
diff --git a/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp b/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp
index 8905b87838..475b18600d 100644
--- a/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp
+++ b/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp
@@ -634,7 +634,7 @@ void AsynchIO::readComplete(AsynchReadResult *result) {
if (status == 0 && bytes > 0) {
bool restartRead = true; // May not if receiver doesn't want more
if (readCallback)
- restartRead = readCallback(*this, result->getBuff());
+ readCallback(*this, result->getBuff());
if (restartRead)
startReading();
}
diff --git a/qpid/cpp/src/qpid/xml/XmlExchange.cpp b/qpid/cpp/src/qpid/xml/XmlExchange.cpp
index 8a1ef6149e..472ca28954 100644
--- a/qpid/cpp/src/qpid/xml/XmlExchange.cpp
+++ b/qpid/cpp/src/qpid/xml/XmlExchange.cpp
@@ -206,45 +206,22 @@ void XmlExchange::route(Deliverable& msg, const string& routingKey, const FieldT
PreRoute pr(msg, this);
try {
XmlBinding::vector::ConstPtr p;
- {
+ BindingList b(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >);
+ {
RWlock::ScopedRlock l(lock);
- p = bindingsMap[routingKey].snapshot();
- if (!p) return;
- }
- int count(0);
+ p = bindingsMap[routingKey].snapshot();
+ if (!p.get()) return;
+ }
for (std::vector<XmlBinding::shared_ptr>::const_iterator i = p->begin(); i != p->end(); i++) {
if (matches((*i)->xquery, msg, args, (*i)->parse_message_content)) {
- msg.deliverTo((*i)->queue);
- count++;
- QPID_LOG(trace, "Delivered to queue" );
-
- if ((*i)->mgmtBinding != 0)
- (*i)->mgmtBinding->inc_msgMatched ();
+ b->push_back(*i);
}
- }
- if (!count) {
- QPID_LOG(warning, "XMLExchange " << getName() << ": could not route message with query " << routingKey);
- if (mgmtExchange != 0) {
- mgmtExchange->inc_msgDrops ();
- mgmtExchange->inc_byteDrops (msg.contentSize ());
- }
- } else {
- if (mgmtExchange != 0) {
- mgmtExchange->inc_msgRoutes (count);
- mgmtExchange->inc_byteRoutes (count * msg.contentSize ());
- }
- }
-
- if (mgmtExchange != 0) {
- mgmtExchange->inc_msgReceives ();
- mgmtExchange->inc_byteReceives (msg.contentSize ());
- }
+ }
+ doRoute(msg, b);
} catch (...) {
QPID_LOG(warning, "XMLExchange " << getName() << ": exception routing message with query " << routingKey);
}
-
-
}
diff --git a/qpid/cpp/src/qpidd.cpp b/qpid/cpp/src/qpidd.cpp
index 1839a62205..f2b46942fb 100644
--- a/qpid/cpp/src/qpidd.cpp
+++ b/qpid/cpp/src/qpidd.cpp
@@ -36,25 +36,29 @@ int main(int argc, char* argv[])
{
try
{
- {
- BootstrapOptions bootOptions(argv[0]);
- string defaultPath (bootOptions.module.loadDir);
- // Parse only the common, load, and log options to see which
- // modules need to be loaded. Once the modules are loaded,
- // the command line will be re-parsed with all of the
- // module-supplied options.
+ BootstrapOptions bootOptions(argv[0]);
+ string defaultPath (bootOptions.module.loadDir);
+ // Parse only the common, load, and log options to see which
+ // modules need to be loaded. Once the modules are loaded,
+ // the command line will be re-parsed with all of the
+ // module-supplied options.
+ try {
bootOptions.parse (argc, argv, bootOptions.common.config, true);
qpid::log::Logger::instance().configure(bootOptions.log);
+ } catch (const std::exception& e) {
+ // Couldn't configure logging so write the message direct to stderr.
+ cerr << "Unexpected error: " << e.what() << endl;
+ return 1;
+ }
- for (vector<string>::iterator iter = bootOptions.module.load.begin();
- iter != bootOptions.module.load.end();
- iter++)
- qpid::tryShlib (iter->data(), false);
+ for (vector<string>::iterator iter = bootOptions.module.load.begin();
+ iter != bootOptions.module.load.end();
+ iter++)
+ qpid::tryShlib (iter->data(), false);
- if (!bootOptions.module.noLoad) {
- bool isDefault = defaultPath == bootOptions.module.loadDir;
- qpid::loadModuleDir (bootOptions.module.loadDir, isDefault);
- }
+ if (!bootOptions.module.noLoad) {
+ bool isDefault = defaultPath == bootOptions.module.loadDir;
+ qpid::loadModuleDir (bootOptions.module.loadDir, isDefault);
}
// Parse options
diff --git a/qpid/cpp/src/tests/AsyncCompletion.cpp b/qpid/cpp/src/tests/AsyncCompletion.cpp
index 4492e6b6bc..e32097106f 100644
--- a/qpid/cpp/src/tests/AsyncCompletion.cpp
+++ b/qpid/cpp/src/tests/AsyncCompletion.cpp
@@ -70,9 +70,11 @@ class AsyncCompletionMessageStore : public NullMessageStore {
QPID_AUTO_TEST_SUITE(AsyncCompletionTestSuite)
QPID_AUTO_TEST_CASE(testWaitTillComplete) {
- AsyncCompletionMessageStore* store = new AsyncCompletionMessageStore;
SessionFixture fix;
- fix.broker->setStore(store); // Broker will delete store.
+ AsyncCompletionMessageStore* store = new AsyncCompletionMessageStore;
+ boost::shared_ptr<qpid::broker::MessageStore> p;
+ p.reset(store);
+ fix.broker->setStore(p);
AsyncSession s = fix.session;
static const int count = 3;
diff --git a/qpid/cpp/src/tests/ClusterFixture.h b/qpid/cpp/src/tests/ClusterFixture.h
index 5952cc1736..1eee32b9a4 100644
--- a/qpid/cpp/src/tests/ClusterFixture.h
+++ b/qpid/cpp/src/tests/ClusterFixture.h
@@ -75,10 +75,10 @@ class ClusterFixture : public vector<uint16_t> {
/** @param localIndex can be -1 meaning don't automatically start a local broker.
* A local broker can be started with addLocal().
*/
- ClusterFixture(size_t n, const Args& args, int localIndex=0);
+ ClusterFixture(size_t n, const Args& args, int localIndex=-1);
/**@param updateArgs function is passed the index of the cluster member and can update the arguments. */
- ClusterFixture(size_t n, boost::function<void (Args&, size_t)> updateArgs, int localIndex);
+ ClusterFixture(size_t n, boost::function<void (Args&, size_t)> updateArgs, int localIndex=-1);
void add(size_t n) { for (size_t i=0; i < n; ++i) add(); }
void add(); // Add a broker.
diff --git a/qpid/cpp/src/tests/ExchangeTest.cpp b/qpid/cpp/src/tests/ExchangeTest.cpp
index 44835c6184..88a1cd99c2 100644
--- a/qpid/cpp/src/tests/ExchangeTest.cpp
+++ b/qpid/cpp/src/tests/ExchangeTest.cpp
@@ -60,7 +60,7 @@ QPID_AUTO_TEST_CASE(testMe)
queue.reset();
queue2.reset();
- intrusive_ptr<Message> msgPtr(MessageUtils::createMessage("exchange", "key", "id"));
+ intrusive_ptr<Message> msgPtr(MessageUtils::createMessage("exchange", "key", false, "id"));
DeliverableMessage msg(msgPtr);
topic.route(msg, "abc", 0);
direct.route(msg, "abc", 0);
diff --git a/qpid/cpp/src/tests/Makefile.am b/qpid/cpp/src/tests/Makefile.am
index a15ba3578c..15133505a3 100644
--- a/qpid/cpp/src/tests/Makefile.am
+++ b/qpid/cpp/src/tests/Makefile.am
@@ -22,6 +22,7 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src
PUBLIC_INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include # Use public API only
abs_builddir=@abs_builddir@
+abs_srcdir=@abs_srcdir@
extra_libs =
lib_client = $(abs_builddir)/../libqpidclient.la
lib_common = $(abs_builddir)/../libqpidcommon.la
@@ -275,7 +276,6 @@ qpid_stream_INCLUDES=$(PUBLIC_INCLUDES)
qpid_stream_SOURCES=qpid_stream.cpp
qpid_stream_LDADD=$(lib_client)
-
TESTS_ENVIRONMENT = \
VALGRIND=$(VALGRIND) \
srcdir=$(srcdir) \
@@ -311,7 +311,7 @@ EXTRA_DIST += \
TxMocks.h \
replication_test \
run_perftest \
- ring_queue_test \
+ ring_queue_test \
run_ring_queue_test
check_LTLIBRARIES += libdlclose_noop.la
@@ -327,25 +327,47 @@ LONG_TESTS+=start_broker fanout_perftest shared_perftest multiq_perftest topic_p
run_failover_soak reliable_replication_test \
federated_cluster_test_with_node_failure
-EXTRA_DIST+=fanout_perftest shared_perftest multiq_perftest topic_perftest run_failover_soak reliable_replication_test \
- federated_cluster_test_with_node_failure \
- tests.sln \
- client_test.vcproj \
- consume.vcproj \
- echotest.vcproj \
- header_test.vcproj \
- latencytest.vcproj \
- perftest.vcproj \
- publish.vcproj \
- receiver.vcproj \
- sender.vcproj \
- shlibtest.vcproj \
- topic_listener.vcproj \
- topic_publisher.vcproj \
- txjob.vcproj \
- txshift.vcproj \
- txtest.vcproj \
- unit_test.vcproj
+EXTRA_DIST+= \
+ python_env.sh \
+ fanout_perftest \
+ shared_perftest \
+ multiq_perftest \
+ topic_perftest \
+ run_failover_soak \
+ reliable_replication_test \
+ federated_cluster_test_with_node_failure \
+ tests.sln \
+ client_test.vcproj \
+ consume.vcproj \
+ echotest.vcproj \
+ header_test.vcproj \
+ latencytest.vcproj \
+ perftest.vcproj \
+ publish.vcproj \
+ receiver.vcproj \
+ sender.vcproj \
+ shlibtest.vcproj \
+ topic_listener.vcproj \
+ topic_publisher.vcproj \
+ txjob.vcproj \
+ txshift.vcproj \
+ txtest.vcproj \
+ unit_test.vcproj
check-long:
$(MAKE) check TESTS="$(LONG_TESTS)" VALGRIND=
+
+check: python_prep
+
+PYTHON_SRC_DIR=$(abs_srcdir)/../../../python
+PYTHON_BLD_DIR=$(abs_builddir)/python
+AMQP_SPEC_DIR=$(abs_srcdir)/../../../specs
+
+# Generate python client as part of the all-am target so it gets built before tests.
+all-am: python_prep
+
+python_prep:
+ if test -d $(PYTHON_SRC_DIR) -a -d $(AMQP_SPEC_DIR); \
+ then $(MAKE) -C $(PYTHON_SRC_DIR) install PREFIX=$(PYTHON_BLD_DIR) PYTHON_LIB=$(PYTHON_BLD_DIR) EXEC_PREFIX=$(PYTHON_BLD_DIR)/commands AMQP_SPEC_DIR=$(AMQP_SPEC_DIR); \
+ else echo "WARNING: python client not built, missing one of $(PYTHON_SRC_DIR) $(AMQP_SPEC_DIR)"; fi
+
diff --git a/qpid/cpp/src/tests/MessageUtils.h b/qpid/cpp/src/tests/MessageUtils.h
index dae74cce7d..a1b140d484 100644
--- a/qpid/cpp/src/tests/MessageUtils.h
+++ b/qpid/cpp/src/tests/MessageUtils.h
@@ -34,7 +34,8 @@ namespace tests {
struct MessageUtils
{
static boost::intrusive_ptr<Message> createMessage(const string& exchange="", const string& routingKey="",
- const Uuid& messageId=Uuid(true), uint64_t contentSize = 0)
+ const bool durable = false, const Uuid& messageId=Uuid(true),
+ uint64_t contentSize = 0)
{
boost::intrusive_ptr<broker::Message> msg(new broker::Message());
@@ -47,6 +48,8 @@ struct MessageUtils
props->setContentLength(contentSize);
props->setMessageId(messageId);
msg->getFrames().getHeaders()->get<DeliveryProperties>(true)->setRoutingKey(routingKey);
+ if (durable)
+ msg->getFrames().getHeaders()->get<DeliveryProperties>(true)->setDeliveryMode(2);
return msg;
}
diff --git a/qpid/cpp/src/tests/MessagingSessionTests.cpp b/qpid/cpp/src/tests/MessagingSessionTests.cpp
index f5a5420d3a..206f5ba691 100644
--- a/qpid/cpp/src/tests/MessagingSessionTests.cpp
+++ b/qpid/cpp/src/tests/MessagingSessionTests.cpp
@@ -22,6 +22,10 @@
#include "test_tools.h"
#include "BrokerFixture.h"
#include "qpid/messaging/Connection.h"
+#include "qpid/messaging/ListContent.h"
+#include "qpid/messaging/ListView.h"
+#include "qpid/messaging/MapContent.h"
+#include "qpid/messaging/MapView.h"
#include "qpid/messaging/Message.h"
#include "qpid/messaging/MessageListener.h"
#include "qpid/messaging/Receiver.h"
@@ -160,7 +164,7 @@ struct MessageDataCollector : MessageListener
std::vector<std::string> messageData;
void received(Message& message) {
- messageData.push_back(message.getBytes());
+ messageData.push_back(message.getContent());
}
};
@@ -169,7 +173,7 @@ std::vector<std::string> fetch(Receiver& receiver, int count, qpid::sys::Duratio
std::vector<std::string> data;
Message message;
for (int i = 0; i < count && receiver.fetch(message, timeout); i++) {
- data.push_back(message.getBytes());
+ data.push_back(message.getContent());
}
return data;
}
@@ -183,7 +187,7 @@ QPID_AUTO_TEST_CASE(testSimpleSendReceive)
Receiver receiver = fix.session.createReceiver(fix.queue);
Message in = receiver.fetch(5 * qpid::sys::TIME_SEC);
fix.session.acknowledge();
- BOOST_CHECK_EQUAL(in.getBytes(), out.getBytes());
+ BOOST_CHECK_EQUAL(in.getContent(), out.getContent());
}
QPID_AUTO_TEST_CASE(testSendReceiveHeaders)
@@ -199,7 +203,7 @@ QPID_AUTO_TEST_CASE(testSendReceiveHeaders)
Message in;
for (uint i = 0; i < 10; ++i) {
BOOST_CHECK(receiver.fetch(in, 5 * qpid::sys::TIME_SEC));
- BOOST_CHECK_EQUAL(in.getBytes(), out.getBytes());
+ BOOST_CHECK_EQUAL(in.getContent(), out.getContent());
BOOST_CHECK_EQUAL(in.getHeaders()["a"].asUint32(), i);
fix.session.acknowledge();
}
@@ -229,22 +233,22 @@ QPID_AUTO_TEST_CASE(testSimpleTopic)
Receiver sub1 = fix.session.createReceiver(fix.topic);
sub1.setCapacity(10u);
sub1.start();
- msg.setBytes("two");
+ msg.setContent("two");
sender.send(msg);
Receiver sub2 = fix.session.createReceiver(fix.topic);
sub2.setCapacity(10u);
sub2.start();
- msg.setBytes("three");
+ msg.setContent("three");
sender.send(msg);
Receiver sub3 = fix.session.createReceiver(fix.topic);
sub3.setCapacity(10u);
sub3.start();
- msg.setBytes("four");
+ msg.setContent("four");
sender.send(msg);
BOOST_CHECK_EQUAL(fetch(sub2, 2), boost::assign::list_of<std::string>("three")("four"));
sub2.cancel();
- msg.setBytes("five");
+ msg.setContent("five");
sender.send(msg);
BOOST_CHECK_EQUAL(fetch(sub1, 4), boost::assign::list_of<std::string>("two")("three")("four")("five"));
BOOST_CHECK_EQUAL(fetch(sub3, 2), boost::assign::list_of<std::string>("four")("five"));
@@ -274,7 +278,7 @@ QPID_AUTO_TEST_CASE(testSessionFetch)
for (uint i = 0; i < fix.queues.size(); i++) {
Message msg;
BOOST_CHECK(fix.session.fetch(msg, qpid::sys::TIME_SEC));
- BOOST_CHECK_EQUAL(msg.getBytes(), (boost::format("Message_%1%") % (i+1)).str());
+ BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1)).str());
}
}
@@ -307,13 +311,16 @@ QPID_AUTO_TEST_CASE(testMapMessage)
QueueFixture fix;
Sender sender = fix.session.createSender(fix.queue);
Message out;
- out.getContent().asMap()["abc"] = "def";
- out.getContent().asMap()["pi"] = 3.14f;
+ MapContent content(out);
+ content["abc"] = "def";
+ content["pi"] = 3.14f;
+ content.encode();
sender.send(out);
Receiver receiver = fix.session.createReceiver(fix.queue);
Message in = receiver.fetch(5 * qpid::sys::TIME_SEC);
- BOOST_CHECK_EQUAL(in.getContent().asMap()["abc"].asString(), "def");
- BOOST_CHECK_EQUAL(in.getContent().asMap()["pi"].asFloat(), 3.14f);
+ MapView view(in);
+ BOOST_CHECK_EQUAL(view["abc"].asString(), "def");
+ BOOST_CHECK_EQUAL(view["pi"].asFloat(), 3.14f);
fix.session.acknowledge();
}
@@ -322,23 +329,31 @@ QPID_AUTO_TEST_CASE(testListMessage)
QueueFixture fix;
Sender sender = fix.session.createSender(fix.queue);
Message out;
- out.getContent() = Variant::List();
- out.getContent() << "abc";
- out.getContent() << 1234;
- out.getContent() << "def";
- out.getContent() << 56.789;
+ ListContent content(out);
+ content.push_back(Variant("abc"));
+ content.push_back(Variant(1234));
+ content.push_back(Variant("def"));
+ content.push_back(Variant(56.789));
+ content.encode();
sender.send(out);
Receiver receiver = fix.session.createReceiver(fix.queue);
Message in = receiver.fetch(5 * qpid::sys::TIME_SEC);
- Variant::List& list = in.getContent().asList();
- BOOST_CHECK_EQUAL(list.size(), out.getContent().asList().size());
- BOOST_CHECK_EQUAL(list.front().asString(), "abc");
- list.pop_front();
- BOOST_CHECK_EQUAL(list.front().asInt64(), 1234);
- list.pop_front();
- BOOST_CHECK_EQUAL(list.front().asString(), "def");
- list.pop_front();
- BOOST_CHECK_EQUAL(list.front().asDouble(), 56.789);
+ ListView view(in);
+ BOOST_CHECK_EQUAL(view.size(), content.size());
+ BOOST_CHECK_EQUAL(view.front().asString(), "abc");
+ BOOST_CHECK_EQUAL(view.back().asDouble(), 56.789);
+
+ ListView::const_iterator i = view.begin();
+ BOOST_CHECK(i != view.end());
+ BOOST_CHECK_EQUAL(i->asString(), "abc");
+ BOOST_CHECK(++i != view.end());
+ BOOST_CHECK_EQUAL(i->asInt64(), 1234);
+ BOOST_CHECK(++i != view.end());
+ BOOST_CHECK_EQUAL(i->asString(), "def");
+ BOOST_CHECK(++i != view.end());
+ BOOST_CHECK_EQUAL(i->asDouble(), 56.789);
+ BOOST_CHECK(++i == view.end());
+
fix.session.acknowledge();
}
@@ -352,10 +367,10 @@ QPID_AUTO_TEST_CASE(testReject)
sender.send(m2);
Receiver receiver = fix.session.createReceiver(fix.queue);
Message in = receiver.fetch(5 * qpid::sys::TIME_SEC);
- BOOST_CHECK_EQUAL(in.getBytes(), m1.getBytes());
+ BOOST_CHECK_EQUAL(in.getContent(), m1.getContent());
fix.session.reject(in);
in = receiver.fetch(5 * qpid::sys::TIME_SEC);
- BOOST_CHECK_EQUAL(in.getBytes(), m2.getBytes());
+ BOOST_CHECK_EQUAL(in.getContent(), m2.getContent());
fix.session.acknowledge();
}
@@ -384,15 +399,15 @@ QPID_AUTO_TEST_CASE(testAvailable)
for (uint i = 0; i < 5; ++i) {
BOOST_CHECK_EQUAL(fix.session.available(), 15u - 2*i);
BOOST_CHECK_EQUAL(r1.available(), 10u - i);
- BOOST_CHECK_EQUAL(r1.fetch().getBytes(), (boost::format("A_%1%") % (i+1)).str());
+ BOOST_CHECK_EQUAL(r1.fetch().getContent(), (boost::format("A_%1%") % (i+1)).str());
BOOST_CHECK_EQUAL(r2.available(), 5u - i);
- BOOST_CHECK_EQUAL(r2.fetch().getBytes(), (boost::format("B_%1%") % (i+1)).str());
+ BOOST_CHECK_EQUAL(r2.fetch().getContent(), (boost::format("B_%1%") % (i+1)).str());
fix.session.acknowledge();
}
for (uint i = 5; i < 10; ++i) {
BOOST_CHECK_EQUAL(fix.session.available(), 10u - i);
BOOST_CHECK_EQUAL(r1.available(), 10u - i);
- BOOST_CHECK_EQUAL(r1.fetch().getBytes(), (boost::format("A_%1%") % (i+1)).str());
+ BOOST_CHECK_EQUAL(r1.fetch().getContent(), (boost::format("A_%1%") % (i+1)).str());
}
}
@@ -405,7 +420,7 @@ QPID_AUTO_TEST_CASE(testPendingAck)
}
Receiver receiver = fix.session.createReceiver(fix.queue);
for (uint i = 0; i < 10; ++i) {
- BOOST_CHECK_EQUAL(receiver.fetch().getBytes(), (boost::format("Message_%1%") % (i+1)).str());
+ BOOST_CHECK_EQUAL(receiver.fetch().getContent(), (boost::format("Message_%1%") % (i+1)).str());
}
BOOST_CHECK_EQUAL(fix.session.pendingAck(), 0u);
fix.session.acknowledge();
@@ -431,7 +446,7 @@ QPID_AUTO_TEST_CASE(testPendingSend)
Receiver receiver = fix.session.createReceiver(fix.queue);
for (uint i = 0; i < 10; ++i) {
- BOOST_CHECK_EQUAL(receiver.fetch().getBytes(), (boost::format("Message_%1%") % (i+1)).str());
+ BOOST_CHECK_EQUAL(receiver.fetch().getContent(), (boost::format("Message_%1%") % (i+1)).str());
}
fix.session.acknowledge();
}
diff --git a/qpid/cpp/src/tests/PartialFailure.cpp b/qpid/cpp/src/tests/PartialFailure.cpp
index 8d9970f909..5de8ecb189 100644
--- a/qpid/cpp/src/tests/PartialFailure.cpp
+++ b/qpid/cpp/src/tests/PartialFailure.cpp
@@ -105,7 +105,6 @@ QPID_AUTO_TEST_CASE(testCoincidentErrors) {
}
}
-#if 0 // FIXME aconway 2009-07-30:
// Verify normal cluster-wide errors.
QPID_AUTO_TEST_CASE(testNormalErrors) {
// FIXME aconway 2009-04-10: Would like to put a scope just around
@@ -120,7 +119,7 @@ QPID_AUTO_TEST_CASE(testNormalErrors) {
{
ScopedSuppressLogging allQuiet;
- queueAndsub(c0);
+ queueAndSub(c0);
c0.session.messageTransfer(content=Message("x", "c0"));
BOOST_CHECK_EQUAL(c0.lq.get(TIMEOUT).getData(), "x");
@@ -258,7 +257,7 @@ QPID_AUTO_TEST_CASE(testPartialFailureMemberLeaves) {
}
}
#endif
-#endif // FIXME aconway 2009-07-30:
+
QPID_AUTO_TEST_SUITE_END()
}} // namespace qpid::tests
diff --git a/qpid/cpp/src/tests/QueuePolicyTest.cpp b/qpid/cpp/src/tests/QueuePolicyTest.cpp
index f40d30b588..875976db85 100644
--- a/qpid/cpp/src/tests/QueuePolicyTest.cpp
+++ b/qpid/cpp/src/tests/QueuePolicyTest.cpp
@@ -48,56 +48,56 @@ QueuedMessage createMessage(uint32_t size)
QPID_AUTO_TEST_CASE(testCount)
{
- std::auto_ptr<QueuePolicy> policy(QueuePolicy::createQueuePolicy(5, 0));
+ std::auto_ptr<QueuePolicy> policy(QueuePolicy::createQueuePolicy("test", 5, 0));
BOOST_CHECK_EQUAL((uint64_t) 0, policy->getMaxSize());
BOOST_CHECK_EQUAL((uint32_t) 5, policy->getMaxCount());
QueuedMessage msg = createMessage(10);
for (size_t i = 0; i < 5; i++) {
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
}
try {
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
BOOST_FAIL("Policy did not fail on enqueuing sixth message");
} catch (const ResourceLimitExceededException&) {}
policy->dequeued(msg);
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
try {
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
BOOST_FAIL("Policy did not fail on enqueuing sixth message (after dequeue)");
} catch (const ResourceLimitExceededException&) {}
}
QPID_AUTO_TEST_CASE(testSize)
{
- std::auto_ptr<QueuePolicy> policy(QueuePolicy::createQueuePolicy(0, 50));
+ std::auto_ptr<QueuePolicy> policy(QueuePolicy::createQueuePolicy("test", 0, 50));
QueuedMessage msg = createMessage(10);
for (size_t i = 0; i < 5; i++) {
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
}
try {
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
BOOST_FAIL("Policy did not fail on aggregate size exceeding 50. " << *policy);
} catch (const ResourceLimitExceededException&) {}
policy->dequeued(msg);
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
try {
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
BOOST_FAIL("Policy did not fail on aggregate size exceeding 50 (after dequeue). " << *policy);
} catch (const ResourceLimitExceededException&) {}
}
QPID_AUTO_TEST_CASE(testBoth)
{
- std::auto_ptr<QueuePolicy> policy(QueuePolicy::createQueuePolicy(5, 50));
+ std::auto_ptr<QueuePolicy> policy(QueuePolicy::createQueuePolicy("test", 5, 50));
try {
QueuedMessage msg = createMessage(51);
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
BOOST_FAIL("Policy did not fail on single message exceeding 50. " << *policy);
} catch (const ResourceLimitExceededException&) {}
@@ -108,17 +108,17 @@ QPID_AUTO_TEST_CASE(testBoth)
messages.push_back(createMessage(2));
messages.push_back(createMessage(7));
for (size_t i = 0; i < messages.size(); i++) {
- policy->tryEnqueue(messages[i]);
+ policy->tryEnqueue(messages[i].payload);
}
//size = 45 at this point, count = 5
try {
QueuedMessage msg = createMessage(5);
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
BOOST_FAIL("Policy did not fail on count exceeding 6. " << *policy);
} catch (const ResourceLimitExceededException&) {}
try {
QueuedMessage msg = createMessage(10);
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
BOOST_FAIL("Policy did not fail on aggregate size exceeding 50. " << *policy);
} catch (const ResourceLimitExceededException&) {}
@@ -126,7 +126,7 @@ QPID_AUTO_TEST_CASE(testBoth)
policy->dequeued(messages[0]);
try {
QueuedMessage msg = createMessage(20);
- policy->tryEnqueue(msg);
+ policy->tryEnqueue(msg.payload);
} catch (const ResourceLimitExceededException&) {
BOOST_FAIL("Policy failed incorrectly after dequeue. " << *policy);
}
@@ -135,10 +135,10 @@ QPID_AUTO_TEST_CASE(testBoth)
QPID_AUTO_TEST_CASE(testSettings)
{
//test reading and writing the policy from/to field table
- std::auto_ptr<QueuePolicy> a(QueuePolicy::createQueuePolicy(101, 303));
+ std::auto_ptr<QueuePolicy> a(QueuePolicy::createQueuePolicy("test", 101, 303));
FieldTable settings;
a->update(settings);
- std::auto_ptr<QueuePolicy> b(QueuePolicy::createQueuePolicy(settings));
+ std::auto_ptr<QueuePolicy> b(QueuePolicy::createQueuePolicy("test", settings));
BOOST_CHECK_EQUAL(a->getMaxCount(), b->getMaxCount());
BOOST_CHECK_EQUAL(a->getMaxSize(), b->getMaxSize());
}
@@ -146,7 +146,7 @@ QPID_AUTO_TEST_CASE(testSettings)
QPID_AUTO_TEST_CASE(testRingPolicy)
{
FieldTable args;
- std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy(5, 0, QueuePolicy::RING);
+ std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::RING);
policy->update(args);
ProxySessionFixture f;
@@ -175,7 +175,7 @@ QPID_AUTO_TEST_CASE(testRingPolicy)
QPID_AUTO_TEST_CASE(testStrictRingPolicy)
{
FieldTable args;
- std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy(5, 0, QueuePolicy::RING_STRICT);
+ std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::RING_STRICT);
policy->update(args);
ProxySessionFixture f;
@@ -201,7 +201,7 @@ QPID_AUTO_TEST_CASE(testStrictRingPolicy)
QPID_AUTO_TEST_CASE(testPolicyWithDtx)
{
FieldTable args;
- std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy(5, 0, QueuePolicy::REJECT);
+ std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::REJECT);
policy->update(args);
ProxySessionFixture f;
@@ -282,6 +282,22 @@ QPID_AUTO_TEST_CASE(testFlowToDiskWithNoStore)
} catch (const ResourceLimitExceededException&) {}
}
+QPID_AUTO_TEST_CASE(testPolicyFailureOnCommit)
+{
+ FieldTable args;
+ std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::REJECT);
+ policy->update(args);
+
+ ProxySessionFixture f;
+ std::string q("q");
+ f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
+ f.session.txSelect();
+ for (int i = 0; i < 10; i++) {
+ f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q));
+ }
+ ScopedSuppressLogging sl; // Suppress messages for expected errors.
+ BOOST_CHECK_THROW(f.session.txCommit(), InternalErrorException);
+}
QPID_AUTO_TEST_SUITE_END()
diff --git a/qpid/cpp/src/tests/QueueTest.cpp b/qpid/cpp/src/tests/QueueTest.cpp
index 841a19f7c1..3cfaa763ca 100644
--- a/qpid/cpp/src/tests/QueueTest.cpp
+++ b/qpid/cpp/src/tests/QueueTest.cpp
@@ -18,10 +18,13 @@
* under the License.
*
*/
+#include "MessageUtils.h"
#include "unit_test.h"
#include "test_tools.h"
#include "qpid/Exception.h"
#include "qpid/broker/Broker.h"
+#include "qpid/broker/DeliverableMessage.h"
+#include "qpid/broker/FanOutExchange.h"
#include "qpid/broker/Queue.h"
#include "qpid/broker/Deliverable.h"
#include "qpid/broker/ExchangeRegistry.h"
@@ -30,12 +33,16 @@
#include "qpid/broker/ExpiryPolicy.h"
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/client/QueueOptions.h"
+#include "qpid/framing/AMQFrame.h"
+#include "qpid/framing/MessageTransferBody.h"
+#include "qpid/framing/reply_exceptions.h"
#include <iostream>
#include "boost/format.hpp"
using boost::intrusive_ptr;
using namespace qpid;
using namespace qpid::broker;
+using namespace qpid::client;
using namespace qpid::framing;
using namespace qpid::sys;
@@ -61,13 +68,14 @@ public:
class FailOnDeliver : public Deliverable
{
- Message msg;
+ boost::intrusive_ptr<Message> msg;
public:
+ FailOnDeliver() : msg(MessageUtils::createMessage()) {}
void deliverTo(const boost::shared_ptr<Queue>& queue)
{
throw Exception(QPID_MSG("Invalid delivery to " << queue->getName()));
}
- Message& getMessage() { return msg; }
+ Message& getMessage() { return *(msg.get()); }
};
intrusive_ptr<Message> create_message(std::string exchange, std::string routingKey) {
@@ -210,8 +218,7 @@ QPID_AUTO_TEST_CASE(testDequeue){
}
-QPID_AUTO_TEST_CASE(testBound)
-{
+QPID_AUTO_TEST_CASE(testBound){
//test the recording of bindings, and use of those to allow a queue to be unbound
string key("my-key");
FieldTable args;
@@ -245,7 +252,6 @@ QPID_AUTO_TEST_CASE(testBound)
}
QPID_AUTO_TEST_CASE(testPersistLastNodeStanding){
-
client::QueueOptions args;
args.setPersistLastNode();
@@ -273,14 +279,35 @@ QPID_AUTO_TEST_CASE(testPersistLastNodeStanding){
}
-class TestMessageStoreOC : public NullMessageStore
+const std::string nullxid = "";
+
+class SimpleDummyCtxt : public TransactionContext {};
+
+class DummyCtxt : public TPCTransactionContext
+{
+ const std::string xid;
+ public:
+ DummyCtxt(const std::string& _xid) : xid(_xid) {}
+ static std::string getXid(TransactionContext& ctxt)
+ {
+ DummyCtxt* c(dynamic_cast<DummyCtxt*>(&ctxt));
+ return c ? c->xid : nullxid;
+ }
+};
+
+class TestMessageStoreOC : public MessageStore
{
+ std::set<std::string> prepared;
+ uint64_t nextPersistenceId;
public:
uint enqCnt;
uint deqCnt;
bool error;
+ TestMessageStoreOC() : MessageStore(),nextPersistenceId(1),enqCnt(0),deqCnt(0),error(false) {}
+ ~TestMessageStoreOC(){}
+
virtual void dequeue(TransactionContext*,
const boost::intrusive_ptr<PersistableMessage>& /*msg*/,
const PersistableQueue& /*queue*/)
@@ -290,11 +317,12 @@ class TestMessageStoreOC : public NullMessageStore
}
virtual void enqueue(TransactionContext*,
- const boost::intrusive_ptr<PersistableMessage>& /*msg*/,
+ const boost::intrusive_ptr<PersistableMessage>& msg,
const PersistableQueue& /* queue */)
{
if (error) throw Exception("Enqueue error test");
enqCnt++;
+ msg->enqueueComplete();
}
void createError()
@@ -302,8 +330,32 @@ class TestMessageStoreOC : public NullMessageStore
error=true;
}
- TestMessageStoreOC() : NullMessageStore(),enqCnt(0),deqCnt(0),error(false) {}
- ~TestMessageStoreOC(){}
+ bool init(const Options*) { return true; }
+ void truncateInit(const bool) {}
+ void create(PersistableQueue& queue, const framing::FieldTable&) { queue.setPersistenceId(nextPersistenceId++); }
+ void destroy(PersistableQueue&) {}
+ void create(const PersistableExchange& exchange, const framing::FieldTable&) { exchange.setPersistenceId(nextPersistenceId++); }
+ void destroy(const PersistableExchange&) {}
+ void bind(const PersistableExchange&, const PersistableQueue&, const std::string&, const framing::FieldTable&) {}
+ void unbind(const PersistableExchange&, const PersistableQueue&, const std::string&, const framing::FieldTable&) {}
+ void create(const PersistableConfig& config) { config.setPersistenceId(nextPersistenceId++); }
+ void destroy(const PersistableConfig&) {}
+ void stage(const boost::intrusive_ptr<PersistableMessage>&) {}
+ void destroy(PersistableMessage&) {}
+ void appendContent(const boost::intrusive_ptr<const PersistableMessage>&, const std::string&) {}
+ void loadContent(const qpid::broker::PersistableQueue&, const boost::intrusive_ptr<const PersistableMessage>&,
+ std::string&, uint64_t, uint32_t) { throw qpid::framing::InternalErrorException("Can't load content; persistence not enabled"); }
+ void flush(const qpid::broker::PersistableQueue&) {}
+ uint32_t outstandingQueueAIO(const PersistableQueue&) { return 0; }
+
+ std::auto_ptr<TransactionContext> begin() { return std::auto_ptr<TransactionContext>(new SimpleDummyCtxt()); }
+ std::auto_ptr<TPCTransactionContext> begin(const std::string& xid) { return std::auto_ptr<TPCTransactionContext>(new DummyCtxt(xid)); }
+ void prepare(TPCTransactionContext& ctxt) { prepared.insert(DummyCtxt::getXid(ctxt)); }
+ void commit(TransactionContext& ctxt) { prepared.erase(DummyCtxt::getXid(ctxt)); }
+ void abort(TransactionContext& ctxt) { prepared.erase(DummyCtxt::getXid(ctxt)); }
+ void collectPreparedXids(std::set<std::string>& out) { out.insert(prepared.begin(), prepared.end()); }
+
+ void recover(RecoveryManager&) {}
};
@@ -703,7 +755,7 @@ not requeued to the store.
QPID_AUTO_TEST_CASE(testLastNodeJournalError){
/*
-simulate store excption going into last node standing
+simulate store exception going into last node standing
*/
TestMessageStoreOC testStore;
@@ -727,16 +779,271 @@ simulate store excption going into last node standing
}
-intrusive_ptr<Message> mkMsg(std::string exchange, std::string routingKey) {
- intrusive_ptr<Message> msg(new Message());
- AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange, 0, 0)));
- AMQFrame header((AMQHeaderBody()));
- msg->getFrames().append(method);
- msg->getFrames().append(header);
- msg->getFrames().getHeaders()->get<DeliveryProperties>(true)->setRoutingKey(routingKey);
+intrusive_ptr<Message> mkMsg(MessageStore& store, std::string content = "", bool durable = false)
+{
+ intrusive_ptr<Message> msg = MessageUtils::createMessage("", "", durable);
+ if (content.size()) MessageUtils::addContent(msg, content);
+ msg->setStore(&store);
return msg;
}
+QPID_AUTO_TEST_CASE(testFlowToDiskBlocking){
+
+ TestMessageStoreOC testStore;
+ client::QueueOptions args0; // No size policy
+ client::QueueOptions args1;
+ args1.setSizePolicy(FLOW_TO_DISK, 0, 1);
+ client::QueueOptions args2;
+ args2.setSizePolicy(FLOW_TO_DISK, 0, 2);
+
+ // --- Fanout exchange bound to single transient queue -------------------------------------------------------------
+
+ FanOutExchange sbtFanout1("sbtFanout1", false, args0); // single binding to transient queue
+ Queue::shared_ptr tq1(new Queue("tq1", true)); // transient w/ limit
+ tq1->configure(args1);
+ sbtFanout1.bind(tq1, "", 0);
+
+ intrusive_ptr<Message> msg01 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
+ DeliverableMessage dmsg01(msg01);
+ sbtFanout1.route(dmsg01, "", 0); // Brings queue 1 to capacity limit
+ msg01->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg01->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(1u, tq1->getMessageCount());
+
+ intrusive_ptr<Message> msg02 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
+ DeliverableMessage dmsg02(msg02);
+ BOOST_CHECK_THROW(sbtFanout1.route(dmsg02, "", 0), ResourceLimitExceededException);
+ msg02->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg02->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(1u, tq1->getMessageCount());
+
+ intrusive_ptr<Message> msg03 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content
+ DeliverableMessage dmsg03(msg03);
+ BOOST_CHECK_THROW(sbtFanout1.route(dmsg03, "", 0), ResourceLimitExceededException);
+ msg03->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg03->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(1u, tq1->getMessageCount());
+
+ intrusive_ptr<Message> msg04 = mkMsg(testStore); // transient no content
+ DeliverableMessage dmsg04(msg04);
+ BOOST_CHECK_THROW(sbtFanout1.route(dmsg04, "", 0), ResourceLimitExceededException);
+ msg04->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg04->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(1u, tq1->getMessageCount());
+
+ intrusive_ptr<Message> msg05 = mkMsg(testStore, "", true); // durable no content
+ DeliverableMessage dmsg05(msg05);
+ BOOST_CHECK_THROW(sbtFanout1.route(dmsg05, "", 0), ResourceLimitExceededException);
+ msg05->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg05->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(1u, tq1->getMessageCount());
+
+ // --- Fanout exchange bound to single durable queue ---------------------------------------------------------------
+
+ FanOutExchange sbdFanout2("sbdFanout2", false, args0); // single binding to durable queue
+ Queue::shared_ptr dq2(new Queue("dq2", true, &testStore)); // durable w/ limit
+ dq2->configure(args1);
+ sbdFanout2.bind(dq2, "", 0);
+
+ intrusive_ptr<Message> msg06 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
+ DeliverableMessage dmsg06(msg06);
+ sbdFanout2.route(dmsg06, "", 0); // Brings queue 2 to capacity limit
+ msg06->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg06->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(1u, dq2->getMessageCount());
+
+ intrusive_ptr<Message> msg07 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
+ DeliverableMessage dmsg07(msg07);
+ sbdFanout2.route(dmsg07, "", 0);
+ msg07->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg07->isContentReleased(), true);
+ BOOST_CHECK_EQUAL(2u, dq2->getMessageCount());
+
+ intrusive_ptr<Message> msg08 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content
+ DeliverableMessage dmsg08(msg08);
+ sbdFanout2.route(dmsg08, "", 0);
+ msg08->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg08->isContentReleased(), true);
+ BOOST_CHECK_EQUAL(3u, dq2->getMessageCount());
+
+ intrusive_ptr<Message> msg09 = mkMsg(testStore); // transient no content
+ DeliverableMessage dmsg09(msg09);
+ sbdFanout2.route(dmsg09, "", 0);
+ msg09->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg09->isContentReleased(), true);
+ BOOST_CHECK_EQUAL(4u, dq2->getMessageCount());
+
+ intrusive_ptr<Message> msg10 = mkMsg(testStore, "", true); // durable no content
+ DeliverableMessage dmsg10(msg10);
+ sbdFanout2.route(dmsg10, "", 0);
+ msg10->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg10->isContentReleased(), true);
+ BOOST_CHECK_EQUAL(5u, dq2->getMessageCount());
+
+ // --- Fanout exchange bound to multiple durable queues ------------------------------------------------------------
+
+ FanOutExchange mbdFanout3("mbdFanout3", false, args0); // multiple bindings to durable queues
+ Queue::shared_ptr dq3(new Queue("dq3", true, &testStore)); // durable w/ limit 2
+ dq3->configure(args2);
+ mbdFanout3.bind(dq3, "", 0);
+ Queue::shared_ptr dq4(new Queue("dq4", true, &testStore)); // durable w/ limit 1
+ dq4->configure(args1);
+ mbdFanout3.bind(dq4, "", 0);
+ Queue::shared_ptr dq5(new Queue("dq5", true, &testStore)); // durable no limit
+ dq5->configure(args0);
+ mbdFanout3.bind(dq5, "", 0);
+
+ intrusive_ptr<Message> msg11 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
+ DeliverableMessage dmsg11(msg11);
+ mbdFanout3.route(dmsg11, "", 0); // Brings queues 3 and 4 to capacity limit
+ msg11->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg11->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(1u, dq3->getMessageCount());
+ BOOST_CHECK_EQUAL(1u, dq4->getMessageCount());
+ BOOST_CHECK_EQUAL(1u, dq5->getMessageCount());
+
+ intrusive_ptr<Message> msg12 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
+ DeliverableMessage dmsg12(msg12);
+ mbdFanout3.route(dmsg12, "", 0);
+ msg12->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg12->isContentReleased(), false); // XXXX - consequence of transient msg multi-queue ftd policy-handling limitations, fix in broker at some point!
+ BOOST_CHECK_EQUAL(2u, dq3->getMessageCount());
+ BOOST_CHECK_EQUAL(2u, dq4->getMessageCount());
+ BOOST_CHECK_EQUAL(2u, dq5->getMessageCount());
+
+ intrusive_ptr<Message> msg13 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content
+ DeliverableMessage dmsg13(msg13);
+ mbdFanout3.route(dmsg13, "", 0);
+ msg13->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg13->isContentReleased(), true);
+ BOOST_CHECK_EQUAL(3u, dq3->getMessageCount());
+ BOOST_CHECK_EQUAL(3u, dq4->getMessageCount());
+ BOOST_CHECK_EQUAL(3u, dq5->getMessageCount());
+
+ intrusive_ptr<Message> msg14 = mkMsg(testStore); // transient no content
+ DeliverableMessage dmsg14(msg14);
+ mbdFanout3.route(dmsg14, "", 0);
+ msg14->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg14->isContentReleased(), false); // XXXX - consequence of transient msg multi-queue ftd policy-handling limitations, fix in broker at some point!
+ BOOST_CHECK_EQUAL(4u, dq3->getMessageCount());
+ BOOST_CHECK_EQUAL(4u, dq4->getMessageCount());
+ BOOST_CHECK_EQUAL(4u, dq5->getMessageCount());
+
+ intrusive_ptr<Message> msg15 = mkMsg(testStore, "", true); // durable no content
+ DeliverableMessage dmsg15(msg15);
+ mbdFanout3.route(dmsg15, "", 0);
+ msg15->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg15->isContentReleased(), true);
+ BOOST_CHECK_EQUAL(5u, dq3->getMessageCount());
+ BOOST_CHECK_EQUAL(5u, dq4->getMessageCount());
+ BOOST_CHECK_EQUAL(5u, dq5->getMessageCount());
+
+ // Bind a transient queue, this should block the release of any further messages.
+ // Note: this will result in a violation of the count policy of dq3 and dq4 - but this
+ // is expected until a better overall multi-queue design is implemented. Similarly
+ // for the other tests in this section.
+
+ Queue::shared_ptr tq6(new Queue("tq6", true)); // transient no limit
+ tq6->configure(args0);
+ mbdFanout3.bind(tq6, "", 0);
+
+ intrusive_ptr<Message> msg16 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
+ DeliverableMessage dmsg16(msg16);
+ mbdFanout3.route(dmsg16, "", 0);
+ msg16->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg16->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(6u, dq3->getMessageCount());
+ BOOST_CHECK_EQUAL(6u, dq4->getMessageCount());
+ BOOST_CHECK_EQUAL(6u, dq5->getMessageCount());
+
+ intrusive_ptr<Message> msg17 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content
+ DeliverableMessage dmsg17(msg17);
+ mbdFanout3.route(dmsg17, "", 0);
+ msg17->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg17->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(7u, dq3->getMessageCount());
+ BOOST_CHECK_EQUAL(7u, dq4->getMessageCount());
+ BOOST_CHECK_EQUAL(7u, dq5->getMessageCount());
+
+ intrusive_ptr<Message> msg18 = mkMsg(testStore); // transient no content
+ DeliverableMessage dmsg18(msg18);
+ mbdFanout3.route(dmsg18, "", 0);
+ msg18->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg18->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(8u, dq3->getMessageCount());
+ BOOST_CHECK_EQUAL(8u, dq4->getMessageCount());
+ BOOST_CHECK_EQUAL(8u, dq5->getMessageCount());
+
+ intrusive_ptr<Message> msg19 = mkMsg(testStore, "", true); // durable no content
+ DeliverableMessage dmsg19(msg19);
+ mbdFanout3.route(dmsg19, "", 0);
+ msg19->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg19->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(9u, dq3->getMessageCount());
+ BOOST_CHECK_EQUAL(9u, dq4->getMessageCount());
+ BOOST_CHECK_EQUAL(9u, dq5->getMessageCount());
+
+
+ // --- Fanout exchange bound to multiple durable and transient queues ----------------------------------------------
+
+ FanOutExchange mbmFanout4("mbmFanout4", false, args0); // multiple bindings to durable/transient queues
+ Queue::shared_ptr dq7(new Queue("dq7", true, &testStore)); // durable no limit
+ dq7->configure(args0);
+ mbmFanout4.bind(dq7, "", 0);
+ Queue::shared_ptr dq8(new Queue("dq8", true, &testStore)); // durable w/ limit
+ dq8->configure(args1);
+ mbmFanout4.bind(dq8, "", 0);
+ Queue::shared_ptr tq9(new Queue("tq9", true)); // transient no limit
+ tq9->configure(args0);
+ mbmFanout4.bind(tq9, "", 0);
+
+ intrusive_ptr<Message> msg20 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
+ DeliverableMessage dmsg20(msg20);
+ mbmFanout4.route(dmsg20, "", 0); // Brings queue 7 to capacity limit
+ msg20->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg20->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(1u, dq7->getMessageCount());
+ BOOST_CHECK_EQUAL(1u, dq8->getMessageCount());
+ BOOST_CHECK_EQUAL(1u, tq9->getMessageCount());
+
+ intrusive_ptr<Message> msg21 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
+ DeliverableMessage dmsg21(msg21);
+ mbmFanout4.route(dmsg21, "", 0);
+ msg21->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg21->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(2u, dq7->getMessageCount()); // over limit
+ BOOST_CHECK_EQUAL(2u, dq8->getMessageCount());
+ BOOST_CHECK_EQUAL(2u, tq9->getMessageCount());
+
+ intrusive_ptr<Message> msg22 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content
+ DeliverableMessage dmsg22(msg22);
+ mbmFanout4.route(dmsg22, "", 0);
+ msg22->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg22->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(3u, dq7->getMessageCount()); // over limit
+ BOOST_CHECK_EQUAL(3u, dq8->getMessageCount()); // over limit
+ BOOST_CHECK_EQUAL(3u, tq9->getMessageCount());
+
+ intrusive_ptr<Message> msg23 = mkMsg(testStore); // transient no content
+ DeliverableMessage dmsg23(msg23);
+ mbmFanout4.route(dmsg23, "", 0);
+ msg23->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg23->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(4u, dq7->getMessageCount()); // over limit
+ BOOST_CHECK_EQUAL(4u, dq8->getMessageCount()); // over limit
+ BOOST_CHECK_EQUAL(4u, tq9->getMessageCount());
+
+ intrusive_ptr<Message> msg24 = mkMsg(testStore, "", true); // durable no content
+ DeliverableMessage dmsg24(msg24);
+ mbmFanout4.route(dmsg24, "", 0);
+ msg24->tryReleaseContent();
+ BOOST_CHECK_EQUAL(msg24->isContentReleased(), false);
+ BOOST_CHECK_EQUAL(5u, dq7->getMessageCount()); // over limit
+ BOOST_CHECK_EQUAL(5u, dq8->getMessageCount()); // over limit
+ BOOST_CHECK_EQUAL(5u, tq9->getMessageCount());
+}
+
+
QPID_AUTO_TEST_SUITE_END()
}} // namespace qpid::tests
diff --git a/qpid/cpp/src/tests/TxPublishTest.cpp b/qpid/cpp/src/tests/TxPublishTest.cpp
index fabb01b864..6b44d95baa 100644
--- a/qpid/cpp/src/tests/TxPublishTest.cpp
+++ b/qpid/cpp/src/tests/TxPublishTest.cpp
@@ -50,7 +50,7 @@ struct TxPublishTest
TxPublishTest() :
queue1(new Queue("queue1", false, &store, 0)),
queue2(new Queue("queue2", false, &store, 0)),
- msg(MessageUtils::createMessage("exchange", "routing_key", "id")),
+ msg(MessageUtils::createMessage("exchange", "routing_key", false, "id")),
op(msg)
{
msg->getProperties<DeliveryProperties>()->setDeliveryMode(PERSISTENT);
diff --git a/qpid/cpp/src/tests/acl.py b/qpid/cpp/src/tests/acl.py
index fc53d2ce8b..2d776e9941 100755
--- a/qpid/cpp/src/tests/acl.py
+++ b/qpid/cpp/src/tests/acl.py
@@ -220,10 +220,11 @@ class ACLTests(TestBase010):
"""
aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q1 durable=true passive=true\n')
- aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true\n')
+ aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true policytype=ring\n')
aclf.write('acl deny bob@QPID access queue name=q3\n')
aclf.write('acl deny bob@QPID purge queue name=q3\n')
- aclf.write('acl deny bob@QPID delete queue name=q4\n')
+ aclf.write('acl deny bob@QPID delete queue name=q4\n')
+ aclf.write('acl deny bob@QPID create queue name=q5 maxqueuesize=1000 maxqueuecount=100\n')
aclf.write('acl allow all all')
aclf.close()
@@ -241,19 +242,41 @@ class ACLTests(TestBase010):
session = self.get_session('bob','bob')
try:
- session.queue_declare(queue="q2", exclusive=True)
- self.fail("ACL should deny queue create request with name=q2 exclusive=true");
+ queue_options = {}
+ queue_options["qpid.policy_type"] = "ring"
+ session.queue_declare(queue="q2", exclusive=True, arguments=queue_options)
+ self.fail("ACL should deny queue create request with name=q2 exclusive=true qpid.policy_type=ring");
except qpid.session.SessionException, e:
self.assertEqual(530,e.args[0].error_code)
session = self.get_session('bob','bob')
try:
- session.queue_declare(queue="q2", durable=True)
+ queue_options = {}
+ queue_options["qpid.policy_type"] = "ring_strict"
+ session.queue_declare(queue="q2", exclusive=True, arguments=queue_options)
except qpid.session.SessionException, e:
if (530 == e.args[0].error_code):
- self.fail("ACL should allow queue create request for q2 with any parameter other than exclusive=true");
+ self.fail("ACL should allow queue create request with name=q2 exclusive=true qpid.policy_type=ring_strict");
try:
+ queue_options = {}
+ queue_options["qpid.max_count"] = 200
+ queue_options["qpid.max_size"] = 500
+ session.queue_declare(queue="q5", exclusive=True, arguments=queue_options)
+ self.fail("ACL should deny queue create request with name=q2, qpid.max_size=500 and qpid.max_count=200");
+ except qpid.session.SessionException, e:
+ self.assertEqual(530,e.args[0].error_code)
+ session = self.get_session('bob','bob')
+
+ try:
+ queue_options = {}
+ queue_options["qpid.max_count"] = 200
+ queue_options["qpid.max_size"] = 100
+ session.queue_declare(queue="q2", exclusive=True, arguments=queue_options)
+ except qpid.session.SessionException, e:
+ if (530 == e.args[0].error_code):
+ self.fail("ACL should allow queue create request with name=q2, qpid.max_size=100 and qpid.max_count=200 ");
+ try:
session.queue_declare(queue="q3", exclusive=True)
session.queue_declare(queue="q4", durable=True)
except qpid.session.SessionException, e:
@@ -300,12 +323,13 @@ class ACLTests(TestBase010):
"""
aclf = ACLFile()
aclf.write('acl allow bob@QPID create queue name=q1 durable=true passive=true\n')
- aclf.write('acl allow bob@QPID create queue name=q2 exclusive=true\n')
+ aclf.write('acl allow bob@QPID create queue name=q2 exclusive=true policytype=ring\n')
aclf.write('acl allow bob@QPID access queue name=q3\n')
aclf.write('acl allow bob@QPID purge queue name=q3\n')
aclf.write('acl allow bob@QPID create queue name=q3\n')
aclf.write('acl allow bob@QPID create queue name=q4\n')
- aclf.write('acl allow bob@QPID delete queue name=q4\n')
+ aclf.write('acl allow bob@QPID delete queue name=q4\n')
+ aclf.write('acl allow bob@QPID create queue name=q5 maxqueuesize=1000 maxqueuecount=100\n')
aclf.write('acl allow guest@QPID all all\n')
aclf.write('acl deny all all')
aclf.close()
@@ -337,10 +361,31 @@ class ACLTests(TestBase010):
session = self.get_session('bob','bob')
try:
- session.queue_declare(queue="q2", exclusive=True)
+ queue_options = {}
+ queue_options["qpid.max_count"] = 200
+ queue_options["qpid.max_size"] = 500
+ session.queue_declare(queue="q5", arguments=queue_options)
+ self.fail("ACL should deny queue create request with name=q2 maxqueuesize=500 maxqueuecount=200");
+ except qpid.session.SessionException, e:
+ self.assertEqual(530,e.args[0].error_code)
+ session = self.get_session('bob','bob')
+
+ try:
+ queue_options = {}
+ queue_options["qpid.max_count"] = 100
+ queue_options["qpid.max_size"] = 500
+ session.queue_declare(queue="q5", arguments=queue_options)
except qpid.session.SessionException, e:
if (530 == e.args[0].error_code):
- self.fail("ACL should allow queue create request for q2 with exclusive=true");
+ self.fail("ACL should allow queue create request with name=q2 maxqueuesize=500 maxqueuecount=200");
+
+ try:
+ queue_options = {}
+ queue_options["qpid.policy_type"] = "ring"
+ session.queue_declare(queue="q2", exclusive=True, arguments=queue_options)
+ except qpid.session.SessionException, e:
+ if (530 == e.args[0].error_code):
+ self.fail("ACL should allow queue create request for q2 with exclusive=true policytype=ring");
try:
session.queue_declare(queue="q3")
@@ -733,7 +778,7 @@ class ACLTests(TestBase010):
# ACL publish tests
#=====================================
- def test_publish_acl(self):
+ def test_publish_acl_allow_mode(self):
"""
Test various publish acl
"""
@@ -779,4 +824,61 @@ class ACLTests(TestBase010):
session.message_transfer(destination="amq.direct", message=Message(props,"Test"))
except qpid.session.SessionException, e:
if (530 == e.args[0].error_code):
- self.fail("ACL should allow message transfer to exchange amq.direct");
+ self.fail("ACL should allow message transfer to exchange amq.direct with routing key rk2");
+
+
+ def test_publish_acl_deny_mode(self):
+ """
+ Test various publish acl
+ """
+ aclf = ACLFile()
+ aclf.write('acl allow bob@QPID publish exchange name=amq.direct routingkey=rk1\n')
+ aclf.write('acl allow bob@QPID publish exchange name=amq.topic\n')
+ aclf.write('acl allow bob@QPID publish exchange name=myEx routingkey=rk2\n')
+ aclf.write('acl allow bob@QPID create exchange\n')
+ aclf.write('acl allow guest@QPID all all \n')
+ aclf.write('acl deny all all')
+ aclf.close()
+
+ result = self.reload_acl()
+ if (result.text.find("format error",0,len(result.text)) != -1):
+ self.fail(result)
+
+ session = self.get_session('bob','bob')
+
+ props = session.delivery_properties(routing_key="rk2")
+
+ try:
+ session.message_transfer(destination="amq.direct", message=Message(props,"Test"))
+ self.fail("ACL should deny message transfer to name=amq.direct routingkey=rk2");
+ except qpid.session.SessionException, e:
+ self.assertEqual(530,e.args[0].error_code)
+ session = self.get_session('bob','bob')
+
+ try:
+ session.message_transfer(destination="amq.topic", message=Message(props,"Test"))
+ except qpid.session.SessionException, e:
+ if (530 == e.args[0].error_code):
+ self.fail("ACL should allow message transfer to exchange amq.topic with any routing key");
+
+ try:
+ session.exchange_declare(exchange='myEx', type='direct', durable=False)
+ session.message_transfer(destination="myEx", message=Message(props,"Test"))
+ except qpid.session.SessionException, e:
+ if (530 == e.args[0].error_code):
+ self.fail("ACL should allow message transfer to exchange myEx with routing key=rk2");
+
+ props = session.delivery_properties(routing_key="rk1")
+
+ try:
+ session.message_transfer(destination="myEx", message=Message(props,"Test"))
+ self.fail("ACL should deny message transfer to name=myEx routingkey=rk1");
+ except qpid.session.SessionException, e:
+ self.assertEqual(530,e.args[0].error_code)
+ session = self.get_session('bob','bob')
+
+ try:
+ session.message_transfer(destination="amq.direct", message=Message(props,"Test"))
+ except qpid.session.SessionException, e:
+ if (530 == e.args[0].error_code):
+ self.fail("ACL should allow message transfer to exchange amq.direct with routing key rk1");
diff --git a/qpid/cpp/src/tests/ais_check b/qpid/cpp/src/tests/ais_check
index 79862d7439..92eaa9dd39 100755
--- a/qpid/cpp/src/tests/ais_check
+++ b/qpid/cpp/src/tests/ais_check
@@ -21,35 +21,14 @@
srcdir=`dirname $0`
# Check AIS requirements and run tests if found.
-id -nG | grep '\<ais\>' >/dev/null || \
- NOGROUP="You are not a member of the ais group."
-ps -u root | grep 'aisexec\|corosync' >/dev/null || \
- NOAISEXEC="The aisexec or corosync daemon is not running as root"
-
-if test -n "$NOGROUP" -o -n "$NOAISEXEC"; then
- cat <<EOF
-
- =========== WARNING: NOT RUNNING AIS TESTS ==============
-
- Tests that depend on the openais library (used for clustering)
- will not be run because:
- $NOGROUP
- $NOAISEXEC
-
- ==========================================================
-
-EOF
+ps -u root | grep 'aisexec\|corosync' >/dev/null || {
+ echo WARNING: Skipping cluster tests, the aisexec or corosync daemon is not running.
exit 0; # A warning, not a failure.
-fi
+}
-# Execute command with the ais group set.
+# Execute command with the ais group set if user is a member.
with_ais_group() {
- id -nG | grep '\<ais\>' >/dev/null || { echo "You are not a member of the ais group."; exit 1; }
- echo $* | newgrp ais
+ if id -nG | grep '\<ais\>' >/dev/null; then sg ais -c "$*"
+ else "$@"
+ fi
}
-
-# Run the tests
-srcdir=`dirname $0`
-with_ais_group $srcdir/run_test ./cluster_test || ERROR=1
-exit $ERROR
-
diff --git a/qpid/cpp/src/tests/background.ps1 b/qpid/cpp/src/tests/background.ps1
index 934078602b..36e9e4e6e9 100644
--- a/qpid/cpp/src/tests/background.ps1
+++ b/qpid/cpp/src/tests/background.ps1
@@ -30,11 +30,26 @@ trap { break }
$encodedScript = [convert]::ToBase64String(
[Text.Encoding]::Unicode.GetBytes([string] $script))
-$p = new-object System.Diagnostics.Process
+#$p = new-object System.Diagnostics.Process
$si = new-object System.Diagnostics.ProcessStartInfo
$si.WorkingDirectory = $pwd
-$si.UseShellExecute = $true
$si.FileName = (get-command powershell.exe).Definition
$si.Arguments = "-encodedCommand $encodedScript"
-[diagnostics.process]::Start($si)
+###### debugging setup
+#$si.CreateNoWindow = $true
+# UseShellExecute false required for RedirectStandard(Error, Output)
+#$si.UseShellExecute = $false
+#$si.RedirectStandardError = $true
+#$si.RedirectStandardOutput = $true
+######
+$si.UseShellExecute = $true
+
+##### Debugging, instead of the plain Start() above.
+#$output = [io.File]::AppendText("start.out")
+#$error = [io.File]::AppendText("start.err")
+$p = [System.Diagnostics.Process]::Start($si)
+#$output.WriteLine($p.StandardOutput.ReadToEnd())
+#$error.WriteLine($p.StandardError.ReadToEnd())
+#$p.WaitForExit()
+#$output.Close()
diff --git a/qpid/cpp/src/tests/cluster.mk b/qpid/cpp/src/tests/cluster.mk
index 05e18ab9eb..bdec10ebb0 100644
--- a/qpid/cpp/src/tests/cluster.mk
+++ b/qpid/cpp/src/tests/cluster.mk
@@ -30,7 +30,8 @@ if HAVE_LIBCPG
# ais_check checks pre-requisites for cluster tests and runs them if ok.
TESTS += \
- ais_check \
+ run_cluster_test \
+ cluster_read_credit \
test_watchdog \
run_cluster_tests \
federated_cluster_test \
@@ -38,6 +39,8 @@ TESTS += \
EXTRA_DIST += \
ais_check \
+ run_cluster_test \
+ cluster_read_credit \
test_watchdog \
start_cluster \
stop_cluster \
diff --git a/qpid/cpp/src/tests/cluster_read_credit b/qpid/cpp/src/tests/cluster_read_credit
new file mode 100755
index 0000000000..370d4098c5
--- /dev/null
+++ b/qpid/cpp/src/tests/cluster_read_credit
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Regression test for http://issues.apache.org/jira/browse/QPID-2086
+
+srcdir=`dirname $0`
+. $srcdir/ais_check
+$srcdir/start_cluster 1 --cluster-read-max=2 || exit 1
+trap $srcdir/stop_cluster EXIT
+seq 1 10000 | ./sender --port `cat cluster.ports` --routing-key no-such-queue
diff --git a/qpid/cpp/src/tests/cluster_test.cpp b/qpid/cpp/src/tests/cluster_test.cpp
index 28fcdd13ad..247aef1b2a 100644
--- a/qpid/cpp/src/tests/cluster_test.cpp
+++ b/qpid/cpp/src/tests/cluster_test.cpp
@@ -85,6 +85,12 @@ void prepareArgs(ClusterFixture::Args& args, const bool durableFlag = false) {
args += "--no-data-dir";
}
+ClusterFixture::Args prepareArgs(const bool durableFlag = false) {
+ ClusterFixture::Args args;
+ prepareArgs(args, durableFlag);
+ return args;
+}
+
// Timeout for tests that wait for messages
const sys::Duration TIMEOUT=sys::TIME_SEC/4;
@@ -596,16 +602,19 @@ QPID_AUTO_TEST_CASE(testUpdateConsumers) {
}
}
-QPID_AUTO_TEST_CASE(testCatchupSharedState) {
+// Test that message data and delivery properties are updated properly.
+QPID_AUTO_TEST_CASE(testUpdateMessages) {
ClusterFixture::Args args;
prepareArgs(args, durableFlag);
ClusterFixture cluster(1, args, -1);
Client c0(cluster[0], "c0");
- // Create some shared state.
+ // Create messages with different delivery properties
c0.session.queueDeclare("q", arg::durable=durableFlag);
+ c0.session.exchangeBind(arg::exchange="amq.fanout", arg::queue="q");
c0.session.messageTransfer(arg::content=makeMessage("foo","q", durableFlag));
- c0.session.messageTransfer(arg::content=makeMessage("bar","q", durableFlag));
+ c0.session.messageTransfer(arg::content=makeMessage("bar","q", durableFlag),
+ arg::destination="amq.fanout");
while (c0.session.queueQuery("q").getMessageCount() != 2)
sys::usleep(1000); // Wait for message to show up on broker 0.
@@ -628,9 +637,12 @@ QPID_AUTO_TEST_CASE(testCatchupSharedState) {
BOOST_CHECK(c1.subs.get(m, "q", TIMEOUT));
BOOST_CHECK_EQUAL(m.getData(), "foo");
+ BOOST_CHECK(m.getDeliveryProperties().hasExchange());
BOOST_CHECK_EQUAL(m.getDeliveryProperties().getExchange(), "");
BOOST_CHECK(c1.subs.get(m, "q", TIMEOUT));
BOOST_CHECK_EQUAL(m.getData(), "bar");
+ BOOST_CHECK(m.getDeliveryProperties().hasExchange());
+ BOOST_CHECK_EQUAL(m.getDeliveryProperties().getExchange(), "amq.fanout");
BOOST_CHECK_EQUAL(c1.session.queueQuery("q").getMessageCount(), 0u);
// Add another broker, don't wait for join - should be stalled till ready.
@@ -905,6 +917,7 @@ QPID_AUTO_TEST_CASE(testExclusiveQueueUpdate) {
BOOST_CHECK(!result.getDurable());
BOOST_CHECK_EQUAL(result.getAlternateExchange(), std::string("amq.fanout"));
BOOST_CHECK_THROW(c2.session.queueDeclare(arg::queue="q", arg::exclusive=true, arg::passive=true), framing::ResourceLockedException);
+ c1.session.close();
c1.connection.close();
c2.session = c2.connection.newSession();
BOOST_CHECK_THROW(c2.session.queueDeclare(arg::queue="q", arg::passive=true), framing::NotFoundException);
@@ -1100,6 +1113,44 @@ QPID_AUTO_TEST_CASE(testRelease) {
}
}
-QPID_AUTO_TEST_SUITE_END()
+// Browse for 1 message with byte credit, return true if a message was
+// received false if not.
+bool browseByteCredit(Client& c, const string& q, int n, Message& m) {
+ SubscriptionSettings browseSettings(
+ FlowControl(1, n, false), // 1 message, n bytes credit, no window
+ ACCEPT_MODE_NONE,
+ ACQUIRE_MODE_NOT_ACQUIRED,
+ 0 // No auto-ack.
+ );
+ LocalQueue lq;
+ Subscription s = c.subs.subscribe(lq, q, browseSettings);
+ c.session.messageFlush(arg::destination=q, arg::sync=true);
+ c.session.sync();
+ c.subs.getSubscription(q).cancel();
+ return lq.get(m, 0); // No timeout, flush should push message thru.
+}
+
+// Ensure cluster update preserves exact message size, use byte credt as test.
+QPID_AUTO_TEST_CASE(testExactByteCredit) {
+ ClusterFixture cluster(1, prepareArgs(), -1);
+ Client c0(cluster[0], "c0");
+ c0.session.queueDeclare("q");
+ c0.session.messageTransfer(arg::content=Message("MyMessage", "q"));
+ cluster.add();
+
+ int size=36; // Size of message on broker: headers+body
+ Client c1(cluster[1], "c1");
+ Message m;
+
+ // Ensure we get the message with exact credit.
+ BOOST_CHECK(browseByteCredit(c0, "q", size, m));
+ BOOST_CHECK(browseByteCredit(c1, "q", size, m));
+ // and not with one byte less.
+ BOOST_CHECK(!browseByteCredit(c0, "q", size-1, m));
+ BOOST_CHECK(!browseByteCredit(c1, "q", size-1, m));
+}
+
+
+QPID_AUTO_TEST_SUITE_END()
}} // namespace qpid::tests
diff --git a/qpid/cpp/src/tests/clustered_replication_test b/qpid/cpp/src/tests/clustered_replication_test
index cc331957ad..4f13b4672c 100755
--- a/qpid/cpp/src/tests/clustered_replication_test
+++ b/qpid/cpp/src/tests/clustered_replication_test
@@ -22,8 +22,7 @@
# Test reliability of the replication feature in the face of link
# failures:
srcdir=`dirname $0`
-PYTHON_DIR=$srcdir/../../../python
-export PYTHONPATH=$PYTHON_DIR
+. $srcdir/python_env.sh
trap stop_brokers INT EXIT
@@ -31,10 +30,6 @@ fail() {
echo $1
exit 1
}
-with_ais_group() {
- id -nG | grep '\<ais\>' >/dev/null || { echo "You are not a member of the ais group." 1>&2; exit 1; }
- echo $* | newgrp ais
-}
stop_brokers() {
if [[ $PRIMARY1 ]] ; then
@@ -55,26 +50,8 @@ stop_brokers() {
fi
}
-if test -d ${PYTHON_DIR}; then
- id -nG | grep '\<ais\>' >/dev/null || \
- NOGROUP="You are not a member of the ais group."
- ps -u root | grep 'aisexec\|corosync' >/dev/null || \
- NOAISEXEC="The aisexec or corosync daemon is not running as root"
-
- if test -n "$NOGROUP" -o -n "$NOAISEXEC"; then
- cat <<EOF
-
- =========== WARNING: NOT RUNNING AIS TESTS ==============
-
- Not running cluster replication test because:
- $NOGROUP
- $NOAISEXEC
-
- ==========================================================
-
-EOF
- exit 0;
- fi
+if test -d $PYTHON_DIR; then
+ . $srcdir/ais_check
#todo: these cluster names need to be unique to prevent clashes
PRIMARY_CLUSTER=PRIMARY_$(hostname)_$(pwd)
@@ -89,8 +66,8 @@ EOF
#start first node of primary cluster and set up test queue
echo Starting primary cluster
PRIMARY1=$(with_ais_group ../qpidd $GENERAL_OPTS $PRIMARY_OPTS --log-to-file repl.primary.1.tmp) || fail "Could not start node"
- $PYTHON_DIR/commands/qpid-config -a "localhost:$PRIMARY1" add queue test-queue --generate-queue-events 2
- $PYTHON_DIR/commands/qpid-config -a "localhost:$PRIMARY1" add queue control-queue --generate-queue-events 1
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$PRIMARY1" add queue test-queue --generate-queue-events 2
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$PRIMARY1" add queue control-queue --generate-queue-events 1
#send 10 messages, consume 5 of them
for i in `seq 1 10`; do echo Message$i; done | ./sender --port $PRIMARY1
@@ -105,10 +82,10 @@ EOF
DR1=$(with_ais_group ../qpidd $GENERAL_OPTS $DR_OPTS --log-to-file repl.dr.1.tmp)
DR2=$(with_ais_group ../qpidd $GENERAL_OPTS $DR_OPTS --log-to-file repl.dr.2.tmp)
- $PYTHON_DIR/commands/qpid-config -a "localhost:$DR1" add queue test-queue
- $PYTHON_DIR/commands/qpid-config -a "localhost:$DR1" add queue control-queue
- $PYTHON_DIR/commands/qpid-config -a "localhost:$DR1" add exchange replication REPLICATION_EXCHANGE
- $PYTHON_DIR/commands/qpid-route queue add localhost:$DR2 localhost:$PRIMARY2 REPLICATION_EXCHANGE REPLICATION_QUEUE
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$DR1" add queue test-queue
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$DR1" add queue control-queue
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$DR1" add exchange replication REPLICATION_EXCHANGE
+ $PYTHON_COMMANDS/qpid-route queue add localhost:$DR2 localhost:$PRIMARY2 REPLICATION_EXCHANGE REPLICATION_QUEUE
#send more messages to primary
for i in `seq 11 20`; do echo Message$i; done | ./sender --port $PRIMARY1 --send-eos 1
diff --git a/qpid/cpp/src/tests/federated_cluster_test b/qpid/cpp/src/tests/federated_cluster_test
index a781e269d6..8b3ce3cb95 100755
--- a/qpid/cpp/src/tests/federated_cluster_test
+++ b/qpid/cpp/src/tests/federated_cluster_test
@@ -22,7 +22,7 @@
# Test reliability of the replication feature in the face of link
# failures:
srcdir=`dirname $0`
-PYTHON_DIR=$srcdir/../../../python
+. $srcdir/python_env.sh
trap stop_brokers EXIT
@@ -61,22 +61,21 @@ start_brokers() {
}
setup() {
- export PYTHONPATH=$PYTHON_DIR
#create exchange on both cluster and single broker
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" add exchange direct test-exchange
- $PYTHON_DIR/commands/qpid-config -a "localhost:$NODE_1" add exchange direct test-exchange
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add exchange direct test-exchange
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$NODE_1" add exchange direct test-exchange
#create dynamic routes for test exchange
- $PYTHON_DIR/commands/qpid-route dynamic add "localhost:$NODE_2" "localhost:$BROKER_A" test-exchange
- $PYTHON_DIR/commands/qpid-route dynamic add "localhost:$BROKER_A" "localhost:$NODE_2" test-exchange
+ $PYTHON_COMMANDS/qpid-route dynamic add "localhost:$NODE_2" "localhost:$BROKER_A" test-exchange
+ $PYTHON_COMMANDS/qpid-route dynamic add "localhost:$BROKER_A" "localhost:$NODE_2" test-exchange
#create test queue on cluster and bind it to the test exchange
- $PYTHON_DIR/commands/qpid-config -a "localhost:$NODE_1" add queue test-queue
- $PYTHON_DIR/commands/qpid-config -a "localhost:$NODE_1" bind test-exchange test-queue to-cluster
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$NODE_1" add queue test-queue
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$NODE_1" bind test-exchange test-queue to-cluster
#create test queue on single broker and bind it to the test exchange
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" add queue test-queue
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" bind test-exchange test-queue from-cluster
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue test-queue
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" bind test-exchange test-queue from-cluster
}
run_test_pull_to_cluster_two_consumers() {
@@ -127,25 +126,7 @@ run_test_pull_from_cluster() {
if test -d ${PYTHON_DIR}; then
- id -nG | grep '\<ais\>' >/dev/null || \
- NOGROUP="You are not a member of the ais group."
- ps -u root | grep 'aisexec\|corosync' >/dev/null || \
- NOAISEXEC="The aisexec or corosync daemon is not running as root"
-
- if test -n "$NOGROUP" -o -n "$NOAISEXEC"; then
- cat <<EOF
-
- =========== WARNING: NOT RUNNING AIS TESTS ==============
-
- Not running federation to cluster test because:
- $NOGROUP
- $NOAISEXEC
-
- ==========================================================
-
-EOF
- exit 0;
- fi
+ . $srcdir/ais_check
rm -f fed*.tmp #cleanup any files left from previous run
start_brokers
diff --git a/qpid/cpp/src/tests/federated_topic_test b/qpid/cpp/src/tests/federated_topic_test
index 21d8411eaf..dbe9a85e95 100755
--- a/qpid/cpp/src/tests/federated_topic_test
+++ b/qpid/cpp/src/tests/federated_topic_test
@@ -43,7 +43,7 @@ while getopts "s:m:b:" opt ; do
done
MY_DIR=$(dirname $(which $0))
-PYTHON_DIR=${MY_DIR}/../../../python
+. $MY_DIR/python_env.sh
trap stop_brokers EXIT
@@ -87,29 +87,28 @@ setup_routes() {
BROKER_A="localhost:$PORT_A"
BROKER_B="localhost:$PORT_B"
BROKER_C="localhost:$PORT_C"
- export PYTHONPATH=$PYTHON_DIR
if (($VERBOSE)); then
echo "Establishing routes for topic..."
fi
- $PYTHON_DIR/commands/qpid-route route add $BROKER_B $BROKER_A amq.topic topic_control B B
- $PYTHON_DIR/commands/qpid-route route add $BROKER_C $BROKER_B amq.topic topic_control C C
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_B $BROKER_A amq.topic topic_control B B
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_C $BROKER_B amq.topic topic_control C C
if (($VERBOSE)); then
echo "linked A->B->C"
fi
- $PYTHON_DIR/commands/qpid-route route add $BROKER_B $BROKER_C amq.topic topic_control B B
- $PYTHON_DIR/commands/qpid-route route add $BROKER_A $BROKER_B amq.topic topic_control A A
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_B $BROKER_C amq.topic topic_control B B
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_A $BROKER_B amq.topic topic_control A A
if (($VERBOSE)); then
echo "linked C->B->A"
echo "Establishing routes for response queue..."
fi
- $PYTHON_DIR/commands/qpid-route route add $BROKER_B $BROKER_C amq.direct response B B
- $PYTHON_DIR/commands/qpid-route route add $BROKER_A $BROKER_B amq.direct response A A
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_B $BROKER_C amq.direct response B B
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_A $BROKER_B amq.direct response A A
if (($VERBOSE)); then
echo "linked C->B->A"
for b in $BROKER_A $BROKER_B $BROKER_C; do
echo "Routes for $b"
- $PYTHON_DIR/commands/qpid-route route list $b
+ $PYTHON_COMMANDS/qpid-route route list $b
done
fi
}
diff --git a/qpid/cpp/src/tests/python_env.sh b/qpid/cpp/src/tests/python_env.sh
new file mode 100644
index 0000000000..f5dca97a56
--- /dev/null
+++ b/qpid/cpp/src/tests/python_env.sh
@@ -0,0 +1,26 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Environment for python tests
+test -d python || { echo "WARNING: skipping `basename $0`, no python directory."; exit 0; }
+PYTHON_DIR=$PWD/python
+PYTHON_COMMANDS=$PYTHON_DIR/commands
+PYTHONPATH=$PYTHON_DIR
+export PYTHONPATH PYTHON_DIR
+
diff --git a/qpid/cpp/src/tests/python_tests b/qpid/cpp/src/tests/python_tests
index e3906c1685..e2077ef7dc 100755
--- a/qpid/cpp/src/tests/python_tests
+++ b/qpid/cpp/src/tests/python_tests
@@ -20,14 +20,10 @@
#
# Run the python tests.
+. `dirname $0`/python_env.sh
QPID_PORT=${QPID_PORT:-5672}
PYTHON_TESTS=${PYTHON_TESTS:-$*}
-QPID_PYTHON_DIR=${QPID_PYTHON_DIR:-`dirname $0`/../../../python}
FAILING=${FAILING:-/dev/null}
-if test -d $QPID_PYTHON_DIR; then
- cd $QPID_PYTHON_DIR
- ./qpid-python-test -b localhost:$QPID_PORT -I $FAILING $PYTHON_TESTS || { echo "FAIL python tests"; exit 1; }
-else
- echo "WARNING: No python tests. $QPID_PYTHON_DIR not found."
-fi
+cd $PYTHON_DIR
+python commands/qpid-python-test -b localhost:$QPID_PORT -I $FAILING $PYTHON_TESTS || exit 1
diff --git a/qpid/cpp/src/tests/python_tests.ps1 b/qpid/cpp/src/tests/python_tests.ps1
new file mode 100644
index 0000000000..a7f6920783
--- /dev/null
+++ b/qpid/cpp/src/tests/python_tests.ps1
@@ -0,0 +1,42 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Run the python tests; intended to be run by run_test.ps1 which sets up
+# QPID_PORT
+$srcdir = Split-Path $myInvocation.InvocationName
+$PYTHON_DIR = "$srcdir\..\..\..\python"
+if (!(Test-Path $PYTHON_DIR -pathType Container)) {
+ "Skipping header test as python libs not found"
+ exit 1
+}
+
+if (Test-Path env:FAILING) {
+ $fails = "-I $env:FAILING"
+}
+if (Test-Path env:PYTHON_TESTS) {
+ $tests = "$env:PYTHON_TESTS"
+}
+else {
+ $tests = "*"
+}
+
+#cd $PYTHON_DIR
+$env:PYTHONPATH="$PYTHON_DIR;$env:PYTHONPATH"
+python $PYTHON_DIR/qpid-python-test -b localhost:$env:QPID_PORT $fails $tests
+exit $LASTEXITCODE
diff --git a/qpid/cpp/src/tests/qpid_stream.cpp b/qpid/cpp/src/tests/qpid_stream.cpp
index 8e02baa8a0..8195bf390e 100644
--- a/qpid/cpp/src/tests/qpid_stream.cpp
+++ b/qpid/cpp/src/tests/qpid_stream.cpp
@@ -34,6 +34,9 @@
using namespace qpid::messaging;
using namespace qpid::sys;
+namespace qpid {
+namespace tests {
+
struct Args : public qpid::Options
{
std::string url;
@@ -139,10 +142,14 @@ struct Consume : Client
<< ", min=" << minLatency
<< ", max=" << maxLatency << std::endl;
}
- }
+ }
}
};
+}} // namespace qpid::tests
+
+using namespace qpid::tests;
+
int main(int argc, char** argv)
{
try {
diff --git a/qpid/cpp/src/tests/quick_topictest.ps1 b/qpid/cpp/src/tests/quick_topictest.ps1
index 2b857edfff..b1e0ed1f7d 100644
--- a/qpid/cpp/src/tests/quick_topictest.ps1
+++ b/qpid/cpp/src/tests/quick_topictest.ps1
@@ -18,12 +18,13 @@
#
# Quick and quiet topic test for make check.
-$srcdir = Split-Path $myInvocation.ScriptName
-$PsHome\powershell $srcdir\topictest.ps1 -subscribers 2 -messages 2 -batches 1 > topictest.log 2>&1
-if ($LastExitCode != 0) {
- echo $0 FAILED:
+[string]$me = $myInvocation.InvocationName
+$srcdir = Split-Path $me
+powershell "$srcdir\topictest.ps1" -subscribers 2 -messages 2 -batches 1 > topictest.log 2>&1
+if (!$?) {
+ "$me FAILED:"
cat topictest.log
exit $LastExitCode
}
-rm topictest.log
+Remove-Item topictest.log
exit 0
diff --git a/qpid/cpp/src/tests/reliable_replication_test b/qpid/cpp/src/tests/reliable_replication_test
index a788d5a76b..db06259f0c 100755
--- a/qpid/cpp/src/tests/reliable_replication_test
+++ b/qpid/cpp/src/tests/reliable_replication_test
@@ -22,7 +22,7 @@
# Test reliability of the replication feature in the face of link
# failures:
MY_DIR=`dirname \`which $0\``
-PYTHON_DIR=${MY_DIR}/../../../python
+. ${MY_DIR}/python_env.sh
trap stop_brokers EXIT
@@ -53,12 +53,12 @@ setup() {
echo "Testing replication from port $BROKER_A to port $BROKER_B"
export PYTHONPATH=$PYTHON_DIR
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
- $PYTHON_DIR/commands/qpid-route --ack 500 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
+ $PYTHON_COMMANDS/qpid-route --ack 500 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
#create test queue (only replicate enqueues for this test):
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" add queue queue-a --generate-queue-events 1
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add queue queue-a
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-a --generate-queue-events 1
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-a
}
send() {
@@ -72,10 +72,10 @@ receive() {
bounce_link() {
echo "Destroying link..."
- $PYTHON_DIR/commands/qpid-route link del "localhost:$BROKER_B" "localhost:$BROKER_A"
+ $PYTHON_COMMANDS/qpid-route link del "localhost:$BROKER_B" "localhost:$BROKER_A"
echo "Link destroyed; recreating route..."
sleep 2
- $PYTHON_DIR/commands/qpid-route --ack 500 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
+ $PYTHON_COMMANDS/qpid-route --ack 500 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
echo "Route re-established"
}
diff --git a/qpid/cpp/src/tests/replication_test b/qpid/cpp/src/tests/replication_test
index 8b3022b260..000b4591da 100755
--- a/qpid/cpp/src/tests/replication_test
+++ b/qpid/cpp/src/tests/replication_test
@@ -21,7 +21,8 @@
# Run a test of the replication feature
MY_DIR=`dirname \`which $0\``
-PYTHON_DIR=${MY_DIR}/../../../python
+. `dirname $0`/python_env.sh
+
trap stop_brokers INT TERM QUIT
stop_brokers() {
@@ -47,21 +48,21 @@ if test -d ${PYTHON_DIR} && test -f ../.libs/replicating_listener.so && test -f
export PYTHONPATH
echo "Running replication test between localhost:$BROKER_A and localhost:$BROKER_B"
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
- $PYTHON_DIR/commands/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
+ $PYTHON_COMMANDS/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
#create test queues
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" add queue queue-a --generate-queue-events 2
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" add queue queue-b --generate-queue-events 2
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" add queue queue-c --generate-queue-events 1
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" add queue queue-d --generate-queue-events 2
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" add queue queue-e --generate-queue-events 1
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-a --generate-queue-events 2
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-b --generate-queue-events 2
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-c --generate-queue-events 1
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-d --generate-queue-events 2
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-e --generate-queue-events 1
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add queue queue-a
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add queue queue-b
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add queue queue-c
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add queue queue-e
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-a
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-b
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-c
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-e
#queue-d deliberately not declared on DR; this error case should be handled
#publish and consume from test queues on broker A:
@@ -125,13 +126,13 @@ if test -d ${PYTHON_DIR} && test -f ../.libs/replicating_listener.so && test -f
../qpidd --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module ../.libs/replication_exchange.so --log-enable info+ --log-to-file replication-dest.log --log-to-stderr 0 > qpidd.port
BROKER_B=`cat qpidd.port`
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
- $PYTHON_DIR/commands/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
+ $PYTHON_COMMANDS/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" add queue queue-e --generate-queue-events 2
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add queue queue-e
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_A" add queue queue-d --generate-queue-events 1
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add queue queue-d
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-e --generate-queue-events 2
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-e
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-d --generate-queue-events 1
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-d
i=1
while [ $i -le 10 ]; do
@@ -153,9 +154,9 @@ if test -d ${PYTHON_DIR} && test -f ../.libs/replicating_listener.so && test -f
../qpidd --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module ../.libs/replication_exchange.so --log-enable info+ --log-to-file replication-dest.log --log-to-stderr 0 > qpidd.port
BROKER_B=`cat qpidd.port`
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add queue queue-e
- $PYTHON_DIR/commands/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
- $PYTHON_DIR/commands/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-e
+ $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication
+ $PYTHON_COMMANDS/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication
# now send another 15
i=11
while [ $i -le 15 ]; do
diff --git a/qpid/cpp/src/tests/ring_queue_test b/qpid/cpp/src/tests/ring_queue_test
index 5805989d7e..553746eb49 100755
--- a/qpid/cpp/src/tests/ring_queue_test
+++ b/qpid/cpp/src/tests/ring_queue_test
@@ -48,7 +48,7 @@ receive() {
cleanup() {
rm -f sender_${QUEUE_NAME}_* receiver_${QUEUE_NAME}_*
- qpid-config $BROKER_URL add queue $QUEUE_NAME
+ qpid-config $BROKER_URL del queue $QUEUE_NAME --force
}
log() {
@@ -64,10 +64,11 @@ validate() {
if [[ $RECEIVERS -eq 0 ]]; then
#queue should have $LIMIT messages on it, but need to send an eos also
sender --routing-key $QUEUE_NAME --send-eos 1 < /dev/null
- if [[ $(receiver --queue $QUEUE_NAME --browse | wc -l) -eq $(( $LIMIT - 1)) ]]; then
+ received=$(receiver --queue $QUEUE_NAME --browse | wc -l)
+ if [[ received -eq $(( $LIMIT - 1)) ]]; then
log "queue contains $LIMIT messages as expected"
else
- fail "queue does not contain the expected $LIMIT messages"
+ fail "queue does not contain the expected $LIMIT messages (received $received)"
fi
elif [[ $CONCURRENT -eq 0 ]]; then
#sum of length of all output files should be equal to $LIMIT - $RECEIVERS (1 eos message each)
diff --git a/qpid/cpp/src/tests/run_acl_tests b/qpid/cpp/src/tests/run_acl_tests
index d9b654c7cd..c67e2d421d 100755
--- a/qpid/cpp/src/tests/run_acl_tests
+++ b/qpid/cpp/src/tests/run_acl_tests
@@ -20,7 +20,7 @@
#
# Run the acl tests. $srcdir is set by the Makefile.
-PYTHON_DIR=$srcdir/../../../python
+. `dirname $0`/python_env.sh
DATA_DIR=`pwd`/data_dir
trap stop_brokers INT TERM QUIT
@@ -55,7 +55,7 @@ if test -d ${PYTHON_DIR} ; then
echo "Running acl tests using brokers on ports $LOCAL_PORT"
PYTHONPATH=$PYTHON_DIR:$srcdir
export PYTHONPATH
- $PYTHON_DIR/qpid-python-test -b localhost:$LOCAL_PORT -m acl || EXITCODE=1
+ $PYTHON_COMMANDS/qpid-python-test -b localhost:$LOCAL_PORT -m acl || EXITCODE=1
stop_brokers || EXITCODE=1
test_loading_acl_from_absolute_path || EXITCODE=1
rm -rf $DATA_DIR
diff --git a/qpid/cpp/src/tests/run_cli_tests b/qpid/cpp/src/tests/run_cli_tests
index ea0d591176..bb9605410c 100755
--- a/qpid/cpp/src/tests/run_cli_tests
+++ b/qpid/cpp/src/tests/run_cli_tests
@@ -21,8 +21,8 @@
# Run the cli-utility tests.
MY_DIR=`dirname \`which $0\``
-PYTHON_DIR=${MY_DIR}/../../../python
-CLI_DIR=${PYTHON_DIR}/commands
+. `dirname $0`/python_env.sh
+CLI_DIR=$PYTHON_COMMANDS
trap stop_brokers INT TERM QUIT
@@ -43,7 +43,7 @@ if test -d ${PYTHON_DIR} ; then
echo "Running CLI tests using brokers on ports $LOCAL_PORT $REMOTE_PORT"
PYTHONPATH=${PYTHON_DIR}:${MY_DIR}
export PYTHONPATH
- ${PYTHON_DIR}/qpid-python-test -m cli_tests -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dcli-dir=$CLI_DIR $@
+ $PYTHON_COMMANDS/qpid-python-test -m cli_tests -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dcli-dir=$CLI_DIR $@
RETCODE=$?
stop_brokers
if test x$RETCODE != x0; then
diff --git a/qpid/cpp/src/tests/run_cluster_test b/qpid/cpp/src/tests/run_cluster_test
new file mode 100755
index 0000000000..c022eea1fe
--- /dev/null
+++ b/qpid/cpp/src/tests/run_cluster_test
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+
+# Run the tests
+srcdir=`dirname $0`
+. $srcdir/ais_check
+with_ais_group $srcdir/run_test ./cluster_test
diff --git a/qpid/cpp/src/tests/run_cluster_tests b/qpid/cpp/src/tests/run_cluster_tests
index 8b039346db..d1a58f9f6a 100755
--- a/qpid/cpp/src/tests/run_cluster_tests
+++ b/qpid/cpp/src/tests/run_cluster_tests
@@ -22,45 +22,21 @@
# Check that top_builddir and srcdir are set
# If not, assume local run from test dir
if [ -z ${top_builddir} -o -z ${srcdir} ]; then
- srcdir=`pwd`
+ srcdir=`dirname $0`
top_builddir=${srcdir}/../../
fi
TEST_DIR=${top_builddir}/src/tests
-PYTHON_DIR=${srcdir}/../../../python
+. $srcdir/python_env.sh
if test -z $1; then
- CLUSTER_TEST="${PYTHON_DIR}/qpid-python-test -m cluster_tests cluster_tests.ShortTests.\*"
+ CLUSTER_TEST="$PYTHON_COMMANDS/qpid-python-test -m cluster_tests cluster_tests.ShortTests.\*"
else
- CLUSTER_TEST="${PYTHON_DIR}/qpid-python-test -m cluster_tests cluster_tests.LongTests.\*"
+ CLUSTER_TEST="$PYTHON_COMMANDS/qpid-python-test -m cluster_tests cluster_tests.LongTests.\*"
echo "Running $1..."
fi
-
# Check AIS requirements
-id -nG | grep '\<ais\>' > /dev/null || NOGROUP="You are not a member of the ais group."
-ps -u root | grep 'aisexec\|corosync' > /dev/null || NOAISEXEC="The aisexec or corosync daemon is not running as root."
-if ! test -d ${PYTHON_DIR}; then
- NO_PYTHON_DIR="PYTHON_DIR=\"${PYTHON_DIR}\" not found or does not exist."
-fi
-
-if test -n "${NOGROUP}" -o -n "${NOAISEXEC}" -o -n "${NO_PYTHON_DIR}"; then
- cat <<EOF
-
- ======== WARNING: PYTHON CLUSTER TESTS DISABLED ===========
-
- Tests that depend on the openais library (used for clustering)
- and python will not be run because:
-
- ${NOGROUP}
- ${NOAISEXEC}
- ${NO_PYTHON_DIR}
-
- ===========================================================
-
-EOF
- exit 0
-fi
-
+. $srcdir/ais_check
# Check XML exchange requirements
XML_LIB=$srcdir/../.libs/xml.so
@@ -103,7 +79,7 @@ export TMP_DATA_DIR
# Run the test
-sg ais -c "${CLUSTER_TEST}"
+with_ais_group ${CLUSTER_TEST}
RETCODE=$?
if test x${RETCODE} != x0; then
@@ -114,4 +90,4 @@ fi
# Delete cluster store dir if test was successful.
rm -rf ${TMP_DATA_DIR}
-exit 0 \ No newline at end of file
+exit 0
diff --git a/qpid/cpp/src/tests/run_failover_soak b/qpid/cpp/src/tests/run_failover_soak
index 3c9a5589c4..8d5b37f008 100755
--- a/qpid/cpp/src/tests/run_failover_soak
+++ b/qpid/cpp/src/tests/run_failover_soak
@@ -19,29 +19,7 @@
# under the License.
#
-# Check AIS requirements and run tests if found.
-id -ng | grep '\<ais\>' >/dev/null || \
- NOGROUP="The ais group is not your primary group."
-ps -u root | grep 'aisexec\|corosync' >/dev/null || \
- NOAISEXEC="The aisexec/corosync daemon is not running as root"
-
-if test -n "$NOGROUP" -o -n "$NOAISEXEC"; then
- cat <<EOF
-
- =========== WARNING: NOT RUNNING AIS TESTS ==============
-
- Tests that depend on the openais library (used for clustering)
- will not be run because:
-
- $NOGROUP
- $NOAISEXEC
-
- ==========================================================
-
-EOF
- exit 0; # A warning, not a failure.
-fi
-
+. `dirname $0`/ais_check
host=127.0.0.1
diff --git a/qpid/cpp/src/tests/run_federation_tests b/qpid/cpp/src/tests/run_federation_tests
index 8640fb728f..3fe4bccb13 100755
--- a/qpid/cpp/src/tests/run_federation_tests
+++ b/qpid/cpp/src/tests/run_federation_tests
@@ -21,7 +21,7 @@
# Run the federation tests.
MY_DIR=`dirname \`which $0\``
-PYTHON_DIR=${MY_DIR}/../../../python
+. `dirname $0`/python_env.sh
trap stop_brokers INT TERM QUIT
@@ -42,7 +42,7 @@ if test -d ${PYTHON_DIR} ; then
echo "Running federation tests using brokers on ports $LOCAL_PORT $REMOTE_PORT"
PYTHONPATH=${PYTHON_DIR}:${MY_DIR}
export PYTHONPATH
- ${PYTHON_DIR}/qpid-python-test -m federation -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT $@
+ $PYTHON_COMMANDS/qpid-python-test -m federation -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT $@
RETCODE=$?
stop_brokers
if test x$RETCODE != x0; then
diff --git a/qpid/cpp/src/tests/run_federation_tests.ps1 b/qpid/cpp/src/tests/run_federation_tests.ps1
index db3dbf5a11..dd0ea2fe5b 100644
--- a/qpid/cpp/src/tests/run_federation_tests.ps1
+++ b/qpid/cpp/src/tests/run_federation_tests.ps1
@@ -18,42 +18,63 @@
#
# Run the federation tests.
-$srcdir = Split-Path $myInvocation.ScriptName
-$PYTHON_DIR = $srcdir\..\..\..\python
-trap stop_brokers INT TERM QUIT
+$srcdir = Split-Path $myInvocation.InvocationName
+$PYTHON_DIR = "$srcdir\..\..\..\python"
+if (!(Test-Path $PYTHON_DIR -pathType Container)) {
+ "Skipping federation tests as python libs not found"
+ exit 1
+}
-start_brokers() {
+# Test runs from the tests directory but the broker executable is one level
+# up, and most likely in a subdirectory from there based on what build type.
+# Look around for it before trying to start it.
+$subs = "Debug","Release","MinSizeRel","RelWithDebInfo"
+foreach ($sub in $subs) {
+ $prog = "..\$sub\qpidd.exe"
+ if (Test-Path $prog) {
+ break
+ }
+}
+if (!(Test-Path $prog)) {
+ "Cannot locate qpidd.exe"
+ exit 1
+}
+$cmdline = "$prog --auth=no --no-module-dir --port=0 --log-to-file qpidd.log $args | foreach { set-content qpidd.port `$_ }"
+$cmdblock = $executioncontext.invokecommand.NewScriptBlock($cmdline)
+
+function start_brokers {
# Start 2 brokers, saving the port numbers in LOCAL_PORT, REMOTE_PORT.
- . $srcdir\background.ps1 {
- ..\Debug\qpidd --auth=no --no-module-dir --port=0 --log-to-file qpidd.log $args | foreach { set-content qpidd.port $_ } }
+ . $srcdir\background.ps1 $cmdblock
while (!(Test-Path qpidd.port)) {
Start-Sleep 2
}
set-item -path env:LOCAL_PORT -value (get-content -path qpidd.port -totalcount 1)
Remove-Item qpidd.port
- . $srcdir\background.ps1 {
- ..\Debug\qpidd --auth=no --no-module-dir --port=0 --log-to-file qpidd.log $args | foreach { set-content qpidd.port $_ } }
+ . $srcdir\background.ps1 $cmdblock
while (!(Test-Path qpidd.port)) {
Start-Sleep 2
}
set-item -path env:REMOTE_PORT -value (get-content -path qpidd.port -totalcount 1)
}
-stop_brokers() {
- ..\Debug\qpidd -q --port $LOCAL_PORT | Out-Default
- ..\Debug\qpidd -q --port $REMOTE_PORT | Out-Default
+function stop_brokers {
+ Invoke-Expression "$prog -q --port $env:LOCAL_PORT" | Out-Default
+ Invoke-Expression "$prog -q --port $env:REMOTE_PORT" | Out-Default
+}
+
+trap {
+ &stop_brokers
+ break
}
-if (Test-Path $PYTHON_DIR -pathType Container) {
- start_brokers
- "Running federation tests using brokers on ports $LOCAL_PORT $REMOTE_PORT"
- $env:PYTHONPATH=$PYTHON_DIR
- $srcdir/federation.py -v -s $srcdir\..\..\..\specs\amqp.0-10-qpid-errata.xml -b localhost:$LOCAL_PORT --remote-port $REMOTE_PORT $args
- $RETCODE=$LASTEXITCODE
- stop_brokers
- if ($RETCODE != 0) {
- "FAIL federation tests"
- exit 1
- }
+&start_brokers
+"Running federation tests using brokers on ports $env:LOCAL_PORT $env:REMOTE_PORT"
+$env:PYTHONPATH=$PYTHON_DIR
+python $srcdir/federation.py -v -s $srcdir\..\..\..\specs\amqp.0-10-qpid-errata.xml -b localhost:$env:LOCAL_PORT --remote-port $env:REMOTE_PORT $args
+$RETCODE=$LASTEXITCODE
+&stop_brokers
+if ($RETCODE -ne 0) {
+ "FAIL federation tests"
+ exit 1
}
diff --git a/qpid/cpp/src/tests/run_header_test b/qpid/cpp/src/tests/run_header_test
index 414fecd28f..1b5a3963db 100755
--- a/qpid/cpp/src/tests/run_header_test
+++ b/qpid/cpp/src/tests/run_header_test
@@ -24,7 +24,7 @@
# in both directions
srcdir=`dirname $0`
-PYTHON_DIR=$srcdir/../../../python
+. `dirname $0`/python_env.sh
test -f qpidd.port && QPID_PORT=`cat qpidd.port`
if test -d ${PYTHON_DIR} ; then
diff --git a/qpid/cpp/src/tests/run_header_test.ps1 b/qpid/cpp/src/tests/run_header_test.ps1
index add680f569..c7bc2d788e 100644
--- a/qpid/cpp/src/tests/run_header_test.ps1
+++ b/qpid/cpp/src/tests/run_header_test.ps1
@@ -21,20 +21,33 @@
# TODO: this should be expanded to cover a wider set of types and go
# in both directions
-$srcdir = Split-Path $myInvocation.ScriptName
-$PYTHON_DIR = $srcdir\..\..\..\python
+$srcdir = Split-Path $myInvocation.InvocationName
+$PYTHON_DIR = "$srcdir\..\..\..\python"
+if (!(Test-Path $PYTHON_DIR -pathType Container)) {
+ "Skipping header test as python libs not found"
+ exit 0
+}
+
if (Test-Path qpidd.port) {
set-item -path env:QPID_PORT -value (get-content -path qpidd.port -totalcount 1)
}
-if (Test-Path $PYTHON_DIR -pathType Container) {
- ./header_test -p $QPID_PORT
- $env:PYTHONPATH="$PYTHON_DIR;$env:PYTHONPATH"
- $srcdir/header_test.py "localhost" $QPID_PORT
- exit $LASTEXITCODE
+# Test runs from the tests directory but the test executables are in a
+# subdirectory based on the build type. Look around for it before trying
+# to start it.
+$subs = "Debug","Release","MinSizeRel","RelWithDebInfo"
+foreach ($sub in $subs) {
+ $prog = ".\$sub\header_test.exe"
+ if (Test-Path $prog) {
+ break
+ }
}
-else {
- "Skipping header test as python libs not found"
- exit 0
+if (!(Test-Path $prog)) {
+ "Cannot locate header_test.exe"
+ exit 1
}
+Invoke-Expression "$prog -p $env:QPID_PORT" | Write-Output
+$env:PYTHONPATH="$PYTHON_DIR;$env:PYTHONPATH"
+Invoke-Expression "python $srcdir/header_test.py localhost $env:QPID_PORT" | Write-Output
+exit $LASTEXITCODE
diff --git a/qpid/cpp/src/tests/run_long_cluster_tests b/qpid/cpp/src/tests/run_long_cluster_tests
index bc1ae8a0c1..cb9c6b219b 100755
--- a/qpid/cpp/src/tests/run_long_cluster_tests
+++ b/qpid/cpp/src/tests/run_long_cluster_tests
@@ -19,4 +19,5 @@
# under the License.
#
-./run_cluster_tests long_cluster_tests
+srcdir=`dirname $0`
+$srcdir/run_cluster_tests long_cluster_tests
diff --git a/qpid/cpp/src/tests/run_ring_queue_test b/qpid/cpp/src/tests/run_ring_queue_test
index fb90075458..9cd3775de1 100755
--- a/qpid/cpp/src/tests/run_ring_queue_test
+++ b/qpid/cpp/src/tests/run_ring_queue_test
@@ -22,9 +22,8 @@
#setup path to find qpid-config and sender/receiver test progs
srcdir=`dirname $0`
-PYTHON_DIR=$srcdir/../../../python
-export PYTHONPATH=$PYTHON_DIR
-export PATH=./:$PYTHON_DIR/commands:$PATH
+. `dirname $0`/python_env.sh
+export PATH=$PWD:$srcdir:$PYTHON_COMMANDS:$PATH
#set port to connect to via env var
test -s qpidd.port && QPID_PORT=`cat qpidd.port`
diff --git a/qpid/cpp/src/tests/run_test.ps1 b/qpid/cpp/src/tests/run_test.ps1
index ebbef07f1d..551368bc9b 100644
--- a/qpid/cpp/src/tests/run_test.ps1
+++ b/qpid/cpp/src/tests/run_test.ps1
@@ -52,7 +52,6 @@ if (Test-Path qpidd.port) {
set-item -path env:QPID_PORT -value (get-content -path qpidd.port -totalcount 1)
}
-#$p = new-object System.Diagnostics.Process
$si = new-object System.Diagnostics.ProcessStartInfo
$si.WorkingDirectory = $pwd
$si.UseShellExecute = $true
@@ -67,6 +66,6 @@ else {
$si.Arguments = $args[1..$args.length-1]
}
}
-$p = [diagnostics.process]::Start($si)
+$p = [System.Diagnostics.Process]::Start($si)
$p.WaitForExit()
exit $?
diff --git a/qpid/cpp/src/tests/start_broker.ps1 b/qpid/cpp/src/tests/start_broker.ps1
index f2aa20439a..9263262b9f 100644
--- a/qpid/cpp/src/tests/start_broker.ps1
+++ b/qpid/cpp/src/tests/start_broker.ps1
@@ -28,9 +28,26 @@ function Get-ScriptPath
if (Test-Path qpidd.port) {
Remove-Item qpidd.port
}
+
+# Test runs from the tests directory but the broker executable is one level
+# up, and most likely in a subdirectory from there based on what build type.
+# Look around for it before trying to start it.
+$subs = "Debug","Release","MinSizeRel","RelWithDebInfo"
+foreach ($sub in $subs) {
+ $prog = "..\$sub\qpidd.exe"
+ if (Test-Path $prog) {
+ break
+ }
+}
+if (!(Test-Path $prog)) {
+ "Cannot locate qpidd.exe"
+ exit 1
+}
+$cmdline = "$prog --auth=no --no-module-dir --port=0 --log-to-file qpidd.log $args | foreach { set-content qpidd.port `$_ }"
+$cmdblock = $executioncontext.invokecommand.NewScriptBlock($cmdline)
$srcdir = Get-ScriptPath
-. $srcdir\background.ps1 {
- ..\Debug\qpidd --auth=no --no-module-dir --port=0 --log-to-file qpidd.log $args | foreach { set-content qpidd.port $_ } }
+. $srcdir\background.ps1 $cmdblock
+
$wait_time = 0
while (!(Test-Path qpidd.port) -and ($wait_time -lt 10)) {
Start-Sleep 2
diff --git a/qpid/cpp/src/tests/start_cluster b/qpid/cpp/src/tests/start_cluster
index 585ba082d5..fb3d27373a 100755
--- a/qpid/cpp/src/tests/start_cluster
+++ b/qpid/cpp/src/tests/start_cluster
@@ -23,20 +23,17 @@
#
# Execute command with the ais group set.
-with_ais_group() {
- id -nG | grep '\<ais\>' >/dev/null || { echo "You are not a member of the ais group." 1>&2; exit 1; }
- echo $* | newgrp ais
-}
+. `dirname $0`/ais_check
rm -f cluster*.log cluster.ports qpidd.port
SIZE=${1:-3}; shift
CLUSTER=`pwd` # Cluster name=pwd, avoid clashes.
-OPTS="-d --no-module-dir --load-module ../.libs/cluster.so --cluster-name=$CLUSTER --auth=no $@"
+OPTS="-d --no-module-dir --load-module ../.libs/cluster.so --cluster-name=$CLUSTER --auth=no --log-enable notice+ --log-enable debug+:cluster $@"
for (( i=0; i<SIZE; ++i )); do
DDIR=`mktemp -d /tmp/start_cluster.XXXXXXXXXX`
- PORT=`with_ais_group ../qpidd -p0 --log-to-file=cluster$i.log $OPTS --data-dir=$DDIR` || exit 1
+ PORT=`with_ais_group ../qpidd -p0 --log-to-file=cluster$i.log $OPTS --data-dir=$DDIR` || exit 1
echo $PORT >> cluster.ports
done
diff --git a/qpid/cpp/src/tests/stop_broker.ps1 b/qpid/cpp/src/tests/stop_broker.ps1
index 165c7a63b0..4fdeb26e2b 100644
--- a/qpid/cpp/src/tests/stop_broker.ps1
+++ b/qpid/cpp/src/tests/stop_broker.ps1
@@ -21,8 +21,23 @@
Get-Content -path qpidd.port -totalCount 1 | Set-Variable -name qpid_port
Remove-Item qpidd.port
+# Test runs from the tests directory but the broker executable is one level
+# up, and most likely in a subdirectory from there based on what build type.
+# Look around for it before trying to start it.
+$subs = "Debug","Release","MinSizeRel","RelWithDebInfo"
+foreach ($sub in $subs) {
+ $prog = "..\$sub\qpidd.exe"
+ if (Test-Path $prog) {
+ break
+ }
+}
+if (!(Test-Path $prog)) {
+ "Cannot locate qpidd.exe"
+ exit 1
+}
+
# Piping the output makes the script wait for qpidd to finish.
-..\Debug\qpidd --quit --port $qpid_port | Write-Output
+Invoke-Expression "$prog --quit --port $qpid_port" | Write-Output
$stopped = $?
# Check qpidd.log.
diff --git a/qpid/cpp/src/tests/test_store.cpp b/qpid/cpp/src/tests/test_store.cpp
index 64a96bf71a..f2d3aa65a3 100644
--- a/qpid/cpp/src/tests/test_store.cpp
+++ b/qpid/cpp/src/tests/test_store.cpp
@@ -140,7 +140,8 @@ struct TestStorePlugin : public Plugin {
{
Broker* broker = dynamic_cast<Broker*>(&target);
if (!broker) return;
- broker->setStore (new TestStore(options.name, *broker));
+ boost::shared_ptr<MessageStore> p(new TestStore(options.name, *broker));
+ broker->setStore (p);
}
void initialize(qpid::Plugin::Target&) {}
diff --git a/qpid/cpp/src/tests/topictest.ps1 b/qpid/cpp/src/tests/topictest.ps1
index 04dae23ad9..58ae50c67c 100644
--- a/qpid/cpp/src/tests/topictest.ps1
+++ b/qpid/cpp/src/tests/topictest.ps1
@@ -19,9 +19,6 @@
# Run the C++ topic test
-# Clean up old log files
-Get-Item subscriber_*.log | Remove-Item
-
# Parameters with default values: s (subscribers) m (messages) b (batches)
# h (host) t (false; use transactions)
param (
@@ -32,23 +29,28 @@ param (
[switch] $t # transactional
)
+# Clean up old log files
+Get-Item subscriber_*.log | Remove-Item
+
+if ($t) {
+ $transactional = "--transactional --durable"
+}
+
function subscribe {
- "Start subscriber $args[0]"
- $LOG = "subscriber_$args[0].log"
- . $srcdir\background.ps1 {
- $env:OUTDIR\topic_listener $TRANSACTIONAL > $LOG 2>&1
- if ($LastExitCode -ne 0) { Remove-Item $LOG }
- } -inconsole
+ param ([int]$num)
+ "Start subscriber $num"
+ $LOG = "subscriber_$num.log"
+ $cmdline = "$env:OUTDIR\topic_listener $transactional > $LOG 2>&1
+ if (`$LastExitCode -ne 0) { Remove-Item $LOG }"
+ $cmdblock = $executioncontext.invokecommand.NewScriptBlock($cmdline)
+ . $srcdir\background.ps1 $cmdblock
}
-publish() {
- if ($t) {
- $transactional = "--transactional --durable"
- }
- $env:OUTDIR\topic_publisher --messages $messages --batches $batches --subscribers $subscribers $host $transactional 2>&1
+function publish {
+ Invoke-Expression "$env:OUTDIR\topic_publisher --messages $messages --batches $batches --subscribers $subscribers $host $transactional" 2>&1
}
-$srcdir = Split-Path $myInvocation.ScriptName
+$srcdir = Split-Path $MyInvocation.MyCommand.Path
if ($broker.length) {
$broker = "-h$broker"
}
diff --git a/qpid/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp b/qpid/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp
index d51ed90758..a0b665db73 100644
--- a/qpid/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp
+++ b/qpid/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp
@@ -28,9 +28,23 @@
#include <crtdbg.h>
#include <windows.h>
+#include <iostream>
namespace {
+// Instead of popping up a window for exceptions, just print something out
+LONG _stdcall UnhandledExceptionFilter (PEXCEPTION_POINTERS pExceptionInfo)
+{
+ DWORD dwExceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode;
+
+ if (dwExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+ std::cerr << "\nERROR: ACCESS VIOLATION\n" << std::endl;
+ else
+ std::cerr << "\nERROR: UNHANDLED EXCEPTION\n" << std::endl;
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
struct redirect_errors_to_stderr {
redirect_errors_to_stderr ();
};
@@ -50,6 +64,9 @@ redirect_errors_to_stderr::redirect_errors_to_stderr()
// and can't-open-file message boxes.
SetErrorMode(SEM_FAILCRITICALERRORS);
SetErrorMode(SEM_NOOPENFILEERRORBOX);
+
+ // And this will catch all unhandled exceptions.
+ SetUnhandledExceptionFilter (&UnhandledExceptionFilter);
}
} // namespace
diff --git a/qpid/cpp/src/windows/QpiddBroker.cpp b/qpid/cpp/src/windows/QpiddBroker.cpp
index 5c6eef48f8..5bf9477e6a 100644
--- a/qpid/cpp/src/windows/QpiddBroker.cpp
+++ b/qpid/cpp/src/windows/QpiddBroker.cpp
@@ -133,6 +133,14 @@ void ShutdownHandler::run() {
}
}
+// Console control handler to properly handle ctl-c.
+BOOL CtrlHandler(DWORD ctl)
+{
+ ShutdownEvent shutter; // no pid specified == shut me down
+ shutter.signal();
+ return ((ctl == CTRL_C_EVENT || ctl == CTRL_CLOSE_EVENT) ? TRUE : FALSE);
+}
+
}
struct ProcessControlOptions : public qpid::Options {
@@ -245,6 +253,7 @@ int QpiddBroker::execute (QpiddOptions *options) {
ShutdownHandler waitShut(brokerPtr);
qpid::sys::Thread waitThr(waitShut); // Wait for shutdown event
+ SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE);
brokerPtr->run();
waitShut.signal(); // In case we shut down some other way
waitThr.join();