summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorStephen D. Huston <shuston@apache.org>2011-10-21 01:19:00 +0000
committerStephen D. Huston <shuston@apache.org>2011-10-21 01:19:00 +0000
commitebfd9ff053b04ab379acfc0fefedee5a31b6d8a5 (patch)
treedcfb94e75656c6c239fc3dcb754cd2015126424d /cpp
parent5eb354b338bb8d8fcd35b6ac3fb33f8103e757c3 (diff)
downloadqpid-python-ebfd9ff053b04ab379acfc0fefedee5a31b6d8a5.tar.gz
Undo bad merge from trunk - merged at wrong level.
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-2519@1187150 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp')
-rw-r--r--cpp/CMakeLists.txt1
-rw-r--r--cpp/INSTALL20
-rw-r--r--cpp/INSTALL-WINDOWS11
-rw-r--r--cpp/Makefile.am4
-rw-r--r--cpp/bindings/qmf/python/Makefile.am4
-rw-r--r--cpp/bindings/qmf/ruby/Makefile.am4
-rw-r--r--cpp/bindings/qmf/tests/test_base.rb3
-rw-r--r--cpp/bindings/qmf2/examples/cpp/Makefile.am5
-rw-r--r--cpp/bindings/qmf2/examples/cpp/event_driven_list_agents.cpp107
-rw-r--r--cpp/bindings/qmf2/python/Makefile.am4
-rw-r--r--cpp/bindings/qmf2/qmf2.i1
-rw-r--r--cpp/bindings/qmf2/ruby/Makefile.am4
-rw-r--r--cpp/bindings/qpid/CMakeLists.txt41
-rw-r--r--cpp/bindings/qpid/Makefile.am2
-rw-r--r--cpp/bindings/qpid/dotnet/configure-windows.ps1108
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.direct.receiver/Properties/AssemblyInfo.cs16
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.direct.sender/Properties/AssemblyInfo.cs16
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/Properties/AssemblyInfo.cs12
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.map.callback.sender/Properties/AssemblyInfo.cs2
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.map.receiver/Properties/AssemblyInfo.cs16
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.map.sender/Properties/AssemblyInfo.cs16
-rw-r--r--cpp/bindings/qpid/dotnet/examples/visualbasic.example.client/MyProject/AssemblyInfo.vb30
-rw-r--r--cpp/bindings/qpid/dotnet/org.apache.qpid.messaging.sessionreceiver.sln6
-rw-r--r--cpp/bindings/qpid/dotnet/src/Address.cpp24
-rw-r--r--cpp/bindings/qpid/dotnet/src/Address.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Connection.cpp24
-rw-r--r--cpp/bindings/qpid/dotnet/src/Connection.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Duration.h12
-rw-r--r--cpp/bindings/qpid/dotnet/src/FailoverUpdates.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Message.cpp26
-rw-r--r--cpp/bindings/qpid/dotnet/src/Message.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Receiver.cpp25
-rw-r--r--cpp/bindings/qpid/dotnet/src/Receiver.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Sender.cpp25
-rw-r--r--cpp/bindings/qpid/dotnet/src/Sender.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Session.cpp51
-rw-r--r--cpp/bindings/qpid/dotnet/src/Session.h3
-rw-r--r--cpp/bindings/qpid/dotnet/test/messaging.test/Properties/AssemblyInfo.cs16
-rw-r--r--cpp/bindings/qpid/examples/perl/client.pl8
-rw-r--r--cpp/bindings/qpid/examples/perl/drain.pl12
-rw-r--r--cpp/bindings/qpid/examples/perl/hello_world.pl10
-rw-r--r--cpp/bindings/qpid/examples/perl/hello_xml.pl6
-rw-r--r--cpp/bindings/qpid/examples/perl/map_receiver.pl8
-rw-r--r--cpp/bindings/qpid/examples/perl/map_sender.pl8
-rw-r--r--cpp/bindings/qpid/examples/perl/server.pl6
-rw-r--r--cpp/bindings/qpid/examples/perl/spout.pl10
-rw-r--r--cpp/bindings/qpid/perl/CMakeLists.txt38
-rw-r--r--cpp/bindings/qpid/perl/Makefile.am22
-rw-r--r--cpp/bindings/qpid/perl/perl.i2
-rw-r--r--cpp/bindings/qpid/python/CMakeLists.txt45
-rw-r--r--cpp/bindings/qpid/python/Makefile.am6
-rw-r--r--cpp/bindings/qpid/python/python.i338
-rw-r--r--cpp/bindings/qpid/qpid.i3
-rw-r--r--cpp/bindings/qpid/ruby/.gitignore2
-rw-r--r--cpp/bindings/qpid/ruby/CMakeLists.txt63
-rw-r--r--cpp/bindings/qpid/ruby/LICENSE234
-rw-r--r--cpp/bindings/qpid/ruby/Makefile.am6
-rw-r--r--cpp/bindings/qpid/ruby/README.rdoc45
-rw-r--r--cpp/bindings/qpid/ruby/Rakefile130
-rw-r--r--cpp/bindings/qpid/ruby/TODO7
-rw-r--r--cpp/bindings/qpid/ruby/examples/client.rb50
-rw-r--r--cpp/bindings/qpid/ruby/examples/drain.rb111
-rw-r--r--cpp/bindings/qpid/ruby/examples/hello_world.rb49
-rw-r--r--cpp/bindings/qpid/ruby/examples/map_receiver.rb63
-rw-r--r--cpp/bindings/qpid/ruby/examples/map_sender.rb52
-rw-r--r--cpp/bindings/qpid/ruby/examples/server.rb51
-rw-r--r--cpp/bindings/qpid/ruby/examples/spout.rb126
-rw-r--r--cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb73
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid.rb29
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/address.rb125
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/connection.rb134
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/duration.rb63
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/encoding.rb56
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/errors.rb30
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/message.rb157
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/receiver.rb102
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/sender.rb82
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/session.rb186
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/version.rb31
-rw-r--r--cpp/bindings/qpid/ruby/test/lib/setup.rb29
-rw-r--r--cpp/bindings/qpid/ruby/test/test_address.rb39
-rw-r--r--cpp/bindings/qpid/ruby/test/test_connection.rb257
-rw-r--r--cpp/bindings/qpid/ruby/test/test_encoding.rb146
-rw-r--r--cpp/bindings/qpid/ruby/test/test_message.rb353
-rw-r--r--cpp/bindings/qpid/ruby/test/test_receiver.rb238
-rw-r--r--cpp/bindings/qpid/ruby/test/test_sender.rb183
-rw-r--r--cpp/bindings/qpid/ruby/test/test_session.rb445
-rw-r--r--cpp/bindings/qpid/ruby/test/ts_bindings.rb30
-rw-r--r--cpp/bindings/swig_python_typemaps.i56
-rw-r--r--cpp/bindings/swig_ruby_typemaps.i2
-rw-r--r--cpp/bld-winsdk.ps13
-rw-r--r--cpp/configure.ac21
-rw-r--r--cpp/design_docs/hot-standby-design.txt239
-rw-r--r--cpp/design_docs/new-cluster-design.txt285
-rw-r--r--cpp/design_docs/new-cluster-plan.txt545
-rw-r--r--cpp/docs/api/developer.doxygen.in2
-rw-r--r--cpp/docs/api/doxygen_mainpage.h41
-rw-r--r--cpp/docs/api/footer.html2
-rw-r--r--cpp/docs/api/user.doxygen.in2
-rw-r--r--cpp/docs/man/Makefile.am23
-rw-r--r--cpp/docs/man/qpidd.1247
-rw-r--r--cpp/docs/man/qpidd.x2
-rw-r--r--cpp/etc/Makefile.am23
-rw-r--r--cpp/etc/qpidd.conf2
-rw-r--r--cpp/etc/sasl2/qpidd.conf5
-rw-r--r--cpp/examples/CMakeLists.txt13
-rw-r--r--cpp/examples/Makefile.am16
-rw-r--r--cpp/examples/README.verify (renamed from cpp/examples/old_api/README.verify)0
-rw-r--r--cpp/examples/direct/CMakeLists.txt (renamed from cpp/examples/old_api/direct/CMakeLists.txt)0
-rw-r--r--cpp/examples/direct/Makefile.am (renamed from cpp/examples/old_api/direct/Makefile.am)2
-rw-r--r--cpp/examples/direct/declare_queues.cpp (renamed from cpp/examples/old_api/direct/declare_queues.cpp)0
-rw-r--r--cpp/examples/direct/direct_declare_queues.vcproj (renamed from cpp/examples/old_api/direct/direct_declare_queues.vcproj)0
-rw-r--r--cpp/examples/direct/direct_direct_producer.vcproj (renamed from cpp/examples/old_api/direct/direct_direct_producer.vcproj)0
-rw-r--r--cpp/examples/direct/direct_listener.vcproj (renamed from cpp/examples/old_api/direct/direct_listener.vcproj)0
-rw-r--r--cpp/examples/direct/direct_producer.cpp (renamed from cpp/examples/old_api/direct/direct_producer.cpp)0
-rw-r--r--cpp/examples/direct/listener.cpp (renamed from cpp/examples/old_api/direct/listener.cpp)0
-rw-r--r--cpp/examples/direct/verify (renamed from cpp/examples/old_api/direct/verify)0
-rw-r--r--cpp/examples/direct/verify.in (renamed from cpp/examples/old_api/direct/verify.in)0
-rw-r--r--cpp/examples/examples.sln24
-rw-r--r--cpp/examples/failover/CMakeLists.txt (renamed from cpp/examples/old_api/failover/CMakeLists.txt)0
-rw-r--r--cpp/examples/failover/Makefile.am (renamed from cpp/examples/old_api/failover/Makefile.am)2
-rw-r--r--cpp/examples/failover/declare_queues.cpp (renamed from cpp/examples/old_api/failover/declare_queues.cpp)0
-rw-r--r--cpp/examples/failover/failover_declare_queues.vcproj (renamed from cpp/examples/old_api/failover/failover_declare_queues.vcproj)0
-rw-r--r--cpp/examples/failover/failover_replaying_sender.vcproj (renamed from cpp/examples/old_api/failover/failover_replaying_sender.vcproj)0
-rw-r--r--cpp/examples/failover/failover_resuming_receiver.vcproj (renamed from cpp/examples/old_api/failover/failover_resuming_receiver.vcproj)0
-rw-r--r--cpp/examples/failover/replaying_sender.cpp (renamed from cpp/examples/old_api/failover/replaying_sender.cpp)0
-rw-r--r--cpp/examples/failover/resuming_receiver.cpp (renamed from cpp/examples/old_api/failover/resuming_receiver.cpp)0
-rw-r--r--cpp/examples/fanout/CMakeLists.txt (renamed from cpp/examples/old_api/fanout/CMakeLists.txt)0
-rw-r--r--cpp/examples/fanout/Makefile.am (renamed from cpp/examples/old_api/fanout/Makefile.am)2
-rw-r--r--cpp/examples/fanout/fanout_fanout_producer.vcproj (renamed from cpp/examples/old_api/fanout/fanout_fanout_producer.vcproj)0
-rw-r--r--cpp/examples/fanout/fanout_listener.vcproj (renamed from cpp/examples/old_api/fanout/fanout_listener.vcproj)0
-rw-r--r--cpp/examples/fanout/fanout_producer.cpp (renamed from cpp/examples/old_api/fanout/fanout_producer.cpp)0
-rw-r--r--cpp/examples/fanout/listener.cpp (renamed from cpp/examples/old_api/fanout/listener.cpp)0
-rw-r--r--cpp/examples/fanout/verify (renamed from cpp/examples/old_api/fanout/verify)0
-rw-r--r--cpp/examples/fanout/verify.in (renamed from cpp/examples/old_api/fanout/verify.in)0
-rw-r--r--cpp/examples/messaging/drain.cpp4
-rw-r--r--cpp/examples/messaging/server.cpp4
-rw-r--r--cpp/examples/messaging/spout.cpp2
-rw-r--r--cpp/examples/old-examples.sln (renamed from cpp/examples/old_api/old-examples.sln)24
-rw-r--r--cpp/examples/old_api/CMakeLists.txt25
-rw-r--r--cpp/examples/old_api/Makefile.am48
-rw-r--r--cpp/examples/pub-sub/CMakeLists.txt (renamed from cpp/examples/old_api/pub-sub/CMakeLists.txt)0
-rw-r--r--cpp/examples/pub-sub/Makefile.am (renamed from cpp/examples/old_api/pub-sub/Makefile.am)2
-rw-r--r--cpp/examples/pub-sub/pub-sub_topic_listener.vcproj (renamed from cpp/examples/old_api/pub-sub/pub-sub_topic_listener.vcproj)0
-rw-r--r--cpp/examples/pub-sub/pub-sub_topic_publisher.vcproj (renamed from cpp/examples/old_api/pub-sub/pub-sub_topic_publisher.vcproj)0
-rw-r--r--cpp/examples/pub-sub/topic_listener.cpp (renamed from cpp/examples/old_api/pub-sub/topic_listener.cpp)0
-rw-r--r--cpp/examples/pub-sub/topic_publisher.cpp (renamed from cpp/examples/old_api/pub-sub/topic_publisher.cpp)0
-rw-r--r--cpp/examples/pub-sub/verify (renamed from cpp/examples/old_api/pub-sub/verify)0
-rw-r--r--cpp/examples/pub-sub/verify.in (renamed from cpp/examples/old_api/pub-sub/verify.in)0
-rw-r--r--cpp/examples/qmf-console/ping.cpp4
-rw-r--r--cpp/examples/qmf-console/printevents.cpp4
-rw-r--r--cpp/examples/request-response/CMakeLists.txt (renamed from cpp/examples/old_api/request-response/CMakeLists.txt)0
-rw-r--r--cpp/examples/request-response/Makefile.am (renamed from cpp/examples/old_api/request-response/Makefile.am)2
-rw-r--r--cpp/examples/request-response/client.cpp (renamed from cpp/examples/old_api/request-response/client.cpp)0
-rw-r--r--cpp/examples/request-response/request-response_client.vcproj (renamed from cpp/examples/old_api/request-response/request-response_client.vcproj)0
-rw-r--r--cpp/examples/request-response/request-response_server.vcproj (renamed from cpp/examples/old_api/request-response/request-response_server.vcproj)0
-rw-r--r--cpp/examples/request-response/server.cpp (renamed from cpp/examples/old_api/request-response/server.cpp)0
-rw-r--r--cpp/examples/request-response/verify (renamed from cpp/examples/old_api/request-response/verify)0
-rw-r--r--cpp/examples/request-response/verify.in (renamed from cpp/examples/old_api/request-response/verify.in)0
-rw-r--r--cpp/examples/tradedemo/CMakeLists.txt (renamed from cpp/examples/old_api/tradedemo/CMakeLists.txt)0
-rw-r--r--cpp/examples/tradedemo/Makefile.am (renamed from cpp/examples/old_api/tradedemo/Makefile.am)2
-rw-r--r--cpp/examples/tradedemo/declare_queues.cpp (renamed from cpp/examples/old_api/tradedemo/declare_queues.cpp)0
-rw-r--r--cpp/examples/tradedemo/topic_listener.cpp (renamed from cpp/examples/old_api/tradedemo/topic_listener.cpp)0
-rw-r--r--cpp/examples/tradedemo/topic_publisher.cpp (renamed from cpp/examples/old_api/tradedemo/topic_publisher.cpp)0
-rw-r--r--cpp/examples/tradedemo/tradedemo_declare_queues.vcproj (renamed from cpp/examples/old_api/tradedemo/tradedemo_declare_queues.vcproj)0
-rw-r--r--cpp/examples/tradedemo/tradedemo_topic_listener.vcproj (renamed from cpp/examples/old_api/tradedemo/tradedemo_topic_listener.vcproj)0
-rw-r--r--cpp/examples/tradedemo/tradedemo_topic_publisher.vcproj (renamed from cpp/examples/old_api/tradedemo/tradedemo_topic_publisher.vcproj)0
-rwxr-xr-xcpp/examples/verify (renamed from cpp/examples/old_api/verify)0
-rwxr-xr-xcpp/examples/verify_all (renamed from cpp/examples/old_api/verify_all)2
-rw-r--r--cpp/examples/xml-exchange/CMakeLists.txt (renamed from cpp/examples/old_api/xml-exchange/CMakeLists.txt)0
-rw-r--r--cpp/examples/xml-exchange/Makefile.am (renamed from cpp/examples/old_api/xml-exchange/Makefile.am)2
-rw-r--r--cpp/examples/xml-exchange/README.txt (renamed from cpp/examples/old_api/xml-exchange/README.txt)0
-rw-r--r--cpp/examples/xml-exchange/declare_queues.cpp (renamed from cpp/examples/old_api/xml-exchange/declare_queues.cpp)0
-rw-r--r--cpp/examples/xml-exchange/listener.cpp (renamed from cpp/examples/old_api/xml-exchange/listener.cpp)0
-rw-r--r--cpp/examples/xml-exchange/xml_producer.cpp (renamed from cpp/examples/old_api/xml-exchange/xml_producer.cpp)0
-rw-r--r--cpp/include/qmf/Agent.h2
-rw-r--r--cpp/include/qmf/AgentEvent.h2
-rw-r--r--cpp/include/qmf/AgentSession.h48
-rw-r--r--cpp/include/qmf/ConsoleEvent.h2
-rw-r--r--cpp/include/qmf/ConsoleSession.h55
-rw-r--r--cpp/include/qmf/Data.h2
-rw-r--r--cpp/include/qmf/DataAddr.h5
-rw-r--r--cpp/include/qmf/Handle.h10
-rw-r--r--cpp/include/qmf/ImportExport.h16
-rw-r--r--cpp/include/qmf/Query.h4
-rw-r--r--cpp/include/qmf/Schema.h2
-rw-r--r--cpp/include/qmf/SchemaId.h2
-rw-r--r--cpp/include/qmf/SchemaMethod.h2
-rw-r--r--cpp/include/qmf/SchemaProperty.h2
-rw-r--r--cpp/include/qmf/Subscription.h4
-rw-r--r--cpp/include/qmf/engine/QmfEngineImportExport.h9
-rw-r--r--cpp/include/qmf/exceptions.h8
-rw-r--r--cpp/include/qmf/posix/EventNotifier.h63
-rwxr-xr-xcpp/include/qpid/Address.h2
-rw-r--r--cpp/include/qpid/CommonImportExport.h14
-rw-r--r--cpp/include/qpid/Exception.h12
-rw-r--r--cpp/include/qpid/ImportExport.h71
-rw-r--r--cpp/include/qpid/Msg.h1
-rw-r--r--cpp/include/qpid/Options.h88
-rw-r--r--cpp/include/qpid/Url.h2
-rw-r--r--cpp/include/qpid/agent/ManagementAgent.h4
-rw-r--r--cpp/include/qpid/agent/QmfAgentImportExport.h16
-rw-r--r--cpp/include/qpid/amqp_0_10/Codecs.h20
-rw-r--r--cpp/include/qpid/client/ClientImportExport.h14
-rw-r--r--cpp/include/qpid/client/Completion.h2
-rw-r--r--cpp/include/qpid/client/Connection.h10
-rw-r--r--cpp/include/qpid/client/ConnectionSettings.h2
-rw-r--r--cpp/include/qpid/client/FailoverListener.h2
-rw-r--r--cpp/include/qpid/client/FailoverManager.h2
-rw-r--r--cpp/include/qpid/client/Future.h2
-rw-r--r--cpp/include/qpid/client/FutureResult.h2
-rw-r--r--cpp/include/qpid/client/Handle.h10
-rw-r--r--cpp/include/qpid/client/LocalQueue.h2
-rw-r--r--cpp/include/qpid/client/Message.h2
-rw-r--r--cpp/include/qpid/client/MessageListener.h2
-rw-r--r--cpp/include/qpid/client/MessageReplayTracker.h2
-rw-r--r--cpp/include/qpid/client/QueueOptions.h2
-rw-r--r--cpp/include/qpid/client/SessionBase_0_10.h2
-rw-r--r--cpp/include/qpid/client/Subscription.h8
-rw-r--r--cpp/include/qpid/client/SubscriptionManager.h2
-rw-r--r--cpp/include/qpid/console/Agent.h14
-rw-r--r--cpp/include/qpid/console/Broker.h16
-rw-r--r--cpp/include/qpid/console/ClassKey.h30
-rw-r--r--cpp/include/qpid/console/ConsoleImportExport.h14
-rw-r--r--cpp/include/qpid/console/ObjectId.h8
-rw-r--r--cpp/include/qpid/framing/Array.h26
-rw-r--r--cpp/include/qpid/framing/Buffer.h16
-rw-r--r--cpp/include/qpid/framing/FieldTable.h6
-rw-r--r--cpp/include/qpid/framing/FieldValue.h21
-rw-r--r--cpp/include/qpid/framing/List.h25
-rw-r--r--cpp/include/qpid/framing/ProtocolVersion.h12
-rw-r--r--cpp/include/qpid/framing/SequenceNumber.h2
-rw-r--r--cpp/include/qpid/framing/SequenceSet.h2
-rw-r--r--cpp/include/qpid/framing/StructHelper.h2
-rw-r--r--cpp/include/qpid/framing/Uuid.h10
-rw-r--r--cpp/include/qpid/log/Logger.h6
-rw-r--r--cpp/include/qpid/log/Options.h2
-rw-r--r--cpp/include/qpid/management/ManagementObject.h18
-rw-r--r--cpp/include/qpid/messaging/Address.h2
-rw-r--r--cpp/include/qpid/messaging/Connection.h30
-rw-r--r--cpp/include/qpid/messaging/Duration.h8
-rw-r--r--cpp/include/qpid/messaging/FailoverUpdates.h2
-rw-r--r--cpp/include/qpid/messaging/Handle.h10
-rw-r--r--cpp/include/qpid/messaging/ImportExport.h14
-rw-r--r--cpp/include/qpid/messaging/Message.h101
-rw-r--r--cpp/include/qpid/messaging/Receiver.h2
-rw-r--r--cpp/include/qpid/messaging/Sender.h2
-rw-r--r--cpp/include/qpid/messaging/Session.h51
-rw-r--r--cpp/include/qpid/messaging/exceptions.h98
-rw-r--r--cpp/include/qpid/sys/ExceptionHolder.h13
-rwxr-xr-xcpp/include/qpid/sys/IntegerTypes.h2
-rw-r--r--cpp/include/qpid/sys/Runnable.h2
-rw-r--r--cpp/include/qpid/sys/Thread.h6
-rw-r--r--cpp/include/qpid/sys/Time.h5
-rwxr-xr-xcpp/include/qpid/sys/windows/IntegerTypes.h6
-rw-r--r--cpp/include/qpid/types/Exception.h2
-rw-r--r--cpp/include/qpid/types/ImportExport.h14
-rw-r--r--cpp/include/qpid/types/Uuid.h2
-rw-r--r--cpp/include/qpid/types/Variant.h6
-rw-r--r--cpp/managementgen/Makefile.am12
-rwxr-xr-xcpp/managementgen/qmfgen/schema.py4
-rwxr-xr-xcpp/rubygen/0-10/specification.rb2
-rwxr-xr-xcpp/rubygen/MethodBodyDefaultVisitor.rb2
-rwxr-xr-xcpp/rubygen/amqpgen.rb6
-rwxr-xr-xcpp/rubygen/cppgen.rb3
-rwxr-xr-xcpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb2
-rwxr-xr-xcpp/rubygen/framing.0-10/OperationsInvoker.rb2
-rwxr-xr-xcpp/rubygen/framing.0-10/Proxy.rb4
-rwxr-xr-xcpp/rubygen/framing.0-10/Session.rb4
-rwxr-xr-xcpp/rubygen/framing.0-10/structs.rb2
-rw-r--r--cpp/src/CMakeLists.txt128
-rw-r--r--cpp/src/CMakeWinVersions.cmake12
-rw-r--r--cpp/src/Makefile.am55
-rw-r--r--cpp/src/acl.mk4
-rw-r--r--cpp/src/cluster.mk6
-rw-r--r--cpp/src/posix/QpiddBroker.cpp12
-rw-r--r--cpp/src/qmf.mk9
-rw-r--r--cpp/src/qmf/Agent.cpp29
-rw-r--r--cpp/src/qmf/AgentImpl.h1
-rw-r--r--cpp/src/qmf/AgentSession.cpp229
-rw-r--r--cpp/src/qmf/AgentSessionImpl.h175
-rw-r--r--cpp/src/qmf/ConsoleSession.cpp125
-rw-r--r--cpp/src/qmf/ConsoleSessionImpl.h22
-rw-r--r--cpp/src/qmf/DataAddr.cpp6
-rw-r--r--cpp/src/qmf/DataAddrImpl.h4
-rw-r--r--cpp/src/qmf/EventNotifierImpl.cpp56
-rw-r--r--cpp/src/qmf/PosixEventNotifier.cpp65
-rw-r--r--cpp/src/qmf/PosixEventNotifierImpl.cpp112
-rw-r--r--cpp/src/qmf/PosixEventNotifierImpl.h61
-rw-r--r--cpp/src/qmf/PrivateImplRef.h2
-rw-r--r--cpp/src/qmf/engine/ResilientConnection.cpp6
-rw-r--r--cpp/src/qmf/engine/SchemaImpl.cpp11
-rw-r--r--cpp/src/qmf/engine/SchemaImpl.h7
-rw-r--r--cpp/src/qpid/Address.cpp8
-rw-r--r--cpp/src/qpid/BufferRef.h70
-rw-r--r--cpp/src/qpid/Exception.cpp16
-rw-r--r--cpp/src/qpid/Modules.cpp3
-rw-r--r--cpp/src/qpid/Options.cpp269
-rw-r--r--cpp/src/qpid/RefCounted.h6
-rw-r--r--cpp/src/qpid/RefCountedBuffer.cpp29
-rw-r--r--cpp/src/qpid/RefCountedBuffer.h61
-rw-r--r--cpp/src/qpid/Sasl.h4
-rw-r--r--cpp/src/qpid/SaslFactory.cpp28
-rw-r--r--cpp/src/qpid/Url.cpp23
-rw-r--r--cpp/src/qpid/acl/Acl.cpp5
-rw-r--r--cpp/src/qpid/acl/AclPlugin.cpp2
-rw-r--r--cpp/src/qpid/agent/ManagementAgentImpl.cpp361
-rw-r--r--cpp/src/qpid/agent/ManagementAgentImpl.h4
-rw-r--r--cpp/src/qpid/amqp_0_10/Codecs.cpp6
-rw-r--r--cpp/src/qpid/amqp_0_10/SessionHandler.cpp8
-rw-r--r--cpp/src/qpid/amqp_0_10/SessionHandler.h6
-rw-r--r--cpp/src/qpid/broker/AsyncCompletion.h201
-rw-r--r--cpp/src/qpid/broker/Bridge.cpp6
-rw-r--r--cpp/src/qpid/broker/Bridge.h2
-rw-r--r--cpp/src/qpid/broker/Broker.cpp566
-rw-r--r--cpp/src/qpid/broker/Broker.h107
-rw-r--r--cpp/src/qpid/broker/BrokerImportExport.h23
-rw-r--r--cpp/src/qpid/broker/Connection.cpp57
-rw-r--r--cpp/src/qpid/broker/Connection.h9
-rw-r--r--cpp/src/qpid/broker/ConnectionHandler.cpp78
-rw-r--r--cpp/src/qpid/broker/ConnectionHandler.h6
-rw-r--r--cpp/src/qpid/broker/ConnectionState.h9
-rw-r--r--cpp/src/qpid/broker/Consumer.h21
-rw-r--r--cpp/src/qpid/broker/Daemon.cpp5
-rw-r--r--cpp/src/qpid/broker/DeliverableMessage.h2
-rw-r--r--cpp/src/qpid/broker/DeliveryRecord.cpp28
-rw-r--r--cpp/src/qpid/broker/DeliveryRecord.h4
-rw-r--r--cpp/src/qpid/broker/DirectExchange.cpp14
-rw-r--r--cpp/src/qpid/broker/DtxAck.cpp4
-rw-r--r--cpp/src/qpid/broker/DtxAck.h35
-rw-r--r--cpp/src/qpid/broker/DtxBuffer.cpp22
-rw-r--r--cpp/src/qpid/broker/DtxBuffer.h53
-rw-r--r--cpp/src/qpid/broker/DtxManager.cpp40
-rw-r--r--cpp/src/qpid/broker/DtxManager.h26
-rw-r--r--cpp/src/qpid/broker/DtxTimeout.cpp2
-rw-r--r--cpp/src/qpid/broker/DtxTimeout.h10
-rw-r--r--cpp/src/qpid/broker/DtxWorkRecord.cpp40
-rw-r--r--cpp/src/qpid/broker/DtxWorkRecord.h14
-rw-r--r--cpp/src/qpid/broker/Exchange.cpp83
-rw-r--r--cpp/src/qpid/broker/Exchange.h48
-rw-r--r--cpp/src/qpid/broker/ExchangeRegistry.cpp11
-rw-r--r--cpp/src/qpid/broker/ExpiryPolicy.cpp10
-rw-r--r--cpp/src/qpid/broker/ExpiryPolicy.h14
-rw-r--r--cpp/src/qpid/broker/Fairshare.cpp76
-rw-r--r--cpp/src/qpid/broker/Fairshare.h6
-rw-r--r--cpp/src/qpid/broker/FanOutExchange.cpp11
-rw-r--r--cpp/src/qpid/broker/FifoDistributor.cpp58
-rw-r--r--cpp/src/qpid/broker/HeadersExchange.cpp20
-rw-r--r--cpp/src/qpid/broker/IncompleteMessageList.cpp85
-rw-r--r--cpp/src/qpid/broker/IncompleteMessageList.h (renamed from cpp/src/qpid/broker/FifoDistributor.h)50
-rw-r--r--cpp/src/qpid/broker/LegacyLVQ.cpp6
-rw-r--r--cpp/src/qpid/broker/Link.cpp65
-rw-r--r--cpp/src/qpid/broker/Link.h10
-rw-r--r--cpp/src/qpid/broker/LinkRegistry.cpp6
-rw-r--r--cpp/src/qpid/broker/Message.cpp172
-rw-r--r--cpp/src/qpid/broker/Message.h78
-rw-r--r--cpp/src/qpid/broker/MessageBuilder.h2
-rw-r--r--cpp/src/qpid/broker/MessageDistributor.h76
-rw-r--r--cpp/src/qpid/broker/MessageGroupManager.cpp411
-rw-r--r--cpp/src/qpid/broker/MessageGroupManager.h107
-rw-r--r--cpp/src/qpid/broker/Messages.h4
-rw-r--r--cpp/src/qpid/broker/NullMessageStore.cpp4
-rw-r--r--cpp/src/qpid/broker/NullMessageStore.h4
-rw-r--r--cpp/src/qpid/broker/PersistableMessage.cpp26
-rw-r--r--cpp/src/qpid/broker/PersistableMessage.h29
-rw-r--r--cpp/src/qpid/broker/Queue.cpp727
-rw-r--r--cpp/src/qpid/broker/Queue.h131
-rw-r--r--cpp/src/qpid/broker/QueueCleaner.cpp18
-rw-r--r--cpp/src/qpid/broker/QueueCleaner.h14
-rw-r--r--cpp/src/qpid/broker/QueueEvents.cpp4
-rw-r--r--cpp/src/qpid/broker/QueueFlowLimit.cpp410
-rw-r--r--cpp/src/qpid/broker/QueueFlowLimit.h132
-rw-r--r--cpp/src/qpid/broker/QueueListeners.cpp36
-rw-r--r--cpp/src/qpid/broker/QueueListeners.h4
-rw-r--r--cpp/src/qpid/broker/QueueObserver.h42
-rw-r--r--cpp/src/qpid/broker/QueuePolicy.cpp23
-rw-r--r--cpp/src/qpid/broker/QueuePolicy.h3
-rw-r--r--cpp/src/qpid/broker/QueueRegistry.cpp20
-rw-r--r--cpp/src/qpid/broker/QueueRegistry.h7
-rw-r--r--cpp/src/qpid/broker/RateTracker.cpp51
-rw-r--r--cpp/src/qpid/broker/RateTracker.h57
-rw-r--r--cpp/src/qpid/broker/RecoveredDequeue.cpp1
-rw-r--r--cpp/src/qpid/broker/RecoveredEnqueue.cpp1
-rw-r--r--cpp/src/qpid/broker/RecoveryManagerImpl.cpp3
-rw-r--r--cpp/src/qpid/broker/SaslAuthenticator.cpp66
-rw-r--r--cpp/src/qpid/broker/SaslAuthenticator.h2
-rw-r--r--cpp/src/qpid/broker/SemanticState.cpp171
-rw-r--r--cpp/src/qpid/broker/SemanticState.h45
-rw-r--r--cpp/src/qpid/broker/SessionAdapter.cpp292
-rw-r--r--cpp/src/qpid/broker/SessionAdapter.h1
-rw-r--r--cpp/src/qpid/broker/SessionContext.h1
-rw-r--r--cpp/src/qpid/broker/SessionHandler.cpp5
-rw-r--r--cpp/src/qpid/broker/SessionState.cpp245
-rw-r--r--cpp/src/qpid/broker/SessionState.h119
-rw-r--r--cpp/src/qpid/broker/StatefulQueueObserver.h63
-rw-r--r--cpp/src/qpid/broker/ThresholdAlerts.cpp68
-rw-r--r--cpp/src/qpid/broker/ThresholdAlerts.h7
-rw-r--r--cpp/src/qpid/broker/TopicExchange.cpp84
-rw-r--r--cpp/src/qpid/broker/TopicExchange.h29
-rw-r--r--cpp/src/qpid/broker/TxBuffer.cpp2
-rw-r--r--cpp/src/qpid/broker/TxPublish.cpp9
-rw-r--r--cpp/src/qpid/broker/TxPublish.h91
-rw-r--r--cpp/src/qpid/broker/windows/BrokerDefaults.cpp6
-rw-r--r--cpp/src/qpid/broker/windows/SaslAuthenticator.cpp32
-rw-r--r--cpp/src/qpid/broker/windows/SslProtocolFactory.cpp53
-rw-r--r--cpp/src/qpid/client/ConnectionHandler.cpp64
-rw-r--r--cpp/src/qpid/client/ConnectionImpl.cpp12
-rw-r--r--cpp/src/qpid/client/Connector.h2
-rw-r--r--cpp/src/qpid/client/RdmaConnector.cpp6
-rw-r--r--cpp/src/qpid/client/SessionImpl.cpp1
-rw-r--r--cpp/src/qpid/client/SslConnector.cpp6
-rw-r--r--cpp/src/qpid/client/TCPConnector.cpp6
-rw-r--r--cpp/src/qpid/client/TCPConnector.h2
-rw-r--r--cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp42
-rw-r--r--cpp/src/qpid/client/amqp0_10/AcceptTracker.h5
-rw-r--r--cpp/src/qpid/client/amqp0_10/AddressResolution.cpp60
-rw-r--r--cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp179
-rw-r--r--cpp/src/qpid/client/amqp0_10/ConnectionImpl.h2
-rw-r--r--cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp10
-rw-r--r--cpp/src/qpid/client/amqp0_10/IncomingMessages.h2
-rw-r--r--cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp4
-rw-r--r--cpp/src/qpid/client/amqp0_10/SenderImpl.cpp3
-rw-r--r--cpp/src/qpid/client/amqp0_10/SessionImpl.cpp56
-rw-r--r--cpp/src/qpid/client/amqp0_10/SessionImpl.h11
-rw-r--r--cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp79
-rw-r--r--cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h (renamed from cpp/src/qpid/DisableExceptionLogging.h)27
-rw-r--r--cpp/src/qpid/client/windows/SaslFactory.cpp16
-rw-r--r--cpp/src/qpid/client/windows/SslConnector.cpp4
-rw-r--r--cpp/src/qpid/cluster/Cluster.cpp169
-rw-r--r--cpp/src/qpid/cluster/Cluster.h56
-rw-r--r--cpp/src/qpid/cluster/ClusterMap.cpp5
-rw-r--r--cpp/src/qpid/cluster/ClusterPlugin.cpp1
-rw-r--r--cpp/src/qpid/cluster/ClusterSettings.h3
-rw-r--r--cpp/src/qpid/cluster/ClusterTimer.cpp4
-rw-r--r--cpp/src/qpid/cluster/Connection.cpp235
-rw-r--r--cpp/src/qpid/cluster/Connection.h55
-rw-r--r--cpp/src/qpid/cluster/Decoder.h2
-rw-r--r--cpp/src/qpid/cluster/ErrorCheck.h2
-rw-r--r--cpp/src/qpid/cluster/Event.cpp5
-rw-r--r--cpp/src/qpid/cluster/Event.h28
-rw-r--r--cpp/src/qpid/cluster/EventFrame.h6
-rw-r--r--cpp/src/qpid/cluster/ExpiryPolicy.cpp95
-rw-r--r--cpp/src/qpid/cluster/ExpiryPolicy.h42
-rw-r--r--cpp/src/qpid/cluster/FailoverExchange.cpp26
-rw-r--r--cpp/src/qpid/cluster/FailoverExchange.h10
-rw-r--r--cpp/src/qpid/cluster/Multicaster.cpp3
-rw-r--r--cpp/src/qpid/cluster/OutputInterceptor.cpp39
-rw-r--r--cpp/src/qpid/cluster/OutputInterceptor.h10
-rw-r--r--cpp/src/qpid/cluster/SecureConnectionFactory.cpp8
-rw-r--r--cpp/src/qpid/cluster/UpdateClient.cpp223
-rw-r--r--cpp/src/qpid/cluster/UpdateClient.h32
-rw-r--r--cpp/src/qpid/cluster/UpdateDataExchange.cpp10
-rw-r--r--cpp/src/qpid/cluster/UpdateDataExchange.h2
-rw-r--r--cpp/src/qpid/cluster/UpdateExchange.cpp27
-rw-r--r--cpp/src/qpid/cluster/UpdateReceiver.h14
-rw-r--r--cpp/src/qpid/cluster/types.h1
-rw-r--r--cpp/src/qpid/console/SessionManager.cpp3
-rw-r--r--cpp/src/qpid/framing/AMQBody.h2
-rw-r--r--cpp/src/qpid/framing/AMQContentBody.h12
-rw-r--r--cpp/src/qpid/framing/AMQFrame.cpp5
-rw-r--r--cpp/src/qpid/framing/AMQFrame.h7
-rw-r--r--cpp/src/qpid/framing/AMQHeaderBody.h14
-rw-r--r--cpp/src/qpid/framing/AMQHeartbeatBody.h2
-rw-r--r--cpp/src/qpid/framing/FieldTable.cpp6
-rw-r--r--cpp/src/qpid/framing/List.cpp6
-rw-r--r--cpp/src/qpid/framing/MethodBodyFactory.h1
-rw-r--r--cpp/src/qpid/framing/SendContent.h2
-rw-r--r--cpp/src/qpid/framing/TransferContent.h2
-rw-r--r--cpp/src/qpid/framing/Uuid.cpp4
-rw-r--r--cpp/src/qpid/log/Logger.cpp21
-rw-r--r--cpp/src/qpid/log/Options.cpp4
-rw-r--r--cpp/src/qpid/log/Statement.cpp5
-rw-r--r--cpp/src/qpid/log/posix/SinkOptions.cpp2
-rw-r--r--cpp/src/qpid/log/windows/SinkOptions.cpp4
-rw-r--r--cpp/src/qpid/log/windows/SinkOptions.h2
-rw-r--r--cpp/src/qpid/management/ManagementAgent.cpp228
-rw-r--r--cpp/src/qpid/management/ManagementAgent.h13
-rw-r--r--cpp/src/qpid/messaging/AddressParser.cpp5
-rw-r--r--cpp/src/qpid/messaging/Duration.cpp10
-rw-r--r--cpp/src/qpid/messaging/Message.cpp7
-rw-r--r--cpp/src/qpid/messaging/Session.cpp3
-rw-r--r--cpp/src/qpid/messaging/SessionImpl.h2
-rw-r--r--cpp/src/qpid/replication/ReplicatingEventListener.cpp7
-rw-r--r--cpp/src/qpid/replication/ReplicationExchange.cpp9
-rw-r--r--cpp/src/qpid/store/StorageProvider.h2
-rw-r--r--cpp/src/qpid/sys/AggregateOutput.h2
-rw-r--r--cpp/src/qpid/sys/AsynchIO.h4
-rw-r--r--cpp/src/qpid/sys/AsynchIOHandler.h2
-rw-r--r--cpp/src/qpid/sys/AtomicValue.h7
-rw-r--r--cpp/src/qpid/sys/AtomicValue_gcc.h11
-rw-r--r--cpp/src/qpid/sys/ClusterSafe.cpp12
-rw-r--r--cpp/src/qpid/sys/ClusterSafe.h21
-rw-r--r--cpp/src/qpid/sys/CopyOnWriteArray.h6
-rw-r--r--cpp/src/qpid/sys/PollableQueue.h21
-rw-r--r--cpp/src/qpid/sys/Poller.h2
-rw-r--r--cpp/src/qpid/sys/ProtocolFactory.h3
-rw-r--r--cpp/src/qpid/sys/RdmaIOPlugin.cpp24
-rw-r--r--cpp/src/qpid/sys/Socket.h32
-rw-r--r--cpp/src/qpid/sys/SocketAddress.h10
-rw-r--r--cpp/src/qpid/sys/SslPlugin.cpp11
-rw-r--r--cpp/src/qpid/sys/StateMonitor.h14
-rw-r--r--cpp/src/qpid/sys/TCPIOPlugin.cpp80
-rw-r--r--cpp/src/qpid/sys/Timer.cpp22
-rw-r--r--cpp/src/qpid/sys/Timer.h8
-rw-r--r--cpp/src/qpid/sys/TimerWarnings.cpp16
-rw-r--r--cpp/src/qpid/sys/alloca.h25
-rw-r--r--cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp3
-rw-r--r--cpp/src/qpid/sys/epoll/EpollPoller.cpp7
-rw-r--r--cpp/src/qpid/sys/posix/AsynchIO.cpp36
-rwxr-xr-xcpp/src/qpid/sys/posix/LockFile.cpp3
-rw-r--r--cpp/src/qpid/sys/posix/Socket.cpp171
-rw-r--r--cpp/src/qpid/sys/posix/SocketAddress.cpp80
-rw-r--r--cpp/src/qpid/sys/posix/Thread.cpp3
-rw-r--r--cpp/src/qpid/sys/posix/Time.cpp7
-rw-r--r--cpp/src/qpid/sys/rdma/RdmaIO.cpp14
-rw-r--r--cpp/src/qpid/sys/rdma/rdma_wrap.cpp15
-rw-r--r--cpp/src/qpid/sys/rdma/rdma_wrap.h10
-rw-r--r--cpp/src/qpid/sys/ssl/SslHandler.h2
-rw-r--r--cpp/src/qpid/sys/ssl/SslIo.cpp2
-rw-r--r--cpp/src/qpid/sys/ssl/SslIo.h2
-rw-r--r--cpp/src/qpid/sys/ssl/SslSocket.cpp4
-rw-r--r--cpp/src/qpid/sys/ssl/SslSocket.h2
-rw-r--r--cpp/src/qpid/sys/windows/AsynchIO.cpp71
-rwxr-xr-xcpp/src/qpid/sys/windows/AsynchIoResult.h6
-rwxr-xr-xcpp/src/qpid/sys/windows/IocpPoller.cpp6
-rw-r--r--cpp/src/qpid/sys/windows/Shlib.cpp3
-rwxr-xr-x[-rw-r--r--]cpp/src/qpid/sys/windows/Socket.cpp188
-rw-r--r--cpp/src/qpid/sys/windows/SocketAddress.cpp120
-rw-r--r--cpp/src/qpid/sys/windows/SslAsynchIO.h3
-rwxr-xr-xcpp/src/qpid/sys/windows/StrError.cpp7
-rwxr-xr-xcpp/src/qpid/sys/windows/Thread.cpp285
-rw-r--r--cpp/src/qpid/sys/windows/Time.cpp36
-rw-r--r--cpp/src/qpid/sys/windows/uuid.cpp6
-rw-r--r--cpp/src/qpid/types/Uuid.cpp19
-rw-r--r--cpp/src/qpid/types/Variant.cpp35
-rw-r--r--cpp/src/replication.mk6
-rw-r--r--cpp/src/ssl.mk6
-rw-r--r--cpp/src/tests/.valgrind.supp74
-rw-r--r--cpp/src/tests/Address.cpp11
-rw-r--r--cpp/src/tests/BrokerFixture.h32
-rw-r--r--cpp/src/tests/BrokerMgmtAgent.cpp3
-rw-r--r--cpp/src/tests/BrokerOptions.cpp79
-rw-r--r--cpp/src/tests/CMakeLists.txt18
-rw-r--r--cpp/src/tests/ClientSessionTest.cpp33
-rw-r--r--cpp/src/tests/ExchangeTest.cpp2
-rw-r--r--cpp/src/tests/ForkedBroker.cpp3
-rw-r--r--cpp/src/tests/IncompleteMessageList.cpp134
-rw-r--r--cpp/src/tests/Makefile.am47
-rw-r--r--cpp/src/tests/MessageReplayTracker.cpp4
-rw-r--r--cpp/src/tests/MessagingFixture.h117
-rw-r--r--cpp/src/tests/MessagingSessionTests.cpp228
-rw-r--r--cpp/src/tests/Qmf2.cpp104
-rw-r--r--cpp/src/tests/QueueEvents.cpp4
-rw-r--r--cpp/src/tests/QueueFlowLimitTest.cpp463
-rw-r--r--cpp/src/tests/QueuePolicyTest.cpp21
-rw-r--r--cpp/src/tests/QueueTest.cpp444
-rw-r--r--cpp/src/tests/ReplicationTest.cpp2
-rw-r--r--cpp/src/tests/SessionState.cpp8
-rw-r--r--cpp/src/tests/SocketProxy.h181
-rw-r--r--cpp/src/tests/TimerTest.cpp4
-rw-r--r--cpp/src/tests/TxPublishTest.cpp7
-rw-r--r--cpp/src/tests/Url.cpp26
-rw-r--r--cpp/src/tests/Variant.cpp58
-rw-r--r--cpp/src/tests/XmlClientSessionTest.cpp2
-rwxr-xr-xcpp/src/tests/acl.py219
-rwxr-xr-xcpp/src/tests/allhosts4
-rw-r--r--cpp/src/tests/brokertest.py312
-rwxr-xr-xcpp/src/tests/cli_tests.py24
-rw-r--r--cpp/src/tests/cluster_python_tests_failing.txt28
-rwxr-xr-xcpp/src/tests/cluster_test_logs.py16
-rwxr-xr-xcpp/src/tests/cluster_tests.py1033
-rw-r--r--cpp/src/tests/exception_test.cpp14
-rwxr-xr-xcpp/src/tests/federated_topic_test27
-rwxr-xr-xcpp/src/tests/federation.py398
-rwxr-xr-xcpp/src/tests/federation_sys.py1900
-rwxr-xr-xcpp/src/tests/ipv6_test150
-rw-r--r--cpp/src/tests/msg_group_test.cpp618
-rwxr-xr-xcpp/src/tests/python_tests2
-rwxr-xr-xcpp/src/tests/qpid-cluster-benchmark47
-rwxr-xr-xcpp/src/tests/qpid-cpp-benchmark71
-rwxr-xr-xcpp/src/tests/qpid-ctrl5
-rw-r--r--cpp/src/tests/qpid-perftest.cpp18
-rw-r--r--cpp/src/tests/qpid-receive.cpp9
-rw-r--r--cpp/src/tests/qpid-send.cpp104
-rw-r--r--cpp/src/tests/qrsh.cpp169
-rw-r--r--cpp/src/tests/qrsh_run.cpp321
-rw-r--r--cpp/src/tests/qrsh_server.cpp1068
-rwxr-xr-x[-rw-r--r--]cpp/src/tests/qrsh_utils/10_all (renamed from cpp/src/qpid/sys/windows/mingw32_compat.h)23
-rwxr-xr-xcpp/src/tests/qrsh_utils/1_remote_run26
-rwxr-xr-xcpp/src/tests/qrsh_utils/2_forever26
-rwxr-xr-xcpp/src/tests/qrsh_utils/3_kill_it27
-rwxr-xr-xcpp/src/tests/qrsh_utils/4_wait_for_it26
-rwxr-xr-xcpp/src/tests/qrsh_utils/5_exited64
-rwxr-xr-xcpp/src/tests/qrsh_utils/6_get29
-rwxr-xr-xcpp/src/tests/qrsh_utils/7_get_output44
-rwxr-xr-xcpp/src/tests/qrsh_utils/8_any43
-rwxr-xr-xcpp/src/tests/qrsh_utils/9_alias38
-rw-r--r--cpp/src/tests/qrsh_utils/qrsh_example_command.cpp (renamed from cpp/src/qmf/EventNotifierImpl.h)58
-rw-r--r--cpp/src/tests/qrsh_utils/qrsh_forever.cpp50
-rw-r--r--cpp/src/tests/qrsh_utils/qsh_doc.txt309
-rw-r--r--cpp/src/tests/queue_flow_limit_tests.py371
-rwxr-xr-xcpp/src/tests/replication_test2
-rwxr-xr-xcpp/src/tests/run_acl_tests2
-rwxr-xr-xcpp/src/tests/run_cli_tests5
-rwxr-xr-xcpp/src/tests/run_federation_sys_tests97
-rwxr-xr-xcpp/src/tests/run_federation_tests4
-rwxr-xr-xcpp/src/tests/run_header_test2
-rw-r--r--cpp/src/tests/run_long_federation_sys_tests24
-rwxr-xr-xcpp/src/tests/run_msg_group_tests66
-rwxr-xr-xcpp/src/tests/run_msg_group_tests_soak60
-rwxr-xr-xcpp/src/tests/run_queue_flow_limit_tests57
-rw-r--r--cpp/src/tests/run_store_tests.ps12
-rwxr-xr-xcpp/src/tests/run_test2
-rw-r--r--cpp/src/tests/sasl.mk16
-rwxr-xr-xcpp/src/tests/sasl_fed2
-rwxr-xr-xcpp/src/tests/sasl_fed_ex306
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_dynamic27
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_dynamic_cluster28
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_link27
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_link_cluster28
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_queue27
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_queue_cluster28
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_route27
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_route_cluster28
-rwxr-xr-xcpp/src/tests/sasl_no_dir218
-rwxr-xr-xcpp/src/tests/sasl_test_setup.sh1
-rw-r--r--cpp/src/tests/sender.cpp2
-rwxr-xr-xcpp/src/tests/ssl_test14
-rw-r--r--cpp/src/tests/windows/DisableWin32ErrorWindows.cpp4
-rw-r--r--cpp/src/windows/QpiddBroker.cpp16
-rw-r--r--cpp/src/windows/SCM.cpp (renamed from cpp/src/qpid/sys/windows/SCM.cpp)664
-rw-r--r--cpp/src/windows/SCM.h (renamed from cpp/src/qpid/sys/windows/SCM.h)220
-rw-r--r--cpp/src/windows/resources/template-resource.rc2
-rw-r--r--cpp/src/xml.mk2
-rw-r--r--cpp/xml/cluster.xml74
635 files changed, 8823 insertions, 22446 deletions
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 17411e90a4..5c37ecfc97 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -80,7 +80,6 @@ set(CPACK_PACKAGE_INSTALL_DIRECTORY "qpidc-${qpidc_version}")
add_subdirectory(managementgen)
add_subdirectory(etc)
add_subdirectory(src)
-add_subdirectory(bindings/qpid)
add_subdirectory(docs/api)
# add_subdirectory(docs/man)
add_subdirectory(examples)
diff --git a/cpp/INSTALL b/cpp/INSTALL
index dbd41c7cc1..6483d7de4e 100644
--- a/cpp/INSTALL
+++ b/cpp/INSTALL
@@ -47,9 +47,9 @@ Redhat Linux 3, will almost certainly require some packages to be upgraded.
====================
The following libraries and header files must be installed to build
a source distribution:
- * boost <http://www.boost.org> (1.35)(*)
- * libuuid <http://kernel.org/~kzak/util-linux/> (2.19)
- * pkgconfig <http://pkgconfig.freedesktop.org/wiki/> (0.21)
+ * boost <http://www.boost.org> (1.35)(*)
+ * e2fsprogs <http://e2fsprogs.sourceforge.net/> (1.39)
+ * pkgconfig <http://pkgconfig.freedesktop.org/wiki/> (0.21)
(*) earlier versions of boost e.g. 1.33 also work and there is a patch
to get 1.32 working in the svn tree though that is only recommended as
@@ -96,12 +96,12 @@ the following must also be installed:
* python-devel
* swig <http://www.swig.org> (1.3.35)
-UUID problems:
-In some earlier Linux releases (such as Fedora 11), the uuid/uuid.h
-file is located in the e2fsprogs-devel package instead of
-libuuid-devel. If you are using an older Linux release and run into a
-problem during configure in which uuid.h cannot be found, install the
-e2fsprogs-devel package.
+UUID problems:
+In some later Linux releases (such as Fedora 12), the uuid/uuid.h file has been
+moved from e2fsprogs-devel into libuuid-devel. If you are using a newer Linux
+release and run into a problem during configure in which uuid.h cannot be found,
+look for and install the libuuid-devel package.
+
2.2. How to Install
===================
@@ -112,7 +112,7 @@ e2fsprogs-devel package.
On linux most packages can be installed using your distribution's
package management tool. For example on Fedora:
- # yum install boost-devel libuuid-devel pkgconfig gcc-c++ make autoconf automake ruby libtool help2man doxygen graphviz
+ # yum install boost-devel e2fsprogs-devel pkgconfig gcc-c++ make autoconf automake ruby libtool help2man doxygen graphviz
The optional clustering packages changed name in Fedora 10. On Fedora 9 or earlier:
# yum install openais-devel cman-devel
diff --git a/cpp/INSTALL-WINDOWS b/cpp/INSTALL-WINDOWS
index 75fa69079e..964d644a7a 100644
--- a/cpp/INSTALL-WINDOWS
+++ b/cpp/INSTALL-WINDOWS
@@ -64,7 +64,7 @@ manually installed to non-standard locations. For example:
It is also necessary to set BOOST_ROOT to refer to the base of your Boost
installation. The Visual Studio projects refer to it. For example:
- # set BOOST_ROOT="C:\Program Files\boost\boost_1_35_0"
+ # set BOOST_ROOT=C:\Program Files\boost\boost_1_35_0
3. Building from a Source Distribution
@@ -75,7 +75,7 @@ Visual Studio solution file which is generated by CMake.
From a command prompt:
# cd qpid\cpp
- # cmake -i -G "Visual Studio 9 2008" .
+ # cmake -i
Output from CMake includes .h files in the include directory, .vcproj
files for executables and dlls, and the qpid-cpp.sln solution file.
@@ -120,12 +120,7 @@ files that are part of the build.
Configure again. Repeat until all the Cache Values are gray.
- Click the OK button to generate the project/make files.
-Open the qpid-cpp.sln solution located in the build directory, select Debug
-or Release, and build. You can build both Release and Debug from the same
-project.
-
-If you build all the projects you can then "Build" the RUN_TESTS project.
-This will run the test suite against the Qpid version just built.
+Now follow instruction for building from a source distribution in step (3).
5. Tests
diff --git a/cpp/Makefile.am b/cpp/Makefile.am
index 9f4b8e2082..01b8507454 100644
--- a/cpp/Makefile.am
+++ b/cpp/Makefile.am
@@ -33,7 +33,3 @@ SUBDIRS = managementgen etc src docs/api docs/man examples bindings/qmf bindings
# Update libtool, if needed.
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck
-
-check-long: all
- $(MAKE) -C src/tests check-long
- \ No newline at end of file
diff --git a/cpp/bindings/qmf/python/Makefile.am b/cpp/bindings/qmf/python/Makefile.am
index 8abad32959..421590f189 100644
--- a/cpp/bindings/qmf/python/Makefile.am
+++ b/cpp/bindings/qmf/python/Makefile.am
@@ -30,13 +30,11 @@ BUILT_SOURCES = $(generated_file_list)
SWIG_FLAGS = -w362,401
$(generated_file_list): $(srcdir)/python.i $(srcdir)/../qmfengine.i
- $(SWIG) -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I$(top_srcdir)/src/qmf -I/usr/include -o qmfengine.cpp $(srcdir)/python.i
+ swig -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I$(top_srcdir)/src/qmf -I/usr/include -o qmfengine.cpp $(srcdir)/python.i
pylibdir = $(PYTHON_LIB)
lib_LTLIBRARIES = _qmfengine.la
-qenginedir = $(pyexecdir)
-qengine_PYTHON = qmfengine.py qmf.py
#_qmfengine_la_LDFLAGS = -avoid-version -module -shrext "$(PYTHON_SO)"
#_qmfengine_la_LDFLAGS = -avoid-version -module -shrext ".so"
diff --git a/cpp/bindings/qmf/ruby/Makefile.am b/cpp/bindings/qmf/ruby/Makefile.am
index de8c4d10d5..cfb3a33870 100644
--- a/cpp/bindings/qmf/ruby/Makefile.am
+++ b/cpp/bindings/qmf/ruby/Makefile.am
@@ -35,9 +35,9 @@ qmfengine.cpp: $(srcdir)/ruby.i $(srcdir)/../qmfengine.i
rubylibarchdir = $(RUBY_LIB_ARCH)
rubylibarch_LTLIBRARIES = qmfengine.la
-qmfengine_la_LDFLAGS = -avoid-version -module -shared -shrext ".$(RUBY_DLEXT)"
+qmfengine_la_LDFLAGS = -avoid-version -module -shrext ".$(RUBY_DLEXT)"
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) -fno-strict-aliasing
+qmfengine_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH)
nodist_qmfengine_la_SOURCES = qmfengine.cpp
CLEANFILES = qmfengine.cpp
diff --git a/cpp/bindings/qmf/tests/test_base.rb b/cpp/bindings/qmf/tests/test_base.rb
index 7d4609097c..3e4337a9c0 100644
--- a/cpp/bindings/qmf/tests/test_base.rb
+++ b/cpp/bindings/qmf/tests/test_base.rb
@@ -24,7 +24,6 @@ require 'socket'
class ConsoleTestBase < Qmf::ConsoleHandler
def initialize
- sleep(2)
@settings = Qmf::ConnectionSettings.new
@settings.host = ARGV[0] if ARGV.size > 0
@settings.port = ARGV[1].to_i if ARGV.size > 1
@@ -68,7 +67,7 @@ class ConsoleTestBase < Qmf::ConsoleHandler
def assert(condition, in_text=nil)
text = " (#{in_text})" if in_text
- raise "Assertion failed: #{condition} #{text}" unless condition
+ raise "Assertion failed: #{left} != #{right}#{text}" unless condition
end
def fail(text)
diff --git a/cpp/bindings/qmf2/examples/cpp/Makefile.am b/cpp/bindings/qmf2/examples/cpp/Makefile.am
index 062fbd0a85..84207d43c4 100644
--- a/cpp/bindings/qmf2/examples/cpp/Makefile.am
+++ b/cpp/bindings/qmf2/examples/cpp/Makefile.am
@@ -21,7 +21,7 @@ INCLUDE = -I$(top_srcdir)/include
AM_CPPFLAGS = $(INCLUDE)
-noinst_PROGRAMS=agent event_driven_list_agents list_agents print_events
+noinst_PROGRAMS=agent list_agents print_events
agent_SOURCES=agent.cpp
agent_LDADD=$(top_builddir)/src/libqmf2.la
@@ -29,8 +29,5 @@ agent_LDADD=$(top_builddir)/src/libqmf2.la
list_agents_SOURCES=list_agents.cpp
list_agents_LDADD=$(top_builddir)/src/libqmf2.la
-event_driven_list_agents_SOURCES=event_driven_list_agents.cpp
-event_driven_list_agents_LDADD=$(top_builddir)/src/libqmf2.la
-
print_events_SOURCES=print_events.cpp
print_events_LDADD=$(top_builddir)/src/libqmf2.la
diff --git a/cpp/bindings/qmf2/examples/cpp/event_driven_list_agents.cpp b/cpp/bindings/qmf2/examples/cpp/event_driven_list_agents.cpp
deleted file mode 100644
index c288aa6bdd..0000000000
--- a/cpp/bindings/qmf2/examples/cpp/event_driven_list_agents.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <sys/select.h>
-#include <time.h>
-
-#include <qpid/messaging/Connection.h>
-#include <qpid/messaging/Duration.h>
-#include <qmf/Agent.h>
-#include <qmf/ConsoleEvent.h>
-#include <qmf/ConsoleSession.h>
-#include <qpid/types/Variant.h>
-#include "qmf/posix/EventNotifier.h"
-
-#include <string>
-#include <iostream>
-
-using namespace std;
-using namespace qmf;
-using qpid::types::Variant;
-using qpid::messaging::Duration;
-
-int main(int argc, char** argv)
-{
- string url("localhost");
- string connectionOptions;
- string sessionOptions;
-
- if (argc > 1)
- url = argv[1];
- if (argc > 2)
- connectionOptions = argv[2];
- if (argc > 3)
- sessionOptions = argv[3];
-
- qpid::messaging::Connection connection(url, connectionOptions);
- connection.open();
-
- ConsoleSession session(connection, sessionOptions);
- session.open();
- session.setAgentFilter("");
-
- posix::EventNotifier notifier(session);
-
- int fd(notifier.getHandle());
- time_t lastUpdate;
- bool ftl = false;
-
- time(&lastUpdate);
-
- while (true) {
- fd_set rfds;
- struct timeval tv;
- int nfds, retval;
-
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
- nfds = fd + 1;
- tv.tv_sec = 10;
- tv.tv_usec = 0;
-
- retval = select(nfds, &rfds, NULL, NULL, &tv);
-
- if (retval > 0 && FD_ISSET(fd, &rfds)) {
- ConsoleEvent event;
- while (session.nextEvent(event, Duration::IMMEDIATE)) {
- string eventType = "";
- switch(event.getType()) {
- case CONSOLE_AGENT_ADD: eventType = "Added"; break;
- case CONSOLE_AGENT_DEL: eventType = "Deleted"; break;
- case CONSOLE_AGENT_RESTART: eventType = "Restarted"; break;
- case CONSOLE_AGENT_SCHEMA_UPDATE: eventType = "Schema Updated"; break;
- case CONSOLE_AGENT_SCHEMA_RESPONSE: eventType = "Schema Response"; break;
- case CONSOLE_EVENT: eventType = "Event"; break;
- case CONSOLE_QUERY_RESPONSE: eventType = "Query Response"; break;
- case CONSOLE_METHOD_RESPONSE: eventType = "Method Response"; break;
- case CONSOLE_EXCEPTION: eventType = "Exception"; break;
- case CONSOLE_SUBSCRIBE_ADD: eventType = "Subscription Added"; break;
- case CONSOLE_SUBSCRIBE_UPDATE: eventType = "Subscription Updated"; break;
- case CONSOLE_SUBSCRIBE_DEL: eventType = "Subscription Deleted" ; break;
- case CONSOLE_THREAD_FAILED: eventType = "Thread Failure"; break;
- default: eventType = "[UNDEFINED]";
- }
- cout << "Agent " << eventType << ": " << event.getAgent().getName() << endl;
- }
- } else {
- cout << "No message received within waiting period." << endl;
- }
- }
-}
-
diff --git a/cpp/bindings/qmf2/python/Makefile.am b/cpp/bindings/qmf2/python/Makefile.am
index 3dc04e832f..7adc62eddb 100644
--- a/cpp/bindings/qmf2/python/Makefile.am
+++ b/cpp/bindings/qmf2/python/Makefile.am
@@ -30,12 +30,12 @@ BUILT_SOURCES = $(generated_file_list)
SWIG_FLAGS = -w362,401
$(generated_file_list): $(srcdir)/python.i $(srcdir)/../qmf2.i $(srcdir)/../../swig_python_typemaps.i
- $(SWIG) -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqmf2.cpp $(srcdir)/python.i
+ swig -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqmf2.cpp $(srcdir)/python.i
pylibdir = $(PYTHON_LIB)
lib_LTLIBRARIES = _cqmf2.la
-cqpiddir = $(pyexecdir)
+cqpiddir = $(pythondir)
cqpid_PYTHON = qmf2.py cqmf2.py
_cqmf2_la_LDFLAGS = -avoid-version -module -shared
diff --git a/cpp/bindings/qmf2/qmf2.i b/cpp/bindings/qmf2/qmf2.i
index 0f573fe3e6..a09a95168f 100644
--- a/cpp/bindings/qmf2/qmf2.i
+++ b/cpp/bindings/qmf2/qmf2.i
@@ -37,7 +37,6 @@
%}
-%include <qpid/ImportExport.h>
%include <qpid/messaging/ImportExport.h>
%include <qpid/messaging/Duration.h>
diff --git a/cpp/bindings/qmf2/ruby/Makefile.am b/cpp/bindings/qmf2/ruby/Makefile.am
index 97bbc6f385..ae840f87c6 100644
--- a/cpp/bindings/qmf2/ruby/Makefile.am
+++ b/cpp/bindings/qmf2/ruby/Makefile.am
@@ -34,9 +34,9 @@ rubylibarchdir = $(RUBY_LIB_ARCH)
rubylibarch_LTLIBRARIES = cqmf2.la
dist_rubylib_DATA = qmf2.rb
-cqmf2_la_LDFLAGS = -avoid-version -module -shared -shrext ".$(RUBY_DLEXT)"
+cqmf2_la_LDFLAGS = -avoid-version -module -shrext ".$(RUBY_DLEXT)"
cqmf2_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqmf2 $(top_builddir)/src/libqmf2.la
-cqmf2_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH) -fno-strict-aliasing
+cqmf2_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH)
nodist_cqmf2_la_SOURCES = cqmf2.cpp
CLEANFILES = cqmf2.cpp
diff --git a/cpp/bindings/qpid/CMakeLists.txt b/cpp/bindings/qpid/CMakeLists.txt
deleted file mode 100644
index 7c9f76f991..0000000000
--- a/cpp/bindings/qpid/CMakeLists.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-include(FindSWIG)
-include(UseSWIG)
-include(FindRuby)
-include(FindPythonLibs)
-include(FindPerlLibs)
-
-if (SWIG_FOUND)
- set(CMAKE_SWIG_FLAGS "-w361,362,401,467,503")
-
- if (PYTHONLIBS_FOUND)
- add_subdirectory(python)
- endif (PYTHONLIBS_FOUND)
-
- if (RUBY_FOUND)
- add_subdirectory(ruby)
- endif (RUBY_FOUND)
-
- if (PERLLIBS_FOUND)
- add_subdirectory(perl)
- endif (PERLLIBS_FOUND)
-endif (SWIG_FOUND)
diff --git a/cpp/bindings/qpid/Makefile.am b/cpp/bindings/qpid/Makefile.am
index 31bce5d1d5..ca9eda0c73 100644
--- a/cpp/bindings/qpid/Makefile.am
+++ b/cpp/bindings/qpid/Makefile.am
@@ -21,7 +21,7 @@ SUBDIRS = dotnet
if HAVE_SWIG
-EXTRA_DIST = CMakeLists.txt qpid.i
+EXTRA_DIST = qpid.i
if HAVE_RUBY_DEVEL
SUBDIRS += ruby
diff --git a/cpp/bindings/qpid/dotnet/configure-windows.ps1 b/cpp/bindings/qpid/dotnet/configure-windows.ps1
index 23fc742e07..34395911b9 100644
--- a/cpp/bindings/qpid/dotnet/configure-windows.ps1
+++ b/cpp/bindings/qpid/dotnet/configure-windows.ps1
@@ -24,32 +24,29 @@
# This script configures a qpid\cpp developer build environment under Windows
# to enable working with cpp\bindings\qpid\dotnet binding source code.
#
-# * Supports multiple versions of Visual Studio (VS2008, VS2010) as CMake
-# generator.
-#
# * Supports 32-bit and/or 64-bit development platforms.
#
# * User chooses in-source or out-of-source build directories.
#
# - 'In-source' builds happen when CMake is run from directory qpid\cpp.
-# Hundreds of CMake-generated output files are placed in qpid\cpp\src.
+# Hundreds of CMake-generated output files are placed in qpid\cpp\src.
# These files go right on top of files that are part of the source tree
# in qpid\cpp\src.
-# In-source builds support only one platform.
+# In-source builds support only one platform.
# Choose only a 32-bit or a 64-bit platform but not both.
#
# - Out-of-source builds happen when the user chooses another directory
# under qpid in which to run CMake. Out-of-source builds are required
-# in order to build both x86 and x64 targets using the same source tree.
+# in order to build both x86 and x64 targets using the same source tree.
# For each build platform (32-bit x86 or Win32, or 64-bit x64) the user
-# specifies a build directory and a specific version of Boost.
+# specifies a build directory and a specific version of Boost.
# Many platform/Boost-version directories may reside side by side.
#
# * User chooses to run CMake or not.
#
# - When a new build directory is created then the user is given the
-# option of running CMake in that directory. Running CMake is a
-# necessary step as CMake creates important source, solution, and
+# option of running CMake in that directory. Running CMake is a
+# necessary step as CMake creates important source, solution, and
# project files.
#
# - If a directory "looks like" is has already had CMake run in it
@@ -66,7 +63,7 @@
# 3. CMake 2.8 (or later) must be installed. The cmake\bin directory
# must be in the user's path.
# 4. Boost library specifications may or may not be in the user's path.
-# The script author recommeds not to have Boost in the path and only
+# The script author recommeds not to have Boost in the path and only
# allow the Boost path to be specified by generated command procedures.
# 5. Visual Studio build environment must be installed.
#
@@ -93,7 +90,7 @@
# In this example the build dirs are new. The script will prompt
# asking if CMake is to run in the build directories. User chooses Yes.
#
-# Now this script runs CMake twice, once each with the 32-bit and 64-bit
+# Now this script runs CMake twice, once each with the 32-bit and 64-bit
# generators.
# * This step creates qpid-cpp.sln and related project files.
# C:\svn\qpid\build32\qpid-cpp.sln
@@ -110,7 +107,7 @@
# C:\svn\qpid\build64\setenv-messaging-x64-64bit.bat
#
# Next the user compiles solution qpid\build32\qpid-cpp.sln.
-#
+#
# Using the generated scripts:
#
# Case 1. Run an executable in 32-bit mode.
@@ -145,11 +142,6 @@ $global:txtPath = '$env:PATH'
$global:txtQR = '$env:QPID_BUILD_ROOT'
$global:txtWH = 'Write-Host'
-#############################
-# Visual Studio version selection dialog items and choice
-#
-[array]$global:VsVersionCmakeChoiceList = "Visual Studio 10", "Visual Studio 9 2008"
-$global:cmakeGenerator = ''
#############################
# Select-Folder
@@ -176,7 +168,7 @@ function AskYesOrNo ($Question="No question?", $Title="No Title?")
[Windows.Forms.MessageBoxIcon]::Question)
$result = $dlg -eq [Windows.Forms.DialogResult]::Yes
-
+
$result
}
@@ -196,7 +188,7 @@ function SanityCheckBoostPath ($path=0)
$toTest = ('include', 'lib')
foreach ($pattern in $toTest) {
- $target = Join-Path $path $pattern
+ $target = Join-Path $path $pattern
if (!(Test-Path -path $target)) {
$result = $false
}
@@ -204,7 +196,7 @@ function SanityCheckBoostPath ($path=0)
} else {
$result = $false
}
-
+
if (! $result) {
Write-Host "The path ""$displayPath"" does not appear to be a Boost root path."
}
@@ -227,7 +219,7 @@ function SanityCheckBuildPath ($path=0)
$toTest = ('CMakeFiles', 'docs', 'etc', 'examples', 'include',
'managementgen', 'src')
foreach ($pattern in $toTest) {
- $target = Join-Path $path $pattern
+ $target = Join-Path $path $pattern
if (!(Test-Path -path $target)) {
$result = $false
}
@@ -321,7 +313,7 @@ function WriteDotnetBindingEnvSetupBat
$out = @("@ECHO OFF
REM
-REM Call this command procedure from a command prompt to set up a $vsPlatform ($nBits-bit)
+REM Call this command procedure from a command prompt to set up a $vsPlatform ($nBits-bit)
REM $slnName environment
REM
REM > call $outfileName
@@ -337,56 +329,6 @@ ECHO Environment set for $slnName $vsPlatform $nBits-bit development.
$out | Out-File "$buildRoot\$outfileName" -encoding ASCII
}
-#############################
-# Return the SelectedItem from the dropdown list and close the form.
-#
-function Return-DropDown {
- if ($DropDown.SelectedItem -ne $null) {
- $global:cmakeGenerator = $DropDown.SelectedItem.ToString()
- $Form.Close()
- Write-Host "Selected generator: $global:cmakeGenerator"
- }
-}
-
-#############################
-# Create the CMake generator form and launch it
-#
-function SelectCMakeGenerator {
-
- $Form = New-Object System.Windows.Forms.Form
-
- $Form.width = 350
- $Form.height = 150
- $Form.Text = ”Select CMake Generator”
-
- $DropDown = new-object System.Windows.Forms.ComboBox
- $DropDown.Location = new-object System.Drawing.Size(120,10)
- $DropDown.Size = new-object System.Drawing.Size(150,30)
-
- ForEach ($Item in $global:VsVersionCmakeChoiceList) {
- $DropDown.Items.Add($Item)
- }
- $DropDown.SelectedIndex = 0
-
- $Form.Controls.Add($DropDown)
-
- $DropDownLabel = new-object System.Windows.Forms.Label
- $DropDownLabel.Location = new-object System.Drawing.Size(10,10)
- $DropDownLabel.size = new-object System.Drawing.Size(100,20)
- $DropDownLabel.Text = "CMake generators"
- $Form.Controls.Add($DropDownLabel)
-
- $Button = new-object System.Windows.Forms.Button
- $Button.Location = new-object System.Drawing.Size(120,50)
- $Button.Size = new-object System.Drawing.Size(120,20)
- $Button.Text = "Select a generator"
- $Button.Add_Click({Return-DropDown})
- $form.Controls.Add($Button)
-
- $Form.Add_Shown({$Form.Activate()})
- $Form.ShowDialog()
-}
-
#############################
# Main
@@ -399,12 +341,6 @@ function SelectCMakeGenerator {
[string] $cppDir = Resolve-Path (Join-Path $curDir "..\..\..")
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
-[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
-
-#############################
-# User dialog to select a version of Visual Studio as CMake generator
-#
-SelectCMakeGenerator
#############################
# User dialog to get optional 32-bit boost and build paths
@@ -476,7 +412,7 @@ if ($make32) {
$env:BOOST_ROOT = "$boost32"
cd "$build32"
Write-Host "Running 32-bit CMake in $build32 ..."
- CMake -G "$global:cmakeGenerator" "-DCMAKE_INSTALL_PREFIX=install_x86" $cppDir
+ CMake -G "Visual Studio 9 2008" "-DCMAKE_INSTALL_PREFIX=install_x86" $cppDir
} else {
Write-Host "Skipped 32-bit CMake."
}
@@ -488,7 +424,7 @@ if ($make64) {
$env:BOOST_ROOT = "$boost64"
cd "$build64"
Write-Host "Running 64-bit CMake in $build64"
- CMake -G "$global:cmakeGenerator Win64" "-DCMAKE_INSTALL_PREFIX=install_x64" $cppDir
+ CMake -G "Visual Studio 9 2008 Win64" "-DCMAKE_INSTALL_PREFIX=install_x64" $cppDir
} else {
Write-Host "Skipped 64-bit CMake."
}
@@ -501,7 +437,7 @@ if ($make64) {
if ($defined32) {
Write-Host "Writing 32-bit scripts..."
-
+
###########
# Powershell script to launch org.apache.qpid.messaging.sln
#
@@ -512,8 +448,8 @@ if ($defined32) {
-vsPlatform "x86" `
-nBits "32" `
-outfileName "start-devenv-messaging-x86-32bit.ps1"
-
-
+
+
###########
# Batch script (that you doubleclick) to launch powershell script
# that launches org.apache.qpid.messaging.sln.
@@ -546,7 +482,7 @@ if ($defined32) {
if ($defined64) {
Write-Host "Writing 64-bit scripts..."
-
+
###########
# Powershell script to launch org.apache.qpid.messaging.sln
#
@@ -557,8 +493,8 @@ if ($defined64) {
-vsPlatform "x64" `
-nBits "64" `
-outfileName "start-devenv-messaging-x64-64bit.ps1"
-
-
+
+
###########
# Batch script (that you doubleclick) to launch powershell script
# that launches org.apache.qpid.messaging.sln.
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.direct.receiver/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.direct.receiver/Properties/AssemblyInfo.cs
index 6976be5d02..abe35cf053 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.direct.receiver/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.direct.receiver/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,7 +23,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("csharp.direct.receiver")]
@@ -31,12 +31,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.direct.receiver")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -46,11 +46,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.direct.sender/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.direct.sender/Properties/AssemblyInfo.cs
index 12368def8e..18502a0666 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.direct.sender/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.direct.sender/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,7 +23,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("csharp.direct.sender")]
@@ -31,12 +31,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.direct.sender")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -46,11 +46,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/Properties/AssemblyInfo.cs
index 459130ec6c..a87f92ccdf 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/Properties/AssemblyInfo.cs
@@ -20,7 +20,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("csharp.map.callback.receiver")]
@@ -28,12 +28,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.map.callback.receiver")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -43,11 +43,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.sender/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.sender/Properties/AssemblyInfo.cs
index 2be4011f19..e633f76673 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.sender/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.sender/Properties/AssemblyInfo.cs
@@ -28,7 +28,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.map.callback.sender")]
-[assembly: AssemblyCopyright("Copyright 2010")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.map.receiver/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.map.receiver/Properties/AssemblyInfo.cs
index f11ce8c220..694d6b9ce1 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.map.receiver/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.map.receiver/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,7 +23,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("csharp.map.receiver")]
@@ -31,12 +31,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.map.receiver")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -46,11 +46,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.map.sender/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.map.sender/Properties/AssemblyInfo.cs
index ee09057f18..ea29ac2417 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.map.sender/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.map.sender/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,7 +23,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("csharp.map.sender")]
@@ -31,12 +31,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.map.sender")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -46,11 +46,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/dotnet/examples/visualbasic.example.client/MyProject/AssemblyInfo.vb b/cpp/bindings/qpid/dotnet/examples/visualbasic.example.client/MyProject/AssemblyInfo.vb
index 469d6ed5cf..d0727fe9fa 100644
--- a/cpp/bindings/qpid/dotnet/examples/visualbasic.example.client/MyProject/AssemblyInfo.vb
+++ b/cpp/bindings/qpid/dotnet/examples/visualbasic.example.client/MyProject/AssemblyInfo.vb
@@ -6,9 +6,9 @@
' to you under the Apache License, Version 2.0 (the
' "License"); you may not use this file except in compliance
' with the License. You may obtain a copy of the License at
-'
+'
' http://www.apache.org/licenses/LICENSE-2.0
-'
+'
' Unless required by applicable law or agreed to in writing,
' software distributed under the License is distributed on an
' "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,34 +21,34 @@ Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
-' General Information about an assembly is controlled through the following
+' General Information about an assembly is controlled through the following
' set of attributes. Change these attribute values to modify the information
' associated with an assembly.
' Review the values of the assembly attributes
-<Assembly: AssemblyTitle("visualbasic.example.client")>
-<Assembly: AssemblyDescription("")>
-<Assembly: AssemblyCompany("")>
-<Assembly: AssemblyProduct("visualbasic.example.client")>
-<Assembly: AssemblyCopyright("Copyright 2011")>
-<Assembly: AssemblyTrademark("")>
+<Assembly: AssemblyTitle("visualbasic.example.client")>
+<Assembly: AssemblyDescription("")>
+<Assembly: AssemblyCompany("Microsoft")>
+<Assembly: AssemblyProduct("visualbasic.example.client")>
+<Assembly: AssemblyCopyright("Copyright © Microsoft 2010")>
+<Assembly: AssemblyTrademark("")>
<Assembly: ComVisible(False)>
'The following GUID is for the ID of the typelib if this project is exposed to COM
-<Assembly: Guid("ec9df8cf-c1d4-4938-9e72-93fb81d55700")>
+<Assembly: Guid("ec9df8cf-c1d4-4938-9e72-93fb81d55700")>
' Version information for an assembly consists of the following four values:
'
' Major Version
-' Minor Version
+' Minor Version
' Build Number
' Revision
'
-' You can specify all the values or you can default the Build and Revision Numbers
+' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below:
-' <Assembly: AssemblyVersion("1.0.*")>
+' <Assembly: AssemblyVersion("1.0.*")>
-<Assembly: AssemblyVersion("1.0.0.0")>
-<Assembly: AssemblyFileVersion("1.0.0.0")>
+<Assembly: AssemblyVersion("1.0.0.0")>
+<Assembly: AssemblyFileVersion("1.0.0.0")>
diff --git a/cpp/bindings/qpid/dotnet/org.apache.qpid.messaging.sessionreceiver.sln b/cpp/bindings/qpid/dotnet/org.apache.qpid.messaging.sessionreceiver.sln
index edf8af4808..90e98a4bbe 100644
--- a/cpp/bindings/qpid/dotnet/org.apache.qpid.messaging.sessionreceiver.sln
+++ b/cpp/bindings/qpid/dotnet/org.apache.qpid.messaging.sessionreceiver.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
-#
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -8,9 +8,9 @@ Microsoft Visual Studio Solution File, Format Version 10.00
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
diff --git a/cpp/bindings/qpid/dotnet/src/Address.cpp b/cpp/bindings/qpid/dotnet/src/Address.cpp
index 79a8021d9a..b688d973ed 100644
--- a/cpp/bindings/qpid/dotnet/src/Address.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Address.cpp
@@ -141,7 +141,7 @@ namespace Messaging {
}
}
- // Copy constructor look-alike (C#)
+ // copy constructor
Address::Address(const Address ^ address)
{
System::Exception ^ newException = nullptr;
@@ -163,28 +163,6 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Address::Address(const Address % address)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- addressp = new ::qpid::messaging::Address(
- *(const_cast<Address %>(address).NativeAddress));
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
// unmanaged clone
Address::Address(const ::qpid::messaging::Address & addrp)
{
diff --git a/cpp/bindings/qpid/dotnet/src/Address.h b/cpp/bindings/qpid/dotnet/src/Address.h
index 8bbc207d4e..e5a00d8f11 100644
--- a/cpp/bindings/qpid/dotnet/src/Address.h
+++ b/cpp/bindings/qpid/dotnet/src/Address.h
@@ -64,7 +64,6 @@ namespace Messaging {
// copy constructor
Address(const Address ^ address);
- Address(const Address % address);
// unmanaged clone
Address(const ::qpid::messaging::Address & addrp);
diff --git a/cpp/bindings/qpid/dotnet/src/Connection.cpp b/cpp/bindings/qpid/dotnet/src/Connection.cpp
index 12c0e29f74..69ace7db52 100644
--- a/cpp/bindings/qpid/dotnet/src/Connection.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Connection.cpp
@@ -114,7 +114,7 @@ namespace Messaging {
}
- // Copy constructor look-alike (C#)
+ // Copy constructor
Connection::Connection(const Connection ^ connection)
{
System::Exception ^ newException = nullptr;
@@ -136,28 +136,6 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Connection::Connection(const Connection % connection)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- connectionp = new ::qpid::messaging::Connection(
- *(const_cast<Connection %>(connection).NativeConnection));
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
// Destructor
Connection::~Connection()
diff --git a/cpp/bindings/qpid/dotnet/src/Connection.h b/cpp/bindings/qpid/dotnet/src/Connection.h
index 0788f5d225..f9b62d4a08 100644
--- a/cpp/bindings/qpid/dotnet/src/Connection.h
+++ b/cpp/bindings/qpid/dotnet/src/Connection.h
@@ -56,7 +56,6 @@ namespace Messaging {
// copy constructor
Connection(const Connection ^ connection);
- Connection(const Connection % connection);
// unmanaged clone
// not defined
diff --git a/cpp/bindings/qpid/dotnet/src/Duration.h b/cpp/bindings/qpid/dotnet/src/Duration.h
index d4239fae88..213c338a59 100644
--- a/cpp/bindings/qpid/dotnet/src/Duration.h
+++ b/cpp/bindings/qpid/dotnet/src/Duration.h
@@ -81,17 +81,7 @@ namespace Messaging {
Duration ^ result = gcnew Duration(multiplier * dur->Milliseconds);
return result;
}
-
- static bool operator == (Duration ^ a, Duration ^ b)
- {
- return a->Milliseconds == b->Milliseconds;
- }
-
- static bool operator != (Duration ^ a, Duration ^ b)
- {
- return a->Milliseconds != b->Milliseconds;
- }
-};
+ };
public ref class DurationConstants sealed
{
diff --git a/cpp/bindings/qpid/dotnet/src/FailoverUpdates.h b/cpp/bindings/qpid/dotnet/src/FailoverUpdates.h
index d82e276fc8..1dd92b8688 100644
--- a/cpp/bindings/qpid/dotnet/src/FailoverUpdates.h
+++ b/cpp/bindings/qpid/dotnet/src/FailoverUpdates.h
@@ -54,7 +54,6 @@ namespace Messaging {
// copy constructor
FailoverUpdates(const FailoverUpdates ^ failoverUpdates) {}
- FailoverUpdates(const FailoverUpdates % failoverUpdates) {}
// assignment operator
FailoverUpdates % operator=(const FailoverUpdates % rhs)
diff --git a/cpp/bindings/qpid/dotnet/src/Message.cpp b/cpp/bindings/qpid/dotnet/src/Message.cpp
index e5dbf845b3..fe7825134d 100644
--- a/cpp/bindings/qpid/dotnet/src/Message.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Message.cpp
@@ -235,7 +235,7 @@ namespace Messaging {
}
}
- // Copy constructor look-alike (C#)
+ // Copy constructor
Message::Message(const Message ^ message)
{
System::Exception ^ newException = nullptr;
@@ -257,29 +257,7 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Message::Message(const Message % message)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- messagep = new ::qpid::messaging::Message(
- *(const_cast<Message %>(message).NativeMessage));
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
- // Property
+ // Property
void Message::SetProperty(System::String ^ name, System::Object ^ value)
{
System::Exception ^ newException = nullptr;
diff --git a/cpp/bindings/qpid/dotnet/src/Message.h b/cpp/bindings/qpid/dotnet/src/Message.h
index ac7f285fe5..b92cc4200b 100644
--- a/cpp/bindings/qpid/dotnet/src/Message.h
+++ b/cpp/bindings/qpid/dotnet/src/Message.h
@@ -71,7 +71,6 @@ namespace Messaging {
// Copy constructor
Message(const Message ^ message);
- Message(const Message % message);
// unmanaged clone
Message(const ::qpid::messaging::Message & msgp);
diff --git a/cpp/bindings/qpid/dotnet/src/Receiver.cpp b/cpp/bindings/qpid/dotnet/src/Receiver.cpp
index 8aa77effbd..3c0d79b393 100644
--- a/cpp/bindings/qpid/dotnet/src/Receiver.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Receiver.cpp
@@ -89,7 +89,7 @@ namespace Messaging {
}
- // Copy constructor look-alike (C#)
+ // Copy constructor
Receiver::Receiver(const Receiver ^ receiver) :
parentSession(receiver->parentSession)
{
@@ -112,29 +112,6 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Receiver::Receiver(const Receiver % receiver) :
- parentSession(receiver.parentSession)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- receiverp = new ::qpid::messaging::Receiver(
- *(const_cast<Receiver %>(receiver).NativeReceiver));
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
//
// Get(message)
diff --git a/cpp/bindings/qpid/dotnet/src/Receiver.h b/cpp/bindings/qpid/dotnet/src/Receiver.h
index 8ddcc9ac01..e9912a61dd 100644
--- a/cpp/bindings/qpid/dotnet/src/Receiver.h
+++ b/cpp/bindings/qpid/dotnet/src/Receiver.h
@@ -65,7 +65,6 @@ namespace Messaging {
// copy constructor
Receiver(const Receiver ^ receiver);
- Receiver(const Receiver % receiver);
// unmanaged clone
// undefined
diff --git a/cpp/bindings/qpid/dotnet/src/Sender.cpp b/cpp/bindings/qpid/dotnet/src/Sender.cpp
index 3225f1a6e1..584075ef5f 100644
--- a/cpp/bindings/qpid/dotnet/src/Sender.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Sender.cpp
@@ -84,7 +84,7 @@ namespace Messaging {
}
- // Copy constructor look-alike (C#)
+ // Copy constructor
Sender::Sender(const Sender ^ sender)
: parentSession(sender->parentSession)
{
@@ -107,29 +107,6 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Sender::Sender(const Sender % sender)
- : parentSession(sender.parentSession)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- senderp = new ::qpid::messaging::Sender(
- *(const_cast<Sender %>(sender).NativeSender));
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
//
// Send(msg)
diff --git a/cpp/bindings/qpid/dotnet/src/Sender.h b/cpp/bindings/qpid/dotnet/src/Sender.h
index 4054e87316..0e90a9f4a4 100644
--- a/cpp/bindings/qpid/dotnet/src/Sender.h
+++ b/cpp/bindings/qpid/dotnet/src/Sender.h
@@ -62,7 +62,6 @@ namespace Messaging {
// copy constructor
Sender(const Sender ^ sender);
- Sender(const Sender % sender);
~Sender();
!Sender();
diff --git a/cpp/bindings/qpid/dotnet/src/Session.cpp b/cpp/bindings/qpid/dotnet/src/Session.cpp
index 0e918769a3..880331c588 100644
--- a/cpp/bindings/qpid/dotnet/src/Session.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Session.cpp
@@ -89,7 +89,7 @@ namespace Messaging {
}
- // Copy constructor look-alike (C#)
+ // Copy constructor
Session::Session(const Session ^ session)
: parentConnectionp(session->parentConnectionp)
{
@@ -113,30 +113,6 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Session::Session(const Session % session)
- : parentConnectionp(session.parentConnectionp)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- sessionp = new ::qpid::messaging::Session(
- *(const_cast<Session %>(session).NativeSession));
-
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
void Session::Close()
{
@@ -248,31 +224,6 @@ namespace Messaging {
}
}
- void Session::AcknowledgeUpTo(Message ^ message)
- {
- AcknowledgeUpTo(message, false);
- }
-
- void Session::AcknowledgeUpTo(Message ^ message, bool sync)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- sessionp->acknowledgeUpTo(*(message->NativeMessage), sync);
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
void Session::Reject(Message ^ message)
{
System::Exception ^ newException = nullptr;
diff --git a/cpp/bindings/qpid/dotnet/src/Session.h b/cpp/bindings/qpid/dotnet/src/Session.h
index 4b98a37f18..7eaad8a0a5 100644
--- a/cpp/bindings/qpid/dotnet/src/Session.h
+++ b/cpp/bindings/qpid/dotnet/src/Session.h
@@ -69,7 +69,6 @@ namespace Messaging {
// copy constructor
Session(const Session ^ session);
- Session(const Session % session);
~Session();
!Session();
@@ -104,8 +103,6 @@ namespace Messaging {
void Acknowledge(bool sync);
void Acknowledge(Message ^ message);
void Acknowledge(Message ^ message, bool sync);
- void AcknowledgeUpTo(Message ^ message);
- void AcknowledgeUpTo(Message ^ message, bool sync);
void Reject(Message ^);
void Release(Message ^);
void Sync();
diff --git a/cpp/bindings/qpid/dotnet/test/messaging.test/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/test/messaging.test/Properties/AssemblyInfo.cs
index 81a89ce393..cf50e88200 100644
--- a/cpp/bindings/qpid/dotnet/test/messaging.test/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/test/messaging.test/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,7 +23,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("messaging.test")]
@@ -31,12 +31,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("messaging.test")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -46,11 +46,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/examples/perl/client.pl b/cpp/bindings/qpid/examples/perl/client.pl
index 19d9d3f14f..93eec88e07 100644
--- a/cpp/bindings/qpid/examples/perl/client.pl
+++ b/cpp/bindings/qpid/examples/perl/client.pl
@@ -20,13 +20,13 @@
use strict;
use warnings;
-use cqpid_perl;
+use cqpid;
my $url = ( @ARGV == 1 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672";
my $connectionOptions = ( @ARGV > 1 ) ? $ARGV[1] : "";
-my $connection = new cqpid_perl::Connection($url, $connectionOptions);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
@@ -35,7 +35,7 @@ my $session = $connection->createSession();
my $sender = $session->createSender("service_queue");
#create temp queue & receiver...
-my $responseQueue = new cqpid_perl::Address("#response-queue; {create:always, delete:always}");
+my $responseQueue = new cqpid::Address("#response-queue; {create:always, delete:always}");
my $receiver = $session->createReceiver($responseQueue);
#Now send some messages...
@@ -47,7 +47,7 @@ my @s = (
"And the mome raths outgrabe."
);
-my $request = new cqpid_perl::Message();
+my $request = new cqpid::Message();
$request->setReplyTo($responseQueue);
for (my $i=0; $i<4; $i++) {
$request->setContent($s[$i]);
diff --git a/cpp/bindings/qpid/examples/perl/drain.pl b/cpp/bindings/qpid/examples/perl/drain.pl
index 60ac0c50ed..8010b7c95b 100644
--- a/cpp/bindings/qpid/examples/perl/drain.pl
+++ b/cpp/bindings/qpid/examples/perl/drain.pl
@@ -20,7 +20,7 @@
use strict;
use warnings;
-use cqpid_perl;
+use cqpid;
use Getopt::Long;
my $url = "127.0.0.1";
@@ -47,11 +47,11 @@ if ($#ARGV ge 0) {
}
sub getTimeout {
- return ($forever) ? $cqpid_perl::Duration::FOREVER : new cqpid_perl::Duration($timeout*1000);
+ return ($forever) ? $cqpid::Duration::FOREVER : new cqpid::Duration($timeout*1000);
}
-my $connection = new cqpid_perl::Connection($url, $connectionOptions);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
@@ -59,13 +59,13 @@ eval {
my $receiver = $session->createReceiver($address);
my $timeout = getTimeout();
- my $message = new cqpid_perl::Message();
+ my $message = new cqpid::Message();
my $i = 0;
while($receiver->fetch($message, $timeout)) {
print "Message(properties=" . $message->getProperties() . ",content='";
if ($message->getContentType() eq "amqp/map") {
- my $content = cqpid_perl::decodeMap($message);
+ my $content = cqpid::decodeMap($message);
map{ print "\n$_ => $content->{$_}"; } keys %{$content};
}
else {
@@ -77,7 +77,7 @@ eval {
if ($replyto->getName()) {
print "Replying to " . $message->getReplyTo()->str() . "...\n";
my $sender = $session->createSender($replyto);
- my $response = new cqpid_perl::Message("received by the server.");
+ my $response = new cqpid::Message("received by the server.");
$sender->send($response);
}
$session->acknowledge();
diff --git a/cpp/bindings/qpid/examples/perl/hello_world.pl b/cpp/bindings/qpid/examples/perl/hello_world.pl
index a96b98a002..cf2f05f8b7 100644
--- a/cpp/bindings/qpid/examples/perl/hello_world.pl
+++ b/cpp/bindings/qpid/examples/perl/hello_world.pl
@@ -21,13 +21,13 @@ use strict;
use warnings;
use Data::Dumper;
-use cqpid_perl;
+use cqpid;
my $broker = ( @ARGV > 0 ) ? $ARGV[0] : "localhost:5672";
my $address = ( @ARGV > 1 ) ? $ARGV[0] : "amq.topic";
my $connectionOptions = ( @ARGV > 2 ) ? $ARGV[1] : "";
-my $connection = new cqpid_perl::Connection($broker, $connectionOptions);
+my $connection = new cqpid::Connection($broker, $connectionOptions);
eval {
$connection->open();
@@ -36,12 +36,12 @@ eval {
my $receiver = $session->createReceiver($address);
my $sender = $session->createSender($address);
- $sender->send(new cqpid_perl::Message("Hello world!"));
+ $sender->send(new cqpid::Message("Hello world!"));
- #my $duration = new cqpid_perl::Duration(1000);
+ #my $duration = new cqpid::Duration(1000);
#print ">>>" . $duration->getMilliseconds() . "\n";
- my $message = $receiver->fetch($cqpid_perl::Duration::SECOND);
+ my $message = $receiver->fetch($cqpid::Duration::SECOND);
#$message->setDurable(1);
#print "Durable: " . $message->getDurable() . "\n";
diff --git a/cpp/bindings/qpid/examples/perl/hello_xml.pl b/cpp/bindings/qpid/examples/perl/hello_xml.pl
index cebf2ceee6..c48a5225c2 100644
--- a/cpp/bindings/qpid/examples/perl/hello_xml.pl
+++ b/cpp/bindings/qpid/examples/perl/hello_xml.pl
@@ -20,7 +20,7 @@
use strict;
use warnings;
-use cqpid_perl;
+use cqpid;
my $broker = ( @ARGV > 0 ) ? $ARGV[0] : "localhost:5672";
my $connectionOptions = ( @ARGV > 1 ) ? $ARGV[1] : "";
@@ -44,7 +44,7 @@ x-bindings: [{ exchange: xml-exchange, key: weather, arguments: { xquery:" $quer
END
-my $connection = new cqpid_perl::Connection($broker, $connectionOptions);
+my $connection = new cqpid::Connection($broker, $connectionOptions);
eval {
$connection->open();
@@ -52,7 +52,7 @@ eval {
my $receiver = $session->createReceiver($address);
- my $message = new cqpid_perl::Message();
+ my $message = new cqpid::Message();
my $content = <<END;
<weather>
diff --git a/cpp/bindings/qpid/examples/perl/map_receiver.pl b/cpp/bindings/qpid/examples/perl/map_receiver.pl
index 2e2611e38f..e3e8a201dd 100644
--- a/cpp/bindings/qpid/examples/perl/map_receiver.pl
+++ b/cpp/bindings/qpid/examples/perl/map_receiver.pl
@@ -21,21 +21,21 @@ use strict;
use warnings;
use Data::Dumper;
-use cqpid_perl;
+use cqpid;
my $url = ( @ARGV > 0 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672";
my $address = ( @ARGV > 1 ) ? $ARGV[0] : "message_queue; {create: always}";
my $connectionOptions = ( @ARGV > 2 ) ? $ARGV[1] : "";
-my $connection = new cqpid_perl::Connection($url, $connectionOptions);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
my $session = $connection->createSession();
my $receiver = $session->createReceiver($address);
- my $content = cqpid_perl::decodeMap($receiver->fetch());
- #my $content = cqpid_perl::decodeList($receiver->fetch());
+ my $content = cqpid::decodeMap($receiver->fetch());
+ #my $content = cqpid::decodeList($receiver->fetch());
print Dumper($content);
diff --git a/cpp/bindings/qpid/examples/perl/map_sender.pl b/cpp/bindings/qpid/examples/perl/map_sender.pl
index 4107cd48b9..095acce0ab 100644
--- a/cpp/bindings/qpid/examples/perl/map_sender.pl
+++ b/cpp/bindings/qpid/examples/perl/map_sender.pl
@@ -21,13 +21,13 @@ use strict;
use warnings;
use Data::Dumper;
-use cqpid_perl;
+use cqpid;
my $url = ( @ARGV > 0 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672";
my $address = ( @ARGV > 1 ) ? $ARGV[1] : "message_queue; {create: always}";
my $connectionOptions = ( @ARGV > 2 ) ? $ARGV[2] : "";
-my $connection = new cqpid_perl::Connection($url, $connectionOptions);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
@@ -35,13 +35,13 @@ eval {
my $session = $connection->createSession();
my $sender = $session->createSender($address);
- my $message = new cqpid_perl::Message();
+ my $message = new cqpid::Message();
my $content = { id => 987654321,
name => "Widget",
percent => sprintf("%.2f", 0.99),
colours => [ qw (red green white) ],
};
- cqpid_perl::encode($content, $message);
+ cqpid::encode($content, $message);
$sender->send($message, 1);
$connection->close();
diff --git a/cpp/bindings/qpid/examples/perl/server.pl b/cpp/bindings/qpid/examples/perl/server.pl
index b14da565b9..0c64f15c66 100644
--- a/cpp/bindings/qpid/examples/perl/server.pl
+++ b/cpp/bindings/qpid/examples/perl/server.pl
@@ -20,13 +20,13 @@
use strict;
use warnings;
-use cqpid_perl;
+use cqpid;
my $url = ( @ARGV == 1 ) ? $ARGV[0] : "amqp:tcp:127.0.0.1:5672";
my $connectionOptions = ( @ARGV > 1 ) ? $ARGV[1] : "";
-my $connection = new cqpid_perl::Connection($url, $connectionOptions);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
@@ -41,7 +41,7 @@ eval {
my $sender = $session->createSender($address);
my $s = $request->getContent();
$s = uc($s);
- my $response = new cqpid_perl::Message($s);
+ my $response = new cqpid::Message($s);
$sender->send($response);
print "Processed request: " . $request->getContent() . " -> " . $response->getContent() . "\n";
$session->acknowledge();
diff --git a/cpp/bindings/qpid/examples/perl/spout.pl b/cpp/bindings/qpid/examples/perl/spout.pl
index 7365e732bf..50773a4fe2 100644
--- a/cpp/bindings/qpid/examples/perl/spout.pl
+++ b/cpp/bindings/qpid/examples/perl/spout.pl
@@ -20,7 +20,7 @@
use strict;
use warnings;
-use cqpid_perl;
+use cqpid;
use Getopt::Long;
use Time::Local;
@@ -77,19 +77,19 @@ sub setProperties {
}
}
-my $connection = new cqpid_perl::Connection($url, $connectionOptions);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
my $session = $connection->createSession();
my $sender = $session->createSender($address);
- my $message = new cqpid_perl::Message();
+ my $message = new cqpid::Message();
setProperties($message) if (@properties);
if (@entries) {
my $content = {};
setEntries($content);
- cqpid_perl::encode($content, $message);
+ cqpid::encode($content, $message);
}
elsif ($content) {
$message->setContent($content);
@@ -98,7 +98,7 @@ eval {
my $receiver;
if ($replyto) {
- my $responseQueue = new cqpid_perl::Address($replyto);
+ my $responseQueue = new cqpid::Address($replyto);
$receiver = $session->createReceiver($responseQueue);
$message->setReplyTo($responseQueue);
}
diff --git a/cpp/bindings/qpid/perl/CMakeLists.txt b/cpp/bindings/qpid/perl/CMakeLists.txt
deleted file mode 100644
index 6edaf284b1..0000000000
--- a/cpp/bindings/qpid/perl/CMakeLists.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-##------------------------------------------------------
-## Use Swig to generate a literal binding to the C++ API
-##------------------------------------------------------
-set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/perl.i PROPERTIES CPLUSPLUS ON)
-set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/perl.i PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include")
-
-swig_add_module(cqpid_perl perl ${CMAKE_CURRENT_SOURCE_DIR}/perl.i)
-swig_link_libraries(cqpid_perl qpidmessaging qpidtypes qmf2 ${PERL_LIBRARY})
-
-set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -I${PERL_INCLUDE_PATH} -I${qpid-cpp_SOURCE_DIR}/include")
-
-##----------------------------------
-## Install the complete Perl binding
-##----------------------------------
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcqpid_perl.so
- ${CMAKE_CURRENT_BINARY_DIR}/cqpid_perl.pm
- DESTINATION ${PERL_VENDORARCH}
- COMPONENT ${QPID_COMPONENT_CLIENT}
- )
diff --git a/cpp/bindings/qpid/perl/Makefile.am b/cpp/bindings/qpid/perl/Makefile.am
index da082896e8..982d493ba0 100644
--- a/cpp/bindings/qpid/perl/Makefile.am
+++ b/cpp/bindings/qpid/perl/Makefile.am
@@ -21,22 +21,22 @@ if HAVE_PERL_DEVEL
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src -I$(PERL_INC)
-EXTRA_DIST = CMakeLists.txt perl.i
-BUILT_SOURCES = cqpid_perl.cpp
+EXTRA_DIST = perl.i
+BUILT_SOURCES = cqpid.cpp
SWIG_FLAGS = -w362,401
-cqpid_perl.cpp: $(srcdir)/perl.i $(srcdir)/../qpid.i $(srcdir)/../../swig_perl_typemaps.i
- $(SWIG) -perl -c++ $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqpid_perl.cpp $(srcdir)/perl.i
+cqpid.cpp: $(srcdir)/perl.i $(srcdir)/../qpid.i $(srcdir)/../../swig_perl_typemaps.i
+ $(SWIG) -perl -c++ $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqpid.cpp $(srcdir)/perl.i
-lib_LTLIBRARIES = libcqpid_perl.la
-cqpid_perl_PERL = cqpid_perl.pm
+lib_LTLIBRARIES = cqpid.la
+cqpid_PERL = cqpid.pm
-libcqpid_perl_la_LDFLAGS = -avoid-version -shared
-libcqpid_perl_la_LIBADD = -L$(top_builddir)/src/.libs -lqpidmessaging -lqpidtypes \
+cqpid_la_LDFLAGS = -avoid-version -module -shared
+cqpid_la_LIBADD = -L$(top_builddir)/src/.libs -lqpidmessaging -lqpidtypes \
$(top_builddir)/src/libqpidmessaging.la $(top_builddir)/src/libqpidtypes.la
-libcqpid_perl_la_CXXFLAGS = $(INCLUDES) -fno-strict-aliasing
-nodist_libcqpid_perl_la_SOURCES = cqpid_perl.cpp
+cqpid_la_CXXFLAGS = $(INCLUDES)
+nodist_cqpid_la_SOURCES = cqpid.cpp
-CLEANFILES = cqpid_perl.cpp cqpid_perl.pm
+CLEANFILES = cqpid.cpp cqpid.pm
endif # HAVE_PERL_DEVEL
diff --git a/cpp/bindings/qpid/perl/perl.i b/cpp/bindings/qpid/perl/perl.i
index 38ac91761f..b7ae0568b6 100644
--- a/cpp/bindings/qpid/perl/perl.i
+++ b/cpp/bindings/qpid/perl/perl.i
@@ -17,7 +17,7 @@
* under the License.
*/
-%module cqpid_perl
+%module cqpid
%include "std_string.i"
%include "../../swig_perl_typemaps.i"
diff --git a/cpp/bindings/qpid/python/CMakeLists.txt b/cpp/bindings/qpid/python/CMakeLists.txt
deleted file mode 100644
index 5e4649cd7c..0000000000
--- a/cpp/bindings/qpid/python/CMakeLists.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-##------------------------------------------------------
-## Use Swig to generate a literal binding to the C++ API
-##------------------------------------------------------
-set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i PROPERTIES CPLUSPLUS ON)
-set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/python.i PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include")
-
-swig_add_module(cqpid python ${CMAKE_CURRENT_SOURCE_DIR}/python.i)
-swig_link_libraries(cqpid qpidmessaging qpidtypes qmf2 ${PYTHON_LIBRARIES})
-
-set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -I${PYTHON_INCLUDE_PATH} -I${qpid-cpp_SOURCE_DIR}/include")
-
-##------------------------------------
-## Install the complete Python binding
-##------------------------------------
-execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
-install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile cqpid.py
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
-install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile cqpid.py
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cqpid.py
- ${CMAKE_CURRENT_BINARY_DIR}/cqpid.pyc
- ${CMAKE_CURRENT_BINARY_DIR}/cqpid.pyo
- ${CMAKE_CURRENT_BINARY_DIR}/_cqpid.so
- DESTINATION ${PYTHON_SITE_PACKAGES}
- COMPONENT ${QPID_COMPONENT_CLIENT}
- )
diff --git a/cpp/bindings/qpid/python/Makefile.am b/cpp/bindings/qpid/python/Makefile.am
index dd25f34829..7fa4106be0 100644
--- a/cpp/bindings/qpid/python/Makefile.am
+++ b/cpp/bindings/qpid/python/Makefile.am
@@ -25,17 +25,17 @@ generated_file_list = \
cqpid.cpp \
cqpid.py
-EXTRA_DIST = CMakeLists.txt python.i
+EXTRA_DIST = python.i
BUILT_SOURCES = $(generated_file_list)
SWIG_FLAGS = -w362,401
$(generated_file_list): $(srcdir)/python.i $(srcdir)/../qpid.i $(srcdir)/../../swig_python_typemaps.i
- $(SWIG) -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I$(top_srcdir)/src/qmf -I/usr/include -o cqpid.cpp $(srcdir)/python.i
+ swig -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I$(top_srcdir)/src/qmf -I/usr/include -o cqpid.cpp $(srcdir)/python.i
pylibdir = $(PYTHON_LIB)
lib_LTLIBRARIES = _cqpid.la
-cqpiddir = $(pyexecdir)
+cqpiddir = $(pythondir)
cqpid_PYTHON = cqpid.py
_cqpid_la_LDFLAGS = -avoid-version -module -shared
diff --git a/cpp/bindings/qpid/python/python.i b/cpp/bindings/qpid/python/python.i
index 9d45bf54ee..bf61cb10b7 100644
--- a/cpp/bindings/qpid/python/python.i
+++ b/cpp/bindings/qpid/python/python.i
@@ -21,357 +21,21 @@
%include "std_string.i"
%include "../../swig_python_typemaps.i"
-/* Needed for get/setPriority methods. Surprising SWIG 1.3.40 doesn't
- * convert uint8_t by default. */
-%apply unsigned char { uint8_t };
-
-
-/*
- * Exceptions
- *
- * The convention below is that exceptions in _cqpid.so have the same
- * names as in the C++ library. They get renamed to their Python
- * equivalents when brought into the Python wrapping
- */
-%{
-static PyObject* pNoMessageAvailable;
-static PyObject* pTargetCapacityExceeded;
-static PyObject* pNotFound;
-static PyObject* pTransportFailure;
-%}
-
-%init %{
- pNoMessageAvailable = PyErr_NewException(
- "_cqpid.NoMessageAvailable", NULL, NULL);
- Py_INCREF(pNoMessageAvailable);
- PyModule_AddObject(m, "NoMessageAvailable", pNoMessageAvailable);
-
- pTargetCapacityExceeded = PyErr_NewException(
- "_cqpid.TargetCapacityExceeded", NULL, NULL);
- Py_INCREF(pTargetCapacityExceeded);
- PyModule_AddObject(m, "TargetCapacityExceeded", pTargetCapacityExceeded);
-
- pNotFound = PyErr_NewException(
- "_cqpid.NotFound", NULL, NULL);
- Py_INCREF(pNotFound);
- PyModule_AddObject(m, "NotFound", pNotFound);
-
- pTransportFailure = PyErr_NewException(
- "_cqpid.TransportFailure", NULL, NULL);
- Py_INCREF(pTransportFailure);
- PyModule_AddObject(m, "TransportFailure", pTransportFailure);
-%}
-
-%pythoncode %{
- Empty = _cqpid.NoMessageAvailable
- TargetCapacityExceeded = _cqpid.TargetCapacityExceeded
- NotFound = _cqpid.NotFound
- ConnectError = _cqpid.TransportFailure
-%}
-
/* Define the general-purpose exception handling */
%exception {
- PyObject * pExceptionType = NULL;
std::string error;
Py_BEGIN_ALLOW_THREADS;
try {
$action
- } catch (qpid::messaging::NoMessageAvailable & ex) {
- pExceptionType = pNoMessageAvailable;
- error = ex.what();
- } catch (qpid::messaging::TargetCapacityExceeded & ex) {
- pExceptionType = pTargetCapacityExceeded;
- error = ex.what();
- } catch (qpid::messaging::NotFound & ex) {
- pExceptionType = pNotFound;
- error = ex.what();
- } catch (qpid::messaging::TransportFailure & ex) {
- pExceptionType = pTransportFailure;
- error = ex.what();
} catch (qpid::types::Exception& ex) {
- pExceptionType = PyExc_RuntimeError;
error = ex.what();
}
Py_END_ALLOW_THREADS;
if (!error.empty()) {
- PyErr_SetString(pExceptionType, error.c_str());
+ PyErr_SetString(PyExc_RuntimeError, error.c_str());
return NULL;
}
}
-
-/* This only renames the non-const version (I believe). Then again, I
- * don't even know why there is a non-const version of the method. */
-%rename(opened) qpid::messaging::Connection::isOpen();
-%rename(receiver) qpid::messaging::Session::createReceiver;
-%rename(sender) qpid::messaging::Session::createSender;
-%rename(_acknowledge_all) qpid::messaging::Session::acknowledge(bool);
-%rename(_acknowledge_msg) qpid::messaging::Session::acknowledge(
- Message &, bool);
-
-%rename(_fetch) qpid::messaging::Receiver::fetch;
-%rename(unsettled) qpid::messaging::Receiver::getUnsettled;
-%rename(available) qpid::messaging::Receiver::getAvailable;
-
-%rename(unsettled) qpid::messaging::Sender::getUnsettled;
-%rename(available) qpid::messaging::Sender::getAvailable;
-%rename(_send) qpid::messaging::Sender::send;
-
-%rename(_getReplyTo) qpid::messaging::Message::getReplyTo;
-%rename(_setReplyTo) qpid::messaging::Message::setReplyTo;
-%rename(_getTtl) qpid::messaging::Message::getTtl;
-%rename(_setTtl) qpid::messaging::Message::setTtl;
-
-
%include "../qpid.i"
-%extend qpid::messaging::Connection {
- %pythoncode %{
- # Handle the different options by converting underscores to hyphens.
- # Also, the sasl_mechanisms option in Python has no direct
- # equivalent in C++, so we will translate them to sasl_mechanism
- # when possible.
- def __init__(self, url=None, **options):
- args = [url] if url else []
- if options :
- if "sasl_mechanisms" in options :
- if ' ' in options.get("sasl_mechanisms",'') :
- raise Exception(
- "C++ Connection objects are unable to handle "
- "multiple sasl-mechanisms")
- options["sasl_mechanism"] = options.pop("sasl_mechanisms")
- args.append(options)
- this = _cqpid.new_Connection(*args)
- try: self.this.append(this)
- except: self.this = this
- %}
-
- /* Return a pre-existing session with the given name, if one
- * exists, otherwise return a new one. (Note that if a
- * pre-existing session exists, the transactional argument is
- * ignored, and the returned session might not satisfy the desired
- * setting. */
- qpid::messaging::Session _session(const std::string & name,
- bool transactional) {
- if (!name.empty()) {
- try {
- return self->getSession(name);
- }
- catch (const qpid::messaging::KeyError &) {
- }
- }
- if (transactional) {
- return self->createTransactionalSession(name);
- }
- else {
- return self->createSession(name);
- }
- }
-
- %pythoncode %{
- def session(self, name=None, transactional=False) :
- if name is None :
- name = ''
- return self._session(name, transactional)
- %}
-
- %pythoncode %{
- @staticmethod
- def establish(url=None, **options) :
- conn = Connection(url, **options)
- conn.open()
- return conn
- %}
-}
-
-%extend qpid::messaging::Session {
- %pythoncode %{
- def acknowledge(self, message=None, disposition=None, sync=True) :
- if disposition :
- raise Exception("SWIG does not support dispositions yet. Use "
- "Session.reject and Session.release instead")
- if message :
- self._acknowledge_msg(message, sync)
- else :
- self._acknowledge_all(sync)
-
- __swig_getmethods__["connection"] = getConnection
- if _newclass: connection = _swig_property(getConnection)
- %}
-}
-
-
-%extend qpid::messaging::Receiver {
- %pythoncode %{
- __swig_getmethods__["capacity"] = getCapacity
- __swig_setmethods__["capacity"] = setCapacity
- if _newclass: capacity = _swig_property(getCapacity, setCapacity)
-
- __swig_getmethods__["session"] = getSession
- if _newclass: session = _swig_property(getSession)
- %}
-
- %pythoncode %{
- def fetch(self, timeout=None) :
- if timeout is None :
- return self._fetch()
- else :
- # Python API uses timeouts in seconds,
- # but C++ API uses milliseconds
- return self._fetch(Duration(int(1000*timeout)))
- %}
-}
-
-%extend qpid::messaging::Sender {
- %pythoncode %{
- def send(self, object, sync=True) :
- if isinstance(object, Message):
- message = object
- else:
- message = Message(object)
- return self._send(message, sync)
-
- __swig_getmethods__["capacity"] = getCapacity
- __swig_setmethods__["capacity"] = setCapacity
- if _newclass: capacity = _swig_property(getCapacity, setCapacity)
-
- __swig_getmethods__["session"] = getSession
- if _newclass: session = _swig_property(getSession)
- %}
-}
-
-
-%extend qpid::messaging::Message {
- %pythoncode %{
- # UNSPECIFIED was module level before, but I do not
- # know how to insert python code at the top of the module.
- # (A bare "%pythoncode" inserts at the end.
- UNSPECIFIED=object()
- def __init__(self, content=None, content_type=UNSPECIFIED, id=None,
- subject=None, user_id=None, reply_to=None,
- correlation_id=None, durable=None, priority=None,
- ttl=None, properties=None):
- this = _cqpid.new_Message('')
- try: self.this.append(this)
- except: self.this = this
- if content :
- self.content = content
- if content_type != UNSPECIFIED :
- self.content_type = content_type
- if id is not None :
- self.id = id
- if subject is not None :
- self.subject = subject
- if user_id is not None :
- self.user_id = user_id
- if reply_to is not None :
- self.reply_to = reply_to
- if correlation_id is not None :
- self.correlation_id = correlation_id
- if durable is not None :
- self.durable = durable
- if priority is not None :
- self.priority = priority
- if ttl is not None :
- self.ttl = ttl
- if properties is not None :
- # Can't set properties via (inst).getProperties, because
- # the typemaps make a copy of the underlying properties.
- # Instead, set via setProperty for the time-being
- for k, v in properties.iteritems() :
- self.setProperty(k, v)
-
- def _get_content(self) :
- if self.content_type == "amqp/list" :
- return decodeList(self)
- if self.content_type == "amqp/map" :
- return decodeMap(self)
- return self.getContent()
- def _set_content(self, content) :
- if isinstance(content, basestring) :
- self.setContent(content)
- elif isinstance(content, list) or isinstance(content, dict) :
- encode(content, self)
- else :
- # Not a type we can handle. Try setting it anyway,
- # although this will probably lead to a swig error
- self.setContent(content)
- __swig_getmethods__["content"] = _get_content
- __swig_setmethods__["content"] = _set_content
- if _newclass: content = _swig_property(_get_content, _set_content)
-
- __swig_getmethods__["content_type"] = getContentType
- __swig_setmethods__["content_type"] = setContentType
- if _newclass: content_type = _swig_property(getContentType,
- setContentType)
-
- __swig_getmethods__["id"] = getMessageId
- __swig_setmethods__["id"] = setMessageId
- if _newclass: id = _swig_property(getMessageId, setMessageId)
-
- __swig_getmethods__["subject"] = getSubject
- __swig_setmethods__["subject"] = setSubject
- if _newclass: subject = _swig_property(getSubject, setSubject)
-
- __swig_getmethods__["priority"] = getPriority
- __swig_setmethods__["priority"] = setPriority
- if _newclass: priority = _swig_property(getPriority, setPriority)
-
- def getTtl(self) :
- return self._getTtl().getMilliseconds()/1000.0
- def setTtl(self, duration) :
- self._setTtl(Duration(int(1000*duration)))
- __swig_getmethods__["ttl"] = getTtl
- __swig_setmethods__["ttl"] = setTtl
- if _newclass: ttl = _swig_property(getTtl, setTtl)
-
- __swig_getmethods__["user_id"] = getUserId
- __swig_setmethods__["user_id"] = setUserId
- if _newclass: user_id = _swig_property(getUserId, setUserId)
-
- __swig_getmethods__["correlation_id"] = getCorrelationId
- __swig_setmethods__["correlation_id"] = setCorrelationId
- if _newclass: correlation_id = _swig_property(getCorrelationId,
- setCorrelationId)
-
- __swig_getmethods__["redelivered"] = getRedelivered
- __swig_setmethods__["redelivered"] = setRedelivered
- if _newclass: redelivered = _swig_property(getRedelivered,
- setRedelivered)
-
- __swig_getmethods__["durable"] = getDurable
- __swig_setmethods__["durable"] = setDurable
- if _newclass: durable = _swig_property(getDurable, setDurable)
-
- __swig_getmethods__["properties"] = getProperties
- if _newclass: properties = _swig_property(getProperties)
-
- def getReplyTo(self) :
- return self._getReplyTo().str()
- def setReplyTo(self, address_str) :
- self._setReplyTo(Address(address_str))
- __swig_getmethods__["reply_to"] = getReplyTo
- __swig_setmethods__["reply_to"] = setReplyTo
- if _newclass: reply_to = _swig_property(getReplyTo, setReplyTo)
-
- def __repr__(self):
- args = []
- for name in ["id", "subject", "user_id", "reply_to",
- "correlation_id", "priority", "ttl",
- "durable", "redelivered", "properties",
- "content_type"] :
- value = getattr(self, name)
- if value : args.append("%s=%r" % (name, value))
- if self.content is not None:
- if args:
- args.append("content=%r" % self.content)
- else:
- args.append(repr(self.content))
- return "Message(%s)" % ", ".join(args)
- %}
-}
-
-%pythoncode %{
-# Bring into module scope
-UNSPECIFIED = Message.UNSPECIFIED
-%}
diff --git a/cpp/bindings/qpid/qpid.i b/cpp/bindings/qpid/qpid.i
index 352bafa3c8..e60ce1ce7c 100644
--- a/cpp/bindings/qpid/qpid.i
+++ b/cpp/bindings/qpid/qpid.i
@@ -27,7 +27,6 @@
#include <qpid/messaging/Sender.h>
#include <qpid/messaging/Message.h>
#include <qpid/messaging/Duration.h>
-#include <qpid/messaging/FailoverUpdates.h>
//
// Wrapper functions for map-decode and list-decode. This allows us to avoid
@@ -49,7 +48,6 @@ qpid::types::Variant::List& decodeList(const qpid::messaging::Message& msg) {
%}
-%include <qpid/ImportExport.h>
%include <qpid/messaging/ImportExport.h>
%include <qpid/messaging/Address.h>
%include <qpid/messaging/Duration.h>
@@ -58,7 +56,6 @@ qpid::types::Variant::List& decodeList(const qpid::messaging::Message& msg) {
%include <qpid/messaging/Sender.h>
%include <qpid/messaging/Session.h>
%include <qpid/messaging/Connection.h>
-%include <qpid/messaging/FailoverUpdates.h>
qpid::types::Variant::Map& decodeMap(const qpid::messaging::Message&);
qpid::types::Variant::List& decodeList(const qpid::messaging::Message&);
diff --git a/cpp/bindings/qpid/ruby/.gitignore b/cpp/bindings/qpid/ruby/.gitignore
deleted file mode 100644
index ab78513491..0000000000
--- a/cpp/bindings/qpid/ruby/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-pkg
-html
diff --git a/cpp/bindings/qpid/ruby/CMakeLists.txt b/cpp/bindings/qpid/ruby/CMakeLists.txt
deleted file mode 100644
index 25258cfc6a..0000000000
--- a/cpp/bindings/qpid/ruby/CMakeLists.txt
+++ /dev/null
@@ -1,63 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-##--------------------------------------------------
-## Properties used for generating the Ruby bindings.
-##--------------------------------------------------
-set(GEM_BINDINGS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/cqpid)
-set(GEM_BINDINGS_SOURCE_FILE ${GEM_BINDINGS_SOURCE_DIR}/cqpid.cpp)
-set(GEM_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR})
-set(GEM_OUTPUT_FILE ${GEM_OUTPUT_PATH}/pkg/qpid-${qpidc_version}.0.gem)
-
-
-##------------------------------------------------------
-## Use Swig to generate a literal binding to the C++ API
-##------------------------------------------------------
-set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ruby.i PROPERTIES CPLUSPLUS ON)
-set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ruby.i PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include")
-
-swig_add_module(cqpid ruby ${CMAKE_CURRENT_SOURCE_DIR}/ruby.i)
-swig_link_libraries(cqpid qpidmessaging qpidtypes qmf2 ${RUBY_LIBRARY})
-
-set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -I${RUBY_INCLUDE_DIR} -I${qpid-cpp_SOURCE_DIR}/include")
-
-##----------------------------------
-## Install the complete Ruby binding
-##----------------------------------
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcqpid.so
- RENAME cqpid.so
- DESTINATION ${RUBY_SITEARCH_DIR}
- COMPONENT ${QPID_COMPONENT_CLIENT}
- )
-
-add_custom_command(OUTPUT ${GEM_BINDINGS_SOURCE_FILE}
- COMMAND cp ${swig_generated_file_fullname} ${GEM_BINDINGS_SOURCE_FILE}
- DEPENDS ${swig_generated_file_fullname}
- )
-
-add_custom_command(OUTPUT ${GEM_OUTPUT_FILE}
- COMMAND OUTPUT_DIR=${GEM_OUTPUT_PATH} rake clean clobber package
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- DEPENDS ${swig_generated_file_fullname} ${GEM_BINDINGS_SOURCE_FILE}
- )
-
-add_custom_target(gemfile
- DEPENDS ${GEM_OUTPUT_FILE}
- )
-
diff --git a/cpp/bindings/qpid/ruby/LICENSE b/cpp/bindings/qpid/ruby/LICENSE
deleted file mode 100644
index cff2a5e25d..0000000000
--- a/cpp/bindings/qpid/ruby/LICENSE
+++ /dev/null
@@ -1,234 +0,0 @@
-=========================================================================
-== Apache License ==
-=========================================================================
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-=========================================================================
-== Boost License ==
-=========================================================================
-
-Boost Software License - Version 1.0 - August 17th, 2003
-
-Permission is hereby granted, free of charge, to any person or organization
-obtaining a copy of the software and accompanying documentation covered by
-this license (the "Software") to use, reproduce, display, distribute,
-execute, and transmit the Software, and to prepare derivative works of the
-Software, and to permit third-parties to whom the Software is furnished to
-do so, all subject to the following:
-
-The copyright notices in the Software and this entire statement, including
-the above license grant, this restriction and the following disclaimer,
-must be included in all copies of the Software, in whole or in part, and
-all derivative works of the Software, unless such copies or derivative
-works are solely in the form of machine-executable object code generated by
-a source language processor.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
-SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
-FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
diff --git a/cpp/bindings/qpid/ruby/Makefile.am b/cpp/bindings/qpid/ruby/Makefile.am
index a2a5dd76bd..67a3615362 100644
--- a/cpp/bindings/qpid/ruby/Makefile.am
+++ b/cpp/bindings/qpid/ruby/Makefile.am
@@ -21,7 +21,7 @@ if HAVE_RUBY_DEVEL
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src
-EXTRA_DIST = CMakeLists.txt ruby.i
+EXTRA_DIST = ruby.i
BUILT_SOURCES = cqpid.cpp
SWIG_FLAGS = -w362,401
@@ -33,10 +33,10 @@ cqpid.cpp: $(srcdir)/ruby.i $(srcdir)/../qpid.i $(srcdir)/../../swig_ruby_typema
rubylibarchdir = $(RUBY_LIB_ARCH)
rubylibarch_LTLIBRARIES = cqpid.la
-cqpid_la_LDFLAGS = -avoid-version -module -shared -shrext ".$(RUBY_DLEXT)"
+cqpid_la_LDFLAGS = -avoid-version -module -shrext ".$(RUBY_DLEXT)"
cqpid_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqpidmessaging -lqpidtypes \
$(top_builddir)/src/libqpidmessaging.la $(top_builddir)/src/libqpidtypes.la
-cqpid_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH) -fno-strict-aliasing
+cqpid_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH)
nodist_cqpid_la_SOURCES = cqpid.cpp
CLEANFILES = cqpid.cpp
diff --git a/cpp/bindings/qpid/ruby/README.rdoc b/cpp/bindings/qpid/ruby/README.rdoc
deleted file mode 100644
index 0ae7e5cbed..0000000000
--- a/cpp/bindings/qpid/ruby/README.rdoc
+++ /dev/null
@@ -1,45 +0,0 @@
-= Qpid - Open Source AMQP Messaging
-
-Qpid is an cross-platform enterprise messaging system.
-
-Version :: 0.10.0.alpha.0
-
-= Links
-
-Documents :: http://qpid.apache.org/
-
-= Installation
-
-You can install Qpid with the following command.
-
- $ gem install qpid
-
-== Building The Native Code
-
-The Qpid gem requires that you have available the Qpid libraries and
-development header files. To install them, please see:
-
-http://cwiki.apache.org/qpid/developer-pages.html
-
-If you are building the gem within the Qpid development environment
-itself, you can specify the location of the Qpid headers and
-libraries with:
-
-$ ruby extconfig.rb --with-qpid-lib=[path to libqpidclient.so, etc.]
-$ make
-
-== Examples
-
-Take a look at the integration tests for examples on how to leverage
-the messaging capabilities of Qpid in your Ruby applications.
-
-== License
-
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor licensing agreements.
-
-Author:: Darryl L. Pierce (mailto:dpierce@redhat.com)
-Copyright:: Copyright (c) 2011, Red Hat, Inc.
-Homepage:: http://qpid.apache.org
-License:: Apache License 2.0 - http://www.apache.org/licenses/LICENSE-2.0.html
-
diff --git a/cpp/bindings/qpid/ruby/Rakefile b/cpp/bindings/qpid/ruby/Rakefile
deleted file mode 100644
index 07cfff9844..0000000000
--- a/cpp/bindings/qpid/ruby/Rakefile
+++ /dev/null
@@ -1,130 +0,0 @@
-# Rakefile for Qpid -*- 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.
-#
-
-task :noop
-
-# look for a root directory for out-of-tree builds
-
-OUTPUT_DIR=ENV["OUTPUT_DIR"] || "."
-
-require "rubygems"
-require "rubygems/package_task"
-
-require "rake/clean"
-require "rake/extensiontask"
-require "rake/rdoctask"
-require "rake/testtask"
-
-CLOBBER.include("pkg")
-
-load "./lib/qpid/version.rb"
-
-#-------------
-# Gem Details.
-#-------------
-
-NAME = "qpid"
-# VERSION = Qpid::VERSION
-AUTHOR = "Darryl L. Pierce"
-EMAIL = "dpierce@redhat.com"
-HOMEPAGE = "http://qpid.apache.org"
-SUMMARY = "Qpid is an enterprise messaging framework."
-
-desc "Default: run all tests."
-task :default => :"test:all"
-
-#---------------
-# Testing tasks.
-#---------------
-
-desc "Run all tests (alias for test:all)."
-task :test => :"test:all"
-
-namespace :test do
- desc "Run all tests (default)."
- task :all => [:units, :integrations]
-
- desc "Run unit tests."
- Rake::TestTask.new(:units) do |t|
- t.libs << "."
- t.pattern = "test/test*.rb"
- t.verbose = true
- end
-
- desc "Run integration tests."
- Rake::TestTask.new(:integrations) do |t|
- t.libs << "."
- t.pattern = "test/integration/*.rb"
- t.verbose = true
- end
-
-end
-
-#---------------------
-# Documentation tasks.
-#---------------------
-
-Rake::RDocTask.new(:rdoc => "rdoc",
- :clobber_rdoc => "rdoc:clean",
- :rerdoc => "rdoc:force") do |rd|
- rd.main = "README.rdoc"
- rd.options << "--all"
- rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
-end
-
-#-----------------
-# Package the gem.
-#-----------------
-
-spec = Gem::Specification.new do |s|
- s.name = NAME
- s.version = Qpid::VERSION
- s.platform = Gem::Platform::RUBY
- s.extra_rdoc_files = ["README.rdoc"]
- s.summary = SUMMARY
- s.description = s.summary
- s.author = AUTHOR
- s.email = EMAIL
- s.homepage = HOMEPAGE
-
- s.extensions = FileList["ext/**/extconf.rb"]
-
- s.require_path = "lib"
- # DEPRECATED s.autorequire = NAME
- s.files = FileList["LICENSE",
- "README.rdoc",
- "Rakefile",
- "TODO",
- "lib/**/*.rb",
- "test/**/*.rb",
- "examples/**/*.rb",
- "ext/**/*"]
-end
-
-Gem::PackageTask.new(spec) do |pkg|
- pkg.package_dir = "#{OUTPUT_DIR}/pkg"
-end
-
-#------------------
-# Build native code
-#------------------
-
-Rake::ExtensionTask.new("cqpid", spec)
-
diff --git a/cpp/bindings/qpid/ruby/TODO b/cpp/bindings/qpid/ruby/TODO
deleted file mode 100644
index 454aac9200..0000000000
--- a/cpp/bindings/qpid/ruby/TODO
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO Items
------------------------------------------------------------------------------
-
-Version 0.11.0:
- * Deliver the Ruby bindings as a gem.
- * Rework the blocking tasks to not bring the main thread to a halt.
-
diff --git a/cpp/bindings/qpid/ruby/examples/client.rb b/cpp/bindings/qpid/ruby/examples/client.rb
deleted file mode 100644
index f42f25cfc9..0000000000
--- a/cpp/bindings/qpid/ruby/examples/client.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-if __FILE__ == $0
- broker = ARGV[1] || "amqp:tcp:localhost:5672"
- options = ARGV[2] || ""
-
- connection = Qpid::Messaging::Connection.new broker, options
- connection.open
- session = connection.create_session
- sender = session.create_sender "service_queue"
- response_queue = Qpid::Messaging::Address.new("#response-queue", "",
- :create => :always,
- :delete => :always)
- receiver = session.create_receiver response_queue
-
- ["Twas brillig, and the slithy toves",
- "Did gire and gymble in the wabe.",
- "All mimsy were the borogroves,",
- "And the mome raths outgrabe."].each do |line|
- request = Qpid::Messaging::Message.new :content => line
- request.reply_to = response_queue
- sender.send request
- response = receiver.fetch
- puts "#{request.content} -> #{response.content}"
- end
-
- connection.close
-end
-
diff --git a/cpp/bindings/qpid/ruby/examples/drain.rb b/cpp/bindings/qpid/ruby/examples/drain.rb
deleted file mode 100644
index a6cf35e189..0000000000
--- a/cpp/bindings/qpid/ruby/examples/drain.rb
+++ /dev/null
@@ -1,111 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-require 'optparse'
-
-options = {
- :broker => "localhost",
- :timeout => Qpid::Messaging::Duration::IMMEDIATE,
- :count => 1,
- :forever => false,
- :connection_options => ""
-}
-
-opts = OptionParser.new do |opts|
- opts.banner = "Usage: drain.rb [OPTIONS] ADDRESS"
-
- opts.separator ""
- opts.separator "Drains messages from the specified address"
- opts.separator ""
-
- opts.on("-h", "--help",
- "show this message") do
- puts opts
- exit
- end
-
- opts.on("-b", "--broker VALUE",
- "url of broker to connect to") do |broker|
- options[:broker] = broker
- end
-
- opts.on("-t", "--timeout VALUE", Integer,
- "timeout in seconds to wait before exiting") do |timeout|
- options[:timeout] = Qpid::Messaging::Duration.new timeout * 1000
- end
-
- opts.on("-f", "--forever",
- "ignore timeout and wait forever") do
- options[:forever] = true
- end
-
- opts.on("--connection-options VALUE",
- "connection options string in the form {name1:value,name2:value2}") do |conopts|
- options[:connection_options] = conopts
- end
-
- opts.on("-c", "--count VALUE", Integer,
- "number of messages to read before exiting") do |count|
- options[:count] = count
- end
-end
-
-opts.parse!(ARGV)
-
-options[:address] = ARGV[0] || ""
-
-connection = Qpid::Messaging::Connection.new options[:broker], options[:connection_options]
-connection.open
-
-def render_map map
- print "{"
- map.keys.sort.each_with_index {|key,index| print "#{index > 0 ? ', ' : ''}#{key}:#{map[key]}"}
- print "}"
-end
-
-begin
- session = connection.create_session
- receiver = session.create_receiver options[:address]
- done = false
- count = 0
- options[:timeout] = Qpid::Messaging::Duration::FOREVER if options[:forever]
-
- while !done && (count < options[:count])
- message = receiver.fetch(options[:timeout])
- print "Message(properties="
- render_map message.properties
- print ", content="
- if message.content_type == "amqp/map"
- print "'#{render_map message.content}')"
- else
- print "'#{message.content}'"
- end
- print ")\n"
- session.acknowledge message
- count += 1
- end
-rescue Exception => error
- puts "Exception: #{error.to_s}"
-end
-
-connection.close
-
diff --git a/cpp/bindings/qpid/ruby/examples/hello_world.rb b/cpp/bindings/qpid/ruby/examples/hello_world.rb
deleted file mode 100644
index 703febeba1..0000000000
--- a/cpp/bindings/qpid/ruby/examples/hello_world.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-# This is your classic Hello World application, written in
-# Ruby, that uses Qpid. It demonstrates how to send and
-# also receive messages.
-#
-if __FILE__ == $0
- broker = ARGV[0] || "localhost:5672"
- address = ARGV[1] || "amq.topic"
- options = ARGV[2] || ""
-
- connection = Qpid::Messaging::Connection.new broker
- connection.open
- session = connection.create_session
- receiver = session.create_receiver address
- sender = session.create_sender address
-
- # Send a simple message
- sender.send Qpid::Messaging::Message.new :content => "Hello world!"
-
- # Now receive the message
- message = receiver.fetch Qpid::Messaging::Duration::SECOND
- puts "#{message.content}"
- session.acknowledge
-
- connection.close
-end
-
diff --git a/cpp/bindings/qpid/ruby/examples/map_receiver.rb b/cpp/bindings/qpid/ruby/examples/map_receiver.rb
deleted file mode 100644
index 805943a0a4..0000000000
--- a/cpp/bindings/qpid/ruby/examples/map_receiver.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-broker = ARGV[0] || "amqp:tcp:127.0.0.1:5672"
-address = ARGV[1] || "message_queue; {create: always}"
-options = ARGV[2] || ""
-
-connection = Qpid::Messaging::Connection.new broker, options
-connection.open
-
-def display_value value
- case value
- when Array
- result = ""
- value.each_with_index {|element, index| result += "#{', ' if index > 0}#{element}"}
- return "[#{result}]"
- end
-
- value.to_s
-end
-
-begin
- session = connection.create_session
- receiver = session.create_receiver address
-
- message = receiver.fetch
- content = message.content
-
- print "content-type:#{message.content_type}"
- print "{"
- content.keys.sort.each_with_index do |key, index|
- print "#{', ' if index > 0}#{key}:#{display_value content[key]}"
- end
- print "}\n"
-
- session.acknowledge
-
-rescue Exception => error
- puts "Exception: #{error.message}"
-end
-
-connection.close
-
diff --git a/cpp/bindings/qpid/ruby/examples/map_sender.rb b/cpp/bindings/qpid/ruby/examples/map_sender.rb
deleted file mode 100644
index fa0c6e4562..0000000000
--- a/cpp/bindings/qpid/ruby/examples/map_sender.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-broker = ARGV[0] || "amqp:tcp:127.0.0.1:5672"
-address = ARGV[1] || "message_queue; {create: always}"
-options = ARGV[2] || []
-
-connection = Qpid::Messaging::Connection.new broker, options
-connection.open
-
-begin
- session = connection.create_session
- sender = session.create_sender address
- message = Qpid::Messaging::Message.new
-
- content = {
- :id => 987654321,
- :name => "Widget",
- :percent => 0.99,
- :colors => ["red", "green", "blue"]
- }
-
- message.content = content
-
- sender.send message
-
-rescue Exception => error
- puts "Exception: #{error.message}"
-end
-
-connection.close
-
diff --git a/cpp/bindings/qpid/ruby/examples/server.rb b/cpp/bindings/qpid/ruby/examples/server.rb
deleted file mode 100644
index ead9d58472..0000000000
--- a/cpp/bindings/qpid/ruby/examples/server.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-if __FILE__ == $0
- broker = ARGV[0] || "amqp:tcp:localhost:5672"
- options = ARGV[1] || ""
-
- connection = Qpid::Messaging::Connection.new broker, options
- connection.open
- session = connection.create_session
- receiver = session.create_receiver "service_queue; {create:always}"
-
- loop do
- request = receiver.fetch
- address = request.reply_to
-
- if !address.nil?
- sender = session.create_sender address
- response = Qpid::Messaging::Message.new :content => request.content.upcase
- sender.send response
- puts "Processed request: #{request.content} -> #{response.content}"
- session.acknowledge
- else
- puts "Error: no reply address specified for request: #{request.content}"
- session.reject request
- end
- end
-
- connection.close
-end
-
diff --git a/cpp/bindings/qpid/ruby/examples/spout.rb b/cpp/bindings/qpid/ruby/examples/spout.rb
deleted file mode 100644
index c012e31f9d..0000000000
--- a/cpp/bindings/qpid/ruby/examples/spout.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-require 'optparse'
-
-options = {
- :broker => "127.0.0.1",
- :address => "",
- :timeout => 0,
- :count => 1,
- :properties => {},
- :content => nil,
- :mapped => {}
-}
-
-opts = OptionParser.new do |opts|
- opts.banner = "Usage: spout.rb [OPTIONS] ADDRESS"
-
- opts.on("-h", "--help",
- "show this message") do |help|
- puts opts
- exit
- end
-
- opts.on("-b","--broker VALUE",
- "url of broker to connect to ") do |broker|
- options[:broker] = broker
- end
-
- opts.on("-t", "--timeout VALUE", Integer,
- "exit after the specified time") do |timeout|
- options[:timeout] = Qpid::Messaging::Duration.new timeout * 1000
- end
-
- opts.on("-c", "--count VALUE", Integer,
- "stop after count messages have been sent, zero disables") do |count|
- options[:count] = count
- end
-
- opts.on("-i", "--id VALUE",
- "use the supplied id instead of generating one") do |id|
- options[:id] = id
- end
-
- opts.on("--reply-to VALUE",
- "specify reply-to address") do |replyto|
- options[:replyto] = replyto
- end
-
- opts.on("-P", "--property VALUE",
- "specify message property") do |property|
- name = property.split(/=/)[0]
- value = property.split(/=/)[1]
- options[:properties][name] = value
- end
-
- opts.on("-M", "--map VALUE",
- "specify entry for map content") do |mapped|
- name = mapped.split(/=/)[0]
- value = mapped.split(/=/)[1]
- options[:mapped][name] = value
- end
-
- opts.on("--content VALUE",
- "specify textual content") do |content|
- options[:content] = content
- end
-
- opts.on(nil, "--connection-options VALUE",
- "connection options string in the form {name1:value1, name2:value2}") do |conopts|
- options[:connection_options] = conopts
- end
-end
-
-begin
- opts.parse!(ARGV)
-rescue => error
- opts.parse(["-h"])
-end
-
-# now get the non-arg options
-options[:address] = ARGV[0] unless ARGV[0].nil?
-
-connection = Qpid::Messaging::Connection.new options[:broker], options[:connection_options]
-connection.open
-session = connection.create_session
-sender = session.create_sender options[:address]
-message = Qpid::Messaging::Message.new
-
-options[:properties].each_key {|key| message.properties[key] = options[:properties][key]}
-
-(1..options[:count]).each do |count|
- if !options[:mapped].keys.empty?
- message.content = options[:mapped]
- elsif options[:content]
- message.content = options[:content]
- end
- message.content = options[:content] unless options[:content].nil?
- message.properties["spout-id"] = "#{count}"
- message.reply_to = options[:replyto] unless options[:replyto].nil? || options[:replyto].empty?
- sender.send message
-end
-
-# session.sync
-
-connection.close
-
diff --git a/cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb b/cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb
deleted file mode 100644
index 90292d4bec..0000000000
--- a/cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# To create the Makefile then you need to specify the location
-# of the Qpid shared libraries using the commandline:
-#
-# $ ruby extconf.rb --with-qpid-lib=[path to libraries]
-#
-
-require 'mkmf'
-
-# Setup the build environment.
-$CFLAGS = "-fPIC -fno-inline -x c++"
-
-REQUIRED_LIBRARIES = [
- 'qpidclient',
- 'qpidcommon',
- 'qpidmessaging',
- 'qpidtypes'
- ]
-
-REQUIRED_HEADERS = [
- 'qpid/messaging/Address.h',
- 'qpid/messaging/Connection.h',
- 'qpid/messaging/Duration.h',
- 'qpid/messaging/exceptions.h',
- 'qpid/messaging/FailoverUpdates.h',
- 'qpid/messaging/Handle.h',
- 'qpid/messaging/ImportExport.h',
- 'qpid/messaging/Message.h',
- 'qpid/messaging/Receiver.h',
- 'qpid/messaging/Sender.h',
- 'qpid/messaging/Session.h'
- ]
-
-dir_config('qpid')
-
-def abort_build filetype, filename
- abort "Missing required #{filetype}: #{filename}"
-end
-
-def require_library lib
- abort_build "library", lib unless have_library lib
-end
-
-def require_header header
- abort_build "header", header unless have_header header
-end
-
-have_library('stdc++')
-
-REQUIRED_LIBRARIES.each {|library| require_library library}
-
-REQUIRED_HEADERS.each {|header| require_header header}
-
-create_makefile('cqpid')
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid.rb b/cpp/bindings/qpid/ruby/lib/qpid.rb
deleted file mode 100644
index 1f00c136c1..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-require 'qpid/errors'
-require 'qpid/duration'
-require 'qpid/address'
-require 'qpid/encoding'
-require 'qpid/message'
-require 'qpid/sender'
-require 'qpid/receiver'
-require 'qpid/session'
-require 'qpid/connection'
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid/address.rb b/cpp/bindings/qpid/ruby/lib/qpid/address.rb
deleted file mode 100644
index 73b61bb1c7..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/address.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-require 'cqpid'
-
-module Qpid
-
- module Messaging
-
- # Address represents an address to which messages can be sent or from
- # which they can be received.
- #
- # An Address can be described using the following pattern:
- #
- # <address> [ / <subject> ] ; [ { <key> : <value> , ... } ]
- #
- # where *address* is a simple name and *subject* is a subject or subject
- # pattern.
- #
- # The options, enclosed in curly braces, are key:value pairs delimited by
- # a comma. The values can be nested maps also enclosed in curly braces.
- # Or they can be lists of values, where they are contained within square
- # brackets but still comma delimited, such as:
- #
- # [value1,value2,value3]
- #
- # The following are the list of supported options:
- #
- # create:: Indicates if the address should be created; values are *always*,
- # *never*, *sender* or *reciever*.
- #
- # assert:: Indicates whether or not to assert any specified node properties;
- # values are *always*, *never*, *sender* or *receiver*.
- #
- # delete:: Indicates whether or not to delete the addressed node when a
- # sender or receiver is cancelled; values are *always*, *never*,
- # *sender* or *receiver*.
- #
- # node:: A nested map describing properties for the addressed node.
- # Properties are *type* (*topic* or *queue*), *durable* (a boolean),
- # *x-declare* (a nested map of amqp 0.10-specific options) and
- # *x-bindings*. (nested list which specifies a queue, exchange or
- # a binding key and arguments.
- #
- # link:: A nested map through which properties of the link can be specified;
- # properties are *durable*, *reliability*, *x-declare*, *x-subscribe*
- # and *x-bindings*.
- #
- # mode:: (*For receivers only*) indicates whether the receiver should consume
- # or browse messages; values are *consume* (the default) and *browse*.
- class Address
-
- def initialize(name, subject, options = {}, _type = "", address_impl = nil)
- @address_impl = address_impl || Cqpid::Address.new(name, subject, convert_options(options), _type)
- end
-
- def address_impl # :nodoc:
- @address_impl
- end
-
- # Returns the name.
- def name; @address_impl.getName; end
-
- # Sets the name.
- def name=(name); @address_impl.setName name; end
-
- # Returns the subject.
- def subject; @address_impl.getSubject; end
-
- # Sets the subject.
- def subject=(subject); @address_impl.setSubject(subject); end
-
- # Returns the type.
- #---
- # We cannot use "type" since that clashes with the Ruby object.type
- # identifier.
- def _type; @address_impl.getType; end
-
- # Sets the type.
- #
- # The type of the address determines how Sender and Receiver objects
- # are constructed for it. If no type is specified then it will be
- # determined by querying the broker.
- def _type=(_type); @address_impl.setType(_type); end
-
- # Returns the options.
- def options; @address_impl.getOptions; end
-
- # Sets the options for the address.
- # Any symbols are converted to strings.
- def options=(options); @address_impl.setOptions(convert_options(options)); end
-
- def to_s; @address_impl.str; end
-
- private
-
- def convert_options(options)
- result = {}
- options.each_pair {|key, value| result[key.to_s] = value.to_s}
-
- return result
- end
-
- end
-
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid/connection.rb b/cpp/bindings/qpid/ruby/lib/qpid/connection.rb
deleted file mode 100644
index 5c56c1f5d0..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/connection.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT 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 'cqpid'
-
-module Qpid
-
- module Messaging
-
- # Connection allows for establishing connections to a remote endpoint.
- class Connection
-
- # The following general options are supported (as strings or symbols):
- #
- # username::
- # password::
- # heartbeat::
- # tcp_nodelay::
- # sasl_mechanism::
- # sasl_service::
- # sasl_min_ssf::
- # sasl_max_ssf::
- # transport::
- #
- # The following options specifically control reconnection behavior:
- #
- # reconnect:: *true* or *false*; indicates whether to attempt reconnections
- # reconnect_timeout:: the number of seconds to attempt reconnecting
- # reconnect_limit:: the number of retries before reporting failure
- # reconnect_interval_min:: initial delay, in seconds, before attempting a reconnecting
- # reconnect_interval_max:: number of seconds to wait before additional reconnect attempts
- # reconnect_interval:: shorthand for setting box min and max values
- # reconnect_urls:: a list of alternate URLs to use for reconnection attempts
- def initialize(url, options = {}, connection_impl = nil)
- @url = url
- @connection_impl = connection_impl
- @options = options
- end
-
- def connection_impl # :nodoc:
- @connection_impl
- end
-
- # Opens the connection.
- def open
- @connection_impl = Cqpid::Connection.new(@url, convert_options)
- @connection_impl.open
- end
-
- # Reports whether the connection is open.
- def open?; false || (@connection_impl.isOpen if @connection_impl); end
-
- # Closes the connection.
- def close; @connection_impl.close if open?; end
-
- # Creates a new session.
- #
- # If :transactional => true then a transactional session is created.
- # Otherwise a standard session is created.
- def create_session(args = {})
- name = args[:name] || ""
- if open?
- if args[:transactional]
- session = @connection_impl.createTransactionalSession name
- else
- session = @connection_impl.createSession name
- end
- return Session.new(session)
- else
- raise RuntimeError.new "No connection available."
- end
- end
-
- # Returns a session for the specified session name.
- def session name
- session_impl = @connection_impl.getSession name
- Qpid::Messaging::Session.new session_impl if session_impl
- end
-
- # Returns the username used to authenticate with the connection.
- def authenticated_username; @connection_impl.getAuthenticatedUsername if open?; end
-
- # inherited from Handle
-
- # Returns whether the underlying handle is valid; i.e., not null.
- def valid?
- @connection_impl.isValid
- end
-
- # Returns whether the underlying handle is null.
- def null?
- @connection_impl.isNull
- end
-
- # Swaps the underlying connection handle.
- def swap connection
- @connection_impl.swap connection.connection_impl
- end
-
- private
-
- def convert_options
- result = {}
- # map only those options defined in the C++ layer
- # TODO when new options are added, this needs to be updated.
- unless @options.nil? || @options.empty?
- @options.each_pair {|key, value| result[key.to_s] = value.to_s}
- end
-
- return result
- end
-
- end
-
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid/duration.rb b/cpp/bindings/qpid/ruby/lib/qpid/duration.rb
deleted file mode 100644
index c1f44e9281..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/duration.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-require 'cqpid'
-
-module Qpid
-
- module Messaging
-
- # A Duration represents a period of time in milliseconds
- #
- # It defines the following named values as symbols:
- #
- # :FOREVER :: the maximum integer value for the platform
- # :IMMEDIATE :: an alias for 0
- # :SECOND :: 1,000ms
- # :MINUTE :: 60,000ms
- class Duration
-
- def initialize duration # :nodoc:
- @duration_impl = Cqpid::Duration.new duration
- end
-
- def duration_impl # :nodoc:
- @duration_impl
- end
-
- def self.add_item(key, value) # :nodoc:
- @hash ||= {}
- @hash[key] = Duration.new value
- end
-
- def self.const_missing(key) # :nodoc:
- @hash[key]
- end
-
- self.add_item :FOREVER, Cqpid::Duration.FOREVER.getMilliseconds
- self.add_item :IMMEDIATE, Cqpid::Duration.IMMEDIATE.getMilliseconds
- self.add_item :SECOND, Cqpid::Duration.SECOND.getMilliseconds
- self.add_item :MINUTE, Cqpid::Duration.MINUTE.getMilliseconds
-
- end
-
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid/encoding.rb b/cpp/bindings/qpid/ruby/lib/qpid/encoding.rb
deleted file mode 100644
index c8b843b597..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/encoding.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-require 'cqpid'
-
-module Qpid
-
- module Messaging
-
- # Encodes the supplied content into the given message.
- def self.encode content, message, encoding = nil
- prepared = content
- case content
- when Hash
- prepared = {}
- content.each_pair do |key,value|
- prepared[key.to_s] = value.to_s
- end
- Cqpid::encode prepared, message.message_impl
- when Array
- prepared = []
- content.each {|value| prepared << value.to_s}
- Cqpid::encode prepared, message.message_impl
- end
- end
-
- # Decodes and returns the message's content.
- def self.decode(message, content_type = nil)
- content_type = message.content_type unless content_type
-
- case content_type
- when "amqp/map": Cqpid.decodeMap message.message_impl
- when "amqp/list": Cqpid.decodeList message.message_impl
- end
- end
-
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid/errors.rb b/cpp/bindings/qpid/ruby/lib/qpid/errors.rb
deleted file mode 100644
index 7a16d08d84..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/errors.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-module Qpid
-
- module Messaging
-
- class KeyError < RuntimeError
- end
-
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid/message.rb b/cpp/bindings/qpid/ruby/lib/qpid/message.rb
deleted file mode 100644
index 9b1b68c7c3..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/message.rb
+++ /dev/null
@@ -1,157 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-require 'cqpid'
-
-module Qpid
-
- module Messaging
-
- # Message represents a message.
- class Message
-
- def initialize(args = {}, message_impl = nil)
- @message_impl = message_impl
- @message_impl = Cqpid::Message.new if @message_impl.nil?
- @message_impl.setContent args[:content].to_s if args[:content]
- @content = nil
- end
-
- def message_impl # :nodoc:
- @message_impl
- end
-
- # Assigns the reply to address.
- # The address must be an instance of Address.
- def reply_to=(address); @message_impl.setReplyTo address.address_impl; end
-
- # Returns the reply to address for the message as an instance of +Address+.
- def reply_to
- address_impl = @message_impl.getReplyTo
- # only return an address if a reply to was specified
- Qpid::Messaging::Address.new(nil, nil, nil, nil, address_impl) if address_impl
- end
-
- # Sets the subject.
- def subject=(subject); @message_impl.setSubject subject; end
-
- # Returns the subject.
- def subject; @message_impl.getSubject; end
-
- # Sets the content type.
- def content_type=(content_type); @message_impl.setContentType content_type; end
-
- # Returns the content type.
- def content_type; @message_impl.getContentType; end
-
- # Sets the message id.
- def message_id=(message_id); @message_impl.setMessageId message_id.to_s; end
-
- # Returns the message id.
- def message_id; @message_impl.getMessageId; end
-
- # Sets the user id.
- def user_id=(user_id); @message_impl.setUserId user_id; end
-
- # Returns the user id.
- def user_id; @message_impl.getUserId; end
-
- # Sets the correlation id.
- def correlation_id=(correlation_id); @message_impl.setCorrelationId correlation_id; end
-
- # Returns the correlation id.
- def correlation_id; @message_impl.getCorrelationId; end
-
- # Sets the priority.
- def priority=(priority); @message_impl.setPriority priority; end
-
- # Returns the priority.
- def priority; @message_impl.getPriority; end
-
- # Sets the time-to-live in milliseconds.
- def ttl=(duration); @message_impl.setTtl duration; end
-
- # Returns the time-to-live in milliseconds.
- def ttl; @message_impl.getTtl; end
-
- # Sets the durability.
- def durable=(durable); @message_impl.setDurable durable; end
-
- # Returns the durability.
- def durable; @message_impl.getDurable; end
-
- # Allows marking the message as redelivered.
- def redelivered=(redelivered); @message_impl.setRedelivered redelivered; end
-
- # Returns if the message was redelivered.
- def redelivered; @message_impl.getRedelivered; end
-
- # Returns all named properties.
- # *NOTE:* It is recommended to use the +foo[key]+ method for
- # retrieving properties.
- def properties; @message_impl.getProperties; end
-
- # Returns the value for the named property.
- def [](key); self.properties[key.to_s]; end
-
- # Assigns a value to the named property.
- def []=(key, value); @message_impl.setProperty(key.to_s, value.to_s); end
-
- # Sets the content.
- def content=(content)
- content_type = nil
- @content = content
- case @content
- when Hash
- content_type = "amqp/map"
- when Array
- content_type = "amqp/list"
- end
- if content_type.nil?
- @message_impl.setContent @content
- else
- Qpid::Messaging.encode @content, self, content_type
- end
- end
-
- # Returns the content.
- def content
- if @content.nil?
- @content = @message_impl.getContent
-
- # decode the content is necessary if it
- # has an encoded content type
- if ["amqp/list", "amqp/map"].include? @message_impl.getContentType
- @content = Qpid::Messaging.decode(self,
- @message_impl.getContentType)
- end
-
- end
- @content
- end
-
- # Returns the content's size.
- def content_size; @message_impl.getContentSize; end
-
- end
-
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid/receiver.rb b/cpp/bindings/qpid/ruby/lib/qpid/receiver.rb
deleted file mode 100644
index d498aa922b..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/receiver.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-require 'cqpid'
-
-require 'qpid/duration'
-
-module Qpid
-
- module Messaging
-
- # Receiver defines a type for receiving messages.
- class Receiver
-
- def initialize(receiver_impl) # :nodoc:
- @receiver_impl = receiver_impl
- end
-
- def receiver_impl # :nodoc:
- @receiver_impl
- end
-
- # Retrieves a message from the receiver's local queue, or waits
- # for up to the duration specified for one to become available.
- def get(duration = Qpid::Messaging::Duration::FOREVER)
- message_impl = @receiver_impl.get duration.duration_impl
- create_message_wrapper message_impl unless message_impl.nil?
- end
-
- # Retrieves a message from the receiver's subscription, or waits
- # for up to the duration specified for one to become available.
- def fetch(duration = Qpid::Messaging::Duration::FOREVER)
- message_impl = @receiver_impl.fetch duration.duration_impl
- create_message_wrapper message_impl unless message_impl.nil?
- end
-
- # Sets the capacity.
- #
- # The capacity for a receiver determines the number of messages that
- # can be held in the receiver before being fetched.
- def capacity=(capacity); @receiver_impl.setCapacity capacity; end
-
- # Returns the capacity.
- def capacity; @receiver_impl.getCapacity; end
-
- # Returns the number of available messages waiting to be fetched.
- def available; @receiver_impl.getAvailable; end
-
- # Returns the number of messages that have been received and acknowledged
- # but whose acknowledgements have not been confirmed by the sender.
- def unsettled; @receiver_impl.getUnsettled; end
-
- # Cancels the reciever.
- def close; @receiver_impl.close; end
-
- # Returns whether the receiver is closed.
- def closed?; @receiver_impl.isClosed; end
-
- # Returns the name of the receiver
- def name; @receiver_impl.getName; end
-
- # Returns the Session for this receiver.
- def session; Qpid::Messaging::Session.new(@receiver_impl.getSession); end
-
- # Returns whether the underlying handle is valid.
- def valid?; @receiver_impl.isValid; end
-
- # Returns whether the underlying handle is null.
- def null?; @receiver_impl.isNull; end
-
- def swap receiver
- @receiver_impl.swap receiver.receiver_impl
- end
-
- private
-
- def create_message_wrapper message_impl
- Qpid::Messaging::Message.new({}, message_impl)
- end
-
- end
-
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid/sender.rb b/cpp/bindings/qpid/ruby/lib/qpid/sender.rb
deleted file mode 100644
index 5d59c20d7e..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/sender.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-module Qpid
-
- module Messaging
-
- # Sender defines a type for sending messages.
- class Sender
-
- def initialize(sender_impl) # :nodoc:
- @sender_impl = sender_impl
- end
-
- def sender_impl # :nodoc:
- @sender_impl
- end
-
- # Sends a message.
- def send(message, args = {})
- block = args[:block] || false
- @sender_impl.send message.message_impl, block
- end
-
- # Closes the sender.
- def close; @sender_impl.close; end
-
- # Returns the name for the sender.
- def name; @sender_impl.getName; end
-
- # Sets the capacity for the sender, which is the number of outgoing
- # messages that can be held pending confirmation or receipt by
- # the broker.
- def capacity=(capacity); @sender_impl.setCapacity capacity; end
-
- # Returns the capacity.
- def capacity; @sender_impl.getCapacity; end
-
- # Returns the number of messages sent that are pending receipt
- # confirmation by the broker.
- def unsettled; @sender_impl.getUnsettled; end
-
- # Returns the available capacity for sending messages.
- def available
- @sender_impl.getAvailable
- end
-
- # Returns the Session for this sender.
- def session; Qpid::Messaging::Session.new @sender_impl.getSession; end
-
- # Returns if the underlying sender is valid.
- def valid?; @sender_impl.isValid; end
-
- # Returns if the underlying sender is null.
- def null?; @sender_impl.isNull; end
-
- def swap sender
- @sender_impl.swap sender.sender_impl
- end
-
- end
-
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid/session.rb b/cpp/bindings/qpid/ruby/lib/qpid/session.rb
deleted file mode 100644
index 543c26cc70..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/session.rb
+++ /dev/null
@@ -1,186 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-require 'cqpid'
-
-require 'qpid/errors'
-
-module Qpid
-
- module Messaging
-
- # A Session represents a distinct conversation between end points.
- class Session
-
- def initialize(session) # :nodoc:
- @session_impl = session
- end
-
- def session_impl # :nodoc:
- @session_impl
- end
-
- # Returns the +Connection+ for the +Session+.
- def connection
- connection_impl = @session_impl.getConnection
- Qpid::Messaging::Connection.new "", {}, connection_impl
- end
-
- # Creates a new endpoint for sending messages.
- def create_sender(address)
- _address = address
-
- if address.class == Qpid::Messaging::Address
- _address = address.address_impl
- end
-
- Qpid::Messaging::Sender.new(@session_impl.createSender(_address))
- end
-
- # Retrieves the +Sender+ with the specified name.
- def sender(name)
- result = nil
-
- begin
- sender_impl = @session_impl.getSender name
- result = Sender.for_impl sender_impl
- rescue
- # treat any error as a key error
- end
-
- raise Qpid::Messaging::KeyError, "No such sender: #{name}" if result.nil?
- result
- end
-
- # Retrieves the +Receiver+ with the specified name.
- def receiver(name)
- result = nil
-
- begin
- receiver_impl = @session_impl.getReceiver name
- result = Receiver.for_impl receiver_impl
- rescue
- # treat any error as a key error
- end
-
- raise Qpid::Messaging::KeyError, "No such receiver: #{name}" if result.nil?
- result
- end
-
- # Creates a new endpoint for receiving messages.
- def create_receiver(address)
- result = nil
-
- if address.class == Qpid::Messaging::Address
- address_impl = address.address_impl
- result = Qpid::Messaging::Receiver.new(@session_impl.createReceiver(address_impl))
- else
- result = Qpid::Messaging::Receiver.new(@session_impl.createReceiver(address))
- end
-
- return result
- end
-
- # Closes the Session and all associated Senders and Receivers.
- # All Sessions are closed when the associated Connection is closed.
- def close; @session_impl.close; end
-
- # Commits any pending transactions for a transactional session.
- def commit; @session_impl.commit; end
-
- # Rolls back any uncommitted transactions on a transactional session.
- def rollback; @session_impl.rollback; end
-
- # Acknowledges one or more outstanding messages that have been received
- # on this session.
- #
- # If a message is submitted (:message => something_message) then only
- # that message is acknowledged. Otherwise all messsages are acknowledged.
- #
- # If :sync => true then the call will block until the server completes
- # processing the acknowledgements.
- # If :sync => true then the call will block until processed by the server (def. false)
- def acknowledge(args = {})
- sync = args[:sync] || false
- message = args[:message] if args[:message]
-
- unless message.nil?
- @session_impl.acknowledge message.message_impl, sync
- else
- @session_impl.acknowledge sync
- end
- end
-
- # Rejects the specified message. A rejected message will not be redelivered.
- #
- # NOTE: A message cannot be rejected once it has been acknowledged.
- def reject(message); @session_impl.reject message.message_impl; end
-
- # Releases the message, which allows the broker to attempt to
- # redeliver it.
- #
- # NOTE: A message connot be released once it has been acknowled.
- def release(message); @session_impl.release message.message_impl; end
-
- # Requests synchronization with the server.
- #
- # If :block => true then the call will block until the server acknowledges.
- #
- # If :block => false (default) then the call will complete and the server
- # will send notification on completion.
- def sync(args = {})
- block = args[:block] || false
- @session_impl.sync block
- end
-
- # Returns the total number of receivable messages, and messages already received,
- # by Receivers associated with this session.
- def receivable; @session_impl.getReceivable; end
-
- # Returns the number of messages that have been acknowledged by this session
- # whose acknowledgements have not been confirmed as processed by the server.
- def unsettled_acks; @session_impl.getUnsettledAcks; end
-
- # Fetches the receiver for the next message.
- def next_receiver(timeout = Qpid::Messaging::Duration::FOREVER)
- receiver_impl = @session_impl.nextReceiver(timeout.duration_impl)
- Qpid::Messaging::Receiver.new receiver_impl
- end
-
- # Returns whether there are errors on this session.
- def error?; @session_impl.hasError; end
-
- def check_error; @session_impl.checkError; end
-
- # Returns if the underlying session is valid.
- def valid?; @session_impl.isValid; end
-
- # Returns if the underlying session is null.
- def null?; @session_impl.isNull; end
-
- def swap session
- @session_impl.swap session.session_impl
- end
-
- end
-
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/lib/qpid/version.rb b/cpp/bindings/qpid/ruby/lib/qpid/version.rb
deleted file mode 100644
index f387ba98dc..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/version.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-module Qpid
-
- module Version
-
- NUMBERS = [MAJOR = 0,
- MINOR = 13,
- BUILD = 0]
- end
-
- VERSION = Version::NUMBERS.join('.')
-
-end
diff --git a/cpp/bindings/qpid/ruby/test/lib/setup.rb b/cpp/bindings/qpid/ruby/test/lib/setup.rb
deleted file mode 100644
index c4901ed907..0000000000
--- a/cpp/bindings/qpid/ruby/test/lib/setup.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-def create_session url, session_name
- conn = Qpid::Messaging::Connection.new url
- conn.open
- conn.create_session session_name
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_address.rb b/cpp/bindings/qpid/ruby/test/test_address.rb
deleted file mode 100644
index f54e93aa3d..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_address.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'cqpid'
-require 'qpid/address'
-
-class TestAddress < Test::Unit::TestCase
-
- def test_constructor
- result = Qpid::Messaging::Address.new "name", "subject", {:foo => :bar}, "type"
-
- assert_equal "name", result.name
- assert_equal "subject", result.subject
- assert_equal "type", result._type
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_connection.rb b/cpp/bindings/qpid/ruby/test/test_connection.rb
deleted file mode 100644
index 648fb0588a..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_connection.rb
+++ /dev/null
@@ -1,257 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'cqpid'
-require 'qpid/connection'
-
-class TestConnection < Test::Unit::TestCase
-
- def setup
- @connection_impl = flexmock("connection_impl")
- @other_connection = flexmock("other_connection")
- @other_connection_impl = flexmock("other_connection_impl")
- @cqpid_connection = flexmock(Cqpid::Connection)
-
- @session = flexmock("session")
- @session_name = "test-session"
-
- @url = "localhost"
- @options = {}
-
- @connection = Qpid::Messaging::Connection.new(@url, @options, @connection_impl)
- end
-
- def test_create_with_username_and_password
- @cqpid_connection.
- should_receive(:new).
- once.with("localhost",
- {"username" => "username",
- "password" => "password"}).
- and_return(@connection_impl)
- @connection_impl.
- should_receive(:open).
- once
-
- result = Qpid::Messaging::Connection.new("localhost",
- :username => "username",
- :password => "password")
- result.open
-
- assert_same @connection_impl, result.connection_impl
- end
-
- def test_create_with_hostname
- result = Qpid::Messaging::Connection.new("localhost")
-
- assert_not_nil result
- end
-
- def test_open
- @cqpid_connection.
- should_receive(:new).
- once.
- with(@url, {}).
- and_return(@connection_impl)
- @connection_impl.
- should_receive(:open).
- once
-
- @connection.open
-
- assert_same @connection_impl, @connection.connection_impl
- end
-
- def test_check_open_when_open
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true)
-
- assert @connection.open?
- end
-
- def test_check_open_before_connection
- result = Qpid::Messaging::Connection.new("hostname")
-
- assert !result.open?
- end
-
- def test_check_open_when_closed
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(false)
-
- assert !@connection.open?
- end
-
- def test_close_an_unopened_session
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(false)
-
- @connection.close
- end
-
- def test_close
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true).
- should_receive(:close).
- once
-
- @connection.close
- end
-
- def test_create_session_without_name
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true).
- should_receive(:createSession).
- once.
- with("").
- and_return(@session)
-
- result = @connection.create_session
-
- assert_not_nil result
- assert_same @session, result.session_impl
- end
-
- def test_create_session
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true).
- should_receive(:createSession).
- once.
- with(@session_name).
- and_return(@session)
-
- result = @connection.create_session :name => @session_name
-
- assert_not_nil result
- assert_same @session, result.session_impl
- end
-
- def test_create_session_raises_exception_when_closed
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(false)
-
- assert_raise(RuntimeError) {@connection.create_session @session_name}
- end
-
- def test_create_transactional_session
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true).
- should_receive(:createTransactionalSession).
- once.
- with("").
- and_return(@session)
-
- result = @connection.create_session :transactional => true
-
- assert_not_nil result
- assert_same @session, result.session_impl
- end
-
- def test_authenticated_username_when_not_connected
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(false)
-
- result = @connection.authenticated_username
-
- assert_nil result
- end
-
- def test_authenticated_username
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true).
- should_receive(:getAuthenticatedUsername).
- once.
- and_return("farkle")
-
- result = @connection.authenticated_username
-
- assert_equal "farkle", result
- end
-
- def test_get_session_with_invalid_name
- @connection_impl.
- should_receive(:getSession).
- once.
- with(@session_name).
- and_return(nil)
-
- result = @connection.session @session_name
-
- assert_nil result
- end
-
- # APIs inherited from Handle
-
- def test_is_valid
- @connection_impl.
- should_receive(:isValid).
- once.
- and_return(true)
-
- assert @connection.valid?
- end
-
- def test_is_null
- @connection_impl.
- should_receive(:isNull).
- once.
- and_return(false)
-
- assert !@connection.null?
- end
-
- def test_swap
- @other_connection.
- should_receive(:connection_impl).
- once.
- and_return(@other_connection_impl)
- @connection_impl.
- should_receive(:swap).
- once.
- with(@other_connection_impl)
-
- @connection.swap @other_connection
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_encoding.rb b/cpp/bindings/qpid/ruby/test/test_encoding.rb
deleted file mode 100644
index 060975a1d5..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_encoding.rb
+++ /dev/null
@@ -1,146 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'cqpid'
-require 'qpid/encoding'
-
-class TestEncoding < Test::Unit::TestCase
-
- def setup
- @cqpid = flexmock(Cqpid)
-
- @message = flexmock("message")
- @message_impl = flexmock("message_impl")
-
- @encoded = {"foo" => "bar"}
- end
-
- def test_encode_map_with_symbols
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:encode).
- once.
- with({"foo" => "bar"}, @message_impl).
- and_return(@encoded)
-
- result = Qpid::Messaging.encode({:foo => :bar}, @message)
-
- assert_same @encoded, result
- end
-
- def test_encode_list_with_symbols
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:encode).
- once.
- with(["foo", "bar"], @message_impl).
- and_return(@encoded)
-
- result = Qpid::Messaging.encode([:foo, :bar], @message)
-
- assert_same @encoded, result
- end
-
- def test_encode_with_content_type
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:encode).
- once.
- with({"foo" => "bar"}, @message_impl).
- and_return(@encoded)
-
- result = Qpid::Messaging.encode({:foo => :bar}, @message)
-
- assert_same @encoded, result
- end
-
- def test_encode
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:encode).
- once.
- with({"foo" => "bar"}, @message_impl).
- and_return(@encoded)
-
- result = Qpid::Messaging.encode({"foo" => "bar"}, @message)
-
- assert_same @encoded, result
- end
-
- def test_decode_for_map
- decoded = {"foo" => "bar"}
- @message.
- should_receive(:content_type).
- once.
- and_return("amqp/map")
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:decodeMap).
- once.
- with(@message_impl).
- and_return(decoded)
-
- result = Qpid::Messaging.decode(@message)
-
- assert_same decoded, result
- end
-
- def test_decode_for_list
- decoded = ["foo", "bar"]
- @message.
- should_receive(:content_type).
- once.
- and_return("amqp/list")
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:decodeList).
- once.
- with(@message_impl).
- and_return(decoded)
-
- result = Qpid::Messaging.decode(@message)
-
- assert_same decoded, result
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_message.rb b/cpp/bindings/qpid/ruby/test/test_message.rb
deleted file mode 100644
index 3fc705bf7e..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_message.rb
+++ /dev/null
@@ -1,353 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'qpid'
-
-class TestMessage < Test::Unit::TestCase
-
- def setup
- @address = flexmock("address")
- @address_impl = flexmock("address_impl")
-
- @messaging = flexmock(Qpid::Messaging)
- @message_impl = flexmock("message")
- @message = Qpid::Messaging::Message.new({}, @message_impl)
- end
-
- def test_message_impl
- assert_same @message_impl, @message.message_impl
- end
-
- def test_set_reply_to
- @address.
- should_receive(:address_impl).
- once.
- and_return(@address_impl)
- @message_impl.
- should_receive(:setReplyTo).
- once.
- with(@address_impl)
-
- @message.reply_to = @address
- end
-
- def test_get_reply_to
- @message_impl.
- should_receive(:getReplyTo).
- once.
- and_return(@address_impl)
-
- result = @message.reply_to
-
- assert_not_nil result
- assert_same @address_impl, result.address_impl
- end
-
- def test_set_subject
- @message_impl.
- should_receive(:setSubject).
- once.
- with("New Subject")
-
- @message.subject = "New Subject"
- end
-
- def test_get_subject
- @message_impl.
- should_receive(:getSubject).
- once.
- and_return("Old Subject")
-
- assert_equal "Old Subject", @message.subject
- end
-
- def test_set_content_type
- @message_impl.
- should_receive(:setContentType).
- once.
- and_return("amqp/map")
-
- @message.content_type = "amqp/map"
- end
-
- def test_get_content_type
- @message_impl.
- should_receive(:getContentType).
- once.
- and_return("amqp/list")
-
- assert_equal "amqp/list", @message.content_type
- end
-
- def test_set_message_id
- @message_impl.
- should_receive(:setMessageId).
- once.
- with("717")
-
- @message.message_id = "717"
- end
-
- def test_get_message_id
- @message_impl.
- should_receive(:getMessageId).
- once.
- and_return("1965")
-
- assert_equal "1965", @message.message_id
- end
-
- def test_set_user_id
- @message_impl.
- should_receive(:setUserId).
- once.
- with("129")
-
- @message.user_id = "129"
- end
-
- def test_get_user_id
- @message_impl.
- should_receive(:getUserId).
- once.
- and_return("1971")
-
- assert_equal "1971", @message.user_id
- end
-
- def test_set_correlation_id
- @message_impl.
- should_receive(:setCorrelationId).
- once.
- with("320")
-
- @message.correlation_id = "320"
- end
-
- def test_get_correlation_id
- @message_impl.
- should_receive(:getCorrelationId).
- once.
- and_return("1996")
-
- assert_equal "1996", @message.correlation_id
- end
-
- def test_set_priority
- @message_impl.
- should_receive(:setPriority).
- once.
- with(9)
-
- @message.priority = 9
- end
-
- def test_get_priority
- @message_impl.
- should_receive(:getPriority).
- once.
- and_return(21)
-
- assert_equal 21, @message.priority
- end
-
- def test_set_ttl
- @message_impl.
- should_receive(:setTtl).
- once.
- with(Qpid::Messaging::Duration::FOREVER)
-
- @message.ttl = Qpid::Messaging::Duration::FOREVER
- end
-
- def test_get_ttl
- @message_impl.
- should_receive(:getTtl).
- once.
- and_return(Qpid::Messaging::Duration::SECOND)
-
- assert_equal Qpid::Messaging::Duration::SECOND, @message.ttl
- end
-
- def test_set_durable
- @message_impl.
- should_receive(:setDurable).
- once.
- with(true)
-
- @message.durable = true
- end
-
- def test_set_not_durable
- @message_impl.
- should_receive(:setDurable).
- once.
- with(false)
-
- @message.durable = false
- end
-
- def test_get_durable
- @message_impl.
- should_receive(:getDurable).
- once.
- and_return(true)
-
- assert @message.durable
- end
-
- def test_set_redelivered
- @message_impl.
- should_receive(:setRedelivered).
- once.
- with(true)
-
- @message.redelivered = true
- end
-
- def test_set_not_redelivered
- @message_impl.
- should_receive(:setRedelivered).
- once.
- with(false)
-
- @message.redelivered = false
- end
-
- def test_get_redelivered
- @message_impl.
- should_receive(:getRedelivered).
- once.
- and_return(false)
-
- assert !@message.redelivered
- end
-
- def test_get_properties
- properties = {"foo" => "bar"}
- @message_impl.
- should_receive(:getProperties).
- once.
- and_return(properties)
-
- result = @message.properties
-
- assert_equal properties, result
- end
-
- def test_get_property
- @message_impl.
- should_receive(:getProperties).
- once.
- and_return({"foo" => "bar"})
-
- result = @message["foo"]
-
- assert_equal "bar", result
- end
-
- def test_set_property
- @message_impl.
- should_receive(:setProperty).
- once.
- with("foo", "bar")
-
- @message["foo"] = "bar"
- end
-
- def test_set_content
- @message_impl.
- should_receive(:setContent).
- once.
- with("foo")
-
- @message.content = "foo"
- assert_equal "foo", @message.content
- end
-
- def test_set_content_with_array
- content = ["one", "two", "three"]
-
- @messaging.
- should_receive(:encode).
- once.
- with(content, @message, "amqp/list")
-
- @message.content = content
- assert_same content, @message.content
- end
-
- def test_set_content_with_map
- content = {:foo => "bar", :dog => "cat"}
-
- @messaging.
- should_receive(:encode).
- once.
- with(content, @message, "amqp/map")
-
- @message.content = content
- assert_same content, @message.content
- end
-
- def test_get_content
- @message_impl.
- should_receive(:getContent).
- and_return("foo")
- @message_impl.
- should_receive(:getContentType).
- and_return(String)
-
- assert_equal "foo", @message.content
- end
-
- def test_get_content_with_array
- decoded = ["foo", "bar"]
-
- @message_impl.
- should_receive(:getContent).
- and_return("[foo,bar]")
- @message_impl.
- should_receive(:getContentType).
- and_return("amqp/list")
- @messaging.
- should_receive(:decode).
- once.
- with(@message, "amqp/list").
- and_return(decoded)
-
- result = @message.content
- assert_same decoded, result
- end
-
- def test_get_content_size
- @message_impl.
- should_receive(:getContentSize).
- once.
- and_return(68)
-
- assert_equal 68, @message.content_size
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_receiver.rb b/cpp/bindings/qpid/ruby/test/test_receiver.rb
deleted file mode 100644
index 61a4db17f2..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_receiver.rb
+++ /dev/null
@@ -1,238 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'qpid/receiver'
-
-class TestReceiver < Test::Unit::TestCase
-
- def setup
- @session_impl = flexmock("session")
-
- @Message_class = flexmock(Qpid::Messaging::Message)
- @Messaging_module = flexmock(Qpid::Messaging)
- @message_impl = flexmock("message_impl")
- @message = flexmock("message")
-
- @receiver_impl = flexmock("receiver")
- @other_receiver = flexmock("other_receiver")
- @other_receiver_impl = flexmock("other_receiver_impl")
- @receiver = Qpid::Messaging::Receiver.new @receiver_impl
- end
-
- def test_receiver_impl
- assert_same @receiver_impl, @receiver.receiver_impl
- end
-
- def test_get
- @receiver_impl.
- should_receive(:get).
- once.
- with_any_args.
- and_return(@message_impl)
-
- result = @receiver.get
-
- assert_not_nil result
- assert_same @message_impl, result.message_impl
- end
-
- def test_get_with_duration
- @receiver_impl.
- should_receive(:get).
- once.
- with_any_args.
- and_return(@message_impl)
-
- result = @receiver.get Qpid::Messaging::Duration::MINUTE
-
- assert_not_nil result
- assert_same @message_impl, result.message_impl
- end
-
- def test_get_with_no_message_received
- @receiver_impl.
- should_receive(:get).
- once.
- with_any_args.
- and_return(nil)
-
- result = @receiver.get Qpid::Messaging::Duration::SECOND
-
- assert_nil result
- end
-
- def test_fetch
- @receiver_impl.
- should_receive(:fetch).
- once.
- with_any_args.
- and_return(@message_impl)
-
- result = @receiver.fetch
-
- assert_not_nil result
- assert_same @message_impl, result.message_impl
- end
-
- def test_fetch_with_duration
- @receiver_impl.
- should_receive(:fetch).
- once.
- with_any_args.
- and_return(@message_impl)
-
- result = @receiver.fetch Qpid::Messaging::Duration::MINUTE
-
- assert_not_nil result
- assert_same @message_impl, result.message_impl
- end
-
- def test_fetch_with_no_message_received
- @receiver_impl.
- should_receive(:fetch).
- once.
- with_any_args.
- and_return(nil)
-
- result = @receiver.fetch Qpid::Messaging::Duration::SECOND
-
- assert_nil result
- end
-
- def test_set_capacity
- @receiver_impl.
- should_receive(:setCapacity).
- once.
- with(15)
-
- @receiver.capacity = 15
- end
-
- def test_get_capacity
- @receiver_impl.
- should_receive(:getCapacity).
- once.
- and_return(17)
-
- assert_equal 17, @receiver.capacity
- end
-
- def test_get_available
- @receiver_impl.
- should_receive(:getAvailable).
- once.
- and_return(2)
-
- assert_equal 2, @receiver.available
- end
-
- def test_get_unsettled
- @receiver_impl.
- should_receive(:getUnsettled).
- once.
- and_return(12)
-
- assert_equal 12, @receiver.unsettled
- end
-
- def test_close
- @receiver_impl.
- should_receive(:close).
- once
-
- @receiver.close
- end
-
- def test_closed_when_open
- @receiver_impl.
- should_receive(:isClosed).
- once.
- and_return(false)
-
- assert !@receiver.closed?
- end
-
- def test_closed
- @receiver_impl.
- should_receive(:isClosed).
- once.
- and_return(true)
-
- assert @receiver.closed?
- end
-
- def test_get_name
- @receiver_impl.
- should_receive(:getName).
- once.
- and_return("my-queue")
-
- assert_equal "my-queue", @receiver.name
- end
-
- def test_get_session
- @receiver_impl.
- should_receive(:getSession).
- once.
- and_return(@session_impl)
-
- result = @receiver.session
-
- assert_not_nil result
- assert_same @session_impl, result.session_impl
- end
-
- def test_is_valid
- @receiver_impl.
- should_receive(:isValid).
- once.
- and_return(false)
-
- assert !@receiver.valid?
- end
-
- def test_is_null
- @receiver_impl.
- should_receive(:isNull).
- once.
- and_return(true)
-
- assert @receiver.null?
- end
-
- def test_swap
- @other_receiver.
- should_receive(:receiver_impl).
- once.
- and_return(@other_receiver_impl)
- @receiver_impl.
- should_receive(:swap).
- once.
- with(@other_receiver_impl)
-
- @receiver.swap @other_receiver
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_sender.rb b/cpp/bindings/qpid/ruby/test/test_sender.rb
deleted file mode 100644
index 64348b9f72..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_sender.rb
+++ /dev/null
@@ -1,183 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'qpid/sender'
-
-class TestSender < Test::Unit::TestCase
-
- def setup
- @messaging = flexmock(Qpid::Messaging)
- @message = flexmock("message")
-
- @session_impl = flexmock("session_impl")
-
- @sender_impl = flexmock("sender_impl")
- @other_sender_impl = flexmock("other_sender_impl")
- @sender = Qpid::Messaging::Sender.new @sender_impl
- @other_sender = flexmock("other_sender")
- end
-
- def test_send
- message_impl = "message_impl"
- content = {:foo => :bar}
- @message.
- should_receive(:message_impl).
- once.
- and_return(message_impl)
- @sender_impl.
- should_receive(:send).
- once.
- with(message_impl, false)
-
- @sender.send @message
- end
-
- def test_send_and_dont_block
- message_impl = "message_impl"
- content = {:foo => :bar}
- @message.
- should_receive(:message_impl).
- once.
- and_return(message_impl)
- @sender_impl.
- should_receive(:send).
- once.
- with(message_impl, false)
-
- @sender.send @message, :block => false
- end
-
- def test_send_and_block
- message_impl = "message_impl"
- content = {:foo => :bar}
- @message.
- should_receive(:message_impl).
- once.
- and_return(message_impl)
- @sender_impl.
- should_receive(:send).
- once.
- with(message_impl, true)
-
- @sender.send @message, :block => true
- end
-
- def test_close
- @sender_impl.
- should_receive(:close).
- once
-
- @sender.close
- end
-
- def test_set_capacity
- @sender_impl.
- should_receive(:setCapacity).
- once.
- with(17)
-
- @sender.capacity = 17
- end
-
- def test_get_capacity
- @sender_impl.
- should_receive(:getCapacity).
- once.
- and_return(12)
-
- assert_equal 12, @sender.capacity
- end
-
- def test_unsettled
- @sender_impl.
- should_receive(:getUnsettled).
- once.
- and_return(5)
-
- assert_equal 5, @sender.unsettled
- end
-
- def test_available
- @sender_impl.
- should_receive(:getAvailable).
- once.
- and_return(15)
-
- assert_equal 15, @sender.available
- end
-
- def test_name
- @sender_impl.
- should_receive(:getName).
- once.
- and_return("myname")
-
- assert_equal "myname", @sender.name
- end
-
- def test_session
- @sender_impl.
- should_receive(:getSession).
- once.
- and_return(@session_impl)
-
- result = @sender.session
-
- assert_not_nil result
- assert_same @session_impl, result.session_impl
- end
-
- def test_is_valid
- @sender_impl.
- should_receive(:isValid).
- once.
- and_return(true)
-
- assert @sender.valid?
- end
-
- def test_is_null
- @sender_impl.
- should_receive(:isNull).
- once.
- and_return(false)
-
- assert !@sender.null?
- end
-
- def test_swap
- @other_sender.
- should_receive(:sender_impl).
- once.
- and_return(@other_sender_impl)
- @sender_impl.
- should_receive(:swap).
- once.
- with(@other_sender_impl)
-
- @sender.swap @other_sender
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_session.rb b/cpp/bindings/qpid/ruby/test/test_session.rb
deleted file mode 100644
index 20f055967b..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_session.rb
+++ /dev/null
@@ -1,445 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'qpid/errors'
-require 'qpid/duration'
-require 'qpid/session'
-
-class TestSession < Test::Unit::TestCase
-
- def setup
- @session_impl = flexmock("session_impl")
- @other_session = flexmock("other_session")
- @other_session_impl = flexmock("other_session_impl")
- @sender = flexmock("sender")
-
- @Connection_class = flexmock(Qpid::Messaging::Connection)
- @connection_impl = flexmock("connection_impl")
- @connection = flexmock("connection")
-
- @Receiver_class = flexmock(Qpid::Messaging::Receiver)
- @receiver = flexmock("receiver")
- @receiver_impl = flexmock("receiver_impl")
-
- @address = flexmock("address")
- @address_impl = flexmock("address_impl")
-
- @Sender_class = flexmock(Qpid::Messaging::Sender)
- @sender = flexmock("sender")
- @sender_impl = flexmock("sender_impl")
-
- @message = flexmock("message")
- @message_impl = flexmock("message_impl")
-
- @duration = flexmock("duration")
- @duration_impl = flexmock("duration_impl")
-
- @session = Qpid::Messaging::Session.new(@session_impl)
- end
-
- def test_create_sender_with_Address
- @address.
- should_receive(:class).
- once.
- and_return(Qpid::Messaging::Address).
- should_receive(:address_impl).
- once.
- and_return(@address_impl)
- @session_impl.
- should_receive(:createSender).
- once.
- with(@address_impl).
- and_return(@sender_impl)
-
- result = @session.create_sender @address
-
- assert_not_nil result
- end
-
- def test_create_sender
- @session_impl.
- should_receive(:createSender).
- once.
- with_any_args.
- and_return(@sender_impl)
-
- result = @session.create_sender("my-queue")
-
- assert_not_nil result
- end
-
- def test_create_sender_with_address_string
- @session_impl.
- should_receive(:createSender).
- once.
- with("my-queue;{create:always}").
- and_return(@sender_impl)
-
- result = @session.create_sender "my-queue;{create:always}"
-
- assert_same @sender_impl, result.sender_impl
- end
-
- def test_create_receiver
- @address.
- should_receive(:class).
- once.
- and_return(Qpid::Messaging::Address).
- should_receive(:address_impl).
- once.
- and_return(@address_impl)
- @session_impl.
- should_receive(:createReceiver).
- once.
- with(@address_impl).
- and_return(@receiver_impl)
-
- result = @session.create_receiver(@address)
-
- assert_equal @receiver_impl, result.receiver_impl
- end
-
- def test_create_receiver_with_address_string
- @session_impl.
- should_receive(:createReceiver).
- once.
- with("my-queue").
- and_return(@receiver_impl)
-
- result = @session.create_receiver("my-queue")
-
- assert_same @receiver_impl, result.receiver_impl
- end
-
- def test_close
- @session_impl.
- should_receive(:close).
- once
-
- @session.close
- end
-
- def test_commit
- @session_impl.
- should_receive(:commit).
- once
-
- @session.commit
- end
-
- def test_rollback
- @session_impl.
- should_receive(:rollback).
- once
-
- @session.rollback
- end
-
- def test_acknowledge_with_no_args
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(false)
-
- @session.acknowledge
- end
-
- def test_acknowledge_and_sync
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(true)
-
- @session.acknowledge :sync => true
- end
-
- def test_acknowledge_and_dont_sync
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(false)
-
- @session.acknowledge :sync => false
- end
-
- def test_acknowledge_message_without_sync
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(@message_impl, false)
-
- @session.acknowledge :message => @message
- end
-
- def test_acknowledge_message_and_sync
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(@message_impl, true)
-
- @session.acknowledge :message => @message, :sync => true
- end
-
- def test_acknowledge_message_and_dont_sync
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(@message_impl, false)
-
- @session.acknowledge :message => @message, :sync => false
- end
-
- def test_reject_message
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @session_impl.
- should_receive(:reject).
- once.
- with(@message_impl)
-
- @session.reject @message
- end
-
- def test_release_message
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @session_impl.
- should_receive(:release).
- once.
- with(@message_impl)
-
- @session.release @message
- end
-
- def test_sync_without_block
- @session_impl.
- should_receive(:sync).
- once
-
- @session.sync
- end
-
- def test_sync_and_block
- @session_impl.
- should_receive(:sync).
- once.
- with(true)
-
- @session.sync :block => true
- end
-
- def test_sync_and_dont_block
- @session_impl.
- should_receive(:sync).
- once.
- with(false)
-
- @session.sync :block => false
- end
-
- def test_receivable
- @session_impl.
- should_receive(:getReceivable).
- once.
- and_return(5)
-
- assert_equal 5, @session.receivable
- end
-
- def test_unsettled_acks
- @session_impl.
- should_receive(:getUnsettledAcks).
- once.
- and_return(17)
-
- assert_equal 17, @session.unsettled_acks
- end
-
- def test_next_receiver_with_no_duration
- @session_impl.
- should_receive(:nextReceiver).
- once.
- with(Qpid::Messaging::Duration::FOREVER.duration_impl).
- and_return(@receiver_impl)
-
- result = @session.next_receiver
-
- assert_same @receiver_impl, result.receiver_impl
- end
-
- def test_next_receiver_with_duration
- @duration.
- should_receive(:duration_impl).
- once.
- and_return(@duration_impl)
- @session_impl.
- should_receive(:nextReceiver).
- once.
- with(@duration_impl).
- and_return(@receiver_impl)
-
- result = @session.next_receiver @duration
-
- assert_same @receiver_impl, result.receiver_impl
- end
-
- def test_sender
- @session_impl.
- should_receive(:getSender).
- once.
- with("farkle").
- and_return(@sender_impl)
- @Sender_class.
- should_receive(:for_impl).
- once.
- with(@sender_impl).
- and_return(@sender)
-
- result = @session.sender "farkle"
-
- assert_same @sender, result
- end
-
- def test_sender_with_invalid_name
- @session_impl.
- should_receive(:getSender).
- once.
- with("farkle").
- and_throw(RuntimeError)
-
- assert_raise(Qpid::Messaging::KeyError) {@session.sender "farkle"}
- end
-
- def test_receiver
- @session_impl.
- should_receive(:getReceiver).
- once.
- with("farkle").
- and_return(@receiver_impl)
- @Receiver_class.
- should_receive(:for_impl).
- once.
- with(@receiver_impl).
- and_return(@receiver)
-
- result = @session.receiver "farkle"
-
- assert_same @receiver, result
- end
-
- def test_receiver_with_invalid_name
- @session_impl.
- should_receive(:getReceiver).
- once.
- with("farkle").
- and_throw(RuntimeError)
-
- assert_raise(Qpid::Messaging::KeyError) {@session.receiver "farkle"}
- end
-
- def test_connection
- @session_impl.
- should_receive(:getConnection).
- once.
- and_return(@connection_impl)
-
- result = @session.connection
-
- assert_same @connection_impl, result.connection_impl
- end
-
- def test_error_with_none
- @session_impl.
- should_receive(:hasError).
- once.
- and_return(false)
-
- assert !@session.error?
- end
-
- def test_error
- @session_impl.
- should_receive(:hasError).
- once.
- and_return(true)
-
- assert @session.error?
- end
-
- def test_check_error
- @session_impl.
- should_receive(:checkError).
- once
-
- @session.check_error
- end
-
- def test_is_valid
- @session_impl.
- should_receive(:isValid).
- once.
- and_return(false)
-
- assert !@session.valid?
- end
-
- def test_is_null
- @session_impl.
- should_receive(:isNull).
- once.
- and_return(false)
-
- assert !@session.null?
- end
-
- def test_swap
- @other_session.
- should_receive(:session_impl).
- once.
- and_return(@other_session_impl)
- @session_impl.
- should_receive(:swap).
- once.
- with(@other_session_impl)
-
- @session.swap @other_session
- end
-
-end
diff --git a/cpp/bindings/qpid/ruby/test/ts_bindings.rb b/cpp/bindings/qpid/ruby/test/ts_bindings.rb
deleted file mode 100644
index 7aa410c8f8..0000000000
--- a/cpp/bindings/qpid/ruby/test/ts_bindings.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'test_encoding'
-require 'test_address'
-require 'test_message'
-require 'test_sender'
-require 'test_receiver'
-require 'test_session'
-require 'test_connection'
-
diff --git a/cpp/bindings/swig_python_typemaps.i b/cpp/bindings/swig_python_typemaps.i
index 18bfd48f72..b69784a6de 100644
--- a/cpp/bindings/swig_python_typemaps.i
+++ b/cpp/bindings/swig_python_typemaps.i
@@ -17,25 +17,6 @@
* under the License.
*/
-/* For UUID objects, to convert them to Python uuid.UUID objects,
- * we'll need a reference to the uuid module.
- */
-%{
-static PyObject* pUuidModule;
-%}
-
-%init %{
- pUuidModule = PyImport_ImportModule("uuid");
-
- /* Although it is not required, we'll publish the uuid module in our
- * module, as if this module was a python module and we called
- * "import uuid"
- */
- Py_INCREF(pUuidModule);
- PyModule_AddObject(m, "uuid", pUuidModule);
-%}
-
-
%wrapper %{
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
@@ -47,7 +28,6 @@ typedef int Py_ssize_t;
PyObject* MapToPy(const qpid::types::Variant::Map*);
PyObject* ListToPy(const qpid::types::Variant::List*);
- PyObject* UuidToPy(const qpid::types::Uuid*);
void PyToMap(PyObject*, qpid::types::Variant::Map*);
void PyToList(PyObject*, qpid::types::Variant::List*);
@@ -124,9 +104,6 @@ typedef int Py_ssize_t;
break;
}
case qpid::types::VAR_UUID : {
- qpid::types::Uuid uuid = v->asUuid();
- result = UuidToPy(&uuid);
- break;
}
}
} catch (qpid::types::Exception& ex) {
@@ -166,30 +143,6 @@ typedef int Py_ssize_t;
return result;
}
- PyObject* UuidToPy(const qpid::types::Uuid * uuid) {
- PyObject* pUuidClass = PyObject_GetAttrString(pUuidModule, "UUID");
- if (!pUuidClass) {
- // Failed to get UUID class
- return 0;
- }
-
- PyObject* pArgs = PyTuple_New(0);
- PyObject* pKw = PyDict_New();
- PyObject* pData = PyString_FromStringAndSize(
- (const char*)(uuid->data()), 16);
- PyDict_SetItemString(pKw, "bytes", pData);
-
- PyObject* result = PyObject_Call(pUuidClass, pArgs, pKw);
-
- Py_DECREF(pData);
- Py_DECREF(pKw);
- Py_DECREF(pArgs);
- Py_DECREF(pUuidClass);
-
- return result;
- }
-
-
void PyToMap(PyObject* obj, qpid::types::Variant::Map* map) {
map->clear();
Py_ssize_t iter(0);
@@ -351,15 +304,6 @@ typedef int Py_ssize_t;
Py_INCREF($result);
}
-/*
- * UUID type: C++ --> Python
- */
-%typemap(out) qpid::types::UUID & {
- $result = UuidToPy($1);
- if ($result)
- Py_INCREF($result);
-}
-
/*
* Variant types: Ruby --> C++
diff --git a/cpp/bindings/swig_ruby_typemaps.i b/cpp/bindings/swig_ruby_typemaps.i
index 326d607c8d..79e679663d 100644
--- a/cpp/bindings/swig_ruby_typemaps.i
+++ b/cpp/bindings/swig_ruby_typemaps.i
@@ -49,7 +49,7 @@
}
VALUE VariantToRb(const qpid::types::Variant* v) {
- VALUE result = Qnil;
+ VALUE result;
try {
switch (v->getType()) {
case qpid::types::VAR_VOID: {
diff --git a/cpp/bld-winsdk.ps1 b/cpp/bld-winsdk.ps1
index bea46da28f..8f0a5886dc 100644
--- a/cpp/bld-winsdk.ps1
+++ b/cpp/bld-winsdk.ps1
@@ -186,6 +186,9 @@ function BuildAPlatform
'examples/qmf-console',
'examples/request-response',
'examples/tradedemo',
+ 'examples/old-examples.sln',
+ 'examples/README.*',
+ 'examples/verify*',
'include',
'plugins')
diff --git a/cpp/configure.ac b/cpp/configure.ac
index 092694d56b..ea1a1b49ea 100644
--- a/cpp/configure.ac
+++ b/cpp/configure.ac
@@ -68,10 +68,8 @@ if test x$GXX = xyes; then
# The following warnings are deliberately omitted, they warn on valid code.
# -Wunreachable-code -Wpadded -Winline
# -Wshadow - warns about boost headers.
- # Can't test for -Werror as whether it fails or not depends on what's in
- # CFLAGS/CXXFLAGS. In any case it's been in gcc for a long time (since 2.95 at least)
if test "${enableval}" = yes; then
- COMPILER_FLAGS="-Werror"
+ gl_COMPILER_FLAGS(-Werror)
gl_COMPILER_FLAGS(-pedantic)
gl_COMPILER_FLAGS(-Wall)
gl_COMPILER_FLAGS(-Wextra)
@@ -523,19 +521,18 @@ AM_PATH_PYTHON()
builddir_lib_suffix="/.libs"
AC_SUBST([builddir_lib_suffix])
-# Files to generate
+# Files to generate
AC_CONFIG_FILES([
Makefile
examples/Makefile
- examples/old_api/Makefile
- examples/old_api/direct/Makefile
- examples/old_api/fanout/Makefile
- examples/old_api/pub-sub/Makefile
- examples/old_api/request-response/Makefile
- examples/old_api/failover/Makefile
- examples/old_api/xml-exchange/Makefile
+ examples/direct/Makefile
+ examples/fanout/Makefile
+ examples/pub-sub/Makefile
+ examples/request-response/Makefile
+ examples/failover/Makefile
+ examples/xml-exchange/Makefile
examples/qmf-console/Makefile
- examples/old_api/tradedemo/Makefile
+ examples/tradedemo/Makefile
examples/messaging/Makefile
bindings/qpid/Makefile
bindings/qpid/ruby/Makefile
diff --git a/cpp/design_docs/hot-standby-design.txt b/cpp/design_docs/hot-standby-design.txt
deleted file mode 100644
index 99a5dc0199..0000000000
--- a/cpp/design_docs/hot-standby-design.txt
+++ /dev/null
@@ -1,239 +0,0 @@
--*-org-*-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-* Another new design for Qpid clustering.
-
-For background see [[./new-cluster-design.txt]] which describes the issues
-with the old design and a new active-active design that could replace it.
-
-This document describes an alternative hot-standby approach.
-
-** Delivery guarantee
-
-We guarantee N-way redundant, at least once delivey. Once a message
-from a client has been acknowledged by the broker, it will be
-delivered even if N-1 brokers subsequently fail. There may be
-duplicates in the event of a failure. We don't make duplicates
-during normal operation (i.e when no brokers have failed)
-
-This is the same guarantee as the old cluster and the alternative
-active-active design.
-
-** Active-active vs. hot standby (aka primary-backup)
-
-An active-active cluster allows clients to connect to any broker in
-the cluster. If a broker fails, clients can fail-over to any other
-live broker.
-
-A hot-standby cluster has only one active broker at a time (the
-"primary") and one or more brokers on standby (the "backups"). Clients
-are only served by the leader, clients that connect to a backup are
-redirected to the leader. The backpus are kept up-to-date in real time
-by the primary, if the primary fails a backup is elected to be the new
-primary.
-
-Aside: A cold-standby cluster is possible using a standalone broker,
-CMAN and shared storage. In this scenario only one broker runs at a
-time writing to a shared store. If it fails, another broker is started
-(by CMAN) and recovers from the store. This bears investigation but
-the store recovery time is probably too long for failover.
-
-** Why hot standby?
-
-Active-active has some advantages:
-- Finding a broker on startup or failover is simple, just pick any live broker.
-- All brokers are always running in active mode, there's no
-- Distributing clients across brokers gives better performance, but see [1].
-- A broker failure affects only clients connected to that broker.
-
-The main problem with active-active is co-ordinating consumers of the
-same queue on multiple brokers such that there are no duplicates in
-normal operation. There are 2 approaches:
-
-Predictive: each broker predicts which messages others will take. This
-the main weakness of the old design so not appealing.
-
-Locking: brokers "lock" a queue in order to take messages. This is
-complex to implement, its not straighforward to determine the most
-performant strategie for passing the lock.
-
-Hot-standby removes this problem. Only the primary can modify queues
-so it just has to tell the backups what it is doing, there's no
-locking.
-
-The primary can enqueue messages and replicate asynchronously -
-exactly like the store does, but it "writes" to the replicas over the
-network rather than writing to disk.
-
-** Failover in a hot-standby cluster.
-
-Hot-standby has some potential performance issues around failover:
-
-- Failover "spike": when the primary fails every client will fail over
- at the same time, putting strain on the system.
-
-- Until a new primary is elected, cluster cannot serve any clients or
- redirect clients to the primary.
-
-We want to minimize the number of re-connect attempts that clients
-have to make. The cluster can use a well-known algorithm to choose the
-new primary (e.g. round robin on a known sequence of brokers) so that
-clients can guess the new primary correctly in most cases.
-
-Even if clients do guess correctly it may be that the new primary is
-not yet aware of the death of the old primary, which is may to cause
-multiple failed connect attempts before clients eventually get
-connected. We will need to prototype to see how much this happens in
-reality and how we can best get clients redirected.
-
-** Threading and performance.
-
-The primary-backup cluster operates analogously to the way the disk store does now:
-- use the same MessageStore interface as the store to interact with the broker
-- use the same asynchronous-completion model for replicating messages.
-- use the same recovery interfaces (?) for new backups joining.
-
-Re-using the well-established store design gives credibility to the new cluster design.
-
-The single CPG dispatch thread was a severe performance bottleneck for the old cluster.
-
-The primary has the same threading model as a a standalone broker with
-a store, which we know that this performs well.
-
-If we use CPG for replication of messages, the backups will receive
-messages in the CPG dispatch thread. To get more concurency, the CPG
-thread can dump work onto internal PollableQueues to be processed in
-parallel.
-
-Messages from the same broker queue need to go onto the same
-PollableQueue. There could be a separate PollableQueue for each broker
-queue. If that's too resource intensive we can use a fixed set of
-PollableQueues and assign broker queues to PollableQueues via hashing
-or round robin.
-
-Another possible optimization is to use multiple CPG queues: one per
-queue or a hashed set, to get more concurrency in the CPG layer. The
-old cluster is not able to keep CPG busy.
-
-TODO: Transactions pose a challenge with these concurrent models: how
-to co-ordinate multiple messages being added (commit a publish or roll
-back an accept) to multiple queues so that all replicas end up with
-the same message sequence while respecting atomicity.
-
-** Use of CPG
-
-CPG provides several benefits in the old cluster:
-- tracking membership (essential for determining the primary)
-- handling "spit brain" (integrates with partition support from CMAN)
-- reliable multicast protocol to distribute messages.
-
-I believe we still need CPG for membership and split brain. We could
-experiment with sending the bulk traffic over AMQP conections.
-
-** Flow control
-
-Need to ensure that
-1) In-memory internal queues used by the cluster don't overflow.
-2) The backups don't fall too far behind on processing CPG messages
-
-** Recovery
-When a new backup joins an active cluster it must get a snapshot
-from one of the other backups, or the primary if there are none. In
-store terms this is "recovery" (old cluster called it an "update)
-
-Compared to old cluster we only replidate well defined data set of the store.
-This is the crucial sore spot of old cluster.
-
-We can also replicated it more efficiently by recovering queues in
-reverse (LIFO) order. That means as clients actively consume messages
-from the front of the queue, they are redeucing the work we have to do
-in recovering from the back. (NOTE: this may not be compatible with
-using the same recovery interfaces as the store.)
-
-** Selective replication
-In this model it's easy to support selective replication of individual queues via
-configuration.
-- Explicit exchange/queue declare argument and message boolean: x-qpid-replicate.
- Treated analogously to persistent/durable properties for the store.
-- if not explicitly marked, provide a choice of default
- - default is replicate (replicated message on replicated queue)
- - default is don't replicate
- - default is replicate persistent/durable messages.
-
-** Inconsistent errors
-
-The new design eliminates most sources of inconsistent errors in the
-old design (connections, sessions, security, management etc.) and
-eliminates the need to stall the whole cluster till an error is
-resolved. We still have to handle inconsistent store errors when store
-and cluster are used together.
-
-We also have to include error handling in the async completion loop to
-guarantee N-way at least once: we should only report success to the
-client when we know the message was replicated and stored on all N-1
-backups.
-
-TODO: We have a lot more options than the old cluster, need to figure
-out the best approach, or possibly allow mutliple approaches. Need to
-go thru the various failure cases. We may be able to do recovery on a
-per-queue basis rather than restarting an entire node.
-
-** New members joining
-
-We should be able to catch up much faster than the the old design. A
-new backup can catch up ("recover") the current cluster state on a
-per-queue basis.
-- queues can be updated in parallel
-- "live" updates avoid the the "endless chase"
-
-During a "live" update several things are happening on a queue:
-- clients are publishing messages to the back of the queue, replicated to the backup
-- clients are consuming messages from the front of the queue, replicated to the backup.
-- the primary is sending pre-existing messages to the new backup.
-
-The primary sends pre-existing messages in LIFO order - starting from
-the back of the queue, at the same time clients are consuming from the front.
-The active consumers actually reduce the amount of work to be done, as there's
-no need to replicate messages that are no longer on the queue.
-
-* Steps to get there
-
-** Baseline replication
-Validate the overall design get initial notion of performance. Just
-message+wiring replication, no update/recovery for new members joining,
-single CPG dispatch thread on backups, no failover, no transactions.
-
-** Failover
-Electing primary, backups redirect to primary. Measure failover time
-for large # clients. Strategies to minimise number of retries after a
-failure.
-
-** Flow Control
-Keep internal queues from over-flowing. Similar to internal flow control in old cluster.
-Needed for realistic performance/stress tests
-
-** Concurrency
-Experiment with multiple threads on backups, multiple CPG groups.
-
-** Recovery/new member joining
-Initial status handshake for new member. Recovering queues from the back.
-
-** Transactions
-TODO: How to implement transactions with concurrency. Worst solution:
-a global --cluster-use-transactions flag that forces single thread
-mode. Need to find a better solution.
diff --git a/cpp/design_docs/new-cluster-design.txt b/cpp/design_docs/new-cluster-design.txt
index a162ea68ec..7adb46fee3 100644
--- a/cpp/design_docs/new-cluster-design.txt
+++ b/cpp/design_docs/new-cluster-design.txt
@@ -17,6 +17,7 @@
# under the License.
* A new design for Qpid clustering.
+
** Issues with current design.
The cluster is based on virtual synchrony: each broker multicasts
@@ -94,9 +95,8 @@ Use a moving queue ownership protocol to agree order of dequeues.
No longer relies on identical state and lock-step behavior to cause
identical dequeues on each broker.
-Use multiple CPG groups to process different queues in parallel. Use a
-fixed set of groups and hash queue names to choose the group for each
-queue.
+Each queue has an associated thread-context. Events for a queue are executed
+in that queues context, in parallel with events for other queues.
*** Requirements
@@ -149,7 +149,7 @@ a release-queue event, allowing another interested broker to take
ownership.
*** Asynchronous completion of accept
-
+### HERE
In acknowledged mode a message is not forgotten until it is accepted,
to allow for requeue on rejection or crash. The accept should not be
completed till the message has been forgotten.
@@ -162,32 +162,19 @@ On receiving an accept the broker:
NOTE: The message store does not currently implement asynchronous
completions of accept, this is a bug.
-*** Multiple CPG groups.
-
-The old cluster was bottlenecked by processing everything in a single
-CPG deliver thread.
-
-The new cluster uses a set of CPG groups, one per core. Queue names
-are hashed to give group indexes, so statistically queues are likely
-to be spread over the set of groups.
-
-Operations on a given queue always use the same group, so we have
-order within each queue, but operations on different queues can use
-different groups giving greater throughput sending to CPG and multiple
-handler threads to process CPG messages.
-
** Inconsistent errors.
-An inconsistent error means that after multicasting an enqueue, accept
-or dequeue, some brokers succeed in processing it and others fail.
+The new design eliminates most sources of inconsistent errors
+(connections, sessions, security, management etc.) The only points
+where inconsistent errors can occur are at enqueue and dequeue (most
+likely store-related errors.)
-The new design eliminates most sources of inconsistent errors in the
-old broker: connections, sessions, security, management etc. Only
-store journal errors remain.
+The new design can use the exisiting error-handling protocol with one
+major improvement: since brokers are no longer required to maintain
+identical state they do not have to stall processing while an error is
+being resolved.
-The new inconsistent error protocol is similar to the old one with one
-major improvement: brokers do not have to stall processing while an
-error is being resolved.
+#TODO: The only source of dequeue errors is probably an unrecoverable journal failure.
** Updating new members
@@ -206,44 +193,60 @@ catch up (which is not guaranteed to happen in a bounded time.)
With the new cluster design only exchanges, queues, bindings and
messages need to be replicated.
-We update individual objects (queues and exchanges) independently.
-- create queues first, then update all queues and exchanges in parallel.
-- multiple updater threads, per queue/exchange.
+Update of wiring (exchanges, queues, bindings) is the same as current
+design.
+
+Update of messages is different:
+- per-queue rather than per-broker, separate queues can be updated in parallel.
+- updates queues in reverse order to eliminate unbounded catch-up
+- does not require updater & updatee to stall during update.
-Queue updater:
-- marks the queue position at the sync point
-- sends messages starting from the sync point working towards the head of the queue.
-- send "done" message.
+Replication events, multicast to cluster:
+- enqueue(q,m): message m pushed on back of queue q .
+- acquire(q,m): mark m acquired
+- dequeue(q,m): forget m.
+Messages sent on update connection:
+- update_front(q,m): during update, receiver pushes m to *front* of q
+- update_done(q): during update, update of q is complete.
-Queue updatee:
-- enqueues received from CPG: add to back of queue as normal.
-- dequeues received from CPG: apply if found, else save to check at end of update.
-- messages from updater: add to the *front* of the queue.
-- update complete: apply any saved dequeues.
+Updater:
+- when updatee joins set iterator i = q.end()
+- while i != q.begin(): --i; send update_front(q,*i) to updatee
+- send update_done(q) to updatee
-Exchange updater:
-- updater: send snapshot of exchange as it was at the sync point.
+Updatee:
+- q initially in locked state, can't dequeue locally.
+- start processing replication events for q immediately (enqueue, dequeue, acquire etc.)
+- receive update_front(q,m): q.push_front(m)
+- receive update_done(q): q can be unlocked for local dequeing.
-Exchange updatee:
-- queue exchange operations after the sync point.
-- when snapshot is received: apply saved operations.
+Benefits:
+- Stall only for wiring update: updater & updatee can process multicast messages while messages are updated.
+- No unbounded catch-up: update consists of at most N update_front() messages where N=q.size() at start of update.
+- During update consumers actually help by removing messages before they need to be updated.
+- Needs no separate "work to do" queue, only the broker queues themselves.
-Note:
-- Updater is active throughout, no stalling.
-- Consuming clients actually reduce the size of the update.
-- Updatee stalls clients until the update completes.
- (Note: May be possible to avoid updatee stall as well, needs thought)
+# TODO how can we recover from updater crashing before update complete?
+# Clear queues that are not updated & send request for udpates on those queues?
-** Internal cluster interface
+# TODO updatee may receive a dequeue for a message it has not yet seen, needs
+# to hold on to that so it can drop the message when it is seen.
+# Similar problem exists for wiring?
-The new cluster interface is similar to the MessageStore interface, but
-provides more detail (message positions) and some additional call
-points (e.g. acquire)
+** Cluster API
+
+The new cluster API is similar to the MessageStore interface.
+(Initially I thought it would be an extension of the MessageStore interface,
+but as the design develops it seems better to make it a separate interface.)
The cluster interface captures these events:
- wiring changes: queue/exchange declare/bind
- message enqueued/acquired/released/rejected/dequeued.
-- transactional events.
+
+The cluster will require some extensions to the Queue:
+- Queues can be "locked", locked queues are ignored by IO-driven output.
+- Cluster must be able to apply queue events from the cluster to a queue.
+ These appear to fit into existing queue operations.
** Maintainability
@@ -270,48 +273,106 @@ A number of specific ways the code will be simplified:
** Performance
-The standalone broker processes _connections_ concurrently, so CPU
-usage increases as you add more connections.
-
-The new cluster processes _queues_ concurrently, so CPU usage increases as you
-add more queues.
-
-In both cases, CPU usage peaks when the number of "units of
- concurrency" (connections or queues) goes above the number of cores.
-
-When all consumers on a queue are connected to the same broker the new
-cluster uses the same messagea allocation threading/logic as a
-standalone broker, with a little extra asynchronous book-keeping.
-
-If a queue has multiple consumers connected to multiple brokers, the
-new cluster time-shares the queue which is less efficient than having
-all consumers on a queue connected to the same broker.
+The only way to verify the relative performance of the new design is
+to prototype & profile. The following points suggest the new design
+may scale/perform better:
+
+Some work moved from virtual synchrony thread to connection threads:
+- All connection/session logic moves to connection thread.
+- Exchange routing logic moves to connection thread.
+- On local broker dequeueing is done in connection thread
+- Local broker dequeue is IO driven as for a standalone broker.
+
+For queues with all consumers on a single node dequeue is all
+IO-driven in connection thread. Pay for time-sharing only if queue has
+consumers on multiple brokers.
+
+Doing work for different queues in parallel scales on multi-core boxes when
+there are multiple queues.
+
+One difference works against performance, thre is an extra
+encode/decode. The old design multicasts raw client data and decodes
+it in the virtual synchrony thread. The new design would decode
+messages in the connection thread, re-encode them for multicast, and
+decode (on non-local brokers) in the virtual synchrony thread. There
+is extra work here, but only in the *connection* thread: on a
+multi-core machine this happens in parallel for every connection, so
+it probably is not a bottleneck. There may be scope to optimize
+decode/re-encode by re-using some of the original encoded data, this
+could also benefit the stand-alone broker.
+
+** Asynchronous queue replication
+
+The existing "asynchronous queue replication" feature maintains a
+passive backup passive backup of queues on a remote broker over a TCP
+connection.
+
+The new cluster replication protocol could be re-used to implement
+asynchronous queue replication: its just a special case where the
+active broker is always the queue owner and the enqueue/dequeue
+messages are sent over a TCP connection rather than multicast.
+
+The new update update mechanism could also work with 'asynchronous
+queue replication', allowing such replication (over a TCP connection
+on a WAN say) to be initiated after the queue had already been created
+and been in use (one of the key missing features).
+
+** Increasing Concurrency and load sharing
+
+The current cluster is bottlenecked by processing everything in the
+CPG deliver thread. By removing the need for identical operation on
+each broker, we open up the possiblility of greater concurrency.
+
+Handling multicast enqueue, acquire, accpet, release etc: concurrency
+per queue. Operatons on different queues can be done in different
+threads.
+
+The new design does not force each broker to do all the work in the
+CPG thread so spreading load across cluster members should give some
+scale-up.
+
+** Misc outstanding issues & notes
+
+Replicating wiring
+- Need async completion of wiring commands?
+- qpid.sequence_counter: need extra work to support in new design, do we care?
+
+Cluster+persistence:
+- finish async completion: dequeue completion for store & cluster
+- cluster restart from store: clean stores *not* identical, pick 1, all others update.
+- need to generate cluster ids for messages recovered from store.
+
+Live updates: we don't need to stall brokers during an update!
+- update on queue-by-queue basis.
+- updatee locks queues during update, no dequeue.
+- update in reverse: don't update messages dequeued during update.
+- updatee adds update messages at front (as normal), replicated messages at back.
+- updater starts from back, sends "update done" when it hits front of queue.
+
+Flow control: need to throttle multicasting
+1. bound the number of outstanding multicasts.
+2. ensure the entire cluster keeps up, no unbounded "lag"
+The existing design uses read-credit to solve 1., and does not solve 2.
+New design should stop reading on all connections while flow control
+condition exists?
+
+Can federation also be unified, at least in configuration?
+
+Consider queues (and exchanges?) as having "reliability" attributes:
+- persistent: is the message stored on disk.
+- backed-up (to another broker): active/passive async replication.
+- replicated (to a cluster): active/active multicast replication to cluster.
+- federated: federation link to a queue/exchange on another broker.
+
+"Reliability" seems right for the first 3 but not for federation, is
+there a better term?
+
+Clustering and scalability: new design may give us the flexibility to
+address scalability as part of cluster design. Think about
+relationship to federation and "fragmented queues" idea.
+
+* Design debates/descisions
-** Flow control
-New design does not queue up CPG delivered messages, they are
-processed immediately in the CPG deliver thread. This means that CPG's
-flow control is sufficient for qpid.
-
-** Live upgrades
-
-Live upgrades refers to the ability to upgrade a cluster while it is
-running, with no downtime. Each brokers in the cluster is shut down,
-and then re-started with a new version of the broker code.
-
-To achieve this
-- Cluster protocl XML file has a new element <version number=N> attached
- to each method. This is the version at which the method was added.
-- New versions can only add methods, existing methods cannot be changed.
-- The cluster handshake for new members includes the protocol version
- at each member.
-- The cluster's version is the lowest version among its members.
-- A newer broker can join and older cluster. When it does, it must restrict
- itself to speaking the older version protocol.
-- When the cluster version increases (because the lowest version member has left)
- the remaining members may move up to the new version.
-
-
-* Design debates
** Active/active vs. active passive
An active-active cluster can be used in an active-passive mode. In
@@ -324,7 +385,7 @@ An active/passive implementation allows some simplifications over active/active:
- can do immediate local enqueue and still guarantee order.
Active/passive introduces a few extra requirements:
-- Exactly one broker has to take over if primary fails.
+- Exactly one broker hast to take over if primary fails.
- Passive members must refuse client connections.
- On failover, clients must re-try all known addresses till they find the active member.
@@ -332,17 +393,43 @@ Active/active benefits:
- A broker failure only affects the subset of clients connected to that broker.
- Clients can switch to any other broker on failover
- Backup brokers are immediately available on failover.
-- As long as a client can connect to any broker in the cluster, it can be served.
+- Some load sharing: reading from client + multicast only done on direct node.
+
+Active/active drawbacks:
+- Co-ordinating message acquisition may impact performance (not tested)
+- Code may be more complex that active/passive.
Active/passive benefits:
-- Don't need to replicate message allocation, can feed consumers at top speed.
+- Don't need message allocation strategy, can feed consumers at top speed.
+- Code may be simpler than active/active.
Active/passive drawbacks:
- All clients on one node so a failure affects every client in the system.
- After a failure there is a "reconnect storm" as every client reconnects to the new active node.
- After a failure there is a period where no broker is active, until the other brokers realize the primary is gone and agree on the new primary.
- Clients must find the single active node, may involve multiple connect attempts.
-- No service if a partition separates a client from the active broker,
- even if the client can see other brokers.
+** Total ordering.
+
+Initial thinking: allow message ordering to differ between brokers.
+New thinking: use CPG total ordering, get identical ordering on all brokers.
+- Allowing variation in order introduces too much chance of unexpected behavior.
+- Usign total order allows other optimizations, see Message Identifiers below.
+
+** Message identifiers.
+
+Initial thinking: message ID = CPG node id + 64 bit sequence number.
+This involves a lot of mapping between cluster IDs and broker messsages.
+
+New thinking: message ID = queue name + queue position.
+- Removes most of the mapping and memory management for cluster code.
+- Requires total ordering of messages (see above)
+
+** Message rejection
+
+Initial thinking: add special reject/rejected points to cluster interface so
+rejected messages could be re-queued without multicast.
+New thinking: treat re-queueing after reject as entirely new message.
+- Simplifies cluster interface & implementation
+- Not on the critical path.
diff --git a/cpp/design_docs/new-cluster-plan.txt b/cpp/design_docs/new-cluster-plan.txt
index 32e3f710e7..781876e55a 100644
--- a/cpp/design_docs/new-cluster-plan.txt
+++ b/cpp/design_docs/new-cluster-plan.txt
@@ -17,150 +17,376 @@
# specific language governing permissions and limitations
# under the License.
-* Status of impementation
-Meaning of priorities:
-[#A] Essential for basic functioning.
-[#B] Required for first release.
-[#C] Can be addressed in a later release.
+Notes on new cluster implementation. See also: new-cluster-design.txt
-The existig prototype is bare bones to do performance benchmarks:
-- Implements publish and consumer locking protocol.
-- Defered delivery and asynchronous completion of message.
-- Optimize the case all consumers are on the same node.
-- No new member updates, no failover updates, no transactions, no persistence etc.
+* Implementation plan.
-Prototype code is on branch qpid-2920-active, in cpp/src/qpid/cluster/exp/
+Co-existence with old cluster code and tests:
+- Separate plugin cluster2, options --cluster2-*. Eventually renamed to replace cluster.
+- Double up tests with old version/new version as the new code develops.
-** Similarities to existing cluster.
+Minimal POC for message delivery & perf test.
+- no wiring replication, no updates, no failover, no persistence, no async completion.
+- just implement publish and acquire/dequeue locking protocol.
+- optimize the special case where all consumers are on the same node.
+- measure performance: compare active-passive and active-active modes of use.
-/Active-active/: the new cluster can be a drop-in replacement for the
-old, existing tests & customer deployment configurations are still
-valid.
+Full implementation of transient cluster
+- Update (based on existing update), async completion etc.
+- Passing all existing transient cluster tests.
-/Virtual synchrony/: Uses corosync to co-ordinate activity of members.
+Persistent cluster
+- Make sure async completion works correctly.
+- InitialStatus protoocl etc. to support persistent start-up (existing code)
+- cluster restart from store: stores not identical. Load one, update the rest.
+ - assign cluster ID's to messages recovered from store, don't replicate.
-/XML controls/: Uses XML to define the primitives multicast to the
-cluster.
+Improved update protocol
+- per-queue, less stalling, bounded catch-up.
-** Differences with existing cluster.
+* Task list
-/Report rather than predict consumption/: brokers explicitly tell each
-other which messages have been acquired or dequeued. This removes the
-major cause of bugs in the existing cluster.
+** TODO [#A] Minimal POC: publish/acquire/dequeue protocol.
-/Queue consumer locking/: to avoid duplicates only one broker can acquire or
-dequeue messages at a time - while has the consume-lock on the
-queue. If multiple brokers are consuming from the same queue the lock
-is passed around to time-share access to the queue.
+NOTE: as implementation questions arise, take the easiest option and make
+a note for later optimization/improvement.
-/Per-queue concurrency/: uses a fixed-size set of CPG groups (reflecting
-the concurrency of the host) to allow concurrent processing on
-different queues. Queues are hashed onto the groups.
+*** Tests
+- python test: 4 senders, numbered messages, 4 receivers, verify message set.
+- acquire then release messages: verify can be dequeued on any member
+- acquire then kill broker: verify can be dequeued other members.
+- acquire then reject: verify goes on alt-exchange once only.
-* Completed tasks
-** DONE [#A] Minimal POC: publish/acquire/dequeue protocol.
- CLOSED: [2011-10-05 Wed 16:03]
+*** DONE broker::Cluster interface and call points.
-Defines broker::Cluster interface and call points.
-Initial interface commite
+Initial interface commited.
-Main classes
-Core: central object holding cluster classes together (replaces cluster::Cluster)
-BrokerContext: implements broker::Cluster interface.
-QueueContext: Attached to a broker::Queue, holds cluster status.
-MessageHolder:holds local messages while they are being enqueued.
+*** Main classes
-Implements multiple CPG groups for better concurrency.
+BrokerHandler:
+- implements broker::Cluster intercept points.
+- sends mcast events to inform cluster of local actions.
+- thread safe, called in connection threads.
-** DONE [#A] Large message replication.
- CLOSED: [2011-10-05 Wed 17:22]
-Multicast using fixed-size (64k) buffers, allow fragmetation of messages across buffers (frame by frame)
+LocalMessageMap:
+- Holds local messages while they are being enqueued.
+- thread safe: called by both BrokerHandler and MessageHandler
+
+MessageHandler:
+- handles delivered mcast messages related to messages.
+- initiates local actions in response to mcast events.
+- thread unsafe, only called in deliver thread.
+- maintains view of cluster state regarding messages.
-* Open questions
+QueueOwnerHandler:
+- handles delivered mcast messages related to queue consumer ownership.
+- thread safe, called in deliver, connection and timer threads.
+- maintains view of cluster state regarding queue ownership.
+
+cluster::Core: class to hold new cluster together (replaces cluster::Cluster)
+- thread safe: manage state used by both MessageHandler and BrokerHandler
+
+The following code sketch illustrates only the "happy path" error handling
+is omitted.
+
+*** BrokerHandler
+Types:
+- struct QueuedMessage { Message msg; QueueName q; SequenceNumber position; }
+- struct
+
+NOTE:
+- Messages on queues are identified by a queue name + a position.
+- Messages being routed are identified by a sequence number.
+
+Members:
+- thread_local bool noReplicate // suppress replication.
+- thread_local bool isRouting // suppress operations while routing
+- Message localMessage[SequenceNumber] // local messages being routed.
+- thread_local SequenceNumber routingSequence
+
+NOTE: localMessage is also modified by MessageHandler.
+
+broker::Cluster intercept functions:
+
+routing(msg)
+ if noReplicate: return
+ # Supress everything except enqueues while we are routing.
+ # We don't want to replicate acquires & dequeues caused by an enqueu,
+ # e.g. removal of messages from ring/LV queues.
+ isRouting = true
+
+enqueue(qmsg):
+ if noReplicate: return
+ if routingSequence == 0 # thread local
+ routingSequence = nextRoutingSequence()
+ mcast create(encode(qmsg.msg),routingSeq)
+ mcast enqueue(qmsg.q,routingSeq)
+
+routed(msg):
+ if noReplicate: return
+ isRouting = false
+
+acquire(qmsg):
+ if noReplicate: return
+ if isRouting: return # Ignore while we are routing a message.
+ if msg.id: mcast acquire(qmsg)
+
+release(QueuedMessage)
+ if noReplicate: return
+ if isRouting: return # Ignore while we are routing a message.
+ mcast release(qmsg)
+
+accept(QueuedMessage):
+ if noReplicate: return
+ if isRouting: return # Ignore while we are routing a message.
+ mcast accept(qmsg)
+
+reject(QueuedMessage):
+ isRejecting = true
+ mcast reject(qmsg)
+
+# FIXME no longer needed?
+drop(QueuedMessage)
+ cleanup(qmsg)
+
+*** MessageHandler and mcast messages
+Types:
+- struct QueueEntry { QueuedMessage qmsg; NodeId acquired; }
+- struct QueueKey { MessageId id; QueueName q; }
+- typedef map<QueueKey, QueueEntry> Queue
+- struct Node { Message routing[SequenceNumber]; list<QueueKey> acquired; }
+
+Members:
+- QueueEntry enqueued[QueueKey]
+- Node node[NodeId]
+
+Mcast messages in Message class:
+
+create(msg,seq)
+ if sender != self: node[sender].routing[seq] = decode(msg)
+
+enqueue(q,seq):
+ id = (sender,seq)
+ if sender == self:
+ enqueued[id,q] = (localMessage[seq], acquired=None)
+ else:
+ msg = sender.routing[seq]
+ enqueued[id,q] = (qmsg, acquired=None)
+ with noReplicate=true: qmsg = broker.getQueue(q).push(msg)
+
+routed(seq):
+ if sender == self: localMessage.erase(msg.id.seq)
+ else: sender.routing.erase(seq)
+
+acquire(id,q):
+ enqueued[id,q].acquired = sender
+ node[sender].acquired.push_back((id,q))
+ if sender != self:
+ with noReplicate=true: broker.getQueue(q).acquire(enqueued[id,q])
+
+release(id,q)
+ enqueued[id,q].acquired = None
+ node[sender].acquired.erase((id,q))
+ if sender != self
+ with noReplicate=true: broker.getQueue(q).requeue(enqueued[id,q])
+
+reject(id,q):
+ sender.routing[id] = enqueued[id,q] # prepare for re-queueing
+
+rejected(id,q)
+ sender.routing.erase[id]
+
+dequeue(id,q)
+ entry = enqueued[id,q]
+ enqueued.erase[id,q]
+ node[entry.acquired].acquired.erase(id,q)
+ if sender != self:
+ with noReplicate=true: broker.getQueue(q).dequeue(entry.qmsg)
+
+member m leaves cluster:
+ for key in node[m].acquired:
+ release(key.id, key.q)
+ node.erase(m)
+
+*** Queue consumer locking
+
+When a queue is locked it does not deliver messages to its consumers.
+
+New broker::Queue functions:
+- stopConsumers(): set consumersStopped flag, wait for currently busy consumers to exit.
+- startConsumers(): reset consumersStopped flag
+
+Implementation sketch, locking omitted:
+
+void Queue::stopConsumers() {
+ consumersStopped = true;
+ while (consumersBusy) consumersBusyMonitor.wait();
+}
+
+void Queue::startConsumers() {
+ consumersStopped = false;
+ listeners.notify();
+}
+
+bool Queue::dispatch(consumer) {
+ if (consumersStopped) return false;
+ ++consumersBusy;
+ do_regular_dispatch_body()
+ if (--consumersBusy == 0) consumersBusyMonitor.notify();
+}
+
+*** QueueOwnerHandler
+
+Invariants:
+- Each queue is owned by at most one node at any time.
+- Each node is interested in a set of queues at any given time.
+- A queue is un-owned if no node is interested.
+
+The queue owner releases the queue when
+- it loses interest i.e. queue has no consumers with credit.
+- a configured time delay expires and there are other interested nodes.
+
+The owner mcasts release(q). On delivery the new queue owner is the
+next node in node-id order (treating nodes as a circular list)
+starting from the old owner that is interested in the queue.
+
+Queue consumers initially are stopped, only started when we get
+ownership from the cluster.
+
+Thread safety: called by deliver, connection and timer threads, needs locking.
+
+Thread safe object per queue holding queue ownership status.
+Called by deliver, connection and timer threads.
+
+class QueueOwnership {
+ bool owned;
+ Timer timer;
+ BrokerQueue q;
+
+ drop(): # locked
+ if owned:
+ owned = false
+ q.stopConsumers()
+ mcast release(q.name, false)
+ timer.stop()
+
+ take(): # locked
+ if not owned:
+ owned = true
+ q.startConsumers()
+ timer.start(timeout)
+
+ timer.fire(): drop()
+}
+
+Data Members, only modified/examined in deliver thread:
+- typedef set<NodeId> ConsumerSet
+- map<QueueName, ConsumerSet> consumers
+- map<QueueName, NodeId> owner
-** TODO [#A] Queue sequence numbers vs. independant message IDs.
- SCHEDULED: <2011-10-07 Fri>
+Thread safe data members, accessed in connection threads (via BrokerHandler):
+- map<QueueName, QueueOwnership> ownership
-Current prototype uses queue sequence numbers to identify
-message. This is tricky for updating new members as the sequence
-numbers are only known on delivery.
+Multicast messages in QueueOwner class:
-Independent message IDs that can be generated and sent with the message simplify
-this and potentially allow performance benefits by relaxing total ordering.
-However they imply additional map lookups that might hurt performance.
+consume(q):
+ if sender==self and consumers[q].empty(): ownership[q].take()
+ consumers[q].insert(sender)
-- [ ] Prototype independent message IDs, check performance.
+release(q):
+ asssert(owner[q] == sender and owner[q] in consumers[q])
+ owner[q] = circular search from sender in consumers[q]
+ if owner==self: ownership[q].take()
-* Outstanding Tasks
-** TODO [#A] Defer and async completion of wiring commands.
+cancel(q):
+ assert(queue[q].owner != sender) # sender must release() before cancel()
+ consumers[q].erase(sender)
-Testing requirement: Many tests assume wiring changes are visible
-across the cluster once the commad completes.
+member-leaves:
+ for q in queue: if owner[q] = left: left.release(q)
-Name clashes: need to avoid race if same name queue/exchange declared
-on 2 brokers simultaneously
+Need 2 more intercept points in broker::Cluster:
-** TODO [#A] Passing all existing cluster tests.
+consume(q,consumer,consumerCount) - Queue::consume()
+ if consumerCount == 1: mcast consume(q)
-The new cluster should be a drop-in replacement for the old, so it
-should be able to pass all the existing tests.
+cancel(q,consumer,consumerCount) - Queue::cancel()
+ if consumerCount == 0:
+ ownership[q].drop()
+ mcast cancel(q)
-** TODO [#A] Update to new members joining.
+#TODO: lifecycle, updating cluster data structures when queues are destroyed
+
+*** Increasing concurrency
+The major performance limitation of the old cluster is that it does
+everything in the single CPG deliver thread context.
+
+We can get additional concurrency by creating a thread context _per queue_
+for queue operations: enqueue, acquire, accept etc.
+
+We associate a PollableQueue of queue operations with each AMQP queue.
+The CPG deliver thread would
+- build messages and associate with cluster IDs.
+- push queue ops to the appropriate PollableQueue to be dispatched the queues thread.
+
+Serializing operations on the same queue avoids contention, but takes advantage
+of the independence of operations on separate queues.
-Need to resolve [[Queue sequence numbers vs. independant message IDs]] first.
-- implicit sequence numbers are more tricky to replicate to new member.
+*** Re-use of existing cluster code
+- re-use Event
+- re-use Multicaster
+- re-use same PollableQueueSetup (may experiment later)
+- new Core class to replace Cluster.
+- keep design modular, keep threading rules clear.
-Update individual objects (queues and exchanges) independently.
-- create queues first, then update all queues and exchanges in parallel.
-- multiple updater threads, per queue/exchange.
-- updater sends messages to special exchange(s) (not using extended AMQP controls)
+** TODO [#B] Large message replication.
+Multicast should encode messages in fixed size buffers (64k)?
+Can't assume we can send message in one chunk.
+For 0-10 can use channel numbers & send whole frames packed into larger buffer.
+** TODO [#B] Transaction support.
+Extend broker::Cluster interface to capture transaction context and completion.
+Sequence number to generate per-node tx IDs.
+Replicate transaction completion.
+** TODO [#B] Batch CPG multicast messages
+The new cluster design involves a lot of small multicast messages,
+they need to be batched into larger CPG messages for efficiency.
+** TODO [#B] Genuine async completion
+Replace current synchronous waiting implementation with genuine async completion.
-Queue updater:
-- marks the queue position at the sync point
-- sends messages starting from the sync point working towards the head of the queue.
-- send "done" message.
-Note: updater remains active throughout, consuming clients actually reduce the
-size of the update.
+Test: enhance test_store.cpp to defer enqueueComplete till special message received.
-Queue updatee:
-- enqueues received from CPG: add to back of queue as normal.
-- dequeues received from CPG: apply if found, else save to check at end of update.
-- messages from updater: add to the *front* of the queue.
-- update complete: apply any saved dequeues.
+Async callback uses *requestIOProcessing* to queue action on IO thread.
-Exchange updater:
-- updater: send snapshot of exchange as it was at the sync point.
+** TODO [#B] Async completion of accept when dequeue completes.
+Interface is already there on broker::Message, just need to ensure
+that store and cluster implementations call it appropriately.
-Exchange updatee:
-- queue exchange operations after the sync point.
-- when snapshot is received: apply saved operations.
+** TODO [#B] Replicate wiring.
+From messageStore create/destroy/bind, replicate encoded declare/destroy/bind command.
-Updater remains active throughout.
-Updatee stalls clients until the update completes.
+** TODO [#B] New members joining - first pass
-Updating queue/exchange/binding objects is via the same encode/decode
-that is used by the store. Updatee to use recovery interfaces to
-recover?
+Re-use update code from old cluster but don't replicate sessions &
+connections.
-** TODO [#A] Failover updates to client.
-Implement the amq.failover exchange to notify clients of membership.
+Need to extend it to send cluster IDs with messages.
-** TODO [#B] Initial status protocol.
-Handshake to give status of each broker member to new members joining.
-Status includes
-- persistent store state (clean, dirty)
-- cluster protocol version.
+Need to replicate the queue ownership data as part of the update.
-** TODO [#B] Persistent cluster support.
-Initial status protoocl to support persistent start-up (see existing code)
+** TODO [#B] Persistence support.
+InitialStatus protoocl etc. to support persistent start-up (existing code)
Only one broker recovers from store, update to others.
Assign cluster IDs to messages recovered from store, don't replicate. See Queue::recover.
-** TODO [#B] Management support
-Replicate management methods that modify queues - e.g. move, purge.
+** TODO [#B] Handle other ways that messages can leave a queue.
+
+Other ways (other than via a consumer) that messages are take off a queue.
+
+NOTE: Not controlled by queue lock, how to make them consistent?
+
Target broker may not have all messages on other brokers for purge/destroy.
- Queue::move() - need to wait for lock? Replicate?
- Queue::get() - ???
@@ -169,38 +395,66 @@ Target broker may not have all messages on other brokers for purge/destroy.
Need to add callpoints & mcast messages to replicate these?
-** TODO [#B] TX transaction support.
-Extend broker::Cluster interface to capture transaction context and completion.
-Running brokers exchange TX information.
-New broker update includes TX information.
-
- // FIXME aconway 2010-10-18: As things stand the cluster is not
- // compatible with transactions
- // - enqueues occur after routing is complete
- // - no call to Cluster::enqueue, should be in Queue::process?
- // - no transaction context associated with messages in the Cluster interface.
- // - no call to Cluster::accept in Queue::dequeueCommitted
-
-** TODO [#B] DTX transaction support.
-Extend broker::Cluster interface to capture transaction context and completion.
-Running brokers exchange DTX information.
-New broker update includes DTX information.
-
-** TODO [#B] Async completion of accept.
-When this is fixed in the standalone broker, it should be fixed for cluster.
-
-** TODO [#B] Network partitions and quorum.
-Re-use existing implementation.
+** TODO [#B] Flow control for internal queues.
+
+Need to bound the size of internal queues: delivery and multicast.
+- stop polling for read on client connections when we reach a bound.
+- restart polling when we get back under it.
+
+That will stop local multicasting, we still have to deal with remote
+multicasting (note existing cluster does not do this.) Something like:
+- when over bounds multicast a flow-control event.
+- on delivery of flow-control all members stop polling to read client connections
+- when back under bounds send flow-control-end, all members resume
+- if flow-controling member dies others resume
+
+** TODO [#B] Integration with transactions.
+Do we want to replicate during transaction & replicate commit/rollback
+or replicate only on commit?
+No integration with DTX transactions.
+** TODO [#B] Make new cluster work with replication exchange.
+Possibly re-use some common logic. Replication exchange is like clustering
+except over TCP.
+** TODO [#B] Better concurrency, scalabiility on multi-cores.
+Introduce PollableQueue of operations per broker queue. Queue up mcast
+operations (enqueue, acquire, accept etc.) to be handled concurrently
+on different queue. Performance testing to verify improved scalability.
+** TODO [#C] Async completion for declare, bind, destroy queues and exchanges.
+Cluster needs to complete these asynchronously to guarantee resources
+exist across the cluster when the command completes.
** TODO [#C] Allow non-replicated exchanges, queues.
-Set qpid.replicate=false in declare arguments, set flag on Exchange, Queue objects.
+Set qpid.replicated=false in declare arguments, set flag on Exchange, Queue objects.
- save replicated status to store.
- support in management tools.
+Replicated exchange: replicate binds to replicated queues.
Replicated queue: replicate all messages.
-Replicated exchange: replicate bindings to replicated queues only.
-Configurable default? Defaults to true.
+** TODO [#C] New members joining - improved.
+
+Replicate wiring like old cluster, stall for wiring but not for
+messages. Update messages on a per-queue basis from back to front.
+
+Updater:
+- stall & push wiring: declare exchanges, queues, bindings.
+- start update iterator thread on each queue.
+- unstall and process normally while iterator threads run.
+
+Update iterator thread:
+- starts at back of updater queue, message m.
+- send update_front(q,m) to updatee and advance towards front
+- at front: send update_done(q)
+
+Updatee:
+- stall, receive wiring, lock all queues, mark queues "updating", unstall
+- update_front(q,m): push m to *front* of q
+- update_done(q): mark queue "ready"
+
+Updatee cannot take the queue consume lock for a queue that is updating.
+Updatee *can* push messages onto a queue that is updating.
+
+TODO: Is there any way to eliminate the stall for wiring?
** TODO [#C] Refactoring of common concerns.
@@ -215,40 +469,9 @@ Look for ways to capitalize on the similarity & simplify the code.
In particular QueuedEvents (async replication) strongly resembles
cluster replication, but over TCP rather than multicast.
-
+** TODO [#C] Concurrency for enqueue events.
+All enqueue events are being processed in the CPG deliver thread context which
+serializes all the work. We only need ordering on a per queue basis, can we
+enqueue in parallel on different queues and will that improve performance?
** TODO [#C] Handling immediate messages in a cluster
Include remote consumers in descision to deliver an immediate message?
-** TODO [#C] Remove old cluster hacks and workarounds
-The old cluster has workarounds in the broker code that can be removed.
-- [ ] drop code to replicate management model.
-- [ ] drop timer workarounds for TTL, management, heartbeats.
-- [ ] drop "cluster-safe assertions" in broker code.
-- [ ] drop connections, sessions, management from cluster update.
-- [ ] drop security workarounds: cluster code now operates after message decoding.
-- [ ] drop connection tracking in cluster code.
-- [ ] simper inconsistent-error handling code, no need to stall.
-** TODO [#C] Support for live upgrades.
-
-Allow brokers in a running cluster to be replaced one-by-one with a new version.
-
-The old cluster protocol was unstable because any changes in broker
-state caused changes to the cluster protocol.The new design should be
-much more stable.
-
-Points to implement:
-- Brokers should ignore unknown controls (with a warning) rather than an error.
-- Limit logging frequency for unknown control warnings.
-- Add a version number at front of every CPG message. Determines how the
- rest of the message is decoded. (allows for entirely new encodings e.g. AMQP 1.0)
-- Protocol version XML element in cluster.xml, on each control.
-- Initial status protocol to include protocol version number.
-
-** TODO [#C] Support for AMQP 1.0.
-
-* Testing
-** TODO [#A] Pass all existing cluster tests.
-Requires [[Defer and async completion of wiring commands.]]
-** TODO [#A] New cluster tests.
-Stress tests & performance benchmarks focused on changes in new cluster:
-- concurrency by queues rather than connections.
-- different handling shared queues when consuemrs are on different brokers.
diff --git a/cpp/docs/api/developer.doxygen.in b/cpp/docs/api/developer.doxygen.in
index 1e1fddab80..fd3a9ac621 100644
--- a/cpp/docs/api/developer.doxygen.in
+++ b/cpp/docs/api/developer.doxygen.in
@@ -1029,7 +1029,7 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED = QPID_CLIENT_EXTERN= QPID_COMMON_EXTERN= QPID_CONSOLE_EXTERN= QPID_BROKER_EXTERN= QPID_MESSAGING_EXTERN= QMF_EXTERN= QMFE_EXTERN=
+PREDEFINED = QPID_CLIENT_EXTERN= QPID_COMMON_EXTERN= QPID_CONSOLE_EXTERN= QPID_BROKER_EXTERN= QPID_MESSAGING_EXTERN= QMF_EXTERN=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
diff --git a/cpp/docs/api/doxygen_mainpage.h b/cpp/docs/api/doxygen_mainpage.h
index 9acae52da4..cb36d7edb0 100644
--- a/cpp/docs/api/doxygen_mainpage.h
+++ b/cpp/docs/api/doxygen_mainpage.h
@@ -266,46 +266,7 @@
* else
* session.rollback();
* </pre>
- *
- * <h3>Exceptions</h3>
- *
- * All exceptions for the messaging API have MessagingException as
- * their base class.
-
- * A common class of exception are those related to processing
- * addresses used to create senders and/or receivers. These all have
- * AddressError as their base class.
- *
- * Where there is a syntax error in the address itself, a
- * MalformedAddress will be thrown. Where the address is valid, but
- * there is an error in interpreting (i.e. resolving) it, a
- * ResolutionError - or a sub-class of it - will be thrown. If the
- * address has assertions enabled for a given context and the asserted
- * node properties are not in fact correct then AssertionFailed will
- * be thrown. If the node is not found, NotFound will be thrown.
- *
- * The loss of the underlying connection (e.g. the TCP connection)
- * results in TransportFailure being thrown. If automatic reconnect is
- * enabled, this will be caught be the library which will then try to
- * reconnect. If reconnection - as configured by the connection
- * options - fails, then TransportFailure will be thrown. This can
- * occur on any call to the messaging API.
- *
- * Sending a message may also result in an exception
- * (e.g. TargetCapacityExceeded if a queue to which the message is
- * delivered cannot enqueue it due to lack of capacity). For
- * asynchronous send the exception may not be thrown on the send
- * invocation that actually triggers it, but on a subsequent method
- * call on the API.
- *
- * Certain exceptions may render the session invalid; once these
- * occur, subsequent calls on the session will throw the same class of
- * exception. This is not an intrinsic property of the class of
- * exception, but is a result of the current mapping of the API to the
- * underlying AMQP 0-10 protocol. You can test whether the session is
- * valid at any time using the hasError() and/or checkError() methods
- * on Session.
- *
+ *
* <h3>Logging</h3>
*
* The Qpidd broker and C++ clients can both use environment variables to
diff --git a/cpp/docs/api/footer.html b/cpp/docs/api/footer.html
index 5a31e81821..883410ce25 100644
--- a/cpp/docs/api/footer.html
+++ b/cpp/docs/api/footer.html
@@ -25,7 +25,7 @@ Qpid C++ API Reference</small></address>
<address style="text-align: right;">
<small>
-Generated on $date for $projectname by&nbsp;<a href="http://www.doxygen.org/index.html"><img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> $doxygenversion</small>
+Generated on $datetime for $projectname by&nbsp;<a href="http://www.doxygen.org/index.html"><img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> $doxygenversion</small>
</address>
</body>
</html>
diff --git a/cpp/docs/api/user.doxygen.in b/cpp/docs/api/user.doxygen.in
index ec0fd1361c..2728df47e4 100644
--- a/cpp/docs/api/user.doxygen.in
+++ b/cpp/docs/api/user.doxygen.in
@@ -1021,7 +1021,7 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED = QPID_CLIENT_EXTERN= QPID_COMMON_EXTERN= QPID_CONSOLE_EXTERN= QPID_BROKER_EXTERN= QPID_MESSAGING_EXTERN= QMF_EXTERN= QMFE_EXTERN=
+PREDEFINED = QPID_CLIENT_EXTERN= QPID_COMMON_EXTERN= QPID_CONSOLE_EXTERN= QPID_BROKER_EXTERN= QPID_MESSAGING_EXTERN= QMF_EXTERN=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
diff --git a/cpp/docs/man/Makefile.am b/cpp/docs/man/Makefile.am
index b821568f81..14295f73bf 100644
--- a/cpp/docs/man/Makefile.am
+++ b/cpp/docs/man/Makefile.am
@@ -16,29 +16,10 @@
# specific language governing permissions and limitations
# under the License.
#
-
-# Generate makefile from qpidd --help
-#
-# Note: qiddd.1 is normally a _checked in_ pre-generated file, so that
-# make dist does not have to build the entire source just for the man page.
-#
-# To update the checked-in file (e.g. for a new release) do the following:
-#
-# - start with a completely clean checkout.
-# - make sure there are no modules installed in your configured prefix,
-# we don't want to pick up configuration from optional modules
-# - do bootstrap; configure
-# - in build-dir: cd src; make # build the broker
-# - in source-dir: cd docs/man; rm qpidd.1 # remove checked-in man page.
-# - in build-dir: cd docs/man; make # make new man page
-# - edit qpidd.1 to remove all default values referring to file/directory locations.
-# these values will differ between builds depending on configuration.
-# - if source-dir != build-dir: copy qpidd.1 from build-dir/docs/man to source-dir/docs/man
-
dist_man_MANS = qpidd.1
-man_aux = $(dist_man_MANS:.1=.x)
-EXTRA_DIST = $(man_aux) generate_manpage groffify_options.sed groffify_template.sed
+man_aux = $(dist_man_MANS:.1=.x)
+EXTRA_DIST = $(man_aux) generate_manpage groffify_options.sed groffify_template.sed
DISTCLEANFILES = $(dist_man_MANS)
CLEANFILES=qpidd.1
diff --git a/cpp/docs/man/qpidd.1 b/cpp/docs/man/qpidd.1
deleted file mode 100644
index d2cff454cf..0000000000
--- a/cpp/docs/man/qpidd.1
+++ /dev/null
@@ -1,247 +0,0 @@
-.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.38.2.
-.TH QPIDD "1" "March 2011" "qpidd (qpidc) version 0.11" "User Commands"
-.SH NAME
-
-qpidd \- the Qpid AMQP Message Broker Daemon
-.SH SYNOPSIS
-
-qpidd [-p port] [--config config_file] [--data-dir directory]
-.SH DESCRIPTION
-
-An AMQP message broker daemon that stores, routes and forwards
-messages using the Advanced Message Queueing Protocol (AMQP).
-.SH OPTIONS
-
-The options below are built-in to qpidd. Installing add-on modules provides additional options. To see the full set of options available type "qpidd --help"
-
-Options may be specified via command line, environment variable or configuration file. See FILES and ENVIRONMENT below for details.
-.PP
-
-.TP
-\fB\-h\fR [ \fB\-\-help\fR ]
-Displays the help message
-.TP
-\fB\-v\fR [ \fB\-\-version\fR ]
-Displays version information
-.TP
-\fB\-\-config\fR FILE
-Reads configuration from FILE
-.SS "Module options:"
-.TP
-\fB\-\-module\-dir\fR DIR
-Load all shareable modules in this
-directory
-.TP
-\fB\-\-load\-module\fR FILE
-Specifies additional module(s) to be
-loaded
-.TP
-\fB\-\-no\-module\-dir\fR
-Don't load modules from module
-directory
-.SS "Broker Options:"
-.TP
-\fB\-\-data\-dir\fR DIR
-Directory to contain persistent data
-generated by the broker
-.TP
-\fB\-\-no\-data\-dir\fR
-Don't use a data directory. No
-persistent configuration will be loaded
-or stored
-.TP
-\fB\-p\fR [ \fB\-\-port\fR ] PORT (5672)
-Tells the broker to listen on PORT
-.TP
-\fB\-\-worker\-threads\fR N (3)
-Sets the broker thread pool size
-.TP
-\fB\-\-max\-connections\fR N (500)
-Sets the maximum allowed connections
-.TP
-\fB\-\-connection\-backlog\fR N (10)
-Sets the connection backlog limit for
-the server socket
-.TP
-\fB\-m\fR [ \fB\-\-mgmt\-enable\fR ] yes|no (1)
-Enable Management
-.TP
-\fB\-\-mgmt\-qmf2\fR yes|no (1)
-Enable broadcast of management
-information over QMF v2
-.TP
-\fB\-\-mgmt\-qmf1\fR yes|no (1)
-Enable broadcast of management
-information over QMF v1
-.TP
-\fB\-\-mgmt\-pub\-interval\fR SECONDS (10)
-Management Publish Interval
-.TP
-\fB\-\-queue\-purge\-interval\fR SECONDS (600)
-Interval between attempts to purge any
-expired messages from queues
-.TP
-\fB\-\-auth\fR yes|no (1)
-Enable authentication, if disabled all
-incoming connections will be trusted
-.TP
-\fB\-\-realm\fR REALM (QPID)
-Use the given realm when performing
-authentication
-.TP
-\fB\-\-default\-queue\-limit\fR BYTES (104857600)
-Default maximum size for queues (in
-bytes)
-.TP
-\fB\-\-tcp\-nodelay\fR
-Set TCP_NODELAY on TCP connections
-.TP
-\fB\-\-require\-encryption\fR
-Only accept connections that are
-encrypted
-.TP
-\fB\-\-known\-hosts\-url\fR URL or 'none'
-URL to send as 'known\-hosts' to clients
-('none' implies empty list)
-.TP
-\fB\-\-sasl\-config\fR DIR
-gets sasl config info from nonstandard
-location
-.TP
-\fB\-\-max\-session\-rate\fR MESSAGES/S (0)
-Sets the maximum message rate per
-session (0=unlimited)
-.TP
-\fB\-\-async\-queue\-events\fR yes|no (0)
-Set Queue Events async, used for
-services like replication
-.TP
-\fB\-\-default\-flow\-stop\-threshold\fR PERCENT (80)
-Percent of queue's maximum capacity at
-which flow control is activated.
-.TP
-\fB\-\-default\-flow\-resume\-threshold\fR PERCENT (70)
-Percent of queue's maximum capacity at
-which flow control is de\-activated.
-.TP
-\fB\-\-default\-event\-threshold\-ratio\fR %age of limit (80)
-The ratio of any specified queue limit
-at which an event will be raised
-.SS "Logging options:"
-.TP
-\fB\-t\fR [ \fB\-\-trace\fR ]
-Enables all logging
-.TP
-\fB\-\-log\-enable\fR RULE (notice+)
-Enables logging for selected levels and
-components. RULE is in the form
-\&'LEVEL[+][:PATTERN]' Levels are one of:
-.IP
-trace debug info notice warning error
-.IP
-critical
-For example:
-\&'\-\-log\-enable warning+' logs all
-warning, error and critical messages.
-\&'\-\-log\-enable debug:framing' logs debug
-messages from the framing namespace.
-This option can be used multiple times
-.TP
-\fB\-\-log\-time\fR yes|no (1)
-Include time in log messages
-.TP
-\fB\-\-log\-level\fR yes|no (1)
-Include severity level in log messages
-.TP
-\fB\-\-log\-source\fR yes|no (0)
-Include source file:line in log
-messages
-.TP
-\fB\-\-log\-thread\fR yes|no (0)
-Include thread ID in log messages
-.TP
-\fB\-\-log\-function\fR yes|no (0)
-Include function signature in log
-messages
-.TP
-\fB\-\-log\-prefix\fR STRING
-Prefix to append to all log messages
-.SS "Logging sink options:"
-.TP
-\fB\-\-log\-to\-stderr\fR yes|no (1)
-Send logging output to stderr
-.TP
-\fB\-\-log\-to\-stdout\fR yes|no (0)
-Send logging output to stdout
-.TP
-\fB\-\-log\-to\-file\fR FILE
-Send log output to FILE.
-.TP
-\fB\-\-log\-to\-syslog\fR yes|no (0)
-Send logging output to syslog;
-customize using \fB\-\-syslog\-name\fR and
-\fB\-\-syslog\-facility\fR
-.TP
-\fB\-\-syslog\-name\fR NAME (lt\-qpidd)
-Name to use in syslog messages
-.TP
-\fB\-\-syslog\-facility\fR LOG_XXX (LOG_DAEMON)
-Facility to use in syslog messages
-.SS "Daemon options:"
-.TP
-\fB\-d\fR [ \fB\-\-daemon\fR ]
-Run as a daemon. Logs to syslog by
-default in this mode.
-.TP
-\fB\-\-transport\fR TRANSPORT (tcp)
-The transport for which to return the
-port
-.TP
-\fB\-\-pid\-dir\fR DIR
-Directory where port\-specific PID file
-is stored
-.TP
-\fB\-w\fR [ \fB\-\-wait\fR ] SECONDS (600)
-Sets the maximum wait time to
-initialize the daemon. If the daemon
-fails to initialize, prints an error
-and returns 1
-.TP
-\fB\-c\fR [ \fB\-\-check\fR ]
-Prints the daemon's process ID to
-stdout and returns 0 if the daemon is
-running, otherwise returns 1
-.TP
-\fB\-q\fR [ \fB\-\-quit\fR ]
-Tells the daemon to shut down
-.SH ENVIRONMENT
-.I QPID_<option>
-.RS
-There is an environment variable for each option.
-.RE
-
-The environment variable is the option name in uppercase, prefixed with QPID_ and '.' or '-' are replaced with '_'. Environment settings are over-ridden by command line settings. For example:
-
- export QPID_PORT=6000
- export QPID_MAX_CONNECTIONS=10
- export QPID_LOG_TO_FILE=/tmp/qpidd.log
-.SH FILES
-.I /etc/qpidd.conf
-.RS
-Default configuration file.
-.RE
-
-Configuration file settings are over-ridden by command line or environment variable settings. '--config <file>' or 'export QPID_CONFIG=<file>' specifies an alternate file.
-
-Each line is a name=value pair. Blank lines and lines beginning with # are ignored. For example:
-
- # My qpidd configuration file.
- port=6000
- max-connections=10
- log-to-file=/tmp/qpidd.log
-.SH AUTHOR
-
-The Apache Qpid Project, dev@qpid.apache.org
-.SH "REPORTING BUGS"
-
-Please report bugs to users@qpid.apache.org
diff --git a/cpp/docs/man/qpidd.x b/cpp/docs/man/qpidd.x
index 0ccf3b562a..af5d9628ee 100644
--- a/cpp/docs/man/qpidd.x
+++ b/cpp/docs/man/qpidd.x
@@ -13,8 +13,6 @@ messages using the Advanced Message Queueing Protocol (AMQP).
[OPTIONS]
-The options below are built-in to qpidd. Installing add-on modules provides additional options. To see the full set of options available type "qpidd --help"
-
Options may be specified via command line, environment variable or configuration file. See FILES and ENVIRONMENT below for details.
[FILES]
diff --git a/cpp/etc/Makefile.am b/cpp/etc/Makefile.am
index 1e4db561a7..c91dbcbbad 100644
--- a/cpp/etc/Makefile.am
+++ b/cpp/etc/Makefile.am
@@ -30,7 +30,30 @@ nobase_sysconf_DATA = \
qpidd.conf
if HAVE_SASL
+SASL_DB = qpidd.sasldb
+
nobase_sysconf_DATA += \
$(SASL_CONF)
+sasldbdir = $(localstatedir)/lib/qpidd
+sasldb_DATA = $(SASL_DB)
+
+# Setup the default sasldb file with a single user, guest, with an
+# obvious password. This user and password are the default for many
+# clients.
+#
+# The realm specified by -u is very important, and QPID is the default
+# for the broker so we use it here. The realm is important because it
+# defaults to the local hostname of the machine running the
+# broker. This may not seem to bad at first glance, but it means that
+# the sasldb has to be tailored to each machine that would be running
+# a broker, and if the machine ever changed its name the
+# authentication would stop working until the sasldb was updated. For
+# these reasons we always want the broker to specify a realm where its
+# users live, and we want the users to exist in that realm as well.
+$(SASL_DB):
+ echo guest | $(SASL_PASSWD) -c -p -f $(SASL_DB) -u QPID guest
+
+CLEANFILES=$(SASL_DB)
+
endif
diff --git a/cpp/etc/qpidd.conf b/cpp/etc/qpidd.conf
index bfe4e38bbd..8082660f6f 100644
--- a/cpp/etc/qpidd.conf
+++ b/cpp/etc/qpidd.conf
@@ -21,4 +21,4 @@
#
# (Note: no spaces on either side of '='). Using default settings:
# "qpidd --help" or "man qpidd" for more details.
-cluster-mechanism=DIGEST-MD5 ANONYMOUS
+cluster-mechanism=ANONYMOUS
diff --git a/cpp/etc/sasl2/qpidd.conf b/cpp/etc/sasl2/qpidd.conf
index d766cb8ef8..3197d7792a 100644
--- a/cpp/etc/sasl2/qpidd.conf
+++ b/cpp/etc/sasl2/qpidd.conf
@@ -17,8 +17,8 @@
# under the License.
#
#
-# This configuation allows for either SASL ANONYMOUS or DIGEST-MD5
-# authentication. The DIGEST-MD5 authentication is done on a
+# This configuation allows for either SASL PLAIN or ANONYMOUS
+# authentication. The PLAIN authentication is done on a
# username+password, which is stored in the sasldb_path
# file. Usernames and passwords can be added to the file using the
# command:
@@ -39,7 +39,6 @@
pwcheck_method: auxprop
auxprop_plugin: sasldb
sasldb_path: /var/lib/qpidd/qpidd.sasldb
-mech_list: DIGEST-MD5 ANONYMOUS
#following line stops spurious 'sql_select option missing' errors when
#cyrus-sql-sasl plugin is installed
diff --git a/cpp/examples/CMakeLists.txt b/cpp/examples/CMakeLists.txt
index 1b28cfd031..da8e39e944 100644
--- a/cpp/examples/CMakeLists.txt
+++ b/cpp/examples/CMakeLists.txt
@@ -77,14 +77,25 @@ macro(add_example subdir example)
endmacro(add_example)
install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/README.txt
+ ${CMAKE_CURRENT_SOURCE_DIR}/README.verify
+ ${CMAKE_CURRENT_SOURCE_DIR}/verify
+ ${CMAKE_CURRENT_SOURCE_DIR}/verify_all
DESTINATION ${QPID_INSTALL_EXAMPLESDIR}
COMPONENT ${QPID_COMPONENT_EXAMPLES})
if (MSVC)
install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/examples.sln
+ ${CMAKE_CURRENT_SOURCE_DIR}/old-examples.sln
DESTINATION ${QPID_INSTALL_EXAMPLESDIR}
COMPONENT ${QPID_COMPONENT_EXAMPLES})
endif (MSVC)
+add_subdirectory(direct)
+add_subdirectory(failover)
+add_subdirectory(fanout)
+add_subdirectory(pub-sub)
+#add_subdirectory(qmf-agent)
add_subdirectory(qmf-console)
+add_subdirectory(request-response)
+add_subdirectory(tradedemo)
+add_subdirectory(xml-exchange)
add_subdirectory(messaging)
-add_subdirectory(old_api)
diff --git a/cpp/examples/Makefile.am b/cpp/examples/Makefile.am
index 6b2bb73587..c6cc308d98 100644
--- a/cpp/examples/Makefile.am
+++ b/cpp/examples/Makefile.am
@@ -16,7 +16,15 @@
# specific language governing permissions and limitations
# under the License.
#
-SUBDIRS = qmf-console messaging old_api
+SUBDIRS = direct fanout pub-sub request-response failover qmf-console tradedemo messaging
+if HAVE_XML
+ SUBDIRS += xml-exchange
+ broker_args = "--no-module-dir --data-dir \"\" --auth no --load-module $(top_builddir)/src/.libs/xml.so"
+endif
+if !HAVE_XML
+ exclude_examples_regexp="xml" # Exclude XML examples.
+ broker_args = "--no-module-dir --data-dir \"\" --auth no"
+endif
MAKEDIST=.libs/Makefile
@@ -29,9 +37,13 @@ $(MAKEDIST): Makefile
examplesdir=$(pkgdatadir)/examples
dist_examples_DATA = README.txt $(MAKEDIST)
-EXTRA_DIST = examples.sln CMakeLists.txt
+EXTRA_DIST = README.verify verify verify_all examples.sln CMakeLists.txt
# For older versions of automake
abs_top_srcdir = @abs_top_srcdir@
abs_top_builddir = @abs_top_builddir@
+# Verify the examples in the buid tree.
+check-local:
+ $(srcdir)/verify_all $(abs_top_srcdir)/.. $(abs_top_builddir) $(broker_args) $(exclude_examples_regexp)
+
diff --git a/cpp/examples/old_api/README.verify b/cpp/examples/README.verify
index e1370764c9..e1370764c9 100644
--- a/cpp/examples/old_api/README.verify
+++ b/cpp/examples/README.verify
diff --git a/cpp/examples/old_api/direct/CMakeLists.txt b/cpp/examples/direct/CMakeLists.txt
index 2ec1b2b813..2ec1b2b813 100644
--- a/cpp/examples/old_api/direct/CMakeLists.txt
+++ b/cpp/examples/direct/CMakeLists.txt
diff --git a/cpp/examples/old_api/direct/Makefile.am b/cpp/examples/direct/Makefile.am
index 24f783fcc7..b07db2cfd6 100644
--- a/cpp/examples/old_api/direct/Makefile.am
+++ b/cpp/examples/direct/Makefile.am
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-examplesdir=$(pkgdatadir)/examples/old_api/direct
+examplesdir=$(pkgdatadir)/examples/direct
MAKELDFLAGS=$(CLIENTFLAGS)
include $(top_srcdir)/examples/makedist.mk
diff --git a/cpp/examples/old_api/direct/declare_queues.cpp b/cpp/examples/direct/declare_queues.cpp
index 9a51d1982b..9a51d1982b 100644
--- a/cpp/examples/old_api/direct/declare_queues.cpp
+++ b/cpp/examples/direct/declare_queues.cpp
diff --git a/cpp/examples/old_api/direct/direct_declare_queues.vcproj b/cpp/examples/direct/direct_declare_queues.vcproj
index 083474b9ef..083474b9ef 100644
--- a/cpp/examples/old_api/direct/direct_declare_queues.vcproj
+++ b/cpp/examples/direct/direct_declare_queues.vcproj
diff --git a/cpp/examples/old_api/direct/direct_direct_producer.vcproj b/cpp/examples/direct/direct_direct_producer.vcproj
index f091fbf291..f091fbf291 100644
--- a/cpp/examples/old_api/direct/direct_direct_producer.vcproj
+++ b/cpp/examples/direct/direct_direct_producer.vcproj
diff --git a/cpp/examples/old_api/direct/direct_listener.vcproj b/cpp/examples/direct/direct_listener.vcproj
index dce1d3ec28..dce1d3ec28 100644
--- a/cpp/examples/old_api/direct/direct_listener.vcproj
+++ b/cpp/examples/direct/direct_listener.vcproj
diff --git a/cpp/examples/old_api/direct/direct_producer.cpp b/cpp/examples/direct/direct_producer.cpp
index ecc9675189..ecc9675189 100644
--- a/cpp/examples/old_api/direct/direct_producer.cpp
+++ b/cpp/examples/direct/direct_producer.cpp
diff --git a/cpp/examples/old_api/direct/listener.cpp b/cpp/examples/direct/listener.cpp
index 38bf24ec41..38bf24ec41 100644
--- a/cpp/examples/old_api/direct/listener.cpp
+++ b/cpp/examples/direct/listener.cpp
diff --git a/cpp/examples/old_api/direct/verify b/cpp/examples/direct/verify
index f598bacc1f..f598bacc1f 100644
--- a/cpp/examples/old_api/direct/verify
+++ b/cpp/examples/direct/verify
diff --git a/cpp/examples/old_api/direct/verify.in b/cpp/examples/direct/verify.in
index d1e95f1151..d1e95f1151 100644
--- a/cpp/examples/old_api/direct/verify.in
+++ b/cpp/examples/direct/verify.in
diff --git a/cpp/examples/examples.sln b/cpp/examples/examples.sln
index 6f96105d97..8511fe3cce 100644
--- a/cpp/examples/examples.sln
+++ b/cpp/examples/examples.sln
@@ -32,14 +32,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "messaging_drain", "messagin
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "messaging_spout", "messaging\messaging_spout.vcproj", "{D3115AC9-91C4-4D79-BCAC-DE837C70F1EA}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_console", "qmf-console\qmf-console_console.vcproj", "{490473E1-FECA-1BAD-2E13-3FFA2B8669C3}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_ping", "qmf-console\qmf-console_ping.vcproj", "{C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_printevents", "qmf-console\qmf-console_printevents.vcproj", "{72C74624-FECA-1BAD-2E13-3FFA2B8669C3}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_queuestats", "qmf-console\qmf-console_queuestats.vcproj", "{B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -96,22 +88,6 @@ Global
{D3115AC9-91C4-4D79-BCAC-DE837C70F1EA}.Release|Win32.Build.0 = Release|Win32
{D3115AC9-91C4-4D79-BCAC-DE837C70F1EA}.Release|x64.ActiveCfg = Release|x64
{D3115AC9-91C4-4D79-BCAC-DE837C70F1EA}.Release|x64.Build.0 = Release|x64
- {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
- {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
- {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
- {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
- {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Debug|Win32.ActiveCfg = Debug|Win32
- {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Debug|Win32.Build.0 = Debug|Win32
- {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Release|Win32.ActiveCfg = Release|Win32
- {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Release|Win32.Build.0 = Release|Win32
- {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
- {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
- {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
- {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
- {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
- {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
- {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
- {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/cpp/examples/old_api/failover/CMakeLists.txt b/cpp/examples/failover/CMakeLists.txt
index 05db8fad51..05db8fad51 100644
--- a/cpp/examples/old_api/failover/CMakeLists.txt
+++ b/cpp/examples/failover/CMakeLists.txt
diff --git a/cpp/examples/old_api/failover/Makefile.am b/cpp/examples/failover/Makefile.am
index 8b1da80f2c..48846fdf79 100644
--- a/cpp/examples/old_api/failover/Makefile.am
+++ b/cpp/examples/failover/Makefile.am
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-examplesdir=$(pkgdatadir)/examples/old_api/failover
+examplesdir=$(pkgdatadir)/examples/failover
MAKELDFLAGS=$(CLIENTFLAGS)
include $(top_srcdir)/examples/makedist.mk
diff --git a/cpp/examples/old_api/failover/declare_queues.cpp b/cpp/examples/failover/declare_queues.cpp
index a677870c53..a677870c53 100644
--- a/cpp/examples/old_api/failover/declare_queues.cpp
+++ b/cpp/examples/failover/declare_queues.cpp
diff --git a/cpp/examples/old_api/failover/failover_declare_queues.vcproj b/cpp/examples/failover/failover_declare_queues.vcproj
index c87c72affd..c87c72affd 100644
--- a/cpp/examples/old_api/failover/failover_declare_queues.vcproj
+++ b/cpp/examples/failover/failover_declare_queues.vcproj
diff --git a/cpp/examples/old_api/failover/failover_replaying_sender.vcproj b/cpp/examples/failover/failover_replaying_sender.vcproj
index 6d22fa6770..6d22fa6770 100644
--- a/cpp/examples/old_api/failover/failover_replaying_sender.vcproj
+++ b/cpp/examples/failover/failover_replaying_sender.vcproj
diff --git a/cpp/examples/old_api/failover/failover_resuming_receiver.vcproj b/cpp/examples/failover/failover_resuming_receiver.vcproj
index ba5061e248..ba5061e248 100644
--- a/cpp/examples/old_api/failover/failover_resuming_receiver.vcproj
+++ b/cpp/examples/failover/failover_resuming_receiver.vcproj
diff --git a/cpp/examples/old_api/failover/replaying_sender.cpp b/cpp/examples/failover/replaying_sender.cpp
index 22a7e1ebd3..22a7e1ebd3 100644
--- a/cpp/examples/old_api/failover/replaying_sender.cpp
+++ b/cpp/examples/failover/replaying_sender.cpp
diff --git a/cpp/examples/old_api/failover/resuming_receiver.cpp b/cpp/examples/failover/resuming_receiver.cpp
index d1886ce861..d1886ce861 100644
--- a/cpp/examples/old_api/failover/resuming_receiver.cpp
+++ b/cpp/examples/failover/resuming_receiver.cpp
diff --git a/cpp/examples/old_api/fanout/CMakeLists.txt b/cpp/examples/fanout/CMakeLists.txt
index 3f89d67650..3f89d67650 100644
--- a/cpp/examples/old_api/fanout/CMakeLists.txt
+++ b/cpp/examples/fanout/CMakeLists.txt
diff --git a/cpp/examples/old_api/fanout/Makefile.am b/cpp/examples/fanout/Makefile.am
index 3ab43b0279..6e2e821eae 100644
--- a/cpp/examples/old_api/fanout/Makefile.am
+++ b/cpp/examples/fanout/Makefile.am
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-examplesdir=$(pkgdatadir)/examples/old_api/fanout
+examplesdir=$(pkgdatadir)/examples/fanout
MAKELDFLAGS=$(CLIENTFLAGS)
include $(top_srcdir)/examples/makedist.mk
diff --git a/cpp/examples/old_api/fanout/fanout_fanout_producer.vcproj b/cpp/examples/fanout/fanout_fanout_producer.vcproj
index daff5f3cf0..daff5f3cf0 100644
--- a/cpp/examples/old_api/fanout/fanout_fanout_producer.vcproj
+++ b/cpp/examples/fanout/fanout_fanout_producer.vcproj
diff --git a/cpp/examples/old_api/fanout/fanout_listener.vcproj b/cpp/examples/fanout/fanout_listener.vcproj
index f0e91b7dc6..f0e91b7dc6 100644
--- a/cpp/examples/old_api/fanout/fanout_listener.vcproj
+++ b/cpp/examples/fanout/fanout_listener.vcproj
diff --git a/cpp/examples/old_api/fanout/fanout_producer.cpp b/cpp/examples/fanout/fanout_producer.cpp
index decd4d314d..decd4d314d 100644
--- a/cpp/examples/old_api/fanout/fanout_producer.cpp
+++ b/cpp/examples/fanout/fanout_producer.cpp
diff --git a/cpp/examples/old_api/fanout/listener.cpp b/cpp/examples/fanout/listener.cpp
index cd3071c29a..cd3071c29a 100644
--- a/cpp/examples/old_api/fanout/listener.cpp
+++ b/cpp/examples/fanout/listener.cpp
diff --git a/cpp/examples/old_api/fanout/verify b/cpp/examples/fanout/verify
index 2eaadff56b..2eaadff56b 100644
--- a/cpp/examples/old_api/fanout/verify
+++ b/cpp/examples/fanout/verify
diff --git a/cpp/examples/old_api/fanout/verify.in b/cpp/examples/fanout/verify.in
index 8f8612ce67..8f8612ce67 100644
--- a/cpp/examples/old_api/fanout/verify.in
+++ b/cpp/examples/fanout/verify.in
diff --git a/cpp/examples/messaging/drain.cpp b/cpp/examples/messaging/drain.cpp
index 563e5e5060..5c938e9742 100644
--- a/cpp/examples/messaging/drain.cpp
+++ b/cpp/examples/messaging/drain.cpp
@@ -45,12 +45,12 @@ struct Options : OptionParser
url("127.0.0.1"),
timeout(0),
forever(false),
- count(0)
+ count(1)
{
add("broker,b", url, "url of broker to connect to");
add("timeout,t", timeout, "timeout in seconds to wait before exiting");
add("forever,f", forever, "ignore timeout and wait forever");
- add("connection-options", connectionOptions, "connection options string in the form {name1:value1, name2:value2}");
+ add("connection-options", connectionOptions, "connection options string in the form {name1=value1, name2=value2}");
add("count,c", count, "number of messages to read before exiting");
}
diff --git a/cpp/examples/messaging/server.cpp b/cpp/examples/messaging/server.cpp
index aa271d91f9..ab72694c61 100644
--- a/cpp/examples/messaging/server.cpp
+++ b/cpp/examples/messaging/server.cpp
@@ -39,8 +39,8 @@ using std::string;
int main(int argc, char** argv) {
const char* url = argc>1 ? argv[1] : "amqp:tcp:127.0.0.1:5672";
- std::string connectionOptions = argc > 2 ? argv[2] : "";
-
+ std::string connectionOptions = argc > 3 ? argv[3] : "";
+
Connection connection(url, connectionOptions);
try {
connection.open();
diff --git a/cpp/examples/messaging/spout.cpp b/cpp/examples/messaging/spout.cpp
index cd11a7ad81..57b955c1de 100644
--- a/cpp/examples/messaging/spout.cpp
+++ b/cpp/examples/messaging/spout.cpp
@@ -65,7 +65,7 @@ struct Options : OptionParser
add("property,P", properties, "specify message property");
add("map,M", entries, "specify entry for map content");
add("content", content, "specify textual content");
- add("connection-options", connectionOptions, "connection options string in the form {name1:value1, name2:value2}");
+ add("connection-options", connectionOptions, "connection options string in the form {name1=value1, name2=value2}");
}
static bool nameval(const std::string& in, std::string& name, std::string& value)
diff --git a/cpp/examples/old_api/old-examples.sln b/cpp/examples/old-examples.sln
index e6ec9a0d66..7f2fa3e8b0 100644
--- a/cpp/examples/old_api/old-examples.sln
+++ b/cpp/examples/old-examples.sln
@@ -40,6 +40,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pub_sub_topic_listener", "p
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pub_sub_topic_publisher", "pub-sub\pub-sub_topic_publisher.vcproj", "{05158653-FECA-1BAD-A430-FD5330E23A2D}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_console", "qmf-console\qmf-console_console.vcproj", "{490473E1-FECA-1BAD-2E13-3FFA2B8669C3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_ping", "qmf-console\qmf-console_ping.vcproj", "{C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_printevents", "qmf-console\qmf-console_printevents.vcproj", "{72C74624-FECA-1BAD-2E13-3FFA2B8669C3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_queuestats", "qmf-console\qmf-console_queuestats.vcproj", "{B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "request_response_client", "request-response\request-response_client.vcproj", "{2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "request_response_server", "request-response\request-response_server.vcproj", "{46817425-FECA-1BAD-BD3A-8A467D0C5CCC}"
@@ -96,6 +104,22 @@ Global
{05158653-FECA-1BAD-A430-FD5330E23A2D}.Debug|Win32.Build.0 = Debug|Win32
{05158653-FECA-1BAD-A430-FD5330E23A2D}.Release|Win32.ActiveCfg = Release|Win32
{05158653-FECA-1BAD-A430-FD5330E23A2D}.Release|Win32.Build.0 = Release|Win32
+ {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
+ {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
+ {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
+ {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Debug|Win32.Build.0 = Debug|Win32
+ {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Release|Win32.ActiveCfg = Release|Win32
+ {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Release|Win32.Build.0 = Release|Win32
+ {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
+ {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
+ {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
+ {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
+ {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
+ {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
{2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Debug|Win32.ActiveCfg = Debug|Win32
{2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Debug|Win32.Build.0 = Debug|Win32
{2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/cpp/examples/old_api/CMakeLists.txt b/cpp/examples/old_api/CMakeLists.txt
deleted file mode 100644
index 701f9be860..0000000000
--- a/cpp/examples/old_api/CMakeLists.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-add_subdirectory(direct)
-add_subdirectory(failover)
-add_subdirectory(fanout)
-add_subdirectory(pub-sub)
-add_subdirectory(request-response)
-add_subdirectory(tradedemo)
-add_subdirectory(xml-exchange)
diff --git a/cpp/examples/old_api/Makefile.am b/cpp/examples/old_api/Makefile.am
deleted file mode 100644
index 04216ffa97..0000000000
--- a/cpp/examples/old_api/Makefile.am
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-SUBDIRS = direct pub-sub fanout request-response failover tradedemo
-if HAVE_XML
- SUBDIRS += xml-exchange
- broker_args = "--no-module-dir --data-dir \"\" --auth no --load-module $(top_builddir)/src/.libs/xml.so"
-endif
-if !HAVE_XML
- exclude_examples_regexp="xml" # Exclude XML examples.
- broker_args = "--no-module-dir --data-dir \"\" --auth no"
-endif
-
-MAKEDIST=.libs/Makefile
-
-$(MAKEDIST): Makefile
- mkdir -p .libs
- @(echo 'all clean:' ; \
- echo ' for d in $(SUBDIRS) ; do $$(MAKE) -C $$$$d $$@ ; done' ; \
- ) > $(MAKEDIST)
-
-examplesdir=$(pkgdatadir)/examples/old_api
-dist_examples_DATA = $(MAKEDIST)
-EXTRA_DIST = README.verify verify verify_all CMakeLists.txt
-
-# For older versions of automake
-abs_top_srcdir = @abs_top_srcdir@
-abs_top_builddir = @abs_top_builddir@
-
-# Verify the examples in the buid tree.
-check-local:
- $(srcdir)/verify_all $(abs_top_srcdir)/.. $(abs_top_builddir) $(broker_args) $(exclude_examples_regexp)
-
diff --git a/cpp/examples/old_api/pub-sub/CMakeLists.txt b/cpp/examples/pub-sub/CMakeLists.txt
index 961de06d5a..961de06d5a 100644
--- a/cpp/examples/old_api/pub-sub/CMakeLists.txt
+++ b/cpp/examples/pub-sub/CMakeLists.txt
diff --git a/cpp/examples/old_api/pub-sub/Makefile.am b/cpp/examples/pub-sub/Makefile.am
index 8f42ee0211..62658ebe94 100644
--- a/cpp/examples/old_api/pub-sub/Makefile.am
+++ b/cpp/examples/pub-sub/Makefile.am
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-examplesdir=$(pkgdatadir)/examples/old_api/pub-sub
+examplesdir=$(pkgdatadir)/examples/pub-sub
MAKELDFLAGS=$(CLIENTFLAGS)
include $(top_srcdir)/examples/makedist.mk
diff --git a/cpp/examples/old_api/pub-sub/pub-sub_topic_listener.vcproj b/cpp/examples/pub-sub/pub-sub_topic_listener.vcproj
index aa0b3bcaa3..aa0b3bcaa3 100644
--- a/cpp/examples/old_api/pub-sub/pub-sub_topic_listener.vcproj
+++ b/cpp/examples/pub-sub/pub-sub_topic_listener.vcproj
diff --git a/cpp/examples/old_api/pub-sub/pub-sub_topic_publisher.vcproj b/cpp/examples/pub-sub/pub-sub_topic_publisher.vcproj
index 76e51df4df..76e51df4df 100644
--- a/cpp/examples/old_api/pub-sub/pub-sub_topic_publisher.vcproj
+++ b/cpp/examples/pub-sub/pub-sub_topic_publisher.vcproj
diff --git a/cpp/examples/old_api/pub-sub/topic_listener.cpp b/cpp/examples/pub-sub/topic_listener.cpp
index d38a806303..d38a806303 100644
--- a/cpp/examples/old_api/pub-sub/topic_listener.cpp
+++ b/cpp/examples/pub-sub/topic_listener.cpp
diff --git a/cpp/examples/old_api/pub-sub/topic_publisher.cpp b/cpp/examples/pub-sub/topic_publisher.cpp
index aed5f8f033..aed5f8f033 100644
--- a/cpp/examples/old_api/pub-sub/topic_publisher.cpp
+++ b/cpp/examples/pub-sub/topic_publisher.cpp
diff --git a/cpp/examples/old_api/pub-sub/verify b/cpp/examples/pub-sub/verify
index 528d2f401e..528d2f401e 100644
--- a/cpp/examples/old_api/pub-sub/verify
+++ b/cpp/examples/pub-sub/verify
diff --git a/cpp/examples/old_api/pub-sub/verify.in b/cpp/examples/pub-sub/verify.in
index 6413c5c788..6413c5c788 100644
--- a/cpp/examples/old_api/pub-sub/verify.in
+++ b/cpp/examples/pub-sub/verify.in
diff --git a/cpp/examples/qmf-console/ping.cpp b/cpp/examples/qmf-console/ping.cpp
index e6d6d138d5..fe537d48d2 100644
--- a/cpp/examples/qmf-console/ping.cpp
+++ b/cpp/examples/qmf-console/ping.cpp
@@ -31,7 +31,9 @@ using namespace qpid::console;
int main_int(int /*argc*/, char** /*argv*/)
{
//
- // Declare connection settings for the messaging broker.
+ // Declare connection settings for the messaging broker. The settings default to
+ // localhost:5672 with user guest (password guest). Refer to the header file
+ // <qpid/client/ConnectionSettings.h> for full details.
//
qpid::client::ConnectionSettings connSettings;
diff --git a/cpp/examples/qmf-console/printevents.cpp b/cpp/examples/qmf-console/printevents.cpp
index ac3e449a2c..3a0a2ab68b 100644
--- a/cpp/examples/qmf-console/printevents.cpp
+++ b/cpp/examples/qmf-console/printevents.cpp
@@ -64,7 +64,9 @@ struct Main {
Listener listener;
//
- // Declare connection settings for the messaging broker.
+ // Declare connection settings for the messaging broker. The settings default to
+ // localhost:5672 with user guest (password guest). Refer to the header file
+ // <qpid/client/ConnectionSettings.h> for full details.
//
qpid::client::ConnectionSettings connSettings;
diff --git a/cpp/examples/old_api/request-response/CMakeLists.txt b/cpp/examples/request-response/CMakeLists.txt
index 873a0cfa86..873a0cfa86 100644
--- a/cpp/examples/old_api/request-response/CMakeLists.txt
+++ b/cpp/examples/request-response/CMakeLists.txt
diff --git a/cpp/examples/old_api/request-response/Makefile.am b/cpp/examples/request-response/Makefile.am
index f48762da51..48b3d989f0 100644
--- a/cpp/examples/old_api/request-response/Makefile.am
+++ b/cpp/examples/request-response/Makefile.am
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-examplesdir=$(pkgdatadir)/examples/old_api/request-response
+examplesdir=$(pkgdatadir)/examples/request-response
MAKELDFLAGS=$(CLIENTFLAGS)
include $(top_srcdir)/examples/makedist.mk
diff --git a/cpp/examples/old_api/request-response/client.cpp b/cpp/examples/request-response/client.cpp
index 679d1c5fc2..679d1c5fc2 100644
--- a/cpp/examples/old_api/request-response/client.cpp
+++ b/cpp/examples/request-response/client.cpp
diff --git a/cpp/examples/old_api/request-response/request-response_client.vcproj b/cpp/examples/request-response/request-response_client.vcproj
index 5f9eadde36..5f9eadde36 100644
--- a/cpp/examples/old_api/request-response/request-response_client.vcproj
+++ b/cpp/examples/request-response/request-response_client.vcproj
diff --git a/cpp/examples/old_api/request-response/request-response_server.vcproj b/cpp/examples/request-response/request-response_server.vcproj
index 54352b9f46..54352b9f46 100644
--- a/cpp/examples/old_api/request-response/request-response_server.vcproj
+++ b/cpp/examples/request-response/request-response_server.vcproj
diff --git a/cpp/examples/old_api/request-response/server.cpp b/cpp/examples/request-response/server.cpp
index 65a4717b35..65a4717b35 100644
--- a/cpp/examples/old_api/request-response/server.cpp
+++ b/cpp/examples/request-response/server.cpp
diff --git a/cpp/examples/old_api/request-response/verify b/cpp/examples/request-response/verify
index dee82413e7..dee82413e7 100644
--- a/cpp/examples/old_api/request-response/verify
+++ b/cpp/examples/request-response/verify
diff --git a/cpp/examples/old_api/request-response/verify.in b/cpp/examples/request-response/verify.in
index 7925dc5671..7925dc5671 100644
--- a/cpp/examples/old_api/request-response/verify.in
+++ b/cpp/examples/request-response/verify.in
diff --git a/cpp/examples/old_api/tradedemo/CMakeLists.txt b/cpp/examples/tradedemo/CMakeLists.txt
index e61fc1467d..e61fc1467d 100644
--- a/cpp/examples/old_api/tradedemo/CMakeLists.txt
+++ b/cpp/examples/tradedemo/CMakeLists.txt
diff --git a/cpp/examples/old_api/tradedemo/Makefile.am b/cpp/examples/tradedemo/Makefile.am
index 445b15b367..f4d8686d05 100644
--- a/cpp/examples/old_api/tradedemo/Makefile.am
+++ b/cpp/examples/tradedemo/Makefile.am
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-examplesdir=$(pkgdatadir)/examples/old_api/tradedemo
+examplesdir=$(pkgdatadir)/examples/tradedemo
MAKELDFLAGS=$(CLIENTFLAGS)
include $(top_srcdir)/examples/makedist.mk
diff --git a/cpp/examples/old_api/tradedemo/declare_queues.cpp b/cpp/examples/tradedemo/declare_queues.cpp
index b1f2cc3510..b1f2cc3510 100644
--- a/cpp/examples/old_api/tradedemo/declare_queues.cpp
+++ b/cpp/examples/tradedemo/declare_queues.cpp
diff --git a/cpp/examples/old_api/tradedemo/topic_listener.cpp b/cpp/examples/tradedemo/topic_listener.cpp
index c488e7fb69..c488e7fb69 100644
--- a/cpp/examples/old_api/tradedemo/topic_listener.cpp
+++ b/cpp/examples/tradedemo/topic_listener.cpp
diff --git a/cpp/examples/old_api/tradedemo/topic_publisher.cpp b/cpp/examples/tradedemo/topic_publisher.cpp
index e22c185bc7..e22c185bc7 100644
--- a/cpp/examples/old_api/tradedemo/topic_publisher.cpp
+++ b/cpp/examples/tradedemo/topic_publisher.cpp
diff --git a/cpp/examples/old_api/tradedemo/tradedemo_declare_queues.vcproj b/cpp/examples/tradedemo/tradedemo_declare_queues.vcproj
index 34b5cb3b2b..34b5cb3b2b 100644
--- a/cpp/examples/old_api/tradedemo/tradedemo_declare_queues.vcproj
+++ b/cpp/examples/tradedemo/tradedemo_declare_queues.vcproj
diff --git a/cpp/examples/old_api/tradedemo/tradedemo_topic_listener.vcproj b/cpp/examples/tradedemo/tradedemo_topic_listener.vcproj
index 965be2e88b..965be2e88b 100644
--- a/cpp/examples/old_api/tradedemo/tradedemo_topic_listener.vcproj
+++ b/cpp/examples/tradedemo/tradedemo_topic_listener.vcproj
diff --git a/cpp/examples/old_api/tradedemo/tradedemo_topic_publisher.vcproj b/cpp/examples/tradedemo/tradedemo_topic_publisher.vcproj
index 77fd511e15..77fd511e15 100644
--- a/cpp/examples/old_api/tradedemo/tradedemo_topic_publisher.vcproj
+++ b/cpp/examples/tradedemo/tradedemo_topic_publisher.vcproj
diff --git a/cpp/examples/old_api/verify b/cpp/examples/verify
index 9a1ed078d6..9a1ed078d6 100755
--- a/cpp/examples/old_api/verify
+++ b/cpp/examples/verify
diff --git a/cpp/examples/old_api/verify_all b/cpp/examples/verify_all
index fbe51377b6..cb4c5283fa 100755
--- a/cpp/examples/old_api/verify_all
+++ b/cpp/examples/verify_all
@@ -32,7 +32,7 @@ trap "$qpidd -q" exit
QPID_PORT=`$qpidd -dp0 $broker_args` || { echo "Can't run qpidd" ; exit 1; }
export QPID_PORT
-find="find $topsrcdir/cpp/examples/old_api"
+find="find $topsrcdir/cpp/examples"
find="$find -mindepth 2 -name verify"
all_examples=`$find`
diff --git a/cpp/examples/old_api/xml-exchange/CMakeLists.txt b/cpp/examples/xml-exchange/CMakeLists.txt
index 3fea47a208..3fea47a208 100644
--- a/cpp/examples/old_api/xml-exchange/CMakeLists.txt
+++ b/cpp/examples/xml-exchange/CMakeLists.txt
diff --git a/cpp/examples/old_api/xml-exchange/Makefile.am b/cpp/examples/xml-exchange/Makefile.am
index 3e1082cdb2..9001e3fa61 100644
--- a/cpp/examples/old_api/xml-exchange/Makefile.am
+++ b/cpp/examples/xml-exchange/Makefile.am
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-examplesdir=$(pkgdatadir)/examples/old_api/xml-exchange
+examplesdir=$(pkgdatadir)/examples/xml-exchange
MAKELDFLAGS=$(CLIENTFLAGS)
include $(top_srcdir)/examples/makedist.mk
diff --git a/cpp/examples/old_api/xml-exchange/README.txt b/cpp/examples/xml-exchange/README.txt
index 85caebe352..85caebe352 100644
--- a/cpp/examples/old_api/xml-exchange/README.txt
+++ b/cpp/examples/xml-exchange/README.txt
diff --git a/cpp/examples/old_api/xml-exchange/declare_queues.cpp b/cpp/examples/xml-exchange/declare_queues.cpp
index ad08642019..ad08642019 100644
--- a/cpp/examples/old_api/xml-exchange/declare_queues.cpp
+++ b/cpp/examples/xml-exchange/declare_queues.cpp
diff --git a/cpp/examples/old_api/xml-exchange/listener.cpp b/cpp/examples/xml-exchange/listener.cpp
index 11bcb9f669..11bcb9f669 100644
--- a/cpp/examples/old_api/xml-exchange/listener.cpp
+++ b/cpp/examples/xml-exchange/listener.cpp
diff --git a/cpp/examples/old_api/xml-exchange/xml_producer.cpp b/cpp/examples/xml-exchange/xml_producer.cpp
index af1a7e60c7..af1a7e60c7 100644
--- a/cpp/examples/old_api/xml-exchange/xml_producer.cpp
+++ b/cpp/examples/xml-exchange/xml_producer.cpp
diff --git a/cpp/include/qmf/Agent.h b/cpp/include/qmf/Agent.h
index 94083be4f3..8c0f48b8b1 100644
--- a/cpp/include/qmf/Agent.h
+++ b/cpp/include/qmf/Agent.h
@@ -42,7 +42,7 @@ namespace qmf {
class SchemaId;
class Schema;
- class QMF_CLASS_EXTERN Agent : public qmf::Handle<AgentImpl> {
+ class Agent : public qmf::Handle<AgentImpl> {
public:
QMF_EXTERN Agent(AgentImpl* impl = 0);
QMF_EXTERN Agent(const Agent&);
diff --git a/cpp/include/qmf/AgentEvent.h b/cpp/include/qmf/AgentEvent.h
index 0f93a9bb0a..59a41c3267 100644
--- a/cpp/include/qmf/AgentEvent.h
+++ b/cpp/include/qmf/AgentEvent.h
@@ -46,7 +46,7 @@ namespace qmf {
AGENT_THREAD_FAILED = 8
};
- class QMF_CLASS_EXTERN AgentEvent : public qmf::Handle<AgentEventImpl> {
+ class AgentEvent : public qmf::Handle<AgentEventImpl> {
public:
QMF_EXTERN AgentEvent(AgentEventImpl* impl = 0);
QMF_EXTERN AgentEvent(const AgentEvent&);
diff --git a/cpp/include/qmf/AgentSession.h b/cpp/include/qmf/AgentSession.h
index 589d364bcc..9e29d6b54b 100644
--- a/cpp/include/qmf/AgentSession.h
+++ b/cpp/include/qmf/AgentSession.h
@@ -40,7 +40,7 @@ namespace qmf {
class Data;
class DataAddr;
- class QMF_CLASS_EXTERN AgentSession : public qmf::Handle<AgentSessionImpl> {
+ class AgentSession : public qmf::Handle<AgentSessionImpl> {
public:
QMF_EXTERN AgentSession(AgentSessionImpl* impl = 0);
QMF_EXTERN AgentSession(const AgentSession&);
@@ -71,20 +71,15 @@ namespace qmf {
* If False: Listen only on the routable direct address
* strict-security:{True,False} - If True: Cooperate with the broker to enforce strict access control to the network
* - If False: Operate more flexibly with regard to use of messaging facilities [default]
- * max-thread-wait-time:N - Time (in seconds) the session thread will wait for messages from the network between
- * periodic background processing passes. [default: 5]
- * Must not be greater than 'interval'. Larger numbers will cause fewer wake-ups but will
- * increase the time it takes to shut down the process. This setting will not affect the
- * agent's response time for queries or method invocation.
*/
- QMF_EXTERN AgentSession(qpid::messaging::Connection& conn, const std::string& options="");
+ QMF_EXTERN AgentSession(qpid::messaging::Connection&, const std::string& options="");
/**
* setDomain - Change the QMF domain that this agent will operate in. If this is not called,
* the domain will be "default". Agents in a domain can be seen only by consoles in the same domain.
* This must be called prior to opening the agent session.
*/
- QMF_EXTERN void setDomain(const std::string& domain);
+ QMF_EXTERN void setDomain(const std::string&);
/**
* Set identifying attributes of this agent.
@@ -93,16 +88,16 @@ namespace qmf {
* setInstance - Set the unique instance name (if not set, a UUID will be assigned)
* These must be called prior to opening the agent session.
*/
- QMF_EXTERN void setVendor(const std::string& vendor);
- QMF_EXTERN void setProduct(const std::string& product);
- QMF_EXTERN void setInstance(const std::string& instance);
+ QMF_EXTERN void setVendor(const std::string&);
+ QMF_EXTERN void setProduct(const std::string&);
+ QMF_EXTERN void setInstance(const std::string&);
/**
* setAttribute - Set an arbitrary attribute for this agent. The attributes are not used
* to uniquely identify the agent but can be used as a search criteria when looking for agents.
* This must be called prior to opening the agent session.
*/
- QMF_EXTERN void setAttribute(const std::string& key, const qpid::types::Variant& value);
+ QMF_EXTERN void setAttribute(const std::string&, const qpid::types::Variant&);
/**
* Get the identifying name of the agent.
@@ -124,19 +119,13 @@ namespace qmf {
* Get the next event from the agent session. Events represent actions that must be acted upon by the
* agent application. This method blocks for up to the timeout if there are no events to be handled.
* This method will typically be the focus of the agent application's main execution loop.
- * If the timeout is set to Duration::IMMEDIATE, the call will not block.
*/
- QMF_EXTERN bool nextEvent(AgentEvent& outEvent, qpid::messaging::Duration timeout=qpid::messaging::Duration::FOREVER);
-
- /**
- * Return the number of events pending for nextEvent. This method will never block.
- */
- QMF_EXTERN int pendingEvents() const;
+ QMF_EXTERN bool nextEvent(AgentEvent&, qpid::messaging::Duration timeout=qpid::messaging::Duration::FOREVER);
/**
* Register a schema to be exposed by this agent.
*/
- QMF_EXTERN void registerSchema(Schema& schema);
+ QMF_EXTERN void registerSchema(Schema&);
/**
* Add data to be managed internally by the agent. If the option external:True is selected, this call
@@ -149,12 +138,12 @@ namespace qmf {
* across different sessions. If persistent, it is the agent application's
* responsibility to ensure the name is the same each time it is added.
*/
- QMF_EXTERN DataAddr addData(Data& data, const std::string& name="", bool persistent=false);
+ QMF_EXTERN DataAddr addData(Data&, const std::string& name="", bool persistent=false);
/**
* Delete data from internal agent management.
*/
- QMF_EXTERN void delData(const DataAddr& dataAddr);
+ QMF_EXTERN void delData(const DataAddr&);
/**
* The following methods are used to respond to events received in nextEvent.
@@ -166,13 +155,13 @@ namespace qmf {
* complete - Indicate that the response to a query is complete (external:True only)
* methodSuccess - Indicate the successful completion of a method call.
*/
- QMF_EXTERN void authAccept(AgentEvent& event);
- QMF_EXTERN void authReject(AgentEvent& event, const std::string& diag="");
- QMF_EXTERN void raiseException(AgentEvent& event, const std::string& errorText);
- QMF_EXTERN void raiseException(AgentEvent& event, const Data& errorData);
- QMF_EXTERN void response(AgentEvent& event, const Data& responseData);
- QMF_EXTERN void complete(AgentEvent& event);
- QMF_EXTERN void methodSuccess(AgentEvent& event);
+ QMF_EXTERN void authAccept(AgentEvent&);
+ QMF_EXTERN void authReject(AgentEvent&, const std::string& diag="");
+ QMF_EXTERN void raiseException(AgentEvent&, const std::string&);
+ QMF_EXTERN void raiseException(AgentEvent&, const Data&);
+ QMF_EXTERN void response(AgentEvent&, const Data&);
+ QMF_EXTERN void complete(AgentEvent&);
+ QMF_EXTERN void methodSuccess(AgentEvent&);
/**
* Raise an event to be sent into the QMF network.
@@ -188,7 +177,6 @@ namespace qmf {
#ifndef SWIG
private:
friend class qmf::PrivateImplRef<AgentSession>;
- friend struct AgentSessionImplAccess;
#endif
};
diff --git a/cpp/include/qmf/ConsoleEvent.h b/cpp/include/qmf/ConsoleEvent.h
index 94600f9357..b836b629af 100644
--- a/cpp/include/qmf/ConsoleEvent.h
+++ b/cpp/include/qmf/ConsoleEvent.h
@@ -57,7 +57,7 @@ namespace qmf {
AGENT_DEL_FILTER = 2
};
- class QMF_CLASS_EXTERN ConsoleEvent : public qmf::Handle<ConsoleEventImpl> {
+ class ConsoleEvent : public qmf::Handle<ConsoleEventImpl> {
public:
QMF_EXTERN ConsoleEvent(ConsoleEventImpl* impl = 0);
QMF_EXTERN ConsoleEvent(const ConsoleEvent&);
diff --git a/cpp/include/qmf/ConsoleSession.h b/cpp/include/qmf/ConsoleSession.h
index 022485cfa7..0c73e7a6db 100644
--- a/cpp/include/qmf/ConsoleSession.h
+++ b/cpp/include/qmf/ConsoleSession.h
@@ -38,7 +38,7 @@ namespace qmf {
class ConsoleSessionImpl;
class ConsoleEvent;
- class QMF_CLASS_EXTERN ConsoleSession : public qmf::Handle<ConsoleSessionImpl> {
+ class ConsoleSession : public qmf::Handle<ConsoleSessionImpl> {
public:
QMF_EXTERN ConsoleSession(ConsoleSessionImpl* impl = 0);
QMF_EXTERN ConsoleSession(const ConsoleSession&);
@@ -61,53 +61,15 @@ namespace qmf {
* If False: Listen only on the routable direct address
* strict-security:{True,False} - If True: Cooperate with the broker to enforce strict access control to the network
* - If False: Operate more flexibly with regard to use of messaging facilities [default]
- * max-thread-wait-time:N - Time (in seconds) the session thread will wait for messages from the network between
- * periodic background processing passes.
- * Must not be greater than 60. Larger numbers will cause fewer wake-ups but will
- * increase the time it takes to shut down the process. [default: 5]
- */
- QMF_EXTERN ConsoleSession(qpid::messaging::Connection& conn, const std::string& options="");
-
- /**
- * setDomain - Change the QMF domain that this console will operate in. If this is not called,
- * the domain will be "default". Agents in a domain can be seen only by consoles in the same domain.
- * This must be called prior to opening the console session.
- */
- QMF_EXTERN void setDomain(const std::string& domain);
- QMF_EXTERN void setAgentFilter(const std::string& filter);
-
- /**
- * Open the console session. After opening the session, the domain cannot be changed.
*/
+ QMF_EXTERN ConsoleSession(qpid::messaging::Connection&, const std::string& options="");
+ QMF_EXTERN void setDomain(const std::string&);
+ QMF_EXTERN void setAgentFilter(const std::string&);
QMF_EXTERN void open();
-
- /**
- * Close the session. Once closed, the session no longer communicates on the messaging network.
- */
QMF_EXTERN void close();
-
- /**
- * Get the next event from the console session. Events represent actions that must be acted upon by the
- * console application. This method blocks for up to the timeout if there are no events to be handled.
- * This method will typically be the focus of the console application's main execution loop.
- * If the timeout is set to Duration::IMMEDIATE, the call will not block.
- */
- QMF_EXTERN bool nextEvent(ConsoleEvent& outEvent, qpid::messaging::Duration timeout=qpid::messaging::Duration::FOREVER);
-
- /**
- * Return the number of events pending for nextEvent. This method will never block.
- */
- QMF_EXTERN int pendingEvents() const;
-
- /**
- * getAgentCount, getAgent - Retrieve the set of agents that match the console session's agent filter.
- */
+ QMF_EXTERN bool nextEvent(ConsoleEvent&, qpid::messaging::Duration timeout=qpid::messaging::Duration::FOREVER);
QMF_EXTERN uint32_t getAgentCount() const;
- QMF_EXTERN Agent getAgent(uint32_t agentIndex) const;
-
- /**
- * Get the agent for the connected broker (i.e. the agent embedded in the broker to which we have a connection).
- */
+ QMF_EXTERN Agent getAgent(uint32_t) const;
QMF_EXTERN Agent getConnectedBrokerAgent() const;
/**
@@ -117,13 +79,12 @@ namespace qmf {
* will involve all known agents. If agentFilter is non-empty, it will be applied only to the set of known
* agents. A subscription cannot be created that involves an agent not known by the session.
*/
- QMF_EXTERN Subscription subscribe(const Query& query, const std::string& agentFilter = "", const std::string& options = "");
- QMF_EXTERN Subscription subscribe(const std::string& query, const std::string& agentFilter = "", const std::string& options = "");
+ QMF_EXTERN Subscription subscribe(const Query&, const std::string& agentFilter = "", const std::string& options = "");
+ QMF_EXTERN Subscription subscribe(const std::string&, const std::string& agentFilter = "", const std::string& options = "");
#ifndef SWIG
private:
friend class qmf::PrivateImplRef<ConsoleSession>;
- friend struct ConsoleSessionImplAccess;
#endif
};
diff --git a/cpp/include/qmf/Data.h b/cpp/include/qmf/Data.h
index 487a02fe95..82f1569a0b 100644
--- a/cpp/include/qmf/Data.h
+++ b/cpp/include/qmf/Data.h
@@ -39,7 +39,7 @@ namespace qmf {
class DataAddr;
class Agent;
- class QMF_CLASS_EXTERN Data : public qmf::Handle<DataImpl> {
+ class Data : public qmf::Handle<DataImpl> {
public:
QMF_EXTERN Data(DataImpl* impl = 0);
QMF_EXTERN Data(const Data&);
diff --git a/cpp/include/qmf/DataAddr.h b/cpp/include/qmf/DataAddr.h
index 20c469081e..72de0c986a 100644
--- a/cpp/include/qmf/DataAddr.h
+++ b/cpp/include/qmf/DataAddr.h
@@ -34,7 +34,7 @@ namespace qmf {
class DataAddrImpl;
- class QMF_CLASS_EXTERN DataAddr : public qmf::Handle<DataAddrImpl> {
+ class DataAddr : public qmf::Handle<DataAddrImpl> {
public:
QMF_EXTERN DataAddr(DataAddrImpl* impl = 0);
QMF_EXTERN DataAddr(const DataAddr&);
@@ -51,9 +51,6 @@ namespace qmf {
QMF_EXTERN uint32_t getAgentEpoch() const;
QMF_EXTERN qpid::types::Variant::Map asMap() const;
- QMF_EXTERN bool operator==(const DataAddr&) const;
- QMF_EXTERN bool operator<(const DataAddr&) const;
-
#ifndef SWIG
private:
friend class qmf::PrivateImplRef<DataAddr>;
diff --git a/cpp/include/qmf/Handle.h b/cpp/include/qmf/Handle.h
index 50971ea626..510e2993aa 100644
--- a/cpp/include/qmf/Handle.h
+++ b/cpp/include/qmf/Handle.h
@@ -39,22 +39,22 @@ template <class T> class Handle {
public:
/**@return true if handle is valid, i.e. not null. */
- QMF_INLINE_EXTERN bool isValid() const { return impl; }
+ QMF_EXTERN bool isValid() const { return impl; }
/**@return true if handle is null. It is an error to call any function on a null handle. */
- QMF_INLINE_EXTERN bool isNull() const { return !impl; }
+ QMF_EXTERN bool isNull() const { return !impl; }
/** Conversion to bool supports idiom if (handle) { handle->... } */
- QMF_INLINE_EXTERN operator bool() const { return impl; }
+ QMF_EXTERN operator bool() const { return impl; }
/** Operator ! supports idiom if (!handle) { do_if_handle_is_null(); } */
- QMF_INLINE_EXTERN bool operator !() const { return !impl; }
+ QMF_EXTERN bool operator !() const { return !impl; }
void swap(Handle<T>& h) { T* t = h.impl; h.impl = impl; impl = t; }
protected:
typedef T Impl;
- QMF_INLINE_EXTERN Handle() :impl() {}
+ QMF_EXTERN Handle() :impl() {}
// Not implemented,subclasses must implement.
QMF_EXTERN Handle(const Handle&);
diff --git a/cpp/include/qmf/ImportExport.h b/cpp/include/qmf/ImportExport.h
index 7405c15259..f5e1d9127c 100644
--- a/cpp/include/qmf/ImportExport.h
+++ b/cpp/include/qmf/ImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
-#if defined(QMF_EXPORT) || defined (qmf2_EXPORTS)
-# define QMF_EXTERN QPID_EXPORT
-# define QMF_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QMF_INLINE_EXTERN QPID_INLINE_EXPORT
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
+# if defined(QMF_EXPORT) || defined (qmfcommon_EXPORTS)
+# define QMF_EXTERN __declspec(dllexport)
+# else
+# define QMF_EXTERN __declspec(dllimport)
+# endif
#else
-# define QMF_EXTERN QPID_IMPORT
-# define QMF_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QMF_INLINE_EXTERN QPID_INLINE_IMPORT
+# define QMF_EXTERN
#endif
#endif
diff --git a/cpp/include/qmf/Query.h b/cpp/include/qmf/Query.h
index c1264f8901..fec4660bd7 100644
--- a/cpp/include/qmf/Query.h
+++ b/cpp/include/qmf/Query.h
@@ -43,7 +43,7 @@ namespace qmf {
QUERY_SCHEMA_ID = 4
};
- class QMF_CLASS_EXTERN Query : public qmf::Handle<QueryImpl> {
+ class Query : public qmf::Handle<QueryImpl> {
public:
QMF_EXTERN Query(QueryImpl* impl = 0);
QMF_EXTERN Query(const Query&);
@@ -65,7 +65,7 @@ namespace qmf {
#ifndef SWIG
private:
friend class qmf::PrivateImplRef<Query>;
- friend struct QueryImplAccess;
+ friend class QueryImplAccess;
#endif
};
diff --git a/cpp/include/qmf/Schema.h b/cpp/include/qmf/Schema.h
index 6cfd2e2a56..cf316138c1 100644
--- a/cpp/include/qmf/Schema.h
+++ b/cpp/include/qmf/Schema.h
@@ -38,7 +38,7 @@ namespace qmf {
class SchemaProperty;
class SchemaMethod;
- class QMF_CLASS_EXTERN Schema : public qmf::Handle<SchemaImpl> {
+ class Schema : public qmf::Handle<SchemaImpl> {
public:
QMF_EXTERN Schema(SchemaImpl* impl = 0);
QMF_EXTERN Schema(const Schema&);
diff --git a/cpp/include/qmf/SchemaId.h b/cpp/include/qmf/SchemaId.h
index 2dafc1c091..13fb1cb902 100644
--- a/cpp/include/qmf/SchemaId.h
+++ b/cpp/include/qmf/SchemaId.h
@@ -35,7 +35,7 @@ namespace qmf {
class SchemaIdImpl;
- class QMF_CLASS_EXTERN SchemaId : public qmf::Handle<SchemaIdImpl> {
+ class SchemaId : public qmf::Handle<SchemaIdImpl> {
public:
QMF_EXTERN SchemaId(SchemaIdImpl* impl = 0);
QMF_EXTERN SchemaId(const SchemaId&);
diff --git a/cpp/include/qmf/SchemaMethod.h b/cpp/include/qmf/SchemaMethod.h
index b5944dc29e..47302b62b9 100644
--- a/cpp/include/qmf/SchemaMethod.h
+++ b/cpp/include/qmf/SchemaMethod.h
@@ -36,7 +36,7 @@ namespace qmf {
class SchemaMethodImpl;
class SchemaProperty;
- class QMF_CLASS_EXTERN SchemaMethod : public qmf::Handle<SchemaMethodImpl> {
+ class SchemaMethod : public qmf::Handle<SchemaMethodImpl> {
public:
QMF_EXTERN SchemaMethod(SchemaMethodImpl* impl = 0);
QMF_EXTERN SchemaMethod(const SchemaMethod&);
diff --git a/cpp/include/qmf/SchemaProperty.h b/cpp/include/qmf/SchemaProperty.h
index bbb603fa50..a3a328b60b 100644
--- a/cpp/include/qmf/SchemaProperty.h
+++ b/cpp/include/qmf/SchemaProperty.h
@@ -36,7 +36,7 @@ namespace qmf {
class SchemaPropertyImpl;
- class QMF_CLASS_EXTERN SchemaProperty : public Handle<SchemaPropertyImpl> {
+ class SchemaProperty : public Handle<SchemaPropertyImpl> {
public:
QMF_EXTERN SchemaProperty(SchemaPropertyImpl* impl = 0);
QMF_EXTERN SchemaProperty(const SchemaProperty&);
diff --git a/cpp/include/qmf/Subscription.h b/cpp/include/qmf/Subscription.h
index 398a45b922..4e60eb984e 100644
--- a/cpp/include/qmf/Subscription.h
+++ b/cpp/include/qmf/Subscription.h
@@ -35,7 +35,7 @@ namespace qmf {
class SubscriptionImpl;
class Data;
- class QMF_CLASS_EXTERN Subscription : public qmf::Handle<SubscriptionImpl> {
+ class Subscription : public qmf::Handle<SubscriptionImpl> {
public:
QMF_EXTERN Subscription(SubscriptionImpl* impl = 0);
QMF_EXTERN Subscription(const Subscription&);
@@ -73,7 +73,7 @@ namespace qmf {
#ifndef SWIG
private:
friend class qmf::PrivateImplRef<Subscription>;
- friend struct SubscriptionImplAccess;
+ friend class SubscriptionImplAccess;
#endif
};
diff --git a/cpp/include/qmf/engine/QmfEngineImportExport.h b/cpp/include/qmf/engine/QmfEngineImportExport.h
index cf8fffdb17..373617e046 100644
--- a/cpp/include/qmf/engine/QmfEngineImportExport.h
+++ b/cpp/include/qmf/engine/QmfEngineImportExport.h
@@ -26,17 +26,8 @@
# else
# define QMFE_EXTERN __declspec(dllimport)
# endif
-# ifdef _MSC_VER
-# define QMFE_CLASS_EXTERN
-# define QMFE_INLINE_EXTERN QMFE_EXTERN
-# else
-# define QMFE_CLASS_EXTERN QMFE_EXTERN
-# define QMFE_INLINE_EXTERN
-# endif
#else
# define QMFE_EXTERN
-# define QMFE_CLASS_EXTERN
-# define QMFE_INLINE_EXTERN
#endif
#endif
diff --git a/cpp/include/qmf/exceptions.h b/cpp/include/qmf/exceptions.h
index c7ffa68ce2..7959499d63 100644
--- a/cpp/include/qmf/exceptions.h
+++ b/cpp/include/qmf/exceptions.h
@@ -31,24 +31,24 @@ namespace qmf {
/** \ingroup qmf
*/
- struct QMF_CLASS_EXTERN QmfException : public qpid::types::Exception {
+ struct QmfException : public qpid::types::Exception {
QMF_EXTERN QmfException(const std::string& msg);
QMF_EXTERN virtual ~QmfException() throw();
qpid::types::Variant::Map detail;
};
- struct QMF_CLASS_EXTERN KeyNotFound : public QmfException {
+ struct KeyNotFound : public QmfException {
QMF_EXTERN KeyNotFound(const std::string& msg);
QMF_EXTERN virtual ~KeyNotFound() throw();
};
- struct QMF_CLASS_EXTERN IndexOutOfRange : public QmfException {
+ struct IndexOutOfRange : public QmfException {
QMF_EXTERN IndexOutOfRange();
QMF_EXTERN virtual ~IndexOutOfRange() throw();
};
- struct QMF_CLASS_EXTERN OperationTimedOut : public QmfException {
+ struct OperationTimedOut : public QmfException {
QMF_EXTERN OperationTimedOut();
QMF_EXTERN virtual ~OperationTimedOut() throw();
};
diff --git a/cpp/include/qmf/posix/EventNotifier.h b/cpp/include/qmf/posix/EventNotifier.h
deleted file mode 100644
index ebc1cb5364..0000000000
--- a/cpp/include/qmf/posix/EventNotifier.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef __QMF_POSIX_EVENT_NOTIFIER_H
-#define __QMF_POSIX_EVENT_NOTIFIER_H
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <qmf/ImportExport.h>
-#include "qmf/Handle.h"
-#include "qmf/AgentSession.h"
-#include "qmf/ConsoleSession.h"
-
-namespace qmf {
-
- class PosixEventNotifierImpl;
- class PosixEventNotifierImplAccess;
-
-namespace posix {
-
-#ifndef SWIG
- template <class> class PrivateImplRef;
-#endif
-
- class QMF_CLASS_EXTERN EventNotifier : public qmf::Handle<qmf::PosixEventNotifierImpl> {
- public:
- QMF_EXTERN EventNotifier(PosixEventNotifierImpl* impl = 0);
- QMF_EXTERN EventNotifier(::qmf::AgentSession& agentSession);
- QMF_EXTERN EventNotifier(::qmf::ConsoleSession& consoleSession);
- QMF_EXTERN EventNotifier(const EventNotifier& that);
-
- QMF_EXTERN ~EventNotifier();
-
- QMF_EXTERN EventNotifier& operator=(const EventNotifier& that);
-
- QMF_EXTERN int getHandle() const;
-
-#ifndef SWIG
- private:
- friend class qmf::PrivateImplRef<EventNotifier>;
- friend struct qmf::PosixEventNotifierImplAccess;
-#endif
-
- };
-
-}}
-
-#endif
-
diff --git a/cpp/include/qpid/Address.h b/cpp/include/qpid/Address.h
index f5b19d0532..57c9139f87 100755
--- a/cpp/include/qpid/Address.h
+++ b/cpp/include/qpid/Address.h
@@ -36,7 +36,7 @@ public:
static const std::string TCP; // Default TCP protocol tag.
static const uint16_t AMQP_PORT=5672; // Default AMQP port.
- QPID_COMMON_INLINE_EXTERN explicit Address(
+ QPID_COMMON_EXTERN explicit Address(
const std::string& protocol_=std::string(),
const std::string& host_=std::string(),
uint16_t port_=0
diff --git a/cpp/include/qpid/CommonImportExport.h b/cpp/include/qpid/CommonImportExport.h
index dd2b900b73..02c06ed7af 100644
--- a/cpp/include/qpid/CommonImportExport.h
+++ b/cpp/include/qpid/CommonImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
#if defined(COMMON_EXPORT) || defined (qpidcommon_EXPORTS)
-# define QPID_COMMON_EXTERN QPID_EXPORT
-# define QPID_COMMON_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QPID_COMMON_INLINE_EXTERN QPID_INLINE_EXPORT
+#define QPID_COMMON_EXTERN __declspec(dllexport)
+#else
+#define QPID_COMMON_EXTERN __declspec(dllimport)
+#endif
#else
-# define QPID_COMMON_EXTERN QPID_IMPORT
-# define QPID_COMMON_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QPID_COMMON_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QPID_COMMON_EXTERN
#endif
#endif
diff --git a/cpp/include/qpid/Exception.h b/cpp/include/qpid/Exception.h
index cbd175214d..fa7111160c 100644
--- a/cpp/include/qpid/Exception.h
+++ b/cpp/include/qpid/Exception.h
@@ -36,7 +36,7 @@ namespace qpid
/**
* Base class for Qpid runtime exceptions.
*/
-class QPID_COMMON_CLASS_EXTERN Exception : public std::exception
+class Exception : public std::exception
{
public:
QPID_COMMON_EXTERN explicit Exception(const std::string& message=std::string()) throw();
@@ -51,30 +51,30 @@ class QPID_COMMON_CLASS_EXTERN Exception : public std::exception
};
/** Exception that includes an errno message. */
-struct QPID_COMMON_CLASS_EXTERN ErrnoException : public Exception {
+struct ErrnoException : public Exception {
ErrnoException(const std::string& msg, int err) : Exception(msg+": "+qpid::sys::strError(err)) {}
ErrnoException(const std::string& msg) : Exception(msg+": "+qpid::sys::strError(errno)) {}
};
-struct QPID_COMMON_CLASS_EXTERN SessionException : public Exception {
+struct SessionException : public Exception {
const framing::execution::ErrorCode code;
SessionException(framing::execution::ErrorCode code_, const std::string& message)
: Exception(message), code(code_) {}
};
-struct QPID_COMMON_CLASS_EXTERN ChannelException : public Exception {
+struct ChannelException : public Exception {
const framing::session::DetachCode code;
ChannelException(framing::session::DetachCode _code, const std::string& message)
: Exception(message), code(_code) {}
};
-struct QPID_COMMON_CLASS_EXTERN ConnectionException : public Exception {
+struct ConnectionException : public Exception {
const framing::connection::CloseCode code;
ConnectionException(framing::connection::CloseCode _code, const std::string& message)
: Exception(message), code(_code) {}
};
-struct QPID_COMMON_CLASS_EXTERN ClosedException : public Exception {
+struct ClosedException : public Exception {
QPID_COMMON_EXTERN ClosedException(const std::string& msg=std::string());
QPID_COMMON_EXTERN std::string getPrefix() const;
};
diff --git a/cpp/include/qpid/ImportExport.h b/cpp/include/qpid/ImportExport.h
deleted file mode 100644
index e62399faf7..0000000000
--- a/cpp/include/qpid/ImportExport.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef QPID_IMPORTEXPORT_H
-#define QPID_IMPORTEXPORT_H
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-//
-// This header file defines the following macros for the control of library/DLL
-// import and export:
-//
-// QPID_EXPORT - Export declaration for Methods
-// QPID_CLASS_EXPORT - Export declaration for Classes
-// QPID_INLINE_EXPORT - Export declaration for Inline methods
-//
-// QPID_IMPORT - Import declaration for Methods
-// QPID_CLASS_IMPORT - Import declaration for Classes
-// QPID_INLINE_IMPORT - Import declaration for Inline methods
-//
-
-#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
- //
- // Import and Export definitions for Windows:
- //
-# define QPID_EXPORT __declspec(dllexport)
-# define QPID_IMPORT __declspec(dllimport)
-# ifdef _MSC_VER
- //
- // Specific to the Microsoft compiler:
- //
-# define QPID_CLASS_EXPORT
-# define QPID_CLASS_IMPORT
-# define QPID_INLINE_EXPORT QPID_EXPORT
-# define QPID_INLINE_IMPORT QPID_IMPORT
-# else
- //
- // Specific to non-Microsoft compilers (mingw32):
- //
-# define QPID_CLASS_EXPORT QPID_EXPORT
-# define QPID_CLASS_IMPORT QPID_IMPORT
-# define QPID_INLINE_EXPORT
-# define QPID_INLINE_IMPORT
-# endif
-#else
- //
- // Non-Windows (Linux, etc.) definitions:
- //
-# define QPID_EXPORT
-# define QPID_IMPORT
-# define QPID_CLASS_EXPORT
-# define QPID_CLASS_IMPORT
-# define QPID_INLINE_EXPORT
-# define QPID_INLINE_IMPORT
-#endif
-
-#endif /*!QPID_IMPORTEXPORT_H*/
diff --git a/cpp/include/qpid/Msg.h b/cpp/include/qpid/Msg.h
index 5f0b11bc60..e1837c29e5 100644
--- a/cpp/include/qpid/Msg.h
+++ b/cpp/include/qpid/Msg.h
@@ -24,7 +24,6 @@
#include <sstream>
#include <iostream>
-#include "qpid/types/ImportExport.h"
namespace qpid {
diff --git a/cpp/include/qpid/Options.h b/cpp/include/qpid/Options.h
index 63d91c2d72..078a6b4d95 100644
--- a/cpp/include/qpid/Options.h
+++ b/cpp/include/qpid/Options.h
@@ -133,6 +133,77 @@ inline po::value_semantic* optValue(bool& value) { return po::bool_switch(&value
+/*
+ * ---------------------------------------------
+ * Explanation for Boost 103200 conditional code
+ * ---------------------------------------------
+ *
+ * This boost version has an implementation of the program_options library
+ * that has no provision for allowing unregistered options to pass by.
+ *
+ * But that means that, if you have a program that loads optional modules
+ * after start-up, and those modules each have their own set of options,
+ * then if you parse the command line too soon, you will get spurious
+ * reports of unrecognized options -- and the program will exit!
+ *
+ * And we must process the command-line before module-loading, because we
+ * need to look at the "bootstrap" options.
+ *
+ * This conditional code:
+ *
+ * 1. implements it's own functor class, derived from the Boost
+ * "options_description_easy_init" class. This functor is used
+ * to process added options and do the functor chaining, so that
+ * I can snoop on the arguments before doing an explicit call
+ * to its parent.
+ *
+ * 2. It implements two static vectors, one to hold long names, and
+ * one for short names, so that options declared by modules are
+ * not forgotten when their options_description goes out of scope.
+ *
+ * I will be thrilled to personally delete this code if we ever decide
+ * that qpid doesn't really need to support this antique version of Boost.
+ *
+ */
+
+#if ( BOOST_VERSION == 103200 )
+struct Options;
+
+
+struct
+options_description_less_easy_init
+ : public po::options_description_easy_init
+{
+ options_description_less_easy_init ( Options * my_owner,
+ po::options_description * my_parents_owner
+ )
+ : po::options_description_easy_init(my_parents_owner)
+ {
+ owner = my_owner;
+ }
+
+
+ options_description_less_easy_init&
+ operator()(char const * name,
+ char const * description);
+
+
+ options_description_less_easy_init&
+ operator()(char const * name,
+ const po::value_semantic* s);
+
+
+ options_description_less_easy_init&
+ operator()(const char* name,
+ const po::value_semantic* s,
+ const char* description);
+
+
+ Options * owner;
+};
+#endif
+
+
struct Options : public po::options_description {
struct Exception : public qpid::Exception {
@@ -151,9 +222,26 @@ struct Options : public po::options_description {
bool allowUnknown = false);
+ #if ( BOOST_VERSION == 103200 )
+ options_description_less_easy_init m_less_easy;
+
+ options_description_less_easy_init addOptions() {
+ return m_less_easy;
+ }
+
+ bool
+ is_registered_option ( std::string s );
+
+ void
+ register_names ( std::string s );
+
+ static std::vector<std::string> long_names;
+ static std::vector<std::string> short_names;
+ #else
boost::program_options::options_description_easy_init addOptions() {
return add_options();
}
+ #endif
};
diff --git a/cpp/include/qpid/Url.h b/cpp/include/qpid/Url.h
index 915b08ac5f..353e9d5599 100644
--- a/cpp/include/qpid/Url.h
+++ b/cpp/include/qpid/Url.h
@@ -66,7 +66,7 @@ struct Url : public std::vector<Address> {
*@exception Invalid if the url is invalid.
*/
QPID_COMMON_EXTERN void parse(const char* url);
- QPID_COMMON_INLINE_EXTERN void parse(const std::string& url) { parse(url.c_str()); }
+ QPID_COMMON_EXTERN void parse(const std::string& url) { parse(url.c_str()); }
/** Replace contesnts with parsed URL. Replace with empty URL if invalid. */
QPID_COMMON_EXTERN void parseNoThrow(const char* url);
diff --git a/cpp/include/qpid/agent/ManagementAgent.h b/cpp/include/qpid/agent/ManagementAgent.h
index 10bc6527a9..e2451244c1 100644
--- a/cpp/include/qpid/agent/ManagementAgent.h
+++ b/cpp/include/qpid/agent/ManagementAgent.h
@@ -110,8 +110,8 @@ class ManagementAgent
uint16_t intervalSeconds = 10,
bool useExternalThread = false,
const std::string& storeFile = "",
- const std::string& uid = "",
- const std::string& pwd = "",
+ const std::string& uid = "guest",
+ const std::string& pwd = "guest",
const std::string& mech = "PLAIN",
const std::string& proto = "tcp") = 0;
diff --git a/cpp/include/qpid/agent/QmfAgentImportExport.h b/cpp/include/qpid/agent/QmfAgentImportExport.h
index 3f923ac4b2..e41425a7ba 100644
--- a/cpp/include/qpid/agent/QmfAgentImportExport.h
+++ b/cpp/include/qpid/agent/QmfAgentImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
-#if defined(QMF_EXPORT) || defined (qmf_EXPORTS)
-# define QMF_AGENT_EXTERN QPID_EXPORT
-# define QMF_AGENT_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QMF_AGENT_INLINE_EXTERN QPID_INLINE_EXPORT
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
+#if defined (qmf_EXPORTS)
+#define QMF_AGENT_EXTERN __declspec(dllexport)
+#else
+#define QMF_AGENT_EXTERN __declspec(dllimport)
+#endif
#else
-# define QMF_AGENT_EXTERN QPID_IMPORT
-# define QMF_AGENT_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QMF_AGENT_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QMF_AGENT_EXTERN
#endif
#endif
diff --git a/cpp/include/qpid/amqp_0_10/Codecs.h b/cpp/include/qpid/amqp_0_10/Codecs.h
index 73846f33a8..08275402fc 100644
--- a/cpp/include/qpid/amqp_0_10/Codecs.h
+++ b/cpp/include/qpid/amqp_0_10/Codecs.h
@@ -34,14 +34,14 @@ namespace amqp_0_10 {
* Codec for encoding/decoding a map of Variants using the AMQP 0-10
* map encoding.
*/
-class QPID_COMMON_CLASS_EXTERN MapCodec
+class QPID_COMMON_EXTERN MapCodec
{
public:
typedef qpid::types::Variant::Map ObjectType;
- static void QPID_COMMON_EXTERN encode(const ObjectType&, std::string&);
- static void QPID_COMMON_EXTERN decode(const std::string&, ObjectType&);
- static size_t QPID_COMMON_EXTERN encodedSize(const ObjectType&);
- static const QPID_COMMON_EXTERN std::string contentType;
+ static void encode(const ObjectType&, std::string&);
+ static void decode(const std::string&, ObjectType&);
+ static size_t encodedSize(const ObjectType&);
+ static const std::string contentType;
private:
};
@@ -49,14 +49,14 @@ class QPID_COMMON_CLASS_EXTERN MapCodec
* Codec for encoding/decoding a list of Variants using the AMQP 0-10
* list encoding.
*/
-class QPID_COMMON_CLASS_EXTERN ListCodec
+class QPID_COMMON_EXTERN ListCodec
{
public:
typedef qpid::types::Variant::List ObjectType;
- static void QPID_COMMON_EXTERN encode(const ObjectType&, std::string&);
- static void QPID_COMMON_EXTERN decode(const std::string&, ObjectType&);
- static size_t QPID_COMMON_EXTERN encodedSize(const ObjectType&);
- static const QPID_COMMON_EXTERN std::string contentType;
+ static void encode(const ObjectType&, std::string&);
+ static void decode(const std::string&, ObjectType&);
+ static size_t encodedSize(const ObjectType&);
+ static const std::string contentType;
private:
};
diff --git a/cpp/include/qpid/client/ClientImportExport.h b/cpp/include/qpid/client/ClientImportExport.h
index 2a3a5a52e9..42b02e33c3 100644
--- a/cpp/include/qpid/client/ClientImportExport.h
+++ b/cpp/include/qpid/client/ClientImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
#if defined(CLIENT_EXPORT) || defined (qpidclient_EXPORTS)
-# define QPID_CLIENT_EXTERN QPID_EXPORT
-# define QPID_CLIENT_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QPID_CLIENT_INLINE_EXTERN QPID_INLINE_EXPORT
+#define QPID_CLIENT_EXTERN __declspec(dllexport)
+#else
+#define QPID_CLIENT_EXTERN __declspec(dllimport)
+#endif
#else
-# define QPID_CLIENT_EXTERN QPID_IMPORT
-# define QPID_CLIENT_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QPID_CLIENT_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QPID_CLIENT_EXTERN
#endif
#endif
diff --git a/cpp/include/qpid/client/Completion.h b/cpp/include/qpid/client/Completion.h
index 9546db9258..99d940f031 100644
--- a/cpp/include/qpid/client/Completion.h
+++ b/cpp/include/qpid/client/Completion.h
@@ -41,7 +41,7 @@ template <class T> class PrivateImplRef;
*
*\ingroup clientapi
*/
-class QPID_CLIENT_CLASS_EXTERN Completion : public Handle<CompletionImpl>
+class Completion : public Handle<CompletionImpl>
{
public:
QPID_CLIENT_EXTERN Completion(CompletionImpl* = 0);
diff --git a/cpp/include/qpid/client/Connection.h b/cpp/include/qpid/client/Connection.h
index c0db0f301d..6ed0d98bc0 100644
--- a/cpp/include/qpid/client/Connection.h
+++ b/cpp/include/qpid/client/Connection.h
@@ -60,7 +60,7 @@ class ConnectionImpl;
*
*/
-class QPID_CLIENT_CLASS_EXTERN Connection
+class Connection
{
framing::ProtocolVersion version;
@@ -102,8 +102,8 @@ class QPID_CLIENT_CLASS_EXTERN Connection
* within a single broker).
*/
QPID_CLIENT_EXTERN void open(const std::string& host, int port = 5672,
- const std::string& uid = "",
- const std::string& pwd = "",
+ const std::string& uid = "guest",
+ const std::string& pwd = "guest",
const std::string& virtualhost = "/", uint16_t maxFrameSize=65535);
/**
@@ -124,8 +124,8 @@ class QPID_CLIENT_CLASS_EXTERN Connection
* within a single broker).
*/
QPID_CLIENT_EXTERN void open(const Url& url,
- const std::string& uid = "",
- const std::string& pwd = "",
+ const std::string& uid = "guest",
+ const std::string& pwd = "guest",
const std::string& virtualhost = "/", uint16_t maxFrameSize=65535);
/**
diff --git a/cpp/include/qpid/client/ConnectionSettings.h b/cpp/include/qpid/client/ConnectionSettings.h
index 2b6b86f891..1c2ee28b1b 100644
--- a/cpp/include/qpid/client/ConnectionSettings.h
+++ b/cpp/include/qpid/client/ConnectionSettings.h
@@ -37,7 +37,7 @@ namespace client {
/**
* Settings for a Connection.
*/
-struct QPID_CLIENT_CLASS_EXTERN ConnectionSettings {
+struct ConnectionSettings {
QPID_CLIENT_EXTERN ConnectionSettings();
QPID_CLIENT_EXTERN virtual ~ConnectionSettings();
diff --git a/cpp/include/qpid/client/FailoverListener.h b/cpp/include/qpid/client/FailoverListener.h
index 53c7c26211..59108eb7cb 100644
--- a/cpp/include/qpid/client/FailoverListener.h
+++ b/cpp/include/qpid/client/FailoverListener.h
@@ -48,7 +48,7 @@ namespace client {
* FailoverListener::decode to extract a list of broker URLs from a
* failover exchange message.
*/
-class QPID_CLIENT_CLASS_EXTERN FailoverListener : private MessageListener, private qpid::sys::Runnable
+class FailoverListener : private MessageListener, private qpid::sys::Runnable
{
public:
/** The name of the standard failover exchange amq.failover */
diff --git a/cpp/include/qpid/client/FailoverManager.h b/cpp/include/qpid/client/FailoverManager.h
index d3a0dbc976..0d30e2ed60 100644
--- a/cpp/include/qpid/client/FailoverManager.h
+++ b/cpp/include/qpid/client/FailoverManager.h
@@ -42,7 +42,7 @@ struct CannotConnectException : qpid::Exception
/**
* Utility to manage failover.
*/
-class QPID_CLIENT_CLASS_EXTERN FailoverManager
+class FailoverManager
{
public:
/**
diff --git a/cpp/include/qpid/client/Future.h b/cpp/include/qpid/client/Future.h
index 630a7e03c0..09088e68f6 100644
--- a/cpp/include/qpid/client/Future.h
+++ b/cpp/include/qpid/client/Future.h
@@ -34,7 +34,7 @@ namespace qpid {
namespace client {
/**@internal */
-class QPID_CLIENT_CLASS_EXTERN Future
+class Future
{
framing::SequenceNumber command;
boost::shared_ptr<FutureResult> result;
diff --git a/cpp/include/qpid/client/FutureResult.h b/cpp/include/qpid/client/FutureResult.h
index ead4929571..b2b663daa1 100644
--- a/cpp/include/qpid/client/FutureResult.h
+++ b/cpp/include/qpid/client/FutureResult.h
@@ -34,7 +34,7 @@ namespace client {
class SessionImpl;
///@internal
-class QPID_CLIENT_CLASS_EXTERN FutureResult : public FutureCompletion
+class FutureResult : public FutureCompletion
{
std::string result;
public:
diff --git a/cpp/include/qpid/client/Handle.h b/cpp/include/qpid/client/Handle.h
index b8315481a9..088e836fcf 100644
--- a/cpp/include/qpid/client/Handle.h
+++ b/cpp/include/qpid/client/Handle.h
@@ -40,22 +40,22 @@ template <class T> class Handle {
public:
/**@return true if handle is valid, i.e. not null. */
- QPID_CLIENT_INLINE_EXTERN bool isValid() const { return impl; }
+ QPID_CLIENT_EXTERN bool isValid() const { return impl; }
/**@return true if handle is null. It is an error to call any function on a null handle. */
- QPID_CLIENT_INLINE_EXTERN bool isNull() const { return !impl; }
+ QPID_CLIENT_EXTERN bool isNull() const { return !impl; }
/** Conversion to bool supports idiom if (handle) { handle->... } */
- QPID_CLIENT_INLINE_EXTERN operator bool() const { return impl; }
+ QPID_CLIENT_EXTERN operator bool() const { return impl; }
/** Operator ! supports idiom if (!handle) { do_if_handle_is_null(); } */
- QPID_CLIENT_INLINE_EXTERN bool operator !() const { return !impl; }
+ QPID_CLIENT_EXTERN bool operator !() const { return !impl; }
void swap(Handle<T>& h) { T* t = h.impl; h.impl = impl; impl = t; }
protected:
typedef T Impl;
- QPID_CLIENT_INLINE_EXTERN Handle() :impl() {}
+ QPID_CLIENT_EXTERN Handle() :impl() {}
// Not implemented,subclasses must implement.
QPID_CLIENT_EXTERN Handle(const Handle&);
diff --git a/cpp/include/qpid/client/LocalQueue.h b/cpp/include/qpid/client/LocalQueue.h
index 1a19a8499d..70e4cebcf1 100644
--- a/cpp/include/qpid/client/LocalQueue.h
+++ b/cpp/include/qpid/client/LocalQueue.h
@@ -71,7 +71,7 @@ template <class T> class PrivateImplRef;
* </ul>
*/
-class QPID_CLIENT_CLASS_EXTERN LocalQueue : public Handle<LocalQueueImpl> {
+class LocalQueue : public Handle<LocalQueueImpl> {
public:
/** Create a local queue. Subscribe the local queue to a remote broker
* queue with a SubscriptionManager.
diff --git a/cpp/include/qpid/client/Message.h b/cpp/include/qpid/client/Message.h
index ba50dda9ba..2401cbdc92 100644
--- a/cpp/include/qpid/client/Message.h
+++ b/cpp/include/qpid/client/Message.h
@@ -112,7 +112,7 @@ class MessageImpl;
*
*
*/
-class QPID_CLIENT_CLASS_EXTERN Message
+class Message
{
public:
/** Create a Message.
diff --git a/cpp/include/qpid/client/MessageListener.h b/cpp/include/qpid/client/MessageListener.h
index 3ca2fa964a..d200f8cf21 100644
--- a/cpp/include/qpid/client/MessageListener.h
+++ b/cpp/include/qpid/client/MessageListener.h
@@ -84,7 +84,7 @@ namespace client {
*
*/
- class QPID_CLIENT_CLASS_EXTERN MessageListener{
+ class MessageListener{
public:
QPID_CLIENT_EXTERN virtual ~MessageListener();
diff --git a/cpp/include/qpid/client/MessageReplayTracker.h b/cpp/include/qpid/client/MessageReplayTracker.h
index 06a3f29c7d..6f5a0f4ac3 100644
--- a/cpp/include/qpid/client/MessageReplayTracker.h
+++ b/cpp/include/qpid/client/MessageReplayTracker.h
@@ -34,7 +34,7 @@ namespace client {
* Utility to track messages sent asynchronously, allowing those that
* are indoubt to be replayed over a new session.
*/
-class QPID_CLIENT_CLASS_EXTERN MessageReplayTracker
+class MessageReplayTracker
{
public:
QPID_CLIENT_EXTERN MessageReplayTracker(uint flushInterval);
diff --git a/cpp/include/qpid/client/QueueOptions.h b/cpp/include/qpid/client/QueueOptions.h
index 3984b63fdd..f8a4963f06 100644
--- a/cpp/include/qpid/client/QueueOptions.h
+++ b/cpp/include/qpid/client/QueueOptions.h
@@ -35,7 +35,7 @@ enum QueueOrderingPolicy {FIFO, LVQ, LVQ_NO_BROWSE};
* A help class to set options on the Queue. Create a configured args while
* still allowing any custom configuration via the FieldTable base class
*/
-class QPID_CLIENT_CLASS_EXTERN QueueOptions: public framing::FieldTable
+class QueueOptions: public framing::FieldTable
{
public:
QPID_CLIENT_EXTERN QueueOptions();
diff --git a/cpp/include/qpid/client/SessionBase_0_10.h b/cpp/include/qpid/client/SessionBase_0_10.h
index ea50ab32f7..3b5c84e74b 100644
--- a/cpp/include/qpid/client/SessionBase_0_10.h
+++ b/cpp/include/qpid/client/SessionBase_0_10.h
@@ -54,7 +54,7 @@ enum CreditUnit { MESSAGE_CREDIT=0, BYTE_CREDIT=1, UNLIMITED_CREDIT=0xFFFFFFFF }
* Subclasses provide the AMQP commands for a given
* version of the protocol.
*/
-class QPID_CLIENT_CLASS_EXTERN SessionBase_0_10 {
+class SessionBase_0_10 {
public:
///@internal
diff --git a/cpp/include/qpid/client/Subscription.h b/cpp/include/qpid/client/Subscription.h
index bb9b98e8ff..425b6b92e2 100644
--- a/cpp/include/qpid/client/Subscription.h
+++ b/cpp/include/qpid/client/Subscription.h
@@ -39,7 +39,7 @@ class SubscriptionManager;
* A handle to an active subscription. Provides methods to query the subscription status
* and control acknowledgement (acquire and accept) of messages.
*/
-class QPID_CLIENT_CLASS_EXTERN Subscription : public Handle<SubscriptionImpl> {
+class Subscription : public Handle<SubscriptionImpl> {
public:
QPID_CLIENT_EXTERN Subscription(SubscriptionImpl* = 0);
QPID_CLIENT_EXTERN Subscription(const Subscription&);
@@ -91,13 +91,13 @@ class QPID_CLIENT_CLASS_EXTERN Subscription : public Handle<SubscriptionImpl> {
QPID_CLIENT_EXTERN void release(const SequenceSet& messageIds);
/* Acquire a single message */
- QPID_CLIENT_INLINE_EXTERN void acquire(const Message& m) { acquire(SequenceSet(m.getId())); }
+ QPID_CLIENT_EXTERN void acquire(const Message& m) { acquire(SequenceSet(m.getId())); }
/* Accept a single message */
- QPID_CLIENT_INLINE_EXTERN void accept(const Message& m) { accept(SequenceSet(m.getId())); }
+ QPID_CLIENT_EXTERN void accept(const Message& m) { accept(SequenceSet(m.getId())); }
/* Release a single message */
- QPID_CLIENT_INLINE_EXTERN void release(const Message& m) { release(SequenceSet(m.getId())); }
+ QPID_CLIENT_EXTERN void release(const Message& m) { release(SequenceSet(m.getId())); }
/** Get the session associated with this subscription */
QPID_CLIENT_EXTERN Session getSession() const;
diff --git a/cpp/include/qpid/client/SubscriptionManager.h b/cpp/include/qpid/client/SubscriptionManager.h
index b69819a8ff..e70e05f73a 100644
--- a/cpp/include/qpid/client/SubscriptionManager.h
+++ b/cpp/include/qpid/client/SubscriptionManager.h
@@ -94,7 +94,7 @@ class SubscriptionManagerImpl;
* </ul>
*
*/
-class QPID_CLIENT_CLASS_EXTERN SubscriptionManager : public sys::Runnable, public Handle<SubscriptionManagerImpl>
+class SubscriptionManager : public sys::Runnable, public Handle<SubscriptionManagerImpl>
{
public:
/** Create a new SubscriptionManager associated with a session */
diff --git a/cpp/include/qpid/console/Agent.h b/cpp/include/qpid/console/Agent.h
index 629dd71dee..97d75da250 100644
--- a/cpp/include/qpid/console/Agent.h
+++ b/cpp/include/qpid/console/Agent.h
@@ -31,17 +31,17 @@ namespace console {
*
* \ingroup qmfconsoleapi
*/
- class QPID_CONSOLE_CLASS_EXTERN Agent {
+ class QPID_CONSOLE_EXTERN Agent {
public:
typedef std::vector<Agent*> Vector;
- QPID_CONSOLE_INLINE_EXTERN Agent(Broker* _broker, uint32_t _bank, const std::string& _label) :
+ Agent(Broker* _broker, uint32_t _bank, const std::string& _label) :
broker(_broker), brokerBank(broker->getBrokerBank()),
agentBank(_bank), label(_label) {}
- QPID_CONSOLE_INLINE_EXTERN Broker* getBroker() const { return broker; }
- QPID_CONSOLE_INLINE_EXTERN uint32_t getBrokerBank() const { return brokerBank; }
- QPID_CONSOLE_INLINE_EXTERN uint32_t getAgentBank() const { return agentBank; }
- QPID_CONSOLE_INLINE_EXTERN const std::string& getLabel() const { return label; }
+ Broker* getBroker() const { return broker; }
+ uint32_t getBrokerBank() const { return brokerBank; }
+ uint32_t getAgentBank() const { return agentBank; }
+ const std::string& getLabel() const { return label; }
private:
Broker* broker;
@@ -50,7 +50,7 @@ namespace console {
const std::string label;
};
- std::ostream& operator<<(std::ostream& o, const Agent& agent);
+ QPID_CONSOLE_EXTERN std::ostream& operator<<(std::ostream& o, const Agent& agent);
}
}
diff --git a/cpp/include/qpid/console/Broker.h b/cpp/include/qpid/console/Broker.h
index c2ba8ac81f..0b2d1bcb61 100644
--- a/cpp/include/qpid/console/Broker.h
+++ b/cpp/include/qpid/console/Broker.h
@@ -55,12 +55,12 @@ namespace console {
client::ConnectionSettings& settings);
QPID_CONSOLE_EXTERN ~Broker();
- QPID_CONSOLE_INLINE_EXTERN bool isConnected() const { return connected; }
- QPID_CONSOLE_INLINE_EXTERN const std::string& getError() const { return error; }
- QPID_CONSOLE_INLINE_EXTERN const std::string& getSessionId() const { return amqpSessionId; }
- QPID_CONSOLE_INLINE_EXTERN const framing::Uuid& getBrokerId() const { return brokerId; }
- QPID_CONSOLE_INLINE_EXTERN uint32_t getBrokerBank() const { return 1; }
- QPID_CONSOLE_INLINE_EXTERN void addBinding(const std::string& key) {
+ QPID_CONSOLE_EXTERN bool isConnected() const { return connected; }
+ QPID_CONSOLE_EXTERN const std::string& getError() const { return error; }
+ QPID_CONSOLE_EXTERN const std::string& getSessionId() const { return amqpSessionId; }
+ QPID_CONSOLE_EXTERN const framing::Uuid& getBrokerId() const { return brokerId; }
+ QPID_CONSOLE_EXTERN uint32_t getBrokerBank() const { return 1; }
+ QPID_CONSOLE_EXTERN void addBinding(const std::string& key) {
connThreadBody.bindExchange("qpid.management", key);
}
QPID_CONSOLE_EXTERN std::string getUrl() const;
@@ -123,10 +123,10 @@ namespace console {
void setBrokerId(const framing::Uuid& id) { brokerId = id; }
void appendAgents(std::vector<Agent*>& agents) const;
- friend std::ostream& operator<<(std::ostream& o, const Broker& k);
+ friend QPID_CONSOLE_EXTERN std::ostream& operator<<(std::ostream& o, const Broker& k);
};
- std::ostream& operator<<(std::ostream& o, const Broker& k);
+ QPID_CONSOLE_EXTERN std::ostream& operator<<(std::ostream& o, const Broker& k);
}
}
diff --git a/cpp/include/qpid/console/ClassKey.h b/cpp/include/qpid/console/ClassKey.h
index 5f7c50351a..95cd2627f1 100644
--- a/cpp/include/qpid/console/ClassKey.h
+++ b/cpp/include/qpid/console/ClassKey.h
@@ -33,24 +33,24 @@ namespace console {
*
* \ingroup qmfconsoleapi
*/
- class QPID_CONSOLE_CLASS_EXTERN ClassKey {
+ class QPID_CONSOLE_EXTERN ClassKey {
public:
- QPID_CONSOLE_EXTERN static const int HASH_SIZE = 16;
+ static const int HASH_SIZE = 16;
- QPID_CONSOLE_EXTERN ClassKey(const std::string& package, const std::string& name, const uint8_t* hash);
+ ClassKey(const std::string& package, const std::string& name, const uint8_t* hash);
- const QPID_CONSOLE_EXTERN std::string& getPackageName() const { return package; }
- const QPID_CONSOLE_EXTERN std::string& getClassName() const { return name; }
- const QPID_CONSOLE_EXTERN uint8_t* getHash() const { return hash; }
- QPID_CONSOLE_EXTERN std::string getHashString() const;
- QPID_CONSOLE_EXTERN std::string str() const;
- QPID_CONSOLE_EXTERN bool operator==(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN bool operator!=(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN bool operator<(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN bool operator>(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN bool operator<=(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN bool operator>=(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN void encode(framing::Buffer& buffer) const;
+ const std::string& getPackageName() const { return package; }
+ const std::string& getClassName() const { return name; }
+ const uint8_t* getHash() const { return hash; }
+ std::string getHashString() const;
+ std::string str() const;
+ bool operator==(const ClassKey& other) const;
+ bool operator!=(const ClassKey& other) const;
+ bool operator<(const ClassKey& other) const;
+ bool operator>(const ClassKey& other) const;
+ bool operator<=(const ClassKey& other) const;
+ bool operator>=(const ClassKey& other) const;
+ void encode(framing::Buffer& buffer) const;
private:
std::string package;
diff --git a/cpp/include/qpid/console/ConsoleImportExport.h b/cpp/include/qpid/console/ConsoleImportExport.h
index aac30858f7..c2d7cb3a14 100644
--- a/cpp/include/qpid/console/ConsoleImportExport.h
+++ b/cpp/include/qpid/console/ConsoleImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
#if defined(CONSOLE_EXPORT) || defined (qmfconsole_EXPORTS)
-# define QPID_CONSOLE_EXTERN QPID_EXPORT
-# define QPID_CONSOLE_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QPID_CONSOLE_INLINE_EXTERN QPID_INLINE_EXPORT
+#define QPID_CONSOLE_EXTERN __declspec(dllexport)
+#else
+#define QPID_CONSOLE_EXTERN __declspec(dllimport)
+#endif
#else
-# define QPID_CONSOLE_EXTERN QPID_IMPORT
-# define QPID_CONSOLE_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QPID_CONSOLE_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QPID_CONSOLE_EXTERN
#endif
#endif
diff --git a/cpp/include/qpid/console/ObjectId.h b/cpp/include/qpid/console/ObjectId.h
index 0722eaebeb..7904c85598 100644
--- a/cpp/include/qpid/console/ObjectId.h
+++ b/cpp/include/qpid/console/ObjectId.h
@@ -40,10 +40,10 @@ namespace console {
ObjectId() : first(0), second(0) {}
ObjectId(framing::Buffer& buffer);
- uint8_t getFlags() const { return (uint8_t)((first & 0xF000000000000000LL) >> 60); }
- uint16_t getSequence() const { return (uint16_t)((first & 0x0FFF000000000000LL) >> 48); }
- uint32_t getBrokerBank() const { return (uint32_t)((first & 0x0000FFFFF0000000LL) >> 28); }
- uint32_t getAgentBank() const { return (uint32_t) (first & 0x000000000FFFFFFFLL); }
+ uint8_t getFlags() const { return (first & 0xF000000000000000LL) >> 60; }
+ uint16_t getSequence() const { return (first & 0x0FFF000000000000LL) >> 48; }
+ uint32_t getBrokerBank() const { return (first & 0x0000FFFFF0000000LL) >> 28; }
+ uint32_t getAgentBank() const { return first & 0x000000000FFFFFFFLL; }
uint64_t getObject() const { return second; }
bool isDurable() const { return getSequence() == 0; }
void decode(framing::Buffer& buffer);
diff --git a/cpp/include/qpid/framing/Array.h b/cpp/include/qpid/framing/Array.h
index 1e97be3bb4..d3bdd36aa6 100644
--- a/cpp/include/qpid/framing/Array.h
+++ b/cpp/include/qpid/framing/Array.h
@@ -34,7 +34,7 @@ namespace framing {
class Buffer;
-class QPID_COMMON_CLASS_EXTERN Array
+class Array
{
public:
typedef boost::shared_ptr<FieldValue> ValuePtr;
@@ -55,25 +55,25 @@ class QPID_COMMON_CLASS_EXTERN Array
//creates a longstr array
QPID_COMMON_EXTERN Array(const std::vector<std::string>& in);
- QPID_COMMON_INLINE_EXTERN TypeCode getType() const { return type; }
+ QPID_COMMON_EXTERN TypeCode getType() const { return type; }
// std collection interface.
- QPID_COMMON_INLINE_EXTERN const_iterator begin() const { return values.begin(); }
- QPID_COMMON_INLINE_EXTERN const_iterator end() const { return values.end(); }
- QPID_COMMON_INLINE_EXTERN iterator begin() { return values.begin(); }
- QPID_COMMON_INLINE_EXTERN iterator end(){ return values.end(); }
+ QPID_COMMON_EXTERN const_iterator begin() const { return values.begin(); }
+ QPID_COMMON_EXTERN const_iterator end() const { return values.end(); }
+ QPID_COMMON_EXTERN iterator begin() { return values.begin(); }
+ QPID_COMMON_EXTERN iterator end(){ return values.end(); }
- QPID_COMMON_INLINE_EXTERN ValuePtr front() const { return values.front(); }
- QPID_COMMON_INLINE_EXTERN ValuePtr back() const { return values.back(); }
- QPID_COMMON_INLINE_EXTERN size_t size() const { return values.size(); }
+ QPID_COMMON_EXTERN ValuePtr front() const { return values.front(); }
+ QPID_COMMON_EXTERN ValuePtr back() const { return values.back(); }
+ QPID_COMMON_EXTERN size_t size() const { return values.size(); }
QPID_COMMON_EXTERN void insert(iterator i, ValuePtr value);
- QPID_COMMON_INLINE_EXTERN void erase(iterator i) { values.erase(i); }
- QPID_COMMON_INLINE_EXTERN void push_back(ValuePtr value) { values.insert(end(), value); }
- QPID_COMMON_INLINE_EXTERN void pop_back() { values.pop_back(); }
+ QPID_COMMON_EXTERN void erase(iterator i) { values.erase(i); }
+ QPID_COMMON_EXTERN void push_back(ValuePtr value) { values.insert(end(), value); }
+ QPID_COMMON_EXTERN void pop_back() { values.pop_back(); }
// Non-std interface
- QPID_COMMON_INLINE_EXTERN void add(ValuePtr value) { push_back(value); }
+ QPID_COMMON_EXTERN void add(ValuePtr value) { push_back(value); }
template <class T>
void collect(std::vector<T>& out) const
diff --git a/cpp/include/qpid/framing/Buffer.h b/cpp/include/qpid/framing/Buffer.h
index 8b08e60762..04583433c5 100644
--- a/cpp/include/qpid/framing/Buffer.h
+++ b/cpp/include/qpid/framing/Buffer.h
@@ -29,14 +29,14 @@
namespace qpid {
namespace framing {
-struct QPID_COMMON_CLASS_EXTERN OutOfBounds : qpid::Exception {
+struct OutOfBounds : qpid::Exception {
OutOfBounds() : qpid::Exception(std::string("Out of Bounds")) {}
};
class Content;
class FieldTable;
-class QPID_COMMON_CLASS_EXTERN Buffer
+class Buffer
{
uint32_t size;
char* data;
@@ -72,12 +72,12 @@ class QPID_COMMON_CLASS_EXTERN Buffer
QPID_COMMON_EXTERN void restore(bool reRecord = false);
QPID_COMMON_EXTERN void reset();
- QPID_COMMON_INLINE_EXTERN uint32_t available() { return size - position; }
- QPID_COMMON_INLINE_EXTERN uint32_t getSize() { return size; }
- QPID_COMMON_INLINE_EXTERN uint32_t getPosition() { return position; }
- QPID_COMMON_INLINE_EXTERN void setPosition(uint32_t p) { position = p; }
- QPID_COMMON_INLINE_EXTERN Iterator getIterator() { return Iterator(*this); }
- QPID_COMMON_INLINE_EXTERN char* getPointer() { return data; }
+ QPID_COMMON_EXTERN uint32_t available() { return size - position; }
+ QPID_COMMON_EXTERN uint32_t getSize() { return size; }
+ QPID_COMMON_EXTERN uint32_t getPosition() { return position; }
+ QPID_COMMON_EXTERN void setPosition(uint32_t p) { position = p; }
+ QPID_COMMON_EXTERN Iterator getIterator() { return Iterator(*this); }
+ QPID_COMMON_EXTERN char* getPointer() { return data; }
QPID_COMMON_EXTERN void putOctet(uint8_t i);
QPID_COMMON_EXTERN void putShort(uint16_t i);
diff --git a/cpp/include/qpid/framing/FieldTable.h b/cpp/include/qpid/framing/FieldTable.h
index bdcef6d7fd..fdb1a28b9d 100644
--- a/cpp/include/qpid/framing/FieldTable.h
+++ b/cpp/include/qpid/framing/FieldTable.h
@@ -56,7 +56,7 @@ class FieldTable
typedef ValueMap::reference reference;
typedef ValueMap::value_type value_type;
- QPID_COMMON_INLINE_EXTERN FieldTable() {};
+ QPID_COMMON_EXTERN FieldTable() {};
QPID_COMMON_EXTERN FieldTable(const FieldTable& ft);
QPID_COMMON_EXTERN ~FieldTable();
QPID_COMMON_EXTERN FieldTable& operator=(const FieldTable& ft);
@@ -65,11 +65,9 @@ class FieldTable
QPID_COMMON_EXTERN void decode(Buffer& buffer);
QPID_COMMON_EXTERN int count() const;
- QPID_COMMON_INLINE_EXTERN size_t size() const { return values.size(); }
- QPID_COMMON_INLINE_EXTERN bool empty() { return size() == 0; }
QPID_COMMON_EXTERN void set(const std::string& name, const ValuePtr& value);
QPID_COMMON_EXTERN ValuePtr get(const std::string& name) const;
- QPID_COMMON_INLINE_EXTERN bool isSet(const std::string& name) const { return get(name).get() != 0; }
+ QPID_COMMON_EXTERN bool isSet(const std::string& name) const { return get(name).get() != 0; }
QPID_COMMON_EXTERN void setString(const std::string& name, const std::string& value);
QPID_COMMON_EXTERN void setInt(const std::string& name, const int value);
diff --git a/cpp/include/qpid/framing/FieldValue.h b/cpp/include/qpid/framing/FieldValue.h
index 458de62fdf..19220e74d5 100644
--- a/cpp/include/qpid/framing/FieldValue.h
+++ b/cpp/include/qpid/framing/FieldValue.h
@@ -41,14 +41,14 @@ namespace framing {
*
* \ingroup clientapi
*/
-class QPID_COMMON_CLASS_EXTERN FieldValueException : public qpid::Exception {};
+class FieldValueException : public qpid::Exception {};
/**
* Exception thrown when we can't perform requested conversion
*
* \ingroup clientapi
*/
-struct QPID_COMMON_CLASS_EXTERN InvalidConversionException : public FieldValueException {
+struct InvalidConversionException : public FieldValueException {
InvalidConversionException() {}
};
@@ -59,7 +59,7 @@ class List;
*
* \ingroup clientapi
*/
-class QPID_COMMON_CLASS_EXTERN FieldValue {
+class FieldValue {
public:
/*
* Abstract type for content of different types
@@ -90,7 +90,7 @@ class QPID_COMMON_CLASS_EXTERN FieldValue {
void encode(Buffer& buffer);
void decode(Buffer& buffer);
QPID_COMMON_EXTERN bool operator==(const FieldValue&) const;
- QPID_COMMON_INLINE_EXTERN bool operator!=(const FieldValue& v) const { return !(*this == v); }
+ QPID_COMMON_EXTERN bool operator!=(const FieldValue& v) const { return !(*this == v); }
QPID_COMMON_EXTERN void print(std::ostream& out) const;
@@ -98,7 +98,6 @@ class QPID_COMMON_CLASS_EXTERN FieldValue {
template <typename T> T get() const { throw InvalidConversionException(); }
template <class T, int W> T getIntegerValue() const;
- template <class T> T getIntegerValue() const;
template <class T, int W> T getFloatingPointValue() const;
template <int W> void getFixedWidthValue(unsigned char*) const;
template <class T> bool get(T&) const;
@@ -197,18 +196,6 @@ inline T FieldValue::getIntegerValue() const
}
}
-template <class T>
-inline T FieldValue::getIntegerValue() const
-{
- FixedWidthValue<1>* const fwv = dynamic_cast< FixedWidthValue<1>* const>(data.get());
- if (fwv) {
- uint8_t* octets = fwv->rawOctets();
- return octets[0];
- } else {
- throw InvalidConversionException();
- }
-}
-
template <class T, int W>
inline T FieldValue::getFloatingPointValue() const {
FixedWidthValue<W>* const fwv = dynamic_cast< FixedWidthValue<W>* const>(data.get());
diff --git a/cpp/include/qpid/framing/List.h b/cpp/include/qpid/framing/List.h
index 681445947c..0f17c7884c 100644
--- a/cpp/include/qpid/framing/List.h
+++ b/cpp/include/qpid/framing/List.h
@@ -36,11 +36,10 @@ class FieldValue;
/**
* Representation of an AMQP 0-10 list
*/
-class QPID_COMMON_CLASS_EXTERN List
+class List
{
public:
typedef boost::shared_ptr<FieldValue> ValuePtr;
- typedef ValuePtr value_type;
typedef std::list<ValuePtr> Values;
typedef Values::const_iterator const_iterator;
typedef Values::iterator iterator;
@@ -54,19 +53,19 @@ class QPID_COMMON_CLASS_EXTERN List
QPID_COMMON_EXTERN bool operator==(const List& other) const;
// std collection interface.
- QPID_COMMON_INLINE_EXTERN const_iterator begin() const { return values.begin(); }
- QPID_COMMON_INLINE_EXTERN const_iterator end() const { return values.end(); }
- QPID_COMMON_INLINE_EXTERN iterator begin() { return values.begin(); }
- QPID_COMMON_INLINE_EXTERN iterator end(){ return values.end(); }
+ QPID_COMMON_EXTERN const_iterator begin() const { return values.begin(); }
+ QPID_COMMON_EXTERN const_iterator end() const { return values.end(); }
+ QPID_COMMON_EXTERN iterator begin() { return values.begin(); }
+ QPID_COMMON_EXTERN iterator end(){ return values.end(); }
- QPID_COMMON_INLINE_EXTERN ValuePtr front() const { return values.front(); }
- QPID_COMMON_INLINE_EXTERN ValuePtr back() const { return values.back(); }
- QPID_COMMON_INLINE_EXTERN size_t size() const { return values.size(); }
+ QPID_COMMON_EXTERN ValuePtr front() const { return values.front(); }
+ QPID_COMMON_EXTERN ValuePtr back() const { return values.back(); }
+ QPID_COMMON_EXTERN size_t size() const { return values.size(); }
- QPID_COMMON_INLINE_EXTERN iterator insert(iterator i, ValuePtr value) { return values.insert(i, value); }
- QPID_COMMON_INLINE_EXTERN void erase(iterator i) { values.erase(i); }
- QPID_COMMON_INLINE_EXTERN void push_back(ValuePtr value) { values.insert(end(), value); }
- QPID_COMMON_INLINE_EXTERN void pop_back() { values.pop_back(); }
+ QPID_COMMON_EXTERN iterator insert(iterator i, ValuePtr value) { return values.insert(i, value); }
+ QPID_COMMON_EXTERN void erase(iterator i) { values.erase(i); }
+ QPID_COMMON_EXTERN void push_back(ValuePtr value) { values.insert(end(), value); }
+ QPID_COMMON_EXTERN void pop_back() { values.pop_back(); }
private:
Values values;
diff --git a/cpp/include/qpid/framing/ProtocolVersion.h b/cpp/include/qpid/framing/ProtocolVersion.h
index 30094c165d..e7e75d75f6 100644
--- a/cpp/include/qpid/framing/ProtocolVersion.h
+++ b/cpp/include/qpid/framing/ProtocolVersion.h
@@ -29,7 +29,7 @@ namespace qpid
namespace framing
{
-class QPID_COMMON_CLASS_EXTERN ProtocolVersion
+class ProtocolVersion
{
private:
uint8_t major_;
@@ -39,16 +39,16 @@ public:
explicit ProtocolVersion(uint8_t _major=0, uint8_t _minor=0)
: major_(_major), minor_(_minor) {}
- QPID_COMMON_INLINE_EXTERN uint8_t getMajor() const { return major_; }
- QPID_COMMON_INLINE_EXTERN void setMajor(uint8_t major) { major_ = major; }
- QPID_COMMON_INLINE_EXTERN uint8_t getMinor() const { return minor_; }
- QPID_COMMON_INLINE_EXTERN void setMinor(uint8_t minor) { minor_ = minor; }
+ QPID_COMMON_EXTERN uint8_t getMajor() const { return major_; }
+ QPID_COMMON_EXTERN void setMajor(uint8_t major) { major_ = major; }
+ QPID_COMMON_EXTERN uint8_t getMinor() const { return minor_; }
+ QPID_COMMON_EXTERN void setMinor(uint8_t minor) { minor_ = minor; }
QPID_COMMON_EXTERN const std::string toString() const;
QPID_COMMON_EXTERN ProtocolVersion& operator=(ProtocolVersion p);
QPID_COMMON_EXTERN bool operator==(ProtocolVersion p) const;
- QPID_COMMON_INLINE_EXTERN bool operator!=(ProtocolVersion p) const { return ! (*this == p); }
+ QPID_COMMON_EXTERN bool operator!=(ProtocolVersion p) const { return ! (*this == p); }
};
} // namespace framing
diff --git a/cpp/include/qpid/framing/SequenceNumber.h b/cpp/include/qpid/framing/SequenceNumber.h
index eed15a4b75..1e53058df8 100644
--- a/cpp/include/qpid/framing/SequenceNumber.h
+++ b/cpp/include/qpid/framing/SequenceNumber.h
@@ -34,7 +34,7 @@ class Buffer;
/**
* 4-byte sequence number that 'wraps around'.
*/
-class QPID_COMMON_CLASS_EXTERN SequenceNumber : public
+class SequenceNumber : public
boost::equality_comparable<
SequenceNumber, boost::less_than_comparable<
SequenceNumber, boost::incrementable<
diff --git a/cpp/include/qpid/framing/SequenceSet.h b/cpp/include/qpid/framing/SequenceSet.h
index 0a78e418ba..39395e9ad7 100644
--- a/cpp/include/qpid/framing/SequenceSet.h
+++ b/cpp/include/qpid/framing/SequenceSet.h
@@ -29,7 +29,7 @@ namespace qpid {
namespace framing {
class Buffer;
-class QPID_COMMON_CLASS_EXTERN SequenceSet : public RangeSet<SequenceNumber> {
+class SequenceSet : public RangeSet<SequenceNumber> {
public:
SequenceSet() {}
SequenceSet(const RangeSet<SequenceNumber>& r)
diff --git a/cpp/include/qpid/framing/StructHelper.h b/cpp/include/qpid/framing/StructHelper.h
index 21f9b91fa9..fc9a7909cc 100644
--- a/cpp/include/qpid/framing/StructHelper.h
+++ b/cpp/include/qpid/framing/StructHelper.h
@@ -30,7 +30,7 @@
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN StructHelper
+class StructHelper
{
public:
diff --git a/cpp/include/qpid/framing/Uuid.h b/cpp/include/qpid/framing/Uuid.h
index ccfd7e9534..d0a8d02411 100644
--- a/cpp/include/qpid/framing/Uuid.h
+++ b/cpp/include/qpid/framing/Uuid.h
@@ -52,22 +52,22 @@ struct Uuid : public boost::array<uint8_t, 16> {
// boost::array gives us ==, < etc.
/** Copy from 16 bytes of data. */
- QPID_COMMON_EXTERN void assign(const uint8_t* data);
+ void assign(const uint8_t* data);
/** Set to a new unique identifier. */
QPID_COMMON_EXTERN void generate();
/** Set to all zeros. */
- QPID_COMMON_EXTERN void clear();
+ void clear();
/** Test for null (all zeros). */
QPID_COMMON_EXTERN bool isNull() const;
- QPID_COMMON_INLINE_EXTERN operator bool() const { return !isNull(); }
- QPID_COMMON_INLINE_EXTERN bool operator!() const { return isNull(); }
+ operator bool() const { return !isNull(); }
+ bool operator!() const { return isNull(); }
QPID_COMMON_EXTERN void encode(framing::Buffer& buf) const;
QPID_COMMON_EXTERN void decode(framing::Buffer& buf);
- QPID_COMMON_INLINE_EXTERN uint32_t encodedSize() const
+ QPID_COMMON_EXTERN uint32_t encodedSize() const
{ return static_cast<uint32_t>(size()); }
/** String value in format 1b4e28ba-2fa1-11d2-883f-b9a761bde3fb. */
diff --git a/cpp/include/qpid/log/Logger.h b/cpp/include/qpid/log/Logger.h
index d255b7e150..783ab7bdb9 100644
--- a/cpp/include/qpid/log/Logger.h
+++ b/cpp/include/qpid/log/Logger.h
@@ -33,10 +33,10 @@ namespace log {
* is handled by Logger::Output-derived classes instantiated by the
* platform's sink-related options.
*/
-class QPID_COMMON_CLASS_EXTERN Logger : private boost::noncopyable {
+class Logger : private boost::noncopyable {
public:
/** Flags indicating what to include in the log output */
- enum FormatFlag { FILE=1, LINE=2, FUNCTION=4, LEVEL=8, TIME=16, THREAD=32, HIRES=64};
+ enum FormatFlag { FILE=1, LINE=2, FUNCTION=4, LEVEL=8, TIME=16, THREAD=32};
/**
* Logging output sink.
@@ -93,7 +93,7 @@ class QPID_COMMON_CLASS_EXTERN Logger : private boost::noncopyable {
QPID_COMMON_EXTERN void clear();
/** Get the options used to configure the logger. */
- QPID_COMMON_INLINE_EXTERN const Options& getOptions() const { return options; }
+ QPID_COMMON_EXTERN const Options& getOptions() const { return options; }
private:
diff --git a/cpp/include/qpid/log/Options.h b/cpp/include/qpid/log/Options.h
index 17cbfde9bc..bbc47b47d3 100644
--- a/cpp/include/qpid/log/Options.h
+++ b/cpp/include/qpid/log/Options.h
@@ -39,7 +39,7 @@ struct Options : public qpid::Options {
std::string argv0;
std::string name;
std::vector<std::string> selectors;
- bool time, level, thread, source, function, hiresTs;
+ bool time, level, thread, source, function;
bool trace;
std::string prefix;
std::auto_ptr<SinkOptions> sinkOptions;
diff --git a/cpp/include/qpid/management/ManagementObject.h b/cpp/include/qpid/management/ManagementObject.h
index 16bf21038c..747edda150 100644
--- a/cpp/include/qpid/management/ManagementObject.h
+++ b/cpp/include/qpid/management/ManagementObject.h
@@ -58,14 +58,14 @@ protected:
std::string agentName;
void fromString(const std::string&);
public:
- QPID_COMMON_INLINE_EXTERN ObjectId() : agent(0), first(0), second(0), agentEpoch(0) {}
- QPID_COMMON_INLINE_EXTERN ObjectId(const types::Variant& map) :
+ QPID_COMMON_EXTERN ObjectId() : agent(0), first(0), second(0), agentEpoch(0) {}
+ QPID_COMMON_EXTERN ObjectId(const types::Variant& map) :
agent(0), first(0), second(0), agentEpoch(0) { mapDecode(map.asMap()); }
QPID_COMMON_EXTERN ObjectId(uint8_t flags, uint16_t seq, uint32_t broker);
QPID_COMMON_EXTERN ObjectId(AgentAttachment* _agent, uint8_t flags, uint16_t seq);
QPID_COMMON_EXTERN ObjectId(std::istream&);
QPID_COMMON_EXTERN ObjectId(const std::string&);
- QPID_COMMON_INLINE_EXTERN ObjectId(const std::string& agentAddress, const std::string& key,
+ QPID_COMMON_EXTERN ObjectId(const std::string& agentAddress, const std::string& key,
uint64_t epoch=0) : agent(0), first(0), second(0),
agentEpoch(epoch), v2Key(key), agentName(agentAddress) {}
@@ -76,15 +76,15 @@ public:
QPID_COMMON_EXTERN void mapEncode(types::Variant::Map& map) const;
QPID_COMMON_EXTERN void mapDecode(const types::Variant::Map& map);
QPID_COMMON_EXTERN operator types::Variant::Map() const;
- QPID_COMMON_INLINE_EXTERN uint32_t encodedSize() const { return 16; };
+ QPID_COMMON_EXTERN uint32_t encodedSize() const { return 16; };
QPID_COMMON_EXTERN void encode(std::string& buffer) const;
QPID_COMMON_EXTERN void decode(const std::string& buffer);
QPID_COMMON_EXTERN bool equalV1(const ObjectId &other) const;
- QPID_COMMON_INLINE_EXTERN void setV2Key(const std::string& _key) { v2Key = _key; }
+ QPID_COMMON_EXTERN void setV2Key(const std::string& _key) { v2Key = _key; }
QPID_COMMON_EXTERN void setV2Key(const ManagementObject& object);
- QPID_COMMON_INLINE_EXTERN void setAgentName(const std::string& _name) { agentName = _name; }
- QPID_COMMON_INLINE_EXTERN const std::string& getAgentName() const { return agentName; }
- QPID_COMMON_INLINE_EXTERN const std::string& getV2Key() const { return v2Key; }
+ QPID_COMMON_EXTERN void setAgentName(const std::string& _name) { agentName = _name; }
+ QPID_COMMON_EXTERN const std::string& getAgentName() const { return agentName; }
+ QPID_COMMON_EXTERN const std::string& getV2Key() const { return v2Key; }
friend QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const ObjectId&);
};
@@ -131,7 +131,7 @@ public:
virtual ~ManagementItem() {}
};
-class QPID_COMMON_CLASS_EXTERN ManagementObject : public ManagementItem
+class ManagementObject : public ManagementItem
{
protected:
diff --git a/cpp/include/qpid/messaging/Address.h b/cpp/include/qpid/messaging/Address.h
index 63dce0c49d..bebbfc72f6 100644
--- a/cpp/include/qpid/messaging/Address.h
+++ b/cpp/include/qpid/messaging/Address.h
@@ -119,7 +119,7 @@ class AddressImpl;
*
* An address has value semantics.
*/
-class QPID_MESSAGING_CLASS_EXTERN Address
+class Address
{
public:
QPID_MESSAGING_EXTERN Address();
diff --git a/cpp/include/qpid/messaging/Connection.h b/cpp/include/qpid/messaging/Connection.h
index 165573e2ef..1ad7a7242f 100644
--- a/cpp/include/qpid/messaging/Connection.h
+++ b/cpp/include/qpid/messaging/Connection.h
@@ -42,7 +42,7 @@ class Session;
* A connection represents a network connection to a remote endpoint.
*/
-class QPID_MESSAGING_CLASS_EXTERN Connection : public qpid::messaging::Handle<ConnectionImpl>
+class Connection : public qpid::messaging::Handle<ConnectionImpl>
{
public:
QPID_MESSAGING_EXTERN Connection(ConnectionImpl* impl);
@@ -54,27 +54,27 @@ class QPID_MESSAGING_CLASS_EXTERN Connection : public qpid::messaging::Handle<Co
* username
* password
* heartbeat
- * tcp_nodelay
- * sasl_mechanisms
- * sasl_service
- * sasl_min_ssf
- * sasl_max_ssf
+ * tcp-nodelay
+ * sasl-mechanism
+ * sasl-service
+ * sasl-min-ssf
+ * sasl-max-ssf
* transport
*
* Reconnect behaviour can be controlled through the following options:
*
* reconnect: true/false (enables/disables reconnect entirely)
- * reconnect_timeout: number of seconds (give up and report failure after specified time)
- * reconnect_limit: n (give up and report failure after specified number of attempts)
- * reconnect_interval_min: number of seconds (initial delay between failed reconnection attempts)
- * reconnect_interval_max: number of seconds (maximum delay between failed reconnection attempts)
- * reconnect_interval: shorthand for setting the same reconnect_interval_min/max
- * reconnect_urls: list of alternate urls to try when connecting
+ * reconnect-timeout: number of seconds (give up and report failure after specified time)
+ * reconnect-limit: n (give up and report failure after specified number of attempts)
+ * reconnect-interval-min: number of seconds (initial delay between failed reconnection attempts)
+ * reconnect-interval-max: number of seconds (maximum delay between failed reconnection attempts)
+ * reconnect-interval: shorthand for setting the same reconnect_interval_min/max
+ * reconnect-urls: list of alternate urls to try when connecting
*
- * The reconnect_interval is the time that the client waits
+ * The reconnect-interval is the time that the client waits
* for after a failed attempt to reconnect before retrying. It
- * starts at the value of the min_retry_interval and is
- * doubled every failure until the value of max_retry_interval
+ * starts at the value of the min-retry-interval and is
+ * doubled every failure until the value of max-retry-interval
* is reached.
*/
QPID_MESSAGING_EXTERN Connection(const std::string& url, const qpid::types::Variant::Map& options = qpid::types::Variant::Map());
diff --git a/cpp/include/qpid/messaging/Duration.h b/cpp/include/qpid/messaging/Duration.h
index 6b8f05c7c6..abcf169090 100644
--- a/cpp/include/qpid/messaging/Duration.h
+++ b/cpp/include/qpid/messaging/Duration.h
@@ -32,7 +32,7 @@ namespace messaging {
/** \ingroup messaging
* A duration is a time in milliseconds.
*/
-class QPID_MESSAGING_CLASS_EXTERN Duration
+class Duration
{
public:
QPID_MESSAGING_EXTERN explicit Duration(uint64_t milliseconds);
@@ -46,11 +46,9 @@ class QPID_MESSAGING_CLASS_EXTERN Duration
};
QPID_MESSAGING_EXTERN Duration operator*(const Duration& duration,
- uint64_t multiplier);
+ uint64_t multiplier);
QPID_MESSAGING_EXTERN Duration operator*(uint64_t multiplier,
- const Duration& duration);
-QPID_MESSAGING_EXTERN bool operator==(const Duration& a, const Duration& b);
-QPID_MESSAGING_EXTERN bool operator!=(const Duration& a, const Duration& b);
+ const Duration& duration);
}} // namespace qpid::messaging
diff --git a/cpp/include/qpid/messaging/FailoverUpdates.h b/cpp/include/qpid/messaging/FailoverUpdates.h
index 6d7314620a..14a1a31b63 100644
--- a/cpp/include/qpid/messaging/FailoverUpdates.h
+++ b/cpp/include/qpid/messaging/FailoverUpdates.h
@@ -32,7 +32,7 @@ struct FailoverUpdatesImpl;
* A utility to listen for updates on cluster membership and update
* the list of known urls for a connection accordingly.
*/
-class QPID_MESSAGING_CLASS_EXTERN FailoverUpdates
+class FailoverUpdates
{
public:
QPID_MESSAGING_EXTERN FailoverUpdates(Connection& connection);
diff --git a/cpp/include/qpid/messaging/Handle.h b/cpp/include/qpid/messaging/Handle.h
index 97a8f00b54..1e634ef888 100644
--- a/cpp/include/qpid/messaging/Handle.h
+++ b/cpp/include/qpid/messaging/Handle.h
@@ -40,22 +40,22 @@ template <class T> class Handle {
public:
/**@return true if handle is valid, i.e. not null. */
- QPID_MESSAGING_INLINE_EXTERN bool isValid() const { return impl; }
+ QPID_MESSAGING_EXTERN bool isValid() const { return impl; }
/**@return true if handle is null. It is an error to call any function on a null handle. */
- QPID_MESSAGING_INLINE_EXTERN bool isNull() const { return !impl; }
+ QPID_MESSAGING_EXTERN bool isNull() const { return !impl; }
/** Conversion to bool supports idiom if (handle) { handle->... } */
- QPID_MESSAGING_INLINE_EXTERN operator bool() const { return impl; }
+ QPID_MESSAGING_EXTERN operator bool() const { return impl; }
/** Operator ! supports idiom if (!handle) { do_if_handle_is_null(); } */
- QPID_MESSAGING_INLINE_EXTERN bool operator !() const { return !impl; }
+ QPID_MESSAGING_EXTERN bool operator !() const { return !impl; }
void swap(Handle<T>& h) { T* t = h.impl; h.impl = impl; impl = t; }
protected:
typedef T Impl;
- QPID_MESSAGING_INLINE_EXTERN Handle() :impl() {}
+ QPID_MESSAGING_EXTERN Handle() :impl() {}
// Not implemented,subclasses must implement.
QPID_MESSAGING_EXTERN Handle(const Handle&);
diff --git a/cpp/include/qpid/messaging/ImportExport.h b/cpp/include/qpid/messaging/ImportExport.h
index ab5f21f618..52f3eb8568 100644
--- a/cpp/include/qpid/messaging/ImportExport.h
+++ b/cpp/include/qpid/messaging/ImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
#if defined(CLIENT_EXPORT) || defined (qpidmessaging_EXPORTS)
-# define QPID_MESSAGING_EXTERN QPID_EXPORT
-# define QPID_MESSAGING_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QPID_MESSAGING_INLINE_EXTERN QPID_INLINE_EXPORT
+#define QPID_MESSAGING_EXTERN __declspec(dllexport)
+#else
+#define QPID_MESSAGING_EXTERN __declspec(dllimport)
+#endif
#else
-# define QPID_MESSAGING_EXTERN QPID_IMPORT
-# define QPID_MESSAGING_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QPID_MESSAGING_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QPID_MESSAGING_EXTERN
#endif
#endif /*!QPID_MESSAGING_IMPORTEXPORT_H*/
diff --git a/cpp/include/qpid/messaging/Message.h b/cpp/include/qpid/messaging/Message.h
index e89a6ce02f..d48af35cc0 100644
--- a/cpp/include/qpid/messaging/Message.h
+++ b/cpp/include/qpid/messaging/Message.h
@@ -39,7 +39,7 @@ struct MessageImpl;
/** \ingroup messaging
* Representation of a message.
*/
-class QPID_MESSAGING_CLASS_EXTERN Message
+class Message
{
public:
QPID_MESSAGING_EXTERN Message(const std::string& bytes = std::string());
@@ -55,58 +55,23 @@ class QPID_MESSAGING_CLASS_EXTERN Message
QPID_MESSAGING_EXTERN void setSubject(const std::string&);
QPID_MESSAGING_EXTERN const std::string& getSubject() const;
- /**
- * Set the content type (i.e. the MIME type) for the message. This
- * should be set by the sending application and indicates to
- * recipients of message how to interpret or decode the content.
- */
QPID_MESSAGING_EXTERN void setContentType(const std::string&);
- /**
- * Returns the content type (i.e. the MIME type) for the
- * message. This can be used to determine how to decode the
- * message content.
- */
QPID_MESSAGING_EXTERN const std::string& getContentType() const;
- /**
- * Set an application defined identifier for the message. At
- * present this must be a stringfied UUID (support for less
- * restrictive IDs is anticipated however).
- */
QPID_MESSAGING_EXTERN void setMessageId(const std::string&);
QPID_MESSAGING_EXTERN const std::string& getMessageId() const;
- /**
- * Sets the user id of the message. This should in general be the
- * user-id as which the sending connection authenticated itself as
- * the messaging infrastructure will verify this. See
- * Connection::getAuthenticatedUsername()
- */
QPID_MESSAGING_EXTERN void setUserId(const std::string&);
QPID_MESSAGING_EXTERN const std::string& getUserId() const;
- /**
- * Can be used to set application specific correlation identifiers
- * as part of a protocol for message exchange patterns. E.g. a
- * request-reponse pattern might require the correlation-id of the
- * request and response to match, or might use the message-id of
- * the request as the correlation-id on the response etc.
- */
QPID_MESSAGING_EXTERN void setCorrelationId(const std::string&);
QPID_MESSAGING_EXTERN const std::string& getCorrelationId() const;
- /**
- * Sets a priority level on the message. This may be used by the
- * messaging infrastructure to prioritise delivery of higher
- * priority messages.
- */
QPID_MESSAGING_EXTERN void setPriority(uint8_t);
QPID_MESSAGING_EXTERN uint8_t getPriority() const;
/**
- * Set the time to live for this message in milliseconds. This can
- * be used by the messaging infrastructure to discard messages
- * that are no longer of relevance.
+ * Set the time to live for this message in milliseconds.
*/
QPID_MESSAGING_EXTERN void setTtl(Duration ttl);
/**
@@ -114,62 +79,24 @@ class QPID_MESSAGING_CLASS_EXTERN Message
*/
QPID_MESSAGING_EXTERN Duration getTtl() const;
- /**
- * Mark the message as durable. This is a hint to the messaging
- * infrastructure that the message should be persisted or
- * otherwise stored such that failoures or shutdown do not cause
- * it to be lost.
- */
QPID_MESSAGING_EXTERN void setDurable(bool durable);
QPID_MESSAGING_EXTERN bool getDurable() const;
- /**
- * The redelivered flag if set implies that the message *may* have
- * been previously delivered and thus is a hint to the application
- * or messaging infrastructure that if de-duplication is required
- * this message should be examined to determine if it is a
- * duplicate.
- */
QPID_MESSAGING_EXTERN bool getRedelivered() const;
- /**
- * Can be used to provide a hint to the application or messaging
- * infrastructure that if de-duplication is required this message
- * should be examined to determine if it is a duplicate.
- */
QPID_MESSAGING_EXTERN void setRedelivered(bool);
- /**
- * In addition to a payload (i.e. the content), messages can
- * include annotations describing aspectf of the message. In
- * addition to the standard annotations such as TTL and content
- * type, application- or context- specific properties can also be
- * defined. Each message has a map of name values for such custom
- * properties. The value is specified as a Variant.
- */
QPID_MESSAGING_EXTERN const qpid::types::Variant::Map& getProperties() const;
QPID_MESSAGING_EXTERN qpid::types::Variant::Map& getProperties();
- /**
- * Set the content to the data held in the string parameter. Note:
- * this is treated as raw bytes and need not be text. Consider
- * setting the content-type to indicate how the data should be
- * interpreted by recipients.
- */
QPID_MESSAGING_EXTERN void setContent(const std::string&);
/**
- * Copy count bytes from the region pointed to by chars as the
- * message content.
+ * Note that chars are copied.
*/
QPID_MESSAGING_EXTERN void setContent(const char* chars, size_t count);
/** Get the content as a std::string */
QPID_MESSAGING_EXTERN std::string getContent() const;
- /**
- * Get a const pointer to the start of the content data. The
- * memory pointed to is owned by the message. The getContentSize()
- * method indicates how much data there is (i.e. the extent of the
- * memory region pointed to by the return value of this method).
- */
+ /** Get a const pointer to the start of the content data. */
QPID_MESSAGING_EXTERN const char* getContentPtr() const;
/** Get the size of content in bytes. */
QPID_MESSAGING_EXTERN size_t getContentSize() const;
@@ -180,9 +107,9 @@ class QPID_MESSAGING_CLASS_EXTERN Message
friend struct MessageImplAccess;
};
-struct QPID_MESSAGING_CLASS_EXTERN EncodingException : qpid::types::Exception
+struct EncodingException : qpid::types::Exception
{
- QPID_MESSAGING_EXTERN EncodingException(const std::string& msg);
+ EncodingException(const std::string& msg);
};
/**
@@ -195,8 +122,8 @@ struct QPID_MESSAGING_CLASS_EXTERN EncodingException : qpid::types::Exception
* @exception EncodingException
*/
QPID_MESSAGING_EXTERN void decode(const Message& message,
- qpid::types::Variant::Map& map,
- const std::string& encoding = std::string());
+ qpid::types::Variant::Map& map,
+ const std::string& encoding = std::string());
/**
* Decodes message content into a Variant::List.
*
@@ -207,8 +134,8 @@ QPID_MESSAGING_EXTERN void decode(const Message& message,
* @exception EncodingException
*/
QPID_MESSAGING_EXTERN void decode(const Message& message,
- qpid::types::Variant::List& list,
- const std::string& encoding = std::string());
+ qpid::types::Variant::List& list,
+ const std::string& encoding = std::string());
/**
* Encodes a Variant::Map into a message.
*
@@ -219,8 +146,8 @@ QPID_MESSAGING_EXTERN void decode(const Message& message,
* @exception EncodingException
*/
QPID_MESSAGING_EXTERN void encode(const qpid::types::Variant::Map& map,
- Message& message,
- const std::string& encoding = std::string());
+ Message& message,
+ const std::string& encoding = std::string());
/**
* Encodes a Variant::List into a message.
*
@@ -231,8 +158,8 @@ QPID_MESSAGING_EXTERN void encode(const qpid::types::Variant::Map& map,
* @exception EncodingException
*/
QPID_MESSAGING_EXTERN void encode(const qpid::types::Variant::List& list,
- Message& message,
- const std::string& encoding = std::string());
+ Message& message,
+ const std::string& encoding = std::string());
}} // namespace qpid::messaging
diff --git a/cpp/include/qpid/messaging/Receiver.h b/cpp/include/qpid/messaging/Receiver.h
index 13317dfcbd..6f3ae961db 100644
--- a/cpp/include/qpid/messaging/Receiver.h
+++ b/cpp/include/qpid/messaging/Receiver.h
@@ -41,7 +41,7 @@ class Session;
/** \ingroup messaging
* Interface through which messages are received.
*/
-class QPID_MESSAGING_CLASS_EXTERN Receiver : public qpid::messaging::Handle<ReceiverImpl>
+class Receiver : public qpid::messaging::Handle<ReceiverImpl>
{
public:
QPID_MESSAGING_EXTERN Receiver(ReceiverImpl* impl = 0);
diff --git a/cpp/include/qpid/messaging/Sender.h b/cpp/include/qpid/messaging/Sender.h
index 8e1c5846e9..85658f37cc 100644
--- a/cpp/include/qpid/messaging/Sender.h
+++ b/cpp/include/qpid/messaging/Sender.h
@@ -40,7 +40,7 @@ class Session;
/** \ingroup messaging
* Interface through which messages are sent.
*/
-class QPID_MESSAGING_CLASS_EXTERN Sender : public qpid::messaging::Handle<SenderImpl>
+class Sender : public qpid::messaging::Handle<SenderImpl>
{
public:
QPID_MESSAGING_EXTERN Sender(SenderImpl* impl = 0);
diff --git a/cpp/include/qpid/messaging/Session.h b/cpp/include/qpid/messaging/Session.h
index e8d6efb35d..6c023629e0 100644
--- a/cpp/include/qpid/messaging/Session.h
+++ b/cpp/include/qpid/messaging/Session.h
@@ -46,7 +46,7 @@ class SessionImpl;
* A session represents a distinct 'conversation' which can involve
* sending and receiving messages to and from different addresses.
*/
-class QPID_MESSAGING_CLASS_EXTERN Session : public qpid::messaging::Handle<SessionImpl>
+class Session : public qpid::messaging::Handle<SessionImpl>
{
public:
QPID_MESSAGING_EXTERN Session(SessionImpl* impl = 0);
@@ -62,12 +62,6 @@ class QPID_MESSAGING_CLASS_EXTERN Session : public qpid::messaging::Handle<Sessi
*/
QPID_MESSAGING_EXTERN void close();
- /**
- * Commits the sessions transaction.
- *
- * @exception TransactionAborted if the original session is lost
- * forcing an automatic rollback.
- */
QPID_MESSAGING_EXTERN void commit();
QPID_MESSAGING_EXTERN void rollback();
@@ -84,10 +78,6 @@ class QPID_MESSAGING_CLASS_EXTERN Session : public qpid::messaging::Handle<Sessi
*/
QPID_MESSAGING_EXTERN void acknowledge(Message&, bool sync=false);
/**
- * Acknowledges all message up to the specified message.
- */
- QPID_MESSAGING_EXTERN void acknowledgeUpTo(Message&, bool sync=false);
- /**
* Rejects the specified message. The broker does not redeliver a
* message that has been rejected. Once a message has been
* acknowledged, it can no longer be rejected.
@@ -145,51 +135,25 @@ class QPID_MESSAGING_CLASS_EXTERN Session : public qpid::messaging::Handle<Sessi
/**
* Create a new sender through which messages can be sent to the
* specified address.
- *
- * @exception ResolutionError if there is an error in resolving
- * the address
*/
QPID_MESSAGING_EXTERN Sender createSender(const Address& address);
- /**
- * Create a new sender through which messages can be sent to the
- * specified address.
- *
- * @exception ResolutionError if there is an error in resolving
- * the address
- *
- * @exception MalformedAddress if the syntax of address is not
- * valid
- */
QPID_MESSAGING_EXTERN Sender createSender(const std::string& address);
/**
* Create a new receiver through which messages can be received
* from the specified address.
- *
- * @exception ResolutionError if there is an error in resolving
- * the address
*/
QPID_MESSAGING_EXTERN Receiver createReceiver(const Address& address);
- /**
- * Create a new receiver through which messages can be received
- * from the specified address.
- *
- * @exception ResolutionError if there is an error in resolving
- * the address
- *
- * @exception MalformedAddress if the syntax of address is not
- * valid
- */
QPID_MESSAGING_EXTERN Receiver createReceiver(const std::string& address);
/**
* Returns the sender with the specified name.
- * @exception KeyError if there is none for that name.
+ *@exception KeyError if there is none for that name.
*/
QPID_MESSAGING_EXTERN Sender getSender(const std::string& name) const;
/**
* Returns the receiver with the specified name.
- * @exception KeyError if there is none for that name.
+ *@exception KeyError if there is none for that name.
*/
QPID_MESSAGING_EXTERN Receiver getReceiver(const std::string& name) const;
/**
@@ -198,16 +162,7 @@ class QPID_MESSAGING_CLASS_EXTERN Session : public qpid::messaging::Handle<Sessi
*/
QPID_MESSAGING_EXTERN Connection getConnection() const;
- /**
- * @returns true if the session has been rendered invalid by some
- * exception, false if it is valid for use.
- */
QPID_MESSAGING_EXTERN bool hasError();
- /**
- * If the session has been rendered invalid by some exception,
- * this method will result in that exception being thrown on
- * calling this method.
- */
QPID_MESSAGING_EXTERN void checkError();
#ifndef SWIG
diff --git a/cpp/include/qpid/messaging/exceptions.h b/cpp/include/qpid/messaging/exceptions.h
index 31e2488d91..0ff608b343 100644
--- a/cpp/include/qpid/messaging/exceptions.h
+++ b/cpp/include/qpid/messaging/exceptions.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -29,47 +29,34 @@
namespace qpid {
namespace messaging {
-/** \ingroup messaging
+/** \ingroup messaging
*/
-/**
- * This is the base class for all messaging related exceptions thrown
- * by this API.
- */
-struct QPID_MESSAGING_CLASS_EXTERN MessagingException : public qpid::types::Exception
+struct MessagingException : public qpid::types::Exception
{
QPID_MESSAGING_EXTERN MessagingException(const std::string& msg);
QPID_MESSAGING_EXTERN virtual ~MessagingException() throw();
-
+
qpid::types::Variant::Map detail;
//TODO: override what() to include detail if present
};
-/**
- * Thrown when the syntax of the option string used to configure a
- * connection in not valid
- */
-struct QPID_MESSAGING_CLASS_EXTERN InvalidOptionString : public MessagingException
+struct InvalidOptionString : public MessagingException
{
QPID_MESSAGING_EXTERN InvalidOptionString(const std::string& msg);
};
-/**
- * Thrown to indicate a failed lookup of some local object. For
- * example when attempting to retrieve a session, sender or receiver
- * by name.
- */
-struct QPID_MESSAGING_CLASS_EXTERN KeyError : public MessagingException
+struct KeyError : public MessagingException
{
QPID_MESSAGING_EXTERN KeyError(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN LinkError : public MessagingException
+struct LinkError : public MessagingException
{
QPID_MESSAGING_EXTERN LinkError(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN AddressError : public LinkError
+struct AddressError : public LinkError
{
QPID_MESSAGING_EXTERN AddressError(const std::string&);
};
@@ -78,118 +65,85 @@ struct QPID_MESSAGING_CLASS_EXTERN AddressError : public LinkError
* Thrown when a syntactically correct address cannot be resolved or
* used.
*/
-struct QPID_MESSAGING_CLASS_EXTERN ResolutionError : public AddressError
+struct ResolutionError : public AddressError
{
QPID_MESSAGING_EXTERN ResolutionError(const std::string& msg);
};
-/**
- * Thrown when creating a sender or receiver for an address for which
- * some asserted property of the node is not matched.
- */
-struct QPID_MESSAGING_CLASS_EXTERN AssertionFailed : public ResolutionError
+struct AssertionFailed : public ResolutionError
{
QPID_MESSAGING_EXTERN AssertionFailed(const std::string& msg);
};
-/**
- * Thrown on attempts to create a sender or receiver to a non-existent
- * node.
- */
-struct QPID_MESSAGING_CLASS_EXTERN NotFound : public ResolutionError
+struct NotFound : public ResolutionError
{
QPID_MESSAGING_EXTERN NotFound(const std::string& msg);
};
/**
- * Thrown when an address string with invalid syntax is used.
+ * Thrown when an address string with inalid sytanx is used.
*/
-struct QPID_MESSAGING_CLASS_EXTERN MalformedAddress : public AddressError
+struct MalformedAddress : public AddressError
{
QPID_MESSAGING_EXTERN MalformedAddress(const std::string& msg);
};
-struct QPID_MESSAGING_CLASS_EXTERN ReceiverError : public LinkError
+struct ReceiverError : public LinkError
{
QPID_MESSAGING_EXTERN ReceiverError(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN FetchError : public ReceiverError
+struct FetchError : public ReceiverError
{
QPID_MESSAGING_EXTERN FetchError(const std::string&);
};
-/**
- * Thrown by Receiver::fetch(), Receiver::get() and
- * Session::nextReceiver() to indicate that there no message was
- * available before the timeout specified.
- */
-struct QPID_MESSAGING_CLASS_EXTERN NoMessageAvailable : public FetchError
+struct NoMessageAvailable : public FetchError
{
QPID_MESSAGING_EXTERN NoMessageAvailable();
};
-struct QPID_MESSAGING_CLASS_EXTERN SenderError : public LinkError
+struct SenderError : public LinkError
{
QPID_MESSAGING_EXTERN SenderError(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN SendError : public SenderError
+struct SendError : public SenderError
{
QPID_MESSAGING_EXTERN SendError(const std::string&);
};
-/**
- * Thrown to indicate that the sender attempted to send a message that
- * would result in the target node on the peer exceeding a
- * preconfigured capacity.
- */
-struct QPID_MESSAGING_CLASS_EXTERN TargetCapacityExceeded : public SendError
+struct TargetCapacityExceeded : public SendError
{
QPID_MESSAGING_EXTERN TargetCapacityExceeded(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN SessionError : public MessagingException
+struct SessionError : public MessagingException
{
QPID_MESSAGING_EXTERN SessionError(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN TransactionError : public SessionError
+struct TransactionError : public SessionError
{
QPID_MESSAGING_EXTERN TransactionError(const std::string&);
};
-/**
- * Thrown on Session::commit() if reconnection results in the
- * transaction being automatically aborted.
- */
-struct QPID_MESSAGING_CLASS_EXTERN TransactionAborted : public TransactionError
+struct TransactionAborted : public TransactionError
{
QPID_MESSAGING_EXTERN TransactionAborted(const std::string&);
};
-/**
- * Thrown to indicate that the application attempted to do something
- * for which it was not authorised by its peer.
- */
-struct QPID_MESSAGING_CLASS_EXTERN UnauthorizedAccess : public SessionError
+struct UnauthorizedAccess : public SessionError
{
QPID_MESSAGING_EXTERN UnauthorizedAccess(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN ConnectionError : public MessagingException
+struct ConnectionError : public MessagingException
{
QPID_MESSAGING_EXTERN ConnectionError(const std::string&);
};
-/**
- * Thrown to indicate loss of underlying connection. When
- * auto-reconnect is used this will be caught by the library and used
- * to trigger reconnection attempts. If reconnection fails (according
- * to whatever settings have been configured), then an instnace of
- * this class will be thrown to signal that.
- */
-struct QPID_MESSAGING_CLASS_EXTERN TransportFailure : public MessagingException
+struct TransportFailure : public MessagingException
{
QPID_MESSAGING_EXTERN TransportFailure(const std::string&);
};
diff --git a/cpp/include/qpid/sys/ExceptionHolder.h b/cpp/include/qpid/sys/ExceptionHolder.h
index 4bc934cf75..9eff1d64c7 100644
--- a/cpp/include/qpid/sys/ExceptionHolder.h
+++ b/cpp/include/qpid/sys/ExceptionHolder.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -42,11 +42,14 @@ class ExceptionHolder : public Raisable {
public:
ExceptionHolder() {}
// Use default copy & assign.
-
+
/** Take ownership of ex */
template <class Ex> ExceptionHolder(Ex* ex) { wrap(ex); }
- template <class Ex> ExceptionHolder& operator=(Ex* ex) { wrap(ex); return *this; }
+ template <class Ex> ExceptionHolder(const boost::shared_ptr<Ex>& ex) { wrap(ex.release()); }
+ template <class Ex> ExceptionHolder& operator=(Ex* ex) { wrap(ex); return *this; }
+ template <class Ex> ExceptionHolder& operator=(boost::shared_ptr<Ex> ex) { wrap(ex.release()); return *this; }
+
void raise() const { if (wrapper.get()) wrapper->raise() ; }
std::string what() const { return wrapper.get() ? wrapper->what() : std::string(); }
bool empty() const { return !wrapper.get(); }
@@ -63,7 +66,7 @@ class ExceptionHolder : public Raisable {
template <class Ex> void wrap(Ex* ex) { wrapper.reset(new Wrapper<Ex>(ex)); }
boost::shared_ptr<Raisable> wrapper;
};
-
+
}} // namespace qpid::sys
diff --git a/cpp/include/qpid/sys/IntegerTypes.h b/cpp/include/qpid/sys/IntegerTypes.h
index 75fa921de0..89635f033e 100755
--- a/cpp/include/qpid/sys/IntegerTypes.h
+++ b/cpp/include/qpid/sys/IntegerTypes.h
@@ -21,7 +21,7 @@
*
*/
-#if (defined(_WINDOWS) || defined (WIN32))
+#if (defined(_WINDOWS) || defined (WIN32)) && defined(_MSC_VER)
#include "qpid/sys/windows/IntegerTypes.h"
#endif
#if !defined _WINDOWS && !defined WIN32
diff --git a/cpp/include/qpid/sys/Runnable.h b/cpp/include/qpid/sys/Runnable.h
index fed7663cb6..0f1243a277 100644
--- a/cpp/include/qpid/sys/Runnable.h
+++ b/cpp/include/qpid/sys/Runnable.h
@@ -30,7 +30,7 @@ namespace sys {
/**
* Interface for objects that can be run, e.g. in a thread.
*/
-class QPID_COMMON_CLASS_EXTERN Runnable
+class Runnable
{
public:
/** Type to represent a runnable as a Functor */
diff --git a/cpp/include/qpid/sys/Thread.h b/cpp/include/qpid/sys/Thread.h
index f556612908..45a39e796f 100644
--- a/cpp/include/qpid/sys/Thread.h
+++ b/cpp/include/qpid/sys/Thread.h
@@ -25,11 +25,7 @@
#include "qpid/CommonImportExport.h"
#ifdef _WIN32
-# ifdef _MSC_VER
-# define QPID_TSS __declspec(thread)
-# else
-# define QPID_TSS __thread
-# endif
+# define QPID_TSS __declspec(thread)
#elif defined (__GNUC__)
# define QPID_TSS __thread
#elif defined (__SUNPRO_CC)
diff --git a/cpp/include/qpid/sys/Time.h b/cpp/include/qpid/sys/Time.h
index 9c5ac66e9a..d3ab832229 100644
--- a/cpp/include/qpid/sys/Time.h
+++ b/cpp/include/qpid/sys/Time.h
@@ -119,7 +119,7 @@ class Duration {
friend class AbsTime;
public:
- QPID_COMMON_INLINE_EXTERN inline Duration(int64_t time0 = 0);
+ QPID_COMMON_EXTERN inline Duration(int64_t time0 = 0);
QPID_COMMON_EXTERN explicit Duration(const AbsTime& start, const AbsTime& finish);
inline operator int64_t() const;
};
@@ -167,9 +167,6 @@ QPID_COMMON_EXTERN void usleep(uint64_t usecs);
/** Output formatted date/time for now*/
void outputFormattedNow(std::ostream&);
-/** Output unformatted nanosecond-resolution time for now */
-void outputHiresNow(std::ostream&);
-
}}
#endif /*!_sys_Time_h*/
diff --git a/cpp/include/qpid/sys/windows/IntegerTypes.h b/cpp/include/qpid/sys/windows/IntegerTypes.h
index 28b82da1a0..ece1a618e9 100755
--- a/cpp/include/qpid/sys/windows/IntegerTypes.h
+++ b/cpp/include/qpid/sys/windows/IntegerTypes.h
@@ -22,17 +22,13 @@
*/
typedef unsigned char uint8_t;
+typedef char int8_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef unsigned int uint32_t;
typedef int int32_t;
-#if defined(_MSC_VER)
-typedef signed char int8_t;
typedef unsigned __int64 uint64_t;
typedef __int64 int64_t;
-#else
-#include <stdint.h>
-#endif
// Visual Studio doesn't define other common types, so set them up here too.
typedef unsigned int uint;
diff --git a/cpp/include/qpid/types/Exception.h b/cpp/include/qpid/types/Exception.h
index 483d104cc8..d061a7df0e 100644
--- a/cpp/include/qpid/types/Exception.h
+++ b/cpp/include/qpid/types/Exception.h
@@ -28,7 +28,7 @@
namespace qpid {
namespace types {
-class QPID_TYPES_CLASS_EXTERN Exception : public std::exception
+class Exception : public std::exception
{
public:
QPID_TYPES_EXTERN explicit Exception(const std::string& message=std::string()) throw();
diff --git a/cpp/include/qpid/types/ImportExport.h b/cpp/include/qpid/types/ImportExport.h
index 8fa41884fb..bb10575fcd 100644
--- a/cpp/include/qpid/types/ImportExport.h
+++ b/cpp/include/qpid/types/ImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
#if defined(TYPES_EXPORT) || defined (qpidtypes_EXPORTS)
-# define QPID_TYPES_EXTERN QPID_EXPORT
-# define QPID_TYPES_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QPID_TYPES_INLINE_EXTERN QPID_INLINE_EXPORT
+#define QPID_TYPES_EXTERN __declspec(dllexport)
+#else
+#define QPID_TYPES_EXTERN __declspec(dllimport)
+#endif
#else
-# define QPID_TYPES_EXTERN QPID_IMPORT
-# define QPID_TYPES_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QPID_TYPES_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QPID_TYPES_EXTERN
#endif
#endif /*!QPID_TYPES_IMPORTEXPORT_H*/
diff --git a/cpp/include/qpid/types/Uuid.h b/cpp/include/qpid/types/Uuid.h
index 02af4c7e7f..467a895184 100644
--- a/cpp/include/qpid/types/Uuid.h
+++ b/cpp/include/qpid/types/Uuid.h
@@ -29,7 +29,7 @@
namespace qpid {
namespace types {
-class QPID_TYPES_CLASS_EXTERN Uuid
+class Uuid
{
public:
static const size_t SIZE;
diff --git a/cpp/include/qpid/types/Variant.h b/cpp/include/qpid/types/Variant.h
index 4459fc4123..9ae672b7c2 100644
--- a/cpp/include/qpid/types/Variant.h
+++ b/cpp/include/qpid/types/Variant.h
@@ -36,7 +36,7 @@ namespace types {
/**
* Thrown when an illegal conversion of a variant is attempted.
*/
-struct QPID_TYPES_CLASS_EXTERN InvalidConversion : public Exception
+struct InvalidConversion : public Exception
{
InvalidConversion(const std::string& msg);
};
@@ -60,14 +60,12 @@ enum VariantType {
VAR_UUID
};
-std::string getTypeName(VariantType type);
-
class VariantImpl;
/**
* Represents a value of variable type.
*/
-class QPID_TYPES_CLASS_EXTERN Variant
+class Variant
{
public:
typedef std::map<std::string, Variant> Map;
diff --git a/cpp/managementgen/Makefile.am b/cpp/managementgen/Makefile.am
index 4fc5edcad4..6c2024ccaa 100644
--- a/cpp/managementgen/Makefile.am
+++ b/cpp/managementgen/Makefile.am
@@ -19,26 +19,20 @@
qmfpythondir = $(pythondir)
dist_bin_SCRIPTS = \
qmf-gen
-
-pkgpyexec_qmfgendir = $(pyexecdir)/qmfgen
-pkgpyexec_qmfgen_PYTHON = \
+nobase_qmfpython_DATA = \
qmfgen/__init__.py \
qmfgen/generate.py \
qmfgen/schema.py \
- qmfgen/management-types.xml
-
-pkgpyexec_qmfgentmpldir = $(pyexecdir)/qmfgen/templates
-pkgpyexec_qmfgentmpl_PYTHON = \
qmfgen/templates/Args.h \
qmfgen/templates/Class.cpp \
qmfgen/templates/Class.h \
- qmfgen/templates/CMakeLists.cmake \
qmfgen/templates/Event.cpp \
qmfgen/templates/Event.h \
qmfgen/templates/Makefile.mk \
qmfgen/templates/Package.cpp \
qmfgen/templates/Package.h \
qmfgen/templates/V2Package.cpp \
- qmfgen/templates/V2Package.h
+ qmfgen/templates/V2Package.h \
+ qmfgen/management-types.xml
EXTRA_DIST = $(nobase_qmfpython_DATA) CMakeLists.txt
diff --git a/cpp/managementgen/qmfgen/schema.py b/cpp/managementgen/qmfgen/schema.py
index 59e951fb6e..afdfe42639 100755
--- a/cpp/managementgen/qmfgen/schema.py
+++ b/cpp/managementgen/qmfgen/schema.py
@@ -1731,9 +1731,9 @@ class SchemaPackage:
stream.write(" qmf::SchemaProperty arg(\"%s\", %s);\n" % (arg.name, typeName))
if subType:
stream.write(" arg.setSubtype(\"%s\");\n" % subType)
- if arg.unit:
+ if stat.unit:
stream.write(" arg.setUnit(\"%s\");\n" % arg.unit)
- if arg.desc:
+ if stat.desc:
stream.write(" arg.setDesc(\"%s\");\n" % arg.desc)
stream.write(" arg.setDirection(%s);\n" % self.qmfv2Dir(arg.dir))
stream.write(" method.addArgument(arg);\n")
diff --git a/cpp/rubygen/0-10/specification.rb b/cpp/rubygen/0-10/specification.rb
index ef193f5fd0..7366599eba 100755
--- a/cpp/rubygen/0-10/specification.rb
+++ b/cpp/rubygen/0-10/specification.rb
@@ -252,7 +252,7 @@ class Specification < CppGen
include "#{@dir}/specification"
namespace(@ns) {
genl "template <class F, class R=typename F::result_type>"
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", "ProxyTemplate") {
+ cpp_class("ProxyTemplate") {
public
genl "ProxyTemplate(F f=F()) : functor(f) {}"
@amqp.classes.each { |c|
diff --git a/cpp/rubygen/MethodBodyDefaultVisitor.rb b/cpp/rubygen/MethodBodyDefaultVisitor.rb
index 11dbcb8f83..4f9b369117 100755
--- a/cpp/rubygen/MethodBodyDefaultVisitor.rb
+++ b/cpp/rubygen/MethodBodyDefaultVisitor.rb
@@ -33,7 +33,7 @@ class MethodBodyDefaultVisitorGen < CppGen
include "qpid/framing/MethodBodyConstVisitor"
namespace(@namespace) {
genl
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", @classname, "public MethodBodyConstVisitor") {
+ cpp_class(@classname, "public MethodBodyConstVisitor") {
genl "public:"
genl "virtual void defaultVisit() = 0;"
@amqp.methods_.each { |m|
diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb
index 88720cad5f..69e65a4056 100755
--- a/cpp/rubygen/amqpgen.rb
+++ b/cpp/rubygen/amqpgen.rb
@@ -61,8 +61,7 @@ end
class Module
# Add trailing _ to avoid conflict with Object methods.
def mangle(sym)
- sym = (sym.to_s+"_").to_sym if (Object.method_defined?(sym) or sym == :type)
- sym
+ (Object.method_defined? sym) ? (sym.to_s+"_").intern : sym
end
# Add attribute reader for XML attribute.
@@ -191,8 +190,7 @@ class AmqpElement
"command-fragments" => "session.command-fragment",
"in-doubt" => "dtx.xid",
"tx-publish" => "str-8",
- "queues" => "str-8",
- "prepared" => "str-8"
+ "queues" => "str-8"
}
def array_type(name)
diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb
index 7dc21fe1bc..f0995105f1 100755
--- a/cpp/rubygen/cppgen.rb
+++ b/cpp/rubygen/cppgen.rb
@@ -377,9 +377,6 @@ class CppGen < Generator
def cpp_class(name, *bases, &block)
struct_class("class", name, bases, &block);
end
- def cpp_extern_class(scope, name, *bases, &block)
- struct_class("class "+scope, name, bases, &block);
- end
def typedef(type, name) genl "typedef #{type} #{name};\n"; end
diff --git a/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb b/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb
index 4c58ff2bbb..00962de4f9 100755
--- a/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb
+++ b/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb
@@ -33,7 +33,7 @@ class MethodBodyDefaultVisitorGen < CppGen
include "qpid/CommonImportExport.h"
namespace(@namespace) {
genl "class AMQMethodBody;"
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", @classname, "public MethodBodyConstVisitor") {
+ cpp_class(@classname, "public MethodBodyConstVisitor") {
genl "public:"
genl "virtual void defaultVisit(const AMQMethodBody&) = 0;"
@amqp.methods_.each { |m|
diff --git a/cpp/rubygen/framing.0-10/OperationsInvoker.rb b/cpp/rubygen/framing.0-10/OperationsInvoker.rb
index f9b5ce58d8..f9b6cac76b 100755
--- a/cpp/rubygen/framing.0-10/OperationsInvoker.rb
+++ b/cpp/rubygen/framing.0-10/OperationsInvoker.rb
@@ -69,7 +69,7 @@ class OperationsInvokerGen < CppGen
def invoker_h(invoker, target, methods)
return if methods.empty?
genl
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", invoker, "public qpid::framing::Invoker") {
+ cpp_class(invoker, "public qpid::framing::Invoker") {
genl "#{target}& target;"
public
genl("Invoker(#{target}& target_) : target(target_) {}")
diff --git a/cpp/rubygen/framing.0-10/Proxy.rb b/cpp/rubygen/framing.0-10/Proxy.rb
index 3325616754..6e3cb4fd4d 100755
--- a/cpp/rubygen/framing.0-10/Proxy.rb
+++ b/cpp/rubygen/framing.0-10/Proxy.rb
@@ -37,7 +37,7 @@ class ProxyGen < CppGen
def inner_class_decl(c)
cname=c.name.caps
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", cname, "public Proxy") {
+ cpp_class(cname, "public Proxy") {
gen <<EOS
public:
#{cname}(FrameHandler& f) : Proxy(f) {}
@@ -69,7 +69,7 @@ EOS
include "qpid/CommonImportExport.h"
namespace("qpid::framing") {
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", @classname, "public Proxy") {
+ cpp_class(@classname, "public Proxy") {
public
genl "QPID_COMMON_EXTERN #{@classname}(FrameHandler& out);"
genl
diff --git a/cpp/rubygen/framing.0-10/Session.rb b/cpp/rubygen/framing.0-10/Session.rb
index e800df9b2e..61f0e03a8b 100755
--- a/cpp/rubygen/framing.0-10/Session.rb
+++ b/cpp/rubygen/framing.0-10/Session.rb
@@ -56,8 +56,8 @@ module SyncAsync
def decl_ctor_opeq()
genl
genl "QPID_CLIENT_EXTERN #{@classname}();"
- genl "QPID_CLIENT_INLINE_EXTERN #{@classname}(const #{@version_base}& other);"
- genl "QPID_CLIENT_INLINE_EXTERN #{@classname}& operator=(const #{@version_base}& other);"
+ genl "QPID_CLIENT_EXTERN #{@classname}(const #{@version_base}& other);"
+ genl "QPID_CLIENT_EXTERN #{@classname}& operator=(const #{@version_base}& other);"
end
def defn_ctor_opeq(inline="")
diff --git a/cpp/rubygen/framing.0-10/structs.rb b/cpp/rubygen/framing.0-10/structs.rb
index 62b33ce773..c3684aea66 100755
--- a/cpp/rubygen/framing.0-10/structs.rb
+++ b/cpp/rubygen/framing.0-10/structs.rb
@@ -406,7 +406,7 @@ EOS
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN #{classname} #{inheritance} {
+class #{classname} #{inheritance} {
EOS
if (is_packed(s))
indent { s.fields.each { |f| genl "#{f.cpptype.name} #{f.cppname};" unless f.type_ == "bit"} }
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index 0dbcf8e2e6..60f505a10e 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -96,7 +96,7 @@ MACRO (add_msvc_version_full verProject verProjectType verProjectFileExt verFN1
inherit_value ("winver_${verProject}_InternalName" "${verProject}")
inherit_value ("winver_${verProject}_OriginalFilename" "${verProject}.${verProjectFileExt}")
inherit_value ("winver_${verProject}_ProductName" "${winver_DESCRIPTION_SUMMARY}")
-
+
# Create strings to be substituted into the template file
set ("winverFileVersionBinary" "${winver_${verProject}_FileVersionBinary}")
set ("winverProductVersionBinary" "${winver_${verProject}_ProductVersionBinary}")
@@ -126,7 +126,7 @@ ENDMACRO (add_msvc_version_full)
#
MACRO (add_msvc_version verProject verProjectType verProjectFileExt)
if (MSVC)
- add_msvc_version_full (${verProject}
+ add_msvc_version_full (${verProject}
${verProjectType}
${verProjectFileExt}
${winver_FILE_VERSION_N1}
@@ -313,6 +313,10 @@ if (NOT Boost_FILESYSTEM_LIBRARY)
set(Boost_FILESYSTEM_LIBRARY boost_filesystem)
endif (NOT Boost_FILESYSTEM_LIBRARY)
+if (NOT Boost_SYSTEM_LIBRARY)
+ set(Boost_SYSTEM_LIBRARY boost_system)
+endif (NOT Boost_SYSTEM_LIBRARY)
+
if (NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY)
set(Boost_UNIT_TEST_FRAMEWORK_LIBRARY boost_unit_test_framework)
endif (NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY)
@@ -580,15 +584,6 @@ include (ssl.cmake)
check_symbol_exists (LOG_AUTHPRIV "sys/syslog.h" HAVE_LOG_AUTHPRIV)
check_symbol_exists (LOG_FTP "sys/syslog.h" HAVE_LOG_FTP)
-# Allow MSVC user to select 'WinXP-SP3/Windows Server 2003' as build target version
-set (win32_winnt_default OFF)
-if (CMAKE_SYSTEM_NAME STREQUAL Windows)
- if (MSVC)
- set (win32_winnt_default ON)
- endif (MSVC)
-endif (CMAKE_SYSTEM_NAME STREQUAL Windows)
-option(SET_WIN32_WINNT "In Windows-MSVC build: define _WIN32_WINNT=0x0502 to select target version: Windows XP with SP3" ${win32_winnt_default})
-
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
if (MSVC)
add_definitions(
@@ -598,11 +593,10 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
/wd4244
/wd4800
/wd4355
- /wd4267
)
- if (SET_WIN32_WINNT)
- add_definitions(/D "_WIN32_WINNT=0x0502")
- endif (SET_WIN32_WINNT)
+ if (MSVC80)
+ add_definitions(/D "_WIN32_WINNT=0x0501")
+ endif (MSVC80)
# set the RelWithDebInfo compile/link switches to equal Release
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /O2 /Ob2 /D NDEBUG")
@@ -634,7 +628,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
qpid/sys/windows/LockFile.cpp
qpid/sys/windows/PipeHandle.cpp
qpid/sys/windows/PollableCondition.cpp
- qpid/sys/windows/SCM.cpp
qpid/sys/windows/Shlib.cpp
qpid/sys/windows/Socket.cpp
qpid/sys/windows/SocketAddress.cpp
@@ -647,7 +640,8 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
)
set (qpidcommon_platform_LIBS
- ${Boost_THREAD_LIBRARY} ${windows_ssl_libs} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ws2_32 )
+ ${windows_ssl_libs} ws2_32
+ )
set (qpidbroker_platform_SOURCES
qpid/broker/windows/BrokerDefaults.cpp
qpid/broker/windows/SaslAuthenticator.cpp
@@ -666,8 +660,9 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
set (qpidd_platform_SOURCES
windows/QpiddBroker.cpp
+ windows/SCM.cpp
)
-
+
set (qpidmessaging_platform_SOURCES
qpid/messaging/HandleInstantiator.cpp
)
@@ -925,6 +920,8 @@ set (qpidmessaging_SOURCES
qpid/client/amqp0_10/SessionImpl.cpp
qpid/client/amqp0_10/SenderImpl.h
qpid/client/amqp0_10/SenderImpl.cpp
+ qpid/client/amqp0_10/SimpleUrlParser.h
+ qpid/client/amqp0_10/SimpleUrlParser.cpp
)
add_msvc_version (qpidmessaging library dll)
@@ -946,7 +943,7 @@ if (NOT QPID_GENERATED_HEADERS_IN_SOURCE)
endif (NOT QPID_GENERATED_HEADERS_IN_SOURCE)
-if (MSVC)
+if (WIN32)
# Install the DtcPlugin project and call it qpidxarm.
set(AMQP_WCF_DIR ${qpid-cpp_SOURCE_DIR}/../wcf)
set(qpidxarm_SOURCES ${AMQP_WCF_DIR}/src/Apache/Qpid/DtcPlugin/DtcPlugin.cpp)
@@ -959,7 +956,7 @@ if (MSVC)
COMPONENT ${QPID_COMPONENT_CLIENT})
install_pdb (qpidxarm ${QPID_COMPONENT_CLIENT})
endif (EXISTS ${qpidxarm_SOURCES})
-endif (MSVC)
+endif (WIN32)
set (qpidbroker_SOURCES
${mgen_broker_cpp}
@@ -977,8 +974,6 @@ set (qpidbroker_SOURCES
qpid/broker/Queue.cpp
qpid/broker/QueueCleaner.cpp
qpid/broker/QueueListeners.cpp
- qpid/broker/FifoDistributor.cpp
- qpid/broker/MessageGroupManager.cpp
qpid/broker/PersistableMessage.cpp
qpid/broker/Bridge.cpp
qpid/broker/Connection.cpp
@@ -995,6 +990,7 @@ set (qpidbroker_SOURCES
qpid/broker/ExchangeRegistry.cpp
qpid/broker/FanOutExchange.cpp
qpid/broker/HeadersExchange.cpp
+ qpid/broker/IncompleteMessageList.cpp
qpid/broker/Link.cpp
qpid/broker/LinkRegistry.cpp
qpid/broker/Message.cpp
@@ -1007,7 +1003,7 @@ set (qpidbroker_SOURCES
qpid/broker/QueueEvents.cpp
qpid/broker/QueuePolicy.cpp
qpid/broker/QueueRegistry.cpp
- qpid/broker/QueueFlowLimit.cpp
+ qpid/broker/RateTracker.cpp
qpid/broker/RecoveryManagerImpl.cpp
qpid/broker/RecoveredEnqueue.cpp
qpid/broker/RecoveredDequeue.cpp
@@ -1073,15 +1069,13 @@ endif (CPACK_GENERATOR STREQUAL "NSIS")
# 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 2.0.0)
-set (qmf2_version 1.0.0)
+set (qmf_version 1.0.0)
set (qmfengine_version 1.0.0)
set (qmf_SOURCES
qpid/agent/ManagementAgentImpl.cpp
qpid/agent/ManagementAgentImpl.h
)
-
add_msvc_version (qmf library dll)
add_library (qmf SHARED ${qmf_SOURCES})
target_link_libraries (qmf qpidclient)
@@ -1092,88 +1086,6 @@ install (TARGETS qmf OPTIONAL
COMPONENT ${QPID_COMPONENT_QMF})
install_pdb (qmf ${QPID_COMPONENT_QMF})
-if(NOT WIN32)
- set (qmf2_HEADERS
- ../include/qmf/AgentEvent.h
- ../include/qmf/Agent.h
- ../include/qmf/AgentSession.h
- ../include/qmf/ConsoleEvent.h
- ../include/qmf/ConsoleSession.h
- ../include/qmf/DataAddr.h
- ../include/qmf/Data.h
- ../include/qmf/exceptions.h
- ../include/qmf/Handle.h
- ../include/qmf/ImportExport.h
- ../include/qmf/posix/EventNotifier.h
- ../include/qmf/Query.h
- ../include/qmf/Schema.h
- ../include/qmf/SchemaId.h
- ../include/qmf/SchemaMethod.h
- ../include/qmf/SchemaProperty.h
- ../include/qmf/SchemaTypes.h
- ../include/qmf/Subscription.h
- )
-
- set (qmf2_SOURCES
- ${qmf2_HEADERS}
- qmf/agentCapability.h
- qmf/Agent.cpp
- qmf/AgentEvent.cpp
- qmf/AgentEventImpl.h
- qmf/AgentImpl.h
- qmf/AgentSession.cpp
- qmf/AgentSubscription.cpp
- qmf/AgentSubscription.h
- qmf/ConsoleEvent.cpp
- qmf/ConsoleEventImpl.h
- qmf/ConsoleSession.cpp
- qmf/ConsoleSessionImpl.h
- qmf/constants.cpp
- qmf/constants.h
- qmf/DataAddr.cpp
- qmf/DataAddrImpl.h
- qmf/Data.cpp
- qmf/DataImpl.h
- qmf/EventNotifierImpl.h
- qmf/EventNotifierImpl.cpp
- qmf/PosixEventNotifier.cpp
- qmf/PosixEventNotifierImpl.cpp
- qmf/exceptions.cpp
- qmf/Expression.cpp
- qmf/Expression.h
- qmf/Hash.cpp
- qmf/Hash.h
- qmf/PrivateImplRef.h
- qmf/Query.cpp
- qmf/QueryImpl.h
- qmf/Schema.cpp
- qmf/SchemaCache.cpp
- qmf/SchemaCache.h
- qmf/SchemaId.cpp
- qmf/SchemaIdImpl.h
- qmf/SchemaImpl.h
- qmf/SchemaMethod.cpp
- qmf/SchemaMethodImpl.h
- qmf/SchemaProperty.cpp
- qmf/SchemaPropertyImpl.h
- qmf/Subscription.cpp
- qmf/SubscriptionImpl.h
- )
-
- add_msvc_version (qmf2 library dll)
- add_library (qmf2 SHARED ${qmf2_SOURCES})
- target_link_libraries (qmf2 qpidmessaging qpidtypes qpidclient qpidcommon)
- set_target_properties (qmf2 PROPERTIES
- VERSION ${qmf2_version})
- install (TARGETS qmf2 OPTIONAL
- DESTINATION ${QPID_INSTALL_LIBDIR}
- COMPONENT ${QPID_COMPONENT_QMF})
- install (FILES ${qmf2_HEADERS}
- DESTINATION ${QPID_INSTALL_INCLUDEDIR}/qmf
- COMPONENT ${QPID_COMPONENT_QMF})
- install_pdb (qmf2 ${QPID_COMPONENT_QMF})
-endif (NOT WIN32)
-
set (qmfengine_SOURCES
qmf/engine/Agent.cpp
qmf/engine/BrokerProxyImpl.cpp
diff --git a/cpp/src/CMakeWinVersions.cmake b/cpp/src/CMakeWinVersions.cmake
index 0bac7cab47..9bffd2ba0e 100644
--- a/cpp/src/CMakeWinVersions.cmake
+++ b/cpp/src/CMakeWinVersions.cmake
@@ -34,11 +34,11 @@
# set ("winver_PACKAGE_NAME" "qpid-cpp")
# set ("winver_DESCRIPTION_SUMMARY" "Apache Qpid C++")
# set ("winver_FILE_VERSION_N1" "0")
-# set ("winver_FILE_VERSION_N2" "11")
+# set ("winver_FILE_VERSION_N2" "9")
# set ("winver_FILE_VERSION_N3" "0")
# set ("winver_FILE_VERSION_N4" "0")
# set ("winver_PRODUCT_VERSION_N1" "0")
-# set ("winver_PRODUCT_VERSION_N2" "11")
+# set ("winver_PRODUCT_VERSION_N2" "9")
# set ("winver_PRODUCT_VERSION_N3" "0")
# set ("winver_PRODUCT_VERSION_N4" "0")
# set ("winver_LEGAL_COPYRIGHT" "")
@@ -46,10 +46,10 @@
#
# Specification of per-project settings:
#
-# set ("winver_${projectName}_FileVersionBinary" "0,11,0,0")
-# set ("winver_${projectName}_ProductVersionBinary" "0,11,0,0")
-# set ("winver_${projectName}_FileVersionString" "0, 11, 0, 0")
-# set ("winver_${projectName}_ProductVersionString" "0, 11, 0, 0")
+# set ("winver_${projectName}_FileVersionBinary" "0,9,0,0")
+# set ("winver_${projectName}_ProductVersionBinary" "0,9,0,0")
+# set ("winver_${projectName}_FileVersionString" "0, 9, 0, 0")
+# set ("winver_${projectName}_ProductVersionString" "0, 9, 0, 0")
# set ("winver_${projectName}_FileDescription" "qpid-cpp-qpidcommon Library")
# set ("winver_${projectName}_LegalCopyright" "")
# set ("winver_${projectName}_InternalName" "qpidcommon")
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
index 6230a8f6f6..2cd6ad462f 100644
--- a/cpp/src/Makefile.am
+++ b/cpp/src/Makefile.am
@@ -37,7 +37,6 @@ windows_dist = \
qpid/sys/windows/IOHandle.cpp \
qpid/sys/windows/IoHandlePrivate.h \
qpid/sys/windows/LockFile.cpp \
- qpid/sys/windows/mingw32_compat.h \
qpid/sys/windows/PollableCondition.cpp \
qpid/sys/windows/PipeHandle.cpp \
../include/qpid/sys/windows/Mutex.h \
@@ -89,7 +88,7 @@ rgen_cmd=ruby -I $(rgen_dir) $(rgen_dir)/generate . ../include $(specs) all
$(rgen_srcs) $(srcdir)/rubygen.mk: rgen.timestamp
rgen.timestamp: $(rgen_generator) $(specs)
- $(rgen_cmd) $(srcdir)/rubygen.mk && touch $@
+ $(rgen_cmd) $(srcdir)/rubygen.mk; touch $@
$(rgen_generator):
# The CMake version is needed for dist
@@ -128,14 +127,14 @@ qpidexec_SCRIPTS =
qpidtestdir = $(qpidexecdir)/tests
qpidtest_PROGRAMS =
qpidtest_SCRIPTS =
-tmoduleexecdir = $(libdir)/qpid/tests
-tmoduleexec_LTLIBRARIES=
+tmoduledir = $(libdir)/qpid/tests
+tmodule_LTLIBRARIES=
AM_CXXFLAGS += -DBOOST_FILESYSTEM_VERSION=2
## Automake macros to build libraries and executables.
-qpidd_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDD_MODULE_DIR=\"$(dmoduleexecdir)\" -DQPIDD_CONF_FILE=\"$(sysconfdir)/qpidd.conf\"
-libqpidclient_la_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDC_MODULE_DIR=\"$(cmoduleexecdir)\" -DQPIDC_CONF_FILE=\"$(confdir)/qpidc.conf\"
+qpidd_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDD_MODULE_DIR=\"$(dmoduledir)\" -DQPIDD_CONF_FILE=\"$(sysconfdir)/qpidd.conf\"
+libqpidclient_la_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDC_MODULE_DIR=\"$(cmoduledir)\" -DQPIDC_CONF_FILE=\"$(confdir)/qpidc.conf\"
qpidd_LDADD = \
libqpidbroker.la \
@@ -177,7 +176,7 @@ nobase_include_HEADERS += \
../include/qpid/sys/posix/Time.h \
../include/qpid/sys/posix/check.h
-if HAVE_EPOLL
+if HAVE_EPOLL
poller = qpid/sys/epoll/EpollPoller.cpp
endif
@@ -196,15 +195,15 @@ libqpidcommon_la_SOURCES += $(poller) $(systeminfo)
posix_broker_src = \
qpid/broker/posix/BrokerDefaults.cpp
-lib_LTLIBRARIES = libqpidtypes.la libqpidcommon.la libqpidbroker.la libqpidclient.la libqpidmessaging.la
+lib_LTLIBRARIES = libqpidtypes.la libqpidcommon.la libqpidbroker.la libqpidclient.la libqpidmessaging.la
# Definitions for client and daemon plugins
PLUGINLDFLAGS=-no-undefined -module -avoid-version
confdir=$(sysconfdir)/qpid
-dmoduleexecdir=$(libdir)/qpid/daemon
-cmoduleexecdir=$(libdir)/qpid/client
-dmoduleexec_LTLIBRARIES =
-cmoduleexec_LTLIBRARIES =
+dmoduledir=$(libdir)/qpid/daemon
+cmoduledir=$(libdir)/qpid/client
+dmodule_LTLIBRARIES =
+cmodule_LTLIBRARIES =
include cluster.mk
include acl.mk
@@ -246,7 +245,7 @@ rdma_la_LIBADD = \
rdma_la_LDFLAGS = $(PLUGINLDFLAGS)
rdma_la_CXXFLAGS = \
$(AM_CXXFLAGS) -Wno-missing-field-initializers
-dmoduleexec_LTLIBRARIES += \
+dmodule_LTLIBRARIES += \
rdma.la
rdmaconnector_la_SOURCES = \
@@ -258,7 +257,7 @@ rdmaconnector_la_LIBADD = \
rdmaconnector_la_LDFLAGS = $(PLUGINLDFLAGS)
rdmaconnector_la_CXXFLAGS = \
$(AM_CXXFLAGS) -Wno-missing-field-initializers
-cmoduleexec_LTLIBRARIES += \
+cmodule_LTLIBRARIES += \
rdmaconnector.la
# RDMA test/sample programs
@@ -333,7 +332,6 @@ libqpidcommon_la_SOURCES += \
qpid/Address.cpp \
qpid/DataDir.cpp \
qpid/DataDir.h \
- qpid/DisableExceptionLogging.h \
qpid/Exception.cpp \
qpid/Modules.cpp \
qpid/Modules.h \
@@ -343,7 +341,6 @@ libqpidcommon_la_SOURCES += \
qpid/RefCounted.h \
qpid/RefCountedBuffer.cpp \
qpid/RefCountedBuffer.h \
- qpid/BufferRef.h \
qpid/Sasl.h \
qpid/SaslFactory.cpp \
qpid/SaslFactory.h \
@@ -564,7 +561,8 @@ libqpidbroker_la_SOURCES = \
qpid/broker/HandlerImpl.h \
qpid/broker/HeadersExchange.cpp \
qpid/broker/HeadersExchange.h \
- qpid/broker/AsyncCompletion.h \
+ qpid/broker/IncompleteMessageList.cpp \
+ qpid/broker/IncompleteMessageList.h \
qpid/broker/LegacyLVQ.h \
qpid/broker/LegacyLVQ.cpp \
qpid/broker/Link.cpp \
@@ -614,9 +612,9 @@ libqpidbroker_la_SOURCES = \
qpid/broker/QueueRegistry.cpp \
qpid/broker/QueueRegistry.h \
qpid/broker/QueuedMessage.h \
- qpid/broker/QueueFlowLimit.h \
- qpid/broker/QueueFlowLimit.cpp \
qpid/broker/RateFlowcontrol.h \
+ qpid/broker/RateTracker.cpp \
+ qpid/broker/RateTracker.h \
qpid/broker/RecoverableConfig.h \
qpid/broker/RecoverableExchange.h \
qpid/broker/RecoverableMessage.h \
@@ -653,7 +651,6 @@ libqpidbroker_la_SOURCES = \
qpid/broker/SessionState.h \
qpid/broker/SignalHandler.cpp \
qpid/broker/SignalHandler.h \
- qpid/broker/StatefulQueueObserver.h \
qpid/broker/System.cpp \
qpid/broker/System.h \
qpid/broker/ThresholdAlerts.cpp \
@@ -671,11 +668,6 @@ libqpidbroker_la_SOURCES = \
qpid/broker/TxPublish.h \
qpid/broker/Vhost.cpp \
qpid/broker/Vhost.h \
- qpid/broker/MessageDistributor.h \
- qpid/broker/FifoDistributor.h \
- qpid/broker/FifoDistributor.cpp \
- qpid/broker/MessageGroupManager.cpp \
- qpid/broker/MessageGroupManager.h \
qpid/management/ManagementAgent.cpp \
qpid/management/ManagementAgent.h \
qpid/management/ManagementDirectExchange.cpp \
@@ -747,7 +739,7 @@ libqpidclient_la_SOURCES = \
QPIDCLIENT_VERSION_INFO = 2:0:0
libqpidclient_la_LDFLAGS = -version-info $(QPIDCLIENT_VERSION_INFO)
-libqpidtypes_la_LIBADD= -luuid
+libqpidtypes_la_libadd=-luuid
libqpidtypes_la_SOURCES= \
qpid/types/Exception.cpp \
qpid/types/Uuid.cpp \
@@ -794,7 +786,9 @@ libqpidmessaging_la_SOURCES = \
qpid/client/amqp0_10/SessionImpl.h \
qpid/client/amqp0_10/SessionImpl.cpp \
qpid/client/amqp0_10/SenderImpl.h \
- qpid/client/amqp0_10/SenderImpl.cpp
+ qpid/client/amqp0_10/SenderImpl.cpp \
+ qpid/client/amqp0_10/SimpleUrlParser.h \
+ qpid/client/amqp0_10/SimpleUrlParser.cpp
QPIDMESSAGING_VERSION_INFO = 2:0:0
libqpidmessaging_la_LDFLAGS = -version-info $(QPIDMESSAGING_VERSION_INFO)
@@ -807,7 +801,6 @@ nobase_include_HEADERS += \
../include/qpid/Address.h \
../include/qpid/CommonImportExport.h \
../include/qpid/Exception.h \
- ../include/qpid/ImportExport.h \
../include/qpid/InlineAllocator.h \
../include/qpid/InlineVector.h \
../include/qpid/Msg.h \
@@ -890,10 +883,14 @@ nobase_include_HEADERS += \
../include/qpid/types/Variant.h \
../include/qpid/types/ImportExport.h
+# Force build of qpidd during dist phase so help2man will work.
+dist-hook: $(BUILT_SOURCES)
+ $(MAKE) qpidd
+
# Create the default data directory
install-data-local:
$(mkinstalldirs) $(DESTDIR)/$(localstatedir)/lib/qpidd
-# Support for pkg-config
+# Support for pkg-config
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = qpid.pc
diff --git a/cpp/src/acl.mk b/cpp/src/acl.mk
index b8e2ff0e13..bcd1d88335 100644
--- a/cpp/src/acl.mk
+++ b/cpp/src/acl.mk
@@ -18,8 +18,8 @@
#
#
# acl library makefile fragment, to be included in Makefile.am
-#
-dmoduleexec_LTLIBRARIES += acl.la
+#
+dmodule_LTLIBRARIES += acl.la
acl_la_SOURCES = \
qpid/acl/Acl.cpp \
diff --git a/cpp/src/cluster.mk b/cpp/src/cluster.mk
index 3ce4ce25b3..a791b2d41a 100644
--- a/cpp/src/cluster.mk
+++ b/cpp/src/cluster.mk
@@ -18,7 +18,7 @@
#
#
# Cluster library makefile fragment, to be included in Makefile.am
-#
+#
# Optional CMAN support
@@ -34,7 +34,7 @@ endif
if HAVE_LIBCPG
-dmoduleexec_LTLIBRARIES += cluster.la
+dmodule_LTLIBRARIES += cluster.la
cluster_la_SOURCES = \
$(CMAN_SOURCES) \
@@ -102,7 +102,7 @@ cluster_la_CXXFLAGS = $(AM_CXXFLAGS) -fno-strict-aliasing
cluster_la_LDFLAGS = $(PLUGINLDFLAGS)
# The watchdog plugin and helper executable
-dmoduleexec_LTLIBRARIES += watchdog.la
+dmodule_LTLIBRARIES += watchdog.la
watchdog_la_SOURCES = qpid/cluster/WatchDogPlugin.cpp
watchdog_la_LIBADD = libqpidbroker.la
watchdog_la_LDFLAGS = $(PLUGINLDFLAGS)
diff --git a/cpp/src/posix/QpiddBroker.cpp b/cpp/src/posix/QpiddBroker.cpp
index 1cebcfc3ac..86504ba7fc 100644
--- a/cpp/src/posix/QpiddBroker.cpp
+++ b/cpp/src/posix/QpiddBroker.cpp
@@ -138,9 +138,6 @@ struct QpiddDaemon : public Daemon {
brokerPtr->accept();
uint16_t port=brokerPtr->getPort(options->daemon.transport);
ready(port); // Notify parent.
- if (options->parent->broker.enableMgmt && (options->parent->broker.port == 0 || options->daemon.transport != TCP)) {
- dynamic_cast<qmf::org::apache::qpid::broker::Broker*>(brokerPtr->GetManagementObject())->set_port(port);
- }
brokerPtr->run();
}
};
@@ -185,13 +182,8 @@ int QpiddBroker::execute (QpiddOptions *options) {
boost::intrusive_ptr<Broker> brokerPtr(new Broker(options->broker));
ScopedSetBroker ssb(brokerPtr);
brokerPtr->accept();
- if (options->broker.port == 0 || myOptions->daemon.transport != TCP) {
- uint16_t port = brokerPtr->getPort(myOptions->daemon.transport);
- cout << port << endl;
- if (options->broker.enableMgmt) {
- dynamic_cast<qmf::org::apache::qpid::broker::Broker*>(brokerPtr->GetManagementObject())->set_port(port);
- }
- }
+ if (options->broker.port == 0 || myOptions->daemon.transport != TCP)
+ cout << uint16_t(brokerPtr->getPort(myOptions->daemon.transport)) << endl;
brokerPtr->run();
}
return 0;
diff --git a/cpp/src/qmf.mk b/cpp/src/qmf.mk
index 3b6583bfaf..f3462f1a93 100644
--- a/cpp/src/qmf.mk
+++ b/cpp/src/qmf.mk
@@ -43,7 +43,6 @@ QMF2_API = \
../include/qmf/ConsoleSession.h \
../include/qmf/DataAddr.h \
../include/qmf/Data.h \
- ../include/qmf/posix/EventNotifier.h \
../include/qmf/exceptions.h \
../include/qmf/Handle.h \
../include/qmf/ImportExport.h \
@@ -93,7 +92,6 @@ libqmf2_la_SOURCES = \
qmf/AgentEventImpl.h \
qmf/AgentImpl.h \
qmf/AgentSession.cpp \
- qmf/AgentSessionImpl.h \
qmf/AgentSubscription.cpp \
qmf/AgentSubscription.h \
qmf/ConsoleEvent.cpp \
@@ -106,22 +104,17 @@ libqmf2_la_SOURCES = \
qmf/DataAddrImpl.h \
qmf/Data.cpp \
qmf/DataImpl.h \
- qmf/EventNotifierImpl.cpp \
- qmf/EventNotifierImpl.h \
qmf/exceptions.cpp \
qmf/Expression.cpp \
qmf/Expression.h \
qmf/Hash.cpp \
qmf/Hash.h \
- qmf/PosixEventNotifier.cpp \
- qmf/PosixEventNotifierImpl.cpp \
- qmf/PosixEventNotifierImpl.h \
qmf/PrivateImplRef.h \
qmf/Query.cpp \
qmf/QueryImpl.h \
+ qmf/Schema.cpp \
qmf/SchemaCache.cpp \
qmf/SchemaCache.h \
- qmf/Schema.cpp \
qmf/SchemaId.cpp \
qmf/SchemaIdImpl.h \
qmf/SchemaImpl.h \
diff --git a/cpp/src/qmf/Agent.cpp b/cpp/src/qmf/Agent.cpp
index 684f8e4fba..915f2a1c88 100644
--- a/cpp/src/qmf/Agent.cpp
+++ b/cpp/src/qmf/Agent.cpp
@@ -72,7 +72,7 @@ Schema Agent::getSchema(const SchemaId& s, Duration t) { return impl->getSchema(
AgentImpl::AgentImpl(const std::string& n, uint32_t e, ConsoleSessionImpl& s) :
name(n), directSubject(n), epoch(e), session(s), touched(true), untouchedCount(0), capability(0),
- sender(session.directSender), schemaCache(s.schemaCache)
+ sender(session.directSender), nextCorrelator(1), schemaCache(s.schemaCache)
{
}
@@ -102,11 +102,12 @@ const Variant& AgentImpl::getAttribute(const string& k) const
ConsoleEvent AgentImpl::query(const Query& query, Duration timeout)
{
boost::shared_ptr<SyncContext> context(new SyncContext());
- uint32_t correlator(session.correlator());
+ uint32_t correlator;
ConsoleEvent result;
{
qpid::sys::Mutex::ScopedLock l(lock);
+ correlator = nextCorrelator++;
contextMap[correlator] = context;
}
try {
@@ -150,7 +151,12 @@ ConsoleEvent AgentImpl::query(const string& text, Duration timeout)
uint32_t AgentImpl::queryAsync(const Query& query)
{
- uint32_t correlator(session.correlator());
+ uint32_t correlator;
+
+ {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ correlator = nextCorrelator++;
+ }
sendQuery(query, correlator);
return correlator;
@@ -166,11 +172,12 @@ uint32_t AgentImpl::queryAsync(const string& text)
ConsoleEvent AgentImpl::callMethod(const string& method, const Variant::Map& args, const DataAddr& addr, Duration timeout)
{
boost::shared_ptr<SyncContext> context(new SyncContext());
- uint32_t correlator(session.correlator());
+ uint32_t correlator;
ConsoleEvent result;
{
qpid::sys::Mutex::ScopedLock l(lock);
+ correlator = nextCorrelator++;
contextMap[correlator] = context;
}
try {
@@ -206,7 +213,12 @@ ConsoleEvent AgentImpl::callMethod(const string& method, const Variant::Map& arg
uint32_t AgentImpl::callMethodAsync(const string& method, const Variant::Map& args, const DataAddr& addr)
{
- uint32_t correlator(session.correlator());
+ uint32_t correlator;
+
+ {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ correlator = nextCorrelator++;
+ }
sendMethod(method, args, addr, correlator);
return correlator;
@@ -584,7 +596,12 @@ void AgentImpl::sendMethod(const string& method, const Variant::Map& args, const
void AgentImpl::sendSchemaRequest(const SchemaId& id)
{
- uint32_t correlator(session.correlator());
+ uint32_t correlator;
+
+ {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ correlator = nextCorrelator++;
+ }
if (capability >= AGENT_CAPABILITY_V2_SCHEMA) {
Query query(QUERY_SCHEMA, id);
diff --git a/cpp/src/qmf/AgentImpl.h b/cpp/src/qmf/AgentImpl.h
index 09754a3a7e..7fa4f4373a 100644
--- a/cpp/src/qmf/AgentImpl.h
+++ b/cpp/src/qmf/AgentImpl.h
@@ -99,6 +99,7 @@ namespace qmf {
uint32_t capability;
qpid::messaging::Sender sender;
qpid::types::Variant::Map attributes;
+ uint32_t nextCorrelator;
std::map<uint32_t, boost::shared_ptr<SyncContext> > contextMap;
boost::shared_ptr<SchemaCache> schemaCache;
mutable std::set<std::string> packageSet;
diff --git a/cpp/src/qmf/AgentSession.cpp b/cpp/src/qmf/AgentSession.cpp
index 251c25fd44..4c5a72a467 100644
--- a/cpp/src/qmf/AgentSession.cpp
+++ b/cpp/src/qmf/AgentSession.cpp
@@ -19,7 +19,132 @@
*
*/
-#include "qmf/AgentSessionImpl.h"
+#include "qpid/RefCounted.h"
+#include "qmf/PrivateImplRef.h"
+#include "qmf/exceptions.h"
+#include "qmf/AgentSession.h"
+#include "qmf/AgentEventImpl.h"
+#include "qmf/SchemaIdImpl.h"
+#include "qmf/SchemaImpl.h"
+#include "qmf/DataAddrImpl.h"
+#include "qmf/DataImpl.h"
+#include "qmf/QueryImpl.h"
+#include "qmf/agentCapability.h"
+#include "qmf/constants.h"
+#include "qpid/sys/Mutex.h"
+#include "qpid/sys/Condition.h"
+#include "qpid/sys/Thread.h"
+#include "qpid/sys/Runnable.h"
+#include "qpid/log/Statement.h"
+#include "qpid/messaging/Connection.h"
+#include "qpid/messaging/Session.h"
+#include "qpid/messaging/Receiver.h"
+#include "qpid/messaging/Sender.h"
+#include "qpid/messaging/Message.h"
+#include "qpid/messaging/AddressParser.h"
+#include "qpid/management/Buffer.h"
+#include <queue>
+#include <map>
+#include <set>
+#include <iostream>
+#include <memory>
+
+using namespace std;
+using namespace qpid::messaging;
+using namespace qmf;
+using qpid::types::Variant;
+
+namespace qmf {
+ class AgentSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable {
+ public:
+ ~AgentSessionImpl();
+
+ //
+ // Methods from API handle
+ //
+ AgentSessionImpl(Connection& c, const string& o);
+ void setDomain(const string& d) { checkOpen(); domain = d; }
+ void setVendor(const string& v) { checkOpen(); attributes["_vendor"] = v; }
+ void setProduct(const string& p) { checkOpen(); attributes["_product"] = p; }
+ void setInstance(const string& i) { checkOpen(); attributes["_instance"] = i; }
+ void setAttribute(const string& k, const qpid::types::Variant& v) { checkOpen(); attributes[k] = v; }
+ const string& getName() const { return agentName; }
+ void open();
+ void close();
+ bool nextEvent(AgentEvent& e, Duration t);
+
+ void registerSchema(Schema& s);
+ DataAddr addData(Data& d, const string& n, bool persist);
+ void delData(const DataAddr&);
+
+ void authAccept(AgentEvent& e);
+ void authReject(AgentEvent& e, const string& m);
+ void raiseException(AgentEvent& e, const string& s);
+ void raiseException(AgentEvent& e, const Data& d);
+ void response(AgentEvent& e, const Data& d);
+ void complete(AgentEvent& e);
+ void methodSuccess(AgentEvent& e);
+ void raiseEvent(const Data& d);
+ void raiseEvent(const Data& d, int s);
+
+ private:
+ typedef map<DataAddr, Data, DataAddrCompare> DataIndex;
+ typedef map<SchemaId, Schema, SchemaIdCompare> SchemaMap;
+
+ mutable qpid::sys::Mutex lock;
+ qpid::sys::Condition cond;
+ Connection connection;
+ Session session;
+ Sender directSender;
+ Sender topicSender;
+ string domain;
+ Variant::Map attributes;
+ Variant::Map options;
+ string agentName;
+ bool opened;
+ queue<AgentEvent> eventQueue;
+ qpid::sys::Thread* thread;
+ bool threadCanceled;
+ uint32_t bootSequence;
+ uint32_t interval;
+ uint64_t lastHeartbeat;
+ uint64_t lastVisit;
+ bool forceHeartbeat;
+ bool externalStorage;
+ bool autoAllowQueries;
+ bool autoAllowMethods;
+ uint32_t maxSubscriptions;
+ uint32_t minSubInterval;
+ uint32_t subLifetime;
+ bool publicEvents;
+ bool listenOnDirect;
+ bool strictSecurity;
+ uint64_t schemaUpdateTime;
+ string directBase;
+ string topicBase;
+
+ SchemaMap schemata;
+ DataIndex globalIndex;
+ map<SchemaId, DataIndex, SchemaIdCompareNoHash> schemaIndex;
+
+ void checkOpen();
+ void setAgentName();
+ void enqueueEvent(const AgentEvent&);
+ void handleLocateRequest(const Variant::List& content, const Message& msg);
+ void handleMethodRequest(const Variant::Map& content, const Message& msg);
+ void handleQueryRequest(const Variant::Map& content, const Message& msg);
+ void handleSchemaRequest(AgentEvent&);
+ void handleV1SchemaRequest(qpid::management::Buffer&, uint32_t, const Message&);
+ void dispatch(Message);
+ void sendHeartbeat();
+ void send(Message, const Address&);
+ void flushResponses(AgentEvent&, bool);
+ void periodicProcessing(uint64_t);
+ void run();
+ };
+}
+
+typedef qmf::PrivateImplRef<AgentSession> PI;
AgentSession::AgentSession(AgentSessionImpl* impl) { PI::ctor(*this, impl); }
AgentSession::AgentSession(const AgentSession& s) : qmf::Handle<AgentSessionImpl>() { PI::copy(*this, s); }
@@ -36,7 +161,6 @@ const string& AgentSession::getName() const { return impl->getName(); }
void AgentSession::open() { impl->open(); }
void AgentSession::close() { impl->close(); }
bool AgentSession::nextEvent(AgentEvent& e, Duration t) { return impl->nextEvent(e, t); }
-int AgentSession::pendingEvents() const { return impl->pendingEvents(); }
void AgentSession::registerSchema(Schema& s) { impl->registerSchema(s); }
DataAddr AgentSession::addData(Data& d, const string& n, bool p) { return impl->addData(d, n, p); }
void AgentSession::delData(const DataAddr& a) { impl->delData(a); }
@@ -55,11 +179,11 @@ void AgentSession::raiseEvent(const Data& d, int s) { impl->raiseEvent(d, s); }
//========================================================================================
AgentSessionImpl::AgentSessionImpl(Connection& c, const string& options) :
- connection(c), domain("default"), opened(false), eventNotifier(0), thread(0), threadCanceled(false),
+ connection(c), domain("default"), opened(false), thread(0), threadCanceled(false),
bootSequence(1), interval(60), lastHeartbeat(0), lastVisit(0), forceHeartbeat(false),
externalStorage(false), autoAllowQueries(true), autoAllowMethods(true),
maxSubscriptions(64), minSubInterval(3000), subLifetime(300), publicEvents(true),
- listenOnDirect(true), strictSecurity(false), maxThreadWaitTime(5),
+ listenOnDirect(true), strictSecurity(false),
schemaUpdateTime(uint64_t(qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now())))
{
//
@@ -120,14 +244,7 @@ AgentSessionImpl::AgentSessionImpl(Connection& c, const string& options) :
iter = optMap.find("strict-security");
if (iter != optMap.end())
strictSecurity = iter->second.asBool();
-
- iter = optMap.find("max-thread-wait-time");
- if (iter != optMap.end())
- maxThreadWaitTime = iter->second.asUint32();
}
-
- if (maxThreadWaitTime > interval)
- maxThreadWaitTime = interval;
}
@@ -135,11 +252,6 @@ AgentSessionImpl::~AgentSessionImpl()
{
if (opened)
close();
-
- if (thread) {
- thread->join();
- delete thread;
- }
}
@@ -148,12 +260,6 @@ void AgentSessionImpl::open()
if (opened)
throw QmfException("The session is already open");
- // If the thread exists, join and delete it before creating a new one.
- if (thread) {
- thread->join();
- delete thread;
- }
-
const string addrArgs(";{create:never,node:{type:topic}}");
const string routableAddr("direct-agent.route." + qpid::types::Uuid(true).str());
attributes["_direct_subject"] = routableAddr;
@@ -191,26 +297,19 @@ void AgentSessionImpl::open()
}
-void AgentSessionImpl::closeAsync()
+void AgentSessionImpl::close()
{
if (!opened)
return;
- // Stop the receiver thread. Don't join it until the destructor is called or open() is called.
+ // Stop and join the receiver thread
threadCanceled = true;
- opened = false;
-}
+ thread->join();
+ delete thread;
-
-void AgentSessionImpl::close()
-{
- closeAsync();
-
- if (thread) {
- thread->join();
- delete thread;
- thread = 0;
- }
+ // Close the AMQP session
+ session.close();
+ opened = false;
}
@@ -219,19 +318,13 @@ bool AgentSessionImpl::nextEvent(AgentEvent& event, Duration timeout)
uint64_t milliseconds = timeout.getMilliseconds();
qpid::sys::Mutex::ScopedLock l(lock);
- if (eventQueue.empty() && milliseconds > 0) {
- int64_t nsecs(qpid::sys::TIME_INFINITE);
- if ((uint64_t)(nsecs / 1000000) > milliseconds)
- nsecs = (int64_t) milliseconds * 1000000;
- qpid::sys::Duration then(nsecs);
- cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(), then));
- }
+ if (eventQueue.empty())
+ cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(),
+ qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC)));
if (!eventQueue.empty()) {
event = eventQueue.front();
eventQueue.pop();
- if (eventQueue.empty())
- alertEventNotifierLH(false);
return true;
}
@@ -239,26 +332,6 @@ bool AgentSessionImpl::nextEvent(AgentEvent& event, Duration timeout)
}
-int AgentSessionImpl::pendingEvents() const
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- return eventQueue.size();
-}
-
-
-void AgentSessionImpl::setEventNotifier(EventNotifierImpl* notifier)
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- eventNotifier = notifier;
-}
-
-EventNotifierImpl* AgentSessionImpl::getEventNotifier() const
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- return eventNotifier;
-}
-
-
void AgentSessionImpl::registerSchema(Schema& schema)
{
if (!schema.isFinalized())
@@ -514,10 +587,8 @@ void AgentSessionImpl::enqueueEvent(const AgentEvent& event)
qpid::sys::Mutex::ScopedLock l(lock);
bool notify = eventQueue.empty();
eventQueue.push(event);
- if (notify) {
+ if (notify)
cond.notify();
- alertEventNotifierLH(true);
- }
}
@@ -961,13 +1032,6 @@ void AgentSessionImpl::periodicProcessing(uint64_t seconds)
}
-void AgentSessionImpl::alertEventNotifierLH(bool readable)
-{
- if (eventNotifier)
- eventNotifier->setReadable(readable);
-}
-
-
void AgentSessionImpl::run()
{
QPID_LOG(debug, "AgentSession thread started for agent " << agentName);
@@ -977,7 +1041,7 @@ void AgentSessionImpl::run()
periodicProcessing((uint64_t) qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now()) / qpid::sys::TIME_SEC);
Receiver rx;
- bool valid = session.nextReceiver(rx, Duration::SECOND * maxThreadWaitTime);
+ bool valid = session.nextReceiver(rx, Duration::SECOND);
if (threadCanceled)
break;
if (valid) {
@@ -994,19 +1058,6 @@ void AgentSessionImpl::run()
enqueueEvent(AgentEvent(new AgentEventImpl(AGENT_THREAD_FAILED)));
}
- session.close();
QPID_LOG(debug, "AgentSession thread exiting for agent " << agentName);
}
-
-AgentSessionImpl& AgentSessionImplAccess::get(AgentSession& session)
-{
- return *session.impl;
-}
-
-
-const AgentSessionImpl& AgentSessionImplAccess::get(const AgentSession& session)
-{
- return *session.impl;
-}
-
diff --git a/cpp/src/qmf/AgentSessionImpl.h b/cpp/src/qmf/AgentSessionImpl.h
deleted file mode 100644
index ae512a4054..0000000000
--- a/cpp/src/qmf/AgentSessionImpl.h
+++ /dev/null
@@ -1,175 +0,0 @@
-#ifndef __QMF_AGENT_SESSION_IMPL_H
-#define __QMF_AGENT_SESSION_IMPL_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/RefCounted.h"
-#include "qmf/PrivateImplRef.h"
-#include "qmf/exceptions.h"
-#include "qmf/AgentSession.h"
-#include "qmf/AgentEventImpl.h"
-#include "qmf/EventNotifierImpl.h"
-#include "qpid/messaging/Connection.h"
-#include "qpid/sys/Runnable.h"
-#include "qpid/sys/Mutex.h"
-#include "qpid/sys/Condition.h"
-#include "qpid/sys/Thread.h"
-#include "qpid/sys/Runnable.h"
-#include "qpid/log/Statement.h"
-#include "qpid/messaging/Connection.h"
-#include "qpid/messaging/Session.h"
-#include "qpid/messaging/Receiver.h"
-#include "qpid/messaging/Sender.h"
-#include "qpid/messaging/Message.h"
-#include "qpid/messaging/AddressParser.h"
-#include "qpid/management/Buffer.h"
-#include "qpid/RefCounted.h"
-#include "qmf/PrivateImplRef.h"
-#include "qmf/AgentSession.h"
-#include "qmf/exceptions.h"
-#include "qmf/AgentSession.h"
-#include "qmf/SchemaIdImpl.h"
-#include "qmf/SchemaImpl.h"
-#include "qmf/DataAddrImpl.h"
-#include "qmf/DataImpl.h"
-#include "qmf/QueryImpl.h"
-#include "qmf/agentCapability.h"
-#include "qmf/constants.h"
-
-#include <queue>
-#include <map>
-#include <iostream>
-#include <memory>
-
-using namespace std;
-using namespace qpid::messaging;
-using namespace qmf;
-using qpid::types::Variant;
-
-typedef qmf::PrivateImplRef<AgentSession> PI;
-
-namespace qmf {
- class AgentSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable {
- public:
- ~AgentSessionImpl();
-
- //
- // Methods from API handle
- //
- AgentSessionImpl(Connection& c, const string& o);
- void setDomain(const string& d) { checkOpen(); domain = d; }
- void setVendor(const string& v) { checkOpen(); attributes["_vendor"] = v; }
- void setProduct(const string& p) { checkOpen(); attributes["_product"] = p; }
- void setInstance(const string& i) { checkOpen(); attributes["_instance"] = i; }
- void setAttribute(const string& k, const qpid::types::Variant& v) { checkOpen(); attributes[k] = v; }
- const string& getName() const { return agentName; }
- void open();
- void closeAsync();
- void close();
- bool nextEvent(AgentEvent& e, Duration t);
- int pendingEvents() const;
-
- void setEventNotifier(EventNotifierImpl* eventNotifier);
- EventNotifierImpl* getEventNotifier() const;
-
- void registerSchema(Schema& s);
- DataAddr addData(Data& d, const string& n, bool persist);
- void delData(const DataAddr&);
-
- void authAccept(AgentEvent& e);
- void authReject(AgentEvent& e, const string& m);
- void raiseException(AgentEvent& e, const string& s);
- void raiseException(AgentEvent& e, const Data& d);
- void response(AgentEvent& e, const Data& d);
- void complete(AgentEvent& e);
- void methodSuccess(AgentEvent& e);
- void raiseEvent(const Data& d);
- void raiseEvent(const Data& d, int s);
-
- private:
- typedef map<DataAddr, Data, DataAddrCompare> DataIndex;
- typedef map<SchemaId, Schema, SchemaIdCompare> SchemaMap;
-
- mutable qpid::sys::Mutex lock;
- qpid::sys::Condition cond;
- Connection connection;
- Session session;
- Sender directSender;
- Sender topicSender;
- string domain;
- Variant::Map attributes;
- Variant::Map options;
- string agentName;
- bool opened;
- queue<AgentEvent> eventQueue;
- EventNotifierImpl* eventNotifier;
- qpid::sys::Thread* thread;
- bool threadCanceled;
- uint32_t bootSequence;
- uint32_t interval;
- uint64_t lastHeartbeat;
- uint64_t lastVisit;
- bool forceHeartbeat;
- bool externalStorage;
- bool autoAllowQueries;
- bool autoAllowMethods;
- uint32_t maxSubscriptions;
- uint32_t minSubInterval;
- uint32_t subLifetime;
- bool publicEvents;
- bool listenOnDirect;
- bool strictSecurity;
- uint32_t maxThreadWaitTime;
- uint64_t schemaUpdateTime;
- string directBase;
- string topicBase;
-
- SchemaMap schemata;
- DataIndex globalIndex;
- map<SchemaId, DataIndex, SchemaIdCompareNoHash> schemaIndex;
-
- void checkOpen();
- void setAgentName();
- void enqueueEvent(const AgentEvent&);
- void alertEventNotifierLH(bool readable);
- void handleLocateRequest(const Variant::List& content, const Message& msg);
- void handleMethodRequest(const Variant::Map& content, const Message& msg);
- void handleQueryRequest(const Variant::Map& content, const Message& msg);
- void handleSchemaRequest(AgentEvent&);
- void handleV1SchemaRequest(qpid::management::Buffer&, uint32_t, const Message&);
- void dispatch(Message);
- void sendHeartbeat();
- void send(Message, const Address&);
- void flushResponses(AgentEvent&, bool);
- void periodicProcessing(uint64_t);
- void run();
- };
-
- struct AgentSessionImplAccess {
- static AgentSessionImpl& get(AgentSession& session);
- static const AgentSessionImpl& get(const AgentSession& session);
- };
-}
-
-
-#endif
-
diff --git a/cpp/src/qmf/ConsoleSession.cpp b/cpp/src/qmf/ConsoleSession.cpp
index 2dfc894c58..e12c1152f6 100644
--- a/cpp/src/qmf/ConsoleSession.cpp
+++ b/cpp/src/qmf/ConsoleSession.cpp
@@ -54,7 +54,6 @@ void ConsoleSession::setAgentFilter(const string& f) { impl->setAgentFilter(f);
void ConsoleSession::open() { impl->open(); }
void ConsoleSession::close() { impl->close(); }
bool ConsoleSession::nextEvent(ConsoleEvent& e, Duration t) { return impl->nextEvent(e, t); }
-int ConsoleSession::pendingEvents() const { return impl->pendingEvents(); }
uint32_t ConsoleSession::getAgentCount() const { return impl->getAgentCount(); }
Agent ConsoleSession::getAgent(uint32_t i) const { return impl->getAgent(i); }
Agent ConsoleSession::getConnectedBrokerAgent() const { return impl->getConnectedBrokerAgent(); }
@@ -66,9 +65,9 @@ Subscription ConsoleSession::subscribe(const string& q, const string& f, const s
//========================================================================================
ConsoleSessionImpl::ConsoleSessionImpl(Connection& c, const string& options) :
- connection(c), domain("default"), maxAgentAgeMinutes(5), listenOnDirect(true), strictSecurity(false), maxThreadWaitTime(5),
- opened(false), eventNotifier(0), thread(0), threadCanceled(false), lastVisit(0), lastAgePass(0),
- connectedBrokerInAgentList(false), schemaCache(new SchemaCache()), nextCorrelator(1)
+ connection(c), domain("default"), maxAgentAgeMinutes(5),
+ opened(false), thread(0), threadCanceled(false), lastVisit(0), lastAgePass(0),
+ connectedBrokerInAgentList(false), schemaCache(new SchemaCache())
{
if (!options.empty()) {
qpid::messaging::AddressParser parser(options);
@@ -92,14 +91,7 @@ ConsoleSessionImpl::ConsoleSessionImpl(Connection& c, const string& options) :
iter = optMap.find("strict-security");
if (iter != optMap.end())
strictSecurity = iter->second.asBool();
-
- iter = optMap.find("max-thread-wait-time");
- if (iter != optMap.end())
- maxThreadWaitTime = iter->second.asUint32();
}
-
- if (maxThreadWaitTime > 60)
- maxThreadWaitTime = 60;
}
@@ -107,11 +99,6 @@ ConsoleSessionImpl::~ConsoleSessionImpl()
{
if (opened)
close();
-
- if (thread) {
- thread->join();
- delete thread;
- }
}
@@ -166,12 +153,6 @@ void ConsoleSessionImpl::open()
if (opened)
throw QmfException("The session is already open");
- // If the thread exists, join and delete it before creating a new one.
- if (thread) {
- thread->join();
- delete thread;
- }
-
// Establish messaging addresses
directBase = "qmf." + domain + ".direct";
topicBase = "qmf." + domain + ".topic";
@@ -200,36 +181,30 @@ void ConsoleSessionImpl::open()
// Start the receiver thread
threadCanceled = false;
- opened = true;
thread = new qpid::sys::Thread(*this);
// Send an agent_locate to direct address 'broker' to identify the connected-broker-agent.
sendBrokerLocate();
if (agentQuery)
sendAgentLocate();
+
+ opened = true;
}
-void ConsoleSessionImpl::closeAsync()
+void ConsoleSessionImpl::close()
{
if (!opened)
throw QmfException("The session is already closed");
- // Stop the receiver thread. Don't join it until the destructor is called or open() is called.
+ // Stop and join the receiver thread
threadCanceled = true;
- opened = false;
-}
-
+ thread->join();
+ delete thread;
-void ConsoleSessionImpl::close()
-{
- closeAsync();
-
- if (thread) {
- thread->join();
- delete thread;
- thread = 0;
- }
+ // Close the AMQP session
+ session.close();
+ opened = false;
}
@@ -238,19 +213,13 @@ bool ConsoleSessionImpl::nextEvent(ConsoleEvent& event, Duration timeout)
uint64_t milliseconds = timeout.getMilliseconds();
qpid::sys::Mutex::ScopedLock l(lock);
- if (eventQueue.empty() && milliseconds > 0) {
- int64_t nsecs(qpid::sys::TIME_INFINITE);
- if ((uint64_t)(nsecs / 1000000) > milliseconds)
- nsecs = (int64_t) milliseconds * 1000000;
- qpid::sys::Duration then(nsecs);
- cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(), then));
- }
+ if (eventQueue.empty())
+ cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(),
+ qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC)));
if (!eventQueue.empty()) {
event = eventQueue.front();
eventQueue.pop();
- if (eventQueue.empty())
- alertEventNotifierLH(false);
return true;
}
@@ -258,27 +227,6 @@ bool ConsoleSessionImpl::nextEvent(ConsoleEvent& event, Duration timeout)
}
-int ConsoleSessionImpl::pendingEvents() const
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- return eventQueue.size();
-}
-
-
-void ConsoleSessionImpl::setEventNotifier(EventNotifierImpl* notifier)
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- eventNotifier = notifier;
-}
-
-
-EventNotifierImpl* ConsoleSessionImpl::getEventNotifier() const
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- return eventNotifier;
-}
-
-
uint32_t ConsoleSessionImpl::getAgentCount() const
{
qpid::sys::Mutex::ScopedLock l(lock);
@@ -320,10 +268,8 @@ void ConsoleSessionImpl::enqueueEventLH(const ConsoleEvent& event)
{
bool notify = eventQueue.empty();
eventQueue.push(event);
- if (notify) {
+ if (notify)
cond.notify();
- alertEventNotifierLH(true);
- }
}
@@ -475,23 +421,7 @@ void ConsoleSessionImpl::handleAgentUpdate(const string& agentName, const Varian
iter = content.find("_values");
if (iter == content.end())
return;
- const Variant::Map& in_attrs(iter->second.asMap());
- Variant::Map attrs;
-
- //
- // Copy the map from the message to "attrs". Translate any old-style
- // keys to their new key values in the process.
- //
- for (iter = in_attrs.begin(); iter != in_attrs.end(); iter++) {
- if (iter->first == "epoch")
- attrs[protocol::AGENT_ATTR_EPOCH] = iter->second;
- else if (iter->first == "timestamp")
- attrs[protocol::AGENT_ATTR_TIMESTAMP] = iter->second;
- else if (iter->first == "heartbeat_interval")
- attrs[protocol::AGENT_ATTR_HEARTBEAT_INTERVAL] = iter->second;
- else
- attrs[iter->first] = iter->second;
- }
+ Variant::Map attrs(iter->second.asMap());
iter = attrs.find(protocol::AGENT_ATTR_EPOCH);
if (iter != attrs.end())
@@ -632,13 +562,6 @@ void ConsoleSessionImpl::periodicProcessing(uint64_t seconds)
}
-void ConsoleSessionImpl::alertEventNotifierLH(bool readable)
-{
- if (eventNotifier)
- eventNotifier->setReadable(readable);
-}
-
-
void ConsoleSessionImpl::run()
{
QPID_LOG(debug, "ConsoleSession thread started");
@@ -649,7 +572,7 @@ void ConsoleSessionImpl::run()
qpid::sys::TIME_SEC);
Receiver rx;
- bool valid = session.nextReceiver(rx, Duration::SECOND * maxThreadWaitTime);
+ bool valid = session.nextReceiver(rx, Duration::SECOND);
if (threadCanceled)
break;
if (valid) {
@@ -666,18 +589,6 @@ void ConsoleSessionImpl::run()
enqueueEvent(ConsoleEvent(new ConsoleEventImpl(CONSOLE_THREAD_FAILED)));
}
- session.close();
QPID_LOG(debug, "ConsoleSession thread exiting");
}
-
-ConsoleSessionImpl& ConsoleSessionImplAccess::get(ConsoleSession& session)
-{
- return *session.impl;
-}
-
-
-const ConsoleSessionImpl& ConsoleSessionImplAccess::get(const ConsoleSession& session)
-{
- return *session.impl;
-}
diff --git a/cpp/src/qmf/ConsoleSessionImpl.h b/cpp/src/qmf/ConsoleSessionImpl.h
index e2b30602fa..675c8bcfb5 100644
--- a/cpp/src/qmf/ConsoleSessionImpl.h
+++ b/cpp/src/qmf/ConsoleSessionImpl.h
@@ -27,7 +27,6 @@
#include "qmf/SchemaId.h"
#include "qmf/Schema.h"
#include "qmf/ConsoleEventImpl.h"
-#include "qmf/EventNotifierImpl.h"
#include "qmf/SchemaCache.h"
#include "qmf/Query.h"
#include "qpid/sys/Mutex.h"
@@ -42,13 +41,9 @@
#include "qpid/messaging/Address.h"
#include "qpid/management/Buffer.h"
#include "qpid/types/Variant.h"
-
-#include <boost/shared_ptr.hpp>
#include <map>
#include <queue>
-using namespace std;
-
namespace qmf {
class ConsoleSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable {
public:
@@ -61,14 +56,8 @@ namespace qmf {
void setDomain(const std::string& d) { domain = d; }
void setAgentFilter(const std::string& f);
void open();
- void closeAsync();
void close();
bool nextEvent(ConsoleEvent& e, qpid::messaging::Duration t);
- int pendingEvents() const;
-
- void setEventNotifier(EventNotifierImpl* notifier);
- EventNotifierImpl* getEventNotifier() const;
-
uint32_t getAgentCount() const;
Agent getAgent(uint32_t i) const;
Agent getConnectedBrokerAgent() const { return connectedBrokerAgent; }
@@ -86,11 +75,9 @@ namespace qmf {
uint32_t maxAgentAgeMinutes;
bool listenOnDirect;
bool strictSecurity;
- uint32_t maxThreadWaitTime;
Query agentQuery;
bool opened;
std::queue<ConsoleEvent> eventQueue;
- EventNotifierImpl* eventNotifier;
qpid::sys::Thread* thread;
bool threadCanceled;
uint64_t lastVisit;
@@ -102,8 +89,6 @@ namespace qmf {
std::string directBase;
std::string topicBase;
boost::shared_ptr<SchemaCache> schemaCache;
- qpid::sys::Mutex corrlock;
- uint32_t nextCorrelator;
void enqueueEvent(const ConsoleEvent&);
void enqueueEventLH(const ConsoleEvent&);
@@ -113,17 +98,10 @@ namespace qmf {
void handleAgentUpdate(const std::string&, const qpid::types::Variant::Map&, const qpid::messaging::Message&);
void handleV1SchemaResponse(qpid::management::Buffer&, uint32_t, const qpid::messaging::Message&);
void periodicProcessing(uint64_t);
- void alertEventNotifierLH(bool readable);
void run();
- uint32_t correlator() { qpid::sys::Mutex::ScopedLock l(corrlock); return nextCorrelator++; }
friend class AgentImpl;
};
-
- struct ConsoleSessionImplAccess {
- static ConsoleSessionImpl& get(ConsoleSession& session);
- static const ConsoleSessionImpl& get(const ConsoleSession& session);
- };
}
#endif
diff --git a/cpp/src/qmf/DataAddr.cpp b/cpp/src/qmf/DataAddr.cpp
index d16e12062e..fb51d5787f 100644
--- a/cpp/src/qmf/DataAddr.cpp
+++ b/cpp/src/qmf/DataAddr.cpp
@@ -36,9 +36,7 @@ DataAddr::~DataAddr() { PI::dtor(*this); }
DataAddr& DataAddr::operator=(const DataAddr& s) { return PI::assign(*this, s); }
bool DataAddr::operator==(const DataAddr& o) { return *impl == *o.impl; }
-bool DataAddr::operator==(const DataAddr& o) const { return *impl == *o.impl; }
bool DataAddr::operator<(const DataAddr& o) { return *impl < *o.impl; }
-bool DataAddr::operator<(const DataAddr& o) const { return *impl < *o.impl; }
DataAddr::DataAddr(const qpid::types::Variant::Map& m) { PI::ctor(*this, new DataAddrImpl(m)); }
DataAddr::DataAddr(const string& n, const string& a, uint32_t e) { PI::ctor(*this, new DataAddrImpl(n, a, e)); }
@@ -47,7 +45,7 @@ const string& DataAddr::getAgentName() const { return impl->getAgentName(); }
uint32_t DataAddr::getAgentEpoch() const { return impl->getAgentEpoch(); }
Variant::Map DataAddr::asMap() const { return impl->asMap(); }
-bool DataAddrImpl::operator==(const DataAddrImpl& other) const
+bool DataAddrImpl::operator==(const DataAddrImpl& other)
{
return
agentName == other.agentName &&
@@ -56,7 +54,7 @@ bool DataAddrImpl::operator==(const DataAddrImpl& other) const
}
-bool DataAddrImpl::operator<(const DataAddrImpl& other) const
+bool DataAddrImpl::operator<(const DataAddrImpl& other)
{
if (agentName < other.agentName) return true;
if (agentName > other.agentName) return false;
diff --git a/cpp/src/qmf/DataAddrImpl.h b/cpp/src/qmf/DataAddrImpl.h
index 11d512f0c4..3f9cae9453 100644
--- a/cpp/src/qmf/DataAddrImpl.h
+++ b/cpp/src/qmf/DataAddrImpl.h
@@ -38,8 +38,8 @@ namespace qmf {
//
// Methods from API handle
//
- bool operator==(const DataAddrImpl&) const;
- bool operator<(const DataAddrImpl&) const;
+ bool operator==(const DataAddrImpl&);
+ bool operator<(const DataAddrImpl&);
DataAddrImpl(const qpid::types::Variant::Map&);
DataAddrImpl(const std::string& _name, const std::string& _agentName, uint32_t _agentEpoch=0) :
agentName(_agentName), name(_name), agentEpoch(_agentEpoch) {}
diff --git a/cpp/src/qmf/EventNotifierImpl.cpp b/cpp/src/qmf/EventNotifierImpl.cpp
deleted file mode 100644
index 20114aaa5e..0000000000
--- a/cpp/src/qmf/EventNotifierImpl.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/EventNotifierImpl.h"
-#include "qmf/AgentSessionImpl.h"
-#include "qmf/ConsoleSessionImpl.h"
-
-EventNotifierImpl::EventNotifierImpl(AgentSession& agentSession)
- : readable(false), agent(agentSession)
-{
- AgentSessionImplAccess::get(agent).setEventNotifier(this);
-}
-
-
-EventNotifierImpl::EventNotifierImpl(ConsoleSession& consoleSession)
- : readable(false), console(consoleSession)
-{
- ConsoleSessionImplAccess::get(console).setEventNotifier(this);
-}
-
-
-EventNotifierImpl::~EventNotifierImpl()
-{
- if (agent.isValid())
- AgentSessionImplAccess::get(agent).setEventNotifier(NULL);
- if (console.isValid())
- ConsoleSessionImplAccess::get(console).setEventNotifier(NULL);
-}
-
-void EventNotifierImpl::setReadable(bool readable)
-{
- update(readable);
- this->readable = readable;
-}
-
-
-bool EventNotifierImpl::isReadable() const
-{
- return this->readable;
-}
diff --git a/cpp/src/qmf/PosixEventNotifier.cpp b/cpp/src/qmf/PosixEventNotifier.cpp
deleted file mode 100644
index a364cc155d..0000000000
--- a/cpp/src/qmf/PosixEventNotifier.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/posix/EventNotifier.h"
-#include "qmf/PosixEventNotifierImpl.h"
-#include "qmf/PrivateImplRef.h"
-
-using namespace qmf;
-using namespace std;
-
-typedef qmf::PrivateImplRef<posix::EventNotifier> PI;
-
-posix::EventNotifier::EventNotifier(PosixEventNotifierImpl* impl) { PI::ctor(*this, impl); }
-
-posix::EventNotifier::EventNotifier(AgentSession& agentSession)
-{
- PI::ctor(*this, new PosixEventNotifierImpl(agentSession));
-}
-
-
-posix::EventNotifier::EventNotifier(ConsoleSession& consoleSession)
-{
- PI::ctor(*this, new PosixEventNotifierImpl(consoleSession));
-}
-
-
-posix::EventNotifier::EventNotifier(const posix::EventNotifier& that)
- : Handle<PosixEventNotifierImpl>()
-{
- PI::copy(*this, that);
-}
-
-
-posix::EventNotifier::~EventNotifier()
-{
- PI::dtor(*this);
-}
-
-posix::EventNotifier& posix::EventNotifier::operator=(const posix::EventNotifier& that)
-{
- return PI::assign(*this, that);
-}
-
-
-int posix::EventNotifier::getHandle() const
-{
- return impl->getHandle();
-}
-
diff --git a/cpp/src/qmf/PosixEventNotifierImpl.cpp b/cpp/src/qmf/PosixEventNotifierImpl.cpp
deleted file mode 100644
index 011dbcc214..0000000000
--- a/cpp/src/qmf/PosixEventNotifierImpl.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "PosixEventNotifierImpl.h"
-#include "qpid/log/Statement.h"
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#define BUFFER_SIZE 10
-
-using namespace qmf;
-
-PosixEventNotifierImpl::PosixEventNotifierImpl(AgentSession& agentSession)
- : EventNotifierImpl(agentSession)
-{
- openHandle();
-}
-
-
-PosixEventNotifierImpl::PosixEventNotifierImpl(ConsoleSession& consoleSession)
- : EventNotifierImpl(consoleSession)
-{
- openHandle();
-}
-
-
-PosixEventNotifierImpl::~PosixEventNotifierImpl()
-{
- closeHandle();
-}
-
-
-void PosixEventNotifierImpl::update(bool readable)
-{
- char buffer[BUFFER_SIZE];
-
- if(readable && !this->isReadable()) {
- if (::write(myHandle, "1", 1) == -1)
- QPID_LOG(error, "PosixEventNotifierImpl::update write failed: " << errno);
- }
- else if(!readable && this->isReadable()) {
- if (::read(yourHandle, buffer, BUFFER_SIZE) == -1)
- QPID_LOG(error, "PosixEventNotifierImpl::update read failed: " << errno);
- }
-}
-
-
-void PosixEventNotifierImpl::openHandle()
-{
- int pair[2];
-
- if(::pipe(pair) == -1)
- throw QmfException("Unable to open event notifier handle.");
-
- yourHandle = pair[0];
- myHandle = pair[1];
-
- int flags;
-
- flags = ::fcntl(yourHandle, F_GETFL);
- if((::fcntl(yourHandle, F_SETFL, flags | O_NONBLOCK)) == -1)
- throw QmfException("Unable to make remote handle non-blocking.");
-
- flags = ::fcntl(myHandle, F_GETFL);
- if((::fcntl(myHandle, F_SETFL, flags | O_NONBLOCK)) == -1)
- throw QmfException("Unable to make local handle non-blocking.");
-}
-
-
-void PosixEventNotifierImpl::closeHandle()
-{
- if(myHandle > 0) {
- ::close(myHandle);
- myHandle = -1;
- }
-
- if(yourHandle > 0) {
- ::close(yourHandle);
- yourHandle = -1;
- }
-}
-
-
-PosixEventNotifierImpl& PosixEventNotifierImplAccess::get(posix::EventNotifier& notifier)
-{
- return *notifier.impl;
-}
-
-
-const PosixEventNotifierImpl& PosixEventNotifierImplAccess::get(const posix::EventNotifier& notifier)
-{
- return *notifier.impl;
-}
-
diff --git a/cpp/src/qmf/PosixEventNotifierImpl.h b/cpp/src/qmf/PosixEventNotifierImpl.h
deleted file mode 100644
index c8a7446bd5..0000000000
--- a/cpp/src/qmf/PosixEventNotifierImpl.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef __QMF_POSIX_EVENT_NOTIFIER_IMPL_H
-#define __QMF_POSIX_EVENT_NOTIFIER_IMPL_H
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "qmf/posix/EventNotifier.h"
-#include "qmf/EventNotifierImpl.h"
-#include "qpid/RefCounted.h"
-
-namespace qmf
-{
- class AgentSession;
- class ConsoleSession;
-
- class PosixEventNotifierImpl : public EventNotifierImpl, public virtual qpid::RefCounted
- {
- public:
- PosixEventNotifierImpl(AgentSession& agentSession);
- PosixEventNotifierImpl(ConsoleSession& consoleSession);
- virtual ~PosixEventNotifierImpl();
-
- int getHandle() const { return yourHandle; }
-
- private:
- int myHandle;
- int yourHandle;
-
- void openHandle();
- void closeHandle();
-
- protected:
- void update(bool readable);
- };
-
- struct PosixEventNotifierImplAccess
- {
- static PosixEventNotifierImpl& get(posix::EventNotifier& notifier);
- static const PosixEventNotifierImpl& get(const posix::EventNotifier& notifier);
- };
-
-}
-
-#endif
-
diff --git a/cpp/src/qmf/PrivateImplRef.h b/cpp/src/qmf/PrivateImplRef.h
index 960cbb2e09..8b698c4199 100644
--- a/cpp/src/qmf/PrivateImplRef.h
+++ b/cpp/src/qmf/PrivateImplRef.h
@@ -23,8 +23,8 @@
*/
#include "qmf/ImportExport.h"
-#include "qpid/RefCounted.h"
#include <boost/intrusive_ptr.hpp>
+#include "qpid/RefCounted.h"
namespace qmf {
diff --git a/cpp/src/qmf/engine/ResilientConnection.cpp b/cpp/src/qmf/engine/ResilientConnection.cpp
index 41dd9ff00c..ab65b8d768 100644
--- a/cpp/src/qmf/engine/ResilientConnection.cpp
+++ b/cpp/src/qmf/engine/ResilientConnection.cpp
@@ -334,7 +334,8 @@ void ResilientConnectionImpl::notify()
{
if (notifyFd != -1)
{
- (void) ::write(notifyFd, ".", 1);
+ int unused_ret; //Suppress warnings about ignoring return value.
+ unused_ret = ::write(notifyFd, ".", 1);
}
}
@@ -431,7 +432,8 @@ void ResilientConnectionImpl::EnqueueEvent(ResilientConnectionEvent::EventKind k
if (notifyFd != -1)
{
- (void) ::write(notifyFd, ".", 1);
+ int unused_ret; //Suppress warnings about ignoring return value.
+ unused_ret = ::write(notifyFd, ".", 1);
}
}
diff --git a/cpp/src/qmf/engine/SchemaImpl.cpp b/cpp/src/qmf/engine/SchemaImpl.cpp
index 9d363d3012..e0948a9911 100644
--- a/cpp/src/qmf/engine/SchemaImpl.cpp
+++ b/cpp/src/qmf/engine/SchemaImpl.cpp
@@ -35,17 +35,17 @@ using qpid::framing::Uuid;
SchemaHash::SchemaHash()
{
for (int idx = 0; idx < 16; idx++)
- hash.b[idx] = 0x5A;
+ hash[idx] = 0x5A;
}
void SchemaHash::encode(Buffer& buffer) const
{
- buffer.putBin128(hash.b);
+ buffer.putBin128(hash);
}
void SchemaHash::decode(Buffer& buffer)
{
- buffer.getBin128(hash.b);
+ buffer.getBin128(hash);
}
void SchemaHash::update(uint8_t data)
@@ -55,8 +55,9 @@ void SchemaHash::update(uint8_t data)
void SchemaHash::update(const char* data, uint32_t len)
{
- uint64_t* first = &hash.q[0];
- uint64_t* second = &hash.q[1];
+ uint64_t* first = (uint64_t*) hash;
+ uint64_t* second = (uint64_t*) hash + 1;
+
for (uint32_t idx = 0; idx < len; idx++) {
*first = *first ^ (uint64_t) data[idx];
*second = *second << 1;
diff --git a/cpp/src/qmf/engine/SchemaImpl.h b/cpp/src/qmf/engine/SchemaImpl.h
index 683fb6f8f0..8b079a5ec6 100644
--- a/cpp/src/qmf/engine/SchemaImpl.h
+++ b/cpp/src/qmf/engine/SchemaImpl.h
@@ -35,10 +35,7 @@ namespace engine {
// they've been registered.
class SchemaHash {
- union h {
- uint8_t b[16];
- uint64_t q[2];
- } hash;
+ uint8_t hash[16];
public:
SchemaHash();
void encode(qpid::framing::Buffer& buffer) const;
@@ -50,7 +47,7 @@ namespace engine {
void update(Direction d) { update((uint8_t) d); }
void update(Access a) { update((uint8_t) a); }
void update(bool b) { update((uint8_t) (b ? 1 : 0)); }
- const uint8_t* get() const { return hash.b; }
+ const uint8_t* get() const { return hash; }
bool operator==(const SchemaHash& other) const;
bool operator<(const SchemaHash& other) const;
bool operator>(const SchemaHash& other) const;
diff --git a/cpp/src/qpid/Address.cpp b/cpp/src/qpid/Address.cpp
index bed3d592df..e2b2dfbcdf 100644
--- a/cpp/src/qpid/Address.cpp
+++ b/cpp/src/qpid/Address.cpp
@@ -28,13 +28,7 @@ namespace qpid {
const string Address::TCP("tcp");
ostream& operator<<(ostream& os, const Address& a) {
- // If the host is an IPv6 literal we need to print "[]" around it
- // (we detect IPv6 literals because they contain ":" which is otherwise illegal)
- if (a.host.find(':') != string::npos) {
- return os << a.protocol << ":[" << a.host << "]:" << a.port;
- } else {
- return os << a.protocol << ":" << a.host << ":" << a.port;
- }
+ return os << a.protocol << ":" << a.host << ":" << a.port;
}
bool operator==(const Address& x, const Address& y) {
diff --git a/cpp/src/qpid/BufferRef.h b/cpp/src/qpid/BufferRef.h
deleted file mode 100644
index bfe1f9ebaa..0000000000
--- a/cpp/src/qpid/BufferRef.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef QPID_BUFFERREF_H
-#define QPID_BUFFERREF_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/RefCounted.h"
-#include <boost/intrusive_ptr.hpp>
-
-namespace qpid {
-
-/** Template for mutable or const buffer references */
-template <class T> class BufferRefT {
- public:
- BufferRefT() : begin_(0), end_(0) {}
-
- BufferRefT(boost::intrusive_ptr<RefCounted> c, T* begin, T* end) :
- counter(c), begin_(begin), end_(end) {}
-
- template <class U> BufferRefT(const BufferRefT<U>& other) :
- counter(other.counter), begin_(other.begin_), end_(other.end_) {}
-
- T* begin() const { return begin_; }
- T* end() const { return end_; }
-
- /** Return a sub-buffer of the current buffer */
- BufferRefT sub_buffer(T* begin, T* end) {
- assert(begin_ <= begin && begin <= end_);
- assert(begin_ <= end && end <= end_);
- assert(begin <= end);
- return BufferRefT(counter, begin, end);
- }
-
- private:
- boost::intrusive_ptr<RefCounted> counter;
- T* begin_;
- T* end_;
-};
-
-/**
- * Reference to a mutable ref-counted buffer.
- */
-typedef BufferRefT<char> BufferRef;
-
-/**
- * Reference to a const ref-counted buffer.
- */
-typedef BufferRefT<const char> ConstBufferRef;
-
-} // namespace qpid
-
-#endif /*!QPID_BUFFERREF_H*/
diff --git a/cpp/src/qpid/Exception.cpp b/cpp/src/qpid/Exception.cpp
index a6696f06e1..16a3a13d17 100644
--- a/cpp/src/qpid/Exception.cpp
+++ b/cpp/src/qpid/Exception.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,25 +21,13 @@
#include "qpid/log/Statement.h"
#include "qpid/Exception.h"
-#include "qpid/DisableExceptionLogging.h"
#include <typeinfo>
#include <assert.h>
#include <string.h>
namespace qpid {
-// Note on static initialization order: if an exception is constructed
-// in a static constructor before disableExceptionLogging has been
-// initialized, the worst that can happen is we lose an exception log
-// message. Since we shouldn't be throwing a lot of exceptions during
-// static construction this seems safe.
-static bool disableExceptionLogging = false;
-
-DisableExceptionLogging::DisableExceptionLogging() { disableExceptionLogging = true; }
-DisableExceptionLogging::~DisableExceptionLogging() { disableExceptionLogging = false; }
-
Exception::Exception(const std::string& msg) throw() : message(msg) {
- if (disableExceptionLogging) return;
QPID_LOG_IF(debug, !msg.empty(), "Exception constructed: " << message);
}
diff --git a/cpp/src/qpid/Modules.cpp b/cpp/src/qpid/Modules.cpp
index 727e05d212..8f58df6ed1 100644
--- a/cpp/src/qpid/Modules.cpp
+++ b/cpp/src/qpid/Modules.cpp
@@ -64,6 +64,7 @@ void tryShlib(const char* libname_, bool noThrow) {
if (!isShlibName(libname)) libname += suffix();
try {
sys::Shlib shlib(libname);
+ QPID_LOG (info, "Loaded Module: " << libname);
}
catch (const std::exception& /*e*/) {
if (!noThrow)
@@ -81,7 +82,7 @@ void loadModuleDir (std::string dirname, bool isDefault)
return;
throw Exception ("Directory not found: " + dirname);
}
- if (!fs::is_directory(dirPath))
+ if (!fs::is_directory(dirPath))
{
throw Exception ("Invalid value for module-dir: " + dirname + " is not a directory");
}
diff --git a/cpp/src/qpid/Options.cpp b/cpp/src/qpid/Options.cpp
index 4b13e349f5..499fb71bc3 100644
--- a/cpp/src/qpid/Options.cpp
+++ b/cpp/src/qpid/Options.cpp
@@ -30,6 +30,23 @@ namespace qpid {
using namespace std;
+/*
+ * ---------------------------------------------
+ * Explanation for Boost 103200 conditional code
+ * ---------------------------------------------
+ *
+ * Please see large comment in Options.h .
+ *
+ */
+
+#if ( BOOST_VERSION == 103200 )
+std::vector<std::string> Options::long_names;
+std::vector<std::string> Options::short_names;
+#endif
+
+
+
+
namespace {
struct EnvOptMapper {
@@ -52,11 +69,49 @@ struct EnvOptMapper {
static const std::string prefix("QPID_");
if (envVar.substr(0, prefix.size()) == prefix) {
string env = envVar.substr(prefix.size());
+#if (BOOST_VERSION >= 103300)
typedef const std::vector< boost::shared_ptr<po::option_description> > OptDescs;
OptDescs::const_iterator i =
find_if(opts.options().begin(), opts.options().end(), boost::bind(matchStr, env, _1));
if (i != opts.options().end())
return (*i)->long_name();
+#else
+ /*
+ * For Boost version 103200 and below.
+ *
+ * In Boost version 103200, the options_description::options member,
+ * used above, is private. So what I will do here is use the
+ * count() funtion, which returns a 1 or 0 indicating presence or
+ * absence of the environment variable.
+ *
+ * If it is present, I will return its name. Env vars do not have
+ * short and long forms, so the name is synonymous with the long
+ * name. (This would not work for command line args.)
+ * And if it's absent -- an empty string.
+ */
+
+
+ /*
+ * The env vars come in unaltered, i.e. QPID_FOO, but the
+ * options are stored normalized as "qpid-foo". Change the
+ * local variable "env" so it can be found by "opts".
+ */
+ for (std::string::iterator i = env.begin(); i != env.end(); ++i)
+ {
+ *i = (*i == '_')
+ ? '-'
+ : ::tolower(*i);
+ }
+
+ if ( opts.count(env.c_str()) > 0 )
+ {
+ return env.c_str();
+ }
+ else
+ {
+ return string();
+ }
+#endif
}
return string();
}
@@ -111,6 +166,10 @@ std::string prettyArg(const std::string& name, const std::string& value) {
Options::Options(const string& name) :
po::options_description(name)
+
+#if ( BOOST_VERSION == 103200 )
+ , m_less_easy(this, this)
+#endif
{
}
@@ -127,6 +186,7 @@ void Options::parse(int argc, char const* const* argv, const std::string& config
parsing="command line options";
if (argc > 0 && argv != 0) {
if (allowUnknown) {
+#if (BOOST_VERSION >= 103300)
// This hideous workaround is required because boost 1.33 has a bug
// that causes 'allow_unregistered' to not work.
po::command_line_parser clp = po::command_line_parser(argc, const_cast<char**>(argv)).
@@ -140,6 +200,113 @@ void Options::parse(int argc, char const* const* argv, const std::string& config
filtopts.options.push_back (*i);
po::store(filtopts, vm);
+#elif ( BOOST_VERSION == 103200 )
+
+ /*
+ * "Tokenize" the argv to get rid of equals signs.
+ */
+ vector<string> tokenized_argv;
+ vector<string>::iterator iter;
+
+ for ( int i = 0; i < argc; ++ i )
+ {
+ string s = argv[i];
+ size_t equals_pos = s.find_first_of ( '=' );
+
+ if ( string::npos == equals_pos ) // There's no equals sign. This is a token.
+ {
+ tokenized_argv.push_back(s);
+ }
+ else
+ {
+ // Two tokens -- before and after the equals position.
+ tokenized_argv.push_back ( s.substr(0, equals_pos) );
+ tokenized_argv.push_back ( s.substr(equals_pos+1) );
+ }
+ }
+
+
+ /*
+ * Now "filter" the tokenized argv, to get rid of all
+ * unrecognized options. Because Boost 103200 has no
+ * facility for dealing gracefully with "unregistered"
+ * options.
+ */
+ vector<string> filtered_argv;
+ vector<string>::iterator the_end = tokenized_argv.end();
+
+ // The program-name gets in for free...
+ iter = tokenized_argv.begin();
+ filtered_argv.push_back ( * iter );
+ ++ iter;
+
+ // ...but all other args get checked.
+ while ( iter < the_end )
+ {
+ /*
+ * If this is an argument that is registered,
+ * copy it to filtered_argv and also copy all
+ * of its arguments.
+ */
+ if ( is_registered_option ( * iter ) )
+ {
+ // Store this recognized arg.
+ filtered_argv.push_back ( * iter );
+ ++ iter;
+
+ // Copy all values for the above arg.
+ // Args are tokens that do not start with a minus.
+ while ( (iter < the_end) && ((* iter)[0] != '-') )
+ {
+ filtered_argv.push_back ( * iter );
+ ++ iter;
+ }
+ }
+ else
+ {
+ // Skip this unrecognized arg.
+ ++ iter;
+
+ // Copy all values for the above arg.
+ // Values are tokens that do not start with a minus.
+ while ( (iter < the_end) && ( '-' != (*iter)[0] ) )
+ {
+ ++ iter;
+ }
+ }
+ }
+
+ // Make an array of temporary C strings, because
+ // the interface I can use wants it that way.
+ int new_argc = filtered_argv.size();
+ char ** new_argv = new char * [ new_argc ];
+ int i = 0;
+
+ // cout << "NEW ARGV: |";
+ for ( iter = filtered_argv.begin();
+ iter < filtered_argv.end();
+ ++ iter, ++ i
+ )
+ {
+ new_argv[i] = strdup( (* iter).c_str() );
+ // cout << " " << new_argv[i] ;
+ }
+ // cout << "|\n";
+
+
+ // Use the array of C strings.
+ po::basic_parsed_options<char> bpo = po::parse_command_line(new_argc, const_cast<char**>(new_argv), *this);
+ po::store(bpo, vm);
+
+
+ // Now free the temporary C strings.
+ for ( i = 0; i < new_argc; ++ i )
+ {
+ free ( new_argv[i] );
+ }
+ delete[] new_argv;
+
+#endif
}
else
po::store(po::parse_command_line(argc, const_cast<char**>(argv), *this), vm);
@@ -196,5 +363,107 @@ CommonOptions::CommonOptions(const string& name, const string& configfile)
}
+
+
+#if ( BOOST_VERSION == 103200 )
+options_description_less_easy_init&
+options_description_less_easy_init::operator()(char const * name,
+ char const * description)
+{
+ // Snoop on the arguments....
+ owner->register_names ( name );
+ // ... then call parent function explicitly.
+ po::options_description_easy_init::operator() ( name, description );
+ return * this;
+}
+
+
+options_description_less_easy_init&
+options_description_less_easy_init::operator()(char const * name,
+ const po::value_semantic* s)
+{
+ // Snoop on the arguments....
+ owner->register_names ( name );
+ // ... then call parent function explicitly.
+ po::options_description_easy_init::operator() ( name, s );
+ return * this;
+}
+
+
+options_description_less_easy_init&
+options_description_less_easy_init::operator()(const char* name,
+ const po::value_semantic* s,
+ const char* description)
+{
+ // Snoop on the arguments....
+ owner->register_names ( name );
+ // ... then call parent function explicitly.
+ po::options_description_easy_init::operator() ( name, s, description );
+ return * this;
+}
+
+
+
+
+
+void
+Options::register_names ( std::string s )
+{
+
+ std::string::size_type comma_pos = s.find_first_of ( ',' );
+
+ if ( std::string::npos == comma_pos )
+ {
+ // There is no short-name.
+ long_names.push_back ( s );
+ }
+ else
+ {
+ std::string long_name = s.substr(0, comma_pos),
+ short_name = s.substr(comma_pos+1);
+ long_names .push_back ( long_name );
+ short_names.push_back ( short_name );
+ }
+
+ /*
+ * There is no way to tell when the adding of new options is finished,
+ * so I re-sort after each one.
+ */
+ std::sort ( long_names .begin(), long_names .end() );
+ std::sort ( short_names.begin(), short_names.end() );
+}
+
+
+
+
+
+bool
+Options::is_registered_option ( std::string s )
+{
+ std::string without_dashes = s.substr ( s.find_first_not_of ( '-' ) );
+ std::vector<std::string>::iterator i;
+
+ // Look among the long names.
+ i = std::find ( long_names.begin(),
+ long_names.end(),
+ without_dashes
+ );
+ if ( i != long_names.end() )
+ return true;
+
+ // Look among the short names.
+ i = std::find ( short_names.begin(),
+ short_names.end(),
+ without_dashes
+ );
+ if ( i != short_names.end() )
+ return true;
+
+
+ return false;
+}
+#endif
+
+
} // namespace qpid
diff --git a/cpp/src/qpid/RefCounted.h b/cpp/src/qpid/RefCounted.h
index f9e0107103..e7a9bf31c1 100644
--- a/cpp/src/qpid/RefCounted.h
+++ b/cpp/src/qpid/RefCounted.h
@@ -53,10 +53,8 @@ protected:
// intrusive_ptr support.
namespace boost {
-template <typename T>
-inline void intrusive_ptr_add_ref(const T* p) { p->qpid::RefCounted::addRef(); }
-template <typename T>
-inline void intrusive_ptr_release(const T* p) { p->qpid::RefCounted::release(); }
+inline void intrusive_ptr_add_ref(const qpid::RefCounted* p) { p->addRef(); }
+inline void intrusive_ptr_release(const qpid::RefCounted* p) { p->release(); }
}
diff --git a/cpp/src/qpid/RefCountedBuffer.cpp b/cpp/src/qpid/RefCountedBuffer.cpp
index a82e1a02ab..9b8f1ebd5e 100644
--- a/cpp/src/qpid/RefCountedBuffer.cpp
+++ b/cpp/src/qpid/RefCountedBuffer.cpp
@@ -20,27 +20,34 @@
*/
#include "qpid/RefCountedBuffer.h"
-#include <stdlib.h>
#include <new>
namespace qpid {
-void RefCountedBuffer::released() const {
+RefCountedBuffer::RefCountedBuffer() : count(0) {}
+
+void RefCountedBuffer::destroy() const {
this->~RefCountedBuffer();
- ::free (reinterpret_cast<void *>(const_cast<RefCountedBuffer *>(this)));
+ ::delete[] reinterpret_cast<const char*>(this);
+}
+
+char* RefCountedBuffer::addr() const {
+ return const_cast<char*>(reinterpret_cast<const char*>(this)+sizeof(RefCountedBuffer));
}
-BufferRef RefCountedBuffer::create(size_t n) {
- void* store=::malloc (n + sizeof(RefCountedBuffer));
- if (NULL == store)
- throw std::bad_alloc();
+RefCountedBuffer::pointer RefCountedBuffer::create(size_t n) {
+ char* store=::new char[n+sizeof(RefCountedBuffer)];
new(store) RefCountedBuffer;
- char* start = reinterpret_cast<char *>(store) + sizeof(RefCountedBuffer);
- return BufferRef(
- boost::intrusive_ptr<RefCounted>(reinterpret_cast<RefCountedBuffer*>(store)),
- start, start+n);
+ return pointer(reinterpret_cast<RefCountedBuffer*>(store));
}
+RefCountedBuffer::pointer::pointer() {}
+RefCountedBuffer::pointer::pointer(RefCountedBuffer* x) : p(x) {}
+RefCountedBuffer::pointer::pointer(const pointer& x) : p(x.p) {}
+RefCountedBuffer::pointer::~pointer() {}
+RefCountedBuffer::pointer& RefCountedBuffer::pointer::operator=(const RefCountedBuffer::pointer& x) { p = x.p; return *this; }
+
+char* RefCountedBuffer::pointer::cp() const { return p ? p->get() : 0; }
} // namespace qpid
diff --git a/cpp/src/qpid/RefCountedBuffer.h b/cpp/src/qpid/RefCountedBuffer.h
index f0ea86130b..75a23862be 100644
--- a/cpp/src/qpid/RefCountedBuffer.h
+++ b/cpp/src/qpid/RefCountedBuffer.h
@@ -22,23 +22,68 @@
*
*/
-#include <qpid/RefCounted.h>
-#include <qpid/BufferRef.h>
+#include <boost/utility.hpp>
+#include <boost/detail/atomic_count.hpp>
+#include <boost/intrusive_ptr.hpp>
namespace qpid {
/**
- * Reference-counted byte buffer. No alignment guarantees.
+ * Reference-counted byte buffer.
+ * No alignment guarantees.
*/
-class RefCountedBuffer : public RefCounted {
- public:
+class RefCountedBuffer : boost::noncopyable {
+ mutable boost::detail::atomic_count count;
+ RefCountedBuffer();
+ void destroy() const;
+ char* addr() const;
+
+public:
+ /** Smart char pointer to a reference counted buffer */
+ class pointer {
+ boost::intrusive_ptr<RefCountedBuffer> p;
+ char* cp() const;
+ pointer(RefCountedBuffer* x);
+ friend class RefCountedBuffer;
+
+ public:
+ pointer();
+ pointer(const pointer&);
+ ~pointer();
+ pointer& operator=(const pointer&);
+
+ char* get() { return cp(); }
+ operator char*() { return cp(); }
+ char& operator*() { return *cp(); }
+ char& operator[](size_t i) { return cp()[i]; }
+
+ const char* get() const { return cp(); }
+ operator const char*() const { return cp(); }
+ const char& operator*() const { return *cp(); }
+ const char& operator[](size_t i) const { return cp()[i]; }
+ };
+
/** Create a reference counted buffer of size n */
- static BufferRef create(size_t n);
+ static pointer create(size_t n);
+
+ /** Get a pointer to the start of the buffer. */
+ char* get() { return addr(); }
+ const char* get() const { return addr(); }
+ char& operator[](size_t i) { return get()[i]; }
+ const char& operator[](size_t i) const { return get()[i]; }
- protected:
- void released() const;
+ void addRef() const { ++count; }
+ void release() const { if (--count==0) destroy(); }
+ long refCount() { return count; }
};
} // namespace qpid
+// intrusive_ptr support.
+namespace boost {
+inline void intrusive_ptr_add_ref(const qpid::RefCountedBuffer* p) { p->addRef(); }
+inline void intrusive_ptr_release(const qpid::RefCountedBuffer* p) { p->release(); }
+}
+
+
#endif /*!QPID_REFCOUNTEDBUFFER_H*/
diff --git a/cpp/src/qpid/Sasl.h b/cpp/src/qpid/Sasl.h
index 4d579fa051..9a9d61b037 100644
--- a/cpp/src/qpid/Sasl.h
+++ b/cpp/src/qpid/Sasl.h
@@ -47,8 +47,8 @@ class Sasl
* client supports.
* @param externalSecuritySettings security related details from the underlying transport
*/
- virtual bool start(const std::string& mechanisms, std::string& response,
- const qpid::sys::SecuritySettings* externalSecuritySettings = 0) = 0;
+ virtual std::string start(const std::string& mechanisms,
+ const qpid::sys::SecuritySettings* externalSecuritySettings = 0) = 0;
virtual std::string step(const std::string& challenge) = 0;
virtual std::string getMechanism() = 0;
virtual std::string getUserId() = 0;
diff --git a/cpp/src/qpid/SaslFactory.cpp b/cpp/src/qpid/SaslFactory.cpp
index a8d1f94c1e..055883abee 100644
--- a/cpp/src/qpid/SaslFactory.cpp
+++ b/cpp/src/qpid/SaslFactory.cpp
@@ -112,7 +112,7 @@ class CyrusSasl : public Sasl
public:
CyrusSasl(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool allowInteraction);
~CyrusSasl();
- bool start(const std::string& mechanisms, std::string& response, const SecuritySettings* externalSettings);
+ std::string start(const std::string& mechanisms, const SecuritySettings* externalSettings);
std::string step(const std::string& challenge);
std::string getMechanism();
std::string getUserId();
@@ -182,17 +182,16 @@ CyrusSasl::CyrusSasl(const std::string & username, const std::string & password,
callbacks[i].id = SASL_CB_AUTHNAME;
callbacks[i].proc = (CallbackProc*) &getUserFromSettings;
callbacks[i++].context = &settings;
-
- callbacks[i].id = SASL_CB_PASS;
- if (settings.password.empty()) {
- callbacks[i].proc = 0;
- callbacks[i++].context = 0;
- } else {
- callbacks[i].proc = (CallbackProc*) &getPasswordFromSettings;
- callbacks[i++].context = &settings;
- }
}
+ callbacks[i].id = SASL_CB_PASS;
+ if (settings.password.empty()) {
+ callbacks[i].proc = 0;
+ callbacks[i++].context = 0;
+ } else {
+ callbacks[i].proc = (CallbackProc*) &getPasswordFromSettings;
+ callbacks[i++].context = &settings;
+ }
callbacks[i].id = SASL_CB_LIST_END;
callbacks[i].proc = 0;
@@ -210,7 +209,7 @@ namespace {
const std::string SSL("ssl");
}
-bool CyrusSasl::start(const std::string& mechanisms, std::string& response, const SecuritySettings* externalSettings)
+std::string CyrusSasl::start(const std::string& mechanisms, const SecuritySettings* externalSettings)
{
QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << ")");
int result = sasl_client_new(settings.service.c_str(),
@@ -283,12 +282,7 @@ bool CyrusSasl::start(const std::string& mechanisms, std::string& response, cons
mechanism = std::string(chosenMechanism);
QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << "): selected "
<< mechanism << " response: '" << std::string(out, outlen) << "'");
- if (out) {
- response = std::string(out, outlen);
- return true;
- } else {
- return false;
- }
+ return std::string(out, outlen);
}
std::string CyrusSasl::step(const std::string& challenge)
diff --git a/cpp/src/qpid/Url.cpp b/cpp/src/qpid/Url.cpp
index f699b60c17..ab796f4642 100644
--- a/cpp/src/qpid/Url.cpp
+++ b/cpp/src/qpid/Url.cpp
@@ -156,12 +156,11 @@ class UrlParser {
return false;
}
- // A liberal interpretation of http://www.ietf.org/rfc/rfc3986.txt.
- // Works for DNS names and and ipv4 and ipv6 literals
+ // TODO aconway 2008-11-20: this does not fully implement
+ // http://www.ietf.org/rfc/rfc3986.txt. Works for DNS names and
+ // ipv4 literals but won't handle ipv6.
//
bool host(string& h) {
- if (ip6literal(h)) return true;
-
const char* start=i;
while (unreserved() || pctEncoded())
;
@@ -170,22 +169,6 @@ class UrlParser {
return true;
}
- // This is a bit too liberal for IPv6 literal addresses, but probably good enough
- bool ip6literal(string& h) {
- if (literal("[")) {
- const char* start = i;
- while (hexDigit() || literal(":") || literal("."))
- ;
- const char* end = i;
- if ( end-start < 2 ) return false; // Smallest valid address is "::"
- if (literal("]")) {
- h.assign(start, end);
- return true;
- }
- }
- return false;
- }
-
bool unreserved() { return (::isalnum(*i) || ::strchr("-._~", *i)) && advance(); }
bool pctEncoded() { return literal("%") && hexDigit() && hexDigit(); }
diff --git a/cpp/src/qpid/acl/Acl.cpp b/cpp/src/qpid/acl/Acl.cpp
index 4b3dda7962..67603015d7 100644
--- a/cpp/src/qpid/acl/Acl.cpp
+++ b/cpp/src/qpid/acl/Acl.cpp
@@ -180,10 +180,7 @@ Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(fals
{
case _qmf::Acl::METHOD_RELOADACLFILE :
readAclFile(text);
- if (text.empty())
- status = Manageable::STATUS_OK;
- else
- status = Manageable::STATUS_USER;
+ status = Manageable::STATUS_USER;
break;
}
diff --git a/cpp/src/qpid/acl/AclPlugin.cpp b/cpp/src/qpid/acl/AclPlugin.cpp
index d611797c49..e4d721ea44 100644
--- a/cpp/src/qpid/acl/AclPlugin.cpp
+++ b/cpp/src/qpid/acl/AclPlugin.cpp
@@ -69,7 +69,7 @@ struct AclPlugin : public Plugin {
}
acl = new Acl(values, b);
- b.setAcl(acl.get());
+ b.setAcl(acl.get());
b.addFinalizer(boost::bind(&AclPlugin::shutdown, this));
}
diff --git a/cpp/src/qpid/agent/ManagementAgentImpl.cpp b/cpp/src/qpid/agent/ManagementAgentImpl.cpp
index f183ff8e0c..593d403a11 100644
--- a/cpp/src/qpid/agent/ManagementAgentImpl.cpp
+++ b/cpp/src/qpid/agent/ManagementAgentImpl.cpp
@@ -305,47 +305,43 @@ void ManagementAgentImpl::raiseEvent(const ManagementEvent& event, severity_t se
"emerg", "alert", "crit", "error", "warn",
"note", "info", "debug"
};
- string content;
+ sys::Mutex::ScopedLock lock(agentLock);
+ Buffer outBuffer(eventBuffer, MA_BUFFER_SIZE);
+ uint8_t sev = (severity == SEV_DEFAULT) ? event.getSeverity() : (uint8_t) severity;
stringstream key;
- Variant::Map headers;
- {
- sys::Mutex::ScopedLock lock(agentLock);
- Buffer outBuffer(eventBuffer, MA_BUFFER_SIZE);
- uint8_t sev = (severity == SEV_DEFAULT) ? event.getSeverity() : (uint8_t) severity;
-
- // key << "console.event." << assignedBrokerBank << "." << assignedAgentBank << "." <<
- // event.getPackageName() << "." << event.getEventName();
- key << "agent.ind.event." << keyifyNameStr(event.getPackageName())
- << "." << keyifyNameStr(event.getEventName())
- << "." << severityStr[sev]
- << "." << vendorNameKey
- << "." << productNameKey
- << "." << instanceNameKey;
-
- Variant::Map map_;
- Variant::Map schemaId;
- Variant::Map values;
-
- map_["_schema_id"] = mapEncodeSchemaId(event.getPackageName(),
- event.getEventName(),
- event.getMd5Sum(),
- ManagementItem::CLASS_KIND_EVENT);
- event.mapEncode(values);
- map_["_values"] = values;
- map_["_timestamp"] = uint64_t(Duration(EPOCH, now()));
- map_["_severity"] = sev;
+ // key << "console.event." << assignedBrokerBank << "." << assignedAgentBank << "." <<
+ // event.getPackageName() << "." << event.getEventName();
+ key << "agent.ind.event." << keyifyNameStr(event.getPackageName())
+ << "." << keyifyNameStr(event.getEventName())
+ << "." << severityStr[sev]
+ << "." << vendorNameKey
+ << "." << productNameKey
+ << "." << instanceNameKey;
- headers["method"] = "indication";
- headers["qmf.opcode"] = "_data_indication";
- headers["qmf.content"] = "_event";
- headers["qmf.agent"] = name_address;
+ Variant::Map map_;
+ Variant::Map schemaId;
+ Variant::Map values;
+ Variant::Map headers;
+ string content;
- Variant::List list;
- list.push_back(map_);
- ListCodec::encode(list, content);
- }
+ map_["_schema_id"] = mapEncodeSchemaId(event.getPackageName(),
+ event.getEventName(),
+ event.getMd5Sum(),
+ ManagementItem::CLASS_KIND_EVENT);
+ event.mapEncode(values);
+ map_["_values"] = values;
+ map_["_timestamp"] = uint64_t(Duration(EPOCH, now()));
+ map_["_severity"] = sev;
+ headers["method"] = "indication";
+ headers["qmf.opcode"] = "_data_indication";
+ headers["qmf.content"] = "_event";
+ headers["qmf.agent"] = name_address;
+
+ Variant::List list;
+ list.push_back(map_);
+ ListCodec::encode(list, content);
connThreadBody.sendBuffer(content, "", headers, topicExchange, key.str(), "amqp/list");
}
@@ -525,12 +521,9 @@ void ManagementAgentImpl::sendException(const string& rte, const string& rtk, co
void ManagementAgentImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence, const string& rte, const string& rtk)
{
+ sys::Mutex::ScopedLock lock(agentLock);
string packageName;
SchemaClassKey key;
- uint32_t outLen(0);
- char localBuffer[MA_BUFFER_SIZE];
- Buffer outBuffer(localBuffer, MA_BUFFER_SIZE);
- bool found(false);
inBuffer.getShortString(packageName);
inBuffer.getShortString(key.name);
@@ -538,30 +531,26 @@ void ManagementAgentImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequenc
QPID_LOG(trace, "RCVD SchemaRequest: package=" << packageName << " class=" << key.name);
- {
- sys::Mutex::ScopedLock lock(agentLock);
- PackageMap::iterator pIter = packages.find(packageName);
- if (pIter != packages.end()) {
- ClassMap& cMap = pIter->second;
- ClassMap::iterator cIter = cMap.find(key);
- if (cIter != cMap.end()) {
- SchemaClass& schema = cIter->second;
- string body;
-
- encodeHeader(outBuffer, 's', sequence);
- schema.writeSchemaCall(body);
- outBuffer.putRawData(body);
- outLen = MA_BUFFER_SIZE - outBuffer.available();
- outBuffer.reset();
- found = true;
- }
+ PackageMap::iterator pIter = packages.find(packageName);
+ if (pIter != packages.end()) {
+ ClassMap& cMap = pIter->second;
+ ClassMap::iterator cIter = cMap.find(key);
+ if (cIter != cMap.end()) {
+ SchemaClass& schema = cIter->second;
+ Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
+ uint32_t outLen;
+ string body;
+
+ encodeHeader(outBuffer, 's', sequence);
+ schema.writeSchemaCall(body);
+ outBuffer.putRawData(body);
+ outLen = MA_BUFFER_SIZE - outBuffer.available();
+ outBuffer.reset();
+ connThreadBody.sendBuffer(outBuffer, outLen, rte, rtk);
+
+ QPID_LOG(trace, "SENT SchemaInd: package=" << packageName << " class=" << key.name);
}
}
-
- if (found) {
- connThreadBody.sendBuffer(outBuffer, outLen, rte, rtk);
- QPID_LOG(trace, "SENT SchemaInd: package=" << packageName << " class=" << key.name);
- }
}
void ManagementAgentImpl::handleConsoleAddedIndication()
@@ -980,6 +969,18 @@ ManagementAgentImpl::PackageMap::iterator ManagementAgentImpl::findOrAddPackage(
pair<PackageMap::iterator, bool> result =
packages.insert(pair<string, ClassMap>(name, ClassMap()));
+ if (connected) {
+ // Publish a package-indication message
+ Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
+ uint32_t outLen;
+
+ encodeHeader(outBuffer, 'p');
+ encodePackageIndication(outBuffer, result.first);
+ outLen = MA_BUFFER_SIZE - outBuffer.available();
+ outBuffer.reset();
+ connThreadBody.sendBuffer(outBuffer, outLen, "qpid.management", "schema.package");
+ }
+
return result.first;
}
@@ -1037,146 +1038,131 @@ void ManagementAgentImpl::encodeClassIndication(Buffer& buf,
QPID_LOG(trace, "SENT ClassInd: package=" << (*pIter).first << " class=" << key.name);
}
-struct MessageItem {
- string content;
- Variant::Map headers;
- string key;
- MessageItem(const Variant::Map& h, const string& k) : headers(h), key(k) {}
-};
-
void ManagementAgentImpl::periodicProcessing()
{
string addr_key_base = "agent.ind.data.";
+ sys::Mutex::ScopedLock lock(agentLock);
list<ObjectId> deleteList;
- list<boost::shared_ptr<MessageItem> > message_list;
+
+ if (!connected)
+ return;
sendHeartbeat();
- {
- sys::Mutex::ScopedLock lock(agentLock);
+ moveNewObjectsLH();
- if (!connected)
- return;
+ //
+ // Clear the been-here flag on all objects in the map.
+ //
+ for (ObjectMap::iterator iter = managementObjects.begin();
+ iter != managementObjects.end();
+ iter++) {
+ ManagementObject* object = iter->second.get();
+ object->setFlags(0);
+ if (publishAllData) {
+ object->setForcePublish(true);
+ }
+ }
+
+ publishAllData = false;
- moveNewObjectsLH();
+ //
+ // Process the entire object map.
+ //
+ uint32_t v2Objs = 0;
+
+ for (ObjectMap::iterator baseIter = managementObjects.begin();
+ baseIter != managementObjects.end();
+ baseIter++) {
+ ManagementObject* baseObject = baseIter->second.get();
//
- // Clear the been-here flag on all objects in the map.
+ // Skip until we find a base object requiring a sent message.
//
- for (ObjectMap::iterator iter = managementObjects.begin();
+ if (baseObject->getFlags() == 1 ||
+ (!baseObject->getConfigChanged() &&
+ !baseObject->getInstChanged() &&
+ !baseObject->getForcePublish() &&
+ !baseObject->isDeleted()))
+ continue;
+
+ std::string packageName = baseObject->getPackageName();
+ std::string className = baseObject->getClassName();
+
+ Variant::List list_;
+ string content;
+ std::stringstream addr_key;
+ Variant::Map headers;
+
+ addr_key << addr_key_base;
+ addr_key << keyifyNameStr(packageName)
+ << "." << keyifyNameStr(className)
+ << "." << vendorNameKey
+ << "." << productNameKey
+ << "." << instanceNameKey;
+
+ headers["method"] = "indication";
+ headers["qmf.opcode"] = "_data_indication";
+ headers["qmf.content"] = "_data";
+ headers["qmf.agent"] = name_address;
+
+ for (ObjectMap::iterator iter = baseIter;
iter != managementObjects.end();
iter++) {
ManagementObject* object = iter->second.get();
- object->setFlags(0);
- if (publishAllData) {
- object->setForcePublish(true);
- }
- }
-
- publishAllData = false;
-
- //
- // Process the entire object map.
- //
- uint32_t v2Objs = 0;
-
- for (ObjectMap::iterator baseIter = managementObjects.begin();
- baseIter != managementObjects.end();
- baseIter++) {
- ManagementObject* baseObject = baseIter->second.get();
-
- //
- // Skip until we find a base object requiring a sent message.
- //
- if (baseObject->getFlags() == 1 ||
- (!baseObject->getConfigChanged() &&
- !baseObject->getInstChanged() &&
- !baseObject->getForcePublish() &&
- !baseObject->isDeleted()))
- continue;
-
- std::string packageName = baseObject->getPackageName();
- std::string className = baseObject->getClassName();
-
- Variant::List list_;
- std::stringstream addr_key;
- Variant::Map headers;
-
- addr_key << addr_key_base;
- addr_key << keyifyNameStr(packageName)
- << "." << keyifyNameStr(className)
- << "." << vendorNameKey
- << "." << productNameKey
- << "." << instanceNameKey;
-
- headers["method"] = "indication";
- headers["qmf.opcode"] = "_data_indication";
- headers["qmf.content"] = "_data";
- headers["qmf.agent"] = name_address;
-
- for (ObjectMap::iterator iter = baseIter;
- iter != managementObjects.end();
- iter++) {
- ManagementObject* object = iter->second.get();
- bool send_stats, send_props;
- if (baseObject->isSameClass(*object) && object->getFlags() == 0) {
- object->setFlags(1);
- if (object->getConfigChanged() || object->getInstChanged())
- object->setUpdateTime();
-
- send_props = (object->getConfigChanged() || object->getForcePublish() || object->isDeleted());
- send_stats = (object->hasInst() && (object->getInstChanged() || object->getForcePublish()));
-
- if (send_stats || send_props) {
- Variant::Map map_;
- Variant::Map values;
- Variant::Map oid;
-
- object->getObjectId().mapEncode(oid);
- map_["_object_id"] = oid;
- map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(),
- object->getClassName(),
- object->getMd5Sum());
- object->writeTimestamps(map_);
- object->mapEncodeValues(values, send_props, send_stats);
- map_["_values"] = values;
- list_.push_back(map_);
+ bool send_stats, send_props;
+ if (baseObject->isSameClass(*object) && object->getFlags() == 0) {
+ object->setFlags(1);
+ if (object->getConfigChanged() || object->getInstChanged())
+ object->setUpdateTime();
- if (++v2Objs >= maxV2ReplyObjs) {
- v2Objs = 0;
- boost::shared_ptr<MessageItem> item(new MessageItem(headers, addr_key.str()));
- ListCodec::encode(list_, item->content);
- message_list.push_back(item);
- list_.clear();
- }
+ send_props = (object->getConfigChanged() || object->getForcePublish() || object->isDeleted());
+ send_stats = (object->hasInst() && (object->getInstChanged() || object->getForcePublish()));
+
+ if (send_stats || send_props) {
+ Variant::Map map_;
+ Variant::Map values;
+ Variant::Map oid;
+
+ object->getObjectId().mapEncode(oid);
+ map_["_object_id"] = oid;
+ map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(),
+ object->getClassName(),
+ object->getMd5Sum());
+ object->writeTimestamps(map_);
+ object->mapEncodeValues(values, send_props, send_stats);
+ map_["_values"] = values;
+ list_.push_back(map_);
+
+ if (++v2Objs >= maxV2ReplyObjs) {
+ v2Objs = 0;
+ ListCodec::encode(list_, content);
+
+ connThreadBody.sendBuffer(content, "", headers, topicExchange, addr_key.str(), "amqp/list");
+ list_.clear();
+ content.clear();
+ QPID_LOG(trace, "SENT DataIndication");
}
-
- if (object->isDeleted())
- deleteList.push_back(iter->first);
- object->setForcePublish(false);
}
- }
- if (!list_.empty()) {
- boost::shared_ptr<MessageItem> item(new MessageItem(headers, addr_key.str()));
- ListCodec::encode(list_, item->content);
- message_list.push_back(item);
+ if (object->isDeleted())
+ deleteList.push_back(iter->first);
+ object->setForcePublish(false);
}
}
- // Delete flagged objects
- for (list<ObjectId>::reverse_iterator iter = deleteList.rbegin();
- iter != deleteList.rend();
- iter++)
- managementObjects.erase(*iter);
+ if (!list_.empty()) {
+ ListCodec::encode(list_, content);
+ connThreadBody.sendBuffer(content, "", headers, topicExchange, addr_key.str(), "amqp/list");
+ QPID_LOG(trace, "SENT DataIndication");
+ }
}
- while (!message_list.empty()) {
- boost::shared_ptr<MessageItem> item(message_list.front());
- message_list.pop_front();
- connThreadBody.sendBuffer(item->content, "", item->headers, topicExchange, item->key, "amqp/list");
- QPID_LOG(trace, "SENT DataIndication");
- }
+ // Delete flagged objects
+ for (list<ObjectId>::reverse_iterator iter = deleteList.rbegin();
+ iter != deleteList.rend();
+ iter++)
+ managementObjects.erase(*iter);
}
@@ -1378,26 +1364,13 @@ bool ManagementAgentImpl::ConnectionThread::isSleeping() const
void ManagementAgentImpl::PublishThread::run()
{
- uint16_t totalSleep;
- uint16_t sleepTime;
+ uint16_t totalSleep;
while (!shutdown) {
agent.periodicProcessing();
totalSleep = 0;
-
- //
- // Calculate a sleep time that is no greater than 5 seconds and
- // no less than 1 second.
- //
- sleepTime = agent.getInterval();
- if (sleepTime > 5)
- sleepTime = 5;
- else if (sleepTime == 0)
- sleepTime = 1;
-
- while (totalSleep < agent.getInterval() && !shutdown) {
- ::sleep(sleepTime);
- totalSleep += sleepTime;
+ while (totalSleep++ < agent.getInterval() && !shutdown) {
+ ::sleep(1);
}
}
}
diff --git a/cpp/src/qpid/agent/ManagementAgentImpl.h b/cpp/src/qpid/agent/ManagementAgentImpl.h
index 53f3c13a91..bf340777d1 100644
--- a/cpp/src/qpid/agent/ManagementAgentImpl.h
+++ b/cpp/src/qpid/agent/ManagementAgentImpl.h
@@ -62,8 +62,8 @@ class ManagementAgentImpl : public ManagementAgent, public client::MessageListen
uint16_t intervalSeconds = 10,
bool useExternalThread = false,
const std::string& storeFile = "",
- const std::string& uid = "",
- const std::string& pwd = "",
+ const std::string& uid = "guest",
+ const std::string& pwd = "guest",
const std::string& mech = "PLAIN",
const std::string& proto = "tcp");
void init(const management::ConnectionSettings& settings,
diff --git a/cpp/src/qpid/amqp_0_10/Codecs.cpp b/cpp/src/qpid/amqp_0_10/Codecs.cpp
index b976a5d09b..0fbe2a60b9 100644
--- a/cpp/src/qpid/amqp_0_10/Codecs.cpp
+++ b/cpp/src/qpid/amqp_0_10/Codecs.cpp
@@ -127,10 +127,10 @@ Variant toVariant(boost::shared_ptr<FieldValue> in)
switch (in->getType()) {
//Fixed Width types:
case 0x01: out.setEncoding(amqp0_10_binary);
- case 0x02: out = in->getIntegerValue<int8_t>(); break;
- case 0x03: out = in->getIntegerValue<uint8_t>(); break;
+ case 0x02: out = in->getIntegerValue<int8_t, 1>(); break;
+ case 0x03: out = in->getIntegerValue<uint8_t, 1>(); break;
case 0x04: break; //TODO: iso-8859-15 char
- case 0x08: out = static_cast<bool>(in->getIntegerValue<uint8_t>()); break;
+ case 0x08: out = static_cast<bool>(in->getIntegerValue<uint8_t, 1>()); break;
case 0x10: out.setEncoding(amqp0_10_binary);
case 0x11: out = in->getIntegerValue<int16_t, 2>(); break;
case 0x12: out = in->getIntegerValue<uint16_t, 2>(); break;
diff --git a/cpp/src/qpid/amqp_0_10/SessionHandler.cpp b/cpp/src/qpid/amqp_0_10/SessionHandler.cpp
index 578598a146..b113d49a73 100644
--- a/cpp/src/qpid/amqp_0_10/SessionHandler.cpp
+++ b/cpp/src/qpid/amqp_0_10/SessionHandler.cpp
@@ -130,6 +130,9 @@ void SessionHandler::handleException(const qpid::SessionException& e)
}
namespace {
+bool isControl(const AMQFrame& f) {
+ return f.getMethod() && f.getMethod()->type() == framing::SEGMENT_TYPE_CONTROL;
+}
bool isCommand(const AMQFrame& f) {
return f.getMethod() && f.getMethod()->type() == framing::SEGMENT_TYPE_COMMAND;
}
@@ -188,10 +191,9 @@ void SessionHandler::detach(const std::string& name) {
void SessionHandler::detached(const std::string& name, uint8_t code) {
CHECK_NAME(name, "session.detached");
awaitingDetached = false;
- if (code != session::DETACH_CODE_NORMAL) {
- sendReady = receiveReady = false;
+ if (code != session::DETACH_CODE_NORMAL)
channelException(convert(code), "session.detached from peer.");
- } else {
+ else {
handleDetach();
}
}
diff --git a/cpp/src/qpid/amqp_0_10/SessionHandler.h b/cpp/src/qpid/amqp_0_10/SessionHandler.h
index 8b072fa05c..a87a1a155f 100644
--- a/cpp/src/qpid/amqp_0_10/SessionHandler.h
+++ b/cpp/src/qpid/amqp_0_10/SessionHandler.h
@@ -41,8 +41,8 @@ namespace amqp_0_10 {
* to a session state.
*/
-class QPID_COMMON_CLASS_EXTERN SessionHandler : public framing::AMQP_AllOperations::SessionHandler,
- public framing::FrameHandler::InOutHandler
+class SessionHandler : public framing::AMQP_AllOperations::SessionHandler,
+ public framing::FrameHandler::InOutHandler
{
public:
QPID_COMMON_EXTERN SessionHandler(framing::FrameHandler* out=0, uint16_t channel=0);
@@ -66,7 +66,7 @@ class QPID_COMMON_CLASS_EXTERN SessionHandler : public framing::AMQP_AllOperatio
QPID_COMMON_EXTERN void handleException(const qpid::SessionException& e);
/** True if the handler is ready to send and receive */
- QPID_COMMON_EXTERN bool ready() const;
+ bool ready() const;
// Protocol methods
QPID_COMMON_EXTERN void attach(const std::string& name, bool force);
diff --git a/cpp/src/qpid/broker/AsyncCompletion.h b/cpp/src/qpid/broker/AsyncCompletion.h
deleted file mode 100644
index fef994438f..0000000000
--- a/cpp/src/qpid/broker/AsyncCompletion.h
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef _AsyncCompletion_
-#define _AsyncCompletion_
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include <boost/intrusive_ptr.hpp>
-
-#include "qpid/broker/BrokerImportExport.h"
-#include "qpid/sys/AtomicValue.h"
-#include "qpid/sys/Mutex.h"
-#include "qpid/sys/Monitor.h"
-
-namespace qpid {
-namespace broker {
-
-/**
- * Class to implement asynchronous notification of completion.
- *
- * Use-case: An "initiator" needs to wait for a set of "completers" to
- * finish a unit of work before an action can occur. This object
- * tracks the progress of the set of completers, and allows the action
- * to occur once all completers have signalled that they are done.
- *
- * The initiator and completers may be running in separate threads.
- *
- * The initiating thread is the thread that initiates the action,
- * i.e. the connection read thread.
- *
- * A completing thread is any thread that contributes to completion,
- * e.g. a store thread that does an async write.
- * There may be zero or more completers.
- *
- * When the work is complete, a callback is invoked. The callback
- * may be invoked in the Initiator thread, or one of the Completer
- * threads. The callback is passed a flag indicating whether or not
- * the callback is running under the context of the Initiator thread.
- *
- * Use model:
- * 1) Initiator thread invokes begin()
- * 2) After begin() has been invoked, zero or more Completers invoke
- * startCompleter(). Completers may be running in the same or
- * different thread as the Initiator, as long as they guarantee that
- * startCompleter() is invoked at least once before the Initiator invokes end().
- * 3) Completers may invoke finishCompleter() at any time, even after the
- * initiator has invoked end(). finishCompleter() may be called from any
- * thread.
- * 4) startCompleter()/finishCompleter() calls "nest": for each call to
- * startCompleter(), a corresponding call to finishCompleter() must be made.
- * Once the last finishCompleter() is called, the Completer must no longer
- * reference the completion object.
- * 5) The Initiator invokes end() at the point where it has finished
- * dispatching work to the Completers, and is prepared for the callback
- * handler to be invoked. Note: if there are no outstanding Completers
- * pending when the Initiator invokes end(), the callback will be invoked
- * directly, and the sync parameter will be set true. This indicates to the
- * Initiator that the callback is executing in the context of the end() call,
- * and the Initiator is free to optimize the handling of the completion,
- * assuming no need for synchronization with Completer threads.
- */
-
-class AsyncCompletion
-{
- public:
-
- /** Supplied by the Initiator to the end() method, allows for a callback
- * when all outstanding completers are done. If the callback cannot be
- * made during the end() call, the clone() method must supply a copy of
- * this callback object that persists after end() returns. The cloned
- * callback object will be used by the last completer thread, and
- * released when the callback returns.
- */
- class Callback : public RefCounted
- {
- public:
- virtual void completed(bool) = 0;
- virtual boost::intrusive_ptr<Callback> clone() = 0;
- };
-
- private:
- mutable qpid::sys::AtomicValue<uint32_t> completionsNeeded;
- mutable qpid::sys::Monitor callbackLock;
- bool inCallback, active;
-
- void invokeCallback(bool sync) {
- qpid::sys::Mutex::ScopedLock l(callbackLock);
- if (active) {
- if (callback.get()) {
- inCallback = true;
- {
- qpid::sys::Mutex::ScopedUnlock ul(callbackLock);
- callback->completed(sync);
- }
- inCallback = false;
- callback = boost::intrusive_ptr<Callback>();
- callbackLock.notifyAll();
- }
- active = false;
- }
- }
-
- protected:
- /** Invoked when all completers have signalled that they have completed
- * (via calls to finishCompleter()). bool == true if called via end()
- */
- boost::intrusive_ptr<Callback> callback;
-
- public:
- AsyncCompletion() : completionsNeeded(0), inCallback(false), active(true) {};
- virtual ~AsyncCompletion() { cancel(); }
-
-
- /** True when all outstanding operations have compeleted
- */
- bool isDone()
- {
- return !active;
- }
-
- /** Called to signal the start of an asynchronous operation. The operation
- * is considered pending until finishCompleter() is called.
- * E.g. called when initiating an async store operation.
- */
- void startCompleter() { ++completionsNeeded; }
-
- /** Called by completer to signal that it has finished the operation started
- * when startCompleter() was invoked.
- * e.g. called when async write complete.
- */
- void finishCompleter()
- {
- if (--completionsNeeded == 0) {
- invokeCallback(false);
- }
- }
-
- /** called by initiator before any calls to startCompleter can be done.
- */
- void begin()
- {
- ++completionsNeeded;
- }
-
- /** called by initiator after all potential completers have called
- * startCompleter().
- */
- void end(Callback& cb)
- {
- assert(completionsNeeded.get() > 0); // ensure begin() has been called!
- // the following only "decrements" the count if it is 1. This means
- // there are no more outstanding completers and we are done.
- if (completionsNeeded.boolCompareAndSwap(1, 0)) {
- // done! Complete immediately
- cb.completed(true);
- return;
- }
-
- // the compare-and-swap did not succeed. This means there are
- // outstanding completers pending (count > 1). Get a persistent
- // Callback object to use when the last completer is done.
- // Decrement after setting up the callback ensures that pending
- // completers cannot touch the callback until it is ready.
- callback = cb.clone();
- if (--completionsNeeded == 0) {
- // note that a completer may have completed during the
- // callback setup or decrement:
- invokeCallback(true);
- }
- }
-
- /** may be called by Initiator to cancel the callback. Will wait for
- * callback to complete if in progress.
- */
- virtual void cancel() {
- qpid::sys::Mutex::ScopedLock l(callbackLock);
- while (inCallback) callbackLock.wait();
- callback = boost::intrusive_ptr<Callback>();
- active = false;
- }
-};
-
-}} // qpid::broker::
-#endif /*!_AsyncCompletion_*/
diff --git a/cpp/src/qpid/broker/Bridge.cpp b/cpp/src/qpid/broker/Bridge.cpp
index c709606c17..7fbbf4e2c4 100644
--- a/cpp/src/qpid/broker/Bridge.cpp
+++ b/cpp/src/qpid/broker/Bridge.cpp
@@ -164,12 +164,6 @@ void Bridge::destroy()
listener(this);
}
-bool Bridge::isSessionReady() const
-{
- SessionHandler& sessionHandler = conn->getChannel(id);
- return sessionHandler.ready();
-}
-
void Bridge::setPersistenceId(uint64_t pId) const
{
persistenceId = pId;
diff --git a/cpp/src/qpid/broker/Bridge.h b/cpp/src/qpid/broker/Bridge.h
index 8b4559a871..a846254c57 100644
--- a/cpp/src/qpid/broker/Bridge.h
+++ b/cpp/src/qpid/broker/Bridge.h
@@ -59,8 +59,6 @@ public:
void destroy();
bool isDurable() { return args.i_durable; }
- bool isSessionReady() const;
-
management::ManagementObject* GetManagementObject() const;
management::Manageable::status_t ManagementMethod(uint32_t methodId,
management::Args& args,
diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp
index ec3cf9d340..3c692fc368 100644
--- a/cpp/src/qpid/broker/Broker.cpp
+++ b/cpp/src/qpid/broker/Broker.cpp
@@ -20,7 +20,6 @@
*/
#include "qpid/broker/Broker.h"
-#include "qpid/broker/ConnectionState.h"
#include "qpid/broker/DirectExchange.h"
#include "qpid/broker/FanOutExchange.h"
#include "qpid/broker/HeadersExchange.h"
@@ -32,26 +31,12 @@
#include "qpid/broker/TopicExchange.h"
#include "qpid/broker/Link.h"
#include "qpid/broker/ExpiryPolicy.h"
-#include "qpid/broker/QueueFlowLimit.h"
-#include "qpid/broker/MessageGroupManager.h"
#include "qmf/org/apache/qpid/broker/Package.h"
-#include "qmf/org/apache/qpid/broker/ArgsBrokerCreate.h"
-#include "qmf/org/apache/qpid/broker/ArgsBrokerDelete.h"
-#include "qmf/org/apache/qpid/broker/ArgsBrokerQuery.h"
#include "qmf/org/apache/qpid/broker/ArgsBrokerEcho.h"
#include "qmf/org/apache/qpid/broker/ArgsBrokerGetLogLevel.h"
#include "qmf/org/apache/qpid/broker/ArgsBrokerQueueMoveMessages.h"
#include "qmf/org/apache/qpid/broker/ArgsBrokerSetLogLevel.h"
-#include "qmf/org/apache/qpid/broker/ArgsBrokerSetTimestampConfig.h"
-#include "qmf/org/apache/qpid/broker/ArgsBrokerGetTimestampConfig.h"
-#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h"
-#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h"
-#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h"
-#include "qmf/org/apache/qpid/broker/EventQueueDelete.h"
-#include "qmf/org/apache/qpid/broker/EventBind.h"
-#include "qmf/org/apache/qpid/broker/EventUnbind.h"
-#include "qpid/amqp_0_10/Codecs.h"
#include "qpid/management/ManagementDirectExchange.h"
#include "qpid/management/ManagementTopicExchange.h"
#include "qpid/log/Logger.h"
@@ -59,9 +44,7 @@
#include "qpid/log/Statement.h"
#include "qpid/log/posix/SinkOptions.h"
#include "qpid/framing/AMQFrame.h"
-#include "qpid/framing/FieldTable.h"
#include "qpid/framing/ProtocolInitiation.h"
-#include "qpid/framing/reply_exceptions.h"
#include "qpid/framing/Uuid.h"
#include "qpid/sys/ProtocolFactory.h"
#include "qpid/sys/Poller.h"
@@ -93,10 +76,7 @@ using qpid::management::ManagementAgent;
using qpid::management::ManagementObject;
using qpid::management::Manageable;
using qpid::management::Args;
-using qpid::management::getManagementExecutionContext;
-using qpid::types::Variant;
using std::string;
-using std::make_pair;
namespace _qmf = qmf::org::apache::qpid::broker;
@@ -123,12 +103,7 @@ Broker::Options::Options(const std::string& name) :
maxSessionRate(0),
asyncQueueEvents(false), // Must be false in a cluster.
qmf2Support(true),
- qmf1Support(true),
- queueFlowStopRatio(80),
- queueFlowResumeRatio(70),
- queueThresholdEventRatio(80),
- defaultMsgGroup("qpid.no-group"),
- timestampRcvMsgs(false) // set the 0.10 timestamp delivery property
+ qmf1Support(true)
{
int c = sys::SystemInfo::concurrency();
workerThreads=c+1;
@@ -159,14 +134,9 @@ 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)")
- ("sasl-config", optValue(saslConfigPath, "DIR"), "gets sasl config info from nonstandard location")
+ ("sasl-config", optValue(saslConfigPath, "FILE"), "gets sasl config from nonstandard location")
("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")
- ("default-flow-stop-threshold", optValue(queueFlowStopRatio, "PERCENT"), "Percent of queue's maximum capacity at which flow control is activated.")
- ("default-flow-resume-threshold", optValue(queueFlowResumeRatio, "PERCENT"), "Percent of queue's maximum capacity at which flow control is de-activated.")
- ("default-event-threshold-ratio", optValue(queueThresholdEventRatio, "%age of limit"), "The ratio of any specified queue limit at which an event will be raised")
- ("default-message-group", optValue(defaultMsgGroup, "GROUP-IDENTIFER"), "Group identifier to assign to messages delivered to a message group queue that do not contain an identifier.")
- ("enable-timestamp", optValue(timestampRcvMsgs, "yes|no"), "Add current time to each received message.");
+ ("async-queue-events", optValue(asyncQueueEvents, "yes|no"), "Set Queue Events async, used for services like replication");
}
const std::string empty;
@@ -196,10 +166,9 @@ Broker::Broker(const Broker::Options& conf) :
conf.replayFlushLimit*1024, // convert kb to bytes.
conf.replayHardLimit*1024),
*this),
- queueCleaner(queues, &timer),
- queueEvents(poller,!conf.asyncQueueEvents),
+ queueCleaner(queues, timer),
+ queueEvents(poller,!conf.asyncQueueEvents),
recovery(true),
- inCluster(false),
clusterUpdatee(false),
expiryPolicy(new ExpiryPolicy),
connectionCounter(conf.maxConnections),
@@ -256,11 +225,8 @@ Broker::Broker(const Broker::Options& conf) :
// Early-Initialize plugins
Plugin::earlyInitAll(*this);
- QueueFlowLimit::setDefaults(conf.queueLimit, conf.queueFlowStopRatio, conf.queueFlowResumeRatio);
- MessageGroupManager::setDefaults(conf.defaultMsgGroup);
-
// If no plugin store module registered itself, set up the null store.
- if (NullMessageStore::isNullStore(store.get()))
+ if (NullMessageStore::isNullStore(store.get()))
setStore();
exchanges.declare(empty, DirectExchange::typeName); // Default exchange.
@@ -305,11 +271,6 @@ Broker::Broker(const Broker::Options& conf) :
else
QPID_LOG(info, "Management not enabled");
- // this feature affects performance, so let's be sure that gets logged!
- if (conf.timestampRcvMsgs) {
- QPID_LOG(notice, "Receive message timestamping is ENABLED.");
- }
-
/**
* SASL setup, can fail and terminate startup
*/
@@ -384,14 +345,14 @@ void Broker::run() {
Dispatcher d(poller);
int numIOThreads = config.workerThreads;
std::vector<Thread> t(numIOThreads-1);
-
+
// Run n-1 io threads
for (int i=0; i<numIOThreads-1; ++i)
t[i] = Thread(d);
-
+
// Run final thread
d.run();
-
+
// Now wait for n-1 io threads to exit
for (int i=0; i<numIOThreads-1; ++i) {
t[i].join();
@@ -438,9 +399,9 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
{
case _qmf::Broker::METHOD_ECHO :
QPID_LOG (debug, "Broker::echo("
- << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_sequence
- << ", "
- << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_body
+ << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_sequence
+ << ", "
+ << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_body
<< ")");
status = Manageable::STATUS_OK;
break;
@@ -448,9 +409,8 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
_qmf::ArgsBrokerConnect& hp=
dynamic_cast<_qmf::ArgsBrokerConnect&>(args);
+ QPID_LOG (debug, "Broker::connect()");
string transport = hp.i_transport.empty() ? TCP_TRANSPORT : hp.i_transport;
- QPID_LOG (debug, "Broker::connect() " << hp.i_host << ":" << hp.i_port << "; transport=" << transport <<
- "; durable=" << (hp.i_durable?"T":"F") << "; authMech=\"" << hp.i_authMechanism << "\"");
if (!getProtocolFactory(transport)) {
QPID_LOG(error, "Transport '" << transport << "' not supported");
return Manageable::STATUS_NOT_IMPLEMENTED;
@@ -467,9 +427,9 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
_qmf::ArgsBrokerQueueMoveMessages& moveArgs=
dynamic_cast<_qmf::ArgsBrokerQueueMoveMessages&>(args);
QPID_LOG (debug, "Broker::queueMoveMessages()");
- if (queueMoveMessages(moveArgs.i_srcQueue, moveArgs.i_destQueue, moveArgs.i_qty, moveArgs.i_filter))
+ if (queueMoveMessages(moveArgs.i_srcQueue, moveArgs.i_destQueue, moveArgs.i_qty))
status = Manageable::STATUS_OK;
- else
+ else
return Manageable::STATUS_PARAMETER_INVALID;
break;
}
@@ -483,38 +443,6 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
QPID_LOG (debug, "Broker::getLogLevel()");
status = Manageable::STATUS_OK;
break;
- case _qmf::Broker::METHOD_CREATE :
- {
- _qmf::ArgsBrokerCreate& a = dynamic_cast<_qmf::ArgsBrokerCreate&>(args);
- createObject(a.i_type, a.i_name, a.i_properties, a.i_strict, getManagementExecutionContext());
- status = Manageable::STATUS_OK;
- break;
- }
- case _qmf::Broker::METHOD_DELETE :
- {
- _qmf::ArgsBrokerDelete& a = dynamic_cast<_qmf::ArgsBrokerDelete&>(args);
- deleteObject(a.i_type, a.i_name, a.i_options, getManagementExecutionContext());
- status = Manageable::STATUS_OK;
- break;
- }
- case _qmf::Broker::METHOD_QUERY :
- {
- _qmf::ArgsBrokerQuery& a = dynamic_cast<_qmf::ArgsBrokerQuery&>(args);
- status = queryObject(a.i_type, a.i_name, a.o_results, getManagementExecutionContext());
- break;
- }
- case _qmf::Broker::METHOD_GETTIMESTAMPCONFIG:
- {
- _qmf::ArgsBrokerGetTimestampConfig& a = dynamic_cast<_qmf::ArgsBrokerGetTimestampConfig&>(args);
- status = getTimestampConfig(a.o_receive, getManagementExecutionContext());
- break;
- }
- case _qmf::Broker::METHOD_SETTIMESTAMPCONFIG:
- {
- _qmf::ArgsBrokerSetTimestampConfig& a = dynamic_cast<_qmf::ArgsBrokerSetTimestampConfig&>(args);
- status = setTimestampConfig(a.i_receive, getManagementExecutionContext());
- break;
- }
default:
QPID_LOG (debug, "Broker ManagementMethod not implemented: id=" << methodId << "]");
status = Manageable::STATUS_NOT_IMPLEMENTED;
@@ -524,240 +452,6 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
return status;
}
-namespace
-{
-const std::string TYPE_QUEUE("queue");
-const std::string TYPE_EXCHANGE("exchange");
-const std::string TYPE_TOPIC("topic");
-const std::string TYPE_BINDING("binding");
-const std::string DURABLE("durable");
-const std::string AUTO_DELETE("auto-delete");
-const std::string ALTERNATE_EXCHANGE("alternate-exchange");
-const std::string EXCHANGE_TYPE("exchange-type");
-const std::string QUEUE_NAME("queue");
-const std::string EXCHANGE_NAME("exchange");
-
-const std::string ATTRIBUTE_TIMESTAMP_0_10("timestamp-0.10");
-
-const std::string _TRUE("true");
-const std::string _FALSE("false");
-}
-
-struct InvalidBindingIdentifier : public qpid::Exception
-{
- InvalidBindingIdentifier(const std::string& name) : qpid::Exception(name) {}
- std::string getPrefix() const { return "invalid binding"; }
-};
-
-struct BindingIdentifier
-{
- std::string exchange;
- std::string queue;
- std::string key;
-
- BindingIdentifier(const std::string& name)
- {
- std::vector<std::string> path;
- split(path, name, "/");
- switch (path.size()) {
- case 1:
- queue = path[0];
- break;
- case 2:
- exchange = path[0];
- queue = path[1];
- break;
- case 3:
- exchange = path[0];
- queue = path[1];
- key = path[2];
- break;
- default:
- throw InvalidBindingIdentifier(name);
- }
- }
-};
-
-struct ObjectAlreadyExists : public qpid::Exception
-{
- ObjectAlreadyExists(const std::string& name) : qpid::Exception(name) {}
- std::string getPrefix() const { return "object already exists"; }
-};
-
-struct UnknownObjectType : public qpid::Exception
-{
- UnknownObjectType(const std::string& type) : qpid::Exception(type) {}
- std::string getPrefix() const { return "unknown object type"; }
-};
-
-void Broker::createObject(const std::string& type, const std::string& name,
- const Variant::Map& properties, bool /*strict*/, const ConnectionState* context)
-{
- std::string userId;
- std::string connectionId;
- if (context) {
- userId = context->getUserId();
- connectionId = context->getUrl();
- }
- //TODO: implement 'strict' option (check there are no unrecognised properties)
- QPID_LOG (debug, "Broker::create(" << type << ", " << name << "," << properties << ")");
- if (type == TYPE_QUEUE) {
- bool durable(false);
- bool autodelete(false);
- std::string alternateExchange;
- Variant::Map extensions;
- for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) {
- // extract durable, auto-delete and alternate-exchange properties
- if (i->first == DURABLE) durable = i->second;
- else if (i->first == AUTO_DELETE) autodelete = i->second;
- else if (i->first == ALTERNATE_EXCHANGE) alternateExchange = i->second.asString();
- //treat everything else as extension properties
- else extensions[i->first] = i->second;
- }
- framing::FieldTable arguments;
- amqp_0_10::translate(extensions, arguments);
-
- std::pair<boost::shared_ptr<Queue>, bool> result =
- createQueue(name, durable, autodelete, 0, alternateExchange, arguments, userId, connectionId);
- if (!result.second) {
- throw ObjectAlreadyExists(name);
- }
- } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) {
- bool durable(false);
- std::string exchangeType("topic");
- std::string alternateExchange;
- Variant::Map extensions;
- for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) {
- // extract durable, auto-delete and alternate-exchange properties
- if (i->first == DURABLE) durable = i->second;
- else if (i->first == EXCHANGE_TYPE) exchangeType = i->second.asString();
- else if (i->first == ALTERNATE_EXCHANGE) alternateExchange = i->second.asString();
- //treat everything else as extension properties
- else extensions[i->first] = i->second;
- }
- framing::FieldTable arguments;
- amqp_0_10::translate(extensions, arguments);
-
- try {
- std::pair<boost::shared_ptr<Exchange>, bool> result =
- createExchange(name, exchangeType, durable, alternateExchange, arguments, userId, connectionId);
- if (!result.second) {
- throw ObjectAlreadyExists(name);
- }
- } catch (const UnknownExchangeTypeException&) {
- throw Exception(QPID_MSG("Invalid exchange type: " << exchangeType));
- }
- } else if (type == TYPE_BINDING) {
- BindingIdentifier binding(name);
- std::string exchangeType("topic");
- Variant::Map extensions;
- for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) {
- // extract durable, auto-delete and alternate-exchange properties
- if (i->first == EXCHANGE_TYPE) exchangeType = i->second.asString();
- //treat everything else as extension properties
- else extensions[i->first] = i->second;
- }
- framing::FieldTable arguments;
- amqp_0_10::translate(extensions, arguments);
-
- bind(binding.queue, binding.exchange, binding.key, arguments, userId, connectionId);
- } else {
- throw UnknownObjectType(type);
- }
-}
-
-void Broker::deleteObject(const std::string& type, const std::string& name,
- const Variant::Map& options, const ConnectionState* context)
-{
- std::string userId;
- std::string connectionId;
- if (context) {
- userId = context->getUserId();
- connectionId = context->getUrl();
- }
- QPID_LOG (debug, "Broker::delete(" << type << ", " << name << "," << options << ")");
- if (type == TYPE_QUEUE) {
- deleteQueue(name, userId, connectionId);
- } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) {
- deleteExchange(name, userId, connectionId);
- } else if (type == TYPE_BINDING) {
- BindingIdentifier binding(name);
- unbind(binding.queue, binding.exchange, binding.key, userId, connectionId);
- } else {
- throw UnknownObjectType(type);
- }
-
-}
-
-Manageable::status_t Broker::queryObject(const std::string& type,
- const std::string& name,
- Variant::Map& results,
- const ConnectionState* context)
-{
- std::string userId;
- std::string connectionId;
- if (context) {
- userId = context->getUserId();
- connectionId = context->getUrl();
- }
- QPID_LOG (debug, "Broker::query(" << type << ", " << name << ")");
-
- if (type == TYPE_QUEUE)
- return queryQueue( name, userId, connectionId, results );
-
- if (type == TYPE_EXCHANGE ||
- type == TYPE_TOPIC ||
- type == TYPE_BINDING)
- return Manageable::STATUS_NOT_IMPLEMENTED;
-
- throw UnknownObjectType(type);
-}
-
-Manageable::status_t Broker::queryQueue( const std::string& name,
- const std::string& userId,
- const std::string& /*connectionId*/,
- Variant::Map& results )
-{
- (void) results;
- if (acl) {
- if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_QUEUE, name, NULL) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue query request from " << userId));
- }
-
- boost::shared_ptr<Queue> q(queues.find(name));
- if (!q) {
- QPID_LOG(error, "Query failed: queue not found, name=" << name);
- return Manageable::STATUS_UNKNOWN_OBJECT;
- }
- q->query( results );
- return Manageable::STATUS_OK;;
-}
-
-Manageable::status_t Broker::getTimestampConfig(bool& receive,
- const ConnectionState* context)
-{
- std::string name; // none needed for broker
- std::string userId = context->getUserId();
- if (acl && !acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_BROKER, name, NULL)) {
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied broker timestamp get request from " << userId));
- }
- receive = config.timestampRcvMsgs;
- return Manageable::STATUS_OK;
-}
-
-Manageable::status_t Broker::setTimestampConfig(const bool receive,
- const ConnectionState* context)
-{
- std::string name; // none needed for broker
- std::string userId = context->getUserId();
- if (acl && !acl->authorise(userId, acl::ACT_UPDATE, acl::OBJ_BROKER, name, NULL)) {
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied broker timestamp set request from " << userId));
- }
- config.timestampRcvMsgs = receive;
- QPID_LOG(notice, "Receive message timestamping is " << ((config.timestampRcvMsgs) ? "ENABLED." : "DISABLED."));
- return Manageable::STATUS_OK;
-}
-
void Broker::setLogLevel(const std::string& level)
{
QPID_LOG(notice, "Changing log level to " << level);
@@ -772,7 +466,7 @@ std::string Broker::getLogLevel()
const std::vector<std::string>& selectors = qpid::log::Logger::instance().getOptions().selectors;
for (std::vector<std::string>::const_iterator i = selectors.begin(); i != selectors.end(); ++i) {
if (i != selectors.begin()) level += std::string(",");
- level += *i;
+ level += *i;
}
return level;
}
@@ -805,7 +499,7 @@ void Broker::accept() {
}
void Broker::connect(
- const std::string& host, const std::string& port, const std::string& transport,
+ const std::string& host, uint16_t port, const std::string& transport,
boost::function2<void, int, std::string> failed,
sys::ConnectionCodec::Factory* f)
{
@@ -821,14 +515,13 @@ void Broker::connect(
{
url.throwIfEmpty();
const Address& addr=url[0];
- connect(addr.host, boost::lexical_cast<std::string>(addr.port), addr.protocol, failed, f);
+ connect(addr.host, addr.port, addr.protocol, failed, f);
}
uint32_t Broker::queueMoveMessages(
const std::string& srcQueue,
const std::string& destQueue,
- uint32_t qty,
- const Variant::Map& filter)
+ uint32_t qty)
{
Queue::shared_ptr src_queue = queues.find(srcQueue);
if (!src_queue)
@@ -837,7 +530,7 @@ uint32_t Broker::queueMoveMessages(
if (!dest_queue)
return 0;
- return src_queue->move(dest_queue, qty, &filter);
+ return src_queue->move(dest_queue, qty);
}
@@ -855,228 +548,9 @@ bool Broker::deferDeliveryImpl(const std::string& ,
void Broker::setClusterTimer(std::auto_ptr<sys::Timer> t) {
clusterTimer = t;
- queueCleaner.setTimer(clusterTimer.get());
- dtxManager.setTimer(*clusterTimer.get());
}
const std::string Broker::TCP_TRANSPORT("tcp");
-
-std::pair<boost::shared_ptr<Queue>, bool> Broker::createQueue(
- const std::string& name,
- bool durable,
- bool autodelete,
- const OwnershipToken* owner,
- const std::string& alternateExchange,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId)
-{
- if (acl) {
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
- params.insert(make_pair(acl::PROP_PASSIVE, _FALSE));
- params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE));
- params.insert(make_pair(acl::PROP_EXCLUSIVE, owner ? _TRUE : _FALSE));
- params.insert(make_pair(acl::PROP_AUTODELETE, 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(userId,acl::ACT_CREATE,acl::OBJ_QUEUE,name,&params) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << userId));
- }
-
- Exchange::shared_ptr alternate;
- if (!alternateExchange.empty()) {
- alternate = exchanges.get(alternateExchange);
- if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange));
- }
-
- std::pair<Queue::shared_ptr, bool> result = queues.declare(name, durable, autodelete, owner, alternate, arguments);
- if (result.second) {
- //add default binding:
- result.first->bind(exchanges.getDefault(), name);
-
- if (managementAgent.get()) {
- //TODO: debatable whether we should raise an event here for
- //create when this is a 'declare' event; ideally add a create
- //event instead?
- managementAgent->raiseEvent(
- _qmf::EventQueueDeclare(connectionId, userId, name,
- durable, owner, autodelete,
- ManagementAgent::toMap(arguments),
- "created"));
- }
- }
- return result;
-}
-
-void Broker::deleteQueue(const std::string& name, const std::string& userId,
- const std::string& connectionId, QueueFunctor check)
-{
- if (acl && !acl->authorise(userId,acl::ACT_DELETE,acl::OBJ_QUEUE,name,NULL)) {
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue delete request from " << userId));
- }
-
- Queue::shared_ptr queue = queues.find(name);
- if (queue) {
- if (check) check(queue);
- queues.destroy(name);
- queue->destroyed();
- } else {
- throw framing::NotFoundException(QPID_MSG("Delete failed. No such queue: " << name));
- }
-
- if (managementAgent.get())
- managementAgent->raiseEvent(_qmf::EventQueueDelete(connectionId, userId, name));
-
-}
-
-std::pair<Exchange::shared_ptr, bool> Broker::createExchange(
- const std::string& name,
- const std::string& type,
- bool durable,
- const std::string& alternateExchange,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId)
-{
- if (acl) {
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_TYPE, type));
- params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
- params.insert(make_pair(acl::PROP_PASSIVE, _FALSE));
- params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE));
- if (!acl->authorise(userId,acl::ACT_CREATE,acl::OBJ_EXCHANGE,name,&params) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange create request from " << userId));
- }
-
- Exchange::shared_ptr alternate;
- if (!alternateExchange.empty()) {
- alternate = exchanges.get(alternateExchange);
- if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange));
- }
-
- std::pair<Exchange::shared_ptr, bool> result;
- result = exchanges.declare(name, type, durable, arguments);
- if (result.second) {
- if (alternate) {
- result.first->setAlternate(alternate);
- alternate->incAlternateUsers();
- }
- if (durable) {
- store->create(*result.first, arguments);
- }
- if (managementAgent.get()) {
- //TODO: debatable whether we should raise an event here for
- //create when this is a 'declare' event; ideally add a create
- //event instead?
- managementAgent->raiseEvent(_qmf::EventExchangeDeclare(connectionId,
- userId,
- name,
- type,
- alternateExchange,
- durable,
- false,
- ManagementAgent::toMap(arguments),
- "created"));
- }
- }
- return result;
-}
-
-void Broker::deleteExchange(const std::string& name, const std::string& userId,
- const std::string& connectionId)
-{
- if (acl) {
- if (!acl->authorise(userId,acl::ACT_DELETE,acl::OBJ_EXCHANGE,name,NULL) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange delete request from " << userId));
- }
-
- if (name.empty()) {
- throw framing::InvalidArgumentException(QPID_MSG("Delete not allowed for default exchange"));
- }
- Exchange::shared_ptr exchange(exchanges.get(name));
- if (!exchange) throw framing::NotFoundException(QPID_MSG("Delete failed. No such exchange: " << name));
- if (exchange->inUseAsAlternate()) throw framing::NotAllowedException(QPID_MSG("Exchange in use as alternate-exchange."));
- if (exchange->isDurable()) store->destroy(*exchange);
- if (exchange->getAlternate()) exchange->getAlternate()->decAlternateUsers();
- exchanges.destroy(name);
-
- if (managementAgent.get())
- managementAgent->raiseEvent(_qmf::EventExchangeDelete(connectionId, userId, name));
-
-}
-
-void Broker::bind(const std::string& queueName,
- const std::string& exchangeName,
- const std::string& key,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId)
-{
- if (acl) {
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_QUEUENAME, queueName));
- params.insert(make_pair(acl::PROP_ROUTINGKEY, key));
-
- if (!acl->authorise(userId,acl::ACT_BIND,acl::OBJ_EXCHANGE,exchangeName,&params))
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange bind request from " << userId));
- }
- if (exchangeName.empty()) {
- throw framing::InvalidArgumentException(QPID_MSG("Bind not allowed for default exchange"));
- }
-
- Queue::shared_ptr queue = queues.find(queueName);
- Exchange::shared_ptr exchange = exchanges.get(exchangeName);
- if (!queue) {
- throw framing::NotFoundException(QPID_MSG("Bind failed. No such queue: " << queueName));
- } else if (!exchange) {
- throw framing::NotFoundException(QPID_MSG("Bind failed. No such exchange: " << exchangeName));
- } else {
- if (queue->bind(exchange, key, arguments)) {
- if (managementAgent.get()) {
- managementAgent->raiseEvent(_qmf::EventBind(connectionId, userId, exchangeName,
- queueName, key, ManagementAgent::toMap(arguments)));
- }
- }
- }
-}
-
-void Broker::unbind(const std::string& queueName,
- const std::string& exchangeName,
- const std::string& key,
- const std::string& userId,
- const std::string& connectionId)
-{
- if (acl) {
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_QUEUENAME, queueName));
- params.insert(make_pair(acl::PROP_ROUTINGKEY, key));
- if (!acl->authorise(userId,acl::ACT_UNBIND,acl::OBJ_EXCHANGE,exchangeName,&params) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange unbind request from " << userId));
- }
- if (exchangeName.empty()) {
- throw framing::InvalidArgumentException(QPID_MSG("Unbind not allowed for default exchange"));
- }
- Queue::shared_ptr queue = queues.find(queueName);
- Exchange::shared_ptr exchange = exchanges.get(exchangeName);
- if (!queue) {
- throw framing::NotFoundException(QPID_MSG("Unbind failed. No such queue: " << queueName));
- } else if (!exchange) {
- throw framing::NotFoundException(QPID_MSG("Unbind failed. No such exchange: " << exchangeName));
- } else {
- if (exchange->unbind(queue, key, 0)) {
- if (exchange->isDurable() && queue->isDurable()) {
- store->unbind(*exchange, *queue, key, qpid::framing::FieldTable());
- }
- if (managementAgent.get()) {
- managementAgent->raiseEvent(_qmf::EventUnbind(connectionId, userId, exchangeName, queueName, key));
- }
- }
- }
-}
-
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h
index b3b751be98..cd6f81dc70 100644
--- a/cpp/src/qpid/broker/Broker.h
+++ b/cpp/src/qpid/broker/Broker.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -49,7 +49,6 @@
#include "qpid/framing/ProtocolInitiation.h"
#include "qpid/sys/Runnable.h"
#include "qpid/sys/Timer.h"
-#include "qpid/types/Variant.h"
#include "qpid/RefCounted.h"
#include "qpid/broker/AclModule.h"
#include "qpid/sys/Mutex.h"
@@ -58,7 +57,7 @@
#include <string>
#include <vector>
-namespace qpid {
+namespace qpid {
namespace sys {
class ProtocolFactory;
@@ -69,7 +68,6 @@ struct Url;
namespace broker {
-class ConnectionState;
class ExpiryPolicy;
class Message;
@@ -82,7 +80,7 @@ struct NoSuchTransportException : qpid::Exception
};
/**
- * A broker instance.
+ * A broker instance.
*/
class Broker : public sys::Runnable, public Plugin::Target,
public management::Manageable,
@@ -118,34 +116,29 @@ public:
bool asyncQueueEvents;
bool qmf2Support;
bool qmf1Support;
- uint queueFlowStopRatio; // producer flow control: on
- uint queueFlowResumeRatio; // producer flow control: off
- uint16_t queueThresholdEventRatio;
- std::string defaultMsgGroup;
- bool timestampRcvMsgs;
private:
std::string getHome();
};
-
+
class ConnectionCounter {
int maxConnections;
int connectionCount;
sys::Mutex connectionCountLock;
public:
ConnectionCounter(int mc): maxConnections(mc),connectionCount(0) {};
- void inc_connectionCount() {
- sys::ScopedLock<sys::Mutex> l(connectionCountLock);
+ void inc_connectionCount() {
+ sys::ScopedLock<sys::Mutex> l(connectionCountLock);
connectionCount++;
- }
- void dec_connectionCount() {
- sys::ScopedLock<sys::Mutex> l(connectionCountLock);
+ }
+ void dec_connectionCount() {
+ sys::ScopedLock<sys::Mutex> l(connectionCountLock);
connectionCount--;
}
bool allowConnection() {
- sys::ScopedLock<sys::Mutex> l(connectionCountLock);
+ sys::ScopedLock<sys::Mutex> l(connectionCountLock);
return (maxConnections <= connectionCount);
- }
+ }
};
private:
@@ -155,20 +148,7 @@ public:
void setStore ();
void setLogLevel(const std::string& level);
std::string getLogLevel();
- void createObject(const std::string& type, const std::string& name,
- const qpid::types::Variant::Map& properties, bool strict, const ConnectionState* context);
- void deleteObject(const std::string& type, const std::string& name,
- const qpid::types::Variant::Map& options, const ConnectionState* context);
- Manageable::status_t queryObject(const std::string& type, const std::string& name,
- qpid::types::Variant::Map& results, const ConnectionState* context);
- Manageable::status_t queryQueue( const std::string& name,
- const std::string& userId,
- const std::string& connectionId,
- qpid::types::Variant::Map& results);
- Manageable::status_t getTimestampConfig(bool& receive,
- const ConnectionState* context);
- Manageable::status_t setTimestampConfig(const bool receive,
- const ConnectionState* context);
+
boost::shared_ptr<sys::Poller> poller;
sys::Timer timer;
std::auto_ptr<sys::Timer> clusterTimer;
@@ -196,10 +176,10 @@ public:
const boost::intrusive_ptr<Message>& msg);
std::string federationTag;
bool recovery;
- bool inCluster, clusterUpdatee;
+ bool clusterUpdatee;
boost::intrusive_ptr<ExpiryPolicy> expiryPolicy;
ConnectionCounter connectionCounter;
-
+
public:
virtual ~Broker();
@@ -255,7 +235,7 @@ public:
QPID_BROKER_EXTERN void accept();
/** Create a connection to another broker. */
- void connect(const std::string& host, const std::string& port,
+ void connect(const std::string& host, uint16_t port,
const std::string& transport,
boost::function2<void, int, std::string> failed,
sys::ConnectionCodec::Factory* =0);
@@ -267,10 +247,9 @@ public:
/** Move messages from one queue to another.
A zero quantity means to move all messages
*/
- uint32_t queueMoveMessages( const std::string& srcQueue,
+ uint32_t queueMoveMessages( const std::string& srcQueue,
const std::string& destQueue,
- uint32_t qty,
- const qpid::types::Variant::Map& filter);
+ uint32_t qty);
boost::shared_ptr<sys::ProtocolFactory> getProtocolFactory(const std::string& name = TCP_TRANSPORT) const;
@@ -294,20 +273,11 @@ public:
void setRecovery(bool set) { recovery = set; }
bool getRecovery() const { return recovery; }
- /** True of this broker is part of a cluster.
- * Only valid after early initialization of plugins is complete.
- */
- bool isInCluster() const { return inCluster; }
- void setInCluster(bool set) { inCluster = set; }
-
- /** True if this broker is joining a cluster and in the process of
- * receiving a state update.
- */
- bool isClusterUpdatee() const { return clusterUpdatee; }
void setClusterUpdatee(bool set) { clusterUpdatee = set; }
+ bool isClusterUpdatee() const { return clusterUpdatee; }
management::ManagementAgent* getManagementAgent() { return managementAgent.get(); }
-
+
ConnectionCounter& getConnectionCounter() {return connectionCounter;}
/**
@@ -320,43 +290,6 @@ public:
const boost::intrusive_ptr<Message>& msg)> deferDelivery;
bool isAuthenticating ( ) { return config.auth; }
- bool isTimestamping() { return config.timestampRcvMsgs; }
-
- typedef boost::function1<void, boost::shared_ptr<Queue> > QueueFunctor;
-
- std::pair<boost::shared_ptr<Queue>, bool> createQueue(
- const std::string& name,
- bool durable,
- bool autodelete,
- const OwnershipToken* owner,
- const std::string& alternateExchange,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId);
- void deleteQueue(const std::string& name,
- const std::string& userId,
- const std::string& connectionId,
- QueueFunctor check = QueueFunctor());
- std::pair<Exchange::shared_ptr, bool> createExchange(
- const std::string& name,
- const std::string& type,
- bool durable,
- const std::string& alternateExchange,
- const qpid::framing::FieldTable& args,
- const std::string& userId, const std::string& connectionId);
- void deleteExchange(const std::string& name, const std::string& userId,
- const std::string& connectionId);
- void bind(const std::string& queue,
- const std::string& exchange,
- const std::string& key,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId);
- void unbind(const std::string& queue,
- const std::string& exchange,
- const std::string& key,
- const std::string& userId,
- const std::string& connectionId);
};
}}
diff --git a/cpp/src/qpid/broker/BrokerImportExport.h b/cpp/src/qpid/broker/BrokerImportExport.h
index ee05788063..4edf8c9844 100644
--- a/cpp/src/qpid/broker/BrokerImportExport.h
+++ b/cpp/src/qpid/broker/BrokerImportExport.h
@@ -20,23 +20,14 @@
* under the License.
*/
-#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
-# if defined(BROKER_EXPORT) || defined (qpidbroker_EXPORTS)
-# define QPID_BROKER_EXTERN __declspec(dllexport)
-# else
-# define QPID_BROKER_EXTERN __declspec(dllimport)
-# endif
-# ifdef _MSC_VER
-# define QPID_BROKER_CLASS_EXTERN
-# define QPID_BROKER_INLINE_EXTERN QPID_BROKER_EXTERN
-# else
-# define QPID_BROKER_CLASS_EXTERN QPID_BROKER_EXTERN
-# define QPID_BROKER_INLINE_EXTERN
-# endif
+#if defined(WIN32) && !defined(QPID_BROKER_STATIC)
+#if defined(BROKER_EXPORT) || defined (qpidbroker_EXPORTS)
+#define QPID_BROKER_EXTERN __declspec(dllexport)
#else
-# define QPID_BROKER_EXTERN
-# define QPID_BROKER_CLASS_EXTERN
-# define QPID_BROKER_INLINE_EXTERN
+#define QPID_BROKER_EXTERN __declspec(dllimport)
+#endif
+#else
+#define QPID_BROKER_EXTERN
#endif
#endif
diff --git a/cpp/src/qpid/broker/Connection.cpp b/cpp/src/qpid/broker/Connection.cpp
index 0b3059d26c..460799280e 100644
--- a/cpp/src/qpid/broker/Connection.cpp
+++ b/cpp/src/qpid/broker/Connection.cpp
@@ -156,7 +156,16 @@ Connection::~Connection()
void Connection::received(framing::AMQFrame& frame) {
// Received frame on connection so delay timeout
restartTimeout();
- adapter.handle(frame);
+
+ if (frame.getChannel() == 0 && frame.getMethod()) {
+ adapter.handle(frame);
+ } else {
+ if (adapter.isOpen())
+ getChannel(frame.getChannel()).in(frame);
+ else
+ close(connection::CLOSE_CODE_FRAMING_ERROR, "Connection not yet open, invalid frame received.");
+ }
+
if (isLink) //i.e. we are acting as the client to another broker
recordFromServer(frame);
else
@@ -269,7 +278,8 @@ void Connection::setUserId(const string& userId)
ConnectionState::setUserId(userId);
// In a cluster, the cluster code will raise the connect event
// when the connection is replicated to the cluster.
- if (!broker.isInCluster()) raiseConnectEvent();
+ if (!sys::isCluster())
+ raiseConnectEvent();
}
void Connection::raiseConnectEvent() {
@@ -279,11 +289,11 @@ void Connection::raiseConnectEvent() {
}
}
-void Connection::setUserProxyAuth(bool b)
+void Connection::setFederationLink(bool b)
{
- ConnectionState::setUserProxyAuth(b);
+ ConnectionState::setFederationLink(b);
if (mgmtObject != 0)
- mgmtObject->set_userProxyAuth(b);
+ mgmtObject->set_federationLink(b);
}
void Connection::close(connection::CloseCode code, const string& text)
@@ -322,30 +332,31 @@ void Connection::closed(){ // Physically closed, suspend open sessions.
try {
while (!channels.empty())
ptr_map_ptr(channels.begin())->handleDetach();
+ while (!exclusiveQueues.empty()) {
+ boost::shared_ptr<Queue> q(exclusiveQueues.front());
+ q->releaseExclusiveOwnership();
+ if (q->canAutoDelete()) {
+ Queue::tryAutoDelete(broker, q);
+ }
+ exclusiveQueues.erase(exclusiveQueues.begin());
+ }
} catch(std::exception& e) {
QPID_LOG(error, QPID_MSG("While closing connection: " << e.what()));
assert(0);
}
}
-void Connection::doIoCallbacks() {
- {
- ScopedLock<Mutex> l(ioCallbackLock);
- // Although IO callbacks execute in the connection thread context, they are
- // not cluster safe because they are queued for execution in non-IO threads.
- ClusterUnsafeScope cus;
- while (!ioCallbacks.empty()) {
- boost::function0<void> cb = ioCallbacks.front();
- ioCallbacks.pop();
- ScopedUnlock<Mutex> ul(ioCallbackLock);
- cb(); // Lend the IO thread for management processing
- }
- }
-}
-
bool Connection::doOutput() {
try {
- doIoCallbacks();
+ {
+ ScopedLock<Mutex> l(ioCallbackLock);
+ while (!ioCallbacks.empty()) {
+ boost::function0<void> cb = ioCallbacks.front();
+ ioCallbacks.pop();
+ ScopedUnlock<Mutex> ul(ioCallbackLock);
+ cb(); // Lend the IO thread for management processing
+ }
+ }
if (mgmtClosing) {
closed();
close(connection::CLOSE_CODE_CONNECTION_FORCED, "Closed by Management Request");
@@ -465,8 +476,8 @@ void Connection::OutboundFrameTracker::abort() { next->abort(); }
void Connection::OutboundFrameTracker::activateOutput() { next->activateOutput(); }
void Connection::OutboundFrameTracker::giveReadCredit(int32_t credit) { next->giveReadCredit(credit); }
void Connection::OutboundFrameTracker::send(framing::AMQFrame& f)
-{
- next->send(f);
+{
+ next->send(f);
con.sent(f);
}
void Connection::OutboundFrameTracker::wrap(sys::ConnectionOutputHandlerPtr& p)
diff --git a/cpp/src/qpid/broker/Connection.h b/cpp/src/qpid/broker/Connection.h
index 3522d70b35..b751848d73 100644
--- a/cpp/src/qpid/broker/Connection.h
+++ b/cpp/src/qpid/broker/Connection.h
@@ -125,7 +125,7 @@ class Connection : public sys::ConnectionInputHandler,
const std::string& getUserId() const { return ConnectionState::getUserId(); }
const std::string& getMgmtId() const { return mgmtId; }
management::ManagementAgent* getAgent() const { return agent; }
- void setUserProxyAuth(bool b);
+ void setFederationLink(bool b);
/** Connection does not delete the listener. 0 resets. */
void setErrorListener(ErrorListener* l) { errorListener=l; }
ErrorListener* getErrorListener() { return errorListener; }
@@ -153,16 +153,13 @@ class Connection : public sys::ConnectionInputHandler,
void addManagementObject();
const qpid::sys::SecuritySettings& getExternalSecuritySettings() const
- {
+ {
return securitySettings;
}
/** @return true if the initial connection negotiation is complete. */
bool isOpen();
- // Used by cluster during catch-up, see cluster::OutputInterceptor
- void doIoCallbacks();
-
private:
typedef boost::ptr_map<framing::ChannelId, SessionHandler> ChannelMap;
typedef std::vector<boost::shared_ptr<Queue> >::iterator queue_iterator;
@@ -204,7 +201,7 @@ class Connection : public sys::ConnectionInputHandler,
sys::ConnectionOutputHandler* next;
};
OutboundFrameTracker outboundTracker;
-
+
void sent(const framing::AMQFrame& f);
public:
diff --git a/cpp/src/qpid/broker/ConnectionHandler.cpp b/cpp/src/qpid/broker/ConnectionHandler.cpp
index 7cd91ae539..3f97e5b9de 100644
--- a/cpp/src/qpid/broker/ConnectionHandler.cpp
+++ b/cpp/src/qpid/broker/ConnectionHandler.cpp
@@ -26,7 +26,6 @@
#include "qpid/broker/SecureConnection.h"
#include "qpid/Url.h"
#include "qpid/framing/AllInvoker.h"
-#include "qpid/framing/ConnectionStartOkBody.h"
#include "qpid/framing/enum.h"
#include "qpid/log/Statement.h"
#include "qpid/sys/SecurityLayer.h"
@@ -64,31 +63,13 @@ void ConnectionHandler::heartbeat()
handler->proxy.heartbeat();
}
-bool ConnectionHandler::handle(const framing::AMQMethodBody& method)
-{
- //Need special handling for start-ok, in order to distinguish
- //between null and empty response
- if (method.isA<ConnectionStartOkBody>()) {
- handler->startOk(dynamic_cast<const ConnectionStartOkBody&>(method));
- return true;
- } else {
- return invoke(static_cast<AMQP_AllOperations::ConnectionHandler&>(*handler), method);
- }
-}
-
void ConnectionHandler::handle(framing::AMQFrame& frame)
{
AMQMethodBody* method=frame.getBody()->getMethod();
Connection::ErrorListener* errorListener = handler->connection.getErrorListener();
try{
- if (method && handle(*method)) {
- // This is a connection control frame, nothing more to do.
- } else if (isOpen()) {
+ if (!invoke(static_cast<AMQP_AllOperations::ConnectionHandler&>(*handler.get()), *method)) {
handler->connection.getChannel(frame.getChannel()).in(frame);
- } else {
- handler->proxy.close(
- connection::CLOSE_CODE_FRAMING_ERROR,
- "Connection not yet open, invalid frame received.");
}
}catch(ConnectionException& e){
if (errorListener) errorListener->connectionError(e.what());
@@ -108,10 +89,13 @@ ConnectionHandler::ConnectionHandler(Connection& connection, bool isClient, bool
ConnectionHandler::Handler::Handler(Connection& c, bool isClient, bool isShadow) :
proxy(c.getOutput()),
- connection(c), serverMode(!isClient), secured(0),
+ connection(c), serverMode(!isClient), acl(0), secured(0),
isOpen(false)
{
if (serverMode) {
+
+ acl = connection.getBroker().getAcl();
+
FieldTable properties;
Array mechanisms(0x95);
@@ -134,20 +118,13 @@ ConnectionHandler::Handler::Handler(Connection& c, bool isClient, bool isShadow)
ConnectionHandler::Handler::~Handler() {}
-void ConnectionHandler::Handler::startOk(const framing::FieldTable& /*clientProperties*/,
- const string& /*mechanism*/,
- const string& /*response*/,
+void ConnectionHandler::Handler::startOk(const framing::FieldTable& clientProperties,
+ const string& mechanism,
+ const string& response,
const string& /*locale*/)
{
- //Need special handling for start-ok, in order to distinguish
- //between null and empty response -> should never use this method
- assert(false);
-}
-
-void ConnectionHandler::Handler::startOk(const ConnectionStartOkBody& body)
-{
try {
- authenticator->start(body.getMechanism(), body.hasResponse() ? &body.getResponse() : 0);
+ authenticator->start(mechanism, response);
} catch (std::exception& /*e*/) {
management::ManagementAgent* agent = connection.getAgent();
if (agent) {
@@ -159,14 +136,9 @@ void ConnectionHandler::Handler::startOk(const ConnectionStartOkBody& body)
}
throw;
}
- const framing::FieldTable& clientProperties = body.getClientProperties();
connection.setFederationLink(clientProperties.get(QPID_FED_LINK));
- if (clientProperties.isSet(QPID_FED_TAG)) {
- connection.setFederationPeerTag(clientProperties.getAsString(QPID_FED_TAG));
- }
+ connection.setFederationPeerTag(clientProperties.getAsString(QPID_FED_TAG));
if (connection.isFederationLink()) {
- AclModule* acl = connection.getBroker().getAcl();
- FieldTable properties;
if (acl && !acl->authorise(connection.getUserId(),acl::ACT_CREATE,acl::OBJ_LINK,"")){
proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,"ACL denied creating a federation link");
return;
@@ -211,7 +183,7 @@ void ConnectionHandler::Handler::secureOk(const string& response)
void ConnectionHandler::Handler::tuneOk(uint16_t /*channelmax*/,
uint16_t framemax, uint16_t heartbeat)
{
- if (framemax) connection.setFrameMax(framemax);
+ connection.setFrameMax(framemax);
connection.setHeartbeatInterval(heartbeat);
}
@@ -284,6 +256,7 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
false ); // disallow interaction
}
std::string supportedMechanismsList;
+ bool requestedMechanismIsSupported = false;
Array::const_iterator i;
/*
@@ -296,9 +269,11 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
if (i != supportedMechanisms.begin())
supportedMechanismsList += SPACE;
supportedMechanismsList += (*i)->get<std::string>();
+ requestedMechanismIsSupported = true;
}
}
else {
+ requestedMechanismIsSupported = false;
/*
The caller has requested a mechanism. If it's available,
make sure it ends up at the head of the list.
@@ -307,6 +282,7 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
string currentMechanism = (*i)->get<std::string>();
if ( requestedMechanism == currentMechanism ) {
+ requestedMechanismIsSupported = true;
supportedMechanismsList = currentMechanism + SPACE + supportedMechanismsList;
} else {
if (i != supportedMechanisms.begin())
@@ -316,9 +292,7 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
}
}
- if (serverProperties.isSet(QPID_FED_TAG)) {
- connection.setFederationPeerTag(serverProperties.getAsString(QPID_FED_TAG));
- }
+ connection.setFederationPeerTag(serverProperties.getAsString(QPID_FED_TAG));
FieldTable ft;
ft.setInt(QPID_FED_LINK,1);
@@ -327,21 +301,11 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
string response;
if (sasl.get()) {
const qpid::sys::SecuritySettings& ss = connection.getExternalSecuritySettings();
- if (sasl->start ( requestedMechanism.empty()
- ? supportedMechanismsList
- : requestedMechanism,
- response,
- & ss )) {
- proxy.startOk ( ft, sasl->getMechanism(), response, en_US );
- } else {
- //response was null
- ConnectionStartOkBody body;
- body.setClientProperties(ft);
- body.setMechanism(sasl->getMechanism());
- //Don't set response, as none was given
- body.setLocale(en_US);
- proxy.send(body);
- }
+ response = sasl->start ( requestedMechanism.empty()
+ ? supportedMechanismsList
+ : requestedMechanism,
+ & ss );
+ proxy.startOk ( ft, sasl->getMechanism(), response, en_US );
}
else {
response = ((char)0) + username + ((char)0) + password;
diff --git a/cpp/src/qpid/broker/ConnectionHandler.h b/cpp/src/qpid/broker/ConnectionHandler.h
index 05c5f00c57..b32167669e 100644
--- a/cpp/src/qpid/broker/ConnectionHandler.h
+++ b/cpp/src/qpid/broker/ConnectionHandler.h
@@ -26,10 +26,8 @@
#include "qpid/broker/SaslAuthenticator.h"
#include "qpid/framing/amqp_types.h"
#include "qpid/framing/AMQFrame.h"
-#include "qpid/framing/AMQMethodBody.h"
#include "qpid/framing/AMQP_AllOperations.h"
#include "qpid/framing/AMQP_AllProxy.h"
-#include "qpid/framing/ConnectionStartOkBody.h"
#include "qpid/framing/enum.h"
#include "qpid/framing/FrameHandler.h"
#include "qpid/framing/ProtocolInitiation.h"
@@ -59,12 +57,12 @@ class ConnectionHandler : public framing::FrameHandler
Connection& connection;
bool serverMode;
std::auto_ptr<SaslAuthenticator> authenticator;
+ AclModule* acl;
SecureConnection* secured;
bool isOpen;
Handler(Connection& connection, bool isClient, bool isShadow=false);
~Handler();
- void startOk(const qpid::framing::ConnectionStartOkBody& body);
void startOk(const qpid::framing::FieldTable& clientProperties,
const std::string& mechanism, const std::string& response,
const std::string& locale);
@@ -98,7 +96,7 @@ class ConnectionHandler : public framing::FrameHandler
};
std::auto_ptr<Handler> handler;
- bool handle(const qpid::framing::AMQMethodBody& method);
+
public:
ConnectionHandler(Connection& connection, bool isClient, bool isShadow=false );
void close(framing::connection::CloseCode code, const std::string& text);
diff --git a/cpp/src/qpid/broker/ConnectionState.h b/cpp/src/qpid/broker/ConnectionState.h
index fdd3c4ddc0..774c37408d 100644
--- a/cpp/src/qpid/broker/ConnectionState.h
+++ b/cpp/src/qpid/broker/ConnectionState.h
@@ -46,7 +46,6 @@ class ConnectionState : public ConnectionToken, public management::Manageable
framemax(65535),
heartbeat(0),
heartbeatmax(120),
- userProxyAuth(false), // Can proxy msgs with non-matching auth ids when true (used by federation links & clustering)
federationLink(true),
clientSupportsThrottling(false),
clusterOrderOut(0)
@@ -68,10 +67,8 @@ class ConnectionState : public ConnectionToken, public management::Manageable
void setUrl(const std::string& _url) { url = _url; }
const std::string& getUrl() const { return url; }
- void setUserProxyAuth(const bool b) { userProxyAuth = b; }
- bool isUserProxyAuth() const { return userProxyAuth || federationPeerTag.size() > 0; } // links can proxy msgs with non-matching auth ids
- void setFederationLink(bool b) { federationLink = b; } // deprecated - use setFederationPeerTag() instead
- bool isFederationLink() const { return federationPeerTag.size() > 0; }
+ void setFederationLink(bool b) { federationLink = b; }
+ bool isFederationLink() const { return federationLink; }
void setFederationPeerTag(const std::string& tag) { federationPeerTag = std::string(tag); }
const std::string& getFederationPeerTag() const { return federationPeerTag; }
std::vector<Url>& getKnownHosts() { return knownHosts; }
@@ -82,6 +79,7 @@ class ConnectionState : public ConnectionToken, public management::Manageable
Broker& getBroker() { return broker; }
Broker& broker;
+ std::vector<boost::shared_ptr<Queue> > exclusiveQueues;
//contained output tasks
sys::AggregateOutput outputTasks;
@@ -108,7 +106,6 @@ class ConnectionState : public ConnectionToken, public management::Manageable
uint16_t heartbeatmax;
std::string userId;
std::string url;
- bool userProxyAuth;
bool federationLink;
std::string federationPeerTag;
std::vector<Url> knownHosts;
diff --git a/cpp/src/qpid/broker/Consumer.h b/cpp/src/qpid/broker/Consumer.h
index 2af9b0c121..b96443fa7c 100644
--- a/cpp/src/qpid/broker/Consumer.h
+++ b/cpp/src/qpid/broker/Consumer.h
@@ -29,33 +29,22 @@ namespace qpid {
namespace broker {
class Queue;
-class QueueListeners;
class Consumer {
const bool acquires;
- // inListeners allows QueueListeners to efficiently track if this instance is registered
- // for notifications without having to search its containers
- bool inListeners;
- // the name is generated by broker and is unique within broker scope. It is not
- // provided or known by the remote Consumer.
- const std::string name;
- public:
- typedef boost::shared_ptr<Consumer> shared_ptr;
-
+ public:
+ typedef boost::shared_ptr<Consumer> shared_ptr;
+
framing::SequenceNumber position;
-
- Consumer(const std::string& _name, bool preAcquires = true)
- : acquires(preAcquires), inListeners(false), name(_name), position(0) {}
+
+ Consumer(bool preAcquires = true) : acquires(preAcquires) {}
bool preAcquires() const { return acquires; }
- const std::string& getName() const { return name; }
-
virtual bool deliver(QueuedMessage& msg) = 0;
virtual void notify() = 0;
virtual bool filter(boost::intrusive_ptr<Message>) { return true; }
virtual bool accept(boost::intrusive_ptr<Message>) { return true; }
virtual OwnershipToken* getSession() = 0;
virtual ~Consumer(){}
- friend class QueueListeners;
};
}}
diff --git a/cpp/src/qpid/broker/Daemon.cpp b/cpp/src/qpid/broker/Daemon.cpp
index c36538beb7..b30e5f18cb 100644
--- a/cpp/src/qpid/broker/Daemon.cpp
+++ b/cpp/src/qpid/broker/Daemon.cpp
@@ -93,10 +93,11 @@ void Daemon::fork()
catch (const exception& e) {
QPID_LOG(critical, "Unexpected error: " << e.what());
uint16_t port = 0;
- (void) write(pipeFds[1], &port, sizeof(uint16_t));
+ int unused_ret; //Supress warning about ignoring return value.
+ unused_ret = write(pipeFds[1], &port, sizeof(uint16_t));
std::string pipeFailureMessage = e.what();
- (void) write ( pipeFds[1],
+ unused_ret = write ( pipeFds[1],
pipeFailureMessage.c_str(),
strlen(pipeFailureMessage.c_str())
);
diff --git a/cpp/src/qpid/broker/DeliverableMessage.h b/cpp/src/qpid/broker/DeliverableMessage.h
index c8d21001eb..ce613e7b6e 100644
--- a/cpp/src/qpid/broker/DeliverableMessage.h
+++ b/cpp/src/qpid/broker/DeliverableMessage.h
@@ -29,7 +29,7 @@
namespace qpid {
namespace broker {
- class QPID_BROKER_CLASS_EXTERN DeliverableMessage : public Deliverable{
+ class DeliverableMessage : public Deliverable{
boost::intrusive_ptr<Message> msg;
public:
QPID_BROKER_EXTERN DeliverableMessage(const boost::intrusive_ptr<Message>& msg);
diff --git a/cpp/src/qpid/broker/DeliveryRecord.cpp b/cpp/src/qpid/broker/DeliveryRecord.cpp
index 0b8fe95d5e..9443eb6ea5 100644
--- a/cpp/src/qpid/broker/DeliveryRecord.cpp
+++ b/cpp/src/qpid/broker/DeliveryRecord.cpp
@@ -75,7 +75,7 @@ void DeliveryRecord::deliver(framing::FrameHandler& h, DeliveryId deliveryId, ui
{
id = deliveryId;
if (msg.payload->getRedelivered()){
- msg.payload->setRedelivered();
+ msg.payload->getProperties<framing::DeliveryProperties>()->setRedelivered(true);
}
msg.payload->adjustTtl();
@@ -131,20 +131,18 @@ void DeliveryRecord::committed() const{
void DeliveryRecord::reject()
{
- if (acquired && !ended) {
- Exchange::shared_ptr alternate = queue->getAlternateExchange();
- if (alternate) {
- DeliverableMessage delivery(msg.payload);
- alternate->routeWithAlternate(delivery);
- QPID_LOG(info, "Routed rejected message from " << queue->getName() << " to "
- << alternate->getName());
- } else {
- //just drop it
- QPID_LOG(info, "Dropping rejected message from " << queue->getName());
- }
- dequeue();
- setEnded();
+ Exchange::shared_ptr alternate = queue->getAlternateExchange();
+ if (alternate) {
+ DeliverableMessage delivery(msg.payload);
+ alternate->route(delivery, msg.payload->getRoutingKey(), msg.payload->getApplicationHeaders());
+ QPID_LOG(info, "Routed rejected message from " << queue->getName() << " to "
+ << alternate->getName());
+ } else {
+ //just drop it
+ QPID_LOG(info, "Dropping rejected message from " << queue->getName());
}
+
+ dequeue();
}
uint32_t DeliveryRecord::getCredit() const
@@ -153,7 +151,7 @@ uint32_t DeliveryRecord::getCredit() const
}
void DeliveryRecord::acquire(DeliveryIds& results) {
- if (queue->acquire(msg, tag)) {
+ if (queue->acquire(msg)) {
acquired = true;
results.push_back(id);
if (!acceptExpected) {
diff --git a/cpp/src/qpid/broker/DeliveryRecord.h b/cpp/src/qpid/broker/DeliveryRecord.h
index 5a331357be..d388ba94be 100644
--- a/cpp/src/qpid/broker/DeliveryRecord.h
+++ b/cpp/src/qpid/broker/DeliveryRecord.h
@@ -46,7 +46,7 @@ class DeliveryRecord
{
QueuedMessage msg;
mutable boost::shared_ptr<Queue> queue;
- std::string tag; // name of consumer
+ std::string tag;
DeliveryId id;
bool acquired : 1;
bool acceptExpected : 1;
@@ -90,7 +90,7 @@ class DeliveryRecord
bool isAcquired() const { return acquired; }
bool isComplete() const { return completed; }
- bool isRedundant() const { return ended && (!windowing || completed || cancelled); }
+ bool isRedundant() const { return ended && (!windowing || completed); }
bool isCancelled() const { return cancelled; }
bool isAccepted() const { return !acceptExpected; }
bool isEnded() const { return ended; }
diff --git a/cpp/src/qpid/broker/DirectExchange.cpp b/cpp/src/qpid/broker/DirectExchange.cpp
index 5591539853..5b8104c77c 100644
--- a/cpp/src/qpid/broker/DirectExchange.cpp
+++ b/cpp/src/qpid/broker/DirectExchange.cpp
@@ -94,7 +94,7 @@ bool DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, con
propagate = bk.fedBinding.delOrigin(queue->getName(), fedOrigin);
if (bk.fedBinding.countFedBindings(queue->getName()) == 0)
- unbind(queue, routingKey, args);
+ unbind(queue, routingKey, 0);
} else if (fedOp == fedOpReorigin) {
/** gather up all the keys that need rebinding in a local vector
@@ -124,24 +124,20 @@ bool DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, con
return true;
}
-bool DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args)
+bool DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* /*args*/)
{
- string fedOrigin(args ? args->getAsString(qpidFedOrigin) : "");
bool propagate = false;
- QPID_LOG(debug, "Unbinding key [" << routingKey << "] from queue " << queue->getName()
- << " on exchange " << getName() << " origin=" << fedOrigin << ")" );
+ QPID_LOG(debug, "Unbind key [" << routingKey << "] from queue " << queue->getName());
+
{
Mutex::ScopedLock l(lock);
BoundKey& bk = bindings[routingKey];
if (bk.queues.remove_if(MatchQueue(queue))) {
- propagate = bk.fedBinding.delOrigin(queue->getName(), fedOrigin);
+ propagate = bk.fedBinding.delOrigin();
if (mgmtExchange != 0) {
mgmtExchange->dec_bindingCount();
}
- if (bk.queues.empty()) {
- bindings.erase(routingKey);
- }
} else {
return false;
}
diff --git a/cpp/src/qpid/broker/DtxAck.cpp b/cpp/src/qpid/broker/DtxAck.cpp
index c558681d62..bca3f90bbe 100644
--- a/cpp/src/qpid/broker/DtxAck.cpp
+++ b/cpp/src/qpid/broker/DtxAck.cpp
@@ -32,10 +32,6 @@ DtxAck::DtxAck(const qpid::framing::SequenceSet& acked, DeliveryRecords& unacked
not1(bind2nd(mem_fun_ref(&DeliveryRecord::coveredBy), &acked)));
}
-DtxAck::DtxAck(DeliveryRecords& unacked) {
- pending = unacked;
-}
-
bool DtxAck::prepare(TransactionContext* ctxt) throw()
{
try{
diff --git a/cpp/src/qpid/broker/DtxAck.h b/cpp/src/qpid/broker/DtxAck.h
index 16c3ff8ba0..166147e58d 100644
--- a/cpp/src/qpid/broker/DtxAck.h
+++ b/cpp/src/qpid/broker/DtxAck.h
@@ -1,6 +1,3 @@
-#ifndef QPID_BROKER_DTXACK_H
-#define QPID_BROKER_DTXACK_H
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,6 +18,9 @@
* under the License.
*
*/
+#ifndef _DtxAck_
+#define _DtxAck_
+
#include <algorithm>
#include <functional>
#include <list>
@@ -29,21 +29,20 @@
#include "qpid/broker/TxOp.h"
namespace qpid {
-namespace broker {
-class DtxAck : public TxOp{
- DeliveryRecords pending;
+ namespace broker {
+ class DtxAck : public TxOp{
+ DeliveryRecords pending;
- public:
- DtxAck(const framing::SequenceSet& acked, DeliveryRecords& unacked);
- DtxAck(DeliveryRecords& unacked);
- virtual bool prepare(TransactionContext* ctxt) throw();
- virtual void commit() throw();
- virtual void rollback() throw();
- virtual ~DtxAck(){}
- virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); }
- const DeliveryRecords& getPending() const { return pending; }
-};
+ public:
+ DtxAck(const framing::SequenceSet& acked, DeliveryRecords& unacked);
+ virtual bool prepare(TransactionContext* ctxt) throw();
+ virtual void commit() throw();
+ virtual void rollback() throw();
+ virtual ~DtxAck(){}
+ virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); }
+ };
+ }
+}
-}} // qpid::broker
-#endif /*!QPID_BROKER_DTXACK_H*/
+#endif
diff --git a/cpp/src/qpid/broker/DtxBuffer.cpp b/cpp/src/qpid/broker/DtxBuffer.cpp
index 13177d3b72..f1b8169cf7 100644
--- a/cpp/src/qpid/broker/DtxBuffer.cpp
+++ b/cpp/src/qpid/broker/DtxBuffer.cpp
@@ -23,11 +23,8 @@
using namespace qpid::broker;
using qpid::sys::Mutex;
-DtxBuffer::DtxBuffer(
- const std::string& _xid,
- bool ended_, bool suspended_, bool failed_, bool expired_)
- : xid(_xid), ended(ended_), suspended(suspended_), failed(failed_), expired(expired_)
-{}
+DtxBuffer::DtxBuffer(const std::string& _xid)
+ : xid(_xid), ended(false), suspended(false), failed(false), expired(false) {}
DtxBuffer::~DtxBuffer() {}
@@ -37,7 +34,7 @@ void DtxBuffer::markEnded()
ended = true;
}
-bool DtxBuffer::isEnded() const
+bool DtxBuffer::isEnded()
{
Mutex::ScopedLock locker(lock);
return ended;
@@ -48,7 +45,7 @@ void DtxBuffer::setSuspended(bool isSuspended)
suspended = isSuspended;
}
-bool DtxBuffer::isSuspended() const
+bool DtxBuffer::isSuspended()
{
return suspended;
}
@@ -61,13 +58,13 @@ void DtxBuffer::fail()
ended = true;
}
-bool DtxBuffer::isRollbackOnly() const
+bool DtxBuffer::isRollbackOnly()
{
Mutex::ScopedLock locker(lock);
return failed;
}
-std::string DtxBuffer::getXid() const
+const std::string& DtxBuffer::getXid()
{
return xid;
}
@@ -79,13 +76,8 @@ void DtxBuffer::timedout()
fail();
}
-bool DtxBuffer::isExpired() const
+bool DtxBuffer::isExpired()
{
Mutex::ScopedLock locker(lock);
return expired;
}
-
-bool DtxBuffer::isFailed() const
-{
- return failed;
-}
diff --git a/cpp/src/qpid/broker/DtxBuffer.h b/cpp/src/qpid/broker/DtxBuffer.h
index cabd37647a..1511cb032f 100644
--- a/cpp/src/qpid/broker/DtxBuffer.h
+++ b/cpp/src/qpid/broker/DtxBuffer.h
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -26,34 +26,31 @@
#include "qpid/sys/Mutex.h"
namespace qpid {
-namespace broker {
-class DtxBuffer : public TxBuffer{
- mutable sys::Mutex lock;
- const std::string xid;
- bool ended;
- bool suspended;
- bool failed;
- bool expired;
+ namespace broker {
+ class DtxBuffer : public TxBuffer{
+ sys::Mutex lock;
+ const std::string xid;
+ bool ended;
+ bool suspended;
+ bool failed;
+ bool expired;
- public:
- typedef boost::shared_ptr<DtxBuffer> shared_ptr;
+ public:
+ typedef boost::shared_ptr<DtxBuffer> shared_ptr;
- QPID_BROKER_EXTERN DtxBuffer(
- const std::string& xid = "",
- bool ended=false, bool suspended=false, bool failed=false, bool expired=false);
- QPID_BROKER_EXTERN ~DtxBuffer();
- QPID_BROKER_EXTERN void markEnded();
- bool isEnded() const;
- void setSuspended(bool suspended);
- bool isSuspended() const;
- void fail();
- bool isRollbackOnly() const;
- void timedout();
- bool isExpired() const;
- bool isFailed() const;
- std::string getXid() const;
-};
-}
+ QPID_BROKER_EXTERN DtxBuffer(const std::string& xid = "");
+ QPID_BROKER_EXTERN ~DtxBuffer();
+ QPID_BROKER_EXTERN void markEnded();
+ bool isEnded();
+ void setSuspended(bool suspended);
+ bool isSuspended();
+ void fail();
+ bool isRollbackOnly();
+ void timedout();
+ bool isExpired();
+ const std::string& getXid();
+ };
+ }
}
diff --git a/cpp/src/qpid/broker/DtxManager.cpp b/cpp/src/qpid/broker/DtxManager.cpp
index febd547478..3caa41c3f4 100644
--- a/cpp/src/qpid/broker/DtxManager.cpp
+++ b/cpp/src/qpid/broker/DtxManager.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -34,7 +34,7 @@ using qpid::ptr_map_ptr;
using namespace qpid::broker;
using namespace qpid::framing;
-DtxManager::DtxManager(qpid::sys::Timer& t) : store(0), timer(&t) {}
+DtxManager::DtxManager(qpid::sys::Timer& t) : store(0), timer(t) {}
DtxManager::~DtxManager() {}
@@ -53,8 +53,8 @@ void DtxManager::recover(const std::string& xid, std::auto_ptr<TPCTransactionCon
createWork(xid)->recover(txn, ops);
}
-bool DtxManager::prepare(const std::string& xid)
-{
+bool DtxManager::prepare(const std::string& xid)
+{
QPID_LOG(debug, "preparing: " << xid);
try {
return getWork(xid)->prepare();
@@ -64,8 +64,8 @@ bool DtxManager::prepare(const std::string& xid)
}
}
-bool DtxManager::commit(const std::string& xid, bool onePhase)
-{
+bool DtxManager::commit(const std::string& xid, bool onePhase)
+{
QPID_LOG(debug, "committing: " << xid);
try {
bool result = getWork(xid)->commit(onePhase);
@@ -77,8 +77,8 @@ bool DtxManager::commit(const std::string& xid, bool onePhase)
}
}
-void DtxManager::rollback(const std::string& xid)
-{
+void DtxManager::rollback(const std::string& xid)
+{
QPID_LOG(debug, "rolling back: " << xid);
try {
getWork(xid)->rollback();
@@ -91,7 +91,7 @@ void DtxManager::rollback(const std::string& xid)
DtxWorkRecord* DtxManager::getWork(const std::string& xid)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
WorkMap::iterator i = work.find(xid);
if (i == work.end()) {
throw NotFoundException(QPID_MSG("Unrecognised xid " << xid));
@@ -99,14 +99,9 @@ DtxWorkRecord* DtxManager::getWork(const std::string& xid)
return ptr_map_ptr(i);
}
-bool DtxManager::exists(const std::string& xid) {
- Mutex::ScopedLock locker(lock);
- return work.find(xid) != work.end();
-}
-
void DtxManager::remove(const std::string& xid)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
WorkMap::iterator i = work.find(xid);
if (i == work.end()) {
throw NotFoundException(QPID_MSG("Unrecognised xid " << xid));
@@ -115,15 +110,14 @@ void DtxManager::remove(const std::string& xid)
}
}
-DtxWorkRecord* DtxManager::createWork(const std::string& xid)
+DtxWorkRecord* DtxManager::createWork(std::string xid)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
WorkMap::iterator i = work.find(xid);
if (i != work.end()) {
throw NotAllowedException(QPID_MSG("Xid " << xid << " is already known (use 'join' to add work to an existing xid)"));
} else {
- std::string ncxid = xid; // Work around const correctness problems in ptr_map.
- return ptr_map_ptr(work.insert(ncxid, new DtxWorkRecord(ncxid, store)).first);
+ return ptr_map_ptr(work.insert(xid, new DtxWorkRecord(xid, store)).first);
}
}
@@ -137,7 +131,7 @@ void DtxManager::setTimeout(const std::string& xid, uint32_t secs)
}
timeout = intrusive_ptr<DtxTimeout>(new DtxTimeout(secs, *this, xid));
record->setTimeout(timeout);
- timer->add(timeout);
+ timer.add(timeout);
}
uint32_t DtxManager::getTimeout(const std::string& xid)
@@ -148,7 +142,7 @@ uint32_t DtxManager::getTimeout(const std::string& xid)
void DtxManager::timedout(const std::string& xid)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
WorkMap::iterator i = work.find(xid);
if (i == work.end()) {
QPID_LOG(warning, "Transaction timeout failed: no record for xid");
@@ -159,7 +153,7 @@ void DtxManager::timedout(const std::string& xid)
}
}
-DtxManager::DtxCleanup::DtxCleanup(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid)
+DtxManager::DtxCleanup::DtxCleanup(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid)
: TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxCleanup"), mgr(_mgr), xid(_xid) {}
void DtxManager::DtxCleanup::fire()
diff --git a/cpp/src/qpid/broker/DtxManager.h b/cpp/src/qpid/broker/DtxManager.h
index 11895695a3..680b62eeb2 100644
--- a/cpp/src/qpid/broker/DtxManager.h
+++ b/cpp/src/qpid/broker/DtxManager.h
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -26,8 +26,8 @@
#include "qpid/broker/DtxWorkRecord.h"
#include "qpid/broker/TransactionalStore.h"
#include "qpid/framing/amqp_types.h"
+#include "qpid/sys/Timer.h"
#include "qpid/sys/Mutex.h"
-#include "qpid/ptr_map.h"
namespace qpid {
namespace broker {
@@ -39,21 +39,22 @@ class DtxManager{
{
DtxManager& mgr;
const std::string& xid;
-
- DtxCleanup(uint32_t timeout, DtxManager& mgr, const std::string& xid);
+
+ DtxCleanup(uint32_t timeout, DtxManager& mgr, const std::string& xid);
void fire();
};
WorkMap work;
TransactionalStore* store;
qpid::sys::Mutex lock;
- qpid::sys::Timer* timer;
+ qpid::sys::Timer& timer;
void remove(const std::string& xid);
- DtxWorkRecord* createWork(const std::string& xid);
+ DtxWorkRecord* getWork(const std::string& xid);
+ DtxWorkRecord* createWork(std::string xid);
public:
- DtxManager(sys::Timer&);
+ DtxManager(qpid::sys::Timer&);
~DtxManager();
void start(const std::string& xid, DtxBuffer::shared_ptr work);
void join(const std::string& xid, DtxBuffer::shared_ptr work);
@@ -65,15 +66,6 @@ public:
uint32_t getTimeout(const std::string& xid);
void timedout(const std::string& xid);
void setStore(TransactionalStore* store);
- void setTimer(sys::Timer& t) { timer = &t; }
-
- // Used by cluster for replication.
- template<class F> void each(F f) const {
- for (WorkMap::const_iterator i = work.begin(); i != work.end(); ++i)
- f(*ptr_map_ptr(i));
- }
- DtxWorkRecord* getWork(const std::string& xid);
- bool exists(const std::string& xid);
};
}
diff --git a/cpp/src/qpid/broker/DtxTimeout.cpp b/cpp/src/qpid/broker/DtxTimeout.cpp
index 58700846ef..c4c52ec40a 100644
--- a/cpp/src/qpid/broker/DtxTimeout.cpp
+++ b/cpp/src/qpid/broker/DtxTimeout.cpp
@@ -25,7 +25,7 @@
using namespace qpid::broker;
DtxTimeout::DtxTimeout(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid)
- : TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxTimeout-"+_xid), timeout(_timeout), mgr(_mgr), xid(_xid)
+ : TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxTimeout"), timeout(_timeout), mgr(_mgr), xid(_xid)
{
}
diff --git a/cpp/src/qpid/broker/DtxTimeout.h b/cpp/src/qpid/broker/DtxTimeout.h
index 1fcb4cee2a..680a210e4f 100644
--- a/cpp/src/qpid/broker/DtxTimeout.h
+++ b/cpp/src/qpid/broker/DtxTimeout.h
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -29,9 +29,7 @@ namespace broker {
class DtxManager;
-struct DtxTimeoutException : public Exception {
- DtxTimeoutException(const std::string& msg=std::string()) : Exception(msg) {}
-};
+struct DtxTimeoutException : public Exception {};
struct DtxTimeout : public sys::TimerTask
{
@@ -39,7 +37,7 @@ struct DtxTimeout : public sys::TimerTask
DtxManager& mgr;
const std::string xid;
- DtxTimeout(uint32_t timeout, DtxManager& mgr, const std::string& xid);
+ DtxTimeout(uint32_t timeout, DtxManager& mgr, const std::string& xid);
void fire();
};
diff --git a/cpp/src/qpid/broker/DtxWorkRecord.cpp b/cpp/src/qpid/broker/DtxWorkRecord.cpp
index a413fe418d..9f33e698db 100644
--- a/cpp/src/qpid/broker/DtxWorkRecord.cpp
+++ b/cpp/src/qpid/broker/DtxWorkRecord.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -28,19 +28,19 @@ using qpid::sys::Mutex;
using namespace qpid::broker;
using namespace qpid::framing;
-DtxWorkRecord::DtxWorkRecord(const std::string& _xid, TransactionalStore* const _store) :
+DtxWorkRecord::DtxWorkRecord(const std::string& _xid, TransactionalStore* const _store) :
xid(_xid), store(_store), completed(false), rolledback(false), prepared(false), expired(false) {}
-DtxWorkRecord::~DtxWorkRecord()
+DtxWorkRecord::~DtxWorkRecord()
{
- if (timeout.get()) {
+ if (timeout.get()) {
timeout->cancel();
}
}
bool DtxWorkRecord::prepare()
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
if (check()) {
txn = store->begin(xid);
if (prepare(txn.get())) {
@@ -68,7 +68,7 @@ bool DtxWorkRecord::prepare(TransactionContext* _txn)
bool DtxWorkRecord::commit(bool onePhase)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
if (check()) {
if (prepared) {
//already prepared i.e. 2pc
@@ -78,13 +78,13 @@ bool DtxWorkRecord::commit(bool onePhase)
store->commit(*txn);
txn.reset();
-
+
std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::commit));
return true;
} else {
//1pc commit optimisation, don't need a 2pc transaction context:
if (!onePhase) {
- throw IllegalStateException(QPID_MSG("Branch with xid " << xid << " has not been prepared, one-phase option required!"));
+ throw IllegalStateException(QPID_MSG("Branch with xid " << xid << " has not been prepared, one-phase option required!"));
}
std::auto_ptr<TransactionContext> localtxn = store->begin();
if (prepare(localtxn.get())) {
@@ -107,16 +107,16 @@ bool DtxWorkRecord::commit(bool onePhase)
void DtxWorkRecord::rollback()
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
check();
abort();
}
void DtxWorkRecord::add(DtxBuffer::shared_ptr ops)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
if (expired) {
- throw DtxTimeoutException(QPID_MSG("Branch with xid " << xid << " has timed out."));
+ throw DtxTimeoutException();
}
if (completed) {
throw CommandInvalidException(QPID_MSG("Branch with xid " << xid << " has been completed!"));
@@ -163,7 +163,7 @@ void DtxWorkRecord::recover(std::auto_ptr<TPCTransactionContext> _txn, DtxBuffer
void DtxWorkRecord::timedout()
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
expired = true;
rolledback = true;
if (!completed) {
@@ -175,17 +175,3 @@ void DtxWorkRecord::timedout()
}
abort();
}
-
-size_t DtxWorkRecord::indexOf(const DtxBuffer::shared_ptr& buf) {
- Work::iterator i = std::find(work.begin(), work.end(), buf);
- if (i == work.end()) throw NotFoundException(
- QPID_MSG("Can't find DTX buffer for xid: " << buf->getXid()));
- return i - work.begin();
-}
-
-DtxBuffer::shared_ptr DtxWorkRecord::operator[](size_t i) const {
- if (i > work.size())
- throw NotFoundException(
- QPID_MSG("Can't find DTX buffer " << i << " for xid: " << xid));
- return work[i];
-}
diff --git a/cpp/src/qpid/broker/DtxWorkRecord.h b/cpp/src/qpid/broker/DtxWorkRecord.h
index 331e42fefd..aec2d2aed4 100644
--- a/cpp/src/qpid/broker/DtxWorkRecord.h
+++ b/cpp/src/qpid/broker/DtxWorkRecord.h
@@ -73,19 +73,9 @@ public:
void timedout();
void setTimeout(boost::intrusive_ptr<DtxTimeout> t) { timeout = t; }
boost::intrusive_ptr<DtxTimeout> getTimeout() { return timeout; }
- std::string getXid() const { return xid; }
- bool isCompleted() const { return completed; }
- bool isRolledback() const { return rolledback; }
- bool isPrepared() const { return prepared; }
- bool isExpired() const { return expired; }
-
- // Used by cluster update;
- size_t size() const { return work.size(); }
- DtxBuffer::shared_ptr operator[](size_t i) const;
- uint32_t getTimeout() const { return timeout? timeout->timeout : 0; }
- size_t indexOf(const DtxBuffer::shared_ptr&);
};
-}} // qpid::broker
+}
+}
#endif
diff --git a/cpp/src/qpid/broker/Exchange.cpp b/cpp/src/qpid/broker/Exchange.cpp
index d68845062d..d143471559 100644
--- a/cpp/src/qpid/broker/Exchange.cpp
+++ b/cpp/src/qpid/broker/Exchange.cpp
@@ -19,18 +19,16 @@
*
*/
-#include "qpid/broker/Broker.h"
-#include "qpid/broker/DeliverableMessage.h"
#include "qpid/broker/Exchange.h"
#include "qpid/broker/ExchangeRegistry.h"
#include "qpid/broker/FedOps.h"
+#include "qpid/broker/Broker.h"
+#include "qpid/management/ManagementAgent.h"
#include "qpid/broker/Queue.h"
+#include "qpid/log/Statement.h"
#include "qpid/framing/MessageProperties.h"
#include "qpid/framing/reply_exceptions.h"
-#include "qpid/log/Statement.h"
-#include "qpid/management/ManagementAgent.h"
-#include "qpid/sys/ExceptionHolder.h"
-#include <stdexcept>
+#include "qpid/broker/DeliverableMessage.h"
using namespace qpid::broker;
using namespace qpid::framing;
@@ -58,7 +56,7 @@ Exchange::PreRoute::PreRoute(Deliverable& msg, Exchange* _p):parent(_p) {
if (parent->sequence){
parent->sequenceNo++;
- msg.getMessage().insertCustomProperty(qpidMsgSequence,parent->sequenceNo);
+ msg.getMessage().getProperties<MessageProperties>()->getApplicationHeaders().setInt64(qpidMsgSequence,parent->sequenceNo);
}
if (parent->ive) {
parent->lastMsg = &( msg.getMessage());
@@ -72,36 +70,6 @@ Exchange::PreRoute::~PreRoute(){
}
}
-namespace {
-/** Store information about an exception to be thrown later.
- * If multiple exceptions are stored, save the first of the "most severe"
- * exceptions, SESSION is les sever than CONNECTION etc.
- */
-class ExInfo {
- public:
- enum Type { NONE, SESSION, CONNECTION, OTHER };
-
- ExInfo(string exchange) : type(NONE), exchange(exchange) {}
- void store(Type type_, const qpid::sys::ExceptionHolder& exception_, const boost::shared_ptr<Queue>& queue) {
- QPID_LOG(warning, "Exchange " << exchange << " cannot deliver to queue "
- << queue->getName() << ": " << exception_.what());
- if (type < type_) { // Replace less severe exception
- type = type_;
- exception = exception_;
- }
- }
-
- void raise() {
- exception.raise();
- }
-
- private:
- Type type;
- string exchange;
- qpid::sys::ExceptionHolder exception;
-};
-}
-
void Exchange::doRoute(Deliverable& msg, ConstBindingList b)
{
int count = 0;
@@ -112,25 +80,11 @@ void Exchange::doRoute(Deliverable& msg, ConstBindingList b)
msg.getMessage().blockContentRelease();
}
-
- ExInfo error(getName()); // Save exception to throw at the end.
for(std::vector<Binding::shared_ptr>::const_iterator i = b->begin(); i != b->end(); i++, count++) {
- try {
- msg.deliverTo((*i)->queue);
- if ((*i)->mgmtBinding != 0)
- (*i)->mgmtBinding->inc_msgMatched();
- }
- catch (const SessionException& e) {
- error.store(ExInfo::SESSION, framing::createSessionException(e.code, e.what()),(*i)->queue);
- }
- catch (const ConnectionException& e) {
- error.store(ExInfo::CONNECTION, framing::createConnectionException(e.code, e.what()), (*i)->queue);
- }
- catch (const std::exception& e) {
- error.store(ExInfo::OTHER, qpid::sys::ExceptionHolder(new Exception(e.what())), (*i)->queue);
- }
+ msg.deliverTo((*i)->queue);
+ if ((*i)->mgmtBinding != 0)
+ (*i)->mgmtBinding->inc_msgMatched();
}
- error.raise();
}
if (mgmtExchange != 0)
@@ -161,7 +115,7 @@ void Exchange::routeIVE(){
Exchange::Exchange (const string& _name, Manageable* parent, Broker* b) :
name(_name), durable(false), persistenceId(0), sequence(false),
- sequenceNo(0), ive(false), mgmtExchange(0), broker(b), destroyed(false)
+ sequenceNo(0), ive(false), mgmtExchange(0), broker(b)
{
if (parent != 0 && broker != 0)
{
@@ -179,7 +133,7 @@ Exchange::Exchange (const string& _name, Manageable* parent, Broker* b) :
Exchange::Exchange(const string& _name, bool _durable, const qpid::framing::FieldTable& _args,
Manageable* parent, Broker* b)
: name(_name), durable(_durable), alternateUsers(0), persistenceId(0),
- args(_args), sequence(false), sequenceNo(0), ive(false), mgmtExchange(0), broker(b), destroyed(false)
+ args(_args), sequence(false), sequenceNo(0), ive(false), mgmtExchange(0), broker(b)
{
if (parent != 0 && broker != 0)
{
@@ -201,11 +155,7 @@ Exchange::Exchange(const string& _name, bool _durable, const qpid::framing::Fiel
}
ive = _args.get(qpidIVE);
- if (ive) {
- if (broker && broker->isInCluster())
- throw framing::NotImplementedException("Cannot use Initial Value Exchanges in a cluster");
- QPID_LOG(debug, "Configured exchange " << _name << " with Initial Value");
- }
+ if (ive) QPID_LOG(debug, "Configured exchange " << _name << " with Initial Value");
}
Exchange::~Exchange ()
@@ -390,14 +340,5 @@ bool Exchange::MatchQueue::operator()(Exchange::Binding::shared_ptr b)
}
void Exchange::setProperties(const boost::intrusive_ptr<Message>& msg) {
- msg->setExchange(getName());
-}
-
-bool Exchange::routeWithAlternate(Deliverable& msg)
-{
- route(msg, msg.getMessage().getRoutingKey(), msg.getMessage().getApplicationHeaders());
- if (!msg.delivered && alternate) {
- alternate->route(msg, msg.getMessage().getRoutingKey(), msg.getMessage().getApplicationHeaders());
- }
- return msg.delivered;
+ msg->getProperties<DeliveryProperties>()->setExchange(getName());
}
diff --git a/cpp/src/qpid/broker/Exchange.h b/cpp/src/qpid/broker/Exchange.h
index b12af9a1dd..3c8b5ca2cd 100644
--- a/cpp/src/qpid/broker/Exchange.h
+++ b/cpp/src/qpid/broker/Exchange.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -39,7 +39,7 @@ namespace broker {
class Broker;
class ExchangeRegistry;
-class QPID_BROKER_CLASS_EXTERN Exchange : public PersistableExchange, public management::Manageable {
+class Exchange : public PersistableExchange, public management::Manageable {
public:
struct Binding : public management::Manageable {
typedef boost::shared_ptr<Binding> shared_ptr;
@@ -82,15 +82,15 @@ protected:
private:
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();
-
+
struct MatchQueue {
- const boost::shared_ptr<Queue> queue;
+ const boost::shared_ptr<Queue> queue;
MatchQueue(boost::shared_ptr<Queue> q);
bool operator()(Exchange::Binding::shared_ptr b);
};
@@ -133,15 +133,15 @@ protected:
/** Returns true if propagation is needed. */
bool delOrigin(const std::string& queueName, const std::string& origin){
- if (origin.empty()) { // no remote == local binding
- if (localBindings > 0)
- localBindings--;
- return localBindings == 0;
- }
- size_t match = fedBindings[queueName].erase(origin);
- if (fedBindings[queueName].empty())
- fedBindings.erase(queueName);
- return match != 0;
+ fedBindings[queueName].erase(origin);
+ return true;
+ }
+
+ /** Returns true if propagation is needed. */
+ bool delOrigin() {
+ if (localBindings > 0)
+ localBindings--;
+ return localBindings == 0;
}
uint32_t count() {
@@ -149,11 +149,7 @@ protected:
}
uint32_t countFedBindings(const std::string& queueName) {
- // don't use '[]' - it may increase size of fedBindings!
- std::map<std::string, originSet>::iterator i;
- if ((i = fedBindings.find(queueName)) != fedBindings.end())
- return i->second.size();
- return 0;
+ return fedBindings[queueName].size();
}
};
@@ -166,7 +162,7 @@ public:
Broker* broker = 0);
QPID_BROKER_EXTERN Exchange(const std::string& _name, bool _durable, const qpid::framing::FieldTable& _args,
management::Manageable* parent = 0, Broker* broker = 0);
- QPID_BROKER_INLINE_EXTERN virtual ~Exchange();
+ QPID_BROKER_EXTERN virtual ~Exchange();
const std::string& getName() const { return name; }
bool isDurable() { return durable; }
@@ -195,7 +191,7 @@ public:
virtual bool isBound(boost::shared_ptr<Queue> queue, const std::string* const routingKey, const qpid::framing::FieldTable* const args) = 0;
QPID_BROKER_EXTERN virtual void setProperties(const boost::intrusive_ptr<Message>&);
virtual void route(Deliverable& msg, const std::string& routingKey, const qpid::framing::FieldTable* args) = 0;
-
+
//PersistableExchange:
QPID_BROKER_EXTERN void setPersistenceId(uint64_t id) const;
uint64_t getPersistenceId() const { return persistenceId; }
@@ -226,20 +222,14 @@ public:
*/
void recoveryComplete(ExchangeRegistry& exchanges);
- bool routeWithAlternate(Deliverable& message);
-
- void destroy() { destroyed = true; }
- bool isDestroyed() const { return destroyed; }
-
protected:
qpid::sys::Mutex bridgeLock;
std::vector<DynamicBridge*> bridgeVector;
Broker* broker;
- bool destroyed;
QPID_BROKER_EXTERN virtual void handleHelloRequest();
void propagateFedOp(const std::string& routingKey, const std::string& tags,
- const std::string& op, const std::string& origin,
+ const std::string& op, const std::string& origin,
qpid::framing::FieldTable* extra_args=0);
};
diff --git a/cpp/src/qpid/broker/ExchangeRegistry.cpp b/cpp/src/qpid/broker/ExchangeRegistry.cpp
index 1c8d26c4f7..99b121cbce 100644
--- a/cpp/src/qpid/broker/ExchangeRegistry.cpp
+++ b/cpp/src/qpid/broker/ExchangeRegistry.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -39,7 +39,7 @@ pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, c
return declare(name, type, false, FieldTable());
}
-pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, const string& type,
+pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, const string& type,
bool durable, const FieldTable& args){
RWlock::ScopedWlock locker(lock);
ExchangeMap::iterator i = exchanges.find(name);
@@ -61,7 +61,7 @@ pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, c
}else{
FunctionMap::iterator i = factory.find(type);
if (i == factory.end()) {
- throw UnknownExchangeTypeException();
+ throw UnknownExchangeTypeException();
} else {
exchange = i->second(name, durable, args, parent, broker);
}
@@ -82,7 +82,6 @@ void ExchangeRegistry::destroy(const string& name){
RWlock::ScopedWlock locker(lock);
ExchangeMap::iterator i = exchanges.find(name);
if (i != exchanges.end()) {
- i->second->destroy();
exchanges.erase(i);
}
}
@@ -105,7 +104,7 @@ void ExchangeRegistry::registerType(const std::string& type, FactoryFunction f)
}
-namespace
+namespace
{
const std::string empty;
}
diff --git a/cpp/src/qpid/broker/ExpiryPolicy.cpp b/cpp/src/qpid/broker/ExpiryPolicy.cpp
index 62cb3fc116..64a12d918a 100644
--- a/cpp/src/qpid/broker/ExpiryPolicy.cpp
+++ b/cpp/src/qpid/broker/ExpiryPolicy.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -27,12 +27,12 @@ namespace broker {
ExpiryPolicy::~ExpiryPolicy() {}
+void ExpiryPolicy::willExpire(Message&) {}
+
bool ExpiryPolicy::hasExpired(Message& m) {
return m.getExpiration() < sys::AbsTime::now();
}
-sys::AbsTime ExpiryPolicy::getCurrentTime() {
- return sys::AbsTime::now();
-}
+void ExpiryPolicy::forget(Message&) {}
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/ExpiryPolicy.h b/cpp/src/qpid/broker/ExpiryPolicy.h
index 2caf00ce00..40e793bf2c 100644
--- a/cpp/src/qpid/broker/ExpiryPolicy.h
+++ b/cpp/src/qpid/broker/ExpiryPolicy.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -26,11 +26,6 @@
#include "qpid/broker/BrokerImportExport.h"
namespace qpid {
-
-namespace sys {
-class AbsTime;
-}
-
namespace broker {
class Message;
@@ -38,12 +33,13 @@ class Message;
/**
* Default expiry policy.
*/
-class QPID_BROKER_CLASS_EXTERN ExpiryPolicy : public RefCounted
+class ExpiryPolicy : public RefCounted
{
public:
QPID_BROKER_EXTERN virtual ~ExpiryPolicy();
+ QPID_BROKER_EXTERN virtual void willExpire(Message&);
QPID_BROKER_EXTERN virtual bool hasExpired(Message&);
- QPID_BROKER_EXTERN virtual qpid::sys::AbsTime getCurrentTime();
+ QPID_BROKER_EXTERN virtual void forget(Message&);
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/Fairshare.cpp b/cpp/src/qpid/broker/Fairshare.cpp
index 313aa746f1..e6bbf86691 100644
--- a/cpp/src/qpid/broker/Fairshare.cpp
+++ b/cpp/src/qpid/broker/Fairshare.cpp
@@ -24,7 +24,6 @@
#include "qpid/log/Statement.h"
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/assign/list_of.hpp>
namespace qpid {
namespace broker {
@@ -105,80 +104,51 @@ bool Fairshare::setState(Messages& m, uint priority, uint count)
return fairshare && fairshare->setState(priority, count);
}
-int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::vector<std::string>& keys)
+int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::string& key)
{
- qpid::framing::FieldTable::ValuePtr v;
- std::vector<std::string>::const_iterator i = keys.begin();
- while (!v && i != keys.end()) {
- v = settings.get(*i++);
- }
-
+ qpid::framing::FieldTable::ValuePtr v = settings.get(key);
if (!v) {
return 0;
} else if (v->convertsTo<int>()) {
return v->get<int>();
} else if (v->convertsTo<std::string>()){
std::string s = v->get<std::string>();
- try {
- return boost::lexical_cast<int>(s);
+ try {
+ return boost::lexical_cast<int>(s);
} catch(const boost::bad_lexical_cast&) {
- QPID_LOG(warning, "Ignoring invalid integer value for " << *i << ": " << s);
+ QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << s);
return 0;
}
} else {
- QPID_LOG(warning, "Ignoring invalid integer value for " << *i << ": " << *v);
+ QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << *v);
return 0;
}
}
-int getIntegerSettingForKey(const qpid::framing::FieldTable& settings, const std::string& key)
-{
- return getIntegerSetting(settings, boost::assign::list_of<std::string>(key));
-}
-
-int getSetting(const qpid::framing::FieldTable& settings, const std::vector<std::string>& keys, int minvalue, int maxvalue)
-{
- return std::max(minvalue,std::min(getIntegerSetting(settings, keys), maxvalue));
-}
-
-std::auto_ptr<Fairshare> getFairshareForKey(const qpid::framing::FieldTable& settings, uint levels, const std::string& key)
-{
- uint defaultLimit = getIntegerSettingForKey(settings, key);
- std::auto_ptr<Fairshare> fairshare(new Fairshare(levels, defaultLimit));
- for (uint i = 0; i < levels; i++) {
- std::string levelKey = (boost::format("%1%-%2%") % key % i).str();
- if(settings.isSet(levelKey)) {
- fairshare->setLimit(i, getIntegerSettingForKey(settings, levelKey));
- }
- }
- if (!fairshare->isNull()) {
- return fairshare;
- } else {
- return std::auto_ptr<Fairshare>();
- }
-}
-
-std::auto_ptr<Fairshare> getFairshare(const qpid::framing::FieldTable& settings,
- uint levels,
- const std::vector<std::string>& keys)
+int getSetting(const qpid::framing::FieldTable& settings, const std::string& key, int minvalue, int maxvalue)
{
- std::auto_ptr<Fairshare> fairshare;
- for (std::vector<std::string>::const_iterator i = keys.begin(); i != keys.end() && !fairshare.get(); ++i) {
- fairshare = getFairshareForKey(settings, levels, *i);
- }
- return fairshare;
+ return std::max(minvalue,std::min(getIntegerSetting(settings, key), maxvalue));
}
std::auto_ptr<Messages> Fairshare::create(const qpid::framing::FieldTable& settings)
{
- using boost::assign::list_of;
std::auto_ptr<Messages> result;
- size_t levels = getSetting(settings, list_of<std::string>("qpid.priorities")("x-qpid-priorities"), 0, 100);
+ size_t levels = getSetting(settings, "x-qpid-priorities", 1, 100);
if (levels) {
- std::auto_ptr<Fairshare> fairshare =
- getFairshare(settings, levels, list_of<std::string>("qpid.fairshare")("x-qpid-fairshare"));
- if (fairshare.get()) result = fairshare;
- else result = std::auto_ptr<Messages>(new PriorityQueue(levels));
+ uint defaultLimit = getIntegerSetting(settings, "x-qpid-fairshare");
+ std::auto_ptr<Fairshare> fairshare(new Fairshare(levels, defaultLimit));
+ for (uint i = 0; i < levels; i++) {
+ std::string key = (boost::format("x-qpid-fairshare-%1%") % i).str();
+ if(settings.isSet(key)) {
+ fairshare->setLimit(i, getIntegerSetting(settings, key));
+ }
+ }
+
+ if (fairshare->isNull()) {
+ result = std::auto_ptr<Messages>(new PriorityQueue(levels));
+ } else {
+ result = fairshare;
+ }
}
return result;
}
diff --git a/cpp/src/qpid/broker/Fairshare.h b/cpp/src/qpid/broker/Fairshare.h
index 1b25721e0c..6c4b87f857 100644
--- a/cpp/src/qpid/broker/Fairshare.h
+++ b/cpp/src/qpid/broker/Fairshare.h
@@ -41,18 +41,18 @@ class Fairshare : public PriorityQueue
bool getState(uint& priority, uint& count) const;
bool setState(uint priority, uint count);
void setLimit(size_t level, uint limit);
- bool isNull();
static std::auto_ptr<Messages> create(const qpid::framing::FieldTable& settings);
static bool getState(const Messages&, uint& priority, uint& count);
static bool setState(Messages&, uint priority, uint count);
private:
std::vector<uint> limits;
-
+
uint priority;
uint count;
-
+
uint currentLevel();
uint nextLevel();
+ bool isNull();
bool limitReached();
bool findFrontLevel(uint& p, PriorityLevels&);
};
diff --git a/cpp/src/qpid/broker/FanOutExchange.cpp b/cpp/src/qpid/broker/FanOutExchange.cpp
index 5879fa0892..ac2c914a97 100644
--- a/cpp/src/qpid/broker/FanOutExchange.cpp
+++ b/cpp/src/qpid/broker/FanOutExchange.cpp
@@ -18,7 +18,6 @@
* under the License.
*
*/
-#include "qpid/log/Statement.h"
#include "qpid/broker/FanOutExchange.h"
#include "qpid/broker/FedOps.h"
#include <algorithm>
@@ -66,7 +65,7 @@ bool FanOutExchange::bind(Queue::shared_ptr queue, const string& /*key*/, const
} else if (fedOp == fedOpUnbind) {
propagate = fedBinding.delOrigin(queue->getName(), fedOrigin);
if (fedBinding.countFedBindings(queue->getName()) == 0)
- unbind(queue, "", args);
+ unbind(queue, "", 0);
} else if (fedOp == fedOpReorigin) {
if (fedBinding.hasLocal()) {
propagateFedOp(string(), string(), fedOpBind, string());
@@ -79,16 +78,12 @@ bool FanOutExchange::bind(Queue::shared_ptr queue, const string& /*key*/, const
return true;
}
-bool FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*key*/, const FieldTable* args)
+bool FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*key*/, const FieldTable* /*args*/)
{
- string fedOrigin(args ? args->getAsString(qpidFedOrigin) : "");
bool propagate = false;
- QPID_LOG(debug, "Unbinding queue " << queue->getName()
- << " from exchange " << getName() << " origin=" << fedOrigin << ")" );
-
if (bindings.remove_if(MatchQueue(queue))) {
- propagate = fedBinding.delOrigin(queue->getName(), fedOrigin);
+ propagate = fedBinding.delOrigin();
if (mgmtExchange != 0) {
mgmtExchange->dec_bindingCount();
}
diff --git a/cpp/src/qpid/broker/FifoDistributor.cpp b/cpp/src/qpid/broker/FifoDistributor.cpp
deleted file mode 100644
index cdb32d8c8c..0000000000
--- a/cpp/src/qpid/broker/FifoDistributor.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-
-#include "qpid/broker/Queue.h"
-#include "qpid/broker/FifoDistributor.h"
-
-using namespace qpid::broker;
-
-FifoDistributor::FifoDistributor(Messages& container)
- : messages(container) {}
-
-bool FifoDistributor::nextConsumableMessage( Consumer::shared_ptr&, QueuedMessage& next )
-{
- if (!messages.empty()) {
- next = messages.front(); // by default, consume oldest msg
- return true;
- }
- return false;
-}
-
-bool FifoDistributor::allocate(const std::string&, const QueuedMessage& )
-{
- // by default, all messages present on the queue may be allocated as they have yet to
- // be acquired.
- return true;
-}
-
-bool FifoDistributor::nextBrowsableMessage( Consumer::shared_ptr& c, QueuedMessage& next )
-{
- if (!messages.empty() && messages.next(c->position, next))
- return true;
- return false;
-}
-
-void FifoDistributor::query(qpid::types::Variant::Map&) const
-{
- // nothing to see here....
-}
-
diff --git a/cpp/src/qpid/broker/HeadersExchange.cpp b/cpp/src/qpid/broker/HeadersExchange.cpp
index 4bda70d313..82ac5911ee 100644
--- a/cpp/src/qpid/broker/HeadersExchange.cpp
+++ b/cpp/src/qpid/broker/HeadersExchange.cpp
@@ -112,14 +112,9 @@ bool HeadersExchange::bind(Queue::shared_ptr queue, const string& bindingKey, co
{
Mutex::ScopedLock l(lock);
- //NOTE: do not include the fed op/tags/origin in the
- //arguments as when x-match is 'all' these would prevent
- //matching (they are internally added properties
- //controlling binding propagation but not relevant to
- //actual routing)
- Binding::shared_ptr binding (new Binding (bindingKey, queue, this, extra_args));
+ Binding::shared_ptr binding (new Binding (bindingKey, queue, this, *args));
BoundKey bk(binding);
- if (bindings.add_unless(bk, MatchArgs(queue, &extra_args))) {
+ if (bindings.add_unless(bk, MatchArgs(queue, args))) {
binding->startManagement();
propagate = bk.fedBinding.addOrigin(queue->getName(), fedOrigin);
if (mgmtExchange != 0) {
@@ -163,13 +158,12 @@ bool HeadersExchange::bind(Queue::shared_ptr queue, const string& bindingKey, co
return true;
}
-bool HeadersExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable *args){
+bool HeadersExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable*){
bool propagate = false;
- string fedOrigin(args ? args->getAsString(qpidFedOrigin) : "");
{
Mutex::ScopedLock l(lock);
- FedUnbindModifier modifier(queue->getName(), fedOrigin);
+ FedUnbindModifier modifier;
MatchKey match_key(queue, bindingKey);
bindings.modify_if(match_key, modifier);
propagate = modifier.shouldPropagate;
@@ -336,7 +330,11 @@ HeadersExchange::FedUnbindModifier::FedUnbindModifier() : shouldUnbind(false), s
bool HeadersExchange::FedUnbindModifier::operator()(BoundKey & bk)
{
- shouldPropagate = bk.fedBinding.delOrigin(queueName, fedOrigin);
+ if ("" == fedOrigin) {
+ shouldPropagate = bk.fedBinding.delOrigin();
+ } else {
+ shouldPropagate = bk.fedBinding.delOrigin(queueName, fedOrigin);
+ }
if (bk.fedBinding.countFedBindings(queueName) == 0)
{
shouldUnbind = true;
diff --git a/cpp/src/qpid/broker/IncompleteMessageList.cpp b/cpp/src/qpid/broker/IncompleteMessageList.cpp
new file mode 100644
index 0000000000..34d92fa752
--- /dev/null
+++ b/cpp/src/qpid/broker/IncompleteMessageList.cpp
@@ -0,0 +1,85 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/broker/IncompleteMessageList.h"
+
+namespace qpid {
+namespace broker {
+
+IncompleteMessageList::IncompleteMessageList() :
+ callback(boost::bind(&IncompleteMessageList::enqueueComplete, this, _1))
+{}
+
+IncompleteMessageList::~IncompleteMessageList()
+{
+ // No lock here. We are relying on Messsag::reset*CompleteCallback
+ // to ensure no callbacks are in progress before they return.
+ for (Messages::iterator i = incomplete.begin(); i != incomplete.end(); ++i) {
+ (*i)->resetEnqueueCompleteCallback();
+ (*i)->resetDequeueCompleteCallback();
+ }
+}
+
+void IncompleteMessageList::add(boost::intrusive_ptr<Message> msg)
+{
+ sys::Mutex::ScopedLock l(lock);
+ msg->setEnqueueCompleteCallback(callback);
+ incomplete.push_back(msg);
+}
+
+void IncompleteMessageList::enqueueComplete(const boost::intrusive_ptr<Message>& ) {
+ sys::Mutex::ScopedLock l(lock);
+ lock.notify();
+}
+
+void IncompleteMessageList::process(const CompletionListener& listen, bool sync)
+{
+ sys::Mutex::ScopedLock l(lock);
+ while (!incomplete.empty()) {
+ boost::intrusive_ptr<Message>& msg = incomplete.front();
+ if (!msg->isEnqueueComplete()) {
+ if (sync){
+ {
+ sys::Mutex::ScopedUnlock u(lock);
+ msg->flush(); // Can re-enter IncompleteMessageList::enqueueComplete
+ }
+ while (!msg->isEnqueueComplete())
+ lock.wait();
+ } else {
+ //leave the message as incomplete for now
+ return;
+ }
+ }
+ listen(msg);
+ incomplete.pop_front();
+ }
+}
+
+void IncompleteMessageList::each(const CompletionListener& listen) {
+ Messages snapshot;
+ {
+ sys::Mutex::ScopedLock l(lock);
+ snapshot = incomplete;
+ }
+ std::for_each(incomplete.begin(), incomplete.end(), listen);
+}
+
+}}
diff --git a/cpp/src/qpid/broker/FifoDistributor.h b/cpp/src/qpid/broker/IncompleteMessageList.h
index 245537ed12..a4debd1233 100644
--- a/cpp/src/qpid/broker/FifoDistributor.h
+++ b/cpp/src/qpid/broker/IncompleteMessageList.h
@@ -1,6 +1,3 @@
-#ifndef _broker_FifoDistributor_h
-#define _broker_FifoDistributor_h
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -10,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,38 +18,41 @@
* under the License.
*
*/
+#ifndef _IncompleteMessageList_
+#define _IncompleteMessageList_
-/** Simple MessageDistributor for FIFO Queues - the HEAD message is always the next
- * available message for consumption.
- */
-
-#include "qpid/broker/MessageDistributor.h"
+#include "qpid/broker/BrokerImportExport.h"
+#include "qpid/sys/Monitor.h"
+#include "qpid/broker/Message.h"
+#include <boost/intrusive_ptr.hpp>
+#include <boost/function.hpp>
+#include <list>
namespace qpid {
namespace broker {
-class Messages;
-
-class FifoDistributor : public MessageDistributor
+class IncompleteMessageList
{
- public:
- FifoDistributor(Messages& container);
+ typedef std::list< boost::intrusive_ptr<Message> > Messages;
- /** Locking Note: all methods assume the caller is holding the Queue::messageLock
- * during the method call.
- */
+ void enqueueComplete(const boost::intrusive_ptr<Message>&);
- /** MessageDistributor interface */
+ sys::Monitor lock;
+ Messages incomplete;
+ Message::MessageCallback callback;
- bool nextConsumableMessage( Consumer::shared_ptr& consumer, QueuedMessage& next );
- bool allocate(const std::string& consumer, const QueuedMessage& target);
- bool nextBrowsableMessage( Consumer::shared_ptr& consumer, QueuedMessage& next );
- void query(qpid::types::Variant::Map&) const;
+public:
+ typedef Message::MessageCallback CompletionListener;
- private:
- Messages& messages;
+ QPID_BROKER_EXTERN IncompleteMessageList();
+ QPID_BROKER_EXTERN ~IncompleteMessageList();
+
+ QPID_BROKER_EXTERN void add(boost::intrusive_ptr<Message> msg);
+ QPID_BROKER_EXTERN void process(const CompletionListener& l, bool sync);
+ void each(const CompletionListener& l);
};
+
}}
#endif
diff --git a/cpp/src/qpid/broker/LegacyLVQ.cpp b/cpp/src/qpid/broker/LegacyLVQ.cpp
index 3262e343a3..a811a86492 100644
--- a/cpp/src/qpid/broker/LegacyLVQ.cpp
+++ b/cpp/src/qpid/broker/LegacyLVQ.cpp
@@ -93,7 +93,11 @@ void LegacyLVQ::removeIf(Predicate p)
//purging of an LVQ is not enabled if the broker is clustered
//(expired messages will be removed on delivery and consolidated
//by key as part of normal LVQ operation).
- if (!broker || !broker->isInCluster())
+
+ //TODO: Is there a neater way to check whether broker is
+ //clustered? Here we assume that if the clustered timer is the
+ //same as the regular timer, we are not clustered:
+ if (!broker || &(broker->getClusterTimer()) == &(broker->getTimer()))
MessageMap::removeIf(p);
}
diff --git a/cpp/src/qpid/broker/Link.cpp b/cpp/src/qpid/broker/Link.cpp
index 8010bf43e7..e1091df724 100644
--- a/cpp/src/qpid/broker/Link.cpp
+++ b/cpp/src/qpid/broker/Link.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -30,6 +30,7 @@
#include "qpid/framing/enum.h"
#include "qpid/framing/reply_exceptions.h"
#include "qpid/broker/AclModule.h"
+#include "qpid/sys/ClusterSafe.h"
using namespace qpid::broker;
using qpid::framing::Buffer;
@@ -56,8 +57,8 @@ Link::Link(LinkRegistry* _links,
string& _password,
Broker* _broker,
Manageable* parent)
- : links(_links), store(_store), host(_host), port(_port),
- transport(_transport),
+ : links(_links), store(_store), host(_host), port(_port),
+ transport(_transport),
durable(_durable),
authMechanism(_authMechanism), username(_username), password(_password),
persistenceId(0), mgmtObject(0), broker(_broker), state(0),
@@ -96,8 +97,7 @@ void Link::setStateLH (int newState)
return;
state = newState;
-
- if (hideManagement())
+ if (mgmtObject == 0)
return;
switch (state)
@@ -117,12 +117,12 @@ void Link::startConnectionLH ()
// Set the state before calling connect. It is possible that connect
// will fail synchronously and call Link::closed before returning.
setStateLH(STATE_CONNECTING);
- broker->connect (host, boost::lexical_cast<std::string>(port), transport,
+ broker->connect (host, port, transport,
boost::bind (&Link::closed, this, _1, _2));
QPID_LOG (debug, "Inter-broker link connecting to " << host << ":" << port);
} catch(std::exception& e) {
setStateLH(STATE_WAITING);
- if (!hideManagement())
+ if (mgmtObject != 0)
mgmtObject->set_lastError (e.what());
}
}
@@ -133,7 +133,8 @@ void Link::established ()
addr << host << ":" << port;
QPID_LOG (info, "Inter-broker link established to " << addr.str());
- if (!hideManagement() && agent)
+ // Don't raise the management event in a cluster, other members wont't get this call.
+ if (!sys::isCluster())
agent->raiseEvent(_qmf::EventBrokerLinkUp(addr.str()));
{
@@ -153,11 +154,12 @@ void Link::closed (int, std::string text)
connection = 0;
+ // Don't raise the management event in a cluster, other members wont't get this call.
if (state == STATE_OPERATIONAL) {
stringstream addr;
addr << host << ":" << port;
QPID_LOG (warning, "Inter-broker link disconnected from " << addr.str());
- if (!hideManagement() && agent)
+ if (!sys::isCluster())
agent->raiseEvent(_qmf::EventBrokerLinkDown(addr.str()));
}
@@ -170,7 +172,7 @@ void Link::closed (int, std::string text)
if (state != STATE_FAILED)
{
setStateLH(STATE_WAITING);
- if (!hideManagement())
+ if (mgmtObject != 0)
mgmtObject->set_lastError (text);
}
@@ -219,7 +221,7 @@ void Link::cancel(Bridge::shared_ptr bridge)
{
{
Mutex::ScopedLock mutex(lock);
-
+
for (Bridges::iterator i = created.begin(); i != created.end(); i++) {
if ((*i).get() == bridge.get()) {
created.erase(i);
@@ -248,19 +250,6 @@ void Link::ioThreadProcessing()
return;
QPID_LOG(debug, "Link::ioThreadProcessing()");
- // check for bridge session errors and recover
- if (!active.empty()) {
- Bridges::iterator removed = std::remove_if(
- active.begin(), active.end(), !boost::bind(&Bridge::isSessionReady, _1));
- for (Bridges::iterator i = removed; i != active.end(); ++i) {
- Bridge::shared_ptr bridge = *i;
- bridge->closed();
- bridge->cancel(*connection);
- created.push_back(bridge);
- }
- active.erase(removed, active.end());
- }
-
//process any pending creates and/or cancellations
if (!created.empty()) {
for (Bridges::iterator i = created.begin(); i != created.end(); ++i) {
@@ -288,9 +277,9 @@ void Link::maintenanceVisit ()
{
Mutex::ScopedLock mutex(lock);
- if (connection && updateUrls) {
+ if (connection && updateUrls) {
urls.reset(connection->getKnownHosts());
- QPID_LOG(debug, "Known hosts for peer of inter-broker link: " << urls);
+ QPID_LOG(debug, "Known hosts for peer of inter-broker link: " << urls);
updateUrls = false;
}
@@ -309,7 +298,7 @@ void Link::maintenanceVisit ()
}
}
}
- else if (state == STATE_OPERATIONAL && (!active.empty() || !created.empty() || !cancellations.empty()) && connection != 0)
+ else if (state == STATE_OPERATIONAL && (!created.empty() || !cancellations.empty()) && connection != 0)
connection->requestIOProcessing (boost::bind(&Link::ioThreadProcessing, this));
}
@@ -320,7 +309,7 @@ void Link::reconnect(const qpid::Address& a)
port = a.port;
transport = a.protocol;
startConnectionLH();
- if (!hideManagement()) {
+ if (mgmtObject != 0) {
stringstream errorString;
errorString << "Failed over to " << a;
mgmtObject->set_lastError(errorString.str());
@@ -330,7 +319,7 @@ void Link::reconnect(const qpid::Address& a)
bool Link::tryFailover()
{
Address next;
- if (urls.next(next) &&
+ if (urls.next(next) &&
(next.host != host || next.port != port || next.protocol != transport)) {
links->changeAddress(Address(transport, host, port), next);
QPID_LOG(debug, "Link failing over to " << host << ":" << port);
@@ -340,12 +329,6 @@ bool Link::tryFailover()
}
}
-// Management updates for a linke are inconsistent in a cluster, so they are
-// suppressed.
-bool Link::hideManagement() const {
- return !mgmtObject || ( broker && broker->isInCluster());
-}
-
uint Link::nextChannel()
{
Mutex::ScopedLock mutex(lock);
@@ -358,7 +341,7 @@ void Link::notifyConnectionForced(const string text)
Mutex::ScopedLock mutex(lock);
setStateLH(STATE_FAILED);
- if (!hideManagement())
+ if (mgmtObject != 0)
mgmtObject->set_lastError(text);
}
@@ -380,7 +363,7 @@ Link::shared_ptr Link::decode(LinkRegistry& links, Buffer& buffer)
string authMechanism;
string username;
string password;
-
+
buffer.getShortString(host);
port = buffer.getShort();
buffer.getShortString(transport);
@@ -392,7 +375,7 @@ Link::shared_ptr Link::decode(LinkRegistry& links, Buffer& buffer)
return links.declare(host, port, transport, durable, authMechanism, username, password).first;
}
-void Link::encode(Buffer& buffer) const
+void Link::encode(Buffer& buffer) const
{
buffer.putShortString(string("link"));
buffer.putShortString(host);
@@ -404,8 +387,8 @@ void Link::encode(Buffer& buffer) const
buffer.putShortString(password);
}
-uint32_t Link::encodedSize() const
-{
+uint32_t Link::encodedSize() const
+{
return host.size() + 1 // short-string (host)
+ 5 // short-string ("link")
+ 2 // port
diff --git a/cpp/src/qpid/broker/Link.h b/cpp/src/qpid/broker/Link.h
index 4badd8b3a1..75a680ff5d 100644
--- a/cpp/src/qpid/broker/Link.h
+++ b/cpp/src/qpid/broker/Link.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -85,7 +85,6 @@ namespace qpid {
void destroy(); // Called when mgmt deletes this link
void ioThreadProcessing(); // Called on connection's IO thread by request
bool tryFailover(); // Called during maintenance visit
- bool hideManagement() const;
public:
typedef boost::shared_ptr<Link> shared_ptr;
@@ -123,12 +122,12 @@ namespace qpid {
void notifyConnectionForced(const std::string text);
void setPassive(bool p);
-
+
// PersistableConfig:
void setPersistenceId(uint64_t id) const;
uint64_t getPersistenceId() const { return persistenceId; }
uint32_t encodedSize() const;
- void encode(framing::Buffer& buffer) const;
+ void encode(framing::Buffer& buffer) const;
const std::string& getName() const;
static Link::shared_ptr decode(LinkRegistry& links, framing::Buffer& buffer);
@@ -136,7 +135,6 @@ namespace qpid {
// Manageable entry points
management::ManagementObject* GetManagementObject(void) const;
management::Manageable::status_t ManagementMethod(uint32_t, management::Args&, std::string&);
-
};
}
}
diff --git a/cpp/src/qpid/broker/LinkRegistry.cpp b/cpp/src/qpid/broker/LinkRegistry.cpp
index e9885f5462..7b1c75db74 100644
--- a/cpp/src/qpid/broker/LinkRegistry.cpp
+++ b/cpp/src/qpid/broker/LinkRegistry.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -381,7 +381,7 @@ std::string LinkRegistry::createKey(const std::string& host, uint16_t port) {
return keystream.str();
}
-void LinkRegistry::setPassive(bool p)
+void LinkRegistry::setPassive(bool p)
{
Mutex::ScopedLock locker(lock);
passiveChanged = p != passive;
diff --git a/cpp/src/qpid/broker/Message.cpp b/cpp/src/qpid/broker/Message.cpp
index d13109dad1..c589669e5a 100644
--- a/cpp/src/qpid/broker/Message.cpp
+++ b/cpp/src/qpid/broker/Message.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -30,7 +30,6 @@
#include "qpid/framing/SendContent.h"
#include "qpid/framing/SequenceNumber.h"
#include "qpid/framing/TypeFilter.h"
-#include "qpid/framing/reply_exceptions.h"
#include "qpid/log/Statement.h"
#include <time.h>
@@ -50,16 +49,27 @@ 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), dequeueCallback(0),
- inCallback(false), requiredCredit(0), isManagementMessage(false), copyHeaderOnWrite(false)
-{}
+ staged(false), forcePersistentPolicy(false), publisher(0), adapter(0),
+ expiration(FAR_FUTURE), enqueueCallback(0), dequeueCallback(0),
+ inCallback(false), requiredCredit(0) {}
-Message::~Message() {}
+Message::Message(const Message& original) :
+ PersistableMessage(), frames(original.frames), persistenceId(0), redelivered(false), loaded(false),
+ staged(false), forcePersistentPolicy(false), publisher(0), adapter(0),
+ expiration(original.expiration), enqueueCallback(0), dequeueCallback(0),
+ inCallback(false), requiredCredit(0)
+{
+ setExpiryPolicy(original.expiryPolicy);
+}
+
+Message::~Message()
+{
+ if (expiryPolicy)
+ expiryPolicy->forget(*this);
+}
void Message::forcePersistent()
{
- sys::Mutex::ScopedLock l(lock);
// only set forced bit if we actually need to force.
if (! getAdapter().isPersistent(frames) ){
forcePersistentPolicy = true;
@@ -76,7 +86,7 @@ std::string Message::getRoutingKey() const
return getAdapter().getRoutingKey(frames);
}
-std::string Message::getExchangeName() const
+std::string Message::getExchangeName() const
{
return getAdapter().getExchange(frames);
}
@@ -85,7 +95,7 @@ const boost::shared_ptr<Exchange> Message::getExchange(ExchangeRegistry& registr
{
if (!exchange) {
exchange = registry.get(getExchangeName());
- }
+ }
return exchange;
}
@@ -96,19 +106,16 @@ bool Message::isImmediate() const
const FieldTable* Message::getApplicationHeaders() const
{
- sys::Mutex::ScopedLock l(lock);
return getAdapter().getApplicationHeaders(frames);
}
std::string Message::getAppId() const
{
- sys::Mutex::ScopedLock l(lock);
return getAdapter().getAppId(frames);
}
bool Message::isPersistent() const
{
- sys::Mutex::ScopedLock l(lock);
return (getAdapter().isPersistent(frames) || forcePersistentPolicy);
}
@@ -188,7 +195,7 @@ void Message::decodeContent(framing::Buffer& buffer)
} else {
//adjust header flags
MarkLastSegment f;
- frames.map_if(f, TypeFilter<HEADER_BODY>());
+ frames.map_if(f, TypeFilter<HEADER_BODY>());
}
//mark content loaded
loaded = true;
@@ -240,7 +247,7 @@ void Message::destroy()
bool Message::getContentFrame(const Queue& queue, AMQFrame& frame, uint16_t maxContentSize, uint64_t offset) const
{
intrusive_ptr<const PersistableMessage> pmsg(this);
-
+
bool done = false;
string& data = frame.castBody<AMQContentBody>()->getData();
store->loadContent(queue, pmsg, data, offset, maxContentSize);
@@ -265,7 +272,7 @@ void Message::sendContent(const Queue& queue, framing::FrameHandler& out, uint16
uint16_t maxContentSize = maxFrameSize - AMQFrame::frameOverhead();
bool morecontent = true;
for (uint64_t offset = 0; morecontent; offset += maxContentSize)
- {
+ {
AMQFrame frame((AMQContentBody()));
morecontent = getContentFrame(queue, frame, maxContentSize, offset);
out.handle(frame);
@@ -283,10 +290,7 @@ void Message::sendHeader(framing::FrameHandler& out, uint16_t /*maxFrameSize*/)
{
sys::Mutex::ScopedLock l(lock);
Relay f(out);
- frames.map_if(f, TypeFilter<HEADER_BODY>());
- //as frame (and pointer to body) has now been passed to handler,
- //subsequent modifications should use a copy
- copyHeaderOnWrite = true;
+ frames.map_if(f, TypeFilter<HEADER_BODY>());
}
// TODO aconway 2007-11-09: Obsolete, remove. Was used to cover over
@@ -316,14 +320,13 @@ bool Message::isContentLoaded() const
}
-namespace
+namespace
{
const std::string X_QPID_TRACE("x-qpid.trace");
}
bool Message::isExcluded(const std::vector<std::string>& excludes) const
{
- sys::Mutex::ScopedLock l(lock);
const FieldTable* headers = getApplicationHeaders();
if (headers) {
std::string traceStr = headers->getAsString(X_QPID_TRACE);
@@ -342,30 +345,11 @@ bool Message::isExcluded(const std::vector<std::string>& excludes) const
return false;
}
-class CloneHeaderBody
-{
-public:
- void operator()(AMQFrame& f)
- {
- f.cloneBody();
- }
-};
-
-AMQHeaderBody* Message::getHeaderBody()
-{
- if (copyHeaderOnWrite) {
- CloneHeaderBody f;
- frames.map_if(f, TypeFilter<HEADER_BODY>());
- copyHeaderOnWrite = false;
- }
- return frames.getHeaders();
-}
-
void Message::addTraceId(const std::string& id)
{
sys::Mutex::ScopedLock l(lock);
if (isA<MessageTransferBody>()) {
- FieldTable& headers = getModifiableProperties<MessageProperties>()->getApplicationHeaders();
+ FieldTable& headers = getProperties<MessageProperties>()->getApplicationHeaders();
std::string trace = headers.getAsString(X_QPID_TRACE);
if (trace.empty()) {
headers.setString(X_QPID_TRACE, id);
@@ -373,22 +357,13 @@ void Message::addTraceId(const std::string& id)
trace += ",";
trace += id;
headers.setString(X_QPID_TRACE, trace);
- }
+ }
}
}
-void Message::setTimestamp()
-{
- sys::Mutex::ScopedLock l(lock);
- DeliveryProperties* props = getModifiableProperties<DeliveryProperties>();
- time_t now = ::time(0);
- props->setTimestamp(now); // AMQP-0.10: posix time_t - secs since Epoch
-}
-
-void Message::computeExpiration(const boost::intrusive_ptr<ExpiryPolicy>& e)
+void Message::setTimestamp(const boost::intrusive_ptr<ExpiryPolicy>& e)
{
- sys::Mutex::ScopedLock l(lock);
- DeliveryProperties* props = getModifiableProperties<DeliveryProperties>();
+ DeliveryProperties* props = getProperties<DeliveryProperties>();
if (props->getTtl()) {
// AMQP requires setting the expiration property to be posix
// time_t in seconds. TTL is in milliseconds
@@ -397,70 +372,26 @@ void Message::computeExpiration(const boost::intrusive_ptr<ExpiryPolicy>& e)
time_t now = ::time(0);
props->setExpiration(now + (props->getTtl()/1000));
}
- if (e) {
- // Use higher resolution time for the internal expiry calculation.
- // Prevent overflow as a signed int64_t
- Duration ttl(std::min(props->getTtl() * TIME_MSEC,
- (uint64_t) std::numeric_limits<int64_t>::max()));
- expiration = AbsTime(e->getCurrentTime(), ttl);
- setExpiryPolicy(e);
- }
+ // Use higher resolution time for the internal expiry calculation.
+ expiration = AbsTime(AbsTime::now(), Duration(props->getTtl() * TIME_MSEC));
+ setExpiryPolicy(e);
}
}
void Message::adjustTtl()
{
- sys::Mutex::ScopedLock l(lock);
- DeliveryProperties* props = getModifiableProperties<DeliveryProperties>();
+ DeliveryProperties* props = getProperties<DeliveryProperties>();
if (props->getTtl()) {
- if (expiration < FAR_FUTURE) {
- sys::AbsTime current(
- expiryPolicy ? expiryPolicy->getCurrentTime() : sys::AbsTime::now());
- sys::Duration ttl(current, getExpiration());
- // convert from ns to ms; set to 1 if expired
- props->setTtl(int64_t(ttl) >= 1000000 ? int64_t(ttl)/1000000 : 1);
- }
+ sys::Mutex::ScopedLock l(lock);
+ sys::Duration d(sys::AbsTime::now(), getExpiration());
+ props->setTtl(int64_t(d) > 0 ? int64_t(d)/1000000 : 1); // convert from ns to ms; set to 1 if expired
}
}
-void Message::setRedelivered()
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<framing::DeliveryProperties>()->setRedelivered(true);
-}
-
-void Message::insertCustomProperty(const std::string& key, int64_t value)
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<MessageProperties>()->getApplicationHeaders().setInt64(key,value);
-}
-
-void Message::insertCustomProperty(const std::string& key, const std::string& value)
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<MessageProperties>()->getApplicationHeaders().setString(key,value);
-}
-
-void Message::removeCustomProperty(const std::string& key)
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<MessageProperties>()->getApplicationHeaders().erase(key);
-}
-
-void Message::setExchange(const std::string& exchange)
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<DeliveryProperties>()->setExchange(exchange);
-}
-
-void Message::clearApplicationHeadersFlag()
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<MessageProperties>()->clearApplicationHeadersFlag();
-}
-
void Message::setExpiryPolicy(const boost::intrusive_ptr<ExpiryPolicy>& e) {
expiryPolicy = e;
+ if (expiryPolicy)
+ expiryPolicy->willExpire(*this);
}
bool Message::hasExpired()
@@ -484,12 +415,30 @@ struct ScopedSet {
};
}
+void Message::allEnqueuesComplete() {
+ ScopedSet ss(callbackLock, inCallback);
+ MessageCallback* cb = enqueueCallback;
+ if (cb && *cb) (*cb)(intrusive_ptr<Message>(this));
+}
+
void Message::allDequeuesComplete() {
ScopedSet ss(callbackLock, inCallback);
MessageCallback* cb = dequeueCallback;
if (cb && *cb) (*cb)(intrusive_ptr<Message>(this));
}
+void Message::setEnqueueCompleteCallback(MessageCallback& cb) {
+ sys::Mutex::ScopedLock l(callbackLock);
+ while (inCallback) callbackLock.wait();
+ enqueueCallback = &cb;
+}
+
+void Message::resetEnqueueCompleteCallback() {
+ sys::Mutex::ScopedLock l(callbackLock);
+ while (inCallback) callbackLock.wait();
+ enqueueCallback = 0;
+}
+
void Message::setDequeueCompleteCallback(MessageCallback& cb) {
sys::Mutex::ScopedLock l(callbackLock);
while (inCallback) callbackLock.wait();
@@ -503,11 +452,12 @@ void Message::resetDequeueCompleteCallback() {
}
uint8_t Message::getPriority() const {
- sys::Mutex::ScopedLock l(lock);
return getAdapter().getPriority(frames);
}
-bool Message::getIsManagementMessage() const { return isManagementMessage; }
-void Message::setIsManagementMessage(bool b) { isManagementMessage = b; }
+framing::FieldTable& Message::getOrInsertHeaders()
+{
+ return getProperties<MessageProperties>()->getApplicationHeaders();
+}
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/Message.h b/cpp/src/qpid/broker/Message.h
index dda45d73e6..f7dd2734b6 100644
--- a/cpp/src/qpid/broker/Message.h
+++ b/cpp/src/qpid/broker/Message.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -29,21 +29,17 @@
#include "qpid/sys/Monitor.h"
#include "qpid/sys/Time.h"
#include <boost/function.hpp>
-#include <boost/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>
-#include <memory>
#include <string>
#include <vector>
namespace qpid {
-
+
namespace framing {
-class AMQBody;
-class AMQHeaderBody;
class FieldTable;
class SequenceNumber;
}
-
+
namespace broker {
class ConnectionToken;
class Exchange;
@@ -55,10 +51,11 @@ class ExpiryPolicy;
class Message : public PersistableMessage {
public:
typedef boost::function<void (const boost::intrusive_ptr<Message>&)> MessageCallback;
-
+
QPID_BROKER_EXTERN Message(const framing::SequenceNumber& id = framing::SequenceNumber());
+ QPID_BROKER_EXTERN Message(const Message&);
QPID_BROKER_EXTERN ~Message();
-
+
uint64_t getPersistenceId() const { return persistenceId; }
void setPersistenceId(uint64_t _persistenceId) const { persistenceId = _persistenceId; }
@@ -78,31 +75,27 @@ public:
bool isImmediate() const;
QPID_BROKER_EXTERN const framing::FieldTable* getApplicationHeaders() const;
QPID_BROKER_EXTERN std::string getAppId() const;
+ framing::FieldTable& getOrInsertHeaders();
QPID_BROKER_EXTERN bool isPersistent() const;
bool requiresAccept();
- /** determine msg expiration time using the TTL value if present */
- QPID_BROKER_EXTERN void computeExpiration(const boost::intrusive_ptr<ExpiryPolicy>& e);
+ QPID_BROKER_EXTERN void setTimestamp(const boost::intrusive_ptr<ExpiryPolicy>& e);
void setExpiryPolicy(const boost::intrusive_ptr<ExpiryPolicy>& e);
bool hasExpired();
sys::AbsTime getExpiration() const { return expiration; }
- void setExpiration(sys::AbsTime exp) { expiration = exp; }
void adjustTtl();
- void setRedelivered();
- QPID_BROKER_EXTERN void insertCustomProperty(const std::string& key, int64_t value);
- QPID_BROKER_EXTERN void insertCustomProperty(const std::string& key, const std::string& value);
- QPID_BROKER_EXTERN void removeCustomProperty(const std::string& key);
- void setExchange(const std::string&);
- void clearApplicationHeadersFlag();
- /** set the timestamp delivery property to the current time-of-day */
- QPID_BROKER_EXTERN void setTimestamp();
-
- framing::FrameSet& getFrames() { return frames; }
- const framing::FrameSet& getFrames() const { return frames; }
+
+ framing::FrameSet& getFrames() { return frames; }
+ const framing::FrameSet& getFrames() const { return frames; }
+
+ template <class T> T* getProperties() {
+ qpid::framing::AMQHeaderBody* p = frames.getHeaders();
+ return p->get<T>(true);
+ }
template <class T> const T* getProperties() const {
- const qpid::framing::AMQHeaderBody* p = frames.getHeaders();
- return p->get<T>();
+ qpid::framing::AMQHeaderBody* p = frames.getHeaders();
+ return p->get<T>(true);
}
template <class T> const T* hasProperties() const {
@@ -110,11 +103,6 @@ public:
return p->get<T>();
}
- template <class T> void eraseProperties() {
- qpid::framing::AMQHeaderBody* p = frames.getHeaders();
- p->erase<T>();
- }
-
template <class T> const T* getMethod() const {
return frames.as<T>();
}
@@ -147,7 +135,7 @@ public:
QPID_BROKER_EXTERN void decodeHeader(framing::Buffer& buffer);
QPID_BROKER_EXTERN void decodeContent(framing::Buffer& buffer);
-
+
void QPID_BROKER_EXTERN tryReleaseContent();
void releaseContent();
void releaseContent(MessageStore* s);//deprecated, use 'setStore(store); releaseContent();' instead
@@ -161,19 +149,24 @@ public:
bool isExcluded(const std::vector<std::string>& excludes) const;
void addTraceId(const std::string& id);
+
+ void forcePersistent();
+ bool isForcedPersistent();
+
- void forcePersistent();
- bool isForcedPersistent();
+ /** Call cb when enqueue is complete, may call immediately. Holds cb by reference. */
+ void setEnqueueCompleteCallback(MessageCallback& cb);
+ void resetEnqueueCompleteCallback();
/** Call cb when dequeue is complete, may call immediately. Holds cb by reference. */
void setDequeueCompleteCallback(MessageCallback& cb);
void resetDequeueCompleteCallback();
uint8_t getPriority() const;
- bool getIsManagementMessage() const;
- void setIsManagementMessage(bool b);
+
private:
MessageAdapter& getAdapter() const;
+ void allEnqueuesComplete();
void allDequeuesComplete();
mutable sys::Mutex lock;
@@ -183,7 +176,7 @@ public:
bool redelivered;
bool loaded;
bool staged;
- bool forcePersistentPolicy; // used to force message as durable, via a broker policy
+ bool forcePersistentPolicy; // used to force message as durable, via a broker policy
ConnectionToken* publisher;
mutable MessageAdapter* adapter;
qpid::sys::AbsTime expiration;
@@ -194,20 +187,11 @@ public:
mutable boost::intrusive_ptr<Message> empty;
sys::Monitor callbackLock;
+ MessageCallback* enqueueCallback;
MessageCallback* dequeueCallback;
bool inCallback;
uint32_t requiredCredit;
- bool isManagementMessage;
- mutable bool copyHeaderOnWrite;
-
- /**
- * Expects lock to be held
- */
- template <class T> T* getModifiableProperties() {
- return getHeaderBody()->get<T>(true);
- }
- qpid::framing::AMQHeaderBody* getHeaderBody();
};
}}
diff --git a/cpp/src/qpid/broker/MessageBuilder.h b/cpp/src/qpid/broker/MessageBuilder.h
index b99b8efee6..75dfd6781d 100644
--- a/cpp/src/qpid/broker/MessageBuilder.h
+++ b/cpp/src/qpid/broker/MessageBuilder.h
@@ -33,7 +33,7 @@ namespace qpid {
class Message;
class MessageStore;
- class QPID_BROKER_CLASS_EXTERN MessageBuilder : public framing::FrameHandler{
+ class MessageBuilder : public framing::FrameHandler{
public:
QPID_BROKER_EXTERN MessageBuilder(MessageStore* const store);
QPID_BROKER_EXTERN void handle(framing::AMQFrame& frame);
diff --git a/cpp/src/qpid/broker/MessageDistributor.h b/cpp/src/qpid/broker/MessageDistributor.h
deleted file mode 100644
index 090393c160..0000000000
--- a/cpp/src/qpid/broker/MessageDistributor.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef _broker_MessageDistributor_h
-#define _broker_MessageDistributor_h
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-/** Abstraction used by Queue to determine the next "most desirable" message to provide to
- * a particular consuming client
- */
-
-
-#include "qpid/broker/Consumer.h"
-
-namespace qpid {
-namespace broker {
-
-struct QueuedMessage;
-
-class MessageDistributor
-{
- public:
- virtual ~MessageDistributor() {};
-
- /** Locking Note: all methods assume the caller is holding the Queue::messageLock
- * during the method call.
- */
-
- /** Determine the next message available for consumption by the consumer
- * @param consumer the consumer that needs a message to consume
- * @param next set to the next message that the consumer may consume.
- * @return true if message is available and next is set
- */
- virtual bool nextConsumableMessage( Consumer::shared_ptr& consumer,
- QueuedMessage& next ) = 0;
-
- /** Allow the comsumer to take ownership of the given message.
- * @param consumer the name of the consumer that is attempting to acquire the message
- * @param qm the message to be acquired, previously returned from nextConsumableMessage()
- * @return true if ownership is permitted, false if ownership cannot be assigned.
- */
- virtual bool allocate( const std::string& consumer,
- const QueuedMessage& target) = 0;
-
- /** Determine the next message available for browsing by the consumer
- * @param consumer the consumer that is browsing the queue
- * @param next set to the next message that the consumer may browse.
- * @return true if a message is available and next is returned
- */
- virtual bool nextBrowsableMessage( Consumer::shared_ptr& consumer,
- QueuedMessage& next ) = 0;
-
- /** hook to add any interesting management state to the status map */
- virtual void query(qpid::types::Variant::Map&) const = 0;
-};
-
-}}
-
-#endif
diff --git a/cpp/src/qpid/broker/MessageGroupManager.cpp b/cpp/src/qpid/broker/MessageGroupManager.cpp
deleted file mode 100644
index 07b05f3b92..0000000000
--- a/cpp/src/qpid/broker/MessageGroupManager.cpp
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/framing/FieldTable.h"
-#include "qpid/types/Variant.h"
-#include "qpid/log/Statement.h"
-#include "qpid/broker/Queue.h"
-#include "qpid/broker/MessageGroupManager.h"
-
-using namespace qpid::broker;
-
-namespace {
- const std::string GROUP_QUERY_KEY("qpid.message_group_queue");
- const std::string GROUP_HEADER_KEY("group_header_key");
- const std::string GROUP_STATE_KEY("group_state");
- const std::string GROUP_ID_KEY("group_id");
- const std::string GROUP_MSG_COUNT("msg_count");
- const std::string GROUP_TIMESTAMP("timestamp");
- const std::string GROUP_CONSUMER("consumer");
-}
-
-
-const std::string MessageGroupManager::qpidMessageGroupKey("qpid.group_header_key");
-const std::string MessageGroupManager::qpidSharedGroup("qpid.shared_msg_group");
-const std::string MessageGroupManager::qpidMessageGroupTimestamp("qpid.group_timestamp");
-
-
-void MessageGroupManager::unFree( const GroupState& state )
-{
- GroupFifo::iterator pos = freeGroups.find( state.members.front() );
- assert( pos != freeGroups.end() && pos->second == &state );
- freeGroups.erase( pos );
-}
-
-void MessageGroupManager::own( GroupState& state, const std::string& owner )
-{
- state.owner = owner;
- unFree( state );
-}
-
-void MessageGroupManager::disown( GroupState& state )
-{
- state.owner.clear();
- assert(state.members.size());
- assert(freeGroups.find(state.members.front()) == freeGroups.end());
- freeGroups[state.members.front()] = &state;
-}
-
-const std::string MessageGroupManager::getGroupId( const QueuedMessage& qm ) const
-{
- const qpid::framing::FieldTable* headers = qm.payload->getApplicationHeaders();
- if (!headers) return defaultGroupId;
- qpid::framing::FieldTable::ValuePtr id = headers->get( groupIdHeader );
- if (!id || !id->convertsTo<std::string>()) return defaultGroupId;
- return id->get<std::string>();
-}
-
-
-void MessageGroupManager::enqueued( const QueuedMessage& qm )
-{
- // @todo KAG optimization - store reference to group state in QueuedMessage
- // issue: const-ness??
- std::string group( getGroupId(qm) );
- GroupState &state(messageGroups[group]);
- state.members.push_back(qm.position);
- uint32_t total = state.members.size();
- QPID_LOG( trace, "group queue " << qName <<
- ": added message to group id=" << group << " total=" << total );
- if (total == 1) {
- // newly created group, no owner
- state.group = group;
- assert(freeGroups.find(qm.position) == freeGroups.end());
- freeGroups[qm.position] = &state;
- }
-}
-
-
-void MessageGroupManager::acquired( const QueuedMessage& qm )
-{
- // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage
- // issue: const-ness??
- std::string group( getGroupId(qm) );
- GroupMap::iterator gs = messageGroups.find( group );
- assert( gs != messageGroups.end() );
- GroupState& state( gs->second );
- state.acquired += 1;
- QPID_LOG( trace, "group queue " << qName <<
- ": acquired message in group id=" << group << " acquired=" << state.acquired );
-}
-
-
-void MessageGroupManager::requeued( const QueuedMessage& qm )
-{
- // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage
- // issue: const-ness??
- std::string group( getGroupId(qm) );
- GroupMap::iterator gs = messageGroups.find( group );
- assert( gs != messageGroups.end() );
- GroupState& state( gs->second );
- assert( state.acquired != 0 );
- state.acquired -= 1;
- if (state.acquired == 0 && state.owned()) {
- QPID_LOG( trace, "group queue " << qName <<
- ": consumer name=" << state.owner << " released group id=" << gs->first);
- disown(state);
- }
- QPID_LOG( trace, "group queue " << qName <<
- ": requeued message to group id=" << group << " acquired=" << state.acquired );
-}
-
-
-void MessageGroupManager::dequeued( const QueuedMessage& qm )
-{
- // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage
- // issue: const-ness??
- std::string group( getGroupId(qm) );
- GroupMap::iterator gs = messageGroups.find( group );
- assert( gs != messageGroups.end() );
- GroupState& state( gs->second );
- assert( state.members.size() != 0 );
- assert( state.acquired != 0 );
- state.acquired -= 1;
-
- // likely to be at or near begin() if dequeued in order
- bool reFreeNeeded = false;
- if (state.members.front() == qm.position) {
- if (!state.owned()) {
- // will be on the freeGroups list if mgmt is dequeueing rather than a consumer!
- // if on freelist, it is indexed by first member, which is about to be removed!
- unFree(state);
- reFreeNeeded = true;
- }
- state.members.pop_front();
- } else {
- GroupState::PositionFifo::iterator pos = state.members.begin() + 1;
- GroupState::PositionFifo::iterator end = state.members.end();
- while (pos != end) {
- if (*pos == qm.position) {
- state.members.erase(pos);
- break;
- }
- ++pos;
- }
- }
-
- uint32_t total = state.members.size();
- if (total == 0) {
- QPID_LOG( trace, "group queue " << qName << ": deleting group id=" << gs->first);
- messageGroups.erase( gs );
- } else if (state.acquired == 0 && state.owned()) {
- QPID_LOG( trace, "group queue " << qName <<
- ": consumer name=" << state.owner << " released group id=" << gs->first);
- disown(state);
- } else if (reFreeNeeded) {
- disown(state);
- }
- QPID_LOG( trace, "group queue " << qName <<
- ": dequeued message from group id=" << group << " total=" << total );
-}
-
-bool MessageGroupManager::nextConsumableMessage( Consumer::shared_ptr& c, QueuedMessage& next )
-{
- if (messages.empty())
- return false;
-
- if (!freeGroups.empty()) {
- framing::SequenceNumber nextFree = freeGroups.begin()->first;
- if (nextFree < c->position) { // next free group's msg is older than current position
- bool ok = messages.find(nextFree, next);
- (void) ok; assert( ok );
- } else {
- if (!messages.next( c->position, next ))
- return false; // shouldn't happen - should find nextFree
- }
- } else { // no free groups available
- if (!messages.next( c->position, next ))
- return false;
- }
-
- do {
- // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage
- std::string group( getGroupId( next ) );
- GroupMap::iterator gs = messageGroups.find( group );
- assert( gs != messageGroups.end() );
- GroupState& state( gs->second );
- if (!state.owned() || state.owner == c->getName()) {
- return true;
- }
- } while (messages.next( next.position, next ));
- return false;
-}
-
-
-bool MessageGroupManager::allocate(const std::string& consumer, const QueuedMessage& qm)
-{
- // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage
- std::string group( getGroupId(qm) );
- GroupMap::iterator gs = messageGroups.find( group );
- assert( gs != messageGroups.end() );
- GroupState& state( gs->second );
-
- if (!state.owned()) {
- own( state, consumer );
- QPID_LOG( trace, "group queue " << qName <<
- ": consumer name=" << consumer << " has acquired group id=" << gs->first);
- return true;
- }
- return state.owner == consumer;
-}
-
-bool MessageGroupManager::nextBrowsableMessage( Consumer::shared_ptr& c, QueuedMessage& next )
-{
- // browse: allow access to any available msg, regardless of group ownership (?ok?)
- if (!messages.empty() && messages.next(c->position, next))
- return true;
- return false;
-}
-
-void MessageGroupManager::query(qpid::types::Variant::Map& status) const
-{
- /** Add a description of the current state of the message groups for this queue.
- FORMAT:
- { "qpid.message_group_queue":
- { "group_header_key" : "<KEY>",
- "group_state" :
- [ { "group_id" : "<name>",
- "msg_count" : <int>,
- "timestamp" : <absTime>,
- "consumer" : <consumer name> },
- {...} // one for each known group
- ]
- }
- }
- **/
-
- assert(status.find(GROUP_QUERY_KEY) == status.end());
- qpid::types::Variant::Map state;
- qpid::types::Variant::List groups;
-
- state[GROUP_HEADER_KEY] = groupIdHeader;
- for (GroupMap::const_iterator g = messageGroups.begin();
- g != messageGroups.end(); ++g) {
- qpid::types::Variant::Map info;
- info[GROUP_ID_KEY] = g->first;
- info[GROUP_MSG_COUNT] = g->second.members.size();
- info[GROUP_TIMESTAMP] = 0; /** @todo KAG - NEED HEAD MSG TIMESTAMP */
- info[GROUP_CONSUMER] = g->second.owner;
- groups.push_back(info);
- }
- state[GROUP_STATE_KEY] = groups;
- status[GROUP_QUERY_KEY] = state;
-}
-
-
-boost::shared_ptr<MessageGroupManager> MessageGroupManager::create( const std::string& qName,
- Messages& messages,
- const qpid::framing::FieldTable& settings )
-{
- boost::shared_ptr<MessageGroupManager> empty;
-
- if (settings.isSet(qpidMessageGroupKey)) {
-
- // @todo: remove once "sticky" consumers are supported - see QPID-3347
- if (!settings.isSet(qpidSharedGroup)) {
- QPID_LOG( error, "Only shared groups are supported in this version of the broker. Use '--shared-groups' in qpid-config." );
- return empty;
- }
-
- std::string headerKey = settings.getAsString(qpidMessageGroupKey);
- if (headerKey.empty()) {
- QPID_LOG( error, "A Message Group header key must be configured, queue=" << qName);
- return empty;
- }
- unsigned int timestamp = settings.getAsInt(qpidMessageGroupTimestamp);
-
- boost::shared_ptr<MessageGroupManager> manager( new MessageGroupManager( headerKey, qName, messages, timestamp ) );
-
- QPID_LOG( debug, "Configured Queue '" << qName <<
- "' for message grouping using header key '" << headerKey << "'" <<
- " (timestamp=" << timestamp << ")");
- return manager;
- }
- return empty;
-}
-
-std::string MessageGroupManager::defaultGroupId;
-void MessageGroupManager::setDefaults(const std::string& groupId) // static
-{
- defaultGroupId = groupId;
-}
-
-/** Cluster replication:
-
- state map format:
-
- { "group-state": [ {"name": <group-name>,
- "owner": <consumer-name>-or-empty,
- "acquired-ct": <acquired count>,
- "positions": [Seqnumbers, ... ]},
- {...}
- ]
- }
-*/
-
-namespace {
- const std::string GROUP_NAME("name");
- const std::string GROUP_OWNER("owner");
- const std::string GROUP_ACQUIRED_CT("acquired-ct");
- const std::string GROUP_POSITIONS("positions");
- const std::string GROUP_STATE("group-state");
-}
-
-
-/** Runs on UPDATER to snapshot current state */
-void MessageGroupManager::getState(qpid::framing::FieldTable& state ) const
-{
- using namespace qpid::framing;
- state.clear();
- framing::Array groupState(TYPE_CODE_MAP);
- for (GroupMap::const_iterator g = messageGroups.begin();
- g != messageGroups.end(); ++g) {
-
- framing::FieldTable group;
- group.setString(GROUP_NAME, g->first);
- group.setString(GROUP_OWNER, g->second.owner);
- group.setInt(GROUP_ACQUIRED_CT, g->second.acquired);
- framing::Array positions(TYPE_CODE_UINT32);
- for (GroupState::PositionFifo::const_iterator p = g->second.members.begin();
- p != g->second.members.end(); ++p)
- positions.push_back(framing::Array::ValuePtr(new IntegerValue( *p )));
- group.setArray(GROUP_POSITIONS, positions);
- groupState.push_back(framing::Array::ValuePtr(new FieldTableValue(group)));
- }
- state.setArray(GROUP_STATE, groupState);
-
- QPID_LOG(debug, "Queue \"" << qName << "\": replicating message group state, key=" << groupIdHeader);
-}
-
-
-/** called on UPDATEE to set state from snapshot */
-void MessageGroupManager::setState(const qpid::framing::FieldTable& state)
-{
- using namespace qpid::framing;
- messageGroups.clear();
- //consumers.clear();
- freeGroups.clear();
-
- framing::Array groupState(TYPE_CODE_MAP);
-
- bool ok = state.getArray(GROUP_STATE, groupState);
- if (!ok) {
- QPID_LOG(error, "Unable to find message group state information for queue \"" <<
- qName << "\": cluster inconsistency error!");
- return;
- }
-
- for (framing::Array::const_iterator g = groupState.begin();
- g != groupState.end(); ++g) {
- framing::FieldTable group;
- ok = framing::getEncodedValue<FieldTable>(*g, group);
- if (!ok) {
- QPID_LOG(error, "Invalid message group state information for queue \"" <<
- qName << "\": table encoding error!");
- return;
- }
- MessageGroupManager::GroupState state;
- if (!group.isSet(GROUP_NAME) || !group.isSet(GROUP_OWNER) || !group.isSet(GROUP_ACQUIRED_CT)) {
- QPID_LOG(error, "Invalid message group state information for queue \"" <<
- qName << "\": fields missing error!");
- return;
- }
- state.group = group.getAsString(GROUP_NAME);
- state.owner = group.getAsString(GROUP_OWNER);
- state.acquired = group.getAsInt(GROUP_ACQUIRED_CT);
- framing::Array positions(TYPE_CODE_UINT32);
- ok = group.getArray(GROUP_POSITIONS, positions);
- if (!ok) {
- QPID_LOG(error, "Invalid message group state information for queue \"" <<
- qName << "\": position encoding error!");
- return;
- }
-
- for (Array::const_iterator p = positions.begin(); p != positions.end(); ++p)
- state.members.push_back((*p)->getIntegerValue<uint32_t, 4>());
- messageGroups[state.group] = state;
- if (!state.owned()) {
- assert(state.members.size());
- freeGroups[state.members.front()] = &messageGroups[state.group];
- }
- }
-
- QPID_LOG(debug, "Queue \"" << qName << "\": message group state replicated, key =" << groupIdHeader)
-}
diff --git a/cpp/src/qpid/broker/MessageGroupManager.h b/cpp/src/qpid/broker/MessageGroupManager.h
deleted file mode 100644
index 6c81ec14d1..0000000000
--- a/cpp/src/qpid/broker/MessageGroupManager.h
+++ /dev/null
@@ -1,107 +0,0 @@
-#ifndef _broker_MessageGroupManager_h
-#define _broker_MessageGroupManager_h
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-/* for managing message grouping on Queues */
-
-#include "qpid/broker/StatefulQueueObserver.h"
-#include "qpid/broker/MessageDistributor.h"
-
-
-namespace qpid {
-namespace broker {
-
-class QueueObserver;
-class MessageDistributor;
-
-class MessageGroupManager : public StatefulQueueObserver, public MessageDistributor
-{
- static std::string defaultGroupId; // assigned if no group id header present
-
- const std::string groupIdHeader; // msg header holding group identifier
- const unsigned int timestamp; // mark messages with timestamp if set
- Messages& messages; // parent Queue's in memory message container
- const std::string qName; // name of parent queue (for logs)
-
- struct GroupState {
- // note: update getState()/setState() when changing this object's state implementation
- typedef std::deque<framing::SequenceNumber> PositionFifo;
-
- std::string group; // group identifier
- std::string owner; // consumer with outstanding acquired messages
- uint32_t acquired; // count of outstanding acquired messages
- PositionFifo members; // msgs belonging to this group
-
- GroupState() : acquired(0) {}
- bool owned() const {return !owner.empty();}
- };
- typedef std::map<std::string, struct GroupState> GroupMap;
- typedef std::map<framing::SequenceNumber, struct GroupState *> GroupFifo;
-
- GroupMap messageGroups; // index: group name
- GroupFifo freeGroups; // ordered by oldest free msg
- //Consumers consumers; // index: consumer name
-
- static const std::string qpidMessageGroupKey;
- static const std::string qpidSharedGroup; // if specified, one group can be consumed by multiple receivers
- static const std::string qpidMessageGroupTimestamp;
-
- const std::string getGroupId( const QueuedMessage& qm ) const;
- void unFree( const GroupState& state );
- void own( GroupState& state, const std::string& owner );
- void disown( GroupState& state );
-
- public:
-
- static QPID_BROKER_EXTERN void setDefaults(const std::string& groupId);
- static boost::shared_ptr<MessageGroupManager> create( const std::string& qName,
- Messages& messages,
- const qpid::framing::FieldTable& settings );
-
- MessageGroupManager(const std::string& header, const std::string& _qName,
- Messages& container, unsigned int _timestamp=0 )
- : StatefulQueueObserver(std::string("MessageGroupManager:") + header),
- groupIdHeader( header ), timestamp(_timestamp), messages(container), qName(_qName) {}
-
- // QueueObserver iface
- void enqueued( const QueuedMessage& qm );
- void acquired( const QueuedMessage& qm );
- void requeued( const QueuedMessage& qm );
- void dequeued( const QueuedMessage& qm );
- void consumerAdded( const Consumer& ) {};
- void consumerRemoved( const Consumer& ) {};
- void getState(qpid::framing::FieldTable& state ) const;
- void setState(const qpid::framing::FieldTable&);
-
- // MessageDistributor iface
- bool nextConsumableMessage(Consumer::shared_ptr& c, QueuedMessage& next);
- bool allocate(const std::string& c, const QueuedMessage& qm);
- bool nextBrowsableMessage(Consumer::shared_ptr& c, QueuedMessage& next);
- void query(qpid::types::Variant::Map&) const;
-
- bool match(const qpid::types::Variant::Map*, const QueuedMessage&) const;
-};
-
-}}
-
-#endif
diff --git a/cpp/src/qpid/broker/Messages.h b/cpp/src/qpid/broker/Messages.h
index 448f17432a..0d75417640 100644
--- a/cpp/src/qpid/broker/Messages.h
+++ b/cpp/src/qpid/broker/Messages.h
@@ -32,8 +32,7 @@ struct QueuedMessage;
/**
* This interface abstracts out the access to the messages held for
- * delivery by a Queue instance. Note the the assumption at present is
- * that all locking is done in the Queue itself.
+ * delivery by a Queue instance.
*/
class Messages
{
@@ -76,6 +75,7 @@ class Messages
* @return true if there is another message, false otherwise.
*/
virtual bool next(const framing::SequenceNumber&, QueuedMessage&) = 0;
+
/**
* Note: Caller is responsible for ensuring that there is a front
* (e.g. empty() returns false)
diff --git a/cpp/src/qpid/broker/NullMessageStore.cpp b/cpp/src/qpid/broker/NullMessageStore.cpp
index 43f600eaf1..dc8615d58b 100644
--- a/cpp/src/qpid/broker/NullMessageStore.cpp
+++ b/cpp/src/qpid/broker/NullMessageStore.cpp
@@ -126,25 +126,21 @@ std::auto_ptr<TPCTransactionContext> NullMessageStore::begin(const std::string&
void NullMessageStore::prepare(TPCTransactionContext& ctxt)
{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock);
prepared.insert(DummyCtxt::getXid(ctxt));
}
void NullMessageStore::commit(TransactionContext& ctxt)
{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock);
prepared.erase(DummyCtxt::getXid(ctxt));
}
void NullMessageStore::abort(TransactionContext& ctxt)
{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock);
prepared.erase(DummyCtxt::getXid(ctxt));
}
void NullMessageStore::collectPreparedXids(std::set<std::string>& out)
{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock);
out.insert(prepared.begin(), prepared.end());
}
diff --git a/cpp/src/qpid/broker/NullMessageStore.h b/cpp/src/qpid/broker/NullMessageStore.h
index c6f402662e..e148ec4d51 100644
--- a/cpp/src/qpid/broker/NullMessageStore.h
+++ b/cpp/src/qpid/broker/NullMessageStore.h
@@ -25,7 +25,6 @@
#include "qpid/broker/BrokerImportExport.h"
#include "qpid/broker/MessageStore.h"
#include "qpid/broker/Queue.h"
-#include "qpid/sys/Mutex.h"
#include <boost/intrusive_ptr.hpp>
@@ -35,11 +34,10 @@ namespace broker {
/**
* A null implementation of the MessageStore interface
*/
-class QPID_BROKER_CLASS_EXTERN NullMessageStore : public MessageStore
+class NullMessageStore : public MessageStore
{
std::set<std::string> prepared;
uint64_t nextPersistenceId;
- qpid::sys::Mutex lock;
public:
QPID_BROKER_EXTERN NullMessageStore();
diff --git a/cpp/src/qpid/broker/PersistableMessage.cpp b/cpp/src/qpid/broker/PersistableMessage.cpp
index 7ba28eb293..e5fbb71cbd 100644
--- a/cpp/src/qpid/broker/PersistableMessage.cpp
+++ b/cpp/src/qpid/broker/PersistableMessage.cpp
@@ -34,6 +34,7 @@ class MessageStore;
PersistableMessage::~PersistableMessage() {}
PersistableMessage::PersistableMessage() :
+ asyncEnqueueCounter(0),
asyncDequeueCounter(0),
store(0)
{}
@@ -67,6 +68,24 @@ bool PersistableMessage::isContentReleased() const
return contentReleaseState.released;
}
+bool PersistableMessage::isEnqueueComplete() {
+ sys::ScopedLock<sys::Mutex> l(asyncEnqueueLock);
+ return asyncEnqueueCounter == 0;
+}
+
+void PersistableMessage::enqueueComplete() {
+ bool notify = false;
+ {
+ sys::ScopedLock<sys::Mutex> l(asyncEnqueueLock);
+ if (asyncEnqueueCounter > 0) {
+ if (--asyncEnqueueCounter == 0) {
+ notify = true;
+ }
+ }
+ }
+ if (notify)
+ allEnqueuesComplete();
+}
bool PersistableMessage::isStoredOnQueue(PersistableQueue::shared_ptr queue){
if (store && (queue->getPersistenceId()!=0)) {
@@ -90,7 +109,12 @@ void PersistableMessage::addToSyncList(PersistableQueue::shared_ptr queue, Messa
void PersistableMessage::enqueueAsync(PersistableQueue::shared_ptr queue, MessageStore* _store) {
addToSyncList(queue, _store);
- enqueueStart();
+ enqueueAsync();
+}
+
+void PersistableMessage::enqueueAsync() {
+ sys::ScopedLock<sys::Mutex> l(asyncEnqueueLock);
+ asyncEnqueueCounter++;
}
bool PersistableMessage::isDequeueComplete() {
diff --git a/cpp/src/qpid/broker/PersistableMessage.h b/cpp/src/qpid/broker/PersistableMessage.h
index d29c2c45b4..96fb922c1a 100644
--- a/cpp/src/qpid/broker/PersistableMessage.h
+++ b/cpp/src/qpid/broker/PersistableMessage.h
@@ -31,7 +31,6 @@
#include "qpid/framing/amqp_types.h"
#include "qpid/sys/Mutex.h"
#include "qpid/broker/PersistableQueue.h"
-#include "qpid/broker/AsyncCompletion.h"
namespace qpid {
namespace broker {
@@ -44,19 +43,18 @@ class MessageStore;
class PersistableMessage : public Persistable
{
typedef std::list< boost::weak_ptr<PersistableQueue> > syncList;
+ sys::Mutex asyncEnqueueLock;
sys::Mutex asyncDequeueLock;
sys::Mutex storeLock;
-
+
/**
- * "Ingress" messages == messages sent _to_ the broker.
- * Tracks the number of outstanding asynchronous operations that must
- * complete before an inbound message can be considered fully received by the
- * broker. E.g. all enqueues have completed, the message has been written
- * to store, credit has been replenished, etc. Once all outstanding
- * operations have completed, the transfer of this message from the client
- * may be considered complete.
+ * Tracks the number of outstanding asynchronous enqueue
+ * operations. When the message is enqueued asynchronously the
+ * count is incremented; when that enqueue completes it is
+ * decremented. Thus when it is 0, there are no outstanding
+ * enqueues.
*/
- AsyncCompletion ingressCompletion;
+ int asyncEnqueueCounter;
/**
* Tracks the number of outstanding asynchronous dequeue
@@ -67,6 +65,7 @@ class PersistableMessage : public Persistable
*/
int asyncDequeueCounter;
+ void enqueueAsync();
void dequeueAsync();
syncList synclist;
@@ -81,6 +80,8 @@ class PersistableMessage : public Persistable
ContentReleaseState contentReleaseState;
protected:
+ /** Called when all enqueues are complete for this message. */
+ virtual void allEnqueuesComplete() = 0;
/** Called when all dequeues are complete for this message. */
virtual void allDequeuesComplete() = 0;
@@ -114,12 +115,9 @@ class PersistableMessage : public Persistable
virtual QPID_BROKER_EXTERN bool isPersistent() const = 0;
- /** track the progress of a message received by the broker - see ingressCompletion above */
- QPID_BROKER_INLINE_EXTERN bool isIngressComplete() { return ingressCompletion.isDone(); }
- QPID_BROKER_INLINE_EXTERN AsyncCompletion& getIngressCompletion() { return ingressCompletion; }
+ QPID_BROKER_EXTERN bool isEnqueueComplete();
- QPID_BROKER_INLINE_EXTERN void enqueueStart() { ingressCompletion.startCompleter(); }
- QPID_BROKER_INLINE_EXTERN void enqueueComplete() { ingressCompletion.finishCompleter(); }
+ QPID_BROKER_EXTERN void enqueueComplete();
QPID_BROKER_EXTERN void enqueueAsync(PersistableQueue::shared_ptr queue,
MessageStore* _store);
@@ -135,6 +133,7 @@ class PersistableMessage : public Persistable
bool isStoredOnQueue(PersistableQueue::shared_ptr queue);
void addToSyncList(PersistableQueue::shared_ptr queue, MessageStore* _store);
+
};
}}
diff --git a/cpp/src/qpid/broker/Queue.cpp b/cpp/src/qpid/broker/Queue.cpp
index 4627b1409a..27c1cc4ad7 100644
--- a/cpp/src/qpid/broker/Queue.cpp
+++ b/cpp/src/qpid/broker/Queue.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -31,10 +31,7 @@
#include "qpid/broker/MessageStore.h"
#include "qpid/broker/NullMessageStore.h"
#include "qpid/broker/QueueRegistry.h"
-#include "qpid/broker/QueueFlowLimit.h"
#include "qpid/broker/ThresholdAlerts.h"
-#include "qpid/broker/FifoDistributor.h"
-#include "qpid/broker/MessageGroupManager.h"
#include "qpid/StringUtils.h"
#include "qpid/log/Statement.h"
@@ -44,7 +41,6 @@
#include "qpid/sys/ClusterSafe.h"
#include "qpid/sys/Monitor.h"
#include "qpid/sys/Time.h"
-#include "qpid/types/Variant.h"
#include "qmf/org/apache/qpid/broker/ArgsQueuePurge.h"
#include "qmf/org/apache/qpid/broker/ArgsQueueReroute.h"
@@ -68,7 +64,7 @@ using std::mem_fun;
namespace _qmf = qmf::org::apache::qpid::broker;
-namespace
+namespace
{
const std::string qpidMaxSize("qpid.max_size");
const std::string qpidMaxCount("qpid.max_count");
@@ -90,16 +86,16 @@ const int ENQUEUE_ONLY=1;
const int ENQUEUE_AND_DEQUEUE=2;
}
-Queue::Queue(const string& _name, bool _autodelete,
+Queue::Queue(const string& _name, bool _autodelete,
MessageStore* const _store,
const OwnershipToken* const _owner,
Manageable* parent,
Broker* b) :
- name(_name),
+ name(_name),
autodelete(_autodelete),
store(_store),
- owner(_owner),
+ owner(_owner),
consumerCount(0),
exclusive(0),
noLocal(false),
@@ -114,8 +110,7 @@ Queue::Queue(const string& _name, bool _autodelete,
broker(b),
deleted(false),
barrier(*this),
- autoDeleteTimeout(0),
- allocator(new FifoDistributor( *messages ))
+ autoDeleteTimeout(0)
{
if (parent != 0 && broker != 0) {
ManagementAgent* agent = broker->getManagementAgent();
@@ -168,8 +163,13 @@ void Queue::deliver(boost::intrusive_ptr<Message> msg){
//drop message
QPID_LOG(info, "Dropping excluded message from " << getName());
} else {
- enqueue(0, msg);
- push(msg);
+ // if no store then mark as enqueued
+ if (!enqueue(0, msg)){
+ push(msg);
+ msg->enqueueComplete();
+ }else {
+ push(msg);
+ }
QPID_LOG(debug, "Message " << msg << " enqueued on " << name);
}
}
@@ -183,10 +183,11 @@ void Queue::recover(boost::intrusive_ptr<Message>& msg){
if (policy.get()) policy->recoverEnqueued(msg);
push(msg, true);
- if (store){
+ if (store){
// setup synclist for recovered messages, so they don't get re-stored on lastNodeFailure
- msg->addToSyncList(shared_from_this(), store);
+ msg->addToSyncList(shared_from_this(), store);
}
+ msg->enqueueComplete(); // mark the message as enqueued
if (store && (!msg->isContentLoaded() || msg->checkContentReleasable())) {
//content has not been loaded, need to ensure that lazy loading mode is set:
@@ -210,13 +211,14 @@ void Queue::process(boost::intrusive_ptr<Message>& msg){
void Queue::requeue(const QueuedMessage& msg){
assertClusterSafe();
QueueListeners::NotificationSet copy;
- {
+ {
Mutex::ScopedLock locker(messageLock);
if (!isEnqueued(msg)) return;
+ msg.payload->enqueueComplete(); // mark the message as enqueued
messages->reinsert(msg);
listeners.populate(copy);
- // for persistLastNode - don't force a message twice to disk, but force it if no force before
+ // for persistLastNode - don't force a message twice to disk, but force it if no force before
if(inLastNodeFailure && persistLastNode && !msg.payload->isStoredOnQueue(shared_from_this())) {
msg.payload->forcePersistent();
if (msg.payload->isForcedPersistent() ){
@@ -224,17 +226,16 @@ void Queue::requeue(const QueuedMessage& msg){
enqueue(0, payload);
}
}
- observeRequeue(msg, locker);
}
copy.notify();
}
-bool Queue::acquireMessageAt(const SequenceNumber& position, QueuedMessage& message)
+bool Queue::acquireMessageAt(const SequenceNumber& position, QueuedMessage& message)
{
Mutex::ScopedLock locker(messageLock);
assertClusterSafe();
QPID_LOG(debug, "Attempting to acquire message at " << position);
- if (acquire(position, message, locker)) {
+ if (messages->remove(position, message)) {
QPID_LOG(debug, "Acquired message at " << position << " from " << name);
return true;
} else {
@@ -243,24 +244,9 @@ bool Queue::acquireMessageAt(const SequenceNumber& position, QueuedMessage& mess
}
}
-bool Queue::acquire(const QueuedMessage& msg, const std::string& consumer)
-{
- Mutex::ScopedLock locker(messageLock);
- assertClusterSafe();
- QPID_LOG(debug, consumer << " attempting to acquire message at " << msg.position);
-
- if (!allocator->allocate( consumer, msg )) {
- QPID_LOG(debug, "Not permitted to acquire msg at " << msg.position << " from '" << name);
- return false;
- }
-
- QueuedMessage copy(msg);
- if (acquire( msg.position, copy, locker)) {
- QPID_LOG(debug, "Acquired message at " << msg.position << " from " << name);
- return true;
- }
- QPID_LOG(debug, "Could not acquire message at " << msg.position << " from " << name << "; no message at that position");
- return false;
+bool Queue::acquire(const QueuedMessage& msg) {
+ QueuedMessage copy = msg;
+ return acquireMessageAt(msg.position, copy);
}
void Queue::notifyListener()
@@ -276,7 +262,7 @@ void Queue::notifyListener()
set.notify();
}
-bool Queue::getNextMessage(QueuedMessage& m, Consumer::shared_ptr& c)
+bool Queue::getNextMessage(QueuedMessage& m, Consumer::shared_ptr c)
{
checkNotDeleted();
if (c->preAcquires()) {
@@ -288,71 +274,52 @@ bool Queue::getNextMessage(QueuedMessage& m, Consumer::shared_ptr& c)
case NO_MESSAGES:
default:
return false;
- }
+ }
} else {
return browseNextMessage(m, c);
}
}
-Queue::ConsumeCode Queue::consumeNextMessage(QueuedMessage& m, Consumer::shared_ptr& c)
+Queue::ConsumeCode Queue::consumeNextMessage(QueuedMessage& m, Consumer::shared_ptr c)
{
while (true) {
Mutex::ScopedLock locker(messageLock);
- QueuedMessage msg;
-
- if (!allocator->nextConsumableMessage(c, msg)) { // no next available
- QPID_LOG(debug, "No messages available to dispatch to consumer " <<
- c->getName() << " on queue '" << name << "'");
+ if (messages->empty()) {
+ QPID_LOG(debug, "No messages to dispatch on queue '" << name << "'");
listeners.addListener(c);
return NO_MESSAGES;
- }
-
- if (msg.payload->hasExpired()) {
- QPID_LOG(debug, "Message expired from queue '" << name << "'");
- c->position = msg.position;
- acquire( msg.position, msg, locker);
- dequeue( 0, msg );
- continue;
- }
-
- // a message is available for this consumer - can the consumer use it?
+ } else {
+ QueuedMessage msg = messages->front();
+ if (msg.payload->hasExpired()) {
+ QPID_LOG(debug, "Message expired from queue '" << name << "'");
+ popAndDequeue();
+ continue;
+ }
- if (c->filter(msg.payload)) {
- if (c->accept(msg.payload)) {
- bool ok = allocator->allocate( c->getName(), msg ); // inform allocator
- (void) ok; assert(ok);
- ok = acquire( msg.position, msg, locker);
- (void) ok; assert(ok);
- m = msg;
- c->position = m.position;
- return CONSUMED;
+ if (c->filter(msg.payload)) {
+ if (c->accept(msg.payload)) {
+ m = msg;
+ pop();
+ return CONSUMED;
+ } else {
+ //message(s) are available but consumer hasn't got enough credit
+ QPID_LOG(debug, "Consumer can't currently accept message from '" << name << "'");
+ return CANT_CONSUME;
+ }
} else {
- //message(s) are available but consumer hasn't got enough credit
- QPID_LOG(debug, "Consumer can't currently accept message from '" << name << "'");
+ //consumer will never want this message
+ QPID_LOG(debug, "Consumer doesn't want message from '" << name << "'");
return CANT_CONSUME;
- }
- } else {
- //consumer will never want this message
- QPID_LOG(debug, "Consumer doesn't want message from '" << name << "'");
- c->position = msg.position;
- return CANT_CONSUME;
+ }
}
}
}
-bool Queue::browseNextMessage(QueuedMessage& m, Consumer::shared_ptr& c)
-{
- while (true) {
- Mutex::ScopedLock locker(messageLock);
- QueuedMessage msg;
-
- if (!allocator->nextBrowsableMessage(c, msg)) { // no next available
- QPID_LOG(debug, "No browsable messages available for consumer " <<
- c->getName() << " on queue '" << name << "'");
- listeners.addListener(c);
- return false;
- }
+bool Queue::browseNextMessage(QueuedMessage& m, Consumer::shared_ptr c)
+{
+ QueuedMessage msg(this);
+ while (seek(msg, c)) {
if (c->filter(msg.payload) && !msg.payload->hasExpired()) {
if (c->accept(msg.payload)) {
//consumer wants the message
@@ -366,8 +333,8 @@ bool Queue::browseNextMessage(QueuedMessage& m, Consumer::shared_ptr& c)
}
} else {
//consumer will never want this message, continue seeking
- QPID_LOG(debug, "Browser skipping message from '" << name << "'");
c->position = msg.position;
+ QPID_LOG(debug, "Browser skipping message from '" << name << "'");
}
}
return false;
@@ -397,71 +364,61 @@ bool Queue::dispatch(Consumer::shared_ptr c)
}
}
-bool Queue::find(SequenceNumber pos, QueuedMessage& msg) const {
-
+// Find the next message
+bool Queue::seek(QueuedMessage& msg, Consumer::shared_ptr c) {
Mutex::ScopedLock locker(messageLock);
- if (messages->find(pos, msg))
+ if (messages->next(c->position, msg)) {
return true;
- return false;
+ } else {
+ listeners.addListener(c);
+ return false;
+ }
+}
+
+QueuedMessage Queue::find(SequenceNumber pos) const {
+
+ Mutex::ScopedLock locker(messageLock);
+ QueuedMessage msg;
+ messages->find(pos, msg);
+ return msg;
}
void Queue::consume(Consumer::shared_ptr c, bool requestExclusive){
assertClusterSafe();
- {
- Mutex::ScopedLock locker(consumerLock);
- if(exclusive) {
+ Mutex::ScopedLock locker(consumerLock);
+ if(exclusive) {
+ throw ResourceLockedException(
+ QPID_MSG("Queue " << getName() << " has an exclusive consumer. No more consumers allowed."));
+ } else if(requestExclusive) {
+ if(consumerCount) {
throw ResourceLockedException(
- QPID_MSG("Queue " << getName() << " has an exclusive consumer. No more consumers allowed."));
- } else if(requestExclusive) {
- if(consumerCount) {
- throw ResourceLockedException(
- QPID_MSG("Queue " << getName() << " already has consumers. Exclusive access denied."));
- } else {
- exclusive = c->getSession();
- }
- }
- consumerCount++;
- if (mgmtObject != 0)
- mgmtObject->inc_consumerCount ();
- //reset auto deletion timer if necessary
- if (autoDeleteTimeout && autoDeleteTask) {
- autoDeleteTask->cancel();
+ QPID_MSG("Queue " << getName() << " already has consumers. Exclusive access denied."));
+ } else {
+ exclusive = c->getSession();
}
}
- Mutex::ScopedLock locker(messageLock);
- for (Observers::const_iterator i = observers.begin(); i != observers.end(); ++i) {
- try{
- (*i)->consumerAdded(*c);
- } catch (const std::exception& e) {
- QPID_LOG(warning, "Exception on notification of new consumer for queue " << getName() << ": " << e.what());
- }
+ consumerCount++;
+ if (mgmtObject != 0)
+ mgmtObject->inc_consumerCount ();
+ //reset auto deletion timer if necessary
+ if (autoDeleteTimeout && autoDeleteTask) {
+ autoDeleteTask->cancel();
}
}
void Queue::cancel(Consumer::shared_ptr c){
removeListener(c);
- {
- Mutex::ScopedLock locker(consumerLock);
- consumerCount--;
- if(exclusive) exclusive = 0;
- if (mgmtObject != 0)
- mgmtObject->dec_consumerCount ();
- }
- Mutex::ScopedLock locker(messageLock);
- for (Observers::const_iterator i = observers.begin(); i != observers.end(); ++i) {
- try{
- (*i)->consumerRemoved(*c);
- } catch (const std::exception& e) {
- QPID_LOG(warning, "Exception on notification of removed consumer for queue " << getName() << ": " << e.what());
- }
- }
+ Mutex::ScopedLock locker(consumerLock);
+ consumerCount--;
+ if(exclusive) exclusive = 0;
+ if (mgmtObject != 0)
+ mgmtObject->dec_consumerCount ();
}
QueuedMessage Queue::get(){
Mutex::ScopedLock locker(messageLock);
QueuedMessage msg(this);
- if (messages->pop(msg))
- observeAcquire(msg, locker);
+ messages->pop(msg);
return msg;
}
@@ -475,135 +432,22 @@ bool collect_if_expired(std::deque<QueuedMessage>& expired, QueuedMessage& messa
}
}
-/**
- *@param lapse: time since the last purgeExpired
- */
-void Queue::purgeExpired(qpid::sys::Duration lapse)
+void Queue::purgeExpired()
{
//As expired messages are discarded during dequeue also, only
//bother explicitly expiring if the rate of dequeues since last
- //attempt is less than one per second.
- int count = dequeueSincePurge.get();
- dequeueSincePurge -= count;
- int seconds = int64_t(lapse)/qpid::sys::TIME_SEC;
- if (seconds == 0 || count / seconds < 1) {
+ //attempt is less than one per second.
+
+ if (dequeueTracker.sampleRatePerSecond() < 1) {
std::deque<QueuedMessage> expired;
{
Mutex::ScopedLock locker(messageLock);
- messages->removeIf(boost::bind(&collect_if_expired, boost::ref(expired), _1));
- }
-
- for (std::deque<QueuedMessage>::const_iterator i = expired.begin();
- i != expired.end(); ++i) {
- {
- Mutex::ScopedLock locker(messageLock);
- observeAcquire(*i, locker);
- }
- dequeue( 0, *i );
+ messages->removeIf(boost::bind(&collect_if_expired, expired, _1));
}
+ for_each(expired.begin(), expired.end(), bind(&Queue::dequeue, this, (TransactionContext*) 0, _1));
}
}
-
-namespace {
- // for use with purge/move below - collect messages that match a given filter
- //
- class MessageFilter
- {
- public:
- static const std::string typeKey;
- static const std::string paramsKey;
- static MessageFilter *create( const ::qpid::types::Variant::Map *filter );
- virtual bool match( const QueuedMessage& ) const { return true; }
- virtual ~MessageFilter() {}
- protected:
- MessageFilter() {};
- };
- const std::string MessageFilter::typeKey("filter_type");
- const std::string MessageFilter::paramsKey("filter_params");
-
- // filter by message header string value exact match
- class HeaderMatchFilter : public MessageFilter
- {
- public:
- /* Config:
- { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "<header name>",
- 'header_value' : "<value to match>"
- }
- }
- */
- static const std::string typeKey;
- static const std::string headerKey;
- static const std::string valueKey;
- HeaderMatchFilter( const std::string& _header, const std::string& _value )
- : MessageFilter (), header(_header), value(_value) {}
- bool match( const QueuedMessage& msg ) const
- {
- const qpid::framing::FieldTable* headers = msg.payload->getApplicationHeaders();
- if (!headers) return false;
- FieldTable::ValuePtr h = headers->get(header);
- if (!h || !h->convertsTo<std::string>()) return false;
- return h->get<std::string>() == value;
- }
- private:
- const std::string header;
- const std::string value;
- };
- const std::string HeaderMatchFilter::typeKey("header_match_str");
- const std::string HeaderMatchFilter::headerKey("header_key");
- const std::string HeaderMatchFilter::valueKey("header_value");
-
- // factory to create correct filter based on map
- MessageFilter* MessageFilter::create( const ::qpid::types::Variant::Map *filter )
- {
- using namespace qpid::types;
- if (filter && !filter->empty()) {
- Variant::Map::const_iterator i = filter->find(MessageFilter::typeKey);
- if (i != filter->end()) {
-
- if (i->second.asString() == HeaderMatchFilter::typeKey) {
- Variant::Map::const_iterator p = filter->find(MessageFilter::paramsKey);
- if (p != filter->end() && p->second.getType() == VAR_MAP) {
- Variant::Map::const_iterator k = p->second.asMap().find(HeaderMatchFilter::headerKey);
- Variant::Map::const_iterator v = p->second.asMap().find(HeaderMatchFilter::valueKey);
- if (k != p->second.asMap().end() && v != p->second.asMap().end()) {
- std::string headerKey(k->second.asString());
- std::string value(v->second.asString());
- QPID_LOG(debug, "Message filtering by header value configured. key: " << headerKey << " value: " << value );
- return new HeaderMatchFilter( headerKey, value );
- }
- }
- }
- }
- QPID_LOG(error, "Ignoring unrecognized message filter: '" << *filter << "'");
- }
- return new MessageFilter();
- }
-
- // used by removeIf() to collect all messages matching a filter, maximum match count is
- // optional.
- struct Collector {
- const uint32_t maxMatches;
- MessageFilter& filter;
- std::deque<QueuedMessage> matches;
- Collector(MessageFilter& filter, uint32_t max)
- : maxMatches(max), filter(filter) {}
- bool operator() (QueuedMessage& qm)
- {
- if (maxMatches == 0 || matches.size() < maxMatches) {
- if (filter.match( qm )) {
- matches.push_back(qm);
- return true;
- }
- }
- return false;
- }
- };
-
-} // end namespace
-
-
/**
* purge - for purging all or some messages on a queue
* depending on the purge_request
@@ -615,77 +459,63 @@ namespace {
* The dest exchange may be supplied to re-route messages through the exchange.
* It is safe to re-route messages such that they arrive back on the same queue,
* even if the queue is ordered by priority.
- *
- * An optional filter can be supplied that will be applied against each message. The
- * message is purged only if the filter matches. See MessageDistributor for more detail.
*/
-uint32_t Queue::purge(const uint32_t purge_request, boost::shared_ptr<Exchange> dest,
- const qpid::types::Variant::Map *filter)
+uint32_t Queue::purge(const uint32_t purge_request, boost::shared_ptr<Exchange> dest)
{
- std::auto_ptr<MessageFilter> mf(MessageFilter::create(filter));
- Collector c(*mf.get(), purge_request);
-
Mutex::ScopedLock locker(messageLock);
- messages->removeIf( boost::bind<bool>(boost::ref(c), _1) );
- for (std::deque<QueuedMessage>::iterator qmsg = c.matches.begin();
- qmsg != c.matches.end(); ++qmsg) {
- // Update observers and message state:
- observeAcquire(*qmsg, locker);
- dequeue(0, *qmsg);
- // now reroute if necessary
+ uint32_t purge_count = purge_request; // only comes into play if >0
+ std::deque<DeliverableMessage> rerouteQueue;
+
+ uint32_t count = 0;
+ // Either purge them all or just the some (purge_count) while the queue isn't empty.
+ while((!purge_request || purge_count--) && !messages->empty()) {
if (dest.get()) {
- assert(qmsg->payload);
- DeliverableMessage dmsg(qmsg->payload);
- dest->routeWithAlternate(dmsg);
+ //
+ // If there is a destination exchange, stage the messages onto a reroute queue
+ // so they don't wind up getting purged more than once.
+ //
+ DeliverableMessage msg(messages->front().payload);
+ rerouteQueue.push_back(msg);
}
+ popAndDequeue();
+ count++;
}
- return c.matches.size();
-}
-
-uint32_t Queue::move(const Queue::shared_ptr destq, uint32_t qty,
- const qpid::types::Variant::Map *filter)
-{
- std::auto_ptr<MessageFilter> mf(MessageFilter::create(filter));
- Collector c(*mf.get(), qty);
- Mutex::ScopedLock locker(messageLock);
- messages->removeIf( boost::bind<bool>(boost::ref(c), _1) );
-
- for (std::deque<QueuedMessage>::iterator qmsg = c.matches.begin();
- qmsg != c.matches.end(); ++qmsg) {
- // Update observers and message state:
- observeAcquire(*qmsg, locker);
- dequeue(0, *qmsg);
- // and move to destination Queue.
- assert(qmsg->payload);
- destq->deliver(qmsg->payload);
+ //
+ // Re-route purged messages into the destination exchange. Note that there's no need
+ // to test dest.get() here because if it is NULL, the rerouteQueue will be empty.
+ //
+ while (!rerouteQueue.empty()) {
+ DeliverableMessage msg(rerouteQueue.front());
+ rerouteQueue.pop_front();
+ dest->route(msg, msg.getMessage().getRoutingKey(),
+ msg.getMessage().getApplicationHeaders());
}
- return c.matches.size();
+
+ return count;
}
-/** Acquire the front (oldest) message from the in-memory queue.
- * assumes messageLock held by caller
- */
-void Queue::pop(const Mutex::ScopedLock& locker)
-{
- assertClusterSafe();
- QueuedMessage msg;
- if (messages->pop(msg)) {
- observeAcquire(msg, locker);
- ++dequeueSincePurge;
+uint32_t Queue::move(const Queue::shared_ptr destq, uint32_t qty) {
+ Mutex::ScopedLock locker(messageLock);
+ uint32_t move_count = qty; // only comes into play if qty >0
+ uint32_t count = 0; // count how many were moved for returning
+
+ while((!qty || move_count--) && !messages->empty()) {
+ QueuedMessage qmsg = messages->front();
+ boost::intrusive_ptr<Message> msg = qmsg.payload;
+ destq->deliver(msg); // deliver message to the destination queue
+ pop();
+ dequeue(0, qmsg);
+ count++;
}
+ return count;
}
-/** Acquire the message at the given position, return true and msg if acquire succeeds */
-bool Queue::acquire(const qpid::framing::SequenceNumber& position, QueuedMessage& msg,
- const Mutex::ScopedLock& locker)
+void Queue::pop()
{
- if (messages->remove(position, msg)) {
- observeAcquire(msg, locker);
- ++dequeueSincePurge;
- return true;
- }
- return false;
+ assertClusterSafe();
+ messages->pop();
+ ++dequeueTracker;
}
void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){
@@ -694,15 +524,13 @@ void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){
QueuedMessage removed;
bool dequeueRequired = false;
{
- Mutex::ScopedLock locker(messageLock);
+ Mutex::ScopedLock locker(messageLock);
QueuedMessage qm(this, msg, ++sequence);
- if (insertSeqNo) msg->insertCustomProperty(seqNoKey, sequence);
-
+ if (insertSeqNo) msg->getOrInsertHeaders().setInt64(seqNoKey, sequence);
+
dequeueRequired = messages->push(qm, removed);
- if (dequeueRequired)
- observeAcquire(removed, locker);
listeners.populate(copy);
- observeEnqueue(qm, locker);
+ enqueued(qm);
}
copy.notify();
if (dequeueRequired) {
@@ -718,7 +546,7 @@ void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){
void isEnqueueComplete(uint32_t* result, const QueuedMessage& message)
{
- if (message.payload->isIngressComplete()) (*result)++;
+ if (message.payload->isEnqueueComplete()) (*result)++;
}
/** function only provided for unit tests, or code not in critical message path */
@@ -778,7 +606,7 @@ void Queue::setLastNodeFailure()
}
-// return true if store exists,
+// return true if store exists,
bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg, bool suppressPolicyCheck)
{
ScopedUse u(barrier);
@@ -792,21 +620,24 @@ bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& 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));
+ for_each(dequeues.begin(), dequeues.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1));
}
if (inLastNodeFailure && persistLastNode){
msg->forcePersistent();
}
-
+
if (traceId.size()) {
+ //copy on write: take deep copy of message before modifying it
+ //as the frames may already be available for delivery on other
+ //threads
+ boost::intrusive_ptr<Message> copy(new Message(*msg));
+ msg = copy;
msg->addTraceId(traceId);
}
if ((msg->isPersistent() || msg->checkContentReleasable()) && store) {
- // mark the message as being enqueued - the store MUST CALL msg->enqueueComplete()
- // when it considers the message stored.
- msg->enqueueAsync(shared_from_this(), 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;
@@ -823,10 +654,10 @@ bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg
void Queue::enqueueAborted(boost::intrusive_ptr<Message> msg)
{
Mutex::ScopedLock locker(messageLock);
- if (policy.get()) policy->enqueueAborted(msg);
+ if (policy.get()) policy->enqueueAborted(msg);
}
-// return true if store exists,
+// return true if store exists,
bool Queue::dequeue(TransactionContext* ctxt, const QueuedMessage& msg)
{
ScopedUse u(barrier);
@@ -835,8 +666,8 @@ bool Queue::dequeue(TransactionContext* ctxt, const QueuedMessage& msg)
{
Mutex::ScopedLock locker(messageLock);
if (!isEnqueued(msg)) return false;
- if (!ctxt) {
- observeDequeue(msg, locker);
+ if (!ctxt) {
+ dequeued(msg);
}
}
// This check prevents messages which have been forced persistent on one queue from dequeuing
@@ -856,7 +687,7 @@ bool Queue::dequeue(TransactionContext* ctxt, const QueuedMessage& msg)
void Queue::dequeueCommitted(const QueuedMessage& msg)
{
Mutex::ScopedLock locker(messageLock);
- observeDequeue(msg, locker);
+ dequeued(msg);
if (mgmtObject != 0) {
mgmtObject->inc_msgTxnDequeues();
mgmtObject->inc_byteTxnDequeues(msg.payload->contentSize());
@@ -864,23 +695,21 @@ void Queue::dequeueCommitted(const QueuedMessage& msg)
}
/**
- * Removes the first (oldest) message from the in-memory delivery queue as well dequeing
- * it from the logical (and persistent if applicable) queue
+ * Removes a message from the in-memory delivery queue as well
+ * dequeing it from the logical (and persistent if applicable) queue
*/
-void Queue::popAndDequeue(const Mutex::ScopedLock& held)
+void Queue::popAndDequeue()
{
- if (!messages->empty()) {
- QueuedMessage msg = messages->front();
- pop(held);
- dequeue(0, msg);
- }
+ QueuedMessage msg = messages->front();
+ pop();
+ dequeue(0, msg);
}
/**
* Updates policy and management when a message has been dequeued,
* expects messageLock to be held
*/
-void Queue::observeDequeue(const QueuedMessage& msg, const Mutex::ScopedLock&)
+void Queue::dequeued(const QueuedMessage& msg)
{
if (policy.get()) policy->dequeued(msg);
mgntDeqStats(msg.payload);
@@ -893,33 +722,6 @@ void Queue::observeDequeue(const QueuedMessage& msg, const Mutex::ScopedLock&)
}
}
-/** updates queue observers when a message has become unavailable for transfer,
- * expects messageLock to be held
- */
-void Queue::observeAcquire(const QueuedMessage& msg, const Mutex::ScopedLock&)
-{
- for (Observers::const_iterator i = observers.begin(); i != observers.end(); ++i) {
- try{
- (*i)->acquired(msg);
- } catch (const std::exception& e) {
- QPID_LOG(warning, "Exception on notification of message removal for queue " << getName() << ": " << e.what());
- }
- }
-}
-
-/** updates queue observers when a message has become re-available for transfer,
- * expects messageLock to be held
- */
-void Queue::observeRequeue(const QueuedMessage& msg, const Mutex::ScopedLock&)
-{
- for (Observers::const_iterator i = observers.begin(); i != observers.end(); ++i) {
- try{
- (*i)->requeued(msg);
- } catch (const std::exception& e) {
- QPID_LOG(warning, "Exception on notification of message requeue for queue " << getName() << ": " << e.what());
- }
- }
-}
void Queue::create(const FieldTable& _settings)
{
@@ -927,7 +729,7 @@ void Queue::create(const FieldTable& _settings)
if (store) {
store->create(*this, _settings);
}
- configureImpl(_settings);
+ configure(_settings);
}
@@ -940,8 +742,8 @@ int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::stri
return v->get<int>();
} else if (v->convertsTo<std::string>()){
std::string s = v->get<std::string>();
- try {
- return boost::lexical_cast<int>(s);
+ try {
+ return boost::lexical_cast<int>(s);
} catch(const boost::bad_lexical_cast&) {
QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << s);
return 0;
@@ -952,45 +754,15 @@ int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::stri
}
}
-bool getBoolSetting(const qpid::framing::FieldTable& settings, const std::string& key)
+void Queue::configure(const FieldTable& _settings, bool recovering)
{
- qpid::framing::FieldTable::ValuePtr v = settings.get(key);
- if (!v) {
- return false;
- } else if (v->convertsTo<int>()) {
- return v->get<int>() != 0;
- } else if (v->convertsTo<std::string>()){
- std::string s = v->get<std::string>();
- if (s == "True") return true;
- if (s == "true") return true;
- if (s == "False") return false;
- if (s == "false") return false;
- try {
- return boost::lexical_cast<bool>(s);
- } catch(const boost::bad_lexical_cast&) {
- QPID_LOG(warning, "Ignoring invalid boolean value for " << key << ": " << s);
- return false;
- }
- } else {
- QPID_LOG(warning, "Ignoring invalid boolean value for " << key << ": " << *v);
- return false;
- }
-}
-
-void Queue::configure(const FieldTable& _settings)
-{
- settings = _settings;
- configureImpl(settings);
-}
-void Queue::configureImpl(const FieldTable& _settings)
-{
eventMode = _settings.getAsInt(qpidQueueEventGeneration);
if (eventMode && broker) {
broker->getQueueEvents().observe(*this, eventMode == ENQUEUE_ONLY);
}
- if (QueuePolicy::getType(_settings) == QueuePolicy::FLOW_TO_DISK &&
+ if (QueuePolicy::getType(_settings) == QueuePolicy::FLOW_TO_DISK &&
(!store || NullMessageStore::isNullStore(store) || (broker && !(broker->getQueueEvents().isSync())) )) {
if ( NullMessageStore::isNullStore(store)) {
QPID_LOG(warning, "Flow to disk not valid for non-persisted queue:" << getName());
@@ -1004,43 +776,32 @@ void Queue::configureImpl(const FieldTable& _settings)
setPolicy(QueuePolicy::createQueuePolicy(getName(), _settings));
}
if (broker && broker->getManagementAgent()) {
- ThresholdAlerts::observe(*this, *(broker->getManagementAgent()), _settings, broker->getOptions().queueThresholdEventRatio);
+ ThresholdAlerts::observe(*this, *(broker->getManagementAgent()), _settings);
}
//set this regardless of owner to allow use of no-local with exclusive consumers also
- noLocal = getBoolSetting(_settings, qpidNoLocal);
+ noLocal = _settings.get(qpidNoLocal);
QPID_LOG(debug, "Configured queue " << getName() << " with no-local=" << noLocal);
std::string lvqKey = _settings.getAsString(qpidLastValueQueueKey);
if (lvqKey.size()) {
QPID_LOG(debug, "Configured queue " << getName() << " as Last Value Queue with key " << lvqKey);
messages = std::auto_ptr<Messages>(new MessageMap(lvqKey));
- allocator = boost::shared_ptr<MessageDistributor>(new FifoDistributor( *messages ));
- } else if (getBoolSetting(_settings, qpidLastValueQueueNoBrowse)) {
+ } else if (_settings.get(qpidLastValueQueueNoBrowse)) {
QPID_LOG(debug, "Configured queue " << getName() << " as Legacy Last Value Queue with 'no-browse' on");
messages = LegacyLVQ::updateOrReplace(messages, qpidVQMatchProperty, true, broker);
- allocator = boost::shared_ptr<MessageDistributor>(new FifoDistributor( *messages ));
- } else if (getBoolSetting(_settings, qpidLastValueQueue)) {
+ } else if (_settings.get(qpidLastValueQueue)) {
QPID_LOG(debug, "Configured queue " << getName() << " as Legacy Last Value Queue");
messages = LegacyLVQ::updateOrReplace(messages, qpidVQMatchProperty, false, broker);
- allocator = boost::shared_ptr<MessageDistributor>(new FifoDistributor( *messages ));
} else {
std::auto_ptr<Messages> m = Fairshare::create(_settings);
if (m.get()) {
messages = m;
- allocator = boost::shared_ptr<MessageDistributor>(new FifoDistributor( *messages ));
QPID_LOG(debug, "Configured queue " << getName() << " as priority queue.");
- } else { // default (FIFO) queue type
- // override default message allocator if message groups configured.
- boost::shared_ptr<MessageGroupManager> mgm(MessageGroupManager::create( getName(), *messages, _settings));
- if (mgm) {
- allocator = mgm;
- addObserver(mgm);
- }
}
}
-
- persistLastNode = getBoolSetting(_settings, qpidPersistLastNode);
+
+ persistLastNode= _settings.get(qpidPersistLastNode);
if (persistLastNode) QPID_LOG(debug, "Configured queue to Persist data if cluster fails to one node for: " << getName());
traceId = _settings.getAsString(qpidTraceIdentity);
@@ -1048,32 +809,32 @@ void Queue::configureImpl(const FieldTable& _settings)
if (excludeList.size()) {
split(traceExclude, excludeList, ", ");
}
- QPID_LOG(debug, "Configured queue " << getName() << " with qpid.trace.id='" << traceId
+ QPID_LOG(debug, "Configured queue " << getName() << " with qpid.trace.id='" << traceId
<< "' and qpid.trace.exclude='"<< excludeList << "' i.e. " << traceExclude.size() << " elements");
FieldTable::ValuePtr p =_settings.get(qpidInsertSequenceNumbers);
if (p && p->convertsTo<std::string>()) insertSequenceNumbers(p->get<std::string>());
autoDeleteTimeout = getIntegerSetting(_settings, qpidAutoDeleteTimeout);
- if (autoDeleteTimeout)
- QPID_LOG(debug, "Configured queue " << getName() << " with qpid.auto_delete_timeout=" << autoDeleteTimeout);
+ if (autoDeleteTimeout)
+ QPID_LOG(debug, "Configured queue " << getName() << " with qpid.auto_delete_timeout=" << autoDeleteTimeout);
- if (mgmtObject != 0) {
+ if (mgmtObject != 0)
mgmtObject->set_arguments(ManagementAgent::toMap(_settings));
- }
- QueueFlowLimit::observe(*this, _settings);
+ if ( isDurable() && ! getPersistenceId() && ! recovering )
+ store->create(*this, _settings);
}
-void Queue::destroyed()
+void Queue::destroy()
{
- unbind(broker->getExchanges());
if (alternateExchange.get()) {
Mutex::ScopedLock locker(messageLock);
while(!messages->empty()){
DeliverableMessage msg(messages->front().payload);
- alternateExchange->routeWithAlternate(msg);
- popAndDequeue(locker);
+ alternateExchange->route(msg, msg.getMessage().getRoutingKey(),
+ msg.getMessage().getApplicationHeaders());
+ popAndDequeue();
}
alternateExchange->decAlternateUsers();
}
@@ -1085,7 +846,6 @@ void Queue::destroyed()
store = 0;//ensure we make no more calls to the store for this queue
}
if (autoDeleteTask) autoDeleteTask = boost::intrusive_ptr<TimerTask>();
- notifyDeleted();
}
void Queue::notifyDeleted()
@@ -1105,9 +865,9 @@ void Queue::bound(const string& exchange, const string& key,
bindings.add(exchange, key, args);
}
-void Queue::unbind(ExchangeRegistry& exchanges)
+void Queue::unbind(ExchangeRegistry& exchanges, Queue::shared_ptr shared_ref)
{
- bindings.unbind(exchanges, shared_from_this());
+ bindings.unbind(exchanges, shared_ref);
}
void Queue::setPolicy(std::auto_ptr<QueuePolicy> _policy)
@@ -1120,9 +880,9 @@ const QueuePolicy* Queue::getPolicy()
return policy.get();
}
-uint64_t Queue::getPersistenceId() const
-{
- return persistenceId;
+uint64_t Queue::getPersistenceId() const
+{
+ return persistenceId;
}
void Queue::setPersistenceId(uint64_t _persistenceId) const
@@ -1136,11 +896,11 @@ void Queue::setPersistenceId(uint64_t _persistenceId) const
persistenceId = _persistenceId;
}
-void Queue::encode(Buffer& buffer) const
+void Queue::encode(Buffer& buffer) const
{
buffer.putShortString(name);
buffer.put(settings);
- if (policy.get()) {
+ if (policy.get()) {
buffer.put(*policy);
}
buffer.putShortString(alternateExchange.get() ? alternateExchange->getName() : std::string(""));
@@ -1154,14 +914,13 @@ uint32_t Queue::encodedSize() const
+ (policy.get() ? (*policy).encodedSize() : 0);
}
-Queue::shared_ptr Queue::restore( QueueRegistry& queues, Buffer& buffer )
+Queue::shared_ptr Queue::decode ( QueueRegistry& queues, Buffer& buffer, bool recovering )
{
string name;
buffer.getShortString(name);
- FieldTable settings;
- buffer.get(settings);
- boost::shared_ptr<Exchange> alternate;
- std::pair<Queue::shared_ptr, bool> result = queues.declare(name, true, false, 0, alternate, settings, true);
+ std::pair<Queue::shared_ptr, bool> result = queues.declare(name, true);
+ buffer.get(result.first->settings);
+ result.first->configure(result.first->settings, recovering );
if (result.first->policy.get() && buffer.available() >= result.first->policy->encodedSize()) {
buffer.get ( *(result.first->policy) );
}
@@ -1193,10 +952,11 @@ boost::shared_ptr<Exchange> Queue::getAlternateExchange()
void tryAutoDeleteImpl(Broker& broker, Queue::shared_ptr queue)
{
- if (broker.getQueues().destroyIf(queue->getName(),
+ if (broker.getQueues().destroyIf(queue->getName(),
boost::bind(boost::mem_fn(&Queue::canAutoDelete), queue))) {
QPID_LOG(debug, "Auto-deleting " << queue->getName());
- queue->destroyed();
+ queue->unbind(broker.getExchanges(), queue);
+ queue->destroy();
}
}
@@ -1205,7 +965,7 @@ struct AutoDeleteTask : qpid::sys::TimerTask
Broker& broker;
Queue::shared_ptr queue;
- AutoDeleteTask(Broker& b, Queue::shared_ptr q, AbsTime fireTime)
+ AutoDeleteTask(Broker& b, Queue::shared_ptr q, AbsTime fireTime)
: qpid::sys::TimerTask(fireTime, "DelayedAutoDeletion"), broker(b), queue(q) {}
void fire()
@@ -1223,27 +983,27 @@ void Queue::tryAutoDelete(Broker& broker, Queue::shared_ptr queue)
if (queue->autoDeleteTimeout && queue->canAutoDelete()) {
AbsTime time(now(), Duration(queue->autoDeleteTimeout * TIME_SEC));
queue->autoDeleteTask = boost::intrusive_ptr<qpid::sys::TimerTask>(new AutoDeleteTask(broker, queue, time));
- broker.getClusterTimer().add(queue->autoDeleteTask);
+ broker.getClusterTimer().add(queue->autoDeleteTask);
QPID_LOG(debug, "Timed auto-delete for " << queue->getName() << " initiated");
} else {
tryAutoDeleteImpl(broker, queue);
}
}
-bool Queue::isExclusiveOwner(const OwnershipToken* const o) const
-{
+bool Queue::isExclusiveOwner(const OwnershipToken* const o) const
+{
Mutex::ScopedLock locker(ownershipLock);
- return o == owner;
+ return o == owner;
}
-void Queue::releaseExclusiveOwnership()
-{
+void Queue::releaseExclusiveOwnership()
+{
Mutex::ScopedLock locker(ownershipLock);
- owner = 0;
+ owner = 0;
}
-bool Queue::setExclusiveOwner(const OwnershipToken* const o)
-{
+bool Queue::setExclusiveOwner(const OwnershipToken* const o)
+{
//reset auto deletion timer if necessary
if (autoDeleteTimeout && autoDeleteTask) {
autoDeleteTask->cancel();
@@ -1252,25 +1012,25 @@ bool Queue::setExclusiveOwner(const OwnershipToken* const o)
if (owner) {
return false;
} else {
- owner = o;
+ owner = o;
return true;
}
}
-bool Queue::hasExclusiveOwner() const
-{
+bool Queue::hasExclusiveOwner() const
+{
Mutex::ScopedLock locker(ownershipLock);
- return owner != 0;
+ return owner != 0;
}
-bool Queue::hasExclusiveConsumer() const
-{
- return exclusive;
+bool Queue::hasExclusiveConsumer() const
+{
+ return exclusive;
}
void Queue::setExternalQueueStore(ExternalQueueStore* inst) {
- if (externalQueueStore!=inst && externalQueueStore)
- delete externalQueueStore;
+ if (externalQueueStore!=inst && externalQueueStore)
+ delete externalQueueStore;
externalQueueStore = inst;
if (inst) {
@@ -1295,7 +1055,7 @@ Manageable::status_t Queue::ManagementMethod (uint32_t methodId, Args& args, str
case _qmf::Queue::METHOD_PURGE :
{
_qmf::ArgsQueuePurge& purgeArgs = (_qmf::ArgsQueuePurge&) args;
- purge(purgeArgs.i_request, boost::shared_ptr<Exchange>(), &purgeArgs.i_filter);
+ purge(purgeArgs.i_request);
status = Manageable::STATUS_OK;
}
break;
@@ -1316,7 +1076,7 @@ Manageable::status_t Queue::ManagementMethod (uint32_t methodId, Args& args, str
}
}
- purge(rerouteArgs.i_request, dest, &rerouteArgs.i_filter);
+ purge(rerouteArgs.i_request, dest);
status = Manageable::STATUS_OK;
}
break;
@@ -1325,14 +1085,6 @@ Manageable::status_t Queue::ManagementMethod (uint32_t methodId, Args& args, str
return status;
}
-
-void Queue::query(qpid::types::Variant::Map& results) const
-{
- Mutex::ScopedLock locker(messageLock);
- /** @todo add any interesting queue state into results */
- if (allocator) allocator->query(results);
-}
-
void Queue::setPosition(SequenceNumber n) {
Mutex::ScopedLock locker(messageLock);
sequence = n;
@@ -1367,10 +1119,7 @@ void Queue::insertSequenceNumbers(const std::string& key)
QPID_LOG(debug, "Inserting sequence numbers as " << key);
}
-/** updates queue observers and state when a message has become available for transfer,
- * expects messageLock to be held
- */
-void Queue::observeEnqueue(const QueuedMessage& m, const Mutex::ScopedLock&)
+void Queue::enqueued(const QueuedMessage& m)
{
for (Observers::iterator i = observers.begin(); i != observers.end(); ++i) {
try {
@@ -1393,8 +1142,7 @@ void Queue::updateEnqueued(const QueuedMessage& m)
if (policy.get()) {
policy->recoverEnqueued(payload);
}
- Mutex::ScopedLock locker(messageLock);
- observeEnqueue(m, locker);
+ enqueued(m);
} else {
QPID_LOG(warning, "Queue informed of enqueued message that has no payload");
}
@@ -1418,7 +1166,6 @@ void Queue::checkNotDeleted()
void Queue::addObserver(boost::shared_ptr<QueueObserver> observer)
{
- Mutex::ScopedLock locker(messageLock);
observers.insert(observer);
}
@@ -1428,32 +1175,6 @@ void Queue::flush()
if (u.acquired && store) store->flush(*this);
}
-
-bool Queue::bind(boost::shared_ptr<Exchange> exchange, const std::string& key,
- const qpid::framing::FieldTable& arguments)
-{
- if (exchange->bind(shared_from_this(), key, &arguments)) {
- bound(exchange->getName(), key, arguments);
- if (exchange->isDurable() && isDurable()) {
- store->bind(*exchange, *this, key, arguments);
- }
- return true;
- } else {
- return false;
- }
-}
-
-
-const Broker* Queue::getBroker()
-{
- return broker;
-}
-
-void Queue::setDequeueSincePurge(uint32_t value) {
- dequeueSincePurge = value;
-}
-
-
Queue::UsageBarrier::UsageBarrier(Queue& q) : parent(q), count(0) {}
bool Queue::UsageBarrier::acquire()
diff --git a/cpp/src/qpid/broker/Queue.h b/cpp/src/qpid/broker/Queue.h
index 59ae41e768..12a3d273be 100644
--- a/cpp/src/qpid/broker/Queue.h
+++ b/cpp/src/qpid/broker/Queue.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -32,9 +32,9 @@
#include "qpid/broker/QueueBindings.h"
#include "qpid/broker/QueueListeners.h"
#include "qpid/broker/QueueObserver.h"
+#include "qpid/broker/RateTracker.h"
#include "qpid/framing/FieldTable.h"
-#include "qpid/sys/AtomicValue.h"
#include "qpid/sys/Monitor.h"
#include "qpid/sys/Timer.h"
#include "qpid/management/Manageable.h"
@@ -59,7 +59,7 @@ class MessageStore;
class QueueEvents;
class QueueRegistry;
class TransactionContext;
-class MessageDistributor;
+class Exchange;
/**
* The brokers representation of an amqp queue. Messages are
@@ -74,13 +74,13 @@ class Queue : public boost::enable_shared_from_this<Queue>,
{
Queue& parent;
uint count;
-
+
UsageBarrier(Queue&);
bool acquire();
void release();
void destroy();
};
-
+
struct ScopedUse
{
UsageBarrier& barrier;
@@ -88,7 +88,7 @@ class Queue : public boost::enable_shared_from_this<Queue>,
ScopedUse(UsageBarrier& b) : barrier(b), acquired(barrier.acquire()) {}
~ScopedUse() { if (acquired) barrier.release(); }
};
-
+
typedef std::set< boost::shared_ptr<QueueObserver> > Observers;
enum ConsumeCode {NO_MESSAGES=0, CANT_CONSUME=1, CONSUMED=2};
@@ -119,7 +119,7 @@ class Queue : public boost::enable_shared_from_this<Queue>,
boost::shared_ptr<Exchange> alternateExchange;
framing::SequenceNumber sequence;
qmf::org::apache::qpid::broker::Queue* mgmtObject;
- sys::AtomicValue<uint32_t> dequeueSincePurge; // Count dequeues since last purge.
+ RateTracker dequeueTracker;
int eventMode;
Observers observers;
bool insertSeqNo;
@@ -129,36 +129,26 @@ class Queue : public boost::enable_shared_from_this<Queue>,
UsageBarrier barrier;
int autoDeleteTimeout;
boost::intrusive_ptr<qpid::sys::TimerTask> autoDeleteTask;
- boost::shared_ptr<MessageDistributor> allocator;
void push(boost::intrusive_ptr<Message>& msg, bool isRecovery=false);
void setPolicy(std::auto_ptr<QueuePolicy> policy);
- bool getNextMessage(QueuedMessage& msg, Consumer::shared_ptr& c);
- ConsumeCode consumeNextMessage(QueuedMessage& msg, Consumer::shared_ptr& c);
- bool browseNextMessage(QueuedMessage& msg, Consumer::shared_ptr& c);
+ bool seek(QueuedMessage& msg, Consumer::shared_ptr position);
+ bool getNextMessage(QueuedMessage& msg, Consumer::shared_ptr c);
+ ConsumeCode consumeNextMessage(QueuedMessage& msg, Consumer::shared_ptr c);
+ bool browseNextMessage(QueuedMessage& msg, Consumer::shared_ptr c);
void notifyListener();
void removeListener(Consumer::shared_ptr);
bool isExcluded(boost::intrusive_ptr<Message>& msg);
- /** update queue observers, stats, policy, etc when the messages' state changes. Lock
- * must be held by caller */
- void observeEnqueue(const QueuedMessage& msg, const sys::Mutex::ScopedLock& lock);
- void observeAcquire(const QueuedMessage& msg, const sys::Mutex::ScopedLock& lock);
- void observeRequeue(const QueuedMessage& msg, const sys::Mutex::ScopedLock& lock);
- void observeDequeue(const QueuedMessage& msg, const sys::Mutex::ScopedLock& lock);
-
- /** modify the Queue's message container - assumes messageLock held */
- void pop(const sys::Mutex::ScopedLock& held); // acquire front msg
- void popAndDequeue(const sys::Mutex::ScopedLock& held); // acquire and dequeue front msg
- // acquire message @ position, return true and set msg if acquire succeeds
- bool acquire(const qpid::framing::SequenceNumber& position, QueuedMessage& msg,
- const sys::Mutex::ScopedLock& held);
-
+ void enqueued(const QueuedMessage& msg);
+ void dequeued(const QueuedMessage& msg);
+ void pop();
+ void popAndDequeue();
+ QueuedMessage getFront();
void forcePersistent(QueuedMessage& msg);
int getEventMode();
- void configureImpl(const qpid::framing::FieldTable& settings);
inline void mgntEnqStats(const boost::intrusive_ptr<Message>& msg)
{
@@ -182,9 +172,8 @@ class Queue : public boost::enable_shared_from_this<Queue>,
}
}
}
-
+
void checkNotDeleted();
- void notifyDeleted();
public:
@@ -193,50 +182,29 @@ class Queue : public boost::enable_shared_from_this<Queue>,
typedef std::vector<shared_ptr> vector;
QPID_BROKER_EXTERN Queue(const std::string& name,
- bool autodelete = false,
- MessageStore* const store = 0,
+ bool autodelete = false,
+ MessageStore* const store = 0,
const OwnershipToken* const owner = 0,
management::Manageable* parent = 0,
Broker* broker = 0);
QPID_BROKER_EXTERN ~Queue();
- /** allow the Consumer to consume or browse the next available message */
QPID_BROKER_EXTERN bool dispatch(Consumer::shared_ptr);
- /** allow the Consumer to acquire a message that it has browsed.
- * @param msg - message to be acquired.
- * @return false if message is no longer available for acquire.
- */
- QPID_BROKER_EXTERN bool acquire(const QueuedMessage& msg, const std::string& consumer);
+ void create(const qpid::framing::FieldTable& settings);
- /**
- * Used to configure a new queue and create a persistent record
- * for it in store if required.
- */
- QPID_BROKER_EXTERN void create(const qpid::framing::FieldTable& settings);
-
- /**
- * Used to reconfigure a recovered queue (does not create
- * persistent record in store).
- */
- QPID_BROKER_EXTERN void configure(const qpid::framing::FieldTable& settings);
- void destroyed();
+ // "recovering" means we are doing a MessageStore recovery.
+ QPID_BROKER_EXTERN void configure(const qpid::framing::FieldTable& settings,
+ bool recovering = false);
+ void destroy();
+ void notifyDeleted();
QPID_BROKER_EXTERN void bound(const std::string& exchange,
const std::string& key,
const qpid::framing::FieldTable& args);
- //TODO: get unbind out of the public interface; only there for purposes of one unit test
- QPID_BROKER_EXTERN void unbind(ExchangeRegistry& exchanges);
- /**
- * Bind self to specified exchange, and record that binding for unbinding on delete.
- */
- bool bind(boost::shared_ptr<Exchange> exchange, const std::string& key,
- const qpid::framing::FieldTable& arguments=qpid::framing::FieldTable());
+ QPID_BROKER_EXTERN void unbind(ExchangeRegistry& exchanges,
+ Queue::shared_ptr shared_ref);
- /** Acquire the message at the given position if it is available for acquire. Not to
- * be used by clients, but used by the broker for queue management.
- * @param message - set to the acquired message if true returned.
- * @return true if the message has been acquired.
- */
+ QPID_BROKER_EXTERN bool acquire(const QueuedMessage& msg);
QPID_BROKER_EXTERN bool acquireMessageAt(const qpid::framing::SequenceNumber& position, QueuedMessage& message);
/**
@@ -265,14 +233,11 @@ class Queue : public boost::enable_shared_from_this<Queue>,
bool exclusive = false);
QPID_BROKER_EXTERN void cancel(Consumer::shared_ptr c);
- uint32_t purge(const uint32_t purge_request=0, //defaults to all messages
- boost::shared_ptr<Exchange> dest=boost::shared_ptr<Exchange>(),
- const ::qpid::types::Variant::Map *filter=0);
- QPID_BROKER_EXTERN void purgeExpired(sys::Duration);
+ uint32_t purge(const uint32_t purge_request=0, boost::shared_ptr<Exchange> dest=boost::shared_ptr<Exchange>()); //defaults to all messages
+ QPID_BROKER_EXTERN void purgeExpired();
//move qty # of messages to destination Queue destq
- uint32_t move(const Queue::shared_ptr destq, uint32_t qty,
- const qpid::types::Variant::Map *filter=0);
+ uint32_t move(const Queue::shared_ptr destq, uint32_t qty);
QPID_BROKER_EXTERN uint32_t getMessageCount() const;
QPID_BROKER_EXTERN uint32_t getEnqueueCompleteMessageCount() const;
@@ -311,8 +276,8 @@ class Queue : public boost::enable_shared_from_this<Queue>,
* Inform queue of messages that were enqueued, have since
* been acquired but not yet accepted or released (and
* thus are still logically on the queue) - used in
- * clustered broker.
- */
+ * clustered broker.
+ */
void updateEnqueued(const QueuedMessage& msg);
/**
@@ -323,14 +288,14 @@ class Queue : public boost::enable_shared_from_this<Queue>,
* accepted it).
*/
bool isEnqueued(const QueuedMessage& msg);
-
+
/**
- * Acquires the next available (oldest) message
+ * Gets the next available message
*/
QPID_BROKER_EXTERN QueuedMessage get();
- /** Get the message at position pos, returns true if found and sets msg */
- QPID_BROKER_EXTERN bool find(framing::SequenceNumber pos, QueuedMessage& msg ) const;
+ /** Get the message at position pos */
+ QPID_BROKER_EXTERN QueuedMessage find(framing::SequenceNumber pos) const;
const QueuePolicy* getPolicy();
@@ -344,13 +309,8 @@ class Queue : public boost::enable_shared_from_this<Queue>,
void encode(framing::Buffer& buffer) const;
uint32_t encodedSize() const;
- /**
- * Restores a queue from encoded data (used in recovery)
- *
- * Note: restored queue will be neither auto-deleted or have an
- * exclusive owner
- */
- static Queue::shared_ptr restore(QueueRegistry& queues, framing::Buffer& buffer);
+ // "recovering" means we are doing a MessageStore recovery.
+ static Queue::shared_ptr decode(QueueRegistry& queues, framing::Buffer& buffer, bool recovering = false );
static void tryAutoDelete(Broker& broker, Queue::shared_ptr);
virtual void setExternalQueueStore(ExternalQueueStore* inst);
@@ -359,7 +319,6 @@ class Queue : public boost::enable_shared_from_this<Queue>,
management::ManagementObject* GetManagementObject (void) const;
management::Manageable::status_t
ManagementMethod (uint32_t methodId, management::Args& args, std::string& text);
- void query(::qpid::types::Variant::Map&) const;
/** Apply f to each Message on the queue. */
template <class F> void eachMessage(F f) {
@@ -372,11 +331,6 @@ class Queue : public boost::enable_shared_from_this<Queue>,
bindings.eachBinding(f);
}
- /** Apply f to each Observer on the queue */
- template <class F> void eachObserver(F f) {
- std::for_each<Observers::iterator, F>(observers.begin(), observers.end(), f);
- }
-
/** Set the position sequence number for the next message on the queue.
* Must be >= the current sequence number.
* Used by cluster to replicate queues.
@@ -404,11 +358,6 @@ class Queue : public boost::enable_shared_from_this<Queue>,
void recoverPrepared(boost::intrusive_ptr<Message>& msg);
void flush();
-
- const Broker* getBroker();
-
- uint32_t getDequeueSincePurge() { return dequeueSincePurge.get(); }
- void setDequeueSincePurge(uint32_t value);
};
}
}
diff --git a/cpp/src/qpid/broker/QueueCleaner.cpp b/cpp/src/qpid/broker/QueueCleaner.cpp
index 838bc28be8..3499ea8a4d 100644
--- a/cpp/src/qpid/broker/QueueCleaner.cpp
+++ b/cpp/src/qpid/broker/QueueCleaner.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -27,7 +27,7 @@
namespace qpid {
namespace broker {
-QueueCleaner::QueueCleaner(QueueRegistry& q, sys::Timer* t) : queues(q), timer(t) {}
+QueueCleaner::QueueCleaner(QueueRegistry& q, sys::Timer& t) : queues(q), timer(t) {}
QueueCleaner::~QueueCleaner()
{
@@ -36,16 +36,10 @@ QueueCleaner::~QueueCleaner()
void QueueCleaner::start(qpid::sys::Duration p)
{
- period = p;
task = new Task(*this, p);
- timer->add(task);
+ timer.add(task);
}
-void QueueCleaner::setTimer(qpid::sys::Timer* timer) {
- this->timer = timer;
-}
-
-
QueueCleaner::Task::Task(QueueCleaner& p, qpid::sys::Duration d) : sys::TimerTask(d,"QueueCleaner"), parent(p) {}
void QueueCleaner::Task::fire()
@@ -71,9 +65,9 @@ void QueueCleaner::fired()
std::vector<Queue::shared_ptr> copy;
CollectQueues collect(&copy);
queues.eachQueue(collect);
- std::for_each(copy.begin(), copy.end(), boost::bind(&Queue::purgeExpired, _1, period));
+ std::for_each(copy.begin(), copy.end(), boost::bind(&Queue::purgeExpired, _1));
task->setupNextFire();
- timer->add(task);
+ timer.add(task);
}
diff --git a/cpp/src/qpid/broker/QueueCleaner.h b/cpp/src/qpid/broker/QueueCleaner.h
index ffebfe3e1b..11c2d180ac 100644
--- a/cpp/src/qpid/broker/QueueCleaner.h
+++ b/cpp/src/qpid/broker/QueueCleaner.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -35,15 +35,14 @@ class QueueRegistry;
class QueueCleaner
{
public:
- QPID_BROKER_EXTERN QueueCleaner(QueueRegistry& queues, sys::Timer* timer);
+ QPID_BROKER_EXTERN QueueCleaner(QueueRegistry& queues, sys::Timer& timer);
QPID_BROKER_EXTERN ~QueueCleaner();
- QPID_BROKER_EXTERN void start(sys::Duration period);
- QPID_BROKER_EXTERN void setTimer(sys::Timer* timer);
+ QPID_BROKER_EXTERN void start(qpid::sys::Duration period);
private:
class Task : public sys::TimerTask
{
public:
- Task(QueueCleaner& parent, sys::Duration duration);
+ Task(QueueCleaner& parent, qpid::sys::Duration duration);
void fire();
private:
QueueCleaner& parent;
@@ -51,8 +50,7 @@ class QueueCleaner
boost::intrusive_ptr<sys::TimerTask> task;
QueueRegistry& queues;
- sys::Timer* timer;
- sys::Duration period;
+ sys::Timer& timer;
void fired();
};
diff --git a/cpp/src/qpid/broker/QueueEvents.cpp b/cpp/src/qpid/broker/QueueEvents.cpp
index c66bdabf0f..2c540ff1ad 100644
--- a/cpp/src/qpid/broker/QueueEvents.cpp
+++ b/cpp/src/qpid/broker/QueueEvents.cpp
@@ -129,10 +129,6 @@ class EventGenerator : public QueueObserver
{
if (!enqueueOnly) manager.dequeued(m);
}
-
- void acquired(const QueuedMessage&) {};
- void requeued(const QueuedMessage&) {};
-
private:
QueueEvents& manager;
const bool enqueueOnly;
diff --git a/cpp/src/qpid/broker/QueueFlowLimit.cpp b/cpp/src/qpid/broker/QueueFlowLimit.cpp
deleted file mode 100644
index f15bb45c01..0000000000
--- a/cpp/src/qpid/broker/QueueFlowLimit.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-#include "qpid/broker/QueueFlowLimit.h"
-#include "qpid/broker/Broker.h"
-#include "qpid/broker/Queue.h"
-#include "qpid/Exception.h"
-#include "qpid/framing/FieldValue.h"
-#include "qpid/framing/reply_exceptions.h"
-#include "qpid/log/Statement.h"
-#include "qpid/sys/Mutex.h"
-#include "qpid/broker/SessionState.h"
-#include "qpid/sys/ClusterSafe.h"
-
-#include "qmf/org/apache/qpid/broker/Queue.h"
-
-#include <sstream>
-
-using namespace qpid::broker;
-using namespace qpid::framing;
-
-namespace {
- /** ensure that the configured flow control stop and resume values are
- * valid with respect to the maximum queue capacity, and each other
- */
- template <typename T>
- void validateFlowConfig(T max, T& stop, T& resume, const std::string& type, const std::string& queue)
- {
- if (resume > stop) {
- throw InvalidArgumentException(QPID_MSG("Queue \"" << queue << "\": qpid.flow_resume_" << type
- << "=" << resume
- << " must be less than qpid.flow_stop_" << type
- << "=" << stop));
- }
- if (resume == 0) resume = stop;
- if (max != 0 && (max < stop)) {
- throw InvalidArgumentException(QPID_MSG("Queue \"" << queue << "\": qpid.flow_stop_" << type
- << "=" << stop
- << " must be less than qpid.max_" << type
- << "=" << max));
- }
- }
-
- /** extract a capacity value as passed in an argument map
- */
- uint64_t getCapacity(const FieldTable& settings, const std::string& key, uint64_t defaultValue)
- {
- FieldTable::ValuePtr v = settings.get(key);
-
- int64_t result = 0;
-
- if (!v) return defaultValue;
- if (v->getType() == 0x23) {
- QPID_LOG(debug, "Value for " << key << " specified as float: " << v->get<float>());
- } else if (v->getType() == 0x33) {
- QPID_LOG(debug, "Value for " << key << " specified as double: " << v->get<double>());
- } else if (v->convertsTo<int64_t>()) {
- result = v->get<int64_t>();
- QPID_LOG(debug, "Got integer value for " << key << ": " << result);
- if (result >= 0) return result;
- } else if (v->convertsTo<string>()) {
- string s(v->get<string>());
- QPID_LOG(debug, "Got string value for " << key << ": " << s);
- std::istringstream convert(s);
- if (convert >> result && result >= 0) return result;
- }
-
- QPID_LOG(warning, "Cannot convert " << key << " to unsigned integer, using default (" << defaultValue << ")");
- return defaultValue;
- }
-}
-
-
-
-QueueFlowLimit::QueueFlowLimit(Queue *_queue,
- uint32_t _flowStopCount, uint32_t _flowResumeCount,
- uint64_t _flowStopSize, uint64_t _flowResumeSize)
- : StatefulQueueObserver(std::string("QueueFlowLimit")), queue(_queue), queueName("<unknown>"),
- flowStopCount(_flowStopCount), flowResumeCount(_flowResumeCount),
- flowStopSize(_flowStopSize), flowResumeSize(_flowResumeSize),
- flowStopped(false), count(0), size(0), queueMgmtObj(0), broker(0)
-{
- uint32_t maxCount(0);
- uint64_t maxSize(0);
-
- if (queue) {
- queueName = _queue->getName();
- if (queue->getPolicy()) {
- maxSize = _queue->getPolicy()->getMaxSize();
- maxCount = _queue->getPolicy()->getMaxCount();
- }
- broker = queue->getBroker();
- queueMgmtObj = dynamic_cast<_qmfBroker::Queue*> (queue->GetManagementObject());
- if (queueMgmtObj) {
- queueMgmtObj->set_flowStopped(isFlowControlActive());
- }
- }
- validateFlowConfig( maxCount, flowStopCount, flowResumeCount, "count", queueName );
- validateFlowConfig( maxSize, flowStopSize, flowResumeSize, "size", queueName );
- QPID_LOG(info, "Queue \"" << queueName << "\": Flow limit created: flowStopCount=" << flowStopCount
- << ", flowResumeCount=" << flowResumeCount
- << ", flowStopSize=" << flowStopSize << ", flowResumeSize=" << flowResumeSize );
-}
-
-
-QueueFlowLimit::~QueueFlowLimit()
-{
- sys::Mutex::ScopedLock l(indexLock);
- if (!index.empty()) {
- // we're gone - release all pending msgs
- for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.begin();
- itr != index.end(); ++itr)
- if (itr->second)
- try {
- itr->second->getIngressCompletion().finishCompleter();
- } catch (...) {} // ignore - not safe for a destructor to throw.
- index.clear();
- }
-}
-
-
-void QueueFlowLimit::enqueued(const QueuedMessage& msg)
-{
- sys::Mutex::ScopedLock l(indexLock);
-
- ++count;
- size += msg.payload->contentSize();
-
- if (!flowStopped) {
- if (flowStopCount && count > flowStopCount) {
- flowStopped = true;
- QPID_LOG(info, "Queue \"" << queueName << "\": has reached " << flowStopCount << " enqueued messages. Producer flow control activated." );
- } else if (flowStopSize && size > flowStopSize) {
- flowStopped = true;
- QPID_LOG(info, "Queue \"" << queueName << "\": has reached " << flowStopSize << " enqueued bytes. Producer flow control activated." );
- }
- if (flowStopped && queueMgmtObj) {
- queueMgmtObj->set_flowStopped(true);
- queueMgmtObj->inc_flowStoppedCount();
- }
- }
-
- if (flowStopped || !index.empty()) {
- // ignore flow control if we are populating the queue due to cluster replication:
- if (broker && broker->isClusterUpdatee()) {
- QPID_LOG(trace, "Queue \"" << queueName << "\": ignoring flow control for msg pos=" << msg.position);
- return;
- }
- QPID_LOG(trace, "Queue \"" << queueName << "\": setting flow control for msg pos=" << msg.position);
- msg.payload->getIngressCompletion().startCompleter(); // don't complete until flow resumes
- bool unique;
- unique = index.insert(std::pair<framing::SequenceNumber, boost::intrusive_ptr<Message> >(msg.position, msg.payload)).second;
- // Like this to avoid tripping up unused variable warning when NDEBUG set
- if (!unique) assert(unique);
- }
-}
-
-
-
-void QueueFlowLimit::dequeued(const QueuedMessage& msg)
-{
- sys::Mutex::ScopedLock l(indexLock);
-
- if (count > 0) {
- --count;
- } else {
- throw Exception(QPID_MSG("Flow limit count underflow on dequeue. Queue=" << queueName));
- }
-
- uint64_t _size = msg.payload->contentSize();
- if (_size <= size) {
- size -= _size;
- } else {
- throw Exception(QPID_MSG("Flow limit size underflow on dequeue. Queue=" << queueName));
- }
-
- if (flowStopped &&
- (flowResumeSize == 0 || size < flowResumeSize) &&
- (flowResumeCount == 0 || count < flowResumeCount)) {
- flowStopped = false;
- if (queueMgmtObj)
- queueMgmtObj->set_flowStopped(false);
- QPID_LOG(info, "Queue \"" << queueName << "\": has drained below the flow control resume level. Producer flow control deactivated." );
- }
-
- if (!index.empty()) {
- if (!flowStopped) {
- // flow enabled - release all pending msgs
- for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.begin();
- itr != index.end(); ++itr)
- if (itr->second)
- itr->second->getIngressCompletion().finishCompleter();
- index.clear();
- } else {
- // even if flow controlled, we must release this msg as it is being dequeued
- std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.find(msg.position);
- if (itr != index.end()) { // this msg is flow controlled, release it:
- msg.payload->getIngressCompletion().finishCompleter();
- index.erase(itr);
- }
- }
- }
-}
-
-
-void QueueFlowLimit::encode(Buffer& buffer) const
-{
- buffer.putLong(flowStopCount);
- buffer.putLong(flowResumeCount);
- buffer.putLongLong(flowStopSize);
- buffer.putLongLong(flowResumeSize);
- buffer.putLong(count);
- buffer.putLongLong(size);
-}
-
-
-void QueueFlowLimit::decode ( Buffer& buffer )
-{
- flowStopCount = buffer.getLong();
- flowResumeCount = buffer.getLong();
- flowStopSize = buffer.getLongLong();
- flowResumeSize = buffer.getLongLong();
- count = buffer.getLong();
- size = buffer.getLongLong();
-}
-
-
-uint32_t QueueFlowLimit::encodedSize() const {
- return sizeof(uint32_t) + // flowStopCount
- sizeof(uint32_t) + // flowResumecount
- sizeof(uint64_t) + // flowStopSize
- sizeof(uint64_t) + // flowResumeSize
- sizeof(uint32_t) + // count
- sizeof(uint64_t); // size
-}
-
-
-const std::string QueueFlowLimit::flowStopCountKey("qpid.flow_stop_count");
-const std::string QueueFlowLimit::flowResumeCountKey("qpid.flow_resume_count");
-const std::string QueueFlowLimit::flowStopSizeKey("qpid.flow_stop_size");
-const std::string QueueFlowLimit::flowResumeSizeKey("qpid.flow_resume_size");
-uint64_t QueueFlowLimit::defaultMaxSize;
-uint QueueFlowLimit::defaultFlowStopRatio;
-uint QueueFlowLimit::defaultFlowResumeRatio;
-
-
-void QueueFlowLimit::setDefaults(uint64_t maxQueueSize, uint flowStopRatio, uint flowResumeRatio)
-{
- defaultMaxSize = maxQueueSize;
- defaultFlowStopRatio = flowStopRatio;
- defaultFlowResumeRatio = flowResumeRatio;
-
- /** @todo KAG: Verify valid range on Broker::Options instead of here */
- if (flowStopRatio > 100 || flowResumeRatio > 100)
- throw InvalidArgumentException(QPID_MSG("Default queue flow ratios must be between 0 and 100, inclusive:"
- << " flowStopRatio=" << flowStopRatio
- << " flowResumeRatio=" << flowResumeRatio));
- if (flowResumeRatio > flowStopRatio)
- throw InvalidArgumentException(QPID_MSG("Default queue flow stop ratio must be >= flow resume ratio:"
- << " flowStopRatio=" << flowStopRatio
- << " flowResumeRatio=" << flowResumeRatio));
-}
-
-
-void QueueFlowLimit::observe(Queue& queue, const qpid::framing::FieldTable& settings)
-{
- QueueFlowLimit *ptr = createLimit( &queue, settings );
- if (ptr) {
- boost::shared_ptr<QueueFlowLimit> observer(ptr);
- queue.addObserver(observer);
- }
-}
-
-/** returns ptr to a QueueFlowLimit, else 0 if no limit */
-QueueFlowLimit *QueueFlowLimit::createLimit(Queue *queue, const qpid::framing::FieldTable& settings)
-{
- std::string type(QueuePolicy::getType(settings));
-
- if (type == QueuePolicy::RING || type == QueuePolicy::RING_STRICT) {
- // The size of a RING queue is limited by design - no need for flow control.
- return 0;
- }
-
- if (settings.get(flowStopCountKey) || settings.get(flowStopSizeKey) ||
- settings.get(flowResumeCountKey) || settings.get(flowResumeSizeKey)) {
- // user provided (some) flow settings manually...
- uint32_t flowStopCount = getCapacity(settings, flowStopCountKey, 0);
- uint32_t flowResumeCount = getCapacity(settings, flowResumeCountKey, 0);
- uint64_t flowStopSize = getCapacity(settings, flowStopSizeKey, 0);
- uint64_t flowResumeSize = getCapacity(settings, flowResumeSizeKey, 0);
- if (flowStopCount == 0 && flowStopSize == 0) { // disable flow control
- return 0;
- }
- return new QueueFlowLimit(queue, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize);
- }
-
- if (defaultFlowStopRatio) { // broker has a default ratio setup...
- uint64_t maxByteCount = getCapacity(settings, QueuePolicy::maxSizeKey, defaultMaxSize);
- uint64_t flowStopSize = (uint64_t)(maxByteCount * (defaultFlowStopRatio/100.0) + 0.5);
- uint64_t flowResumeSize = (uint64_t)(maxByteCount * (defaultFlowResumeRatio/100.0));
- uint32_t maxMsgCount = getCapacity(settings, QueuePolicy::maxCountKey, 0); // no size by default
- uint32_t flowStopCount = (uint32_t)(maxMsgCount * (defaultFlowStopRatio/100.0) + 0.5);
- uint32_t flowResumeCount = (uint32_t)(maxMsgCount * (defaultFlowResumeRatio/100.0));
-
- return new QueueFlowLimit(queue, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize);
- }
- return 0;
-}
-
-/* Cluster replication */
-
-namespace {
- /** pack a set of sequence number ranges into a framing::Array */
- void buildSeqRangeArray(qpid::framing::Array *seqs,
- const qpid::framing::SequenceNumber& first,
- const qpid::framing::SequenceNumber& last)
- {
- seqs->push_back(qpid::framing::Array::ValuePtr(new Unsigned32Value(first)));
- seqs->push_back(qpid::framing::Array::ValuePtr(new Unsigned32Value(last)));
- }
-}
-
-/** Runs on UPDATER to snapshot current state */
-void QueueFlowLimit::getState(qpid::framing::FieldTable& state ) const
-{
- sys::Mutex::ScopedLock l(indexLock);
- state.clear();
-
- framing::SequenceSet ss;
- if (!index.empty()) {
- /* replicate the set of messages pending flow control */
- for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::const_iterator itr = index.begin();
- itr != index.end(); ++itr) {
- ss.add(itr->first);
- }
- framing::Array seqs(TYPE_CODE_UINT32);
- typedef boost::function<void(framing::SequenceNumber, framing::SequenceNumber)> arrayBuilder;
- ss.for_each((arrayBuilder)boost::bind(&buildSeqRangeArray, &seqs, _1, _2));
- state.setArray("pendingMsgSeqs", seqs);
- }
- QPID_LOG(debug, "Queue \"" << queueName << "\": flow limit replicating pending msgs, range=" << ss);
-}
-
-
-/** called on UPDATEE to set state from snapshot */
-void QueueFlowLimit::setState(const qpid::framing::FieldTable& state)
-{
- sys::Mutex::ScopedLock l(indexLock);
- index.clear();
-
- framing::SequenceSet fcmsg;
- framing::Array seqArray(TYPE_CODE_UINT32);
- if (state.getArray("pendingMsgSeqs", seqArray)) {
- assert((seqArray.count() & 0x01) == 0); // must be even since they are sequence ranges
- framing::Array::const_iterator i = seqArray.begin();
- while (i != seqArray.end()) {
- framing::SequenceNumber first((*i)->getIntegerValue<uint32_t, 4>());
- ++i;
- framing::SequenceNumber last((*i)->getIntegerValue<uint32_t, 4>());
- ++i;
- fcmsg.add(first, last);
- for (SequenceNumber seq = first; seq <= last; ++seq) {
- QueuedMessage msg;
- queue->find(seq, msg); // fyi: may not be found if msg is acquired & unacked
- bool unique;
- unique = index.insert(std::pair<framing::SequenceNumber, boost::intrusive_ptr<Message> >(seq, msg.payload)).second;
- // Like this to avoid tripping up unused variable warning when NDEBUG set
- if (!unique) assert(unique);
- }
- }
- }
-
- flowStopped = index.size() != 0;
- if (queueMgmtObj) {
- queueMgmtObj->set_flowStopped(isFlowControlActive());
- }
- QPID_LOG(debug, "Queue \"" << queueName << "\": flow limit replicated the pending msgs, range=" << fcmsg)
-}
-
-
-namespace qpid {
- namespace broker {
-
-std::ostream& operator<<(std::ostream& out, const QueueFlowLimit& f)
-{
- out << "; flowStopCount=" << f.flowStopCount << ", flowResumeCount=" << f.flowResumeCount;
- out << "; flowStopSize=" << f.flowStopSize << ", flowResumeSize=" << f.flowResumeSize;
- return out;
-}
-
- }
-}
-
diff --git a/cpp/src/qpid/broker/QueueFlowLimit.h b/cpp/src/qpid/broker/QueueFlowLimit.h
deleted file mode 100644
index ad8a2720ef..0000000000
--- a/cpp/src/qpid/broker/QueueFlowLimit.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-#ifndef _QueueFlowLimit_
-#define _QueueFlowLimit_
-
-#include <list>
-#include <set>
-#include <iostream>
-#include <memory>
-#include "qpid/broker/BrokerImportExport.h"
-#include "qpid/broker/QueuedMessage.h"
-#include "qpid/broker/StatefulQueueObserver.h"
-#include "qpid/framing/FieldTable.h"
-#include "qpid/sys/AtomicValue.h"
-#include "qpid/sys/Mutex.h"
-
-namespace qmf {
-namespace org {
-namespace apache {
-namespace qpid {
-namespace broker {
- class Queue;
-}}}}}
-namespace _qmfBroker = qmf::org::apache::qpid::broker;
-
-namespace qpid {
-namespace broker {
-
-class Broker;
-
-/**
- * Producer flow control: when level is > flowStop*, flow control is ON.
- * then level is < flowResume*, flow control is OFF. If == 0, flow control
- * is not used. If both byte and msg count thresholds are set, then
- * passing _either_ level may turn flow control ON, but _both_ must be
- * below level before flow control will be turned OFF.
- */
- class QueueFlowLimit : public StatefulQueueObserver
-{
- static uint64_t defaultMaxSize;
- static uint defaultFlowStopRatio;
- static uint defaultFlowResumeRatio;
-
- Queue *queue;
- std::string queueName;
-
- uint32_t flowStopCount;
- uint32_t flowResumeCount;
- uint64_t flowStopSize;
- uint64_t flowResumeSize;
- bool flowStopped; // true = producers held in flow control
-
- // current queue utilization
- uint32_t count;
- uint64_t size;
-
- public:
- static QPID_BROKER_EXTERN const std::string flowStopCountKey;
- static QPID_BROKER_EXTERN const std::string flowResumeCountKey;
- static QPID_BROKER_EXTERN const std::string flowStopSizeKey;
- static QPID_BROKER_EXTERN const std::string flowResumeSizeKey;
-
- QPID_BROKER_EXTERN virtual ~QueueFlowLimit();
-
- /** the queue has added QueuedMessage. Returns true if flow state changes */
- QPID_BROKER_EXTERN void enqueued(const QueuedMessage&);
- /** the queue has removed QueuedMessage. Returns true if flow state changes */
- QPID_BROKER_EXTERN void dequeued(const QueuedMessage&);
- /** ignored */
- QPID_BROKER_EXTERN void acquired(const QueuedMessage&) {};
- QPID_BROKER_EXTERN void requeued(const QueuedMessage&) {};
-
- /** for clustering: */
- QPID_BROKER_EXTERN void getState(qpid::framing::FieldTable&) const;
- QPID_BROKER_EXTERN void setState(const qpid::framing::FieldTable&);
-
- uint32_t getFlowStopCount() const { return flowStopCount; }
- uint32_t getFlowResumeCount() const { return flowResumeCount; }
- uint64_t getFlowStopSize() const { return flowStopSize; }
- uint64_t getFlowResumeSize() const { return flowResumeSize; }
-
- uint32_t getFlowCount() const { return count; }
- uint64_t getFlowSize() const { return size; }
- bool isFlowControlActive() const { return flowStopped; }
- bool monitorFlowControl() const { return flowStopCount || flowStopSize; }
-
- void encode(framing::Buffer& buffer) const;
- void decode(framing::Buffer& buffer);
- uint32_t encodedSize() const;
-
- static QPID_BROKER_EXTERN void observe(Queue& queue, const qpid::framing::FieldTable& settings);
- static QPID_BROKER_EXTERN void setDefaults(uint64_t defaultMaxSize, uint defaultFlowStopRatio, uint defaultFlowResumeRatio);
-
- friend QPID_BROKER_EXTERN std::ostream& operator<<(std::ostream&, const QueueFlowLimit&);
-
- protected:
- // msgs waiting for flow to become available.
- std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> > index;
- mutable qpid::sys::Mutex indexLock;
-
- _qmfBroker::Queue *queueMgmtObj;
-
- const Broker *broker;
-
- QPID_BROKER_EXTERN QueueFlowLimit(Queue *queue,
- uint32_t flowStopCount, uint32_t flowResumeCount,
- uint64_t flowStopSize, uint64_t flowResumeSize);
- static QPID_BROKER_EXTERN QueueFlowLimit *createLimit(Queue *queue, const qpid::framing::FieldTable& settings);
-};
-
-}}
-
-
-#endif
diff --git a/cpp/src/qpid/broker/QueueListeners.cpp b/cpp/src/qpid/broker/QueueListeners.cpp
index 591f4443bb..4d2c57d6b4 100644
--- a/cpp/src/qpid/broker/QueueListeners.cpp
+++ b/cpp/src/qpid/broker/QueueListeners.cpp
@@ -26,25 +26,19 @@ namespace broker {
void QueueListeners::addListener(Consumer::shared_ptr c)
{
- if (!c->inListeners) {
- if (c->acquires) {
- add(consumers, c);
- } else {
- add(browsers, c);
- }
- c->inListeners = true;
+ if (c->preAcquires()) {
+ add(consumers, c);
+ } else {
+ add(browsers, c);
}
}
void QueueListeners::removeListener(Consumer::shared_ptr c)
{
- if (c->inListeners) {
- if (c->acquires) {
- remove(consumers, c);
- } else {
- remove(browsers, c);
- }
- c->inListeners = false;
+ if (c->preAcquires()) {
+ remove(consumers, c);
+ } else {
+ remove(browsers, c);
}
}
@@ -52,20 +46,18 @@ void QueueListeners::populate(NotificationSet& set)
{
if (consumers.size()) {
set.consumer = consumers.front();
- consumers.pop_front();
- set.consumer->inListeners = false;
+ consumers.erase(consumers.begin());
} else {
- // Don't swap the deques, hang on to the memory allocated.
+ // Don't swap the vectors, hang on to the memory allocated.
set.browsers = browsers;
browsers.clear();
- for (Listeners::iterator i = set.browsers.begin(); i != set.browsers.end(); i++)
- (*i)->inListeners = false;
}
}
void QueueListeners::add(Listeners& listeners, Consumer::shared_ptr c)
{
- listeners.push_back(c);
+ Listeners::iterator i = std::find(listeners.begin(), listeners.end(), c);
+ if (i == listeners.end()) listeners.push_back(c);
}
void QueueListeners::remove(Listeners& listeners, Consumer::shared_ptr c)
@@ -81,7 +73,9 @@ void QueueListeners::NotificationSet::notify()
}
bool QueueListeners::contains(Consumer::shared_ptr c) const {
- return c->inListeners;
+ return
+ std::find(browsers.begin(), browsers.end(), c) != browsers.end() ||
+ std::find(consumers.begin(), consumers.end(), c) != consumers.end();
}
void QueueListeners::ListenerSet::notifyAll()
diff --git a/cpp/src/qpid/broker/QueueListeners.h b/cpp/src/qpid/broker/QueueListeners.h
index 0659499253..59d1c84ca4 100644
--- a/cpp/src/qpid/broker/QueueListeners.h
+++ b/cpp/src/qpid/broker/QueueListeners.h
@@ -22,7 +22,7 @@
*
*/
#include "qpid/broker/Consumer.h"
-#include <deque>
+#include <vector>
namespace qpid {
namespace broker {
@@ -40,7 +40,7 @@ namespace broker {
class QueueListeners
{
public:
- typedef std::deque<Consumer::shared_ptr> Listeners;
+ typedef std::vector<Consumer::shared_ptr> Listeners;
class NotificationSet
{
diff --git a/cpp/src/qpid/broker/QueueObserver.h b/cpp/src/qpid/broker/QueueObserver.h
index b58becd2ae..a711213dee 100644
--- a/cpp/src/qpid/broker/QueueObserver.h
+++ b/cpp/src/qpid/broker/QueueObserver.h
@@ -24,52 +24,18 @@
namespace qpid {
namespace broker {
-struct QueuedMessage;
-class Consumer;
-
+class QueuedMessage;
/**
- * Interface for notifying classes who want to act as 'observers' of a queue of particular
- * events.
- *
- * The events that are monitored reflect the relationship between a particular message and
- * the queue it has been delivered to. A message can be considered in one of three states
- * with respect to the queue:
- *
- * 1) "Available" - available for transfer to consumers (i.e. for browse or acquire),
- *
- * 2) "Acquired" - owned by a particular consumer, no longer available to other consumers
- * (by either browse or acquire), but still considered on the queue.
- *
- * 3) "Dequeued" - removed from the queue and no longer available to any consumer.
- *
- * The queue events that are observable are:
- *
- * "Enqueued" - the message is "Available" - on the queue for transfer to any consumer
- * (e.g. browse or acquire)
- *
- * "Acquired" - - a consumer has claimed exclusive access to it. It is no longer available
- * for other consumers to browse or acquire, but it is not yet considered dequeued as it
- * may be requeued by the consumer.
- *
- * "Requeued" - a previously-acquired message is released by its owner: it is put back on
- * the queue at its original position and returns to the "Available" state.
- *
- * "Dequeued" - a message is no longer queued. At this point, the queue no longer tracks
- * the message, and the broker considers the consumer's transaction complete.
+ * Interface for notifying classes who want to act as 'observers' of a
+ * queue of particular events.
*/
class QueueObserver
{
public:
virtual ~QueueObserver() {}
-
- // note: the Queue will hold the messageLock while calling these methods!
virtual void enqueued(const QueuedMessage&) = 0;
virtual void dequeued(const QueuedMessage&) = 0;
- virtual void acquired(const QueuedMessage&) = 0;
- virtual void requeued(const QueuedMessage&) = 0;
- virtual void consumerAdded( const Consumer& ) {};
- virtual void consumerRemoved( const Consumer& ) {};
- private:
+ private:
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/QueuePolicy.cpp b/cpp/src/qpid/broker/QueuePolicy.cpp
index 0c245700af..4168221ad0 100644
--- a/cpp/src/qpid/broker/QueuePolicy.cpp
+++ b/cpp/src/qpid/broker/QueuePolicy.cpp
@@ -117,30 +117,30 @@ void QueuePolicy::update(FieldTable& settings)
settings.setString(typeKey, type);
}
-template <typename T>
-T getCapacity(const FieldTable& settings, const std::string& key, T defaultValue)
+uint32_t QueuePolicy::getCapacity(const FieldTable& settings, const std::string& key, uint32_t defaultValue)
{
FieldTable::ValuePtr v = settings.get(key);
- T result = 0;
+ int32_t result = 0;
if (!v) return defaultValue;
if (v->getType() == 0x23) {
QPID_LOG(debug, "Value for " << key << " specified as float: " << v->get<float>());
} else if (v->getType() == 0x33) {
QPID_LOG(debug, "Value for " << key << " specified as double: " << v->get<double>());
- } else if (v->convertsTo<T>()) {
- result = v->get<T>();
+ } else if (v->convertsTo<int>()) {
+ result = v->get<int>();
QPID_LOG(debug, "Got integer value for " << key << ": " << result);
if (result >= 0) return result;
} else if (v->convertsTo<string>()) {
string s(v->get<string>());
QPID_LOG(debug, "Got string value for " << key << ": " << s);
std::istringstream convert(s);
- if (convert >> result && result >= 0 && convert.eof()) return result;
+ if (convert >> result && result >= 0) return result;
}
- throw IllegalArgumentException(QPID_MSG("Cannot convert " << key << " to unsigned integer: " << *v));
+ QPID_LOG(warning, "Cannot convert " << key << " to unsigned integer, using default (" << defaultValue << ")");
+ return defaultValue;
}
std::string QueuePolicy::getType(const FieldTable& settings)
@@ -247,7 +247,7 @@ bool RingQueuePolicy::checkLimit(boost::intrusive_ptr<Message> m)
{
// If the message is bigger than the queue size, give up
- if (getMaxSize() && m->contentSize() > getMaxSize()) {
+ if (m->contentSize() > getMaxSize()) {
QPID_LOG(debug, "Message too large for ring queue " << name
<< " [" << *this << "] "
<< ": message size = " << m->contentSize() << " bytes"
@@ -269,7 +269,8 @@ bool RingQueuePolicy::checkLimit(boost::intrusive_ptr<Message> m)
do {
QueuedMessage oldest = queue.front();
- if (oldest.queue->acquireMessageAt(oldest.position, oldest) || !strict) {
+
+ if (oldest.queue->acquire(oldest) || !strict) {
queue.pop_front();
pendingDequeues.push_back(oldest);
QPID_LOG(debug, "Ring policy triggered in " << name
@@ -319,8 +320,8 @@ std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const qpid::framing::F
std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const std::string& name, const qpid::framing::FieldTable& settings)
{
- uint32_t maxCount = getCapacity<int32_t>(settings, maxCountKey, 0);
- uint64_t maxSize = getCapacity<int64_t>(settings, maxSizeKey, defaultMaxSize);
+ uint32_t maxCount = getCapacity(settings, maxCountKey, 0);
+ uint32_t maxSize = getCapacity(settings, maxSizeKey, defaultMaxSize);
if (maxCount || maxSize) {
return createQueuePolicy(name, maxCount, maxSize, getType(settings));
} else {
diff --git a/cpp/src/qpid/broker/QueuePolicy.h b/cpp/src/qpid/broker/QueuePolicy.h
index ec7f846704..3cdd63784d 100644
--- a/cpp/src/qpid/broker/QueuePolicy.h
+++ b/cpp/src/qpid/broker/QueuePolicy.h
@@ -43,7 +43,8 @@ class QueuePolicy
uint32_t count;
uint64_t size;
bool policyExceeded;
-
+
+ static uint32_t getCapacity(const qpid::framing::FieldTable& settings, const std::string& key, uint32_t defaultValue);
protected:
uint64_t getCurrentQueueSize() const { return size; }
diff --git a/cpp/src/qpid/broker/QueueRegistry.cpp b/cpp/src/qpid/broker/QueueRegistry.cpp
index 135a3543d9..ea2531dae7 100644
--- a/cpp/src/qpid/broker/QueueRegistry.cpp
+++ b/cpp/src/qpid/broker/QueueRegistry.cpp
@@ -21,7 +21,6 @@
#include "qpid/broker/Queue.h"
#include "qpid/broker/QueueRegistry.h"
#include "qpid/broker/QueueEvents.h"
-#include "qpid/broker/Exchange.h"
#include "qpid/log/Statement.h"
#include <sstream>
#include <assert.h>
@@ -37,13 +36,7 @@ QueueRegistry::~QueueRegistry(){}
std::pair<Queue::shared_ptr, bool>
QueueRegistry::declare(const string& declareName, bool durable,
- bool autoDelete, const OwnershipToken* owner,
- boost::shared_ptr<Exchange> alternate,
- const qpid::framing::FieldTable& arguments,
- bool recovering/*true if this declare is a
- result of recovering queue
- definition from persistente
- record*/)
+ bool autoDelete, const OwnershipToken* owner)
{
RWlock::ScopedWlock locker(lock);
string name = declareName.empty() ? generateName() : declareName;
@@ -52,17 +45,6 @@ QueueRegistry::declare(const string& declareName, bool durable,
if (i == queues.end()) {
Queue::shared_ptr queue(new Queue(name, autoDelete, durable ? store : 0, owner, parent, broker));
- if (alternate) {
- queue->setAlternateExchange(alternate);//need to do this *before* create
- alternate->incAlternateUsers();
- }
- if (!recovering) {
- //apply settings & create persistent record if required
- queue->create(arguments);
- } else {
- //i.e. recovering a queue for which we already have a persistent record
- queue->configure(arguments);
- }
queues[name] = queue;
if (lastNode) queue->setLastNodeFailure();
diff --git a/cpp/src/qpid/broker/QueueRegistry.h b/cpp/src/qpid/broker/QueueRegistry.h
index 8a32a64f05..57859fe639 100644
--- a/cpp/src/qpid/broker/QueueRegistry.h
+++ b/cpp/src/qpid/broker/QueueRegistry.h
@@ -24,7 +24,6 @@
#include "qpid/broker/BrokerImportExport.h"
#include "qpid/sys/Mutex.h"
#include "qpid/management/Manageable.h"
-#include "qpid/framing/FieldTable.h"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <algorithm>
@@ -35,7 +34,6 @@ namespace broker {
class Queue;
class QueueEvents;
-class Exchange;
class OwnershipToken;
class Broker;
class MessageStore;
@@ -62,10 +60,7 @@ class QueueRegistry {
const std::string& name,
bool durable = false,
bool autodelete = false,
- const OwnershipToken* owner = 0,
- boost::shared_ptr<Exchange> alternateExchange = boost::shared_ptr<Exchange>(),
- const qpid::framing::FieldTable& args = framing::FieldTable(),
- bool recovering = false);
+ const OwnershipToken* owner = 0);
/**
* Destroy the named queue.
diff --git a/cpp/src/qpid/broker/RateTracker.cpp b/cpp/src/qpid/broker/RateTracker.cpp
new file mode 100644
index 0000000000..048349b658
--- /dev/null
+++ b/cpp/src/qpid/broker/RateTracker.cpp
@@ -0,0 +1,51 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/broker/RateTracker.h"
+
+using qpid::sys::AbsTime;
+using qpid::sys::Duration;
+using qpid::sys::TIME_SEC;
+
+namespace qpid {
+namespace broker {
+
+RateTracker::RateTracker() : currentCount(0), lastCount(0), lastTime(AbsTime::now()) {}
+
+RateTracker& RateTracker::operator++()
+{
+ ++currentCount;
+ return *this;
+}
+
+double RateTracker::sampleRatePerSecond()
+{
+ int32_t increment = currentCount - lastCount;
+ AbsTime now = AbsTime::now();
+ Duration interval(lastTime, now);
+ lastCount = currentCount;
+ lastTime = now;
+ //if sampling at higher frequency than supported, will just return the number of increments
+ if (interval < TIME_SEC) return increment;
+ else if (increment == 0) return 0;
+ else return increment / (interval / TIME_SEC);
+}
+
+}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/RateTracker.h b/cpp/src/qpid/broker/RateTracker.h
new file mode 100644
index 0000000000..0c20b37312
--- /dev/null
+++ b/cpp/src/qpid/broker/RateTracker.h
@@ -0,0 +1,57 @@
+#ifndef QPID_BROKER_RATETRACKER_H
+#define QPID_BROKER_RATETRACKER_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR 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"
+
+namespace qpid {
+namespace broker {
+
+/**
+ * Simple rate tracker: represents some value that can be incremented,
+ * then can periodcially sample the rate of increments.
+ */
+class RateTracker
+{
+ public:
+ RateTracker();
+ /**
+ * Increments the count being tracked. Can be called concurrently
+ * with other calls to this operator as well as with calls to
+ * sampleRatePerSecond().
+ */
+ RateTracker& operator++();
+ /**
+ * Returns the rate of increments per second since last
+ * called. Calls to this method should be serialised, but can be
+ * called concurrently with the increment operator
+ */
+ double sampleRatePerSecond();
+ private:
+ volatile int32_t currentCount;
+ int32_t lastCount;
+ qpid::sys::AbsTime lastTime;
+};
+}} // namespace qpid::broker
+
+#endif /*!QPID_BROKER_RATETRACKER_H*/
diff --git a/cpp/src/qpid/broker/RecoveredDequeue.cpp b/cpp/src/qpid/broker/RecoveredDequeue.cpp
index cd6735328f..38cb8043c9 100644
--- a/cpp/src/qpid/broker/RecoveredDequeue.cpp
+++ b/cpp/src/qpid/broker/RecoveredDequeue.cpp
@@ -43,6 +43,7 @@ void RecoveredDequeue::commit() throw()
void RecoveredDequeue::rollback() throw()
{
+ msg->enqueueComplete();
queue->process(msg);
}
diff --git a/cpp/src/qpid/broker/RecoveredEnqueue.cpp b/cpp/src/qpid/broker/RecoveredEnqueue.cpp
index 6d2eaee6c4..6263c63e3d 100644
--- a/cpp/src/qpid/broker/RecoveredEnqueue.cpp
+++ b/cpp/src/qpid/broker/RecoveredEnqueue.cpp
@@ -36,6 +36,7 @@ bool RecoveredEnqueue::prepare(TransactionContext*) throw(){
}
void RecoveredEnqueue::commit() throw(){
+ msg->enqueueComplete();
queue->process(msg);
}
diff --git a/cpp/src/qpid/broker/RecoveryManagerImpl.cpp b/cpp/src/qpid/broker/RecoveryManagerImpl.cpp
index d08409695e..2f04943581 100644
--- a/cpp/src/qpid/broker/RecoveryManagerImpl.cpp
+++ b/cpp/src/qpid/broker/RecoveryManagerImpl.cpp
@@ -113,7 +113,7 @@ RecoverableExchange::shared_ptr RecoveryManagerImpl::recoverExchange(framing::Bu
RecoverableQueue::shared_ptr RecoveryManagerImpl::recoverQueue(framing::Buffer& buffer)
{
- Queue::shared_ptr queue = Queue::restore(queues, buffer);
+ Queue::shared_ptr queue = Queue::decode(queues, buffer, true);
try {
Exchange::shared_ptr exchange = exchanges.getDefault();
if (exchange) {
@@ -252,6 +252,7 @@ void RecoverableMessageImpl::dequeue(DtxBuffer::shared_ptr buffer, Queue::shared
void RecoverableMessageImpl::enqueue(DtxBuffer::shared_ptr buffer, Queue::shared_ptr queue)
{
+ msg->enqueueComplete(); // recoved nmessage to enqueued in store already
buffer->enlist(TxOp::shared_ptr(new RecoveredEnqueue(queue, msg)));
}
diff --git a/cpp/src/qpid/broker/SaslAuthenticator.cpp b/cpp/src/qpid/broker/SaslAuthenticator.cpp
index d7adbd68ab..acdb4934d4 100644
--- a/cpp/src/qpid/broker/SaslAuthenticator.cpp
+++ b/cpp/src/qpid/broker/SaslAuthenticator.cpp
@@ -30,7 +30,6 @@
#include <boost/format.hpp>
#if HAVE_SASL
-#include <sys/stat.h>
#include <sasl/sasl.h>
#include "qpid/sys/cyrus/CyrusSecurityLayer.h"
using qpid::sys::cyrus::CyrusSecurityLayer;
@@ -58,7 +57,7 @@ public:
NullAuthenticator(Connection& connection, bool encrypt);
~NullAuthenticator();
void getMechanisms(framing::Array& mechanisms);
- void start(const std::string& mechanism, const std::string* response);
+ void start(const std::string& mechanism, const std::string& response);
void step(const std::string&) {}
std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize);
};
@@ -82,7 +81,7 @@ public:
~CyrusAuthenticator();
void init();
void getMechanisms(framing::Array& mechanisms);
- void start(const std::string& mechanism, const std::string* response);
+ void start(const std::string& mechanism, const std::string& response);
void step(const std::string& response);
void getError(std::string& error);
void getUid(std::string& uid) { getUsername(uid); }
@@ -99,33 +98,11 @@ void SaslAuthenticator::init(const std::string& saslName, std::string const & sa
// Check if we have a version of SASL that supports sasl_set_path()
#if (SASL_VERSION_FULL >= ((2<<16)|(1<<8)|22))
// If we are not given a sasl path, do nothing and allow the default to be used.
- if ( saslConfigPath.empty() ) {
- QPID_LOG ( info, "SASL: no config path set - using default." );
- }
- else {
- struct stat st;
-
- // Make sure the directory exists and we can read up to it.
- if ( ::stat ( saslConfigPath.c_str(), & st) ) {
- // Note: not using strerror() here because I think its messages are a little too hazy.
- if ( errno == ENOENT )
- throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: no such directory: " << saslConfigPath ) );
- if ( errno == EACCES )
- throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: cannot read parent of: " << saslConfigPath ) );
- // catch-all stat failure
- throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: cannot stat: " << saslConfigPath ) );
- }
-
- // Make sure the directory is readable.
- if ( ::access ( saslConfigPath.c_str(), R_OK ) ) {
- throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: directory not readable:" << saslConfigPath ) );
- }
-
- // This shouldn't fail now, but check anyway.
- int code = sasl_set_path(SASL_PATH_TYPE_CONFIG, const_cast<char *>(saslConfigPath.c_str()));
+ if ( ! saslConfigPath.empty() ) {
+ int code = sasl_set_path(SASL_PATH_TYPE_CONFIG,
+ const_cast<char *>(saslConfigPath.c_str()));
if(SASL_OK != code)
throw Exception(QPID_MSG("SASL: sasl_set_path failed [" << code << "] " ));
-
QPID_LOG(info, "SASL: config path set to " << saslConfigPath );
}
#endif
@@ -187,7 +164,7 @@ void NullAuthenticator::getMechanisms(Array& mechanisms)
mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("PLAIN")));//useful for testing
}
-void NullAuthenticator::start(const string& mechanism, const string* response)
+void NullAuthenticator::start(const string& mechanism, const string& response)
{
if (encrypt) {
#if HAVE_SASL
@@ -203,16 +180,16 @@ void NullAuthenticator::start(const string& mechanism, const string* response)
}
}
if (mechanism == "PLAIN") { // Old behavior
- if (response && response->size() > 0) {
+ if (response.size() > 0) {
string uid;
- string::size_type i = response->find((char)0);
- if (i == 0 && response->size() > 1) {
+ string::size_type i = response.find((char)0);
+ if (i == 0 && response.size() > 1) {
//no authorization id; use authentication id
- i = response->find((char)0, 1);
- if (i != string::npos) uid = response->substr(1, i-1);
+ i = response.find((char)0, 1);
+ if (i != string::npos) uid = response.substr(1, i-1);
} else if (i != string::npos) {
//authorization id is first null delimited field
- uid = response->substr(0, i);
+ uid = response.substr(0, i);
}//else not a valid SASL PLAIN response, throw error?
if (!uid.empty()) {
//append realm if it has not already been added
@@ -399,22 +376,18 @@ void CyrusAuthenticator::getMechanisms(Array& mechanisms)
}
}
-void CyrusAuthenticator::start(const string& mechanism, const string* response)
+void CyrusAuthenticator::start(const string& mechanism, const string& response)
{
const char *challenge;
unsigned int challenge_len;
- // This should be at same debug level as mech list in getMechanisms().
- QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism);
+ QPID_LOG(debug, "SASL: Starting authentication with mechanism: " << mechanism);
int code = sasl_server_start(sasl_conn,
mechanism.c_str(),
- (response ? response->c_str() : 0), (response ? response->size() : 0),
+ response.c_str(), response.length(),
&challenge, &challenge_len);
processAuthenticationStep(code, challenge, challenge_len);
- qmf::org::apache::qpid::broker::Connection* cnxMgmt = connection.getMgmtObject();
- if ( cnxMgmt )
- cnxMgmt->set_saslMechanism(mechanism);
}
void CyrusAuthenticator::step(const string& response)
@@ -451,12 +424,10 @@ void CyrusAuthenticator::processAuthenticationStep(int code, const char *challen
client.secure(challenge_str);
} else {
std::string uid;
- //save error detail before trying to retrieve username as error in doing so will overwrite it
- std::string errordetail = sasl_errdetail(sasl_conn);
if (!getUsername(uid)) {
- QPID_LOG(info, "SASL: Authentication failed (no username available yet):" << errordetail);
+ QPID_LOG(info, "SASL: Authentication failed (no username available):" << sasl_errdetail(sasl_conn));
} else {
- QPID_LOG(info, "SASL: Authentication failed for " << uid << ":" << errordetail);
+ QPID_LOG(info, "SASL: Authentication failed for " << uid << ":" << sasl_errdetail(sasl_conn));
}
// TODO: Change to more specific exceptions, when they are
@@ -488,9 +459,6 @@ std::auto_ptr<SecurityLayer> CyrusAuthenticator::getSecurityLayer(uint16_t maxFr
if (ssf) {
securityLayer = std::auto_ptr<SecurityLayer>(new CyrusSecurityLayer(sasl_conn, maxFrameSize));
}
- qmf::org::apache::qpid::broker::Connection* cnxMgmt = connection.getMgmtObject();
- if ( cnxMgmt )
- cnxMgmt->set_saslSsf(ssf);
return securityLayer;
}
diff --git a/cpp/src/qpid/broker/SaslAuthenticator.h b/cpp/src/qpid/broker/SaslAuthenticator.h
index 4e5d43214c..cfbe1a0cd1 100644
--- a/cpp/src/qpid/broker/SaslAuthenticator.h
+++ b/cpp/src/qpid/broker/SaslAuthenticator.h
@@ -41,7 +41,7 @@ class SaslAuthenticator
public:
virtual ~SaslAuthenticator() {}
virtual void getMechanisms(framing::Array& mechanisms) = 0;
- virtual void start(const std::string& mechanism, const std::string* response) = 0;
+ virtual void start(const std::string& mechanism, const std::string& response) = 0;
virtual void step(const std::string& response) = 0;
virtual void getUid(std::string&) {}
virtual bool getUsername(std::string&) { return false; };
diff --git a/cpp/src/qpid/broker/SemanticState.cpp b/cpp/src/qpid/broker/SemanticState.cpp
index fbcb21eab9..c91cfba2f8 100644
--- a/cpp/src/qpid/broker/SemanticState.cpp
+++ b/cpp/src/qpid/broker/SemanticState.cpp
@@ -70,12 +70,14 @@ SemanticState::SemanticState(DeliveryAdapter& da, SessionContext& ss)
deliveryAdapter(da),
tagGenerator("sgen"),
dtxSelected(false),
- authMsg(getSession().getBroker().getOptions().auth && !getSession().getConnection().isUserProxyAuth()),
+ authMsg(getSession().getBroker().getOptions().auth && !getSession().getConnection().isFederationLink()),
userID(getSession().getConnection().getUserId()),
userName(getSession().getConnection().getUserId().substr(0,getSession().getConnection().getUserId().find('@'))),
isDefaultRealm(userID.find('@') != std::string::npos && getSession().getBroker().getOptions().realm == userID.substr(userID.find('@')+1,userID.size())),
closeComplete(false)
-{}
+{
+ acl = getSession().getBroker().getAcl();
+}
SemanticState::~SemanticState() {
closed();
@@ -86,7 +88,7 @@ void SemanticState::closed() {
//prevent requeued messages being redelivered to consumers
for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) {
disable(i->second);
- }
+ }
if (dtxBuffer.get()) {
dtxBuffer->fail();
}
@@ -105,24 +107,16 @@ bool SemanticState::exists(const string& consumerTag){
return consumers.find(consumerTag) != consumers.end();
}
-namespace {
- const std::string SEPARATOR("::");
-}
-
-void SemanticState::consume(const string& tag,
+void SemanticState::consume(const string& tag,
Queue::shared_ptr queue, bool ackRequired, bool acquire,
bool exclusive, const string& resumeId, uint64_t resumeTtl, const FieldTable& arguments)
{
- // "tag" is only guaranteed to be unique to this session (see AMQP 0-10 Message.subscribe, destination).
- // Create a globally unique name so the broker can identify individual consumers
- std::string name = session.getSessionId().str() + SEPARATOR + tag;
- ConsumerImpl::shared_ptr c(new ConsumerImpl(this, name, queue, ackRequired, acquire, exclusive, tag, resumeId, resumeTtl, arguments));
+ ConsumerImpl::shared_ptr c(new ConsumerImpl(this, tag, queue, ackRequired, acquire, exclusive, resumeId, resumeTtl, arguments));
queue->consume(c, exclusive);//may throw exception
consumers[tag] = c;
}
-bool SemanticState::cancel(const string& tag)
-{
+void SemanticState::cancel(const string& tag){
ConsumerImplMap::iterator i = consumers.find(tag);
if (i != consumers.end()) {
cancel(i->second);
@@ -130,13 +124,7 @@ bool SemanticState::cancel(const string& tag)
//should cancel all unacked messages for this consumer so that
//they are not redelivered on recovery
for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::cancel, _1, tag));
- //can also remove any records that are now redundant
- DeliveryRecords::iterator removed =
- remove_if(unacked.begin(), unacked.end(), bind(&DeliveryRecord::isRedundant, _1));
- unacked.erase(removed, unacked.end());
- return true;
- } else {
- return false;
+
}
}
@@ -179,8 +167,8 @@ void SemanticState::startDtx(const std::string& xid, DtxManager& mgr, bool join)
if (!dtxSelected) {
throw CommandInvalidException(QPID_MSG("Session has not been selected for use with dtx"));
}
- dtxBuffer.reset(new DtxBuffer(xid));
- txBuffer = dtxBuffer;
+ dtxBuffer = DtxBuffer::shared_ptr(new DtxBuffer(xid));
+ txBuffer = boost::static_pointer_cast<TxBuffer>(dtxBuffer);
if (join) {
mgr.join(xid, dtxBuffer);
} else {
@@ -206,7 +194,7 @@ void SemanticState::endDtx(const std::string& xid, bool fail)
dtxBuffer->fail();
} else {
dtxBuffer->markEnded();
- }
+ }
dtxBuffer.reset();
}
@@ -248,7 +236,7 @@ void SemanticState::resumeDtx(const std::string& xid)
checkDtxTimeout();
dtxBuffer->setSuspended(false);
- txBuffer = dtxBuffer;
+ txBuffer = boost::static_pointer_cast<TxBuffer>(dtxBuffer);
}
void SemanticState::checkDtxTimeout()
@@ -266,33 +254,31 @@ void SemanticState::record(const DeliveryRecord& delivery)
const std::string QPID_SYNC_FREQUENCY("qpid.sync_frequency");
-SemanticState::ConsumerImpl::ConsumerImpl(SemanticState* _parent,
- const string& _name,
- Queue::shared_ptr _queue,
+SemanticState::ConsumerImpl::ConsumerImpl(SemanticState* _parent,
+ const string& _name,
+ Queue::shared_ptr _queue,
bool ack,
bool _acquire,
bool _exclusive,
- const string& _tag,
const string& _resumeId,
uint64_t _resumeTtl,
const framing::FieldTable& _arguments
-) :
- Consumer(_name, _acquire),
- parent(_parent),
- queue(_queue),
- ackExpected(ack),
+) :
+ Consumer(_acquire),
+ parent(_parent),
+ name(_name),
+ queue(_queue),
+ ackExpected(ack),
acquire(_acquire),
- blocked(true),
+ blocked(true),
windowing(true),
- windowActive(false),
exclusive(_exclusive),
resumeId(_resumeId),
- tag(_tag),
resumeTtl(_resumeTtl),
arguments(_arguments),
- msgCredit(0),
+ msgCredit(0),
byteCredit(0),
notifyEnabled(true),
syncFrequency(_arguments.getAsInt(QPID_SYNC_FREQUENCY)),
@@ -303,10 +289,10 @@ SemanticState::ConsumerImpl::ConsumerImpl(SemanticState* _parent,
{
ManagementAgent* agent = parent->session.getBroker().getManagementAgent();
qpid::management::Manageable* ms = dynamic_cast<qpid::management::Manageable*> (&(parent->session));
-
+
if (agent != 0)
{
- mgmtObject = new _qmf::Subscription(agent, this, ms , queue->GetManagementObject()->getObjectId(), getTag(),
+ mgmtObject = new _qmf::Subscription(agent, this, ms , queue->GetManagementObject()->getObjectId() ,name,
!acquire, ackExpected, exclusive, ManagementAgent::toMap(arguments));
agent->addObject (mgmtObject);
mgmtObject->set_creditMode("WINDOW");
@@ -338,16 +324,16 @@ bool SemanticState::ConsumerImpl::deliver(QueuedMessage& msg)
{
assertClusterSafe();
allocateCredit(msg.payload);
- DeliveryRecord record(msg, queue, getTag(), acquire, !ackExpected, windowing);
+ DeliveryRecord record(msg, queue, name, acquire, !ackExpected, windowing);
bool sync = syncFrequency && ++deliveryCount >= syncFrequency;
if (sync) deliveryCount = 0;//reset
parent->deliver(record, sync);
+ if (!ackExpected && acquire) record.setEnded();//allows message to be released now its been delivered
if (windowing || ackExpected || !acquire) {
parent->record(record);
- }
- if (acquire && !ackExpected) { // auto acquire && auto accept
- queue->dequeue(0 /*ctxt*/, msg);
- record.setEnded();
+ }
+ if (acquire && !ackExpected) {
+ queue->dequeue(0, msg);
}
if (mgmtObject) { mgmtObject->inc_delivered(); }
return true;
@@ -365,7 +351,7 @@ bool SemanticState::ConsumerImpl::accept(intrusive_ptr<Message> msg)
// checkCredit fails because the message is to big, we should
// remain on queue's listener list for possible smaller messages
// in future.
- //
+ //
blocked = !(filter(msg) && checkCredit(msg));
return !blocked;
}
@@ -377,7 +363,7 @@ struct ConsumerName {
};
ostream& operator<<(ostream& o, const ConsumerName& pc) {
- return o << pc.consumer.getTag() << " on "
+ return o << pc.consumer.getName() << " on "
<< pc.consumer.getParent().getSession().getSessionId();
}
}
@@ -386,7 +372,7 @@ void SemanticState::ConsumerImpl::allocateCredit(intrusive_ptr<Message>& msg)
{
assertClusterSafe();
uint32_t originalMsgCredit = msgCredit;
- uint32_t originalByteCredit = byteCredit;
+ uint32_t originalByteCredit = byteCredit;
if (msgCredit != 0xFFFFFFFF) {
msgCredit--;
}
@@ -396,7 +382,7 @@ void SemanticState::ConsumerImpl::allocateCredit(intrusive_ptr<Message>& msg)
QPID_LOG(debug, "Credit allocated for " << ConsumerName(*this)
<< ", was " << " bytes: " << originalByteCredit << " msgs: " << originalMsgCredit
<< " now bytes: " << byteCredit << " msgs: " << msgCredit);
-
+
}
bool SemanticState::ConsumerImpl::checkCredit(intrusive_ptr<Message>& msg)
@@ -410,7 +396,7 @@ bool SemanticState::ConsumerImpl::checkCredit(intrusive_ptr<Message>& msg)
return enoughCredit;
}
-SemanticState::ConsumerImpl::~ConsumerImpl()
+SemanticState::ConsumerImpl::~ConsumerImpl()
{
if (mgmtObject != 0)
mgmtObject->resourceDestroy ();
@@ -428,7 +414,7 @@ void SemanticState::unsubscribe(ConsumerImpl::shared_ptr c)
Queue::shared_ptr queue = c->getQueue();
if(queue) {
queue->cancel(c);
- if (queue->canAutoDelete() && !queue->hasExclusiveOwner()) {
+ if (queue->canAutoDelete() && !queue->hasExclusiveOwner()) {
Queue::tryAutoDelete(session.getBroker(), queue);
}
}
@@ -470,23 +456,23 @@ const std::string nullstring;
}
void SemanticState::route(intrusive_ptr<Message> msg, Deliverable& strategy) {
- msg->computeExpiration(getSession().getBroker().getExpiryPolicy());
-
+ msg->setTimestamp(getSession().getBroker().getExpiryPolicy());
+
std::string exchangeName = msg->getExchangeName();
- if (!cacheExchange || cacheExchange->getName() != exchangeName || cacheExchange->isDestroyed())
+ if (!cacheExchange || cacheExchange->getName() != exchangeName)
cacheExchange = session.getBroker().getExchanges().get(exchangeName);
cacheExchange->setProperties(msg);
/* verify the userid if specified: */
std::string id =
msg->hasProperties<MessageProperties>() ? msg->getProperties<MessageProperties>()->getUserId() : nullstring;
+
if (authMsg && !id.empty() && !(id == userID || (isDefaultRealm && id == userName)))
{
QPID_LOG(debug, "authorised user id : " << userID << " but user id in message declared as " << id);
throw UnauthorizedAccessException(QPID_MSG("authorised user id : " << userID << " but user id in message declared as " << id));
}
- AclModule* acl = getSession().getBroker().getAcl();
if (acl && acl->doTransferAcl())
{
if (!acl->authorise(getSession().getConnection().getUserId(),acl::ACT_PUBLISH,acl::OBJ_EXCHANGE,exchangeName, msg->getRoutingKey() ))
@@ -498,7 +484,7 @@ void SemanticState::route(intrusive_ptr<Message> msg, Deliverable& strategy) {
if (!strategy.delivered) {
//TODO:if discard-unroutable, just drop it
- //TODO:else if accept-mode is explicit, reject it
+ //TODO:else if accept-mode is explicit, reject it
//else route it to alternate exchange
if (cacheExchange->getAlternate()) {
cacheExchange->getAlternate()->route(strategy, msg->getRoutingKey(), msg->getApplicationHeaders());
@@ -527,7 +513,7 @@ void SemanticState::ConsumerImpl::requestDispatch()
}
bool SemanticState::complete(DeliveryRecord& delivery)
-{
+{
ConsumerImplMap::iterator i = consumers.find(delivery.getTag());
if (i != consumers.end()) {
i->second->complete(delivery);
@@ -539,7 +525,7 @@ void SemanticState::ConsumerImpl::complete(DeliveryRecord& delivery)
{
if (!delivery.isComplete()) {
delivery.complete();
- if (windowing && windowActive) {
+ if (windowing) {
if (msgCredit != 0xFFFFFFFF) msgCredit++;
if (byteCredit != 0xFFFFFFFF) byteCredit += delivery.getCredit();
}
@@ -555,7 +541,7 @@ void SemanticState::recover(bool requeue)
unacked.clear();
for_each(copy.rbegin(), copy.rend(), mem_fun_ref(&DeliveryRecord::requeue));
}else{
- for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::redeliver, _1, this));
+ for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::redeliver, _1, this));
//unconfirmed messages re redelivered and therefore have their
//id adjusted, confirmed messages are not and so the ordering
//w.r.t id is lost
@@ -568,61 +554,50 @@ void SemanticState::deliver(DeliveryRecord& msg, bool sync)
return deliveryAdapter.deliver(msg, sync);
}
-const SemanticState::ConsumerImpl::shared_ptr SemanticState::find(const std::string& destination) const
-{
- ConsumerImpl::shared_ptr consumer;
- if (!find(destination, consumer)) {
- throw NotFoundException(QPID_MSG("Unknown destination " << destination << " session=" << session.getSessionId()));
- } else {
- return consumer;
- }
-}
-
-bool SemanticState::find(const std::string& destination, ConsumerImpl::shared_ptr& consumer) const
+SemanticState::ConsumerImpl& SemanticState::find(const std::string& destination)
{
- // @todo KAG gsim: shouldn't the consumers map be locked????
- ConsumerImplMap::const_iterator i = consumers.find(destination);
+ ConsumerImplMap::iterator i = consumers.find(destination);
if (i == consumers.end()) {
- return false;
+ throw NotFoundException(QPID_MSG("Unknown destination " << destination));
+ } else {
+ return *(i->second);
}
- consumer = i->second;
- return true;
}
void SemanticState::setWindowMode(const std::string& destination)
{
- find(destination)->setWindowMode();
+ find(destination).setWindowMode();
}
void SemanticState::setCreditMode(const std::string& destination)
{
- find(destination)->setCreditMode();
+ find(destination).setCreditMode();
}
void SemanticState::addByteCredit(const std::string& destination, uint32_t value)
{
- ConsumerImpl::shared_ptr c = find(destination);
- c->addByteCredit(value);
- c->requestDispatch();
+ ConsumerImpl& c = find(destination);
+ c.addByteCredit(value);
+ c.requestDispatch();
}
void SemanticState::addMessageCredit(const std::string& destination, uint32_t value)
{
- ConsumerImpl::shared_ptr c = find(destination);
- c->addMessageCredit(value);
- c->requestDispatch();
+ ConsumerImpl& c = find(destination);
+ c.addMessageCredit(value);
+ c.requestDispatch();
}
void SemanticState::flush(const std::string& destination)
{
- find(destination)->flush();
+ find(destination).flush();
}
void SemanticState::stop(const std::string& destination)
{
- find(destination)->stop();
+ find(destination).stop();
}
void SemanticState::ConsumerImpl::setWindowMode()
@@ -646,7 +621,6 @@ void SemanticState::ConsumerImpl::setCreditMode()
void SemanticState::ConsumerImpl::addByteCredit(uint32_t value)
{
assertClusterSafe();
- if (windowing) windowActive = true;
if (byteCredit != 0xFFFFFFFF) {
if (value == 0xFFFFFFFF) byteCredit = value;
else byteCredit += value;
@@ -656,7 +630,6 @@ void SemanticState::ConsumerImpl::addByteCredit(uint32_t value)
void SemanticState::ConsumerImpl::addMessageCredit(uint32_t value)
{
assertClusterSafe();
- if (windowing) windowActive = true;
if (msgCredit != 0xFFFFFFFF) {
if (value == 0xFFFFFFFF) msgCredit = value;
else msgCredit += value;
@@ -677,8 +650,7 @@ void SemanticState::ConsumerImpl::flush()
{
while(haveCredit() && queue->dispatch(shared_from_this()))
;
- msgCredit = 0;
- byteCredit = 0;
+ stop();
}
void SemanticState::ConsumerImpl::stop()
@@ -686,7 +658,6 @@ void SemanticState::ConsumerImpl::stop()
assertClusterSafe();
msgCredit = 0;
byteCredit = 0;
- windowActive = false;
}
Queue::shared_ptr SemanticState::getQueue(const string& name) const {
@@ -702,7 +673,7 @@ Queue::shared_ptr SemanticState::getQueue(const string& name) const {
}
AckRange SemanticState::findRange(DeliveryId first, DeliveryId last)
-{
+{
return DeliveryRecord::findRange(unacked, first, last);
}
@@ -720,21 +691,14 @@ void SemanticState::release(DeliveryId first, DeliveryId last, bool setRedeliver
DeliveryRecords::reverse_iterator start(range.end);
DeliveryRecords::reverse_iterator end(range.start);
for_each(start, end, boost::bind(&DeliveryRecord::release, _1, setRedelivered));
-
- DeliveryRecords::iterator removed =
- remove_if(range.start, range.end, bind(&DeliveryRecord::isRedundant, _1));
- unacked.erase(removed, range.end);
}
void SemanticState::reject(DeliveryId first, DeliveryId last)
{
AckRange range = findRange(first, last);
for_each(range.start, range.end, mem_fun_ref(&DeliveryRecord::reject));
- //may need to remove the delivery records as well
- for (DeliveryRecords::iterator i = range.start; i != unacked.end() && i->getId() <= last; ) {
- if (i->isRedundant()) i = unacked.erase(i);
- else i++;
- }
+ //need to remove the delivery records as well
+ unacked.erase(range.start, range.end);
}
bool SemanticState::ConsumerImpl::doOutput()
@@ -797,13 +761,13 @@ void SemanticState::accepted(const SequenceSet& commands) {
//in transactional mode, don't dequeue or remove, just
//maintain set of acknowledged messages:
accumulatedAck.add(commands);
-
+
if (dtxBuffer.get()) {
//if enlisted in a dtx, copy the relevant slice from
//unacked and record it against that transaction
TxOp::shared_ptr txAck(new DtxAck(accumulatedAck, unacked));
accumulatedAck.clear();
- dtxBuffer->enlist(txAck);
+ dtxBuffer->enlist(txAck);
//mark the relevant messages as 'ended' in unacked
//if the messages are already completed, they can be
@@ -825,6 +789,7 @@ void SemanticState::accepted(const SequenceSet& commands) {
}
void SemanticState::completed(const SequenceSet& commands) {
+ assertClusterSafe();
DeliveryRecords::iterator removed =
remove_if(unacked.begin(), unacked.end(),
isInSequenceSetAnd(commands,
@@ -835,6 +800,7 @@ void SemanticState::completed(const SequenceSet& commands) {
void SemanticState::attached()
{
+ assertClusterSafe();
for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) {
i->second->enableNotify();
session.getConnection().outputTasks.addOutputTask(i->second.get());
@@ -844,6 +810,7 @@ void SemanticState::attached()
void SemanticState::detached()
{
+ assertClusterSafe();
for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) {
i->second->disableNotify();
session.getConnection().outputTasks.removeOutputTask(i->second.get());
diff --git a/cpp/src/qpid/broker/SemanticState.h b/cpp/src/qpid/broker/SemanticState.h
index 6d88dd56d9..b2e648410a 100644
--- a/cpp/src/qpid/broker/SemanticState.h
+++ b/cpp/src/qpid/broker/SemanticState.h
@@ -65,7 +65,7 @@ class SessionContext;
*
* Message delivery is driven by ConsumerImpl::doOutput(), which is
* called when a client's socket is ready to write data.
- *
+ *
*/
class SemanticState : private boost::noncopyable {
public:
@@ -75,15 +75,14 @@ class SemanticState : private boost::noncopyable {
{
mutable qpid::sys::Mutex lock;
SemanticState* const parent;
+ const std::string name;
const boost::shared_ptr<Queue> queue;
const bool ackExpected;
const bool acquire;
bool blocked;
bool windowing;
- bool windowActive;
bool exclusive;
std::string resumeId;
- const std::string tag; // <destination> from AMQP 0-10 Message.subscribe command
uint64_t resumeTtl;
framing::FieldTable arguments;
uint32_t msgCredit;
@@ -100,16 +99,15 @@ class SemanticState : private boost::noncopyable {
public:
typedef boost::shared_ptr<ConsumerImpl> shared_ptr;
- ConsumerImpl(SemanticState* parent,
+ ConsumerImpl(SemanticState* parent,
const std::string& name, boost::shared_ptr<Queue> queue,
bool ack, bool acquire, bool exclusive,
- const std::string& tag, const std::string& resumeId,
- uint64_t resumeTtl, const framing::FieldTable& arguments);
+ const std::string& resumeId, uint64_t resumeTtl, const framing::FieldTable& arguments);
~ConsumerImpl();
OwnershipToken* getSession();
- bool deliver(QueuedMessage& msg);
- bool filter(boost::intrusive_ptr<Message> msg);
- bool accept(boost::intrusive_ptr<Message> msg);
+ bool deliver(QueuedMessage& msg);
+ bool filter(boost::intrusive_ptr<Message> msg);
+ bool accept(boost::intrusive_ptr<Message> msg);
void disableNotify();
void enableNotify();
@@ -124,13 +122,15 @@ class SemanticState : private boost::noncopyable {
void addMessageCredit(uint32_t value);
void flush();
void stop();
- void complete(DeliveryRecord&);
+ void complete(DeliveryRecord&);
boost::shared_ptr<Queue> getQueue() const { return queue; }
bool isBlocked() const { return blocked; }
bool setBlocked(bool set) { std::swap(set, blocked); return set; }
bool doOutput();
+ std::string getName() const { return name; }
+
bool isAckExpected() const { return ackExpected; }
bool isAcquire() const { return acquire; }
bool isWindowing() const { return windowing; }
@@ -138,7 +138,6 @@ class SemanticState : private boost::noncopyable {
uint32_t getMsgCredit() const { return msgCredit; }
uint32_t getByteCredit() const { return byteCredit; }
std::string getResumeId() const { return resumeId; };
- const std::string& getTag() const { return tag; }
uint64_t getResumeTtl() const { return resumeTtl; }
const framing::FieldTable& getArguments() const { return arguments; }
@@ -149,10 +148,9 @@ class SemanticState : private boost::noncopyable {
management::Manageable::status_t ManagementMethod (uint32_t methodId, management::Args& args, std::string& text);
};
- typedef std::map<std::string, DtxBuffer::shared_ptr> DtxBufferMap;
-
private:
typedef std::map<std::string, ConsumerImpl::shared_ptr> ConsumerImplMap;
+ typedef std::map<std::string, DtxBuffer::shared_ptr> DtxBufferMap;
SessionContext& session;
DeliveryAdapter& deliveryAdapter;
@@ -165,6 +163,7 @@ class SemanticState : private boost::noncopyable {
DtxBufferMap suspendedXids;
framing::SequenceSet accumulatedAck;
boost::shared_ptr<Exchange> cacheExchange;
+ AclModule* acl;
const bool authMsg;
const std::string userID;
const std::string userName;
@@ -182,16 +181,14 @@ class SemanticState : private boost::noncopyable {
void disable(ConsumerImpl::shared_ptr);
public:
-
SemanticState(DeliveryAdapter&, SessionContext&);
~SemanticState();
SessionContext& getSession() { return session; }
const SessionContext& getSession() const { return session; }
- const ConsumerImpl::shared_ptr find(const std::string& destination) const;
- bool find(const std::string& destination, ConsumerImpl::shared_ptr&) const;
-
+ ConsumerImpl& find(const std::string& destination);
+
/**
* Get named queue, never returns 0.
* @return: named queue
@@ -199,16 +196,16 @@ class SemanticState : private boost::noncopyable {
* @exception: ConnectionException if name="" and session has no default.
*/
boost::shared_ptr<Queue> getQueue(const std::string& name) const;
-
+
bool exists(const std::string& consumerTag);
- void consume(const std::string& destination,
- boost::shared_ptr<Queue> queue,
+ void consume(const std::string& destination,
+ boost::shared_ptr<Queue> queue,
bool ackRequired, bool acquire, bool exclusive,
const std::string& resumeId=std::string(), uint64_t resumeTtl=0,
const framing::FieldTable& = framing::FieldTable());
- bool cancel(const std::string& tag);
+ void cancel(const std::string& tag);
void setWindowMode(const std::string& destination);
void setCreditMode(const std::string& destination);
@@ -221,13 +218,12 @@ class SemanticState : private boost::noncopyable {
void commit(MessageStore* const store);
void rollback();
void selectDtx();
- bool getDtxSelected() const { return dtxSelected; }
void startDtx(const std::string& xid, DtxManager& mgr, bool join);
void endDtx(const std::string& xid, bool fail);
void suspendDtx(const std::string& xid);
void resumeDtx(const std::string& xid);
void recover(bool requeue);
- void deliver(DeliveryRecord& message, bool sync);
+ void deliver(DeliveryRecord& message, bool sync);
void acquire(DeliveryId first, DeliveryId last, DeliveryIds& acquired);
void release(DeliveryId first, DeliveryId last, bool setRedelivered);
void reject(DeliveryId first, DeliveryId last);
@@ -248,12 +244,9 @@ class SemanticState : private boost::noncopyable {
DeliveryRecords& getUnacked() { return unacked; }
framing::SequenceSet getAccumulatedAck() const { return accumulatedAck; }
TxBuffer::shared_ptr getTxBuffer() const { return txBuffer; }
- DtxBuffer::shared_ptr getDtxBuffer() const { return dtxBuffer; }
void setTxBuffer(const TxBuffer::shared_ptr& txb) { txBuffer = txb; }
- void setDtxBuffer(const DtxBuffer::shared_ptr& dtxb) { dtxBuffer = dtxb; txBuffer = dtxb; }
void setAccumulatedAck(const framing::SequenceSet& s) { accumulatedAck = s; }
void record(const DeliveryRecord& delivery);
- DtxBufferMap& getSuspendedXids() { return suspendedXids; }
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/SessionAdapter.cpp b/cpp/src/qpid/broker/SessionAdapter.cpp
index 63c4b660b2..3d62e73185 100644
--- a/cpp/src/qpid/broker/SessionAdapter.cpp
+++ b/cpp/src/qpid/broker/SessionAdapter.cpp
@@ -24,7 +24,6 @@
#include "qpid/log/Statement.h"
#include "qpid/framing/SequenceSet.h"
#include "qpid/management/ManagementAgent.h"
-#include "qpid/broker/SessionState.h"
#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h"
#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h"
#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h"
@@ -65,56 +64,53 @@ void SessionAdapter::ExchangeHandlerImpl::declare(const string& exchange, const
const string& alternateExchange,
bool passive, bool durable, bool /*autoDelete*/, const FieldTable& args){
+ AclModule* acl = getBroker().getAcl();
+ if (acl) {
+ std::map<acl::Property, std::string> params;
+ params.insert(make_pair(acl::PROP_TYPE, type));
+ params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
+ params.insert(make_pair(acl::PROP_PASSIVE, std::string(passive ? _TRUE : _FALSE) ));
+ params.insert(make_pair(acl::PROP_DURABLE, std::string(durable ? _TRUE : _FALSE)));
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_EXCHANGE,exchange,&params) )
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange declare request from " << getConnection().getUserId()));
+ }
+
//TODO: implement autoDelete
Exchange::shared_ptr alternate;
if (!alternateExchange.empty()) {
alternate = getBroker().getExchanges().get(alternateExchange);
}
if(passive){
- AclModule* acl = getBroker().getAcl();
- if (acl) {
- //TODO: why does a passive declare require create
- //permission? The purpose of the passive flag is to state
- //that the exchange should *not* created. For
- //authorisation a passive declare is similar to
- //exchange-query.
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_TYPE, type));
- params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
- params.insert(make_pair(acl::PROP_PASSIVE, _TRUE));
- params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE));
- if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_EXCHANGE,exchange,&params) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange create request from " << getConnection().getUserId()));
- }
Exchange::shared_ptr actual(getBroker().getExchanges().get(exchange));
checkType(actual, type);
checkAlternate(actual, alternate);
- }else{
+ }else{
if(exchange.find("amq.") == 0 || exchange.find("qpid.") == 0) {
throw framing::NotAllowedException(QPID_MSG("Exchange names beginning with \"amq.\" or \"qpid.\" are reserved. (exchange=\"" << exchange << "\")"));
}
try{
- std::pair<Exchange::shared_ptr, bool> response =
- getBroker().createExchange(exchange, type, durable, alternateExchange, args,
- getConnection().getUserId(), getConnection().getUrl());
- if (!response.second) {
- //exchange already there, not created
+ std::pair<Exchange::shared_ptr, bool> response = getBroker().getExchanges().declare(exchange, type, durable, args);
+ if (response.second) {
+ if (alternate) {
+ response.first->setAlternate(alternate);
+ alternate->incAlternateUsers();
+ }
+ if (durable) {
+ getBroker().getStore().create(*response.first, args);
+ }
+ } else {
checkType(response.first, type);
checkAlternate(response.first, alternate);
- ManagementAgent* agent = getBroker().getManagementAgent();
- if (agent)
- agent->raiseEvent(_qmf::EventExchangeDeclare(getConnection().getUrl(),
- getConnection().getUserId(),
- exchange,
- type,
- alternateExchange,
- durable,
- false,
- ManagementAgent::toMap(args),
- "existing"));
}
+
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventExchangeDeclare(getConnection().getUrl(), getConnection().getUserId(), exchange, type,
+ alternateExchange, durable, false, ManagementAgent::toMap(args),
+ response.second ? "created" : "existing"));
+
}catch(UnknownExchangeTypeException& /*e*/){
- throw NotFoundException(QPID_MSG("Exchange type not implemented: " << type));
+ throw CommandInvalidException(QPID_MSG("Exchange type not implemented: " << type));
}
}
}
@@ -138,8 +134,22 @@ void SessionAdapter::ExchangeHandlerImpl::checkAlternate(Exchange::shared_ptr ex
void SessionAdapter::ExchangeHandlerImpl::delete_(const string& name, bool /*ifUnused*/)
{
- //TODO: implement if-unused
- getBroker().deleteExchange(name, getConnection().getUserId(), getConnection().getUrl());
+ AclModule* acl = getBroker().getAcl();
+ if (acl) {
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_DELETE,acl::OBJ_EXCHANGE,name,NULL) )
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange delete request from " << getConnection().getUserId()));
+ }
+
+ //TODO: implement unused
+ Exchange::shared_ptr exchange(getBroker().getExchanges().get(name));
+ if (exchange->inUseAsAlternate()) throw NotAllowedException(QPID_MSG("Exchange in use as alternate-exchange."));
+ if (exchange->isDurable()) getBroker().getStore().destroy(*exchange);
+ if (exchange->getAlternate()) exchange->getAlternate()->decAlternateUsers();
+ getBroker().getExchanges().destroy(name);
+
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventExchangeDelete(getConnection().getUrl(), getConnection().getUserId(), name));
}
ExchangeQueryResult SessionAdapter::ExchangeHandlerImpl::query(const string& name)
@@ -159,19 +169,67 @@ ExchangeQueryResult SessionAdapter::ExchangeHandlerImpl::query(const string& nam
}
void SessionAdapter::ExchangeHandlerImpl::bind(const string& queueName,
- const string& exchangeName, const string& routingKey,
- const FieldTable& arguments)
+ const string& exchangeName, const string& routingKey,
+ const FieldTable& arguments)
{
- getBroker().bind(queueName, exchangeName, routingKey, arguments,
- getConnection().getUserId(), getConnection().getUrl());
+ AclModule* acl = getBroker().getAcl();
+ if (acl) {
+ std::map<acl::Property, std::string> params;
+ params.insert(make_pair(acl::PROP_QUEUENAME, queueName));
+ params.insert(make_pair(acl::PROP_ROUTINGKEY, routingKey));
+
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_BIND,acl::OBJ_EXCHANGE,exchangeName,&params))
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange bind request from " << getConnection().getUserId()));
+ }
+
+ Queue::shared_ptr queue = getQueue(queueName);
+ Exchange::shared_ptr exchange = getBroker().getExchanges().get(exchangeName);
+ if(exchange){
+ string exchangeRoutingKey = routingKey.empty() && queueName.empty() ? queue->getName() : routingKey;
+ if (exchange->bind(queue, exchangeRoutingKey, &arguments)) {
+ queue->bound(exchangeName, routingKey, arguments);
+ if (exchange->isDurable() && queue->isDurable()) {
+ getBroker().getStore().bind(*exchange, *queue, routingKey, arguments);
+ }
+
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventBind(getConnection().getUrl(), getConnection().getUserId(), exchangeName,
+ queueName, exchangeRoutingKey, ManagementAgent::toMap(arguments)));
+ }
+ }else{
+ throw NotFoundException("Bind failed. No such exchange: " + exchangeName);
+ }
}
void SessionAdapter::ExchangeHandlerImpl::unbind(const string& queueName,
const string& exchangeName,
const string& routingKey)
{
- getBroker().unbind(queueName, exchangeName, routingKey,
- getConnection().getUserId(), getConnection().getUrl());
+ AclModule* acl = getBroker().getAcl();
+ if (acl) {
+ std::map<acl::Property, std::string> params;
+ params.insert(make_pair(acl::PROP_QUEUENAME, queueName));
+ params.insert(make_pair(acl::PROP_ROUTINGKEY, routingKey));
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_UNBIND,acl::OBJ_EXCHANGE,exchangeName,&params) )
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange unbind request from " << getConnection().getUserId()));
+ }
+
+ Queue::shared_ptr queue = getQueue(queueName);
+ if (!queue.get()) throw NotFoundException("Unbind failed. No such exchange: " + exchangeName);
+
+ Exchange::shared_ptr exchange = getBroker().getExchanges().get(exchangeName);
+ if (!exchange.get()) throw NotFoundException("Unbind failed. No such exchange: " + exchangeName);
+
+ //TODO: revise unbind to rely solely on binding key (not args)
+ if (exchange->unbind(queue, routingKey, 0)) {
+ if (exchange->isDurable() && queue->isDurable())
+ getBroker().getStore().unbind(*exchange, *queue, routingKey, FieldTable());
+
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventUnbind(getConnection().getUrl(), getConnection().getUserId(), exchangeName, queueName, routingKey));
+ }
}
ExchangeBoundResult SessionAdapter::ExchangeHandlerImpl::bound(const std::string& exchangeName,
@@ -274,42 +332,52 @@ QueueQueryResult SessionAdapter::QueueHandlerImpl::query(const string& name)
void SessionAdapter::QueueHandlerImpl::declare(const string& name, const string& alternateExchange,
bool passive, bool durable, bool exclusive,
bool autoDelete, const qpid::framing::FieldTable& arguments)
-{
+{
+ AclModule* acl = getBroker().getAcl();
+ if (acl) {
+ std::map<acl::Property, std::string> params;
+ params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
+ params.insert(make_pair(acl::PROP_PASSIVE, std::string(passive ? _TRUE : _FALSE) ));
+ 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 UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << getConnection().getUserId()));
+ }
+
+ Exchange::shared_ptr alternate;
+ if (!alternateExchange.empty()) {
+ alternate = getBroker().getExchanges().get(alternateExchange);
+ }
Queue::shared_ptr queue;
if (passive && !name.empty()) {
- AclModule* acl = getBroker().getAcl();
- if (acl) {
- //TODO: why does a passive declare require create
- //permission? The purpose of the passive flag is to state
- //that the queue should *not* created. For
- //authorisation a passive declare is similar to
- //queue-query (or indeed a qmf query).
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
- params.insert(make_pair(acl::PROP_PASSIVE, _TRUE));
- 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 UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << getConnection().getUserId()));
- }
- queue = getQueue(name);
+ queue = getQueue(name);
//TODO: check alternate-exchange is as expected
} else {
- std::pair<Queue::shared_ptr, bool> queue_created =
- getBroker().createQueue(name, durable,
- autoDelete,
- exclusive ? &session : 0,
- alternateExchange,
- arguments,
- getConnection().getUserId(),
- getConnection().getUrl());
+ std::pair<Queue::shared_ptr, bool> queue_created =
+ getBroker().getQueues().declare(name, durable,
+ autoDelete,
+ exclusive ? &session : 0);
queue = queue_created.first;
assert(queue);
if (queue_created.second) { // This is a new queue
+ if (alternate) {
+ queue->setAlternateExchange(alternate);
+ alternate->incAlternateUsers();
+ }
+
+ //apply settings & create persistent record if required
+ try { queue_created.first->create(arguments); }
+ catch (...) { getBroker().getQueues().destroy(name); throw; }
+
+ //add default binding:
+ getBroker().getExchanges().getDefault()->bind(queue, name, 0);
+ queue->bound(getBroker().getExchanges().getDefault()->getName(), name, arguments);
+
//handle automatic cleanup:
if (exclusive) {
exclusiveQueues.push_back(queue);
@@ -318,20 +386,21 @@ void SessionAdapter::QueueHandlerImpl::declare(const string& name, const string&
if (exclusive && queue->setExclusiveOwner(&session)) {
exclusiveQueues.push_back(queue);
}
- ManagementAgent* agent = getBroker().getManagementAgent();
- if (agent)
- agent->raiseEvent(_qmf::EventQueueDeclare(getConnection().getUrl(), getConnection().getUserId(),
- name, durable, exclusive, autoDelete, ManagementAgent::toMap(arguments),
- "existing"));
}
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventQueueDeclare(getConnection().getUrl(), getConnection().getUserId(),
+ name, durable, exclusive, autoDelete, ManagementAgent::toMap(arguments),
+ queue_created.second ? "created" : "existing"));
}
- if (exclusive && !queue->isExclusiveOwner(&session))
+ if (exclusive && !queue->isExclusiveOwner(&session))
throw ResourceLockedException(QPID_MSG("Cannot grant exclusive access to queue "
<< queue->getName()));
-}
-
+}
+
+
void SessionAdapter::QueueHandlerImpl::purge(const string& queue){
AclModule* acl = getBroker().getAcl();
if (acl)
@@ -340,32 +409,40 @@ void SessionAdapter::QueueHandlerImpl::purge(const string& queue){
throw UnauthorizedAccessException(QPID_MSG("ACL denied queue purge request from " << getConnection().getUserId()));
}
getQueue(queue)->purge();
-}
+}
+
+void SessionAdapter::QueueHandlerImpl::delete_(const string& queue, bool ifUnused, bool ifEmpty){
-void SessionAdapter::QueueHandlerImpl::checkDelete(Queue::shared_ptr queue, bool ifUnused, bool ifEmpty)
-{
- if (queue->hasExclusiveOwner() && !queue->isExclusiveOwner(&session)) {
+ AclModule* acl = getBroker().getAcl();
+ if (acl)
+ {
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_DELETE,acl::OBJ_QUEUE,queue,NULL) )
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied queue delete request from " << getConnection().getUserId()));
+ }
+
+ Queue::shared_ptr q = getQueue(queue);
+ if (q->hasExclusiveOwner() && !q->isExclusiveOwner(&session))
throw ResourceLockedException(QPID_MSG("Cannot delete queue "
- << queue->getName() << "; it is exclusive to another session"));
- } else if(ifEmpty && queue->getMessageCount() > 0) {
- throw PreconditionFailedException(QPID_MSG("Cannot delete queue "
- << queue->getName() << "; queue not empty"));
- } else if(ifUnused && queue->getConsumerCount() > 0) {
- throw PreconditionFailedException(QPID_MSG("Cannot delete queue "
- << queue->getName() << "; queue in use"));
- } else if (queue->isExclusiveOwner(&session)) {
+ << queue << "; it is exclusive to another session"));
+ if(ifEmpty && q->getMessageCount() > 0){
+ throw PreconditionFailedException("Queue not empty.");
+ }else if(ifUnused && q->getConsumerCount() > 0){
+ throw PreconditionFailedException("Queue in use.");
+ }else{
//remove the queue from the list of exclusive queues if necessary
- QueueVector::iterator i = std::find(exclusiveQueues.begin(),
- exclusiveQueues.end(),
- queue);
- if (i < exclusiveQueues.end()) exclusiveQueues.erase(i);
- }
-}
-
-void SessionAdapter::QueueHandlerImpl::delete_(const string& queue, bool ifUnused, bool ifEmpty)
-{
- getBroker().deleteQueue(queue, getConnection().getUserId(), getConnection().getUrl(),
- boost::bind(&SessionAdapter::QueueHandlerImpl::checkDelete, this, _1, ifUnused, ifEmpty));
+ if(q->isExclusiveOwner(&getConnection())){
+ QueueVector::iterator i = std::find(getConnection().exclusiveQueues.begin(), getConnection().exclusiveQueues.end(), q);
+ if(i < getConnection().exclusiveQueues.end()) getConnection().exclusiveQueues.erase(i);
+ }
+ q->destroy();
+ getBroker().getQueues().destroy(queue);
+ q->unbind(getBroker().getExchanges(), q);
+
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventQueueDelete(getConnection().getUrl(), getConnection().getUserId(), queue));
+ q->notifyDeleted();
+ }
}
SessionAdapter::MessageHandlerImpl::MessageHandlerImpl(SemanticState& s) :
@@ -431,9 +508,7 @@ SessionAdapter::MessageHandlerImpl::subscribe(const string& queueName,
void
SessionAdapter::MessageHandlerImpl::cancel(const string& destination )
{
- if (!state.cancel(destination)) {
- throw NotFoundException(QPID_MSG("No such subscription: " << destination));
- }
+ state.cancel(destination);
ManagementAgent* agent = getBroker().getManagementAgent();
if (agent)
@@ -512,12 +587,7 @@ framing::MessageResumeResult SessionAdapter::MessageHandlerImpl::resume(const st
-void SessionAdapter::ExecutionHandlerImpl::sync()
-{
- session.addPendingExecutionSync();
- /** @todo KAG - need a generic mechanism to allow a command to returning "not completed" status back to SessionState */
-
-}
+void SessionAdapter::ExecutionHandlerImpl::sync() {} //essentially a no-op
void SessionAdapter::ExecutionHandlerImpl::result(const SequenceNumber& /*commandId*/, const string& /*value*/)
{
diff --git a/cpp/src/qpid/broker/SessionAdapter.h b/cpp/src/qpid/broker/SessionAdapter.h
index 8987c4812f..ca27fb6e1d 100644
--- a/cpp/src/qpid/broker/SessionAdapter.h
+++ b/cpp/src/qpid/broker/SessionAdapter.h
@@ -138,7 +138,6 @@ class Queue;
bool isLocal(const ConnectionToken* t) const;
void destroyExclusiveQueues();
- void checkDelete(boost::shared_ptr<Queue> queue, bool ifUnused, bool ifEmpty);
template <class F> void eachExclusiveQueue(F f)
{
std::for_each(exclusiveQueues.begin(), exclusiveQueues.end(), f);
diff --git a/cpp/src/qpid/broker/SessionContext.h b/cpp/src/qpid/broker/SessionContext.h
index 253ce8dcf2..afbbb2cc22 100644
--- a/cpp/src/qpid/broker/SessionContext.h
+++ b/cpp/src/qpid/broker/SessionContext.h
@@ -46,7 +46,6 @@ class SessionContext : public OwnershipToken, public sys::OutputControl
virtual Broker& getBroker() = 0;
virtual uint16_t getChannel() const = 0;
virtual const SessionId& getSessionId() const = 0;
- virtual void addPendingExecutionSync() = 0;
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/SessionHandler.cpp b/cpp/src/qpid/broker/SessionHandler.cpp
index 752fa55535..69b364ad7b 100644
--- a/cpp/src/qpid/broker/SessionHandler.cpp
+++ b/cpp/src/qpid/broker/SessionHandler.cpp
@@ -40,6 +40,11 @@ SessionHandler::SessionHandler(Connection& c, ChannelId ch)
SessionHandler::~SessionHandler() {}
+namespace {
+ClassId classId(AMQMethodBody* m) { return m ? m->amqpMethodId() : 0; }
+MethodId methodId(AMQMethodBody* m) { return m ? m->amqpClassId() : 0; }
+} // namespace
+
void SessionHandler::connectionException(framing::connection::CloseCode code, const std::string& msg) {
// NOTE: must tell the error listener _before_ calling connection.close()
if (connection.getErrorListener()) connection.getErrorListener()->connectionError(msg);
diff --git a/cpp/src/qpid/broker/SessionState.cpp b/cpp/src/qpid/broker/SessionState.cpp
index 1ab17e9893..1ca7b6dfc1 100644
--- a/cpp/src/qpid/broker/SessionState.cpp
+++ b/cpp/src/qpid/broker/SessionState.cpp
@@ -25,7 +25,6 @@
#include "qpid/broker/SessionManager.h"
#include "qpid/broker/SessionHandler.h"
#include "qpid/broker/RateFlowcontrol.h"
-#include "qpid/sys/ClusterSafe.h"
#include "qpid/sys/Timer.h"
#include "qpid/framing/AMQContentBody.h"
#include "qpid/framing/AMQHeaderBody.h"
@@ -61,9 +60,9 @@ SessionState::SessionState(
semanticState(*this, *this),
adapter(semanticState),
msgBuilder(&broker.getStore()),
+ enqueuedOp(boost::bind(&SessionState::enqueued, this, _1)),
mgmtObject(0),
- rateFlowcontrol(0),
- asyncCommandCompleter(new AsyncCommandCompleter(this))
+ rateFlowcontrol(0)
{
uint32_t maxRate = broker.getOptions().maxSessionRate;
if (maxRate) {
@@ -96,7 +95,6 @@ void SessionState::addManagementObject() {
}
SessionState::~SessionState() {
- asyncCommandCompleter->cancel();
semanticState.closed();
if (mgmtObject != 0)
mgmtObject->resourceDestroy ();
@@ -127,7 +125,6 @@ bool SessionState::isLocal(const ConnectionToken* t) const
void SessionState::detach() {
QPID_LOG(debug, getId() << ": detached on broker.");
- asyncCommandCompleter->detached();
disableOutput();
handler = 0;
if (mgmtObject != 0)
@@ -148,7 +145,6 @@ void SessionState::attach(SessionHandler& h) {
mgmtObject->set_connectionRef (h.getConnection().GetManagementObject()->getObjectId());
mgmtObject->set_channelId (h.getChannel());
}
- asyncCommandCompleter->attached();
}
void SessionState::abort() {
@@ -206,17 +202,15 @@ Manageable::status_t SessionState::ManagementMethod (uint32_t methodId,
}
void SessionState::handleCommand(framing::AMQMethodBody* method, const SequenceNumber& id) {
- currentCommandComplete = true; // assumed, can be overridden by invoker method (this sucks).
Invoker::Result invocation = invoke(adapter, *method);
- if (currentCommandComplete) receiverCompleted(id);
-
+ receiverCompleted(id);
if (!invocation.wasHandled()) {
throw NotImplementedException(QPID_MSG("Not implemented: " << *method));
} else if (invocation.hasResult()) {
getProxy().getExecution().result(id, invocation.getResult());
}
-
- if (method->isSync() && currentCommandComplete) {
+ if (method->isSync()) {
+ incomplete.process(enqueuedOp, true);
sendAcceptAndCompletion();
}
}
@@ -259,14 +253,23 @@ void SessionState::handleContent(AMQFrame& frame, const SequenceNumber& id)
header.setEof(false);
msg->getFrames().append(header);
}
- if (broker.isTimestamping())
- msg->setTimestamp();
msg->setPublisher(&getConnection());
- msg->getIngressCompletion().begin();
semanticState.handle(msg);
msgBuilder.end();
- IncompleteIngressMsgXfer xfer(this, msg);
- msg->getIngressCompletion().end(xfer); // allows msg to complete xfer
+
+ if (msg->isEnqueueComplete()) {
+ enqueued(msg);
+ } else {
+ incomplete.add(msg);
+ }
+
+ //hold up execution until async enqueue is complete
+ if (msg->getFrames().getMethod()->isSync()) {
+ incomplete.process(enqueuedOp, true);
+ sendAcceptAndCompletion();
+ } else {
+ incomplete.process(enqueuedOp, false);
+ }
}
// Handle producer session flow control
@@ -316,41 +319,11 @@ void SessionState::sendAcceptAndCompletion()
sendCompletion();
}
-/** Invoked when the given inbound message is finished being processed
- * by all interested parties (eg. it is done being enqueued to all queues,
- * its credit has been accounted for, etc). At this point, msg is considered
- * by this receiver as 'completed' (as defined by AMQP 0_10)
- */
-void SessionState::completeRcvMsg(SequenceNumber id,
- bool requiresAccept,
- bool requiresSync)
+void SessionState::enqueued(boost::intrusive_ptr<Message> msg)
{
- // Mark this as a cluster-unsafe scope since it can be called in
- // journal threads or connection threads as part of asynchronous
- // command completion.
- sys::ClusterUnsafeScope cus;
-
- bool callSendCompletion = false;
- receiverCompleted(id);
- if (requiresAccept)
- // will cause msg's seq to appear in the next message.accept we send.
- accepted.add(id);
-
- // Are there any outstanding Execution.Sync commands pending the
- // completion of this msg? If so, complete them.
- while (!pendingExecutionSyncs.empty() &&
- receiverGetIncomplete().front() >= pendingExecutionSyncs.front()) {
- const SequenceNumber id = pendingExecutionSyncs.front();
- pendingExecutionSyncs.pop();
- QPID_LOG(debug, getId() << ": delayed execution.sync " << id << " is completed.");
- receiverCompleted(id);
- callSendCompletion = true; // likely peer is pending for this completion.
- }
-
- // if the sender has requested immediate notification of the completion...
- if (requiresSync || callSendCompletion) {
- sendAcceptAndCompletion();
- }
+ receiverCompleted(msg->getCommandId());
+ if (msg->requiresAccept())
+ accepted.add(msg->getCommandId());
}
void SessionState::handleIn(AMQFrame& frame) {
@@ -423,176 +396,4 @@ framing::AMQP_ClientProxy& SessionState::getClusterOrderProxy() {
return handler->getClusterOrderProxy();
}
-
-// Current received command is an execution.sync command.
-// Complete this command only when all preceding commands have completed.
-// (called via the invoker() in handleCommand() above)
-void SessionState::addPendingExecutionSync()
-{
- SequenceNumber syncCommandId = receiverGetCurrent();
- if (receiverGetIncomplete().front() < syncCommandId) {
- currentCommandComplete = false;
- pendingExecutionSyncs.push(syncCommandId);
- asyncCommandCompleter->flushPendingMessages();
- QPID_LOG(debug, getId() << ": delaying completion of execution.sync " << syncCommandId);
- }
-}
-
-
-/** factory for creating a reference-counted IncompleteIngressMsgXfer object
- * which will be attached to a message that will be completed asynchronously.
- */
-boost::intrusive_ptr<AsyncCompletion::Callback>
-SessionState::IncompleteIngressMsgXfer::clone()
-{
- // Optimization: this routine is *only* invoked when the message needs to be asynchronously completed.
- // If the client is pending the message.transfer completion, flush now to force immediate write to journal.
- if (requiresSync)
- msg->flush();
- else {
- // otherwise, we need to track this message in order to flush it if an execution.sync arrives
- // before it has been completed (see flushPendingMessages())
- pending = true;
- completerContext->addPendingMessage(msg);
- }
-
- return boost::intrusive_ptr<SessionState::IncompleteIngressMsgXfer>(new SessionState::IncompleteIngressMsgXfer(*this));
-}
-
-
-/** Invoked by the asynchronous completer associated with a received
- * msg that is pending Completion. May be invoked by the IO thread
- * (sync == true), or some external thread (!sync).
- */
-void SessionState::IncompleteIngressMsgXfer::completed(bool sync)
-{
- if (pending) completerContext->deletePendingMessage(id);
- if (!sync) {
- /** note well: this path may execute in any thread. It is safe to access
- * the scheduledCompleterContext, since *this has a shared pointer to it.
- * but not session!
- */
- session = 0;
- QPID_LOG(debug, ": async completion callback scheduled for msg seq=" << id);
- completerContext->scheduleMsgCompletion(id, requiresAccept, requiresSync);
- } else {
- // this path runs directly from the ac->end() call in handleContent() above,
- // so *session is definately valid.
- if (session->isAttached()) {
- QPID_LOG(debug, ": receive completed for msg seq=" << id);
- session->completeRcvMsg(id, requiresAccept, requiresSync);
- }
- }
- completerContext = boost::intrusive_ptr<AsyncCommandCompleter>();
-}
-
-
-/** Scheduled from an asynchronous command's completed callback to run on
- * the IO thread.
- */
-void SessionState::AsyncCommandCompleter::schedule(boost::intrusive_ptr<AsyncCommandCompleter> ctxt)
-{
- ctxt->completeCommands();
-}
-
-
-/** Track an ingress message that is pending completion */
-void SessionState::AsyncCommandCompleter::addPendingMessage(boost::intrusive_ptr<Message> msg)
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- std::pair<SequenceNumber, boost::intrusive_ptr<Message> > item(msg->getCommandId(), msg);
- bool unique = pendingMsgs.insert(item).second;
- if (!unique) {
- assert(false);
- }
-}
-
-
-/** pending message has completed */
-void SessionState::AsyncCommandCompleter::deletePendingMessage(SequenceNumber id)
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- pendingMsgs.erase(id);
-}
-
-
-/** done when an execution.sync arrives */
-void SessionState::AsyncCommandCompleter::flushPendingMessages()
-{
- std::map<SequenceNumber, boost::intrusive_ptr<Message> > copy;
- {
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- pendingMsgs.swap(copy); // we've only tracked these in case a flush is needed, so nuke 'em now.
- }
- // drop lock, so it is safe to call "flush()"
- for (std::map<SequenceNumber, boost::intrusive_ptr<Message> >::iterator i = copy.begin();
- i != copy.end(); ++i) {
- i->second->flush();
- }
-}
-
-
-/** mark an ingress Message.Transfer command as completed.
- * This method must be thread safe - it may run on any thread.
- */
-void SessionState::AsyncCommandCompleter::scheduleMsgCompletion(SequenceNumber cmd,
- bool requiresAccept,
- bool requiresSync)
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
-
- if (session && isAttached) {
- MessageInfo msg(cmd, requiresAccept, requiresSync);
- completedMsgs.push_back(msg);
- if (completedMsgs.size() == 1) {
- session->getConnection().requestIOProcessing(boost::bind(&schedule,
- session->asyncCommandCompleter));
- }
- }
-}
-
-
-/** Cause the session to complete all completed commands.
- * Executes on the IO thread.
- */
-void SessionState::AsyncCommandCompleter::completeCommands()
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
-
- // when session is destroyed, it clears the session pointer via cancel().
- if (session && session->isAttached()) {
- for (std::vector<MessageInfo>::iterator msg = completedMsgs.begin();
- msg != completedMsgs.end(); ++msg) {
- session->completeRcvMsg(msg->cmd, msg->requiresAccept, msg->requiresSync);
- }
- }
- completedMsgs.clear();
-}
-
-
-/** cancel any pending calls to scheduleComplete */
-void SessionState::AsyncCommandCompleter::cancel()
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- session = 0;
-}
-
-
-/** inform the completer that the session has attached,
- * allows command completion scheduling from any thread */
-void SessionState::AsyncCommandCompleter::attached()
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- isAttached = true;
-}
-
-
-/** inform the completer that the session has detached,
- * disables command completion scheduling from any thread */
-void SessionState::AsyncCommandCompleter::detached()
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- isAttached = false;
-}
-
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/SessionState.h b/cpp/src/qpid/broker/SessionState.h
index 506af85c47..be79eb0eab 100644
--- a/cpp/src/qpid/broker/SessionState.h
+++ b/cpp/src/qpid/broker/SessionState.h
@@ -30,15 +30,13 @@
#include "qmf/org/apache/qpid/broker/Session.h"
#include "qpid/broker/SessionAdapter.h"
#include "qpid/broker/DeliveryAdapter.h"
-#include "qpid/broker/AsyncCompletion.h"
+#include "qpid/broker/IncompleteMessageList.h"
#include "qpid/broker/MessageBuilder.h"
#include "qpid/broker/SessionContext.h"
#include "qpid/broker/SemanticState.h"
-#include "qpid/sys/Monitor.h"
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
-#include <boost/intrusive_ptr.hpp>
#include <set>
#include <vector>
@@ -125,10 +123,6 @@ class SessionState : public qpid::SessionState,
const SessionId& getSessionId() const { return getId(); }
- // Used by ExecutionHandler sync command processing. Notifies
- // the SessionState of a received Execution.Sync command.
- void addPendingExecutionSync();
-
// Used to delay creation of management object for sessions
// belonging to inter-broker bridges
void addManagementObject();
@@ -136,10 +130,7 @@ class SessionState : public qpid::SessionState,
private:
void handleCommand(framing::AMQMethodBody* method, const framing::SequenceNumber& id);
void handleContent(framing::AMQFrame& frame, const framing::SequenceNumber& id);
-
- // indicate that the given ingress msg has been completely received by the
- // broker, and the msg's message.transfer command can be considered completed.
- void completeRcvMsg(SequenceNumber id, bool requiresAccept, bool requiresSync);
+ void enqueued(boost::intrusive_ptr<Message> msg);
void handleIn(framing::AMQFrame& frame);
void handleOut(framing::AMQFrame& frame);
@@ -165,6 +156,8 @@ class SessionState : public qpid::SessionState,
SemanticState semanticState;
SessionAdapter adapter;
MessageBuilder msgBuilder;
+ IncompleteMessageList incomplete;
+ IncompleteMessageList::CompletionListener enqueuedOp;
qmf::org::apache::qpid::broker::Session* mgmtObject;
qpid::framing::SequenceSet accepted;
@@ -173,110 +166,6 @@ class SessionState : public qpid::SessionState,
boost::scoped_ptr<RateFlowcontrol> rateFlowcontrol;
boost::intrusive_ptr<sys::TimerTask> flowControlTimer;
- // sequence numbers for pending received Execution.Sync commands
- std::queue<SequenceNumber> pendingExecutionSyncs;
- bool currentCommandComplete;
-
- /** This class provides a context for completing asynchronous commands in a thread
- * safe manner. Asynchronous commands save their completion state in this class.
- * This class then schedules the completeCommands() method in the IO thread.
- * While running in the IO thread, completeCommands() may safely complete all
- * saved commands without the risk of colliding with other operations on this
- * SessionState.
- */
- class AsyncCommandCompleter : public RefCounted {
- private:
- SessionState *session;
- bool isAttached;
- qpid::sys::Mutex completerLock;
-
- // special-case message.transfer commands for optimization
- struct MessageInfo {
- SequenceNumber cmd; // message.transfer command id
- bool requiresAccept;
- bool requiresSync;
- MessageInfo(SequenceNumber c, bool a, bool s)
- : cmd(c), requiresAccept(a), requiresSync(s) {}
- };
- std::vector<MessageInfo> completedMsgs;
- // If an ingress message does not require a Sync, we need to
- // hold a reference to it in case an Execution.Sync command is received and we
- // have to manually flush the message.
- std::map<SequenceNumber, boost::intrusive_ptr<Message> > pendingMsgs;
-
- /** complete all pending commands, runs in IO thread */
- void completeCommands();
-
- /** for scheduling a run of "completeCommands()" on the IO thread */
- static void schedule(boost::intrusive_ptr<AsyncCommandCompleter>);
-
- public:
- AsyncCommandCompleter(SessionState *s) : session(s), isAttached(s->isAttached()) {};
- ~AsyncCommandCompleter() {};
-
- /** track a message pending ingress completion */
- void addPendingMessage(boost::intrusive_ptr<Message> m);
- void deletePendingMessage(SequenceNumber id);
- void flushPendingMessages();
- /** schedule the processing of a completed ingress message.transfer command */
- void scheduleMsgCompletion(SequenceNumber cmd,
- bool requiresAccept,
- bool requiresSync);
- void cancel(); // called by SessionState destructor.
- void attached(); // called by SessionState on attach()
- void detached(); // called by SessionState on detach()
- };
- boost::intrusive_ptr<AsyncCommandCompleter> asyncCommandCompleter;
-
- /** Abstract class that represents a single asynchronous command that is
- * pending completion.
- */
- class AsyncCommandContext : public AsyncCompletion::Callback
- {
- public:
- AsyncCommandContext( SessionState *ss, SequenceNumber _id )
- : id(_id), completerContext(ss->asyncCommandCompleter) {}
- virtual ~AsyncCommandContext() {}
-
- protected:
- SequenceNumber id;
- boost::intrusive_ptr<AsyncCommandCompleter> completerContext;
- };
-
- /** incomplete Message.transfer commands - inbound to broker from client
- */
- class IncompleteIngressMsgXfer : public SessionState::AsyncCommandContext
- {
- public:
- IncompleteIngressMsgXfer( SessionState *ss,
- boost::intrusive_ptr<Message> m )
- : AsyncCommandContext(ss, m->getCommandId()),
- session(ss),
- msg(m),
- requiresAccept(m->requiresAccept()),
- requiresSync(m->getFrames().getMethod()->isSync()),
- pending(false) {}
- IncompleteIngressMsgXfer( const IncompleteIngressMsgXfer& x )
- : AsyncCommandContext(x.session, x.msg->getCommandId()),
- session(x.session),
- msg(x.msg),
- requiresAccept(x.requiresAccept),
- requiresSync(x.requiresSync),
- pending(x.pending) {}
-
- virtual ~IncompleteIngressMsgXfer() {};
-
- virtual void completed(bool);
- virtual boost::intrusive_ptr<AsyncCompletion::Callback> clone();
-
- private:
- SessionState *session; // only valid if sync flag in callback is true
- boost::intrusive_ptr<Message> msg;
- bool requiresAccept;
- bool requiresSync;
- bool pending; // true if msg saved on pending list...
- };
-
friend class SessionManager;
};
diff --git a/cpp/src/qpid/broker/StatefulQueueObserver.h b/cpp/src/qpid/broker/StatefulQueueObserver.h
deleted file mode 100644
index c682d460b7..0000000000
--- a/cpp/src/qpid/broker/StatefulQueueObserver.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef QPID_BROKER_STATEFULQUEUEOBSERVER_H
-#define QPID_BROKER_STATEFULQUEUEOBSERVER_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-#include "qpid/broker/QueueObserver.h"
-#include "qpid/framing/FieldTable.h"
-
-namespace qpid {
-namespace broker {
-
-/**
- * Specialized type of QueueObserver that maintains internal state that has to
- * be replicated across clustered brokers.
- */
-class StatefulQueueObserver : public QueueObserver
-{
- public:
- StatefulQueueObserver(std::string _id) : id(_id) {}
- virtual ~StatefulQueueObserver() {}
-
- /** This identifier must uniquely identify this particular observer amoung
- * all observers on a queue. For cluster replication, this id will be used
- * to identify the peer queue observer for synchronization across
- * brokers.
- */
- const std::string& getId() const { return id; }
-
- /** This method should return the observer's internal state as an opaque
- * map.
- */
- virtual void getState(qpid::framing::FieldTable& state ) const = 0;
-
- /** The input map represents the internal state of the peer observer that
- * this observer should synchonize to.
- */
- virtual void setState(const qpid::framing::FieldTable&) = 0;
-
-
- private:
- std::string id;
-};
-}} // namespace qpid::broker
-
-#endif /*!QPID_BROKER_STATEFULQUEUEOBSERVER_H*/
diff --git a/cpp/src/qpid/broker/ThresholdAlerts.cpp b/cpp/src/qpid/broker/ThresholdAlerts.cpp
index 3c9e210d4d..4f35884af8 100644
--- a/cpp/src/qpid/broker/ThresholdAlerts.cpp
+++ b/cpp/src/qpid/broker/ThresholdAlerts.cpp
@@ -28,52 +28,6 @@
namespace qpid {
namespace broker {
-namespace {
-const qmf::org::apache::qpid::broker::EventQueueThresholdExceeded EVENT("dummy", 0, 0);
-bool isQMFv2(const boost::intrusive_ptr<Message> message)
-{
- const qpid::framing::MessageProperties* props = message->getProperties<qpid::framing::MessageProperties>();
- return props && props->getAppId() == "qmf2";
-}
-
-bool isThresholdEvent(const boost::intrusive_ptr<Message> message)
-{
- if (message->getIsManagementMessage()) {
- //is this a qmf event? if so is it a threshold event?
- if (isQMFv2(message)) {
- const qpid::framing::FieldTable* headers = message->getApplicationHeaders();
- if (headers && headers->getAsString("qmf.content") == "_event") {
- //decode as list
- std::string content = message->getFrames().getContent();
- qpid::types::Variant::List list;
- qpid::amqp_0_10::ListCodec::decode(content, list);
- if (list.empty() || list.front().getType() != qpid::types::VAR_MAP) return false;
- qpid::types::Variant::Map map = list.front().asMap();
- try {
- std::string eventName = map["_schema_id"].asMap()["_class_name"].asString();
- return eventName == EVENT.getEventName();
- } catch (const std::exception& e) {
- QPID_LOG(error, "Error checking for recursive threshold alert: " << e.what());
- }
- }
- } else {
- std::string content = message->getFrames().getContent();
- qpid::framing::Buffer buffer(const_cast<char*>(content.data()), content.size());
- if (buffer.getOctet() == 'A' && buffer.getOctet() == 'M' && buffer.getOctet() == '2' && buffer.getOctet() == 'e') {
- buffer.getLong();//sequence
- std::string packageName;
- buffer.getShortString(packageName);
- if (packageName != EVENT.getPackageName()) return false;
- std::string eventName;
- buffer.getShortString(eventName);
- return eventName == EVENT.getEventName();
- }
- }
- }
- return false;
-}
-}
-
ThresholdAlerts::ThresholdAlerts(const std::string& n,
qpid::management::ManagementAgent& a,
const uint32_t ct,
@@ -90,14 +44,8 @@ void ThresholdAlerts::enqueued(const QueuedMessage& m)
if ((countThreshold && count >= countThreshold) || (sizeThreshold && size >= sizeThreshold)) {
if ((repeatInterval == 0 && lastAlert == qpid::sys::EPOCH)
|| qpid::sys::Duration(lastAlert, qpid::sys::now()) > repeatInterval) {
- //Note: Raising an event may result in messages being
- //enqueued on queues; it may even be that this event
- //causes a message to be enqueued on the queue we are
- //tracking, and so we need to avoid recursing
- if (isThresholdEvent(m.payload)) return;
- lastAlert = qpid::sys::now();
agent.raiseEvent(qmf::org::apache::qpid::broker::EventQueueThresholdExceeded(name, count, size));
- QPID_LOG(info, "Threshold event triggered for " << name << ", count=" << count << ", size=" << size);
+ lastAlert = qpid::sys::now();
}
}
}
@@ -127,12 +75,12 @@ void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& a
}
void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent,
- const qpid::framing::FieldTable& settings, uint16_t limitRatio)
+ const qpid::framing::FieldTable& settings)
{
qpid::types::Variant::Map map;
qpid::amqp_0_10::translate(settings, map);
- observe(queue, agent, map, limitRatio);
+ observe(queue, agent, map);
}
template <class T>
@@ -170,19 +118,19 @@ class Option
};
void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent,
- const qpid::types::Variant::Map& settings, uint16_t limitRatio)
+ const qpid::types::Variant::Map& settings)
{
//Note: aliases are keys defined by java broker
Option<int64_t> repeatInterval("qpid.alert_repeat_gap", 60);
repeatInterval.addAlias("x-qpid-minimum-alert-repeat-gap");
- //If no explicit threshold settings were given use specified
- //percentage of any limit from the policy.
+ //If no explicit threshold settings were given use 80% of any
+ //limit from the policy.
const QueuePolicy* policy = queue.getPolicy();
- Option<uint32_t> countThreshold("qpid.alert_count", (uint32_t) (policy && limitRatio ? (policy->getMaxCount()*limitRatio/100) : 0));
+ Option<uint32_t> countThreshold("qpid.alert_count", (uint32_t) (policy ? policy->getMaxCount()*0.8 : 0));
countThreshold.addAlias("x-qpid-maximum-message-count");
- Option<uint64_t> sizeThreshold("qpid.alert_size", (uint64_t) (policy && limitRatio ? (policy->getMaxSize()*limitRatio/100) : 0));
+ Option<uint64_t> sizeThreshold("qpid.alert_size", (uint64_t) (policy ? policy->getMaxSize()*0.8 : 0));
sizeThreshold.addAlias("x-qpid-maximum-message-size");
observe(queue, agent, countThreshold.get(settings), sizeThreshold.get(settings), repeatInterval.get(settings));
diff --git a/cpp/src/qpid/broker/ThresholdAlerts.h b/cpp/src/qpid/broker/ThresholdAlerts.h
index 2b4a46b736..e1f59252c4 100644
--- a/cpp/src/qpid/broker/ThresholdAlerts.h
+++ b/cpp/src/qpid/broker/ThresholdAlerts.h
@@ -50,17 +50,14 @@ class ThresholdAlerts : public QueueObserver
const long repeatInterval);
void enqueued(const QueuedMessage&);
void dequeued(const QueuedMessage&);
- void acquired(const QueuedMessage&) {};
- void requeued(const QueuedMessage&) {};
-
static void observe(Queue& queue, qpid::management::ManagementAgent& agent,
const uint64_t countThreshold,
const uint64_t sizeThreshold,
const long repeatInterval);
static void observe(Queue& queue, qpid::management::ManagementAgent& agent,
- const qpid::framing::FieldTable& settings, uint16_t limitRatio);
+ const qpid::framing::FieldTable& settings);
static void observe(Queue& queue, qpid::management::ManagementAgent& agent,
- const qpid::types::Variant::Map& settings, uint16_t limitRatio);
+ const qpid::types::Variant::Map& settings);
private:
const std::string name;
qpid::management::ManagementAgent& agent;
diff --git a/cpp/src/qpid/broker/TopicExchange.cpp b/cpp/src/qpid/broker/TopicExchange.cpp
index 644a3d628e..1b0fe71bcf 100644
--- a/cpp/src/qpid/broker/TopicExchange.cpp
+++ b/cpp/src/qpid/broker/TopicExchange.cpp
@@ -221,7 +221,6 @@ TopicExchange::TopicExchange(const std::string& _name, bool _durable,
bool TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args)
{
- ClearCache cc(&cacheLock,&bindingCache); // clear the cache on function exit.
string fedOp(args ? args->getAsString(qpidFedOp) : fedOpBind);
string fedTags(args ? args->getAsString(qpidFedTags) : "");
string fedOrigin(args ? args->getAsString(qpidFedOrigin) : "");
@@ -250,21 +249,21 @@ bool TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, cons
if (mgmtExchange != 0) {
mgmtExchange->inc_bindingCount();
}
- QPID_LOG(debug, "Binding key [" << routingPattern << "] to queue " << queue->getName()
- << " on exchange " << getName() << " (origin=" << fedOrigin << ")");
+ QPID_LOG(debug, "Bound key [" << routingPattern << "] to queue " << queue->getName()
+ << " (origin=" << fedOrigin << ")");
}
} else if (fedOp == fedOpUnbind) {
- RWlock::ScopedWlock l(lock);
- BindingKey* bk = getQueueBinding(queue, routingPattern);
- if (bk) {
- QPID_LOG(debug, "FedOpUnbind [" << routingPattern << "] from exchange " << getName()
- << " on queue=" << queue->getName() << " origin=" << fedOrigin);
- propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin);
- // if this was the last binding for the queue, delete the binding
- if (bk->fedBinding.countFedBindings(queue->getName()) == 0) {
- deleteBinding(queue, routingPattern, bk);
+ bool reallyUnbind = false;
+ {
+ RWlock::ScopedWlock l(lock);
+ BindingKey* bk = bindingTree.getBindingKey(routingPattern);
+ if (bk) {
+ propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin);
+ reallyUnbind = bk->fedBinding.countFedBindings(queue->getName()) == 0;
}
}
+ if (reallyUnbind)
+ unbind(queue, routingPattern, 0);
} else if (fedOp == fedOpReorigin) {
/** gather up all the keys that need rebinding in a local vector
* while holding the lock. Then propagate once the lock is
@@ -282,38 +281,20 @@ bool TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, cons
}
}
- cc.clearCache(); // clear the cache before we IVE route.
routeIVE();
if (propagate)
propagateFedOp(routingKey, fedTags, fedOp, fedOrigin);
return true;
}
-bool TopicExchange::unbind(Queue::shared_ptr queue, const string& constRoutingKey, const FieldTable* args)
-{
- string fedOrigin(args ? args->getAsString(qpidFedOrigin) : "");
- QPID_LOG(debug, "Unbinding key [" << constRoutingKey << "] from queue " << queue->getName()
- << " on exchange " << getName() << " origin=" << fedOrigin << ")" );
-
- ClearCache cc(&cacheLock,&bindingCache); // clear the cache on function exit.
+bool TopicExchange::unbind(Queue::shared_ptr queue, const string& constRoutingKey, const FieldTable* /*args*/){
RWlock::ScopedWlock l(lock);
string routingKey = normalize(constRoutingKey);
- BindingKey* bk = getQueueBinding(queue, routingKey);
+ BindingKey* bk = bindingTree.getBindingKey(routingKey);
if (!bk) return false;
- bool propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin);
- deleteBinding(queue, routingKey, bk);
- if (propagate)
- propagateFedOp(routingKey, string(), fedOpUnbind, string());
- return true;
-}
-
-
-bool TopicExchange::deleteBinding(Queue::shared_ptr queue,
- const std::string& routingKey,
- BindingKey *bk)
-{
- // Note well: write lock held by caller
Binding::vector& qv(bk->bindingVector);
+ bool propagate = false;
+
Binding::vector::iterator q;
for (q = qv.begin(); q != qv.end(); q++)
if ((*q)->queue == queue)
@@ -322,55 +303,42 @@ bool TopicExchange::deleteBinding(Queue::shared_ptr queue,
qv.erase(q);
assert(nBindings > 0);
nBindings--;
-
+ propagate = bk->fedBinding.delOrigin();
if(qv.empty()) {
bindingTree.removeBindingKey(routingKey);
}
if (mgmtExchange != 0) {
mgmtExchange->dec_bindingCount();
}
- QPID_LOG(debug, "Unbound key [" << routingKey << "] from queue " << queue->getName()
- << " on exchange " << getName());
+ QPID_LOG(debug, "Unbound [" << routingKey << "] from queue " << queue->getName());
+
+ if (propagate)
+ propagateFedOp(routingKey, string(), fedOpUnbind, string());
return true;
}
-/** returns a pointer to the BindingKey if the given queue is bound to this
- * exchange using the routing pattern. 0 if queue binding does not exist.
- */
-TopicExchange::BindingKey *TopicExchange::getQueueBinding(Queue::shared_ptr queue, const string& pattern)
+bool TopicExchange::isBound(Queue::shared_ptr queue, const string& pattern)
{
// Note well: lock held by caller....
BindingKey *bk = bindingTree.getBindingKey(pattern); // Exact match against binding pattern
- if (!bk) return 0;
+ if (!bk) return false;
Binding::vector& qv(bk->bindingVector);
Binding::vector::iterator q;
for (q = qv.begin(); q != qv.end(); q++)
if ((*q)->queue == queue)
break;
- return (q != qv.end()) ? bk : 0;
+ return q != qv.end();
}
void TopicExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/)
{
// Note: PERFORMANCE CRITICAL!!!
- BindingList b;
- std::map<std::string, BindingList>::iterator it;
- { // only lock the cache for read
- RWlock::ScopedRlock cl(cacheLock);
- it = bindingCache.find(routingKey);
- if (it != bindingCache.end()) {
- b = it->second;
- }
- }
+ BindingList b(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >);
PreRoute pr(msg, this);
- if (!b.get()) // no cache hit
+ BindingsFinderIter bindingsFinder(b);
{
RWlock::ScopedRlock l(lock);
- b = BindingList(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >);
- BindingsFinderIter bindingsFinder(b);
bindingTree.iterateMatch(routingKey, bindingsFinder);
- RWlock::ScopedWlock cwl(cacheLock);
- bindingCache[routingKey] = b; // update cache
}
doRoute(msg, b);
}
@@ -380,7 +348,7 @@ bool TopicExchange::isBound(Queue::shared_ptr queue, const string* const routing
RWlock::ScopedRlock l(lock);
if (routingKey && queue) {
string key(normalize(*routingKey));
- return getQueueBinding(queue, key) != 0;
+ return isBound(queue, key);
} else if (!routingKey && !queue) {
return nBindings > 0;
} else if (routingKey) {
diff --git a/cpp/src/qpid/broker/TopicExchange.h b/cpp/src/qpid/broker/TopicExchange.h
index 636918f8a1..a6c457dcb3 100644
--- a/cpp/src/qpid/broker/TopicExchange.h
+++ b/cpp/src/qpid/broker/TopicExchange.h
@@ -56,7 +56,7 @@ class TopicExchange : public virtual Exchange {
// | +-->d-->...
// +-->x-->y-->...
//
- class QPID_BROKER_CLASS_EXTERN BindingNode {
+ class BindingNode {
public:
typedef boost::shared_ptr<BindingNode> shared_ptr;
@@ -135,31 +135,8 @@ class TopicExchange : public virtual Exchange {
BindingNode bindingTree;
unsigned long nBindings;
qpid::sys::RWlock lock; // protects bindingTree and nBindings
- qpid::sys::RWlock cacheLock; // protects cache
- std::map<std::string, BindingList> bindingCache; // cache of matched routes.
- class ClearCache {
- private:
- qpid::sys::RWlock* cacheLock;
- std::map<std::string, BindingList>* bindingCache;
- bool cleared;
- public:
- ClearCache(qpid::sys::RWlock* l, std::map<std::string, BindingList>* bc): cacheLock(l),
- bindingCache(bc),cleared(false) {};
- void clearCache() {
- qpid::sys::RWlock::ScopedWlock l(*cacheLock);
- if (!cleared) {
- bindingCache->clear();
- cleared =true;
- }
- };
- ~ClearCache(){
- clearCache();
- };
- };
- BindingKey *getQueueBinding(Queue::shared_ptr queue, const std::string& pattern);
- bool deleteBinding(Queue::shared_ptr queue,
- const std::string& routingKey,
- BindingKey *bk);
+
+ bool isBound(Queue::shared_ptr queue, const std::string& pattern);
class ReOriginIter;
class BindingsFinderIter;
diff --git a/cpp/src/qpid/broker/TxBuffer.cpp b/cpp/src/qpid/broker/TxBuffer.cpp
index d92e6ace48..b509778e89 100644
--- a/cpp/src/qpid/broker/TxBuffer.cpp
+++ b/cpp/src/qpid/broker/TxBuffer.cpp
@@ -76,5 +76,5 @@ bool TxBuffer::commitLocal(TransactionalStore* const store)
}
void TxBuffer::accept(TxOpConstVisitor& v) const {
- std::for_each(ops.begin(), ops.end(), boost::bind(&TxOp::accept, _1, boost::ref(v)));
+ std::for_each(ops.begin(), ops.end(), boost::bind(&TxOp::accept, _1, boost::ref(v)));
}
diff --git a/cpp/src/qpid/broker/TxPublish.cpp b/cpp/src/qpid/broker/TxPublish.cpp
index 9c2cf4a467..36a451e62c 100644
--- a/cpp/src/qpid/broker/TxPublish.cpp
+++ b/cpp/src/qpid/broker/TxPublish.cpp
@@ -90,7 +90,14 @@ void TxPublish::deliverTo(const boost::shared_ptr<Queue>& queue){
void TxPublish::prepare(TransactionContext* ctxt, const boost::shared_ptr<Queue> queue)
{
- queue->enqueue(ctxt, msg);
+ 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
+ */
+ msg->enqueueComplete();
+ }
}
TxPublish::Commit::Commit(intrusive_ptr<Message>& _msg) : msg(_msg){}
diff --git a/cpp/src/qpid/broker/TxPublish.h b/cpp/src/qpid/broker/TxPublish.h
index dba7878af2..effa585676 100644
--- a/cpp/src/qpid/broker/TxPublish.h
+++ b/cpp/src/qpid/broker/TxPublish.h
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -34,58 +34,57 @@
#include <boost/intrusive_ptr.hpp>
namespace qpid {
-namespace broker {
-/**
- * Defines the behaviour for publish operations on a
- * transactional channel. Messages are routed through
- * exchanges when received but are not at that stage delivered
- * to the matching queues, rather the queues are held in an
- * instance of this class. On prepare() the message is marked
- * enqueued to the relevant queues in the MessagesStore. On
- * commit() the messages will be passed to the queue for
- * dispatch or to be added to the in-memory queue.
- */
-class QPID_BROKER_CLASS_EXTERN TxPublish : public TxOp, public Deliverable{
+ namespace broker {
+ /**
+ * Defines the behaviour for publish operations on a
+ * transactional channel. Messages are routed through
+ * exchanges when received but are not at that stage delivered
+ * to the matching queues, rather the queues are held in an
+ * instance of this class. On prepare() the message is marked
+ * enqueued to the relevant queues in the MessagesStore. On
+ * commit() the messages will be passed to the queue for
+ * dispatch or to be added to the in-memory queue.
+ */
+ class TxPublish : public TxOp, public Deliverable{
- class Commit{
- boost::intrusive_ptr<Message>& msg;
- public:
- Commit(boost::intrusive_ptr<Message>& msg);
- void operator()(const boost::shared_ptr<Queue>& queue);
- };
- class Rollback{
- boost::intrusive_ptr<Message>& msg;
- public:
- Rollback(boost::intrusive_ptr<Message>& msg);
- void operator()(const boost::shared_ptr<Queue>& queue);
- };
+ class Commit{
+ boost::intrusive_ptr<Message>& msg;
+ public:
+ Commit(boost::intrusive_ptr<Message>& msg);
+ void operator()(const boost::shared_ptr<Queue>& queue);
+ };
+ class Rollback{
+ boost::intrusive_ptr<Message>& msg;
+ public:
+ Rollback(boost::intrusive_ptr<Message>& msg);
+ void operator()(const boost::shared_ptr<Queue>& queue);
+ };
- boost::intrusive_ptr<Message> msg;
- std::list<boost::shared_ptr<Queue> > queues;
- std::list<boost::shared_ptr<Queue> > prepared;
+ boost::intrusive_ptr<Message> msg;
+ std::list<boost::shared_ptr<Queue> > queues;
+ std::list<boost::shared_ptr<Queue> > prepared;
- void prepare(TransactionContext* ctxt, boost::shared_ptr<Queue>);
+ void prepare(TransactionContext* ctxt, boost::shared_ptr<Queue>);
- public:
- QPID_BROKER_EXTERN TxPublish(boost::intrusive_ptr<Message> msg);
- QPID_BROKER_EXTERN virtual bool prepare(TransactionContext* ctxt) throw();
- QPID_BROKER_EXTERN virtual void commit() throw();
- QPID_BROKER_EXTERN virtual void rollback() throw();
+ public:
+ QPID_BROKER_EXTERN TxPublish(boost::intrusive_ptr<Message> msg);
+ QPID_BROKER_EXTERN virtual bool prepare(TransactionContext* ctxt) throw();
+ QPID_BROKER_EXTERN virtual void commit() throw();
+ QPID_BROKER_EXTERN virtual void rollback() throw();
- virtual Message& getMessage() { return *msg; };
+ virtual Message& getMessage() { return *msg; };
+
+ QPID_BROKER_EXTERN virtual void deliverTo(const boost::shared_ptr<Queue>& queue);
- QPID_BROKER_EXTERN virtual void deliverTo(const boost::shared_ptr<Queue>& queue);
+ virtual ~TxPublish(){}
+ virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); }
- virtual ~TxPublish(){}
- virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); }
+ QPID_BROKER_EXTERN uint64_t contentSize();
- QPID_BROKER_EXTERN uint64_t contentSize();
-
- boost::intrusive_ptr<Message> getMessage() const { return msg; }
- const std::list<boost::shared_ptr<Queue> >& getQueues() const { return queues; }
- const std::list<boost::shared_ptr<Queue> >& getPrepared() const { return prepared; }
-};
-}
+ boost::intrusive_ptr<Message> getMessage() const { return msg; }
+ const std::list<boost::shared_ptr<Queue> > getQueues() const { return queues; }
+ };
+ }
}
diff --git a/cpp/src/qpid/broker/windows/BrokerDefaults.cpp b/cpp/src/qpid/broker/windows/BrokerDefaults.cpp
index b65440b5ad..b6862f0418 100644
--- a/cpp/src/qpid/broker/windows/BrokerDefaults.cpp
+++ b/cpp/src/qpid/broker/windows/BrokerDefaults.cpp
@@ -31,16 +31,10 @@ const std::string Broker::Options::DEFAULT_DATA_DIR_NAME("\\QPIDD.DATA");
std::string
Broker::Options::getHome() {
std::string home;
-#ifdef _MSC_VER
char home_c[MAX_PATH+1];
size_t unused;
if (0 == getenv_s (&unused, home_c, sizeof(home_c), "HOME"))
home += home_c;
-#else
- char *home_c = getenv("HOME");
- if (home_c)
- home += home_c;
-#endif
return home;
}
diff --git a/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp b/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
index 2acc09cded..608a8f7dae 100644
--- a/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
+++ b/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
@@ -42,7 +42,7 @@ public:
NullAuthenticator(Connection& connection);
~NullAuthenticator();
void getMechanisms(framing::Array& mechanisms);
- void start(const std::string& mechanism, const std::string* response);
+ void start(const std::string& mechanism, const std::string& response);
void step(const std::string&) {}
std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize);
};
@@ -57,7 +57,7 @@ public:
SspiAuthenticator(Connection& connection);
~SspiAuthenticator();
void getMechanisms(framing::Array& mechanisms);
- void start(const std::string& mechanism, const std::string* response);
+ void start(const std::string& mechanism, const std::string& response);
void step(const std::string& response);
std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize);
};
@@ -93,15 +93,14 @@ NullAuthenticator::~NullAuthenticator() {}
void NullAuthenticator::getMechanisms(Array& mechanisms)
{
mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("ANONYMOUS")));
- mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("PLAIN")));
}
-void NullAuthenticator::start(const string& mechanism, const string* response)
+void NullAuthenticator::start(const string& mechanism, const string& response)
{
QPID_LOG(warning, "SASL: No Authentication Performed");
if (mechanism == "PLAIN") { // Old behavior
- if (response && response->size() > 0 && (*response).c_str()[0] == (char) 0) {
- string temp = response->substr(1);
+ if (response.size() > 0 && response[0] == (char) 0) {
+ string temp = response.substr(1);
string::size_type i = temp.find((char)0);
string uid = temp.substr(0, i);
string pwd = temp.substr(i + 1);
@@ -139,7 +138,7 @@ void SspiAuthenticator::getMechanisms(Array& mechanisms)
QPID_LOG(info, "SASL: Mechanism list: ANONYMOUS PLAIN");
}
-void SspiAuthenticator::start(const string& mechanism, const string* response)
+void SspiAuthenticator::start(const string& mechanism, const string& response)
{
QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism);
if (mechanism == "ANONYMOUS") {
@@ -152,19 +151,16 @@ void SspiAuthenticator::start(const string& mechanism, const string* response)
// PLAIN's response is composed of 3 strings separated by 0 bytes:
// authorization id, authentication id (user), clear-text password.
- if (!response || response->size() == 0)
+ if (response.size() == 0)
throw ConnectionForcedException("Authentication failed");
- string::size_type i = response->find((char)0);
- string auth = response->substr(0, i);
- string::size_type j = response->find((char)0, i+1);
- string uid = response->substr(i+1, j-1);
- string pwd = response->substr(j+1);
- string dot(".");
+ string::size_type i = response.find((char)0);
+ string auth = response.substr(0, i);
+ string::size_type j = response.find((char)0, i+1);
+ string uid = response.substr(i+1, j-1);
+ string pwd = response.substr(j+1);
int error = 0;
- if (!LogonUser(const_cast<char*>(uid.c_str()),
- const_cast<char*>(dot.c_str()),
- const_cast<char*>(pwd.c_str()),
+ if (!LogonUser(uid.c_str(), ".", pwd.c_str(),
LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT,
&userToken))
@@ -180,7 +176,7 @@ void SspiAuthenticator::start(const string& mechanism, const string* response)
client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0);
}
-void SspiAuthenticator::step(const string& /*response*/)
+void SspiAuthenticator::step(const string& response)
{
QPID_LOG(info, "SASL: Need another step!!!");
}
diff --git a/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp b/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp
index 1dff1ddc8f..fd0e537192 100644
--- a/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp
+++ b/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp
@@ -27,14 +27,10 @@
#include "qpid/sys/AsynchIOHandler.h"
#include "qpid/sys/ConnectionCodec.h"
#include "qpid/sys/Socket.h"
-#include "qpid/sys/SocketAddress.h"
#include "qpid/sys/SystemInfo.h"
#include "qpid/sys/windows/SslAsynchIO.h"
-
#include <boost/bind.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
#include <memory>
-
// security.h needs to see this to distinguish from kernel use.
#define SECURITY_WIN32
#include <security.h>
@@ -72,10 +68,9 @@ struct SslServerOptions : qpid::Options
};
class SslProtocolFactory : public qpid::sys::ProtocolFactory {
+ qpid::sys::Socket listener;
const bool tcpNoDelay;
- boost::ptr_vector<Socket> listeners;
- boost::ptr_vector<AsynchAcceptor> acceptors;
- uint16_t listeningPort;
+ const uint16_t listeningPort;
std::string brokerHost;
const bool clientAuthSelected;
std::auto_ptr<qpid::sys::AsynchAcceptor> acceptor;
@@ -83,14 +78,15 @@ class SslProtocolFactory : public qpid::sys::ProtocolFactory {
CredHandle credHandle;
public:
- SslProtocolFactory(const SslServerOptions&, const std::string& host, const std::string& port, int backlog, bool nodelay);
+ SslProtocolFactory(const SslServerOptions&, int backlog, bool nodelay);
~SslProtocolFactory();
void accept(sys::Poller::shared_ptr, sys::ConnectionCodec::Factory*);
- void connect(sys::Poller::shared_ptr, const std::string& host, const std::string& port,
+ void connect(sys::Poller::shared_ptr, const std::string& host, int16_t port,
sys::ConnectionCodec::Factory*,
ConnectFailedCallback failed);
uint16_t getPort() const;
+ std::string getHost() const;
bool supports(const std::string& capability);
private:
@@ -119,7 +115,6 @@ static struct SslPlugin : public Plugin {
try {
const broker::Broker::Options& opts = broker->getOptions();
ProtocolFactory::shared_ptr protocol(new SslProtocolFactory(options,
- "", boost::lexical_cast<std::string>(options.port),
opts.connectionBacklog,
opts.tcpNoDelay));
QPID_LOG(notice, "Listening for SSL connections on TCP port " << protocol->getPort());
@@ -132,13 +127,12 @@ static struct SslPlugin : public Plugin {
} sslPlugin;
SslProtocolFactory::SslProtocolFactory(const SslServerOptions& options,
- const std::string& host, const std::string& port, int backlog,
+ int backlog,
bool nodelay)
: tcpNoDelay(nodelay),
+ listeningPort(listener.listen(options.port, backlog)),
clientAuthSelected(options.clientAuth) {
- // Make sure that certificate store is good before listening to sockets
- // to avoid having open and listening sockets when there is no cert store
SecInvalidateHandle(&credHandle);
// Get the certificate for this server.
@@ -183,23 +177,6 @@ SslProtocolFactory::SslProtocolFactory(const SslServerOptions& options,
throw QPID_WINDOWS_ERROR(status);
::CertFreeCertificateContext(certContext);
::CertCloseStore(certStoreHandle, 0);
-
- // Listen to socket(s)
- SocketAddress sa(host, port);
-
- // We must have at least one resolved address
- QPID_LOG(info, "SSL Listening to: " << sa.asString())
- Socket* s = new Socket;
- listeningPort = s->listen(sa, backlog);
- listeners.push_back(s);
-
- // Try any other resolved addresses
- while (sa.nextAddress()) {
- QPID_LOG(info, "SSL Listening to: " << sa.asString())
- Socket* s = new Socket;
- s->listen(sa, backlog);
- listeners.push_back(s);
- }
}
SslProtocolFactory::~SslProtocolFactory() {
@@ -260,19 +237,21 @@ uint16_t SslProtocolFactory::getPort() const {
return listeningPort; // Immutable no need for lock.
}
+std::string SslProtocolFactory::getHost() const {
+ return listener.getSockname();
+}
+
void SslProtocolFactory::accept(sys::Poller::shared_ptr poller,
sys::ConnectionCodec::Factory* fact) {
- for (unsigned i = 0; i<listeners.size(); ++i) {
- acceptors.push_back(
- AsynchAcceptor::create(listeners[i],
- boost::bind(&SslProtocolFactory::established, this, poller, _1, fact, false)));
- acceptors[i].start(poller);
- }
+ acceptor.reset(
+ AsynchAcceptor::create(listener,
+ boost::bind(&SslProtocolFactory::established, this, poller, _1, fact, false)));
+ acceptor->start(poller);
}
void SslProtocolFactory::connect(sys::Poller::shared_ptr poller,
const std::string& host,
- const std::string& port,
+ int16_t port,
sys::ConnectionCodec::Factory* fact,
ConnectFailedCallback failed)
{
diff --git a/cpp/src/qpid/client/ConnectionHandler.cpp b/cpp/src/qpid/client/ConnectionHandler.cpp
index ab0d8e0700..8dc1e8338a 100644
--- a/cpp/src/qpid/client/ConnectionHandler.cpp
+++ b/cpp/src/qpid/client/ConnectionHandler.cpp
@@ -22,7 +22,6 @@
#include "qpid/client/ConnectionHandler.h"
#include "qpid/SaslFactory.h"
-#include "qpid/StringUtils.h"
#include "qpid/client/Bounds.h"
#include "qpid/framing/amqp_framing.h"
#include "qpid/framing/all_method_bodies.h"
@@ -143,9 +142,7 @@ void ConnectionHandler::outgoing(AMQFrame& frame)
void ConnectionHandler::waitForOpen()
{
waitFor(ESTABLISHED);
- if (getState() == FAILED) {
- throw TransportFailure(errorText);
- } else if (getState() == CLOSED) {
+ if (getState() == FAILED || getState() == CLOSED) {
throw ConnectionException(errorCode, errorText);
}
}
@@ -205,24 +202,6 @@ void ConnectionHandler::fail(const std::string& message)
namespace {
std::string SPACE(" ");
-
-std::string join(const std::vector<std::string>& in)
-{
- std::string result;
- for (std::vector<std::string>::const_iterator i = in.begin(); i != in.end(); ++i) {
- if (result.size()) result += SPACE;
- result += *i;
- }
- return result;
-}
-
-void intersection(const std::vector<std::string>& a, const std::vector<std::string>& b, std::vector<std::string>& results)
-{
- for (std::vector<std::string>::const_iterator i = a.begin(); i != a.end(); ++i) {
- if (std::find(b.begin(), b.end(), *i) != b.end()) results.push_back(*i);
- }
-}
-
}
void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& mechanisms, const Array& /*locales*/)
@@ -237,35 +216,26 @@ void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& me
maxSsf
);
- std::vector<std::string> mechlist;
- if (mechanism.empty()) {
- //mechlist is simply what the server offers
- mechanisms.collect(mechlist);
- } else {
- //mechlist is the intersection of those indicated by user and
- //those supported by server, in the order listed by user
- std::vector<std::string> allowed = split(mechanism, " ");
- std::vector<std::string> supported;
- mechanisms.collect(supported);
- intersection(allowed, supported, mechlist);
- if (mechlist.empty()) {
- throw Exception(QPID_MSG("Desired mechanism(s) not valid: " << mechanism << " (supported: " << join(supported) << ")"));
+ std::string mechlist;
+ bool chosenMechanismSupported = mechanism.empty();
+ for (Array::const_iterator i = mechanisms.begin(); i != mechanisms.end(); ++i) {
+ if (!mechanism.empty() && mechanism == (*i)->get<std::string>()) {
+ chosenMechanismSupported = true;
+ mechlist = (*i)->get<std::string>() + SPACE + mechlist;
+ } else {
+ if (i != mechanisms.begin()) mechlist += SPACE;
+ mechlist += (*i)->get<std::string>();
}
}
+ if (!chosenMechanismSupported) {
+ fail("Selected mechanism not supported: " + mechanism);
+ }
+
if (sasl.get()) {
- string response;
- if (sasl->start(join(mechlist), response, getSecuritySettings ? getSecuritySettings() : 0)) {
- proxy.startOk(properties, sasl->getMechanism(), response, locale);
- } else {
- //response was null
- ConnectionStartOkBody body;
- body.setClientProperties(properties);
- body.setMechanism(sasl->getMechanism());
- //Don't set response, as none was given
- body.setLocale(locale);
- proxy.send(body);
- }
+ string response = sasl->start(mechanism.empty() ? mechlist : mechanism,
+ getSecuritySettings ? getSecuritySettings() : 0);
+ proxy.startOk(properties, sasl->getMechanism(), response, locale);
} else {
//TODO: verify that desired mechanism and locale are supported
string response = ((char)0) + username + ((char)0) + password;
diff --git a/cpp/src/qpid/client/ConnectionImpl.cpp b/cpp/src/qpid/client/ConnectionImpl.cpp
index db97f1e0f4..40c004f166 100644
--- a/cpp/src/qpid/client/ConnectionImpl.cpp
+++ b/cpp/src/qpid/client/ConnectionImpl.cpp
@@ -36,7 +36,6 @@
#include <boost/bind.hpp>
#include <boost/format.hpp>
-#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <limits>
@@ -259,16 +258,16 @@ void ConnectionImpl::open()
connector->setInputHandler(&handler);
connector->setShutdownHandler(this);
try {
- std::string p = boost::lexical_cast<std::string>(port);
- connector->connect(host, p);
-
+ connector->connect(host, port);
+
} catch (const std::exception& e) {
QPID_LOG(debug, "Failed to connect to " << protocol << ":" << host << ":" << port << " " << e.what());
connector.reset();
- throw TransportFailure(e.what());
+ throw;
}
connector->init();
-
+ QPID_LOG(info, *this << " connected to " << protocol << ":" << host << ":" << port);
+
// Enable heartbeat if requested
uint16_t heartbeat = static_cast<ConnectionSettings&>(handler).heartbeat;
if (heartbeat) {
@@ -282,7 +281,6 @@ void ConnectionImpl::open()
// - in that case in connector.reset() above;
// - or when we are deleted
handler.waitForOpen();
- QPID_LOG(info, *this << " connected to " << protocol << ":" << host << ":" << port);
// If the SASL layer has provided an "operational" userId for the connection,
// put it in the negotiated settings.
diff --git a/cpp/src/qpid/client/Connector.h b/cpp/src/qpid/client/Connector.h
index bc611ffe0d..586012f9d6 100644
--- a/cpp/src/qpid/client/Connector.h
+++ b/cpp/src/qpid/client/Connector.h
@@ -61,7 +61,7 @@ class Connector : public framing::OutputHandler
static void registerFactory(const std::string& proto, Factory* connectorFactory);
virtual ~Connector() {};
- virtual void connect(const std::string& host, const std::string& port) = 0;
+ virtual void connect(const std::string& host, int port) = 0;
virtual void init() {};
virtual void close() = 0;
virtual void send(framing::AMQFrame& frame) = 0;
diff --git a/cpp/src/qpid/client/RdmaConnector.cpp b/cpp/src/qpid/client/RdmaConnector.cpp
index 664640f5e7..6af607198c 100644
--- a/cpp/src/qpid/client/RdmaConnector.cpp
+++ b/cpp/src/qpid/client/RdmaConnector.cpp
@@ -95,7 +95,7 @@ class RdmaConnector : public Connector, public sys::Codec
std::string identifier;
- void connect(const std::string& host, const std::string& port);
+ void connect(const std::string& host, int port);
void close();
void send(framing::AMQFrame& frame);
void abort() {} // TODO: need to fix this for heartbeat timeouts to work
@@ -173,7 +173,7 @@ RdmaConnector::~RdmaConnector() {
}
}
-void RdmaConnector::connect(const std::string& host, const std::string& port){
+void RdmaConnector::connect(const std::string& host, int port){
Mutex::ScopedLock l(dataConnectedLock);
assert(!dataConnected);
@@ -184,7 +184,7 @@ void RdmaConnector::connect(const std::string& host, const std::string& port){
boost::bind(&RdmaConnector::disconnected, this),
boost::bind(&RdmaConnector::rejected, this, poller, _1, _2));
- SocketAddress sa(host, port);
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
acon->start(poller, sa);
}
diff --git a/cpp/src/qpid/client/SessionImpl.cpp b/cpp/src/qpid/client/SessionImpl.cpp
index 7cf4ef648e..b507625b11 100644
--- a/cpp/src/qpid/client/SessionImpl.cpp
+++ b/cpp/src/qpid/client/SessionImpl.cpp
@@ -170,7 +170,6 @@ Demux& SessionImpl::getDemux()
void SessionImpl::waitForCompletion(const SequenceNumber& id)
{
Lock l(state);
- sys::Waitable::ScopedWait w(state);
waitForCompletionImpl(id);
}
diff --git a/cpp/src/qpid/client/SslConnector.cpp b/cpp/src/qpid/client/SslConnector.cpp
index 26c2335eda..35c7e6bdf6 100644
--- a/cpp/src/qpid/client/SslConnector.cpp
+++ b/cpp/src/qpid/client/SslConnector.cpp
@@ -114,7 +114,7 @@ class SslConnector : public Connector
std::string identifier;
- void connect(const std::string& host, const std::string& port);
+ void connect(const std::string& host, int port);
void init();
void close();
void send(framing::AMQFrame& frame);
@@ -190,14 +190,14 @@ SslConnector::~SslConnector() {
close();
}
-void SslConnector::connect(const std::string& host, const std::string& port){
+void SslConnector::connect(const std::string& host, int port){
Mutex::ScopedLock l(closedLock);
assert(closed);
try {
socket.connect(host, port);
} catch (const std::exception& e) {
socket.close();
- throw TransportFailure(e.what());
+ throw ConnectionException(framing::connection::CLOSE_CODE_FRAMING_ERROR, e.what());
}
identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress());
diff --git a/cpp/src/qpid/client/TCPConnector.cpp b/cpp/src/qpid/client/TCPConnector.cpp
index 0070b24ec0..e284d57bec 100644
--- a/cpp/src/qpid/client/TCPConnector.cpp
+++ b/cpp/src/qpid/client/TCPConnector.cpp
@@ -88,7 +88,7 @@ TCPConnector::~TCPConnector() {
close();
}
-void TCPConnector::connect(const std::string& host, const std::string& port) {
+void TCPConnector::connect(const std::string& host, int port) {
Mutex::ScopedLock l(lock);
assert(closed);
connector = AsynchConnector::create(
@@ -117,11 +117,11 @@ void TCPConnector::connected(const Socket&) {
void TCPConnector::start(sys::AsynchIO* aio_) {
aio = aio_;
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < 32; i++) {
aio->queueReadBuffer(new Buff(maxFrameSize));
}
- identifier = str(format("[%1%]") % socket.getFullAddress());
+ identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress());
}
void TCPConnector::initAmqp() {
diff --git a/cpp/src/qpid/client/TCPConnector.h b/cpp/src/qpid/client/TCPConnector.h
index eb3f696013..c756469182 100644
--- a/cpp/src/qpid/client/TCPConnector.h
+++ b/cpp/src/qpid/client/TCPConnector.h
@@ -98,7 +98,7 @@ class TCPConnector : public Connector, public sys::Codec
protected:
virtual ~TCPConnector();
- void connect(const std::string& host, const std::string& port);
+ void connect(const std::string& host, int port);
void start(sys::AsynchIO* aio_);
void initAmqp();
virtual void connectFailed(const std::string& msg);
diff --git a/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp b/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp
index d2accddcd0..bfb20118b5 100644
--- a/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp
+++ b/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp
@@ -30,23 +30,12 @@ void AcceptTracker::State::accept()
unaccepted.clear();
}
-SequenceSet AcceptTracker::State::accept(qpid::framing::SequenceNumber id, bool cumulative)
+void AcceptTracker::State::accept(qpid::framing::SequenceNumber id)
{
- SequenceSet accepting;
- if (cumulative) {
- for (SequenceSet::iterator i = unaccepted.begin(); i != unaccepted.end() && *i <= id; ++i) {
- accepting.add(*i);
- }
- unconfirmed.add(accepting);
- unaccepted.remove(accepting);
- } else {
- if (unaccepted.contains(id)) {
- unaccepted.remove(id);
- unconfirmed.add(id);
- accepting.add(id);
- }
+ if (unaccepted.contains(id)) {
+ unaccepted.remove(id);
+ unconfirmed.add(id);
}
- return accepting;
}
void AcceptTracker::State::release()
@@ -70,18 +59,6 @@ void AcceptTracker::delivered(const std::string& destination, const qpid::framin
destinationState[destination].unaccepted.add(id);
}
-namespace
-{
-const size_t FLUSH_FREQUENCY = 1024;
-}
-
-void AcceptTracker::addToPending(qpid::client::AsyncSession& session, const Record& record)
-{
- pending.push_back(record);
- if (pending.size() % FLUSH_FREQUENCY == 0) session.flush();
-}
-
-
void AcceptTracker::accept(qpid::client::AsyncSession& session)
{
for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) {
@@ -90,19 +67,20 @@ void AcceptTracker::accept(qpid::client::AsyncSession& session)
Record record;
record.status = session.messageAccept(aggregateState.unaccepted);
record.accepted = aggregateState.unaccepted;
- addToPending(session, record);
+ pending.push_back(record);
aggregateState.accept();
}
-void AcceptTracker::accept(qpid::framing::SequenceNumber id, qpid::client::AsyncSession& session, bool cumulative)
+void AcceptTracker::accept(qpid::framing::SequenceNumber id, qpid::client::AsyncSession& session)
{
for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) {
- i->second.accept(id, cumulative);
+ i->second.accept(id);
}
Record record;
- record.accepted = aggregateState.accept(id, cumulative);
+ record.accepted.add(id);
record.status = session.messageAccept(record.accepted);
- addToPending(session, record);
+ pending.push_back(record);
+ aggregateState.accept(id);
}
void AcceptTracker::release(qpid::client::AsyncSession& session)
diff --git a/cpp/src/qpid/client/amqp0_10/AcceptTracker.h b/cpp/src/qpid/client/amqp0_10/AcceptTracker.h
index 85209c3b87..87890e41cc 100644
--- a/cpp/src/qpid/client/amqp0_10/AcceptTracker.h
+++ b/cpp/src/qpid/client/amqp0_10/AcceptTracker.h
@@ -42,7 +42,7 @@ class AcceptTracker
public:
void delivered(const std::string& destination, const qpid::framing::SequenceNumber& id);
void accept(qpid::client::AsyncSession&);
- void accept(qpid::framing::SequenceNumber, qpid::client::AsyncSession&, bool cumulative);
+ void accept(qpid::framing::SequenceNumber, qpid::client::AsyncSession&);
void release(qpid::client::AsyncSession&);
uint32_t acceptsPending();
uint32_t acceptsPending(const std::string& destination);
@@ -62,7 +62,7 @@ class AcceptTracker
qpid::framing::SequenceSet unconfirmed;
void accept();
- qpid::framing::SequenceSet accept(qpid::framing::SequenceNumber, bool cumulative);
+ void accept(qpid::framing::SequenceNumber);
void release();
uint32_t acceptsPending();
void completed(qpid::framing::SequenceSet&);
@@ -79,7 +79,6 @@ class AcceptTracker
StateMap destinationState;
Records pending;
- void addToPending(qpid::client::AsyncSession&, const Record&);
void checkPending();
void completed(qpid::framing::SequenceSet&);
};
diff --git a/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp b/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
index 16e5fde075..f1295a3b66 100644
--- a/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
+++ b/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
@@ -129,10 +129,6 @@ const std::string HEADERS_EXCHANGE("headers");
const std::string XML_EXCHANGE("xml");
const std::string WILDCARD_ANY("#");
-//exchange prefixes:
-const std::string PREFIX_AMQ("amq.");
-const std::string PREFIX_QPID("qpid.");
-
const Verifier verifier;
}
@@ -203,7 +199,6 @@ class Exchange : protected Node
void checkCreate(qpid::client::AsyncSession&, CheckMode);
void checkAssert(qpid::client::AsyncSession&, CheckMode);
void checkDelete(qpid::client::AsyncSession&, CheckMode);
- bool isReservedName();
protected:
const std::string specifiedType;
@@ -238,8 +233,6 @@ class Subscription : public Exchange, public MessageSource
const bool reliable;
const bool durable;
const std::string actualType;
- const bool exclusiveQueue;
- const bool exclusiveSubscription;
FieldTable queueOptions;
FieldTable subscriptionOptions;
Bindings bindings;
@@ -314,7 +307,6 @@ struct Opt
Opt& operator/(const std::string& name);
operator bool() const;
std::string str() const;
- bool asBool(bool defaultValue) const;
const Variant::List& asList() const;
void collect(qpid::framing::FieldTable& args) const;
@@ -346,12 +338,6 @@ Opt::operator bool() const
return value && !value->isVoid() && value->asBool();
}
-bool Opt::asBool(bool defaultValue) const
-{
- if (value) return value->asBool();
- else return defaultValue;
-}
-
std::string Opt::str() const
{
if (value) return value->asString();
@@ -495,7 +481,7 @@ std::string Subscription::getSubscriptionName(const std::string& base, const std
if (name.empty()) {
return (boost::format("%1%_%2%") % base % Uuid(true).str()).str();
} else {
- return name;
+ return (boost::format("%1%_%2%") % base % name).str();
}
}
@@ -504,9 +490,7 @@ Subscription::Subscription(const Address& address, const std::string& type)
queue(getSubscriptionName(name, (Opt(address)/LINK/NAME).str())),
reliable(AddressResolution::is_reliable(address)),
durable(Opt(address)/LINK/DURABLE),
- actualType(type.empty() ? (specifiedType.empty() ? TOPIC_EXCHANGE : specifiedType) : type),
- exclusiveQueue((Opt(address)/LINK/X_DECLARE/EXCLUSIVE).asBool(true)),
- exclusiveSubscription((Opt(address)/LINK/X_SUBSCRIBE/EXCLUSIVE).asBool(exclusiveQueue))
+ actualType(type.empty() ? (specifiedType.empty() ? TOPIC_EXCHANGE : specifiedType) : type)
{
(Opt(address)/LINK/X_DECLARE/ARGUMENTS).collect(queueOptions);
(Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(subscriptionOptions);
@@ -566,7 +550,7 @@ void Subscription::subscribe(qpid::client::AsyncSession& session, const std::str
checkAssert(session, FOR_RECEIVER);
//create subscription queue:
- session.queueDeclare(arg::queue=queue, arg::exclusive=exclusiveQueue,
+ session.queueDeclare(arg::queue=queue, arg::exclusive=true,
arg::autoDelete=!reliable, arg::durable=durable, arg::arguments=queueOptions);
//'default' binding:
bindings.bind(session);
@@ -575,15 +559,15 @@ void Subscription::subscribe(qpid::client::AsyncSession& session, const std::str
linkBindings.bind(session);
//subscribe to subscription queue:
AcceptMode accept = reliable ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE;
- session.messageSubscribe(arg::queue=queue, arg::destination=destination,
- arg::exclusive=exclusiveSubscription, arg::acceptMode=accept, arg::arguments=subscriptionOptions);
+ session.messageSubscribe(arg::queue=queue, arg::destination=destination,
+ arg::exclusive=true, arg::acceptMode=accept, arg::arguments=subscriptionOptions);
}
void Subscription::cancel(qpid::client::AsyncSession& session, const std::string& destination)
{
linkBindings.unbind(session);
session.messageCancel(destination);
- if (exclusiveQueue) session.queueDelete(arg::queue=queue, arg::ifUnused=true);
+ session.queueDelete(arg::queue=queue);
checkDelete(session, FOR_RECEIVER);
}
@@ -777,32 +761,18 @@ Exchange::Exchange(const Address& a) : Node(a),
linkBindings.setDefaultExchange(name);
}
-bool Exchange::isReservedName()
-{
- return name.find(PREFIX_AMQ) != std::string::npos || name.find(PREFIX_QPID) != std::string::npos;
-}
-
void Exchange::checkCreate(qpid::client::AsyncSession& session, CheckMode mode)
{
if (enabled(createPolicy, mode)) {
try {
- if (isReservedName()) {
- try {
- sync(session).exchangeDeclare(arg::exchange=name, arg::passive=true);
- } catch (const qpid::framing::NotFoundException& /*e*/) {
- throw ResolutionError((boost::format("Cannot create exchange %1%; names beginning with \"amq.\" or \"qpid.\" are reserved.") % name).str());
- }
-
- } else {
- std::string type = specifiedType;
- if (type.empty()) type = TOPIC_EXCHANGE;
- session.exchangeDeclare(arg::exchange=name,
- arg::type=type,
- arg::durable=durable,
- arg::autoDelete=autoDelete,
- arg::alternateExchange=alternateExchange,
- arg::arguments=arguments);
- }
+ std::string type = specifiedType;
+ if (type.empty()) type = TOPIC_EXCHANGE;
+ session.exchangeDeclare(arg::exchange=name,
+ arg::type=type,
+ arg::durable=durable,
+ arg::autoDelete=autoDelete,
+ arg::alternateExchange=alternateExchange,
+ arg::arguments=arguments);
nodeBindings.bind(session);
session.sync();
} catch (const qpid::framing::NotAllowedException& e) {
@@ -852,7 +822,7 @@ void Exchange::checkAssert(qpid::client::AsyncSession& session, CheckMode mode)
FieldTable::ValuePtr v = result.getArguments().get(i->first);
if (!v) {
throw AssertionFailed((boost::format("Option %1% not set for %2%") % i->first % name).str());
- } else if (*i->second != *v) {
+ } else if (i->second != v) {
throw AssertionFailed((boost::format("Option %1% does not match for %2%, expected %3%, got %4%")
% i->first % name % *(i->second) % *v).str());
}
diff --git a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
index cc6e9b9ab2..5a545c1f6a 100644
--- a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
+++ b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
@@ -20,6 +20,7 @@
*/
#include "ConnectionImpl.h"
#include "SessionImpl.h"
+#include "SimpleUrlParser.h"
#include "qpid/messaging/exceptions.h"
#include "qpid/messaging/Session.h"
#include "qpid/messaging/PrivateImplRef.h"
@@ -38,18 +39,26 @@ using qpid::types::Variant;
using qpid::types::VAR_LIST;
using qpid::framing::Uuid;
-namespace {
-void merge(const std::string& value, std::vector<std::string>& list) {
- if (std::find(list.begin(), list.end(), value) == list.end())
- list.push_back(value);
+void convert(const Variant::List& from, std::vector<std::string>& to)
+{
+ for (Variant::List::const_iterator i = from.begin(); i != from.end(); ++i) {
+ to.push_back(i->asString());
+ }
}
-void merge(const Variant::List& from, std::vector<std::string>& to)
+template <class T> bool setIfFound(const Variant::Map& map, const std::string& key, T& value)
{
- for (Variant::List::const_iterator i = from.begin(); i != from.end(); ++i)
- merge(i->asString(), to);
+ Variant::Map::const_iterator i = map.find(key);
+ if (i != map.end()) {
+ value = (T) i->second;
+ QPID_LOG(debug, "option " << key << " specified as " << i->second);
+ return true;
+ } else {
+ return false;
+ }
}
+namespace {
std::string asString(const std::vector<std::string>& v) {
std::stringstream os;
os << "[";
@@ -62,8 +71,49 @@ std::string asString(const std::vector<std::string>& v) {
}
}
+template <> bool setIfFound< std::vector<std::string> >(const Variant::Map& map,
+ const std::string& key,
+ std::vector<std::string>& value)
+{
+ Variant::Map::const_iterator i = map.find(key);
+ if (i != map.end()) {
+ value.clear();
+ if (i->second.getType() == VAR_LIST) {
+ convert(i->second.asList(), value);
+ } else {
+ value.push_back(i->second.asString());
+ }
+ QPID_LOG(debug, "option " << key << " specified as " << asString(value));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void convert(const Variant::Map& from, ConnectionSettings& to)
+{
+ setIfFound(from, "username", to.username);
+ setIfFound(from, "password", to.password);
+ setIfFound(from, "sasl-mechanism", to.mechanism);
+ setIfFound(from, "sasl-service", to.service);
+ setIfFound(from, "sasl-min-ssf", to.minSsf);
+ setIfFound(from, "sasl-max-ssf", to.maxSsf);
+
+ setIfFound(from, "heartbeat", to.heartbeat);
+ setIfFound(from, "tcp-nodelay", to.tcpNoDelay);
+
+ setIfFound(from, "locale", to.locale);
+ setIfFound(from, "max-channels", to.maxChannels);
+ setIfFound(from, "max-frame-size", to.maxFrameSize);
+ setIfFound(from, "bounds", to.bounds);
+
+ setIfFound(from, "transport", to.protocol);
+
+ setIfFound(from, "ssl-cert-name", to.sslCertName);
+}
+
ConnectionImpl::ConnectionImpl(const std::string& url, const Variant::Map& options) :
- replaceUrls(false), reconnect(false), timeout(-1), limit(-1),
+ reconnect(false), timeout(-1), limit(-1),
minReconnectInterval(3), maxReconnectInterval(60),
retries(0), reconnectOnLimitExceeded(true)
{
@@ -74,69 +124,27 @@ ConnectionImpl::ConnectionImpl(const std::string& url, const Variant::Map& optio
void ConnectionImpl::setOptions(const Variant::Map& options)
{
- for (Variant::Map::const_iterator i = options.begin(); i != options.end(); ++i) {
- setOption(i->first, i->second);
+ sys::Mutex::ScopedLock l(lock);
+ convert(options, settings);
+ setIfFound(options, "reconnect", reconnect);
+ setIfFound(options, "reconnect-timeout", timeout);
+ setIfFound(options, "reconnect-limit", limit);
+ int64_t reconnectInterval;
+ if (setIfFound(options, "reconnect-interval", reconnectInterval)) {
+ minReconnectInterval = maxReconnectInterval = reconnectInterval;
+ } else {
+ setIfFound(options, "reconnect-interval-min", minReconnectInterval);
+ setIfFound(options, "reconnect-interval-max", maxReconnectInterval);
}
+ setIfFound(options, "reconnect-urls", urls);
+ setIfFound(options, "x-reconnect-on-limit-exceeded", reconnectOnLimitExceeded);
}
void ConnectionImpl::setOption(const std::string& name, const Variant& value)
{
- sys::Mutex::ScopedLock l(lock);
- if (name == "reconnect") {
- reconnect = value;
- } else if (name == "reconnect-timeout" || name == "reconnect_timeout") {
- timeout = value;
- } else if (name == "reconnect-limit" || name == "reconnect_limit") {
- limit = value;
- } else if (name == "reconnect-interval" || name == "reconnect_interval") {
- maxReconnectInterval = minReconnectInterval = value;
- } else if (name == "reconnect-interval-min" || name == "reconnect_interval_min") {
- minReconnectInterval = value;
- } else if (name == "reconnect-interval-max" || name == "reconnect_interval_max") {
- maxReconnectInterval = value;
- } else if (name == "reconnect-urls-replace" || name == "reconnect_urls_replace") {
- replaceUrls = value.asBool();
- } else if (name == "reconnect-urls" || name == "reconnect_urls") {
- if (replaceUrls) urls.clear();
- if (value.getType() == VAR_LIST) {
- merge(value.asList(), urls);
- } else {
- merge(value.asString(), urls);
- }
- } else if (name == "username") {
- settings.username = value.asString();
- } else if (name == "password") {
- settings.password = value.asString();
- } else if (name == "sasl-mechanism" || name == "sasl_mechanism" ||
- name == "sasl-mechanisms" || name == "sasl_mechanisms") {
- settings.mechanism = value.asString();
- } else if (name == "sasl-service" || name == "sasl_service") {
- settings.service = value.asString();
- } else if (name == "sasl-min-ssf" || name == "sasl_min_ssf") {
- settings.minSsf = value;
- } else if (name == "sasl-max-ssf" || name == "sasl_max_ssf") {
- settings.maxSsf = value;
- } else if (name == "heartbeat") {
- settings.heartbeat = value;
- } else if (name == "tcp-nodelay" || name == "tcp_nodelay") {
- settings.tcpNoDelay = value;
- } else if (name == "locale") {
- settings.locale = value.asString();
- } else if (name == "max-channels" || name == "max_channels") {
- settings.maxChannels = value;
- } else if (name == "max-frame-size" || name == "max_frame_size") {
- settings.maxFrameSize = value;
- } else if (name == "bounds") {
- settings.bounds = value;
- } else if (name == "transport") {
- settings.protocol = value.asString();
- } else if (name == "ssl-cert-name" || name == "ssl_cert_name") {
- settings.sslCertName = value.asString();
- } else if (name == "x-reconnect-on-limit-exceeded" || name == "x_reconnect_on_limit_exceeded") {
- reconnectOnLimitExceeded = value;
- } else {
- throw qpid::messaging::MessagingException(QPID_MSG("Invalid option: " << name << " not recognised"));
- }
+ Variant::Map options;
+ options[name] = value;
+ setOptions(options);
}
@@ -206,7 +214,7 @@ qpid::messaging::Session ConnectionImpl::newSession(bool transactional, const st
sessions[name] = impl;
break;
} catch (const qpid::TransportFailure&) {
- reopen();
+ open();
} catch (const qpid::SessionException& e) {
throw qpid::messaging::SessionError(e.what());
} catch (const std::exception& e) {
@@ -227,15 +235,6 @@ void ConnectionImpl::open()
catch (const qpid::Exception& e) { throw messaging::ConnectionError(e.what()); }
}
-void ConnectionImpl::reopen()
-{
- if (!reconnect) {
- throw qpid::messaging::TransportFailure("Failed to connect (reconnect disabled)");
- }
- open();
-}
-
-
bool expired(const qpid::sys::AbsTime& start, int64_t timeout)
{
if (timeout == 0) return true;
@@ -263,9 +262,14 @@ void ConnectionImpl::connect(const qpid::sys::AbsTime& started)
}
void ConnectionImpl::mergeUrls(const std::vector<Url>& more, const sys::Mutex::ScopedLock&) {
- for (std::vector<Url>::const_iterator i = more.begin(); i != more.end(); ++i)
- merge(i->str(), urls);
- QPID_LOG(debug, "Added known-hosts, reconnect-urls=" << asString(urls));
+ if (more.size()) {
+ for (size_t i = 0; i < more.size(); ++i) {
+ if (std::find(urls.begin(), urls.end(), more[i].str()) == urls.end()) {
+ urls.push_back(more[i].str());
+ }
+ }
+ QPID_LOG(debug, "Added known-hosts, reconnect-urls=" << asString(urls));
+ }
}
bool ConnectionImpl::tryConnect()
@@ -274,14 +278,21 @@ bool ConnectionImpl::tryConnect()
for (std::vector<std::string>::const_iterator i = urls.begin(); i != urls.end(); ++i) {
try {
QPID_LOG(info, "Trying to connect to " << *i << "...");
- Url url(*i);
- if (url.getUser().size()) settings.username = url.getUser();
- if (url.getPass().size()) settings.password = url.getPass();
- connection.open(url, settings);
+ //TODO: when url support is more complete can avoid this test here
+ if (i->find("amqp:") == 0) {
+ Url url(*i);
+ connection.open(url, settings);
+ } else {
+ SimpleUrlParser::parse(*i, settings);
+ connection.open(settings);
+ }
QPID_LOG(info, "Connected to " << *i);
mergeUrls(connection.getInitialBrokers(), l);
return resetSessions(l);
- } catch (const qpid::TransportFailure& e) {
+ } catch (const qpid::ConnectionException& e) {
+ //TODO: need to fix timeout on
+ //qpid::client::Connection::open() so that it throws
+ //TransportFailure rather than a ConnectionException
QPID_LOG(info, "Failed to connect to " << *i << ": " << e.what());
}
}
diff --git a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
index 1b58cbbe3e..09f2038312 100644
--- a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
+++ b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
@@ -43,7 +43,6 @@ class ConnectionImpl : public qpid::messaging::ConnectionImpl
public:
ConnectionImpl(const std::string& url, const qpid::types::Variant::Map& options);
void open();
- void reopen();
bool isOpen() const;
void close();
qpid::messaging::Session newSession(bool transactional, const std::string& name);
@@ -60,7 +59,6 @@ class ConnectionImpl : public qpid::messaging::ConnectionImpl
qpid::sys::Semaphore semaphore;//used to coordinate reconnection
Sessions sessions;
qpid::client::Connection connection;
- bool replaceUrls; // Replace rather than merging with reconnect-urls
std::vector<std::string> urls;
qpid::client::ConnectionSettings settings;
bool reconnect;
diff --git a/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp b/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
index 3badaf40ba..71e89bdba1 100644
--- a/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
+++ b/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
@@ -144,10 +144,10 @@ void IncomingMessages::accept()
acceptTracker.accept(session);
}
-void IncomingMessages::accept(qpid::framing::SequenceNumber id, bool cumulative)
+void IncomingMessages::accept(qpid::framing::SequenceNumber id)
{
sys::Mutex::ScopedLock l(lock);
- acceptTracker.accept(id, session, cumulative);
+ acceptTracker.accept(id, session);
}
@@ -301,7 +301,6 @@ const std::string SUBJECT("qpid.subject");
const std::string X_APP_ID("x-amqp-0-10.app-id");
const std::string X_ROUTING_KEY("x-amqp-0-10.routing-key");
const std::string X_CONTENT_ENCODING("x-amqp-0-10.content-encoding");
-const std::string X_TIMESTAMP("x-amqp-0-10.timestamp");
}
void populateHeaders(qpid::messaging::Message& message,
@@ -335,13 +334,10 @@ void populateHeaders(qpid::messaging::Message& message,
if (messageProperties->hasContentEncoding()) {
message.getProperties()[X_CONTENT_ENCODING] = messageProperties->getContentEncoding();
}
- // routing-key, timestamp, others?
+ // routing-key, others?
if (deliveryProperties && deliveryProperties->hasRoutingKey()) {
message.getProperties()[X_ROUTING_KEY] = deliveryProperties->getRoutingKey();
}
- if (deliveryProperties && deliveryProperties->hasTimestamp()) {
- message.getProperties()[X_TIMESTAMP] = deliveryProperties->getTimestamp();
- }
}
}
diff --git a/cpp/src/qpid/client/amqp0_10/IncomingMessages.h b/cpp/src/qpid/client/amqp0_10/IncomingMessages.h
index 9053b70312..f6a291bc68 100644
--- a/cpp/src/qpid/client/amqp0_10/IncomingMessages.h
+++ b/cpp/src/qpid/client/amqp0_10/IncomingMessages.h
@@ -72,7 +72,7 @@ class IncomingMessages
bool get(Handler& handler, qpid::sys::Duration timeout);
bool getNextDestination(std::string& destination, qpid::sys::Duration timeout);
void accept();
- void accept(qpid::framing::SequenceNumber id, bool cumulative);
+ void accept(qpid::framing::SequenceNumber id);
void releaseAll();
void releasePending(const std::string& destination);
diff --git a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
index d93416da75..82358961c8 100644
--- a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
+++ b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
@@ -59,9 +59,7 @@ void OutgoingMessage::convert(const qpid::messaging::Message& from)
message.getMessageProperties().setReplyTo(AddressResolution::convert(address));
}
translate(from.getProperties(), message.getMessageProperties().getApplicationHeaders());
- if (from.getTtl().getMilliseconds()) {
- message.getDeliveryProperties().setTtl(from.getTtl().getMilliseconds());
- }
+ message.getDeliveryProperties().setTtl(from.getTtl().getMilliseconds());
if (from.getDurable()) {
message.getDeliveryProperties().setDeliveryMode(DELIVERY_MODE_PERSISTENT);
}
diff --git a/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp b/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp
index f2f0f1a9e5..e1b75ec0cf 100644
--- a/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp
+++ b/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp
@@ -135,7 +135,6 @@ void SenderImpl::sendUnreliable(const qpid::messaging::Message& m)
void SenderImpl::replay(const sys::Mutex::ScopedLock&)
{
for (OutgoingMessages::iterator i = outgoing.begin(); i != outgoing.end(); ++i) {
- i->message.setRedelivered(true);
sink->send(session, name, *i);
}
}
@@ -148,7 +147,7 @@ uint32_t SenderImpl::checkPendingSends(bool flush) {
uint32_t SenderImpl::checkPendingSends(bool flush, const sys::Mutex::ScopedLock&)
{
if (flush) {
- session.flush();
+ session.flush();
flushed = true;
} else {
flushed = false;
diff --git a/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp b/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp
index be5eab1f2b..75a71997fd 100644
--- a/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp
+++ b/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp
@@ -60,14 +60,12 @@ SessionImpl::SessionImpl(ConnectionImpl& c, bool t) : connection(&c), transactio
void SessionImpl::checkError()
{
- ScopedLock l(lock);
qpid::client::SessionBase_0_10Access s(session);
s.get()->assertOpen();
}
bool SessionImpl::hasError()
{
- ScopedLock l(lock);
qpid::client::SessionBase_0_10Access s(session);
return s.get()->hasError();
}
@@ -114,14 +112,13 @@ void SessionImpl::release(qpid::messaging::Message& m)
execute1<Release>(m);
}
-void SessionImpl::acknowledge(qpid::messaging::Message& m, bool cumulative)
+void SessionImpl::acknowledge(qpid::messaging::Message& m)
{
//Should probably throw an exception on failure here, or indicate
//it through a return type at least. Failure means that the
//message may be redelivered; i.e. the application cannot delete
//any state necessary for preventing reprocessing of the message
- Acknowledge2 ack(*this, m, cumulative);
- execute(ack);
+ execute1<Acknowledge1>(m);
}
void SessionImpl::close()
@@ -131,29 +128,27 @@ void SessionImpl::close()
senders.clear();
receivers.clear();
} else {
- Senders sCopy;
- Receivers rCopy;
- {
- ScopedLock l(lock);
- senders.swap(sCopy);
- receivers.swap(rCopy);
- }
- for (Senders::iterator i = sCopy.begin(); i != sCopy.end(); ++i)
- {
- // outside the lock, will call senderCancelled
- i->second.close();
+ while (true) {
+ Sender s;
+ {
+ ScopedLock l(lock);
+ if (senders.empty()) break;
+ s = senders.begin()->second;
+ }
+ s.close(); // outside the lock, will call senderCancelled
}
- for (Receivers::iterator i = rCopy.begin(); i != rCopy.end(); ++i)
- {
- // outside the lock, will call receiverCancelled
- i->second.close();
+ while (true) {
+ Receiver r;
+ {
+ ScopedLock l(lock);
+ if (receivers.empty()) break;
+ r = receivers.begin()->second;
+ }
+ r.close(); // outside the lock, will call receiverCancelled
}
}
connection->closed(*this);
- if (!hasError()) {
- ScopedLock l(lock);
- session.close();
- }
+ if (!hasError()) session.close();
}
template <class T, class S> boost::intrusive_ptr<S> getImplPtr(T& t)
@@ -436,11 +431,8 @@ uint32_t SessionImpl::getUnsettledAcksImpl(const std::string* destination)
void SessionImpl::syncImpl(bool block)
{
- {
- ScopedLock l(lock);
- if (block) session.sync();
- else session.flush();
- }
+ if (block) session.sync();
+ else session.flush();
//cleanup unconfirmed accept records:
incoming.pendingAccept();
}
@@ -475,10 +467,10 @@ void SessionImpl::acknowledgeImpl()
if (!transactional) incoming.accept();
}
-void SessionImpl::acknowledgeImpl(qpid::messaging::Message& m, bool cumulative)
+void SessionImpl::acknowledgeImpl(qpid::messaging::Message& m)
{
ScopedLock l(lock);
- if (!transactional) incoming.accept(MessageImplAccess::get(m).getInternalId(), cumulative);
+ if (!transactional) incoming.accept(MessageImplAccess::get(m).getInternalId());
}
void SessionImpl::rejectImpl(qpid::messaging::Message& m)
@@ -517,7 +509,7 @@ void SessionImpl::senderCancelled(const std::string& name)
void SessionImpl::reconnect()
{
- connection->reopen();
+ connection->open();
}
bool SessionImpl::backoff()
diff --git a/cpp/src/qpid/client/amqp0_10/SessionImpl.h b/cpp/src/qpid/client/amqp0_10/SessionImpl.h
index c7dea77d18..2a2aa47df6 100644
--- a/cpp/src/qpid/client/amqp0_10/SessionImpl.h
+++ b/cpp/src/qpid/client/amqp0_10/SessionImpl.h
@@ -63,7 +63,7 @@ class SessionImpl : public qpid::messaging::SessionImpl
void acknowledge(bool sync);
void reject(qpid::messaging::Message&);
void release(qpid::messaging::Message&);
- void acknowledge(qpid::messaging::Message& msg, bool cumulative);
+ void acknowledge(qpid::messaging::Message& msg);
void close();
void sync(bool block);
qpid::messaging::Sender createSender(const qpid::messaging::Address& address);
@@ -139,7 +139,7 @@ class SessionImpl : public qpid::messaging::SessionImpl
void commitImpl();
void rollbackImpl();
void acknowledgeImpl();
- void acknowledgeImpl(qpid::messaging::Message&, bool cumulative);
+ void acknowledgeImpl(qpid::messaging::Message&);
void rejectImpl(qpid::messaging::Message&);
void releaseImpl(qpid::messaging::Message&);
void closeImpl();
@@ -204,13 +204,12 @@ class SessionImpl : public qpid::messaging::SessionImpl
void operator()() { impl.releaseImpl(message); }
};
- struct Acknowledge2 : Command
+ struct Acknowledge1 : Command
{
qpid::messaging::Message& message;
- bool cumulative;
- Acknowledge2(SessionImpl& i, qpid::messaging::Message& m, bool c) : Command(i), message(m), cumulative(c) {}
- void operator()() { impl.acknowledgeImpl(message, cumulative); }
+ Acknowledge1(SessionImpl& i, qpid::messaging::Message& m) : Command(i), message(m) {}
+ void operator()() { impl.acknowledgeImpl(message); }
};
struct CreateSender;
diff --git a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp
new file mode 100644
index 0000000000..327c2274a6
--- /dev/null
+++ b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "SimpleUrlParser.h"
+#include "qpid/client/ConnectionSettings.h"
+#include "qpid/Exception.h"
+#include <boost/lexical_cast.hpp>
+
+namespace qpid {
+namespace client {
+namespace amqp0_10 {
+
+bool split(const std::string& in, char delim, std::pair<std::string, std::string>& result)
+{
+ std::string::size_type i = in.find(delim);
+ if (i != std::string::npos) {
+ result.first = in.substr(0, i);
+ if (i+1 < in.size()) {
+ result.second = in.substr(i+1);
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void parseUsernameAndPassword(const std::string& in, qpid::client::ConnectionSettings& result)
+{
+ std::pair<std::string, std::string> parts;
+ if (!split(in, '/', parts)) {
+ result.username = in;
+ } else {
+ result.username = parts.first;
+ result.password = parts.second;
+ }
+}
+
+void parseHostAndPort(const std::string& in, qpid::client::ConnectionSettings& result)
+{
+ std::pair<std::string, std::string> parts;
+ if (!split(in, ':', parts)) {
+ result.host = in;
+ } else {
+ result.host = parts.first;
+ if (parts.second.size()) {
+ result.port = boost::lexical_cast<uint16_t>(parts.second);
+ }
+ }
+}
+
+void SimpleUrlParser::parse(const std::string& url, qpid::client::ConnectionSettings& result)
+{
+ std::pair<std::string, std::string> parts;
+ if (!split(url, '@', parts)) {
+ parseHostAndPort(url, result);
+ } else {
+ parseUsernameAndPassword(parts.first, result);
+ parseHostAndPort(parts.second, result);
+ }
+}
+
+}}} // namespace qpid::client::amqp0_10
diff --git a/cpp/src/qpid/DisableExceptionLogging.h b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h
index 04a9240513..24f90ca9d6 100644
--- a/cpp/src/qpid/DisableExceptionLogging.h
+++ b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h
@@ -1,5 +1,5 @@
-#ifndef QPID_DISABLEEXCEPTIONLOGGING_H
-#define QPID_DISABLEEXCEPTIONLOGGING_H
+#ifndef QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H
+#define QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H
/*
*
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,19 +21,22 @@
* under the License.
*
*/
-#include "qpid/CommonImportExport.h"
+#include <string>
namespace qpid {
+namespace client {
+
+struct ConnectionSettings;
+
+namespace amqp0_10 {
/**
- * Temporarily disable logging in qpid::Exception constructor.
- * Used by log::Logger to avoid logging exceptions during Logger construction.
+ * Parses a simple url of the form user/password@hostname:port
*/
-struct DisableExceptionLogging
+struct SimpleUrlParser
{
- QPID_COMMON_EXTERN DisableExceptionLogging();
- QPID_COMMON_EXTERN ~DisableExceptionLogging();
+ static void parse(const std::string& url, qpid::client::ConnectionSettings& result);
};
-} // namespace qpid
+}}} // namespace qpid::client::amqp0_10
-#endif /*!QPID_DISABLEEXCEPTIONLOGGING_H*/
+#endif /*!QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H*/
diff --git a/cpp/src/qpid/client/windows/SaslFactory.cpp b/cpp/src/qpid/client/windows/SaslFactory.cpp
index 53d825771b..63c7fa3d1f 100644
--- a/cpp/src/qpid/client/windows/SaslFactory.cpp
+++ b/cpp/src/qpid/client/windows/SaslFactory.cpp
@@ -71,7 +71,7 @@ class WindowsSasl : public Sasl
public:
WindowsSasl( const std::string &, const std::string &, const std::string &, const std::string &, int, int );
~WindowsSasl();
- bool start(const std::string& mechanisms, std::string& response, const SecuritySettings* externalSettings);
+ std::string start(const std::string& mechanisms, const SecuritySettings* externalSettings);
std::string step(const std::string& challenge);
std::string getMechanism();
std::string getUserId();
@@ -121,8 +121,8 @@ WindowsSasl::~WindowsSasl()
{
}
-bool WindowsSasl::start(const std::string& mechanisms, std::string& response,
- const SecuritySettings* /*externalSettings*/)
+std::string WindowsSasl::start(const std::string& mechanisms,
+ const SecuritySettings* /*externalSettings*/)
{
QPID_LOG(debug, "WindowsSasl::start(" << mechanisms << ")");
@@ -142,18 +142,18 @@ bool WindowsSasl::start(const std::string& mechanisms, std::string& response,
if (!haveAnon && !havePlain)
throw InternalErrorException(QPID_MSG("Sasl error: no common mechanism"));
+ std::string resp = "";
if (havePlain) {
mechanism = PLAIN;
- response = ((char)0) + settings.username + ((char)0) + settings.password;
+ resp = ((char)0) + settings.username + ((char)0) + settings.password;
}
else {
mechanism = ANONYMOUS;
- response = "";
}
- return true;
+ return resp;
}
-std::string WindowsSasl::step(const std::string& /*challenge*/)
+std::string WindowsSasl::step(const std::string& challenge)
{
// Shouldn't get this for PLAIN...
throw InternalErrorException(QPID_MSG("Sasl step error"));
@@ -169,7 +169,7 @@ 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*/)
+std::auto_ptr<SecurityLayer> WindowsSasl::getSecurityLayer(uint16_t maxFrameSize)
{
return std::auto_ptr<SecurityLayer>(0);
}
diff --git a/cpp/src/qpid/client/windows/SslConnector.cpp b/cpp/src/qpid/client/windows/SslConnector.cpp
index 785c817928..a33713e1a8 100644
--- a/cpp/src/qpid/client/windows/SslConnector.cpp
+++ b/cpp/src/qpid/client/windows/SslConnector.cpp
@@ -77,7 +77,7 @@ public:
framing::ProtocolVersion pVersion,
const ConnectionSettings&,
ConnectionImpl*);
- virtual void connect(const std::string& host, const std::string& port);
+ virtual void connect(const std::string& host, int port);
virtual void connected(const Socket&);
unsigned int getSSF();
};
@@ -153,7 +153,7 @@ SslConnector::~SslConnector()
// Will this get reach via virtual method via boost::bind????
-void SslConnector::connect(const std::string& host, const std::string& port) {
+void SslConnector::connect(const std::string& host, int port) {
brokerHost = host;
TCPConnector::connect(host, port);
}
diff --git a/cpp/src/qpid/cluster/Cluster.cpp b/cpp/src/qpid/cluster/Cluster.cpp
index e6e3de64f2..dd4882774b 100644
--- a/cpp/src/qpid/cluster/Cluster.cpp
+++ b/cpp/src/qpid/cluster/Cluster.cpp
@@ -36,45 +36,45 @@
*
* IMPORTANT NOTE: any time code is added to the broker that uses timers,
* the cluster may need to be updated to take account of this.
- *
+ *
*
* USE OF TIMESTAMPS IN THE BROKER
- *
+ *
* The following are the current areas where broker uses timers or timestamps:
- *
+ *
* - Producer flow control: broker::SemanticState uses
* connection::getClusterOrderOutput. a FrameHandler that sends
* frames to the client via the cluster. Used by broker::SessionState
- *
+ *
* - QueueCleaner, Message TTL: uses ExpiryPolicy, which is
* implemented by cluster::ExpiryPolicy.
- *
+ *
* - Connection heartbeat: sends connection controls, not part of
* session command counting so OK to ignore.
- *
+ *
* - LinkRegistry: only cluster elder is ever active for links.
- *
+ *
* - management::ManagementBroker: uses MessageHandler supplied by cluster
* to send messages to the broker via the cluster.
+ *
+ * - Dtx: not yet supported with cluster.
*
- * cluster::ExpiryPolicy uses cluster time.
+ * cluster::ExpiryPolicy implements the strategy for message expiry.
*
* ClusterTimer implements periodic timed events in the cluster context.
- * Used for:
- * - periodic management events.
- * - DTX transaction timeouts.
+ * Used for periodic management events.
*
* <h1>CLUSTER PROTOCOL OVERVIEW</h1>
- *
+ *
* Messages sent to/from CPG are called Events.
*
* An Event carries a ConnectionId, which includes a MemberId and a
* connection number.
- *
+ *
* Events are either
* - Connection events: non-0 connection number and are associated with a connection.
* - Cluster Events: 0 connection number, are not associated with a connection.
- *
+ *
* Events are further categorized as:
* - Control: carries method frame(s) that affect cluster behavior.
* - Data: carries raw data received from a client connection.
@@ -146,7 +146,6 @@
#include "qpid/framing/AMQP_AllOperations.h"
#include "qpid/framing/AllInvoker.h"
#include "qpid/framing/ClusterConfigChangeBody.h"
-#include "qpid/framing/ClusterClockBody.h"
#include "qpid/framing/ClusterConnectionDeliverCloseBody.h"
#include "qpid/framing/ClusterConnectionAbortBody.h"
#include "qpid/framing/ClusterRetractOfferBody.h"
@@ -199,7 +198,7 @@ namespace _qmf = ::qmf::org::apache::qpid::cluster;
* Currently use SVN revision to avoid clashes with versions from
* different branches.
*/
-const uint32_t Cluster::CLUSTER_VERSION = 1159329;
+const uint32_t Cluster::CLUSTER_VERSION = 1058747;
struct ClusterDispatcher : public framing::AMQP_AllOperations::ClusterHandler {
qpid::cluster::Cluster& cluster;
@@ -215,7 +214,7 @@ struct ClusterDispatcher : public framing::AMQP_AllOperations::ClusterHandler {
{
cluster.initialStatus(
member, version, active, clusterId,
- framing::cluster::StoreState(storeState), shutdownId,
+ framing::cluster::StoreState(storeState), shutdownId,
firstConfig, l);
}
void ready(const std::string& url) {
@@ -231,21 +230,21 @@ struct ClusterDispatcher : public framing::AMQP_AllOperations::ClusterHandler {
cluster.updateOffer(member, updatee, l);
}
void retractOffer(uint64_t updatee) { cluster.retractOffer(member, updatee, l); }
+ void messageExpired(uint64_t id) { cluster.messageExpired(member, id, l); }
void errorCheck(uint8_t type, const framing::SequenceNumber& frameSeq) {
cluster.errorCheck(member, type, frameSeq, l);
}
void timerWakeup(const std::string& name) { cluster.timerWakeup(member, name, l); }
- void timerDrop(const std::string& name) { cluster.timerDrop(member, name, l); }
+ void timerDrop(const std::string& name) { cluster.timerWakeup(member, name, l); }
void shutdown(const Uuid& id) { cluster.shutdown(member, id, l); }
void deliverToQueue(const std::string& queue, const std::string& message) {
cluster.deliverToQueue(queue, message, l);
}
- void clock(uint64_t time) { cluster.clock(time, l); }
bool invoke(AMQBody& body) { return framing::invoke(*this, body).wasHandled(); }
};
Cluster::Cluster(const ClusterSettings& set, broker::Broker& b) :
- settings(set),
+ settings(set),
broker(b),
mgmtObject(0),
poller(b.getPoller()),
@@ -254,7 +253,7 @@ Cluster::Cluster(const ClusterSettings& set, broker::Broker& b) :
self(cpg.self()),
clusterId(true),
mAgent(0),
- expiryPolicy(new ExpiryPolicy(*this)),
+ expiryPolicy(new ExpiryPolicy(mcast, self, broker.getTimer())),
mcast(cpg, poller, boost::bind(&Cluster::leave, this)),
dispatcher(cpg, poller, boost::bind(&Cluster::leave, this)),
deliverEventQueue(boost::bind(&Cluster::deliveredEvent, this, _1),
@@ -278,11 +277,8 @@ Cluster::Cluster(const ClusterSettings& set, broker::Broker& b) :
lastBroker(false),
updateRetracted(false),
updateClosed(false),
- error(*this),
- acl(0)
+ error(*this)
{
- broker.setInCluster(true);
-
// We give ownership of the timer to the broker and keep a plain pointer.
// This is OK as it means the timer has the same lifetime as the broker.
timer = new ClusterTimer(*this);
@@ -303,7 +299,7 @@ Cluster::Cluster(const ClusterSettings& set, broker::Broker& b) :
// Load my store status before we go into initialization
if (! broker::NullMessageStore::isNullStore(&broker.getStore())) {
store.load();
- clusterId = store.getClusterId();
+ clusterId = store.getClusterId();
QPID_LOG(notice, "Cluster store state: " << store)
}
cpg.join(name);
@@ -364,15 +360,14 @@ void Cluster::addShadowConnection(const boost::intrusive_ptr<Connection>& c) {
// Safe to use connections here because we're pre-catchup, stalled
// and discarding, so deliveredFrame is not processing any
// connection events.
- assert(discarding);
+ assert(discarding);
pair<ConnectionMap::iterator, bool> ib
= connections.insert(ConnectionMap::value_type(c->getId(), c));
- // Like this to avoid tripping up unused variable warning when NDEBUG set
- if (!ib.second) assert(ib.second);
+ assert(ib.second);
}
void Cluster::erase(const ConnectionId& id) {
- Lock l(lock);
+ Lock l(lock);
erase(id,l);
}
@@ -398,9 +393,9 @@ std::vector<Url> Cluster::getUrls() const {
std::vector<Url> Cluster::getUrls(Lock&) const {
return map.memberUrls();
-}
+}
-void Cluster::leave() {
+void Cluster::leave() {
Lock l(lock);
leave(l);
}
@@ -410,7 +405,7 @@ void Cluster::leave() {
QPID_LOG(warning, *this << " error leaving cluster: " << e.what()); \
} do {} while(0)
-void Cluster::leave(Lock&) {
+void Cluster::leave(Lock&) {
if (state != LEFT) {
state = LEFT;
QPID_LOG(notice, *this << " leaving cluster " << name);
@@ -429,7 +424,7 @@ void Cluster::deliver(
uint32_t nodeid,
uint32_t pid,
void* msg,
- int msg_len)
+ int msg_len)
{
MemberId from(nodeid, pid);
framing::Buffer buf(static_cast<char*>(msg), msg_len);
@@ -460,7 +455,7 @@ void Cluster::deliveredEvent(const Event& e) {
EventFrame ef(e, e.getFrame());
// Stop the deliverEventQueue on update offers.
// This preserves the connection decoder fragments for an update.
- // Only do this for the two brokers that are directly involved in this
+ // Only do this for the two brokers that are directly involved in this
// offer: the one making the offer, or the one receiving it.
const ClusterUpdateOfferBody* offer = castUpdateOffer(ef.frame.getBody());
if (offer && ( e.getMemberId() == self || MemberId(offer->getUpdatee()) == self) ) {
@@ -470,7 +465,7 @@ void Cluster::deliveredEvent(const Event& e) {
}
deliverFrame(ef);
}
- else if(!discarding) {
+ else if(!discarding) {
if (e.isControl())
deliverFrame(EventFrame(e, e.getFrame()));
else {
@@ -512,7 +507,7 @@ void Cluster::deliveredFrame(const EventFrame& efConst) {
// the event queue.
e.frame = AMQFrame(
ClusterRetractOfferBody(ProtocolVersion(), offer->getUpdatee()));
- deliverEventQueue.start();
+ deliverEventQueue.start();
}
// Process each frame through the error checker.
if (error.isUnresolved()) {
@@ -520,14 +515,14 @@ void Cluster::deliveredFrame(const EventFrame& efConst) {
while (error.canProcess()) // There is a frame ready to process.
processFrame(error.getNext(), l);
}
- else
+ else
processFrame(e, l);
}
void Cluster::processFrame(const EventFrame& e, Lock& l) {
if (e.isCluster()) {
- QPID_LOG_IF(trace, loggable(e.frame), *this << " DLVR: " << e);
+ QPID_LOG(trace, *this << " DLVR: " << e);
ClusterDispatcher dispatch(*this, e.connectionId.getMember(), l);
if (!framing::invoke(dispatch, *e.frame.getBody()).wasHandled())
throw Exception(QPID_MSG("Invalid cluster control"));
@@ -536,15 +531,14 @@ void Cluster::processFrame(const EventFrame& e, Lock& l) {
map.incrementFrameSeq();
ConnectionPtr connection = getConnection(e, l);
if (connection) {
- QPID_LOG_IF(trace, loggable(e.frame),
- *this << " DLVR " << map.getFrameSeq() << ": " << e);
+ QPID_LOG(trace, *this << " DLVR " << map.getFrameSeq() << ": " << e);
connection->deliveredFrame(e);
}
else
- throw Exception(QPID_MSG("Unknown connection: " << e));
+ QPID_LOG(trace, *this << " DROP (no connection): " << e);
}
else // Drop connection frames while state < CATCHUP
- QPID_LOG_IF(trace, loggable(e.frame), *this << " DROP (joining): " << e);
+ QPID_LOG(trace, *this << " DROP (joining): " << e);
}
// Called in deliverFrameQueue thread
@@ -583,7 +577,7 @@ Cluster::ConnectionVector Cluster::getConnections(Lock&) {
}
// CPG config-change callback.
-void Cluster::configChange (
+void Cluster::configChange (
cpg_handle_t /*handle*/,
const cpg_name */*group*/,
const cpg_address *members, int nMembers,
@@ -613,7 +607,7 @@ void Cluster::setReady(Lock&) {
}
// Set the management status from the Cluster::state.
-//
+//
// NOTE: Management updates are sent based on property changes. In
// order to keep consistency across the cluster, we touch the local
// management status property even if it is locally unchanged for any
@@ -624,7 +618,7 @@ void Cluster::setMgmtStatus(Lock&) {
}
void Cluster::initMapCompleted(Lock& l) {
- // Called on completion of the initial status map.
+ // Called on completion of the initial status map.
QPID_LOG(debug, *this << " initial status map complete. ");
setMgmtStatus(l);
if (state == PRE_INIT) {
@@ -671,8 +665,6 @@ void Cluster::initMapCompleted(Lock& l) {
else { // I can go ready.
discarding = false;
setReady(l);
- // Must be called *before* memberUpdate so first update will be generated.
- failoverExchange->setReady();
memberUpdate(l);
updateMgmtMembership(l);
mcast.mcastControl(ClusterReadyBody(ProtocolVersion(), myUrl.str()), self);
@@ -709,8 +701,8 @@ void Cluster::configChange(const MemberId&,
if (initMap.isResendNeeded()) {
mcast.mcastControl(
ClusterInitialStatusBody(
- ProtocolVersion(), CLUSTER_VERSION, state > INIT, clusterId,
- store.getState(), store.getShutdownId(),
+ ProtocolVersion(), CLUSTER_VERSION, state > INIT, clusterId,
+ store.getState(), store.getShutdownId(),
initMap.getFirstConfigStr()
),
self);
@@ -725,20 +717,6 @@ void Cluster::configChange(const MemberId&,
updateMgmtMembership(l); // Update on every config change for consistency
}
-struct ClusterClockTask : public sys::TimerTask {
- Cluster& cluster;
- sys::Timer& timer;
-
- ClusterClockTask(Cluster& cluster, sys::Timer& timer, uint16_t clockInterval)
- : TimerTask(Duration(clockInterval * TIME_MSEC),"ClusterClock"), cluster(cluster), timer(timer) {}
-
- void fire() {
- cluster.sendClockUpdate();
- setupNextFire();
- timer.add(this);
- }
-};
-
void Cluster::becomeElder(Lock&) {
if (elder) return; // We were already the elder.
// We are the oldest, reactive links if necessary
@@ -746,8 +724,6 @@ void Cluster::becomeElder(Lock&) {
elder = true;
broker.getLinks().setPassive(false);
timer->becomeElder();
-
- clockTimer.add(new ClusterClockTask(*this, clockTimer, settings.clockInterval));
}
void Cluster::makeOffer(const MemberId& id, Lock& ) {
@@ -783,7 +759,7 @@ std::string Cluster::debugSnapshot() {
// point we know the poller has stopped so no poller callbacks will be
// invoked. We must ensure that CPG has also shut down so no CPG
// callbacks will be invoked.
-//
+//
void Cluster::brokerShutdown() {
sys::ClusterSafeScope css; // Don't trigger cluster-safe asserts.
try { cpg.shutdown(); }
@@ -799,7 +775,7 @@ void Cluster::updateRequest(const MemberId& id, const std::string& url, Lock& l)
}
void Cluster::initialStatus(const MemberId& member, uint32_t version, bool active,
- const framing::Uuid& id,
+ const framing::Uuid& id,
framing::cluster::StoreState store,
const framing::Uuid& shutdownId,
const std::string& firstConfig,
@@ -857,8 +833,6 @@ void Cluster::updateOffer(const MemberId& updater, uint64_t updateeInt, Lock& l)
else if (updatee == self && url) {
assert(state == JOINER);
state = UPDATEE;
- acl = broker.getAcl();
- broker.setAcl(0); // Disable ACL during update
QPID_LOG(notice, *this << " receiving update from " << updater);
checkUpdateIn(l);
}
@@ -870,7 +844,7 @@ void Cluster::updateOffer(const MemberId& updater, uint64_t updateeInt, Lock& l)
if (updatee != self && url) {
QPID_LOG(debug, debugSnapshot());
if (mAgent) mAgent->clusterUpdate();
- // Updatee will call clusterUpdate() via checkUpdateIn() when update completes
+ // Updatee will call clusterUpdate when update completes
}
}
@@ -951,15 +925,13 @@ void Cluster::checkUpdateIn(Lock& l) {
if (!updateClosed) return; // Wait till update connection closes.
if (updatedMap) { // We're up to date
map = *updatedMap;
+ failoverExchange->setUrls(getUrls(l));
mcast.mcastControl(ClusterReadyBody(ProtocolVersion(), myUrl.str()), self);
state = CATCHUP;
memberUpdate(l);
- // Must be called *after* memberUpdate() to avoid sending an extra update.
- failoverExchange->setReady();
// NB: don't updateMgmtMembership() here as we are not in the deliver
// thread. It will be updated on delivery of the "ready" we just mcast.
broker.setClusterUpdatee(false);
- broker.setAcl(acl); // Restore ACL
discarding = false; // OK to set, we're stalled for update.
QPID_LOG(notice, *this << " update complete, starting catch-up.");
QPID_LOG(debug, debugSnapshot()); // OK to call because we're stalled.
@@ -969,10 +941,6 @@ void Cluster::checkUpdateIn(Lock& l) {
mAgent->suppress(false); // Enable management output.
mAgent->clusterUpdate();
}
- // Restore alternate exchange settings on exchanges.
- broker.getExchanges().eachExchange(
- boost::bind(&broker::Exchange::recoveryComplete, _1,
- boost::ref(broker.getExchanges())));
enableClusterSafe(); // Enable cluster-safe assertions
deliverEventQueue.start();
}
@@ -1001,7 +969,7 @@ void Cluster::updateOutDone(Lock& l) {
void Cluster::updateOutError(const std::exception& e) {
Monitor::ScopedLock l(lock);
- QPID_LOG(error, *this << " error sending update: " << e.what());
+ QPID_LOG(error, *this << " error sending update: " << e.what());
updateOutDone(l);
}
@@ -1099,7 +1067,7 @@ void Cluster::memberUpdate(Lock& l) {
void Cluster::updateMgmtMembership(Lock& l) {
if (!mgmtObject) return;
std::vector<Url> urls = getUrls(l);
- mgmtObject->set_clusterSize(urls.size());
+ mgmtObject->set_clusterSize(urls.size());
string urlstr;
for(std::vector<Url>::iterator i = urls.begin(); i != urls.end(); i++ ) {
if (i != urls.begin()) urlstr += ";";
@@ -1146,6 +1114,10 @@ void Cluster::setClusterId(const Uuid& uuid, Lock&) {
QPID_LOG(notice, *this << " cluster-uuid = " << clusterId);
}
+void Cluster::messageExpired(const MemberId&, uint64_t id, Lock&) {
+ expiryPolicy->deliverExpire(id);
+}
+
void Cluster::errorCheck(const MemberId& from, uint8_t type, framing::SequenceNumber frameSeq, Lock&) {
// If we see an errorCheck here (rather than in the ErrorCheck
// class) then we have processed succesfully past the point of the
@@ -1183,35 +1155,6 @@ void Cluster::deliverToQueue(const std::string& queue, const std::string& messag
q->deliver(msg);
}
-sys::AbsTime Cluster::getClusterTime() {
- Mutex::ScopedLock l(lock);
- return clusterTime;
-}
-
-// This method is called during update on the updatee to set the initial cluster time.
-void Cluster::clock(const uint64_t time) {
- Mutex::ScopedLock l(lock);
- clock(time, l);
-}
-
-// called when broadcast message received
-void Cluster::clock(const uint64_t time, Lock&) {
- clusterTime = AbsTime(EPOCH, time);
- AbsTime now = AbsTime::now();
-
- if (!elder) {
- clusterTimeOffset = Duration(now, clusterTime);
- }
-}
-
-// called by elder timer to send clock broadcast
-void Cluster::sendClockUpdate() {
- Mutex::ScopedLock l(lock);
- int64_t nanosecondsSinceEpoch = Duration(EPOCH, now());
- nanosecondsSinceEpoch += clusterTimeOffset;
- mcast.mcastControl(ClusterClockBody(ProtocolVersion(), nanosecondsSinceEpoch), self);
-}
-
bool Cluster::deferDeliveryImpl(const std::string& queue,
const boost::intrusive_ptr<broker::Message>& msg)
{
@@ -1224,12 +1167,4 @@ bool Cluster::deferDeliveryImpl(const std::string& queue,
return true;
}
-bool Cluster::loggable(const AMQFrame& f) {
- const AMQMethodBody* method = (f.getMethod());
- if (!method) return true; // Not a method
- bool isClock = method->amqpClassId() == ClusterClockBody::CLASS_ID
- && method->amqpMethodId() == ClusterClockBody::METHOD_ID;
- return !isClock;
-}
-
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/Cluster.h b/cpp/src/qpid/cluster/Cluster.h
index ccec4948e6..8f73c6acca 100644
--- a/cpp/src/qpid/cluster/Cluster.h
+++ b/cpp/src/qpid/cluster/Cluster.h
@@ -56,25 +56,17 @@ namespace qpid {
namespace broker {
class Message;
-class AclModule;
}
namespace framing {
-class AMQFrame;
class AMQBody;
-struct Uuid;
-}
-
-namespace sys {
-class Timer;
-class AbsTime;
-class Duration;
+class Uuid;
}
namespace cluster {
class Connection;
-struct EventFrame;
+class EventFrame;
class ClusterTimer;
class UpdateDataExchange;
@@ -97,10 +89,10 @@ class Cluster : private Cpg::Handler, public management::Manageable {
void initialize();
// Connection map.
- void addLocalConnection(const ConnectionPtr&);
- void addShadowConnection(const ConnectionPtr&);
- void erase(const ConnectionId&);
-
+ void addLocalConnection(const ConnectionPtr&);
+ void addShadowConnection(const ConnectionPtr&);
+ void erase(const ConnectionId&);
+
// URLs of current cluster members.
std::vector<std::string> getIds() const;
std::vector<Url> getUrls() const;
@@ -115,7 +107,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
void updateInRetracted();
// True if we are expecting to receive catch-up connections.
bool isExpectingUpdate();
-
+
MemberId getId() const;
broker::Broker& getBroker() const;
Multicaster& getMulticast() { return mcast; }
@@ -143,12 +135,6 @@ class Cluster : private Cpg::Handler, public management::Manageable {
bool deferDeliveryImpl(const std::string& queue,
const boost::intrusive_ptr<broker::Message>& msg);
- sys::AbsTime getClusterTime();
- void sendClockUpdate();
- void clock(const uint64_t time);
-
- static bool loggable(const framing::AMQFrame&); // True if the frame should be logged.
-
private:
typedef sys::Monitor::ScopedLock Lock;
@@ -158,10 +144,10 @@ class Cluster : private Cpg::Handler, public management::Manageable {
/** Version number of the cluster protocol, to avoid mixed versions. */
static const uint32_t CLUSTER_VERSION;
-
+
// NB: A dummy Lock& parameter marks functions that must only be
// called with Cluster::lock locked.
-
+
void leave(Lock&);
std::vector<std::string> getIds(Lock&) const;
std::vector<Url> getUrls(Lock&) const;
@@ -170,11 +156,11 @@ class Cluster : private Cpg::Handler, public management::Manageable {
void brokerShutdown();
// == Called in deliverEventQueue thread
- void deliveredEvent(const Event&);
+ void deliveredEvent(const Event&);
// == Called in deliverFrameQueue thread
- void deliveredFrame(const EventFrame&);
- void processFrame(const EventFrame&, Lock&);
+ void deliveredFrame(const EventFrame&);
+ void processFrame(const EventFrame&, Lock&);
// Cluster controls implement XML methods from cluster.xml.
void updateRequest(const MemberId&, const std::string&, Lock&);
@@ -194,12 +180,12 @@ class Cluster : private Cpg::Handler, public management::Manageable {
const std::string& left,
const std::string& joined,
Lock& l);
+ void messageExpired(const MemberId&, uint64_t, Lock& l);
void errorCheck(const MemberId&, uint8_t type, SequenceNumber frameSeq, Lock&);
void timerWakeup(const MemberId&, const std::string& name, Lock&);
void timerDrop(const MemberId&, const std::string& name, Lock&);
void shutdown(const MemberId&, const framing::Uuid& shutdownId, Lock&);
void deliverToQueue(const std::string& queue, const std::string& message, Lock&);
- void clock(const uint64_t time, Lock&);
// Helper functions
ConnectionPtr getConnection(const EventFrame&, Lock&);
@@ -209,7 +195,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
void setReady(Lock&);
void memberUpdate(Lock&);
void setClusterId(const framing::Uuid&, Lock&);
- void erase(const ConnectionId&, Lock&);
+ void erase(const ConnectionId&, Lock&);
void requestUpdate(Lock& );
void initMapCompleted(Lock&);
void becomeElder(Lock&);
@@ -217,7 +203,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
void updateMgmtMembership(Lock&);
// == Called in CPG dispatch thread
- void deliver( // CPG deliver callback.
+ void deliver( // CPG deliver callback.
cpg_handle_t /*handle*/,
const struct cpg_name *group,
uint32_t /*nodeid*/,
@@ -226,7 +212,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
int /*msg_len*/);
void deliverEvent(const Event&);
-
+
void configChange( // CPG config change callback.
cpg_handle_t /*handle*/,
const struct cpg_name */*group*/,
@@ -277,7 +263,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
// Used only in deliverEventQueue thread or when stalled for update.
Decoder decoder;
bool discarding;
-
+
// Remaining members are protected by lock.
mutable sys::Monitor lock;
@@ -290,7 +276,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
JOINER, ///< Sent update request, waiting for update offer.
UPDATEE, ///< Stalled receive queue at update offer, waiting for update to complete.
CATCHUP, ///< Update complete, unstalled but has not yet seen own "ready" event.
- READY, ///< Fully operational
+ READY, ///< Fully operational
OFFER, ///< Sent an offer, waiting for accept/reject.
UPDATER, ///< Offer accepted, sending a state update.
LEFT ///< Final state, left the cluster.
@@ -310,13 +296,9 @@ class Cluster : private Cpg::Handler, public management::Manageable {
ErrorCheck error;
UpdateReceiver updateReceiver;
ClusterTimer* timer;
- sys::Timer clockTimer;
- sys::AbsTime clusterTime;
- sys::Duration clusterTimeOffset;
- broker::AclModule* acl;
friend std::ostream& operator<<(std::ostream&, const Cluster&);
- friend struct ClusterDispatcher;
+ friend class ClusterDispatcher;
};
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/ClusterMap.cpp b/cpp/src/qpid/cluster/ClusterMap.cpp
index a8389095c9..040e129970 100644
--- a/cpp/src/qpid/cluster/ClusterMap.cpp
+++ b/cpp/src/qpid/cluster/ClusterMap.cpp
@@ -50,6 +50,11 @@ void insertFieldTableFromMapValue(FieldTable& ft, const ClusterMap::Map::value_t
ft.setString(vt.first.str(), vt.second.str());
}
+void assignFieldTable(FieldTable& ft, const ClusterMap::Map& map) {
+ ft.clear();
+ for_each(map.begin(), map.end(), bind(&insertFieldTableFromMapValue, ref(ft), _1));
+}
+
}
ClusterMap::ClusterMap() : frameSeq(0) {}
diff --git a/cpp/src/qpid/cluster/ClusterPlugin.cpp b/cpp/src/qpid/cluster/ClusterPlugin.cpp
index 69ba095f16..2962daaa07 100644
--- a/cpp/src/qpid/cluster/ClusterPlugin.cpp
+++ b/cpp/src/qpid/cluster/ClusterPlugin.cpp
@@ -72,7 +72,6 @@ struct ClusterOptions : public Options {
("cluster-cman", optValue(settings.quorum), "Integrate with Cluster Manager (CMAN) cluster.")
#endif
("cluster-size", optValue(settings.size, "N"), "Wait for N cluster members before allowing clients to connect.")
- ("cluster-clock-interval", optValue(settings.clockInterval,"N"), "How often to broadcast the current time to the cluster nodes, in milliseconds. A value between 5 and 1000 is recommended.")
("cluster-read-max", optValue(settings.readMax,"N"), "Experimental: flow-control limit reads per connection. 0=no limit.")
;
}
diff --git a/cpp/src/qpid/cluster/ClusterSettings.h b/cpp/src/qpid/cluster/ClusterSettings.h
index 2f7b5be20a..8e708aa139 100644
--- a/cpp/src/qpid/cluster/ClusterSettings.h
+++ b/cpp/src/qpid/cluster/ClusterSettings.h
@@ -35,9 +35,8 @@ struct ClusterSettings {
size_t readMax;
std::string username, password, mechanism;
size_t size;
- uint16_t clockInterval;
- ClusterSettings() : quorum(false), readMax(10), size(1), clockInterval(10)
+ ClusterSettings() : quorum(false), readMax(10), size(1)
{}
Url getUrl(uint16_t port) const {
diff --git a/cpp/src/qpid/cluster/ClusterTimer.cpp b/cpp/src/qpid/cluster/ClusterTimer.cpp
index b4f7d00f38..f6e1c7a849 100644
--- a/cpp/src/qpid/cluster/ClusterTimer.cpp
+++ b/cpp/src/qpid/cluster/ClusterTimer.cpp
@@ -70,7 +70,6 @@ void ClusterTimer::add(intrusive_ptr<TimerTask> task)
if (i != map.end())
throw Exception(QPID_MSG("Task already exists with name " << task->getName()));
map[task->getName()] = task;
-
// Only the elder actually activates the task with the Timer base class.
if (cluster.isElder()) {
QPID_LOG(trace, "Elder activating cluster timer task " << task->getName());
@@ -113,9 +112,6 @@ void ClusterTimer::deliverWakeup(const std::string& name) {
else {
intrusive_ptr<TimerTask> t = i->second;
map.erase(i);
- // Move the nextFireTime so readyToFire() is true. This is to ensure we
- // don't get an error if the fired task calls setupNextFire()
- t->setFired();
Timer::fire(t);
}
}
diff --git a/cpp/src/qpid/cluster/Connection.cpp b/cpp/src/qpid/cluster/Connection.cpp
index 394749aad2..e9b718e6de 100644
--- a/cpp/src/qpid/cluster/Connection.cpp
+++ b/cpp/src/qpid/cluster/Connection.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -24,8 +24,6 @@
#include "Cluster.h"
#include "UpdateReceiver.h"
#include "qpid/assert.h"
-#include "qpid/broker/DtxAck.h"
-#include "qpid/broker/DtxBuffer.h"
#include "qpid/broker/SessionState.h"
#include "qpid/broker/SemanticState.h"
#include "qpid/broker/TxBuffer.h"
@@ -37,7 +35,6 @@
#include "qpid/broker/Fairshare.h"
#include "qpid/broker/Link.h"
#include "qpid/broker/Bridge.h"
-#include "qpid/broker/StatefulQueueObserver.h"
#include "qpid/broker/Queue.h"
#include "qpid/framing/enum.h"
#include "qpid/framing/AMQFrame.h"
@@ -81,7 +78,7 @@ const std::string shadowPrefix("[shadow]");
Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out,
const std::string& mgmtId,
const ConnectionId& id, const qpid::sys::SecuritySettings& external)
- : cluster(c), self(id), catchUp(false), announced(false), output(*this, out),
+ : cluster(c), self(id), catchUp(false), output(*this, out),
connectionCtor(&output, cluster.getBroker(), mgmtId, external, false, 0, true),
expectProtocolHeader(false),
mcastFrameHandler(cluster.getMulticast(), self),
@@ -93,15 +90,13 @@ Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out,
Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out,
const std::string& mgmtId, MemberId member,
bool isCatchUp, bool isLink, const qpid::sys::SecuritySettings& external
-) : cluster(c), self(member, ++idCounter), catchUp(isCatchUp), announced(false), output(*this, out),
+) : cluster(c), self(member, ++idCounter), catchUp(isCatchUp), output(*this, out),
connectionCtor(&output, cluster.getBroker(),
mgmtId,
external,
isLink,
isCatchUp ? ++catchUpId : 0,
- // The first catch-up connection is not considered a shadow
- // as it needs to be authenticated.
- isCatchUp && self.second > 1),
+ isCatchUp), // isCatchUp => shadow
expectProtocolHeader(isLink),
mcastFrameHandler(cluster.getMulticast(), self),
updateIn(c.getUpdateReceiver()),
@@ -118,7 +113,7 @@ Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out,
if (!updateIn.nextShadowMgmtId.empty())
connectionCtor.mgmtId = updateIn.nextShadowMgmtId;
updateIn.nextShadowMgmtId.clear();
- }
+ }
init();
QPID_LOG(debug, cluster << " local connection " << *this);
}
@@ -148,7 +143,7 @@ void Connection::init() {
// Called when we have consumed a read buffer to give credit to the
// connection layer to continue reading.
void Connection::giveReadCredit(int credit) {
- if (cluster.getSettings().readMax && credit)
+ if (cluster.getSettings().readMax && credit)
output.giveReadCredit(credit);
}
@@ -171,7 +166,7 @@ void Connection::announce(
AMQFrame frame;
while (frame.decode(buf))
connection->received(frame);
- connection->setUserId(username);
+ connection->setUserId(username);
}
// Do managment actions now that the connection is replicated.
connection->raiseConnectEvent();
@@ -198,7 +193,7 @@ void Connection::received(framing::AMQFrame& f) {
<< *this << ": " << f);
return;
}
- QPID_LOG_IF(trace, Cluster::loggable(f), cluster << " RECV " << *this << ": " << f);
+ QPID_LOG(trace, cluster << " RECV " << *this << ": " << f);
if (isLocal()) { // Local catch-up connection.
currentChannel = f.getChannel();
if (!framing::invoke(*this, *f.getBody()).wasHandled())
@@ -206,7 +201,7 @@ void Connection::received(framing::AMQFrame& f) {
}
else { // Shadow or updated catch-up connection.
if (f.getMethod() && f.getMethod()->isA<ConnectionCloseBody>()) {
- if (isShadow())
+ if (isShadow())
cluster.addShadowConnection(this);
AMQFrame ok((ConnectionCloseOkBody()));
connection->getOutput().send(ok);
@@ -218,9 +213,16 @@ void Connection::received(framing::AMQFrame& f) {
}
}
-bool Connection::checkUnsupported(const AMQBody&) {
- // Throw an exception for unsupported commands. Currently all are supported.
- return false;
+bool Connection::checkUnsupported(const AMQBody& body) {
+ std::string message;
+ if (body.getMethod()) {
+ switch (body.getMethod()->amqpClassId()) {
+ case DTX_CLASS_ID: message = "DTX transactions are not currently supported by cluster."; break;
+ }
+ }
+ if (!message.empty())
+ connection->close(connection::CLOSE_CODE_FRAMING_ERROR, message);
+ return !message.empty();
}
struct GiveReadCreditOnExit {
@@ -239,7 +241,7 @@ void Connection::deliverDoOutput(uint32_t limit) {
void Connection::deliveredFrame(const EventFrame& f) {
GiveReadCreditOnExit gc(*this, f.readCredit);
assert(!catchUp);
- currentChannel = f.frame.getChannel();
+ currentChannel = f.frame.getChannel();
if (f.frame.getBody() // frame can be emtpy with just readCredit
&& !framing::invoke(*this, *f.frame.getBody()).wasHandled() // Connection contol.
&& !checkUnsupported(*f.frame.getBody())) // Unsupported operation.
@@ -253,7 +255,7 @@ void Connection::deliveredFrame(const EventFrame& f) {
}
}
-// A local connection is closed by the network layer. Called in the connection thread.
+// A local connection is closed by the network layer.
void Connection::closed() {
try {
if (isUpdated()) {
@@ -270,9 +272,8 @@ void Connection::closed() {
// closed and process any outstanding frames from the cluster
// until self-delivery of deliver-close.
output.closeOutput();
- if (announced)
- cluster.getMulticast().mcastControl(
- ClusterConnectionDeliverCloseBody(), self);
+ cluster.getMulticast().mcastControl(
+ ClusterConnectionDeliverCloseBody(), self);
}
}
catch (const std::exception& e) {
@@ -286,7 +287,7 @@ void Connection::deliverClose () {
cluster.erase(self);
}
-// Close the connection
+// Close the connection
void Connection::close() {
if (connection.get()) {
QPID_LOG(debug, cluster << " closed connection " << *this);
@@ -319,10 +320,10 @@ size_t Connection::decode(const char* data, size_t size) {
while (localDecoder.decode(buf))
received(localDecoder.getFrame());
if (!wasOpen && connection->isOpen()) {
- // Connections marked with setUserProxyAuth are allowed to proxy
+ // Connections marked as federation links are allowed to proxy
// messages with user-ID that doesn't match the connection's
// authenticated ID. This is important for updates.
- connection->setUserProxyAuth(isCatchUp());
+ connection->setFederationLink(isCatchUp());
}
}
else { // Multicast local connections.
@@ -331,9 +332,9 @@ size_t Connection::decode(const char* data, size_t size) {
if (!checkProtocolHeader(ptr, size)) // Updates ptr
return 0; // Incomplete header
- if (!connection->isOpen())
+ if (!connection->isOpen())
processInitialFrames(ptr, end-ptr); // Updates ptr
-
+
if (connection->isOpen() && end - ptr > 0) {
// We're multi-casting, we will give read credit on delivery.
grc.credit = 0;
@@ -383,7 +384,6 @@ void Connection::processInitialFrames(const char*& ptr, size_t size) {
connection->getUserId(),
initialFrames),
getId());
- announced = true;
initialFrames.clear();
}
}
@@ -406,11 +406,11 @@ void Connection::shadowSetUser(const std::string& userId) {
void Connection::consumerState(const string& name, bool blocked, bool notifyEnabled, const SequenceNumber& position)
{
- broker::SemanticState::ConsumerImpl::shared_ptr c = semanticState().find(name);
- c->position = position;
- c->setBlocked(blocked);
- if (notifyEnabled) c->enableNotify(); else c->disableNotify();
- updateIn.consumerNumbering.add(c);
+ broker::SemanticState::ConsumerImpl& c = semanticState().find(name);
+ c.position = position;
+ c.setBlocked(blocked);
+ if (notifyEnabled) c.enableNotify(); else c.disableNotify();
+ updateIn.consumerNumbering.add(c.shared_from_this());
}
@@ -421,8 +421,7 @@ void Connection::sessionState(
const SequenceNumber& expected,
const SequenceNumber& received,
const SequenceSet& unknownCompleted,
- const SequenceSet& receivedIncomplete,
- bool dtxSelected)
+ const SequenceSet& receivedIncomplete)
{
sessionState().setState(
replayStart,
@@ -432,10 +431,8 @@ void Connection::sessionState(
received,
unknownCompleted,
receivedIncomplete);
- if (dtxSelected) semanticState().selectDtx();
- QPID_LOG(debug, cluster << " received session state update for "
- << sessionState().getId());
- // The output tasks will be added later in the update process.
+ QPID_LOG(debug, cluster << " received session state update for " << sessionState().getId());
+ // The output tasks will be added later in the update process.
connection->getOutputTasks().removeAll();
}
@@ -444,7 +441,7 @@ void Connection::outputTask(uint16_t channel, const std::string& name) {
if (!session)
throw Exception(QPID_MSG(cluster << " channel not attached " << *this
<< "[" << channel << "] "));
- OutputTask* task = session->getSemanticState().find(name).get();
+ OutputTask* task = &session->getSemanticState().find(name);
connection->getOutputTasks().addOutputTask(task);
}
@@ -464,24 +461,11 @@ void Connection::shadowReady(
output.setSendMax(sendMax);
}
-void Connection::setDtxBuffer(const UpdateReceiver::DtxBufferRef& bufRef) {
- broker::DtxManager& mgr = cluster.getBroker().getDtxManager();
- broker::DtxWorkRecord* record = mgr.getWork(bufRef.xid);
- broker::DtxBuffer::shared_ptr buffer = (*record)[bufRef.index];
- if (bufRef.suspended)
- bufRef.semanticState->getSuspendedXids()[bufRef.xid] = buffer;
- else
- bufRef.semanticState->setDtxBuffer(buffer);
-}
-
-// Marks the end of the update.
void Connection::membership(const FieldTable& joiners, const FieldTable& members,
const framing::SequenceNumber& frameSeq)
{
QPID_LOG(debug, cluster << " incoming update complete on connection " << *this);
updateIn.consumerNumbering.clear();
- for_each(updateIn.dtxBuffers.begin(), updateIn.dtxBuffers.end(),
- boost::bind(&Connection::setDtxBuffer, this, _1));
closeUpdated();
cluster.updateInDone(ClusterMap(joiners, members, frameSeq));
}
@@ -494,7 +478,7 @@ void Connection::retractOffer() {
void Connection::closeUpdated() {
self.second = 0; // Mark this as completed update connection.
- if (connection.get())
+ if (connection.get())
connection->close(connection::CLOSE_CODE_NORMAL, "OK");
}
@@ -545,20 +529,12 @@ void Connection::deliveryRecord(const string& qname,
m = getUpdateMessage();
m.queue = queue.get();
m.position = position;
- if (enqueued) queue->updateEnqueued(m); //inform queue of the message
+ if (enqueued) queue->updateEnqueued(m); //inform queue of the message
} else { // Message at original position in original queue
- queue->find(position, m);
+ m = queue->find(position);
}
- // FIXME aconway 2011-08-19: removed:
- // if (!m.payload)
- // throw Exception(QPID_MSG("deliveryRecord no update message"));
- //
- // It seems this could happen legitimately in the case one
- // session browses message M, then another session acquires
- // it. In that case the browsers delivery record is !acquired
- // but the message is not on its original Queue. In that case
- // we'll get a deliveryRecord with no payload for the browser.
- //
+ if (!m.payload)
+ throw Exception(QPID_MSG("deliveryRecord no update message"));
}
broker::DeliveryRecord dr(m, queue, tag, acquired, accepted, windowing, credit);
@@ -566,11 +542,7 @@ void Connection::deliveryRecord(const string& qname,
if (cancelled) dr.cancel(dr.getTag());
if (completed) dr.complete();
if (ended) dr.setEnded(); // Exsitance of message
-
- if (dtxBuffer) // Record for next dtx-ack
- dtxAckRecords.push_back(dr);
- else
- semanticState().record(dr); // Record on session's unacked list.
+ semanticState().record(dr); // Part of the session's unacked list.
}
void Connection::queuePosition(const string& qname, const SequenceNumber& position) {
@@ -584,46 +556,8 @@ void Connection::queueFairshareState(const std::string& qname, const uint8_t pri
}
}
-
-namespace {
-// find a StatefulQueueObserver that matches a given identifier
-class ObserverFinder {
- const std::string id;
- boost::shared_ptr<broker::QueueObserver> target;
- ObserverFinder(const ObserverFinder&) {}
- public:
- ObserverFinder(const std::string& _id) : id(_id) {}
- broker::StatefulQueueObserver *getObserver()
- {
- if (target)
- return dynamic_cast<broker::StatefulQueueObserver *>(target.get());
- return 0;
- }
- void operator() (boost::shared_ptr<broker::QueueObserver> o)
- {
- if (!target) {
- broker::StatefulQueueObserver *p = dynamic_cast<broker::StatefulQueueObserver *>(o.get());
- if (p && p->getId() == id) {
- target = o;
- }
- }
- }
-};
-}
-
-
-void Connection::queueObserverState(const std::string& qname, const std::string& observerId, const FieldTable& state)
-{
- boost::shared_ptr<broker::Queue> queue(findQueue(qname));
- ObserverFinder finder(observerId); // find this observer
- queue->eachObserver<ObserverFinder &>(finder);
- broker::StatefulQueueObserver *so = finder.getObserver();
- if (so) {
- so->setState( state );
- QPID_LOG(debug, "updated queue observer " << observerId << "'s state on queue " << qname << "; ...");
- return;
- }
- QPID_LOG(error, "Failed to find observer " << observerId << " state on queue " << qname << "; this will result in inconsistencies.");
+void Connection::expiryId(uint64_t id) {
+ cluster.getExpiryPolicy().setId(id);
}
std::ostream& operator<<(std::ostream& o, const Connection& c) {
@@ -640,7 +574,6 @@ std::ostream& operator<<(std::ostream& o, const Connection& c) {
void Connection::txStart() {
txBuffer.reset(new broker::TxBuffer());
}
-
void Connection::txAccept(const framing::SequenceSet& acked) {
txBuffer->enlist(boost::shared_ptr<broker::TxAccept>(
new broker::TxAccept(acked, semanticState().getUnacked())));
@@ -656,11 +589,9 @@ void Connection::txEnqueue(const std::string& queue) {
new broker::RecoveredEnqueue(findQueue(queue), getUpdateMessage().payload)));
}
-void Connection::txPublish(const framing::Array& queues, bool delivered)
-{
- boost::shared_ptr<broker::TxPublish> txPub(
- new broker::TxPublish(getUpdateMessage().payload));
- for (framing::Array::const_iterator i = queues.begin(); i != queues.end(); ++i)
+void Connection::txPublish(const framing::Array& queues, bool delivered) {
+ boost::shared_ptr<broker::TxPublish> txPub(new broker::TxPublish(getUpdateMessage().payload));
+ for (framing::Array::const_iterator i = queues.begin(); i != queues.end(); ++i)
txPub->deliverTo(findQueue((*i)->get<std::string>()));
txPub->delivered = delivered;
txBuffer->enlist(txPub);
@@ -674,51 +605,6 @@ void Connection::accumulatedAck(const qpid::framing::SequenceSet& s) {
semanticState().setAccumulatedAck(s);
}
-void Connection::dtxStart(const std::string& xid,
- bool ended,
- bool suspended,
- bool failed,
- bool expired)
-{
- dtxBuffer.reset(new broker::DtxBuffer(xid, ended, suspended, failed, expired));
- txBuffer = dtxBuffer;
-}
-
-void Connection::dtxEnd() {
- broker::DtxManager& mgr = cluster.getBroker().getDtxManager();
- std::string xid = dtxBuffer->getXid();
- if (mgr.exists(xid))
- mgr.join(xid, dtxBuffer);
- else
- mgr.start(xid, dtxBuffer);
- dtxBuffer.reset();
- txBuffer.reset();
-}
-
-// Sent after all DeliveryRecords for a dtx-ack have been collected in dtxAckRecords
-void Connection::dtxAck() {
- dtxBuffer->enlist(
- boost::shared_ptr<broker::DtxAck>(new broker::DtxAck(dtxAckRecords)));
- dtxAckRecords.clear();
-}
-
-void Connection::dtxBufferRef(const std::string& xid, uint32_t index, bool suspended) {
- // Save the association between DtxBuffers and the session so we
- // can set the DtxBuffers at the end of the update when the
- // DtxManager has been replicated.
- updateIn.dtxBuffers.push_back(
- UpdateReceiver::DtxBufferRef(xid, index, suspended, &semanticState()));
-}
-
-// Sent at end of work record.
-void Connection::dtxWorkRecord(const std::string& xid, bool prepared, uint32_t timeout)
-{
- broker::DtxManager& mgr = cluster.getBroker().getDtxManager();
- if (timeout) mgr.setTimeout(xid, timeout);
- if (prepared) mgr.prepare(xid);
-}
-
-
void Connection::exchange(const std::string& encoded) {
Buffer buf(const_cast<char*>(encoded.data()), encoded.size());
broker::Exchange::shared_ptr ex = broker::Exchange::decode(cluster.getBroker().getExchanges(), buf);
@@ -728,6 +614,12 @@ void Connection::exchange(const std::string& encoded) {
QPID_LOG(debug, cluster << " updated exchange " << ex->getName());
}
+void Connection::queue(const std::string& encoded) {
+ Buffer buf(const_cast<char*>(encoded.data()), encoded.size());
+ broker::Queue::shared_ptr q = broker::Queue::decode(cluster.getBroker().getQueues(), buf);
+ QPID_LOG(debug, cluster << " updated queue " << q->getName());
+}
+
void Connection::sessionError(uint16_t , const std::string& msg) {
// Ignore errors before isOpen(), we're not multicasting yet.
if (connection->isOpen())
@@ -786,23 +678,6 @@ void Connection::config(const std::string& encoded) {
else throw Exception(QPID_MSG("Update failed, invalid kind of config: " << kind));
}
-void Connection::doCatchupIoCallbacks() {
- // We need to process IO callbacks during the catch-up phase in
- // order to service asynchronous completions for messages
- // transferred during catch-up.
-
- if (catchUp) getBrokerConnection()->doIoCallbacks();
-}
-
-void Connection::clock(uint64_t time) {
- QPID_LOG(debug, "Cluster connection received time update");
- cluster.clock(time);
-}
-
-void Connection::queueDequeueSincePurgeState(const std::string& qname, uint32_t dequeueSincePurge) {
- boost::shared_ptr<broker::Queue> queue(findQueue(qname));
- queue->setDequeueSincePurge(dequeueSincePurge);
-}
}} // Namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/Connection.h b/cpp/src/qpid/cluster/Connection.h
index fe66b77238..7ee85bf1aa 100644
--- a/cpp/src/qpid/cluster/Connection.h
+++ b/cpp/src/qpid/cluster/Connection.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -24,12 +24,11 @@
#include "types.h"
#include "OutputInterceptor.h"
+#include "EventFrame.h"
#include "McastFrameHandler.h"
#include "UpdateReceiver.h"
-#include "qpid/RefCounted.h"
#include "qpid/broker/Connection.h"
-#include "qpid/broker/DeliveryRecord.h"
#include "qpid/broker/SecureConnection.h"
#include "qpid/broker/SemanticState.h"
#include "qpid/amqp_0_10/Connection.h"
@@ -48,7 +47,7 @@ namespace framing { class AMQFrame; }
namespace broker {
class SemanticState;
-struct QueuedMessage;
+class QueuedMessage;
class TxBuffer;
class TxAccept;
}
@@ -56,7 +55,6 @@ class TxAccept;
namespace cluster {
class Cluster;
class Event;
-struct EventFrame;
/** Intercept broker::Connection calls for shadow and local cluster connections. */
class Connection :
@@ -64,7 +62,7 @@ class Connection :
public sys::ConnectionInputHandler,
public framing::AMQP_AllOperations::ClusterConnectionHandler,
private broker::Connection::ErrorListener
-
+
{
public:
@@ -75,7 +73,7 @@ class Connection :
Connection(Cluster&, sys::ConnectionOutputHandler& out, const std::string& mgmtId, const ConnectionId& id,
const qpid::sys::SecuritySettings& external);
~Connection();
-
+
ConnectionId getId() const { return self; }
broker::Connection* getBrokerConnection() { return connection.get(); }
const broker::Connection* getBrokerConnection() const { return connection.get(); }
@@ -110,9 +108,9 @@ class Connection :
void deliveredFrame(const EventFrame&);
void consumerState(const std::string& name, bool blocked, bool notifyEnabled, const qpid::framing::SequenceNumber& position);
-
+
// ==== Used in catch-up mode to build initial state.
- //
+ //
// State update methods.
void shadowPrepare(const std::string&);
@@ -124,11 +122,10 @@ class Connection :
const framing::SequenceNumber& expected,
const framing::SequenceNumber& received,
const framing::SequenceSet& unknownCompleted,
- const SequenceSet& receivedIncomplete,
- bool dtxSelected);
-
+ const SequenceSet& receivedIncomplete);
+
void outputTask(uint16_t channel, const std::string& name);
-
+
void shadowReady(uint64_t memberId,
uint64_t connectionId,
const std::string& managementId,
@@ -156,7 +153,7 @@ class Connection :
void queuePosition(const std::string&, const framing::SequenceNumber&);
void queueFairshareState(const std::string&, const uint8_t priority, const uint8_t count);
- void queueObserverState(const std::string&, const std::string&, const framing::FieldTable&);
+ void expiryId(uint64_t);
void txStart();
void txAccept(const framing::SequenceSet&);
@@ -166,18 +163,8 @@ class Connection :
void txEnd();
void accumulatedAck(const framing::SequenceSet&);
- // Dtx state
- void dtxStart(const std::string& xid,
- bool ended,
- bool suspended,
- bool failed,
- bool expired);
- void dtxEnd();
- void dtxAck();
- void dtxBufferRef(const std::string& xid, uint32_t index, bool suspended);
- void dtxWorkRecord(const std::string& xid, bool prepared, uint32_t timeout);
-
- // Encoded exchange replication.
+ // Encoded queue/exchange replication.
+ void queue(const std::string& encoded);
void exchange(const std::string& encoded);
void giveReadCredit(int credit);
@@ -202,12 +189,6 @@ class Connection :
void setSecureConnection ( broker::SecureConnection * sc );
- void doCatchupIoCallbacks();
-
- void clock(uint64_t time);
-
- void queueDequeueSincePurgeState(const std::string&, uint32_t);
-
private:
struct NullFrameHandler : public framing::FrameHandler {
void handle(framing::AMQFrame&) {}
@@ -252,7 +233,7 @@ class Connection :
// Error listener functions
void connectionError(const std::string&);
void sessionError(uint16_t channel, const std::string&);
-
+
void init();
bool checkUnsupported(const framing::AMQBody& body);
void deliverDoOutput(uint32_t limit);
@@ -264,11 +245,10 @@ class Connection :
broker::SemanticState& semanticState();
broker::QueuedMessage getUpdateMessage();
void closeUpdated();
- void setDtxBuffer(const UpdateReceiver::DtxBuffers::value_type &);
+
Cluster& cluster;
ConnectionId self;
bool catchUp;
- bool announced;
OutputInterceptor output;
framing::FrameDecoder localDecoder;
ConnectionCtor connectionCtor;
@@ -276,9 +256,6 @@ class Connection :
framing::SequenceNumber deliverSeq;
framing::ChannelId currentChannel;
boost::shared_ptr<broker::TxBuffer> txBuffer;
- boost::shared_ptr<broker::DtxBuffer> dtxBuffer;
- broker::DeliveryRecords dtxAckRecords;
- broker::DtxWorkRecord* dtxCurrent;
bool expectProtocolHeader;
McastFrameHandler mcastFrameHandler;
UpdateReceiver& updateIn;
diff --git a/cpp/src/qpid/cluster/Decoder.h b/cpp/src/qpid/cluster/Decoder.h
index 3b5ada4a81..2e2af2868f 100644
--- a/cpp/src/qpid/cluster/Decoder.h
+++ b/cpp/src/qpid/cluster/Decoder.h
@@ -31,7 +31,7 @@
namespace qpid {
namespace cluster {
-struct EventFrame;
+class EventFrame;
class EventHeader;
/**
diff --git a/cpp/src/qpid/cluster/ErrorCheck.h b/cpp/src/qpid/cluster/ErrorCheck.h
index a417b2ec25..de8cedafb3 100644
--- a/cpp/src/qpid/cluster/ErrorCheck.h
+++ b/cpp/src/qpid/cluster/ErrorCheck.h
@@ -33,7 +33,7 @@
namespace qpid {
namespace cluster {
-struct EventFrame;
+class EventFrame;
class Cluster;
class Multicaster;
class Connection;
diff --git a/cpp/src/qpid/cluster/Event.cpp b/cpp/src/qpid/cluster/Event.cpp
index da2bc89d8c..cd775ce2f1 100644
--- a/cpp/src/qpid/cluster/Event.cpp
+++ b/cpp/src/qpid/cluster/Event.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,7 +23,6 @@
#include "qpid/cluster/Cpg.h"
#include "qpid/framing/Buffer.h"
#include "qpid/framing/AMQFrame.h"
-#include "qpid/RefCountedBuffer.h"
#include "qpid/assert.h"
#include <ostream>
#include <iterator>
diff --git a/cpp/src/qpid/cluster/Event.h b/cpp/src/qpid/cluster/Event.h
index 13283edff7..07f74d3ba5 100644
--- a/cpp/src/qpid/cluster/Event.h
+++ b/cpp/src/qpid/cluster/Event.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,7 +23,7 @@
*/
#include "qpid/cluster/types.h"
-#include "qpid/BufferRef.h"
+#include "qpid/RefCountedBuffer.h"
#include "qpid/framing/AMQFrame.h"
#include <sys/uio.h> // For iovec
#include <iosfwd>
@@ -53,7 +53,7 @@ class EventHeader {
/** Size of payload data, excluding header. */
size_t getSize() const { return size; }
- /** Size of header + payload. */
+ /** Size of header + payload. */
size_t getStoreSize() const { return size + HEADER_SIZE; }
bool isCluster() const { return connectionId.getNumber() == 0; }
@@ -62,7 +62,7 @@ class EventHeader {
protected:
static const size_t HEADER_SIZE;
-
+
EventType type;
ConnectionId connectionId;
size_t size;
@@ -86,25 +86,25 @@ class Event : public EventHeader {
/** Create a control event. */
static Event control(const framing::AMQFrame&, const ConnectionId&);
-
+
// Data excluding header.
- char* getData() { return store.begin() + HEADER_SIZE; }
- const char* getData() const { return store.begin() + HEADER_SIZE; }
+ char* getData() { return store + HEADER_SIZE; }
+ const char* getData() const { return store + HEADER_SIZE; }
// Store including header
- char* getStore() { return store.begin(); }
- const char* getStore() const { return store.begin(); }
-
- const framing::AMQFrame& getFrame() const;
+ char* getStore() { return store; }
+ const char* getStore() const { return store; }
+ const framing::AMQFrame& getFrame() const;
+
operator framing::Buffer() const;
iovec toIovec() const;
-
+
private:
void encodeHeader() const;
- BufferRef store;
+ RefCountedBuffer::pointer store;
mutable framing::AMQFrame frame;
};
diff --git a/cpp/src/qpid/cluster/EventFrame.h b/cpp/src/qpid/cluster/EventFrame.h
index 6b702a9bf8..61447c5525 100644
--- a/cpp/src/qpid/cluster/EventFrame.h
+++ b/cpp/src/qpid/cluster/EventFrame.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -48,7 +48,7 @@ struct EventFrame
ConnectionId connectionId;
- framing::AMQFrame frame;
+ framing::AMQFrame frame;
int readCredit; ///< last frame in an event, give credit when processed.
EventType type;
};
diff --git a/cpp/src/qpid/cluster/ExpiryPolicy.cpp b/cpp/src/qpid/cluster/ExpiryPolicy.cpp
index 0ef5c2a35d..d9a7b0122a 100644
--- a/cpp/src/qpid/cluster/ExpiryPolicy.cpp
+++ b/cpp/src/qpid/cluster/ExpiryPolicy.cpp
@@ -21,21 +21,106 @@
#include "qpid/broker/Message.h"
#include "qpid/cluster/ExpiryPolicy.h"
-#include "qpid/cluster/Cluster.h"
+#include "qpid/cluster/Multicaster.h"
+#include "qpid/framing/ClusterMessageExpiredBody.h"
#include "qpid/sys/Time.h"
+#include "qpid/sys/Timer.h"
#include "qpid/log/Statement.h"
namespace qpid {
namespace cluster {
-ExpiryPolicy::ExpiryPolicy(Cluster& cluster) : cluster(cluster) {}
+ExpiryPolicy::ExpiryPolicy(Multicaster& m, const MemberId& id, sys::Timer& t)
+ : expiryId(1), expiredPolicy(new Expired), mcast(m), memberId(id), timer(t) {}
+struct ExpiryTask : public sys::TimerTask {
+ ExpiryTask(const boost::intrusive_ptr<ExpiryPolicy>& policy, uint64_t id, sys::AbsTime when)
+ : TimerTask(when,"ExpiryPolicy"), expiryPolicy(policy), expiryId(id) {}
+ void fire() { expiryPolicy->sendExpire(expiryId); }
+ boost::intrusive_ptr<ExpiryPolicy> expiryPolicy;
+ const uint64_t expiryId;
+};
+
+// Called while receiving an update
+void ExpiryPolicy::setId(uint64_t id) {
+ sys::Mutex::ScopedLock l(lock);
+ expiryId = id;
+}
+
+// Called while giving an update
+uint64_t ExpiryPolicy::getId() const {
+ sys::Mutex::ScopedLock l(lock);
+ return expiryId;
+}
+
+// Called in enqueuing connection thread
+void ExpiryPolicy::willExpire(broker::Message& m) {
+ uint64_t id;
+ {
+ // When messages are fanned out to multiple queues, update sends
+ // them as independenty messages so we can have multiple messages
+ // with the same expiry ID.
+ //
+ sys::Mutex::ScopedLock l(lock);
+ id = expiryId++;
+ if (!id) { // This is an update of an already-expired message.
+ m.setExpiryPolicy(expiredPolicy);
+ }
+ else {
+ assert(unexpiredByMessage.find(&m) == unexpiredByMessage.end());
+ // If this is an update, the id may already exist
+ unexpiredById.insert(IdMessageMap::value_type(id, &m));
+ unexpiredByMessage[&m] = id;
+ }
+ }
+ timer.add(new ExpiryTask(this, id, m.getExpiration()));
+}
+
+// Called in dequeueing connection thread
+void ExpiryPolicy::forget(broker::Message& m) {
+ sys::Mutex::ScopedLock l(lock);
+ MessageIdMap::iterator i = unexpiredByMessage.find(&m);
+ assert(i != unexpiredByMessage.end());
+ unexpiredById.erase(i->second);
+ unexpiredByMessage.erase(i);
+}
+
+// Called in dequeueing connection or cleanup thread.
bool ExpiryPolicy::hasExpired(broker::Message& m) {
- return m.getExpiration() < cluster.getClusterTime();
+ sys::Mutex::ScopedLock l(lock);
+ return unexpiredByMessage.find(&m) == unexpiredByMessage.end();
+}
+
+// Called in timer thread
+void ExpiryPolicy::sendExpire(uint64_t id) {
+ {
+ sys::Mutex::ScopedLock l(lock);
+ // Don't multicast an expiry notice if message is already forgotten.
+ if (unexpiredById.find(id) == unexpiredById.end()) return;
+ }
+ mcast.mcastControl(framing::ClusterMessageExpiredBody(framing::ProtocolVersion(), id), memberId);
}
-sys::AbsTime ExpiryPolicy::getCurrentTime() {
- return cluster.getClusterTime();
+// Called in CPG deliver thread.
+void ExpiryPolicy::deliverExpire(uint64_t id) {
+ sys::Mutex::ScopedLock l(lock);
+ std::pair<IdMessageMap::iterator, IdMessageMap::iterator> expired = unexpiredById.equal_range(id);
+ IdMessageMap::iterator i = expired.first;
+ while (i != expired.second) {
+ i->second->setExpiryPolicy(expiredPolicy); // hasExpired() == true;
+ unexpiredByMessage.erase(i->second);
+ unexpiredById.erase(i++);
+ }
}
+// Called in update thread on the updater.
+boost::optional<uint64_t> ExpiryPolicy::getId(broker::Message& m) {
+ sys::Mutex::ScopedLock l(lock);
+ MessageIdMap::iterator i = unexpiredByMessage.find(&m);
+ return i == unexpiredByMessage.end() ? boost::optional<uint64_t>() : i->second;
+}
+
+bool ExpiryPolicy::Expired::hasExpired(broker::Message&) { return true; }
+void ExpiryPolicy::Expired::willExpire(broker::Message&) { }
+
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/ExpiryPolicy.h b/cpp/src/qpid/cluster/ExpiryPolicy.h
index d8ddbca8b3..77a656aa68 100644
--- a/cpp/src/qpid/cluster/ExpiryPolicy.h
+++ b/cpp/src/qpid/cluster/ExpiryPolicy.h
@@ -36,8 +36,12 @@ namespace broker {
class Message;
}
+namespace sys {
+class Timer;
+}
+
namespace cluster {
-class Cluster;
+class Multicaster;
/**
* Cluster expiry policy
@@ -45,13 +49,43 @@ class Cluster;
class ExpiryPolicy : public broker::ExpiryPolicy
{
public:
- ExpiryPolicy(Cluster& cluster);
+ ExpiryPolicy(Multicaster&, const MemberId&, sys::Timer&);
+ void willExpire(broker::Message&);
bool hasExpired(broker::Message&);
- qpid::sys::AbsTime getCurrentTime();
+ void forget(broker::Message&);
+
+ // Send expiration notice to cluster.
+ void sendExpire(uint64_t);
+ // Cluster delivers expiry notice.
+ void deliverExpire(uint64_t);
+
+ void setId(uint64_t id);
+ uint64_t getId() const;
+
+ boost::optional<uint64_t> getId(broker::Message&);
+
private:
- Cluster& cluster;
+ typedef std::map<broker::Message*, uint64_t> MessageIdMap;
+ // When messages are fanned out to multiple queues, update sends
+ // them as independenty messages so we can have multiple messages
+ // with the same expiry ID.
+ typedef std::multimap<uint64_t, broker::Message*> IdMessageMap;
+
+ struct Expired : public broker::ExpiryPolicy {
+ bool hasExpired(broker::Message&);
+ void willExpire(broker::Message&);
+ };
+
+ mutable sys::Mutex lock;
+ MessageIdMap unexpiredByMessage;
+ IdMessageMap unexpiredById;
+ uint64_t expiryId;
+ boost::intrusive_ptr<Expired> expiredPolicy;
+ Multicaster& mcast;
+ MemberId memberId;
+ sys::Timer& timer;
};
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/FailoverExchange.cpp b/cpp/src/qpid/cluster/FailoverExchange.cpp
index cfbe34a460..84232dac1b 100644
--- a/cpp/src/qpid/cluster/FailoverExchange.cpp
+++ b/cpp/src/qpid/cluster/FailoverExchange.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -39,10 +39,8 @@ using namespace broker;
using namespace framing;
const string FailoverExchange::typeName("amq.failover");
-
-FailoverExchange::FailoverExchange(management::Manageable* parent, Broker* b)
- : Exchange(typeName, parent, b ), ready(false)
-{
+
+FailoverExchange::FailoverExchange(management::Manageable* parent, Broker* b) : Exchange(typeName, parent, b ) {
if (mgmtExchange != 0)
mgmtExchange->set_type(typeName);
}
@@ -55,17 +53,16 @@ void FailoverExchange::setUrls(const vector<Url>& u) {
void FailoverExchange::updateUrls(const vector<Url>& u) {
Lock l(lock);
urls=u;
- if (ready && !urls.empty()) {
- std::for_each(queues.begin(), queues.end(),
- boost::bind(&FailoverExchange::sendUpdate, this, _1));
- }
+ if (urls.empty()) return;
+ std::for_each(queues.begin(), queues.end(),
+ boost::bind(&FailoverExchange::sendUpdate, this, _1));
}
string FailoverExchange::getType() const { return typeName; }
bool FailoverExchange::bind(Queue::shared_ptr queue, const string&, const framing::FieldTable*) {
Lock l(lock);
- if (ready) sendUpdate(queue);
+ sendUpdate(queue);
return queues.insert(queue).second;
}
@@ -87,7 +84,7 @@ void FailoverExchange::sendUpdate(const Queue::shared_ptr& queue) {
// Called with lock held.
if (urls.empty()) return;
framing::Array array(0x95);
- for (Urls::const_iterator i = urls.begin(); i != urls.end(); ++i)
+ for (Urls::const_iterator i = urls.begin(); i != urls.end(); ++i)
array.add(boost::shared_ptr<Str16Value>(new Str16Value(i->str())));
const ProtocolVersion v;
boost::intrusive_ptr<Message> msg(new Message);
@@ -99,12 +96,9 @@ void FailoverExchange::sendUpdate(const Queue::shared_ptr& queue) {
header.get<MessageProperties>(true)->getApplicationHeaders().setArray(typeName, array);
AMQFrame headerFrame(header);
headerFrame.setFirstSegment(false);
- msg->getFrames().append(headerFrame);
+ msg->getFrames().append(headerFrame);
DeliverableMessage(msg).deliverTo(queue);
}
-void FailoverExchange::setReady() {
- ready = true;
-}
}} // namespace cluster
diff --git a/cpp/src/qpid/cluster/FailoverExchange.h b/cpp/src/qpid/cluster/FailoverExchange.h
index c3e50c6929..2e1edfc0ae 100644
--- a/cpp/src/qpid/cluster/FailoverExchange.h
+++ b/cpp/src/qpid/cluster/FailoverExchange.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -46,8 +46,6 @@ class FailoverExchange : public broker::Exchange
void setUrls(const std::vector<Url>&);
/** Set the URLs and send an update.*/
void updateUrls(const std::vector<Url>&);
- /** Flag the failover exchange as ready to generate updates (caught up) */
- void setReady();
// Exchange overrides
std::string getType() const;
@@ -58,7 +56,7 @@ class FailoverExchange : public broker::Exchange
private:
void sendUpdate(const boost::shared_ptr<broker::Queue>&);
-
+
typedef sys::Mutex::ScopedLock Lock;
typedef std::vector<Url> Urls;
typedef std::set<boost::shared_ptr<broker::Queue> > Queues;
@@ -66,7 +64,7 @@ class FailoverExchange : public broker::Exchange
sys::Mutex lock;
Urls urls;
Queues queues;
- bool ready;
+
};
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/Multicaster.cpp b/cpp/src/qpid/cluster/Multicaster.cpp
index 217641841c..8916de9628 100644
--- a/cpp/src/qpid/cluster/Multicaster.cpp
+++ b/cpp/src/qpid/cluster/Multicaster.cpp
@@ -21,7 +21,6 @@
#include "qpid/cluster/Multicaster.h"
#include "qpid/cluster/Cpg.h"
-#include "qpid/cluster/Cluster.h"
#include "qpid/log/Statement.h"
#include "qpid/framing/AMQBody.h"
#include "qpid/framing/AMQFrame.h"
@@ -59,7 +58,7 @@ void Multicaster::mcast(const Event& e) {
return;
}
}
- QPID_LOG_IF(trace, e.isControl() && Cluster::loggable(e.getFrame()), "MCAST " << e);
+ QPID_LOG(trace, "MCAST " << e);
if (bypass) { // direct, don't queue
iovec iov = e.toIovec();
while (!cpg.mcast(&iov, 1))
diff --git a/cpp/src/qpid/cluster/OutputInterceptor.cpp b/cpp/src/qpid/cluster/OutputInterceptor.cpp
index 4bf03eefa2..1354dab17b 100644
--- a/cpp/src/qpid/cluster/OutputInterceptor.cpp
+++ b/cpp/src/qpid/cluster/OutputInterceptor.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -45,11 +45,12 @@ void OutputInterceptor::send(framing::AMQFrame& f) {
}
void OutputInterceptor::activateOutput() {
- sys::Mutex::ScopedLock l(lock);
- if (parent.isCatchUp())
+ if (parent.isCatchUp()) {
+ sys::Mutex::ScopedLock l(lock);
next->activateOutput();
+ }
else
- sendDoOutput(sendMax, l);
+ sendDoOutput(sendMax);
}
void OutputInterceptor::abort() {
@@ -65,38 +66,29 @@ void OutputInterceptor::giveReadCredit(int32_t credit) {
}
// Called in write thread when the IO layer has no more data to write.
-// We only process IO callbacks in the write thread during catch-up.
-// Normally we run doOutput only on delivery of doOutput requests.
-bool OutputInterceptor::doOutput() {
- parent.doCatchupIoCallbacks();
- return false;
-}
+// We do nothing in the write thread, we run doOutput only on delivery
+// of doOutput requests.
+bool OutputInterceptor::doOutput() { return false; }
-// Send output up to limit, calculate new limit.
+// Send output up to limit, calculate new limit.
void OutputInterceptor::deliverDoOutput(uint32_t limit) {
- sys::Mutex::ScopedLock l(lock);
sentDoOutput = false;
sendMax = limit;
size_t newLimit = limit;
if (parent.isLocal()) {
- size_t buffered = next->getBuffered();
+ size_t buffered = getBuffered();
if (buffered == 0 && sent == sendMax) // Could have sent more, increase the limit.
- newLimit = sendMax*2;
+ newLimit = sendMax*2;
else if (buffered > 0 && sent > 1) // Data left unsent, reduce the limit.
newLimit = (sendMax + sent) / 2;
}
sent = 0;
- while (sent < limit) {
- {
- sys::Mutex::ScopedUnlock u(lock);
- if (!parent.getBrokerConnection()->doOutput()) break;
- }
+ while (sent < limit && parent.getBrokerConnection()->doOutput())
++sent;
- }
- if (sent == limit) sendDoOutput(newLimit, l);
+ if (sent == limit) sendDoOutput(newLimit);
}
-void OutputInterceptor::sendDoOutput(size_t newLimit, const sys::Mutex::ScopedLock&) {
+void OutputInterceptor::sendDoOutput(size_t newLimit) {
if (parent.isLocal() && !sentDoOutput && !closing) {
sentDoOutput = true;
parent.getCluster().getMulticast().mcastControl(
@@ -105,7 +97,6 @@ void OutputInterceptor::sendDoOutput(size_t newLimit, const sys::Mutex::ScopedLo
}
}
-// Called in connection thread when local connection closes.
void OutputInterceptor::closeOutput() {
sys::Mutex::ScopedLock l(lock);
closing = true;
diff --git a/cpp/src/qpid/cluster/OutputInterceptor.h b/cpp/src/qpid/cluster/OutputInterceptor.h
index 3abf5273a0..65bd82a4fc 100644
--- a/cpp/src/qpid/cluster/OutputInterceptor.h
+++ b/cpp/src/qpid/cluster/OutputInterceptor.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -58,13 +58,13 @@ class OutputInterceptor : public sys::ConnectionOutputHandler {
uint32_t getSendMax() const { return sendMax; }
void setSendMax(uint32_t sendMax_) { sendMax=sendMax_; }
-
+
cluster::Connection& parent;
-
+
private:
typedef sys::Mutex::ScopedLock Locker;
- void sendDoOutput(size_t newLimit, const sys::Mutex::ScopedLock&);
+ void sendDoOutput(size_t newLimit);
mutable sys::Mutex lock;
bool closing;
diff --git a/cpp/src/qpid/cluster/SecureConnectionFactory.cpp b/cpp/src/qpid/cluster/SecureConnectionFactory.cpp
index 2672d8360c..6ddef66226 100644
--- a/cpp/src/qpid/cluster/SecureConnectionFactory.cpp
+++ b/cpp/src/qpid/cluster/SecureConnectionFactory.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -48,7 +48,7 @@ SecureConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, cons
if (clusterCodec) {
SecureConnectionPtr sc(new SecureConnection());
clusterCodec->setSecureConnection(sc.get());
- sc->setCodec(codec);
+ sc->setCodec(codec);
return sc.release();
}
return 0;
@@ -63,7 +63,7 @@ SecureConnectionFactory::create(sys::OutputControl& out, const std::string& id,
if (clusterCodec) {
SecureConnectionPtr sc(new SecureConnection());
clusterCodec->setSecureConnection(sc.get());
- sc->setCodec(codec);
+ sc->setCodec(codec);
return sc.release();
}
return 0;
diff --git a/cpp/src/qpid/cluster/UpdateClient.cpp b/cpp/src/qpid/cluster/UpdateClient.cpp
index 2446c12f2b..8f751add9b 100644
--- a/cpp/src/qpid/cluster/UpdateClient.cpp
+++ b/cpp/src/qpid/cluster/UpdateClient.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -26,9 +26,9 @@
#include "qpid/cluster/Decoder.h"
#include "qpid/cluster/ExpiryPolicy.h"
#include "qpid/cluster/UpdateDataExchange.h"
-#include "qpid/client/SessionBase_0_10Access.h"
-#include "qpid/client/ConnectionAccess.h"
-#include "qpid/client/SessionImpl.h"
+#include "qpid/client/SessionBase_0_10Access.h"
+#include "qpid/client/ConnectionAccess.h"
+#include "qpid/client/SessionImpl.h"
#include "qpid/client/ConnectionImpl.h"
#include "qpid/client/Future.h"
#include "qpid/broker/Broker.h"
@@ -45,13 +45,10 @@
#include "qpid/broker/SessionState.h"
#include "qpid/broker/TxOpVisitor.h"
#include "qpid/broker/DtxAck.h"
-#include "qpid/broker/DtxBuffer.h"
-#include "qpid/broker/DtxWorkRecord.h"
#include "qpid/broker/TxAccept.h"
#include "qpid/broker/TxPublish.h"
#include "qpid/broker/RecoveredDequeue.h"
#include "qpid/broker/RecoveredEnqueue.h"
-#include "qpid/broker/StatefulQueueObserver.h"
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/framing/ClusterConnectionMembershipBody.h"
#include "qpid/framing/ClusterConnectionShadowReadyBody.h"
@@ -67,7 +64,6 @@
#include <boost/bind.hpp>
#include <boost/cast.hpp>
#include <algorithm>
-#include <iterator>
#include <sstream>
namespace qpid {
@@ -86,20 +82,11 @@ using namespace framing;
namespace arg=client::arg;
using client::SessionBase_0_10Access;
-// Reserved exchange/queue name for catch-up, avoid clashes with user queues/exchanges.
-const std::string UpdateClient::UPDATE("x-qpid.cluster-update");
-// Name for header used to carry expiration information.
-const std::string UpdateClient::X_QPID_EXPIRATION = "x-qpid.expiration";
-// Headers used to flag headers/properties added by the UpdateClient so they can be
-// removed on the other side.
-const std::string UpdateClient::X_QPID_NO_MESSAGE_PROPS = "x-qpid.no-message-props";
-const std::string UpdateClient::X_QPID_NO_HEADERS = "x-qpid.no-headers";
-
std::ostream& operator<<(std::ostream& o, const UpdateClient& c) {
return o << "cluster(" << c.updaterId << " UPDATER)";
}
-struct ClusterConnectionProxy : public AMQP_AllProxy::ClusterConnection, public framing::FrameHandler
+struct ClusterConnectionProxy : public AMQP_AllProxy::ClusterConnection, public framing::FrameHandler
{
boost::shared_ptr<qpid::client::ConnectionImpl> connection;
@@ -133,7 +120,7 @@ void send(client::AsyncSession& s, const AMQBody& body) {
// TODO aconway 2008-09-24: optimization: update connections/sessions in parallel.
UpdateClient::UpdateClient(const MemberId& updater, const MemberId& updatee, const Url& url,
- broker::Broker& broker, const ClusterMap& m, ExpiryPolicy& expiry_,
+ broker::Broker& broker, const ClusterMap& m, ExpiryPolicy& expiry_,
const Cluster::ConnectionVector& cons, Decoder& decoder_,
const boost::function<void()>& ok,
const boost::function<void(const std::exception&)>& fail,
@@ -147,11 +134,13 @@ UpdateClient::UpdateClient(const MemberId& updater, const MemberId& updatee, con
UpdateClient::~UpdateClient() {}
+// Reserved exchange/queue name for catch-up, avoid clashes with user queues/exchanges.
+const std::string UpdateClient::UPDATE("qpid.cluster-update");
+
void UpdateClient::run() {
try {
connection.open(updateeUrl, connectionSettings);
session = connection.newSession(UPDATE);
- session.sync();
update();
done();
} catch (const std::exception& e) {
@@ -165,13 +154,6 @@ void UpdateClient::update() {
<< " at " << updateeUrl);
Broker& b = updaterBroker;
- if(b.getExpiryPolicy()) {
- QPID_LOG(debug, *this << "Updating updatee with cluster time");
- qpid::sys::AbsTime clusterTime = b.getExpiryPolicy()->getCurrentTime();
- int64_t time = qpid::sys::Duration(qpid::sys::EPOCH, clusterTime);
- ClusterConnectionProxy(session).clock(time);
- }
-
updateManagementSetupState();
b.getExchanges().eachExchange(boost::bind(&UpdateClient::updateExchange, this, _1));
@@ -181,20 +163,16 @@ void UpdateClient::update() {
// longer on their original queue.
session.queueDeclare(arg::queue=UPDATE, arg::autoDelete=true);
session.sync();
-
std::for_each(connections.begin(), connections.end(),
boost::bind(&UpdateClient::updateConnection, this, _1));
-
- // some Queue Observers need session state & msgs synced first, so sync observers now
- b.getQueues().eachQueue(boost::bind(&UpdateClient::updateQueueObservers, this, _1));
+ session.queueDelete(arg::queue=UPDATE);
// Update queue listeners: must come after sessions so consumerNumbering is populated
b.getQueues().eachQueue(boost::bind(&UpdateClient::updateQueueListeners, this, _1));
+ ClusterConnectionProxy(session).expiryId(expiry.getId());
updateLinks();
updateManagementAgent();
- updateDtxManager();
- session.queueDelete(arg::queue=UPDATE);
session.close();
@@ -206,7 +184,7 @@ void UpdateClient::update() {
// NOTE: connection will be closed from the other end, don't close
// it here as that causes a race.
-
+
// TODO aconway 2010-03-15: This sleep avoids the race condition
// described in // https://bugzilla.redhat.com/show_bug.cgi?id=568831.
// It allows the connection to fully close before destroying the
@@ -298,7 +276,7 @@ class MessageUpdater {
framing::SequenceNumber lastPos;
client::AsyncSession session;
ExpiryPolicy& expiry;
-
+
public:
MessageUpdater(const string& q, const client::AsyncSession s, ExpiryPolicy& expiry_) : queue(q), haveLastPos(false), session(s), expiry(expiry_) {
@@ -315,6 +293,7 @@ class MessageUpdater {
}
}
+
void updateQueuedMessage(const broker::QueuedMessage& message) {
// Send the queue position if necessary.
if (!haveLastPos || message.position - lastPos != 1) {
@@ -323,23 +302,10 @@ class MessageUpdater {
}
lastPos = message.position;
- // if the ttl > 0, we need to send the calculated expiration time to the updatee
- const DeliveryProperties* dprops =
- message.payload->getProperties<DeliveryProperties>();
- if (dprops && dprops->getTtl() > 0) {
- bool hadMessageProps =
- message.payload->hasProperties<framing::MessageProperties>();
- const framing::MessageProperties* mprops =
- message.payload->getProperties<framing::MessageProperties>();
- bool hadApplicationHeaders = mprops->hasApplicationHeaders();
- message.payload->insertCustomProperty(UpdateClient::X_QPID_EXPIRATION,
- sys::Duration(sys::EPOCH, message.payload->getExpiration()));
- // If message properties or application headers didn't exist
- // prior to us adding data, we want to remove them on the other side.
- if (!hadMessageProps)
- message.payload->insertCustomProperty(UpdateClient::X_QPID_NO_MESSAGE_PROPS, 0);
- else if (!hadApplicationHeaders)
- message.payload->insertCustomProperty(UpdateClient::X_QPID_NO_HEADERS, 0);
+ // Send the expiry ID if necessary.
+ if (message.payload->getProperties<DeliveryProperties>()->getTtl()) {
+ boost::optional<uint64_t> expiryId = expiry.getId(*message.payload);
+ ClusterConnectionProxy(session).expiryId(expiryId?*expiryId:0);
}
// We can't send a broker::Message via the normal client API,
@@ -352,7 +318,7 @@ class MessageUpdater {
framing::MessageTransferBody transfer(
*message.payload->getFrames().as<framing::MessageTransferBody>());
transfer.setDestination(UpdateClient::UPDATE);
-
+
sb.get()->send(transfer, message.payload->getFrames(),
!message.payload->isContentReleased());
if (message.payload->isContentReleased()){
@@ -360,10 +326,9 @@ class MessageUpdater {
uint16_t maxContentSize = maxFrameSize - AMQFrame::frameOverhead();
bool morecontent = true;
for (uint64_t offset = 0; morecontent; offset += maxContentSize)
- {
+ {
AMQFrame frame((AMQContentBody()));
- morecontent = message.payload->getContentFrame(
- *(message.queue), frame, maxContentSize, offset);
+ morecontent = message.payload->getContentFrame(*(message.queue), frame, maxContentSize, offset);
sb.get()->sendRawFrame(frame);
}
}
@@ -392,8 +357,6 @@ void UpdateClient::updateQueue(client::AsyncSession& s, const boost::shared_ptr<
if (qpid::broker::Fairshare::getState(q->getMessages(), priority, count)) {
ClusterConnectionProxy(s).queueFairshareState(q->getName(), priority, count);
}
-
- ClusterConnectionProxy(s).queueDequeueSincePurgeState(q->getName(), q->getDequeueSincePurge());
}
void UpdateClient::updateExclusiveQueue(const boost::shared_ptr<broker::Queue>& q) {
@@ -409,11 +372,7 @@ void UpdateClient::updateNonExclusiveQueue(const boost::shared_ptr<broker::Queue
}
void UpdateClient::updateBinding(client::AsyncSession& s, const std::string& queue, const QueueBinding& binding) {
- if (binding.exchange.size())
- s.exchangeBind(queue, binding.exchange, binding.key, binding.args);
- //else its the default exchange and there is no need to replicate
- //the binding, the creation of the queue will have done so
- //automatically
+ s.exchangeBind(queue, binding.exchange, binding.key, binding.args);
}
void UpdateClient::updateOutputTask(const sys::OutputTask* task) {
@@ -421,8 +380,8 @@ void UpdateClient::updateOutputTask(const sys::OutputTask* task) {
boost::polymorphic_downcast<const SemanticState::ConsumerImpl*> (task);
SemanticState::ConsumerImpl* ci = const_cast<SemanticState::ConsumerImpl*>(cci);
uint16_t channel = ci->getParent().getSession().getChannel();
- ClusterConnectionProxy(shadowConnection).outputTask(channel, ci->getTag());
- QPID_LOG(debug, *this << " updating output task " << ci->getTag()
+ ClusterConnectionProxy(shadowConnection).outputTask(channel, ci->getName());
+ QPID_LOG(debug, *this << " updating output task " << ci->getName()
<< " channel=" << channel);
}
@@ -430,7 +389,7 @@ void UpdateClient::updateConnection(const boost::intrusive_ptr<Connection>& upda
QPID_LOG(debug, *this << " updating connection " << *updateConnection);
assert(updateConnection->getBrokerConnection());
broker::Connection& bc = *updateConnection->getBrokerConnection();
-
+
// Send the management ID first on the main connection.
std::string mgmtId = updateConnection->getBrokerConnection()->getMgmtId();
ClusterConnectionProxy(session).shadowPrepare(mgmtId);
@@ -467,7 +426,7 @@ void UpdateClient::updateSession(broker::SessionHandler& sh) {
QPID_LOG(debug, *this << " updating session " << ss->getId());
- // Create a client session to update session state.
+ // Create a client session to update session state.
boost::shared_ptr<client::ConnectionImpl> cimpl = client::ConnectionAccess::getImpl(shadowConnection);
boost::shared_ptr<client::SessionImpl> simpl = cimpl->newSession(ss->getId().getName(), ss->getTimeout(), sh.getChannel());
simpl->disableAutoDetach();
@@ -486,19 +445,19 @@ void UpdateClient::updateSession(broker::SessionHandler& sh) {
QPID_LOG(debug, *this << " updating unacknowledged messages.");
broker::DeliveryRecords& drs = ss->getSemanticState().getUnacked();
std::for_each(drs.begin(), drs.end(),
- boost::bind(&UpdateClient::updateUnacked, this, _1, shadowSession));
+ boost::bind(&UpdateClient::updateUnacked, this, _1));
- updateTransactionState(ss->getSemanticState());
+ updateTxState(ss->getSemanticState()); // Tx transaction state.
// Adjust command counter for message in progress, will be sent after state update.
boost::intrusive_ptr<Message> inProgress = ss->getMessageInProgress();
SequenceNumber received = ss->receiverGetReceived().command;
- if (inProgress)
+ if (inProgress)
--received;
// Sync the session to ensure all responses from broker have been processed.
shadowSession.sync();
-
+
// Reset command-sequence state.
proxy.sessionState(
ss->senderGetReplayPoint().command,
@@ -507,8 +466,7 @@ void UpdateClient::updateSession(broker::SessionHandler& sh) {
std::max(received, ss->receiverGetExpected().command),
received,
ss->receiverGetUnknownComplete(),
- ss->receiverGetIncomplete(),
- ss->getSemanticState().getDtxSelected()
+ ss->receiverGetIncomplete()
);
// Send frames for partial message in progress.
@@ -521,13 +479,13 @@ void UpdateClient::updateSession(broker::SessionHandler& sh) {
void UpdateClient::updateConsumer(
const broker::SemanticState::ConsumerImpl::shared_ptr& ci)
{
- QPID_LOG(debug, *this << " updating consumer " << ci->getTag() << " on "
+ QPID_LOG(debug, *this << " updating consumer " << ci->getName() << " on "
<< shadowSession.getId());
using namespace message;
shadowSession.messageSubscribe(
arg::queue = ci->getQueue()->getName(),
- arg::destination = ci->getTag(),
+ arg::destination = ci->getName(),
arg::acceptMode = ci->isAckExpected() ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE,
arg::acquireMode = ci->isAcquire() ? ACQUIRE_MODE_PRE_ACQUIRED : ACQUIRE_MODE_NOT_ACQUIRED,
arg::exclusive = ci->isExclusive(),
@@ -535,32 +493,29 @@ void UpdateClient::updateConsumer(
arg::resumeTtl = ci->getResumeTtl(),
arg::arguments = ci->getArguments()
);
- shadowSession.messageSetFlowMode(ci->getTag(), ci->isWindowing() ? FLOW_MODE_WINDOW : FLOW_MODE_CREDIT);
- shadowSession.messageFlow(ci->getTag(), CREDIT_UNIT_MESSAGE, ci->getMsgCredit());
- shadowSession.messageFlow(ci->getTag(), CREDIT_UNIT_BYTE, ci->getByteCredit());
+ shadowSession.messageSetFlowMode(ci->getName(), ci->isWindowing() ? FLOW_MODE_WINDOW : FLOW_MODE_CREDIT);
+ shadowSession.messageFlow(ci->getName(), CREDIT_UNIT_MESSAGE, ci->getMsgCredit());
+ shadowSession.messageFlow(ci->getName(), CREDIT_UNIT_BYTE, ci->getByteCredit());
ClusterConnectionProxy(shadowSession).consumerState(
- ci->getTag(),
+ ci->getName(),
ci->isBlocked(),
ci->isNotifyEnabled(),
ci->position
);
consumerNumbering.add(ci.get());
- QPID_LOG(debug, *this << " updated consumer " << ci->getTag()
+ QPID_LOG(debug, *this << " updated consumer " << ci->getName()
<< " on " << shadowSession.getId());
}
-
-void UpdateClient::updateUnacked(const broker::DeliveryRecord& dr,
- client::AsyncSession& updateSession)
-{
- if (!dr.isEnded() && dr.isAcquired()) {
- assert(dr.getMessage().payload);
+
+void UpdateClient::updateUnacked(const broker::DeliveryRecord& dr) {
+ if (!dr.isEnded() && dr.isAcquired() && dr.getMessage().payload) {
// If the message is acquired then it is no longer on the
// updatees queue, put it on the update queue for updatee to pick up.
//
- MessageUpdater(UPDATE, updateSession, expiry).updateQueuedMessage(dr.getMessage());
+ MessageUpdater(UPDATE, shadowSession, expiry).updateQueuedMessage(dr.getMessage());
}
- ClusterConnectionProxy(updateSession).deliveryRecord(
+ ClusterConnectionProxy(shadowSession).deliveryRecord(
dr.getQueue()->getName(),
dr.getMessage().position,
dr.getTag(),
@@ -581,12 +536,10 @@ class TxOpUpdater : public broker::TxOpConstVisitor, public MessageUpdater {
TxOpUpdater(UpdateClient& dc, client::AsyncSession s, ExpiryPolicy& expiry)
: MessageUpdater(UpdateClient::UPDATE, s, expiry), parent(dc), session(s), proxy(s) {}
- void operator()(const broker::DtxAck& ack) {
- std::for_each(ack.getPending().begin(), ack.getPending().end(),
- boost::bind(&UpdateClient::updateUnacked, &parent, _1, session));
- proxy.dtxAck();
+ void operator()(const broker::DtxAck& ) {
+ throw InternalErrorException("DTX transactions not currently supported by cluster.");
}
-
+
void operator()(const broker::RecoveredDequeue& rdeq) {
updateMessage(rdeq.getMessage());
proxy.txEnqueue(rdeq.getQueue()->getName());
@@ -601,18 +554,13 @@ class TxOpUpdater : public broker::TxOpConstVisitor, public MessageUpdater {
proxy.txAccept(txAccept.getAcked());
}
- typedef std::list<Queue::shared_ptr> QueueList;
-
- void copy(const QueueList& l, Array& a) {
- for (QueueList::const_iterator i = l.begin(); i!=l.end(); ++i)
- a.push_back(Array::ValuePtr(new Str8Value((*i)->getName())));
- }
-
void operator()(const broker::TxPublish& txPub) {
updateMessage(txPub.getMessage());
- assert(txPub.getQueues().empty() || txPub.getPrepared().empty());
+ typedef std::list<Queue::shared_ptr> QueueList;
+ const QueueList& qlist = txPub.getQueues();
Array qarray(TYPE_CODE_STR8);
- copy(txPub.getQueues().empty() ? txPub.getPrepared() : txPub.getQueues(), qarray);
+ for (QueueList::const_iterator i = qlist.begin(); i != qlist.end(); ++i)
+ qarray.push_back(Array::ValuePtr(new Str8Value((*i)->getName())));
proxy.txPublish(qarray, txPub.delivered);
}
@@ -621,44 +569,18 @@ class TxOpUpdater : public broker::TxOpConstVisitor, public MessageUpdater {
client::AsyncSession session;
ClusterConnectionProxy proxy;
};
-
-void UpdateClient::updateBufferRef(const broker::DtxBuffer::shared_ptr& dtx,bool suspended)
-{
- ClusterConnectionProxy proxy(shadowSession);
- broker::DtxWorkRecord* record =
- updaterBroker.getDtxManager().getWork(dtx->getXid());
- proxy.dtxBufferRef(dtx->getXid(), record->indexOf(dtx), suspended);
-
-}
-
-void UpdateClient::updateTransactionState(broker::SemanticState& s) {
+
+void UpdateClient::updateTxState(broker::SemanticState& s) {
+ QPID_LOG(debug, *this << " updating TX transaction state.");
ClusterConnectionProxy proxy(shadowSession);
proxy.accumulatedAck(s.getAccumulatedAck());
- broker::TxBuffer::shared_ptr tx = s.getTxBuffer();
- broker::DtxBuffer::shared_ptr dtx = s.getDtxBuffer();
- if (dtx) {
- updateBufferRef(dtx, false); // Current transaction.
- } else if (tx) {
+ broker::TxBuffer::shared_ptr txBuffer = s.getTxBuffer();
+ if (txBuffer) {
proxy.txStart();
TxOpUpdater updater(*this, shadowSession, expiry);
- tx->accept(updater);
+ txBuffer->accept(updater);
proxy.txEnd();
}
- for (SemanticState::DtxBufferMap::iterator i = s.getSuspendedXids().begin();
- i != s.getSuspendedXids().end();
- ++i)
- {
- updateBufferRef(i->second, true);
- }
-}
-
-void UpdateClient::updateDtxBuffer(const broker::DtxBuffer::shared_ptr& dtx) {
- ClusterConnectionProxy proxy(session);
- proxy.dtxStart(
- dtx->getXid(), dtx->isEnded(), dtx->isSuspended(), dtx->isFailed(), dtx->isExpired());
- TxOpUpdater updater(*this, session, expiry);
- dtx->accept(updater);
- proxy.dtxEnd();
}
void UpdateClient::updateQueueListeners(const boost::shared_ptr<broker::Queue>& queue) {
@@ -693,35 +615,4 @@ void UpdateClient::updateBridge(const boost::shared_ptr<broker::Bridge>& bridge)
ClusterConnectionProxy(session).config(encode(*bridge));
}
-void UpdateClient::updateQueueObservers(const boost::shared_ptr<broker::Queue>& q)
-{
- q->eachObserver(boost::bind(&UpdateClient::updateObserver, this, q, _1));
-}
-
-void UpdateClient::updateObserver(const boost::shared_ptr<broker::Queue>& q,
- boost::shared_ptr<broker::QueueObserver> o)
-{
- qpid::framing::FieldTable state;
- broker::StatefulQueueObserver *so = dynamic_cast<broker::StatefulQueueObserver *>(o.get());
- if (so) {
- so->getState( state );
- std::string id(so->getId());
- QPID_LOG(debug, *this << " updating queue " << q->getName() << "'s observer " << id);
- ClusterConnectionProxy(session).queueObserverState( q->getName(), id, state );
- }
-}
-
-void UpdateClient::updateDtxManager() {
- broker::DtxManager& dtm = updaterBroker.getDtxManager();
- dtm.each(boost::bind(&UpdateClient::updateDtxWorkRecord, this, _1));
-}
-
-void UpdateClient::updateDtxWorkRecord(const broker::DtxWorkRecord& r) {
- QPID_LOG(debug, *this << " updating DTX transaction: " << r.getXid());
- for (size_t i = 0; i < r.size(); ++i)
- updateDtxBuffer(r[i]);
- ClusterConnectionProxy(session).dtxWorkRecord(
- r.getXid(), r.isPrepared(), r.getTimeout());
-}
-
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/UpdateClient.h b/cpp/src/qpid/cluster/UpdateClient.h
index 481ee357c7..7520bb82cb 100644
--- a/cpp/src/qpid/cluster/UpdateClient.h
+++ b/cpp/src/qpid/cluster/UpdateClient.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -34,7 +34,7 @@
namespace qpid {
-struct Url;
+class Url;
namespace broker {
@@ -42,8 +42,8 @@ class Broker;
class Queue;
class Exchange;
class QueueBindings;
-struct QueueBinding;
-struct QueuedMessage;
+class QueueBinding;
+class QueuedMessage;
class SessionHandler;
class DeliveryRecord;
class SessionState;
@@ -51,8 +51,7 @@ class SemanticState;
class Decoder;
class Link;
class Bridge;
-class QueueObserver;
-class DtxBuffer;
+
} // namespace broker
namespace cluster {
@@ -69,26 +68,21 @@ class ExpiryPolicy;
class UpdateClient : public sys::Runnable {
public:
static const std::string UPDATE; // Name for special update queue and exchange.
- static const std::string X_QPID_EXPIRATION; // Update message expiration
- // Flag to remove props/headers that were added by the UpdateClient
- static const std::string X_QPID_NO_MESSAGE_PROPS;
- static const std::string X_QPID_NO_HEADERS;
-
static client::Connection catchUpConnection();
-
+
UpdateClient(const MemberId& updater, const MemberId& updatee, const Url&,
broker::Broker& donor, const ClusterMap& map, ExpiryPolicy& expiry,
const std::vector<boost::intrusive_ptr<Connection> >&, Decoder&,
const boost::function<void()>& done,
const boost::function<void(const std::exception&)>& fail,
- const client::ConnectionSettings&
+ const client::ConnectionSettings&
);
~UpdateClient();
void update();
void run(); // Will delete this when finished.
- void updateUnacked(const broker::DeliveryRecord&, client::AsyncSession&);
+ void updateUnacked(const broker::DeliveryRecord&);
private:
void updateQueue(client::AsyncSession&, const boost::shared_ptr<broker::Queue>&);
@@ -100,8 +94,7 @@ class UpdateClient : public sys::Runnable {
void updateBinding(client::AsyncSession&, const std::string& queue, const broker::QueueBinding& binding);
void updateConnection(const boost::intrusive_ptr<Connection>& connection);
void updateSession(broker::SessionHandler& s);
- void updateBufferRef(const broker::DtxBuffer::shared_ptr& dtx, bool suspended);
- void updateTransactionState(broker::SemanticState& s);
+ void updateTxState(broker::SemanticState& s);
void updateOutputTask(const sys::OutputTask* task);
void updateConsumer(const broker::SemanticState::ConsumerImpl::shared_ptr&);
void updateQueueListeners(const boost::shared_ptr<broker::Queue>&);
@@ -111,11 +104,6 @@ class UpdateClient : public sys::Runnable {
void updateLinks();
void updateLink(const boost::shared_ptr<broker::Link>&);
void updateBridge(const boost::shared_ptr<broker::Bridge>&);
- void updateQueueObservers(const boost::shared_ptr<broker::Queue>&);
- void updateObserver(const boost::shared_ptr<broker::Queue>&, boost::shared_ptr<broker::QueueObserver>);
- void updateDtxManager();
- void updateDtxBuffer(const boost::shared_ptr<broker::DtxBuffer>& );
- void updateDtxWorkRecord(const broker::DtxWorkRecord&);
Numbering<broker::SemanticState::ConsumerImpl*> consumerNumbering;
diff --git a/cpp/src/qpid/cluster/UpdateDataExchange.cpp b/cpp/src/qpid/cluster/UpdateDataExchange.cpp
index e5cd82e3d3..2a079b8881 100644
--- a/cpp/src/qpid/cluster/UpdateDataExchange.cpp
+++ b/cpp/src/qpid/cluster/UpdateDataExchange.cpp
@@ -36,8 +36,13 @@ const std::string UpdateDataExchange::MANAGEMENT_AGENTS_KEY("management-agents")
const std::string UpdateDataExchange::MANAGEMENT_SCHEMAS_KEY("management-schemas");
const std::string UpdateDataExchange::MANAGEMENT_DELETED_OBJECTS_KEY("management-deleted-objects");
+std::ostream& operator<<(std::ostream& o, const UpdateDataExchange& c) {
+ return o << "cluster(" << c.clusterId << " UPDATER)";
+}
+
UpdateDataExchange::UpdateDataExchange(Cluster& cluster) :
- Exchange(EXCHANGE_NAME, &cluster)
+ Exchange(EXCHANGE_NAME, &cluster),
+ clusterId(cluster.getId())
{}
void UpdateDataExchange::route(broker::Deliverable& msg, const std::string& routingKey,
@@ -57,9 +62,11 @@ void UpdateDataExchange::updateManagementAgent(management::ManagementAgent* agen
framing::Buffer buf1(const_cast<char*>(managementAgents.data()), managementAgents.size());
agent->importAgents(buf1);
+ QPID_LOG(debug, *this << " updated management agents.");
framing::Buffer buf2(const_cast<char*>(managementSchemas.data()), managementSchemas.size());
agent->importSchemas(buf2);
+ QPID_LOG(debug, *this << " updated management schemas.");
using amqp_0_10::ListCodec;
using types::Variant;
@@ -71,6 +78,7 @@ void UpdateDataExchange::updateManagementAgent(management::ManagementAgent* agen
new management::ManagementAgent::DeletedObject(*i)));
}
agent->importDeletedObjects(objects);
+ QPID_LOG(debug, *this << " updated management deleted objects.");
}
diff --git a/cpp/src/qpid/cluster/UpdateDataExchange.h b/cpp/src/qpid/cluster/UpdateDataExchange.h
index d2f6c35ad0..8c493e400a 100644
--- a/cpp/src/qpid/cluster/UpdateDataExchange.h
+++ b/cpp/src/qpid/cluster/UpdateDataExchange.h
@@ -74,9 +74,11 @@ class UpdateDataExchange : public broker::Exchange
void updateManagementAgent(management::ManagementAgent* agent);
private:
+ MemberId clusterId;
std::string managementAgents;
std::string managementSchemas;
std::string managementDeletedObjects;
+ friend std::ostream& operator<<(std::ostream&, const UpdateDataExchange&);
};
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/UpdateExchange.cpp b/cpp/src/qpid/cluster/UpdateExchange.cpp
index cb1376004e..11937f296f 100644
--- a/cpp/src/qpid/cluster/UpdateExchange.cpp
+++ b/cpp/src/qpid/cluster/UpdateExchange.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -19,7 +19,6 @@
*
*/
#include "qpid/framing/MessageTransferBody.h"
-#include "qpid/framing/FieldTable.h"
#include "qpid/broker/Message.h"
#include "UpdateExchange.h"
@@ -28,8 +27,6 @@ namespace cluster {
using framing::MessageTransferBody;
using framing::DeliveryProperties;
-using framing::MessageProperties;
-using framing::FieldTable;
UpdateExchange::UpdateExchange(management::Manageable* parent)
: broker::Exchange(UpdateClient::UPDATE, parent),
@@ -37,7 +34,6 @@ UpdateExchange::UpdateExchange(management::Manageable* parent)
void UpdateExchange::setProperties(const boost::intrusive_ptr<broker::Message>& msg) {
- // Copy exchange name to destination property.
MessageTransferBody* transfer = msg->getMethod<MessageTransferBody>();
assert(transfer);
const DeliveryProperties* props = msg->getProperties<DeliveryProperties>();
@@ -46,23 +42,6 @@ void UpdateExchange::setProperties(const boost::intrusive_ptr<broker::Message>&
transfer->setDestination(props->getExchange());
else
transfer->clearDestinationFlag();
-
- // Copy expiration from x-property if present.
- if (msg->hasProperties<MessageProperties>()) {
- const MessageProperties* mprops = msg->getProperties<MessageProperties>();
- if (mprops->hasApplicationHeaders()) {
- const FieldTable& headers = mprops->getApplicationHeaders();
- if (headers.isSet(UpdateClient::X_QPID_EXPIRATION)) {
- msg->setExpiration(
- sys::AbsTime(sys::EPOCH, headers.getAsInt64(UpdateClient::X_QPID_EXPIRATION)));
- msg->removeCustomProperty(UpdateClient::X_QPID_EXPIRATION);
- // Erase props/headers that were added by the UpdateClient
- if (headers.isSet(UpdateClient::X_QPID_NO_MESSAGE_PROPS))
- msg->eraseProperties<MessageProperties>();
- else if (headers.isSet(UpdateClient::X_QPID_NO_HEADERS))
- msg->clearApplicationHeadersFlag();
- }
- }
- }
}
+
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/UpdateReceiver.h b/cpp/src/qpid/cluster/UpdateReceiver.h
index 81ee3a5ffe..7e8ce47662 100644
--- a/cpp/src/qpid/cluster/UpdateReceiver.h
+++ b/cpp/src/qpid/cluster/UpdateReceiver.h
@@ -39,20 +39,6 @@ class UpdateReceiver {
/** Management-id for the next shadow connection */
std::string nextShadowMgmtId;
-
- /** Record the position of a DtxBuffer in the DtxManager (xid + index)
- * and the association with a session, either suspended or current.
- */
- struct DtxBufferRef {
- std::string xid;
- uint32_t index; // Index in WorkRecord in DtxManager
- bool suspended; // Is this a suspended or current transaction?
- broker::SemanticState* semanticState; // Associated session
- DtxBufferRef(const std::string& x, uint32_t i, bool s, broker::SemanticState* ss)
- : xid(x), index(i), suspended(s), semanticState(ss) {}
- };
- typedef std::vector<DtxBufferRef> DtxBuffers;
- DtxBuffers dtxBuffers;
};
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/types.h b/cpp/src/qpid/cluster/types.h
index bfb4fd5b9e..0795e5e77a 100644
--- a/cpp/src/qpid/cluster/types.h
+++ b/cpp/src/qpid/cluster/types.h
@@ -24,7 +24,6 @@
#include "config.h"
#include "qpid/Url.h"
-#include "qpid/RefCounted.h"
#include "qpid/sys/IntegerTypes.h"
#include <boost/intrusive_ptr.hpp>
#include <utility>
diff --git a/cpp/src/qpid/console/SessionManager.cpp b/cpp/src/qpid/console/SessionManager.cpp
index 910ae22be8..80c5959417 100644
--- a/cpp/src/qpid/console/SessionManager.cpp
+++ b/cpp/src/qpid/console/SessionManager.cpp
@@ -362,11 +362,12 @@ void SessionManager::handleCommandComplete(Broker* broker, Buffer& inBuffer, uin
void SessionManager::handleClassInd(Broker* broker, Buffer& inBuffer, uint32_t)
{
+ uint8_t kind;
string packageName;
string className;
uint8_t hash[16];
- /*kind*/ (void) inBuffer.getOctet();
+ kind = inBuffer.getOctet();
inBuffer.getShortString(packageName);
inBuffer.getShortString(className);
inBuffer.getBin128(hash);
diff --git a/cpp/src/qpid/framing/AMQBody.h b/cpp/src/qpid/framing/AMQBody.h
index 56d1d250c1..60ac2d3b7e 100644
--- a/cpp/src/qpid/framing/AMQBody.h
+++ b/cpp/src/qpid/framing/AMQBody.h
@@ -46,7 +46,7 @@ struct AMQBodyConstVisitor {
virtual void visit(const AMQMethodBody&) = 0;
};
-class QPID_COMMON_CLASS_EXTERN AMQBody : public RefCounted {
+class AMQBody : public RefCounted {
public:
AMQBody() {}
QPID_COMMON_EXTERN virtual ~AMQBody();
diff --git a/cpp/src/qpid/framing/AMQContentBody.h b/cpp/src/qpid/framing/AMQContentBody.h
index e25451e354..69813b221c 100644
--- a/cpp/src/qpid/framing/AMQContentBody.h
+++ b/cpp/src/qpid/framing/AMQContentBody.h
@@ -29,7 +29,7 @@
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN AMQContentBody : public AMQBody
+class AMQContentBody : public AMQBody
{
string data;
@@ -37,15 +37,15 @@ public:
QPID_COMMON_EXTERN AMQContentBody();
QPID_COMMON_EXTERN AMQContentBody(const string& data);
inline virtual ~AMQContentBody(){}
- inline uint8_t type() const { return CONTENT_BODY; };
- inline const string& getData() const { return data; }
- inline string& getData() { return data; }
+ QPID_COMMON_EXTERN inline uint8_t type() const { return CONTENT_BODY; };
+ QPID_COMMON_EXTERN inline const string& getData() const { return data; }
+ QPID_COMMON_EXTERN inline string& getData() { return data; }
QPID_COMMON_EXTERN uint32_t encodedSize() const;
QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
QPID_COMMON_EXTERN void decode(Buffer& buffer, uint32_t size);
QPID_COMMON_EXTERN void print(std::ostream& out) const;
- void accept(AMQBodyConstVisitor& v) const { v.visit(*this); }
- boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); }
+ QPID_COMMON_EXTERN void accept(AMQBodyConstVisitor& v) const { v.visit(*this); }
+ QPID_COMMON_EXTERN boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); }
};
}
diff --git a/cpp/src/qpid/framing/AMQFrame.cpp b/cpp/src/qpid/framing/AMQFrame.cpp
index 5b9673f0d0..cd60cd971f 100644
--- a/cpp/src/qpid/framing/AMQFrame.cpp
+++ b/cpp/src/qpid/framing/AMQFrame.cpp
@@ -139,11 +139,6 @@ bool AMQFrame::decode(Buffer& buffer)
return true;
}
-void AMQFrame::cloneBody()
-{
- body = body->clone();
-}
-
std::ostream& operator<<(std::ostream& out, const AMQFrame& f)
{
return
diff --git a/cpp/src/qpid/framing/AMQFrame.h b/cpp/src/qpid/framing/AMQFrame.h
index 4f6faf4199..d7b04f0f65 100644
--- a/cpp/src/qpid/framing/AMQFrame.h
+++ b/cpp/src/qpid/framing/AMQFrame.h
@@ -33,7 +33,7 @@
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN AMQFrame : public AMQDataBlock
+class AMQFrame : public AMQDataBlock
{
public:
QPID_COMMON_EXTERN AMQFrame(const boost::intrusive_ptr<AMQBody>& b=0);
@@ -59,11 +59,6 @@ class QPID_COMMON_CLASS_EXTERN AMQFrame : public AMQDataBlock
return boost::polymorphic_downcast<const T*>(getBody());
}
- /**
- * Take a deep copy of the body currently referenced
- */
- QPID_COMMON_EXTERN void cloneBody();
-
QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
QPID_COMMON_EXTERN bool decode(Buffer& buffer);
QPID_COMMON_EXTERN uint32_t encodedSize() const;
diff --git a/cpp/src/qpid/framing/AMQHeaderBody.h b/cpp/src/qpid/framing/AMQHeaderBody.h
index 452154eb5c..8d96e35720 100644
--- a/cpp/src/qpid/framing/AMQHeaderBody.h
+++ b/cpp/src/qpid/framing/AMQHeaderBody.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -35,7 +35,7 @@
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN AMQHeaderBody : public AMQBody
+class AMQHeaderBody : public AMQBody
{
template <class T> struct OptProps { boost::optional<T> props; };
template <class Base, class T>
@@ -58,7 +58,7 @@ class QPID_COMMON_CLASS_EXTERN AMQHeaderBody : public AMQBody
}
else
return Base::decode(buffer, size, type);
- }
+ }
void print(std::ostream& out) const {
const boost::optional<T>& p=this->OptProps<T>::props;
if (p) out << *p;
@@ -77,7 +77,7 @@ class QPID_COMMON_CLASS_EXTERN AMQHeaderBody : public AMQBody
typedef PropSet<PropSet<Empty, DeliveryProperties>, MessageProperties> Properties;
Properties properties;
-
+
public:
inline uint8_t type() const { return HEADER_BODY; }
@@ -99,10 +99,6 @@ public:
return properties.OptProps<T>::props.get_ptr();
}
- template <class T> void erase() {
- properties.OptProps<T>::props.reset();
- }
-
boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); }
};
diff --git a/cpp/src/qpid/framing/AMQHeartbeatBody.h b/cpp/src/qpid/framing/AMQHeartbeatBody.h
index 19ac2be013..9b1fe8a4c1 100644
--- a/cpp/src/qpid/framing/AMQHeartbeatBody.h
+++ b/cpp/src/qpid/framing/AMQHeartbeatBody.h
@@ -29,7 +29,7 @@
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN AMQHeartbeatBody : public AMQBody
+class AMQHeartbeatBody : public AMQBody
{
public:
QPID_COMMON_EXTERN virtual ~AMQHeartbeatBody();
diff --git a/cpp/src/qpid/framing/FieldTable.cpp b/cpp/src/qpid/framing/FieldTable.cpp
index f80d2f9fb1..023e4af819 100644
--- a/cpp/src/qpid/framing/FieldTable.cpp
+++ b/cpp/src/qpid/framing/FieldTable.cpp
@@ -129,7 +129,7 @@ FieldTable::ValuePtr FieldTable::get(const std::string& name) const
namespace {
template <class T> T default_value() { return T(); }
template <> int default_value<int>() { return 0; }
- //template <> uint64_t default_value<uint64_t>() { return 0; }
+ template <> uint64_t default_value<uint64_t>() { return 0; }
}
template <class T>
@@ -198,12 +198,10 @@ void FieldTable::encode(Buffer& buffer) const {
void FieldTable::decode(Buffer& buffer){
clear();
- if (buffer.available() < 4)
- throw IllegalArgumentException(QPID_MSG("Not enough data for field table."));
uint32_t len = buffer.getLong();
if (len) {
uint32_t available = buffer.available();
- if ((available < len) || (available < 4))
+ if (available < len)
throw IllegalArgumentException(QPID_MSG("Not enough data for field table."));
uint32_t count = buffer.getLong();
uint32_t leftover = available - len;
diff --git a/cpp/src/qpid/framing/List.cpp b/cpp/src/qpid/framing/List.cpp
index d7ea172bac..963ebc206b 100644
--- a/cpp/src/qpid/framing/List.cpp
+++ b/cpp/src/qpid/framing/List.cpp
@@ -49,9 +49,6 @@ void List::encode(Buffer& buffer) const
void List::decode(Buffer& buffer)
{
values.clear();
- if (buffer.available() < 4)
- throw IllegalArgumentException(QPID_MSG("Not enough data for list, expected at least "
- " 4 bytes but only " << buffer.available() << " available"));
uint32_t size = buffer.getLong();
uint32_t available = buffer.available();
if (available < size) {
@@ -59,9 +56,6 @@ void List::decode(Buffer& buffer)
<< size << " bytes but only " << available << " available"));
}
if (size) {
- if (buffer.available() < 4)
- throw IllegalArgumentException(QPID_MSG("Not enough data for list, expected at least "
- " 4 bytes but only " << buffer.available() << " available"));
uint32_t count = buffer.getLong();
for (uint32_t i = 0; i < count; i++) {
ValuePtr value(new FieldValue);
diff --git a/cpp/src/qpid/framing/MethodBodyFactory.h b/cpp/src/qpid/framing/MethodBodyFactory.h
index 88bc444795..607ec9d959 100644
--- a/cpp/src/qpid/framing/MethodBodyFactory.h
+++ b/cpp/src/qpid/framing/MethodBodyFactory.h
@@ -22,7 +22,6 @@
*
*/
#include "qpid/framing/amqp_types.h"
-#include "qpid/framing/AMQBody.h"
#include <boost/intrusive_ptr.hpp>
namespace qpid {
diff --git a/cpp/src/qpid/framing/SendContent.h b/cpp/src/qpid/framing/SendContent.h
index 1c464b9c8b..745c948c9e 100644
--- a/cpp/src/qpid/framing/SendContent.h
+++ b/cpp/src/qpid/framing/SendContent.h
@@ -37,7 +37,7 @@ namespace framing {
*/
class SendContent
{
- FrameHandler& handler;
+ mutable FrameHandler& handler;
const uint16_t maxFrameSize;
uint expectedFrameCount;
uint frameCount;
diff --git a/cpp/src/qpid/framing/TransferContent.h b/cpp/src/qpid/framing/TransferContent.h
index 9a698a1823..5fe1a513a9 100644
--- a/cpp/src/qpid/framing/TransferContent.h
+++ b/cpp/src/qpid/framing/TransferContent.h
@@ -32,7 +32,7 @@ namespace qpid {
namespace framing {
/** Message content */
-class QPID_COMMON_CLASS_EXTERN TransferContent : public MethodContent
+class TransferContent : public MethodContent
{
AMQHeaderBody header;
std::string data;
diff --git a/cpp/src/qpid/framing/Uuid.cpp b/cpp/src/qpid/framing/Uuid.cpp
index b3d1e2e1e4..945c0a4d24 100644
--- a/cpp/src/qpid/framing/Uuid.cpp
+++ b/cpp/src/qpid/framing/Uuid.cpp
@@ -59,9 +59,7 @@ void Uuid::clear() {
// Force int 0/!0 to false/true; avoids compile warnings.
bool Uuid::isNull() const {
- // This const cast is for Solaris which has a
- // uuid_is_null that takes a non const argument
- return !!uuid_is_null(const_cast<uint8_t*>(data()));
+ return !!uuid_is_null(data());
}
void Uuid::encode(Buffer& buf) const {
diff --git a/cpp/src/qpid/log/Logger.cpp b/cpp/src/qpid/log/Logger.cpp
index 1600822142..2217cdddbd 100644
--- a/cpp/src/qpid/log/Logger.cpp
+++ b/cpp/src/qpid/log/Logger.cpp
@@ -22,7 +22,6 @@
#include "qpid/memory.h"
#include "qpid/sys/Thread.h"
#include "qpid/sys/Time.h"
-#include "qpid/DisableExceptionLogging.h"
#include <boost/pool/detail/singleton.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
@@ -49,16 +48,11 @@ Logger& Logger::instance() {
}
Logger::Logger() : flags(0) {
- // Disable automatic logging in Exception constructors to avoid
- // re-entrant use of logger singleton if there is an error in
- // option parsing.
- DisableExceptionLogging del;
-
// Initialize myself from env variables so all programs
// (e.g. tests) can use logging even if they don't parse
// command line args.
Options opts("");
- opts.parse(0, 0);
+ opts.parse(0, 0);
configure(opts);
}
@@ -79,12 +73,8 @@ void Logger::log(const Statement& s, const std::string& msg) {
std::ostringstream os;
if (!prefix.empty())
os << prefix << ": ";
- if (flags&TIME) {
- if (flags&HIRES)
- qpid::sys::outputHiresNow(os);
- else
- qpid::sys::outputFormattedNow(os);
- }
+ if (flags&TIME)
+ qpid::sys::outputFormattedNow(os);
if (flags&LEVEL)
os << LevelTraits::name(s.level) << " ";
if (flags&THREAD)
@@ -133,8 +123,7 @@ int Logger::format(const Options& opts) {
bitIf(opts.time, TIME) |
bitIf(opts.source, (FILE|LINE)) |
bitIf(opts.function, FUNCTION) |
- bitIf(opts.thread, THREAD) |
- bitIf(opts.hiresTs, HIRES);
+ bitIf(opts.thread, THREAD);
format(flags);
return flags;
}
@@ -151,7 +140,7 @@ void Logger::configure(const Options& opts) {
Options o(opts);
if (o.trace)
o.selectors.push_back("trace+");
- format(o);
+ format(o);
select(Selector(o));
setPrefix(opts.prefix);
options.sinkOptions->setup(this);
diff --git a/cpp/src/qpid/log/Options.cpp b/cpp/src/qpid/log/Options.cpp
index 0001d00bdf..24ef413cbc 100644
--- a/cpp/src/qpid/log/Options.cpp
+++ b/cpp/src/qpid/log/Options.cpp
@@ -38,7 +38,6 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
thread(false),
source(false),
function(false),
- hiresTs(false),
trace(false),
sinkOptions (SinkOptions::create(argv0_))
{
@@ -66,7 +65,6 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
("log-source", optValue(source,"yes|no"), "Include source file:line in log messages")
("log-thread", optValue(thread,"yes|no"), "Include thread ID in log messages")
("log-function", optValue(function,"yes|no"), "Include function signature in log messages")
- ("log-hires-timestamp", optValue(hiresTs,"yes|no"), "Use unformatted hi-res timestamp in log messages")
("log-prefix", optValue(prefix,"STRING"), "Prefix to append to all log messages")
;
add(*sinkOptions);
@@ -82,7 +80,6 @@ Options::Options(const Options &o) :
thread(o.thread),
source(o.source),
function(o.function),
- hiresTs(o.hiresTs),
trace(o.trace),
prefix(o.prefix),
sinkOptions (SinkOptions::create(o.argv0))
@@ -100,7 +97,6 @@ Options& Options::operator=(const Options& x) {
thread = x.thread;
source = x.source;
function = x.function;
- hiresTs = x.hiresTs;
trace = x.trace;
prefix = x.prefix;
*sinkOptions = *x.sinkOptions;
diff --git a/cpp/src/qpid/log/Statement.cpp b/cpp/src/qpid/log/Statement.cpp
index 7dfdf08703..6a32b50096 100644
--- a/cpp/src/qpid/log/Statement.cpp
+++ b/cpp/src/qpid/log/Statement.cpp
@@ -27,6 +27,8 @@ namespace qpid {
namespace log {
namespace {
+using namespace std;
+
struct NonPrint { bool operator()(unsigned char c) { return !isprint(c) && !isspace(c); } };
const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
@@ -37,7 +39,7 @@ std::string quote(const std::string& str) {
if (n==0) return str;
std::string ret;
ret.reserve(str.size()+2*n); // Avoid extra allocations.
- for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) {
+ for (string::const_iterator i = str.begin(); i != str.end(); ++i) {
if (nonPrint(*i)) {
ret.push_back('\\');
ret.push_back('x');
@@ -48,6 +50,7 @@ std::string quote(const std::string& str) {
}
return ret;
}
+
}
void Statement::log(const std::string& message) {
diff --git a/cpp/src/qpid/log/posix/SinkOptions.cpp b/cpp/src/qpid/log/posix/SinkOptions.cpp
index ffa7633e3b..292e9147f6 100644
--- a/cpp/src/qpid/log/posix/SinkOptions.cpp
+++ b/cpp/src/qpid/log/posix/SinkOptions.cpp
@@ -180,7 +180,7 @@ qpid::log::SinkOptions& SinkOptions::operator=(const qpid::log::SinkOptions& rhs
}
void SinkOptions::detached(void) {
- if (logToStderr && !logToStdout && !logToSyslog && logFile.empty()) {
+ if (logToStderr && !logToStdout && !logToSyslog) {
logToStderr = false;
logToSyslog = true;
}
diff --git a/cpp/src/qpid/log/windows/SinkOptions.cpp b/cpp/src/qpid/log/windows/SinkOptions.cpp
index 0c74bea64e..28f4b267e0 100644
--- a/cpp/src/qpid/log/windows/SinkOptions.cpp
+++ b/cpp/src/qpid/log/windows/SinkOptions.cpp
@@ -53,7 +53,7 @@ static int eventTypes[qpid::log::LevelTraits::COUNT] = {
class EventLogOutput : public qpid::log::Logger::Output {
public:
- EventLogOutput(const std::string& /*sourceName*/) : logHandle(0)
+ EventLogOutput(const std::string& sourceName) : logHandle(0)
{
logHandle = OpenEventLog(0, "Application");
}
@@ -83,7 +83,7 @@ private:
HANDLE logHandle;
};
-SinkOptions::SinkOptions(const std::string& /*argv0*/)
+SinkOptions::SinkOptions(const std::string& argv0)
: qpid::log::SinkOptions(),
logToStderr(true),
logToStdout(false),
diff --git a/cpp/src/qpid/log/windows/SinkOptions.h b/cpp/src/qpid/log/windows/SinkOptions.h
index f270c504a2..605822fd46 100644
--- a/cpp/src/qpid/log/windows/SinkOptions.h
+++ b/cpp/src/qpid/log/windows/SinkOptions.h
@@ -26,7 +26,7 @@ namespace qpid {
namespace log {
namespace windows {
-struct QPID_COMMON_CLASS_EXTERN SinkOptions : public qpid::log::SinkOptions {
+struct SinkOptions : public qpid::log::SinkOptions {
QPID_COMMON_EXTERN SinkOptions(const std::string& argv0);
virtual ~SinkOptions() {}
diff --git a/cpp/src/qpid/management/ManagementAgent.cpp b/cpp/src/qpid/management/ManagementAgent.cpp
index 5799a1adca..23c999a98a 100644
--- a/cpp/src/qpid/management/ManagementAgent.cpp
+++ b/cpp/src/qpid/management/ManagementAgent.cpp
@@ -31,7 +31,6 @@
#include <qpid/broker/Message.h>
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/sys/Time.h"
-#include "qpid/sys/Thread.h"
#include "qpid/broker/ConnectionState.h"
#include "qpid/broker/AclModule.h"
#include "qpid/types/Variant.h"
@@ -75,18 +74,6 @@ namespace {
}
return n2;
}
-
-struct ScopedManagementContext
-{
- ScopedManagementContext(const qpid::broker::ConnectionState* context)
- {
- setManagementExecutionContext(context);
- }
- ~ScopedManagementContext()
- {
- setManagementExecutionContext(0);
- }
-};
}
@@ -548,7 +535,6 @@ void ManagementAgent::sendBufferLH(Buffer& buf,
dp->setRoutingKey(routingKey);
msg->getFrames().append(content);
- msg->setIsManagementMessage(true);
{
sys::Mutex::ScopedUnlock u(userLock);
@@ -614,7 +600,7 @@ void ManagementAgent::sendBufferLH(const string& data,
props->setAppId("qmf2");
for (i = headers.begin(); i != headers.end(); ++i) {
- msg->insertCustomProperty(i->first, i->second.asString());
+ msg->getOrInsertHeaders().setString(i->first, i->second.asString());
}
DeliveryProperties* dp =
@@ -622,10 +608,9 @@ void ManagementAgent::sendBufferLH(const string& data,
dp->setRoutingKey(routingKey);
if (ttl_msec) {
dp->setTtl(ttl_msec);
- msg->computeExpiration(broker->getExpiryPolicy());
+ msg->setTimestamp(broker->getExpiryPolicy());
}
msg->getFrames().append(content);
- msg->setIsManagementMessage(true);
{
sys::Mutex::ScopedUnlock u(userLock);
@@ -2252,7 +2237,6 @@ void ManagementAgent::dispatchAgentCommandLH(Message& msg, bool viaLocal)
uint32_t bufferLen = inBuffer.getPosition();
inBuffer.reset();
- ScopedManagementContext context((const qpid::broker::ConnectionState*) msg.getPublisher());
const framing::FieldTable *headers = msg.getApplicationHeaders();
if (headers && msg.getAppId() == "qmf2")
{
@@ -2756,14 +2740,200 @@ void ManagementAgent::debugSnapshot(const char* title) {
title << ": new objects" << dumpVector(newManagementObjects));
}
-
Variant::Map ManagementAgent::toMap(const FieldTable& from)
{
Variant::Map map;
- qpid::amqp_0_10::translate(from, map);
+
+ for (FieldTable::const_iterator iter = from.begin(); iter != from.end(); iter++) {
+ const string& key(iter->first);
+ const FieldTable::ValuePtr& val(iter->second);
+
+ map[key] = toVariant(val);
+ }
+
return map;
}
+Variant::List ManagementAgent::toList(const List& from)
+{
+ Variant::List _list;
+
+ for (List::const_iterator iter = from.begin(); iter != from.end(); iter++) {
+ const List::ValuePtr& val(*iter);
+
+ _list.push_back(toVariant(val));
+ }
+
+ return _list;
+}
+
+qpid::framing::FieldTable ManagementAgent::fromMap(const Variant::Map& from)
+{
+ qpid::framing::FieldTable ft;
+
+ for (Variant::Map::const_iterator iter = from.begin();
+ iter != from.end();
+ iter++) {
+ const string& key(iter->first);
+ const Variant& val(iter->second);
+
+ ft.set(key, toFieldValue(val));
+ }
+
+ return ft;
+}
+
+
+List ManagementAgent::fromList(const Variant::List& from)
+{
+ List fa;
+
+ for (Variant::List::const_iterator iter = from.begin();
+ iter != from.end();
+ iter++) {
+ const Variant& val(*iter);
+
+ fa.push_back(toFieldValue(val));
+ }
+
+ return fa;
+}
+
+
+boost::shared_ptr<FieldValue> ManagementAgent::toFieldValue(const Variant& in)
+{
+
+ switch(in.getType()) {
+
+ case types::VAR_VOID: return boost::shared_ptr<FieldValue>(new VoidValue());
+ case types::VAR_BOOL: return boost::shared_ptr<FieldValue>(new BoolValue(in.asBool()));
+ case types::VAR_UINT8: return boost::shared_ptr<FieldValue>(new Unsigned8Value(in.asUint8()));
+ case types::VAR_UINT16: return boost::shared_ptr<FieldValue>(new Unsigned16Value(in.asUint16()));
+ case types::VAR_UINT32: return boost::shared_ptr<FieldValue>(new Unsigned32Value(in.asUint32()));
+ case types::VAR_UINT64: return boost::shared_ptr<FieldValue>(new Unsigned64Value(in.asUint64()));
+ case types::VAR_INT8: return boost::shared_ptr<FieldValue>(new Integer8Value(in.asInt8()));
+ case types::VAR_INT16: return boost::shared_ptr<FieldValue>(new Integer16Value(in.asInt16()));
+ case types::VAR_INT32: return boost::shared_ptr<FieldValue>(new Integer32Value(in.asInt32()));
+ case types::VAR_INT64: return boost::shared_ptr<FieldValue>(new Integer64Value(in.asInt64()));
+ case types::VAR_FLOAT: return boost::shared_ptr<FieldValue>(new FloatValue(in.asFloat()));
+ case types::VAR_DOUBLE: return boost::shared_ptr<FieldValue>(new DoubleValue(in.asDouble()));
+ case types::VAR_STRING: return boost::shared_ptr<FieldValue>(new Str16Value(in.asString()));
+ case types::VAR_UUID: return boost::shared_ptr<FieldValue>(new UuidValue(in.asUuid().data()));
+ case types::VAR_MAP: return boost::shared_ptr<FieldValue>(new FieldTableValue(ManagementAgent::fromMap(in.asMap())));
+ case types::VAR_LIST: return boost::shared_ptr<FieldValue>(new ListValue(ManagementAgent::fromList(in.asList())));
+ }
+
+ QPID_LOG(error, "Unknown Variant type - not converted: [" << in.getType() << "]");
+ return boost::shared_ptr<FieldValue>(new VoidValue());
+}
+
+// stolen from qpid/client/amqp0_10/Codecs.cpp - TODO: make Codecs public, and remove this dup.
+Variant ManagementAgent::toVariant(const boost::shared_ptr<FieldValue>& in)
+{
+ const string iso885915("iso-8859-15");
+ const string utf8("utf8");
+ const string utf16("utf16");
+ //const string binary("binary");
+ const string amqp0_10_binary("amqp0-10:binary");
+ //const string amqp0_10_bit("amqp0-10:bit");
+ const string amqp0_10_datetime("amqp0-10:datetime");
+ const string amqp0_10_struct("amqp0-10:struct");
+ Variant out;
+
+ //based on AMQP 0-10 typecode, pick most appropriate variant type
+ switch (in->getType()) {
+ //Fixed Width types:
+ case 0x00: //bin8
+ case 0x01: out.setEncoding(amqp0_10_binary); // int8
+ case 0x02: out = in->getIntegerValue<int8_t, 1>(); break; //uint8
+ case 0x03: out = in->getIntegerValue<uint8_t, 1>(); break; //
+ // case 0x04: break; //TODO: iso-8859-15 char // char
+ case 0x08: out = static_cast<bool>(in->getIntegerValue<uint8_t, 1>()); break; // bool int8
+
+ case 0x10: out.setEncoding(amqp0_10_binary); // bin16
+ case 0x11: out = in->getIntegerValue<int16_t, 2>(); break; // int16
+ case 0x12: out = in->getIntegerValue<uint16_t, 2>(); break; //uint16
+
+ case 0x20: out.setEncoding(amqp0_10_binary); // bin32
+ case 0x21: out = in->getIntegerValue<int32_t, 4>(); break; // int32
+ case 0x22: out = in->getIntegerValue<uint32_t, 4>(); break; // uint32
+
+ case 0x23: out = in->get<float>(); break; // float(32)
+
+ // case 0x27: break; //TODO: utf-32 char
+
+ case 0x30: out.setEncoding(amqp0_10_binary); // bin64
+ case 0x31: out = in->getIntegerValue<int64_t, 8>(); break; //int64
+
+ case 0x38: out.setEncoding(amqp0_10_datetime); //treat datetime as uint64_t, but set encoding
+ case 0x32: out = in->getIntegerValue<uint64_t, 8>(); break; //uint64
+ case 0x33: out = in->get<double>(); break; // double
+
+ case 0x48: // uuid
+ {
+ unsigned char data[16];
+ in->getFixedWidthValue<16>(data);
+ out = qpid::types::Uuid(data);
+ } break;
+
+ //TODO: figure out whether and how to map values with codes 0x40-0xd8
+
+ case 0xf0: break;//void, which is the default value for Variant
+ // case 0xf1: out.setEncoding(amqp0_10_bit); break;//treat 'bit' as void, which is the default value for Variant
+
+ //Variable Width types:
+ //strings:
+ case 0x80: // str8
+ case 0x90: // str16
+ case 0xa0: // str32
+ out = in->get<string>();
+ out.setEncoding(amqp0_10_binary);
+ break;
+
+ case 0x84: // str8
+ case 0x94: // str16
+ out = in->get<string>();
+ out.setEncoding(iso885915);
+ break;
+
+ case 0x85: // str8
+ case 0x95: // str16
+ out = in->get<string>();
+ out.setEncoding(utf8);
+ break;
+
+ case 0x86: // str8
+ case 0x96: // str16
+ out = in->get<string>();
+ out.setEncoding(utf16);
+ break;
+
+ case 0xab: // str32
+ out = in->get<string>();
+ out.setEncoding(amqp0_10_struct);
+ break;
+
+ case 0xa8: // map
+ out = ManagementAgent::toMap(in->get<FieldTable>());
+ break;
+
+ case 0xa9: // list of variant types
+ out = ManagementAgent::toList(in->get<List>());
+ break;
+ //case 0xaa: //convert amqp0-10 array (uniform type) into variant list
+ // out = Variant::List();
+ // translate<Array>(in, out.asList(), &toVariant);
+ // break;
+
+ default:
+ //error?
+ QPID_LOG(error, "Unknown FieldValue type - not converted: [" << (unsigned int)(in->getType()) << "]");
+ break;
+ }
+
+ return out;
+}
+
// Build up a list of the current set of deleted objects that are pending their
// next (last) publish-ment.
@@ -2915,21 +3085,3 @@ bool ManagementAgent::moveDeletedObjectsLH() {
}
return !deleteList.empty();
}
-
-namespace qpid {
-namespace management {
-
-namespace {
-QPID_TSS const qpid::broker::ConnectionState* executionContext = 0;
-}
-
-void setManagementExecutionContext(const qpid::broker::ConnectionState* ctxt)
-{
- executionContext = ctxt;
-}
-const qpid::broker::ConnectionState* getManagementExecutionContext()
-{
- return executionContext;
-}
-
-}}
diff --git a/cpp/src/qpid/management/ManagementAgent.h b/cpp/src/qpid/management/ManagementAgent.h
index c21f384433..0db19594a7 100644
--- a/cpp/src/qpid/management/ManagementAgent.h
+++ b/cpp/src/qpid/management/ManagementAgent.h
@@ -41,9 +41,6 @@
#include <map>
namespace qpid {
-namespace broker {
-class ConnectionState;
-}
namespace management {
class ManagementAgent
@@ -145,7 +142,13 @@ public:
const framing::Uuid& getUuid() const { return uuid; }
void setUuid(const framing::Uuid& id) { uuid = id; writeData(); }
+ // TODO: remove these when Variant API moved into common library.
static types::Variant::Map toMap(const framing::FieldTable& from);
+ static framing::FieldTable fromMap(const types::Variant::Map& from);
+ static types::Variant::List toList(const framing::List& from);
+ static framing::List fromList(const types::Variant::List& from);
+ static boost::shared_ptr<framing::FieldValue> toFieldValue(const types::Variant& in);
+ static types::Variant toVariant(const boost::shared_ptr<framing::FieldValue>& val);
// For Clustering: management objects that have been marked as
// "deleted", but are waiting for their last published object
@@ -419,8 +422,6 @@ private:
void debugSnapshot(const char* title);
};
-void setManagementExecutionContext(const qpid::broker::ConnectionState*);
-const qpid::broker::ConnectionState* getManagementExecutionContext();
}}
-
+
#endif /*!_ManagementAgent_*/
diff --git a/cpp/src/qpid/messaging/AddressParser.cpp b/cpp/src/qpid/messaging/AddressParser.cpp
index d76210ee5d..4c8f35fbc5 100644
--- a/cpp/src/qpid/messaging/AddressParser.cpp
+++ b/cpp/src/qpid/messaging/AddressParser.cpp
@@ -151,7 +151,7 @@ bool AddressParser::readValueIfExists(Variant& value)
bool AddressParser::readString(std::string& value, char delimiter)
{
if (readChar(delimiter)) {
- std::string::size_type start = current;
+ std::string::size_type start = current++;
while (!eos()) {
if (input.at(current) == delimiter) {
if (current > start) {
@@ -201,8 +201,7 @@ bool AddressParser::readSimpleValue(Variant& value)
{
std::string s;
if (readWord(s)) {
- value.parse(s);
- if (value.getType() == VAR_STRING) value.setEncoding("utf8");
+ value.parse(s);
return true;
} else {
return false;
diff --git a/cpp/src/qpid/messaging/Duration.cpp b/cpp/src/qpid/messaging/Duration.cpp
index a23e9f5bcb..a2c443c746 100644
--- a/cpp/src/qpid/messaging/Duration.cpp
+++ b/cpp/src/qpid/messaging/Duration.cpp
@@ -37,16 +37,6 @@ Duration operator*(uint64_t multiplier, const Duration& duration)
return Duration(duration.getMilliseconds() * multiplier);
}
-bool operator==(const Duration& a, const Duration& b)
-{
- return a.getMilliseconds() == b.getMilliseconds();
-}
-
-bool operator!=(const Duration& a, const Duration& b)
-{
- return a.getMilliseconds() != b.getMilliseconds();
-}
-
const Duration Duration::FOREVER(std::numeric_limits<uint64_t>::max());
const Duration Duration::IMMEDIATE(0);
const Duration Duration::SECOND(1000);
diff --git a/cpp/src/qpid/messaging/Message.cpp b/cpp/src/qpid/messaging/Message.cpp
index ef70c103e9..83cdfd3c55 100644
--- a/cpp/src/qpid/messaging/Message.cpp
+++ b/cpp/src/qpid/messaging/Message.cpp
@@ -21,7 +21,6 @@
#include "qpid/messaging/Message.h"
#include "qpid/messaging/MessageImpl.h"
#include "qpid/amqp_0_10/Codecs.h"
-#include <qpid/Exception.h>
#include <boost/format.hpp>
namespace qpid {
@@ -116,11 +115,7 @@ template <class C> struct MessageCodec
static void decode(const Message& message, typename C::ObjectType& object, const std::string& encoding)
{
checkEncoding(message, encoding);
- try {
- C::decode(message.getContent(), object);
- } catch (const qpid::Exception &ex) {
- throw EncodingException(ex.what());
- }
+ C::decode(message.getContent(), object);
}
static void encode(const typename C::ObjectType& map, Message& message, const std::string& encoding)
diff --git a/cpp/src/qpid/messaging/Session.cpp b/cpp/src/qpid/messaging/Session.cpp
index cccfd9a873..496953a8e5 100644
--- a/cpp/src/qpid/messaging/Session.cpp
+++ b/cpp/src/qpid/messaging/Session.cpp
@@ -39,8 +39,7 @@ Session& Session::operator=(const Session& s) { return PI::assign(*this, s); }
void Session::commit() { impl->commit(); }
void Session::rollback() { impl->rollback(); }
void Session::acknowledge(bool sync) { impl->acknowledge(sync); }
-void Session::acknowledge(Message& m, bool s) { impl->acknowledge(m, false); sync(s); }
-void Session::acknowledgeUpTo(Message& m, bool s) { impl->acknowledge(m, true); sync(s); }
+void Session::acknowledge(Message& m, bool s) { impl->acknowledge(m); sync(s); }
void Session::reject(Message& m) { impl->reject(m); }
void Session::release(Message& m) { impl->release(m); }
void Session::close() { impl->close(); }
diff --git a/cpp/src/qpid/messaging/SessionImpl.h b/cpp/src/qpid/messaging/SessionImpl.h
index 60ae615253..02a254e4f2 100644
--- a/cpp/src/qpid/messaging/SessionImpl.h
+++ b/cpp/src/qpid/messaging/SessionImpl.h
@@ -41,7 +41,7 @@ class SessionImpl : public virtual qpid::RefCounted
virtual void commit() = 0;
virtual void rollback() = 0;
virtual void acknowledge(bool sync) = 0;
- virtual void acknowledge(Message&, bool cumulative) = 0;
+ virtual void acknowledge(Message&) = 0;
virtual void reject(Message&) = 0;
virtual void release(Message&) = 0;
virtual void close() = 0;
diff --git a/cpp/src/qpid/replication/ReplicatingEventListener.cpp b/cpp/src/qpid/replication/ReplicatingEventListener.cpp
index 0ced4d9161..b7d52372f4 100644
--- a/cpp/src/qpid/replication/ReplicatingEventListener.cpp
+++ b/cpp/src/qpid/replication/ReplicatingEventListener.cpp
@@ -69,9 +69,10 @@ void ReplicatingEventListener::deliverDequeueMessage(const QueuedMessage& dequeu
void ReplicatingEventListener::deliverEnqueueMessage(const QueuedMessage& enqueued)
{
boost::intrusive_ptr<Message> msg(cloneMessage(*(enqueued.queue), enqueued.payload));
- msg->insertCustomProperty(REPLICATION_TARGET_QUEUE, enqueued.queue->getName());
- msg->insertCustomProperty(REPLICATION_EVENT_TYPE, ENQUEUE);
- msg->insertCustomProperty(QUEUE_MESSAGE_POSITION,enqueued.position);
+ FieldTable& headers = msg->getProperties<MessageProperties>()->getApplicationHeaders();
+ headers.setString(REPLICATION_TARGET_QUEUE, enqueued.queue->getName());
+ headers.setInt(REPLICATION_EVENT_TYPE, ENQUEUE);
+ headers.setInt(QUEUE_MESSAGE_POSITION,enqueued.position);
route(msg);
}
diff --git a/cpp/src/qpid/replication/ReplicationExchange.cpp b/cpp/src/qpid/replication/ReplicationExchange.cpp
index 89a2bf516d..4b6d25ac7d 100644
--- a/cpp/src/qpid/replication/ReplicationExchange.cpp
+++ b/cpp/src/qpid/replication/ReplicationExchange.cpp
@@ -97,10 +97,11 @@ void ReplicationExchange::handleEnqueueEvent(const FieldTable* args, Deliverable
} else {
queue->setPosition(seqno1);
- msg.getMessage().removeCustomProperty(REPLICATION_TARGET_QUEUE);
- msg.getMessage().removeCustomProperty(REPLICATION_EVENT_SEQNO);
- msg.getMessage().removeCustomProperty(REPLICATION_EVENT_TYPE);
- msg.getMessage().removeCustomProperty(QUEUE_MESSAGE_POSITION);
+ FieldTable& headers = msg.getMessage().getProperties<MessageProperties>()->getApplicationHeaders();
+ headers.erase(REPLICATION_TARGET_QUEUE);
+ headers.erase(REPLICATION_EVENT_SEQNO);
+ headers.erase(REPLICATION_EVENT_TYPE);
+ headers.erase(QUEUE_MESSAGE_POSITION);
msg.deliverTo(queue);
QPID_LOG(debug, "Enqueued replicated message onto " << queueName);
if (mgmtExchange != 0) {
diff --git a/cpp/src/qpid/store/StorageProvider.h b/cpp/src/qpid/store/StorageProvider.h
index d162cc58ec..bc8d187517 100644
--- a/cpp/src/qpid/store/StorageProvider.h
+++ b/cpp/src/qpid/store/StorageProvider.h
@@ -54,7 +54,7 @@ struct QueueEntry {
QueueEntry(uint64_t id, TplStatus tpl = NONE, const std::string& x = "")
: queueId(id), tplStatus(tpl), xid(x) {}
- bool operator==(const QueueEntry& rhs) const {
+ bool operator==(const QueueEntry& rhs) {
if (queueId != rhs.queueId) return false;
if (tplStatus == NONE && rhs.tplStatus == NONE) return true;
return xid == rhs.xid;
diff --git a/cpp/src/qpid/sys/AggregateOutput.h b/cpp/src/qpid/sys/AggregateOutput.h
index d7c0ff29e3..6dad998bb0 100644
--- a/cpp/src/qpid/sys/AggregateOutput.h
+++ b/cpp/src/qpid/sys/AggregateOutput.h
@@ -41,7 +41,7 @@ namespace sys {
* doOutput is called in another.
*/
-class QPID_COMMON_CLASS_EXTERN AggregateOutput : public OutputTask, public OutputControl
+class AggregateOutput : public OutputTask, public OutputControl
{
typedef std::deque<OutputTask*> TaskList;
diff --git a/cpp/src/qpid/sys/AsynchIO.h b/cpp/src/qpid/sys/AsynchIO.h
index 41f74f7ed0..50da8fa4fc 100644
--- a/cpp/src/qpid/sys/AsynchIO.h
+++ b/cpp/src/qpid/sys/AsynchIO.h
@@ -64,8 +64,8 @@ public:
// deletes. To correctly manage heaps when needed, the allocate and
// delete should both be done from the same class/library.
QPID_COMMON_EXTERN static AsynchConnector* create(const Socket& s,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb);
virtual void start(boost::shared_ptr<Poller> poller) = 0;
diff --git a/cpp/src/qpid/sys/AsynchIOHandler.h b/cpp/src/qpid/sys/AsynchIOHandler.h
index b9867606c4..e1885bac79 100644
--- a/cpp/src/qpid/sys/AsynchIOHandler.h
+++ b/cpp/src/qpid/sys/AsynchIOHandler.h
@@ -57,7 +57,7 @@ class AsynchIOHandler : public OutputControl {
QPID_COMMON_EXTERN ~AsynchIOHandler();
QPID_COMMON_EXTERN void init(AsynchIO* a, int numBuffs);
- QPID_COMMON_INLINE_EXTERN void setClient() { isClient = true; }
+ QPID_COMMON_EXTERN void setClient() { isClient = true; }
// Output side
QPID_COMMON_EXTERN void abort();
diff --git a/cpp/src/qpid/sys/AtomicValue.h b/cpp/src/qpid/sys/AtomicValue.h
index bf995f991e..6e90eafead 100644
--- a/cpp/src/qpid/sys/AtomicValue.h
+++ b/cpp/src/qpid/sys/AtomicValue.h
@@ -22,12 +22,7 @@
*
*/
-// Have to check for clang before gcc as clang pretends to be gcc too
-#if defined( __clang__ )
-// Use the clang doesn't support atomic builtins for 64 bit values, so use the slow versions
-#include "qpid/sys/AtomicValue_mutex.h"
-
-#elif defined( __GNUC__ ) && __GNUC__ >= 4 && ( defined( __i686__ ) || defined( __x86_64__ ) )
+#if defined( __GNUC__ ) && __GNUC__ >= 4 && ( defined( __i686__ ) || defined( __x86_64__ ) )
// Use the Gnu C built-in atomic operations if compiling with gcc on a suitable platform.
#include "qpid/sys/AtomicValue_gcc.h"
diff --git a/cpp/src/qpid/sys/AtomicValue_gcc.h b/cpp/src/qpid/sys/AtomicValue_gcc.h
index 724bae422e..d022b07c1d 100644
--- a/cpp/src/qpid/sys/AtomicValue_gcc.h
+++ b/cpp/src/qpid/sys/AtomicValue_gcc.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -39,9 +39,6 @@ class AtomicValue
public:
AtomicValue(T init=0) : value(init) {}
- // Not atomic. Don't call concurrently with atomic ops.
- AtomicValue<T>& operator=(T newValue) { value = newValue; return *this; }
-
// Update and return new value.
inline T operator+=(T n) { return __sync_add_and_fetch(&value, n); }
inline T operator-=(T n) { return __sync_sub_and_fetch(&value, n); }
@@ -57,11 +54,11 @@ class AtomicValue
/** If current value == testval then set to newval. Returns the old value. */
T valueCompareAndSwap(T testval, T newval) { return __sync_val_compare_and_swap(&value, testval, newval); }
- /** If current value == testval then set to newval. Returns true if the swap was performed. */
+ /** If current value == testval then set to newval. Returns true if the swap was performed. */
bool boolCompareAndSwap(T testval, T newval) { return __sync_bool_compare_and_swap(&value, testval, newval); }
T get() const { return const_cast<AtomicValue<T>*>(this)->fetchAndAdd(static_cast<T>(0)); }
-
+
private:
T value;
};
diff --git a/cpp/src/qpid/sys/ClusterSafe.cpp b/cpp/src/qpid/sys/ClusterSafe.cpp
index dd37615145..c6b527dfdf 100644
--- a/cpp/src/qpid/sys/ClusterSafe.cpp
+++ b/cpp/src/qpid/sys/ClusterSafe.cpp
@@ -34,6 +34,8 @@ QPID_TSS bool inContext = false;
bool isClusterSafe() { return !inCluster || inContext; }
+bool isCluster() { return inCluster; }
+
void assertClusterSafe() {
if (!isClusterSafe()) {
QPID_LOG(critical, "Modified cluster state outside of cluster context");
@@ -51,16 +53,6 @@ ClusterSafeScope::~ClusterSafeScope() {
inContext = save;
}
-ClusterUnsafeScope::ClusterUnsafeScope() {
- save = inContext;
- inContext = false;
-}
-
-ClusterUnsafeScope::~ClusterUnsafeScope() {
- assert(!inContext);
- inContext = save;
-}
-
void enableClusterSafe() { inCluster = true; }
}} // namespace qpid::sys
diff --git a/cpp/src/qpid/sys/ClusterSafe.h b/cpp/src/qpid/sys/ClusterSafe.h
index 27e4eb46a5..15675e8cc5 100644
--- a/cpp/src/qpid/sys/ClusterSafe.h
+++ b/cpp/src/qpid/sys/ClusterSafe.h
@@ -52,9 +52,14 @@ QPID_COMMON_EXTERN void assertClusterSafe();
*/
QPID_COMMON_EXTERN bool isClusterSafe();
+/** Return true in a clustered broker */
+QPID_COMMON_EXTERN bool isCluster();
+
/**
- * Mark a scope as cluster safe. Sets isClusterSafe in constructor and resets
- * to previous value in destructor.
+ * Base class for classes that encapsulate state which is replicated
+ * to all members of a cluster. Acts as a marker for clustered state
+ * and provides functions to assist detecting bugs in cluster
+ * behavior.
*/
class ClusterSafeScope {
public:
@@ -65,18 +70,6 @@ class ClusterSafeScope {
};
/**
- * Mark a scope as cluster unsafe. Clears isClusterSafe in constructor and resets
- * to previous value in destructor.
- */
-class ClusterUnsafeScope {
- public:
- QPID_COMMON_EXTERN ClusterUnsafeScope();
- QPID_COMMON_EXTERN ~ClusterUnsafeScope();
- private:
- bool save;
-};
-
-/**
* Enable cluster-safe assertions. By default they are no-ops.
* Called by cluster code.
*/
diff --git a/cpp/src/qpid/sys/CopyOnWriteArray.h b/cpp/src/qpid/sys/CopyOnWriteArray.h
index 41384fc5a4..45a231dfd8 100644
--- a/cpp/src/qpid/sys/CopyOnWriteArray.h
+++ b/cpp/src/qpid/sys/CopyOnWriteArray.h
@@ -43,12 +43,6 @@ public:
CopyOnWriteArray() {}
CopyOnWriteArray(const CopyOnWriteArray& c) : array(c.array) {}
- bool empty()
- {
- Mutex::ScopedLock l(lock);
- return array ? array->empty() : true;
- }
-
void add(T& t)
{
Mutex::ScopedLock l(lock);
diff --git a/cpp/src/qpid/sys/PollableQueue.h b/cpp/src/qpid/sys/PollableQueue.h
index 03b9d0084d..81c2301c1e 100644
--- a/cpp/src/qpid/sys/PollableQueue.h
+++ b/cpp/src/qpid/sys/PollableQueue.h
@@ -10,9 +10,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -28,8 +28,7 @@
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <algorithm>
-#include <deque>
-#include "qpid/log/Statement.h" // FIXME aconway 2011-08-05:
+#include <vector>
namespace qpid {
namespace sys {
@@ -45,7 +44,7 @@ class Poller;
template <class T>
class PollableQueue {
public:
- typedef std::deque<T> Batch;
+ typedef std::vector<T> Batch;
typedef T value_type;
/**
@@ -69,11 +68,11 @@ class PollableQueue {
const boost::shared_ptr<sys::Poller>& poller);
~PollableQueue();
-
+
/** Push a value onto the queue. Thread safe */
void push(const T& t);
- /** Start polling. */
+ /** Start polling. */
void start();
/** Stop polling and wait for the current callback, if any, to complete. */
@@ -91,14 +90,14 @@ class PollableQueue {
* ensure clean shutdown with no events left on the queue.
*/
void shutdown();
-
+
private:
typedef sys::Monitor::ScopedLock ScopedLock;
typedef sys::Monitor::ScopedUnlock ScopedUnlock;
void dispatch(PollableCondition& cond);
void process();
-
+
mutable sys::Monitor lock;
Callback callback;
PollableCondition condition;
@@ -108,7 +107,7 @@ class PollableQueue {
};
template <class T> PollableQueue<T>::PollableQueue(
- const Callback& cb, const boost::shared_ptr<sys::Poller>& p)
+ const Callback& cb, const boost::shared_ptr<sys::Poller>& p)
: callback(cb),
condition(boost::bind(&PollableQueue<T>::dispatch, this, _1), p),
stopped(true)
@@ -152,7 +151,7 @@ template <class T> void PollableQueue<T>::process() {
putBack = callback(batch);
}
// put back unprocessed items.
- queue.insert(queue.begin(), putBack, typename Batch::const_iterator(batch.end()));
+ queue.insert(queue.begin(), putBack, typename Batch::const_iterator(batch.end()));
batch.clear();
}
}
diff --git a/cpp/src/qpid/sys/Poller.h b/cpp/src/qpid/sys/Poller.h
index 01ee139ee6..ec53b79bad 100644
--- a/cpp/src/qpid/sys/Poller.h
+++ b/cpp/src/qpid/sys/Poller.h
@@ -120,7 +120,7 @@ class PollerHandle {
friend struct Poller::Event;
PollerHandlePrivate* const impl;
- QPID_COMMON_INLINE_EXTERN virtual void processEvent(Poller::EventType) {};
+ QPID_COMMON_EXTERN virtual void processEvent(Poller::EventType) {};
public:
QPID_COMMON_EXTERN PollerHandle(const IOHandle& h);
diff --git a/cpp/src/qpid/sys/ProtocolFactory.h b/cpp/src/qpid/sys/ProtocolFactory.h
index 4d198a92da..b233b2da1a 100644
--- a/cpp/src/qpid/sys/ProtocolFactory.h
+++ b/cpp/src/qpid/sys/ProtocolFactory.h
@@ -39,10 +39,11 @@ class ProtocolFactory : public qpid::SharedObject<ProtocolFactory>
virtual ~ProtocolFactory() = 0;
virtual uint16_t getPort() const = 0;
+ virtual std::string getHost() const = 0;
virtual void accept(boost::shared_ptr<Poller>, ConnectionCodec::Factory*) = 0;
virtual void connect(
boost::shared_ptr<Poller>,
- const std::string& host, const std::string& port,
+ const std::string& host, int16_t port,
ConnectionCodec::Factory* codec,
ConnectFailedCallback failed) = 0;
virtual bool supports(const std::string& /*capability*/) { return false; }
diff --git a/cpp/src/qpid/sys/RdmaIOPlugin.cpp b/cpp/src/qpid/sys/RdmaIOPlugin.cpp
index 6769e5383c..d53db20598 100644
--- a/cpp/src/qpid/sys/RdmaIOPlugin.cpp
+++ b/cpp/src/qpid/sys/RdmaIOPlugin.cpp
@@ -31,6 +31,7 @@
#include "qpid/sys/SecuritySettings.h"
#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
#include <memory>
#include <netdb.h>
@@ -211,9 +212,10 @@ void RdmaIOHandler::readbuff(Rdma::AsynchIO&, Rdma::Buffer* buff) {
if (readError) {
return;
}
+ size_t decoded = 0;
try {
if (codec) {
- (void) codec->decode(buff->bytes(), buff->dataCount());
+ decoded = codec->decode(buff->bytes(), buff->dataCount());
}else{
// Need to start protocol processing
initProtocolIn(buff);
@@ -228,7 +230,9 @@ void RdmaIOHandler::readbuff(Rdma::AsynchIO&, Rdma::Buffer* buff) {
void RdmaIOHandler::initProtocolIn(Rdma::Buffer* buff) {
framing::Buffer in(buff->bytes(), buff->dataCount());
framing::ProtocolInitiation protocolInit;
+ size_t decoded = 0;
if (protocolInit.decode(in)) {
+ decoded = in.getPosition();
QPID_LOG(debug, "Rdma: RECV [" << identifier << "] INIT(" << protocolInit << ")");
codec = factory->create(protocolInit.getVersion(), *this, identifier, SecuritySettings());
@@ -250,9 +254,10 @@ class RdmaIOProtocolFactory : public ProtocolFactory {
public:
RdmaIOProtocolFactory(int16_t port, int backlog);
void accept(Poller::shared_ptr, ConnectionCodec::Factory*);
- void connect(Poller::shared_ptr, const string& host, const std::string& port, ConnectionCodec::Factory*, ConnectFailedCallback);
+ void connect(Poller::shared_ptr, const string& host, int16_t port, ConnectionCodec::Factory*, ConnectFailedCallback);
uint16_t getPort() const;
+ string getHost() const;
private:
bool request(Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&, ConnectionCodec::Factory*);
@@ -342,7 +347,18 @@ uint16_t RdmaIOProtocolFactory::getPort() const {
return listeningPort; // Immutable no need for lock.
}
+string RdmaIOProtocolFactory::getHost() const {
+ //return listener.getSockname();
+ return "";
+}
+
void RdmaIOProtocolFactory::accept(Poller::shared_ptr poller, ConnectionCodec::Factory* fact) {
+ ::sockaddr_in sin;
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(listeningPort);
+ sin.sin_addr.s_addr = INADDR_ANY;
+
listener.reset(
new Rdma::Listener(
Rdma::ConnectionParams(65536, Rdma::DEFAULT_WR_ENTRIES),
@@ -371,7 +387,7 @@ void RdmaIOProtocolFactory::connected(Poller::shared_ptr poller, Rdma::Connectio
void RdmaIOProtocolFactory::connect(
Poller::shared_ptr poller,
- const std::string& host, const std::string& port,
+ const std::string& host, int16_t port,
ConnectionCodec::Factory* f,
ConnectFailedCallback failed)
{
@@ -383,7 +399,7 @@ void RdmaIOProtocolFactory::connect(
boost::bind(&RdmaIOProtocolFactory::disconnected, this, _1),
boost::bind(&RdmaIOProtocolFactory::rejected, this, _1, _2, failed));
- SocketAddress sa(host, port);
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
c->start(poller, sa);
}
diff --git a/cpp/src/qpid/sys/Socket.h b/cpp/src/qpid/sys/Socket.h
index 25f1c5fb9d..7d50afc59f 100644
--- a/cpp/src/qpid/sys/Socket.h
+++ b/cpp/src/qpid/sys/Socket.h
@@ -33,21 +33,21 @@ namespace sys {
class Duration;
class SocketAddress;
-class QPID_COMMON_CLASS_EXTERN Socket : public IOHandle
+class Socket : public IOHandle
{
public:
/** Create a socket wrapper for descriptor. */
QPID_COMMON_EXTERN Socket();
- /** Create a new Socket which is the same address family as this one */
- QPID_COMMON_EXTERN Socket* createSameTypeSocket() const;
+ /** Set timeout for read and write */
+ void setTimeout(const Duration& interval) const;
/** Set socket non blocking */
void setNonblocking() const;
QPID_COMMON_EXTERN void setTcpNoDelay() const;
- QPID_COMMON_EXTERN void connect(const std::string& host, const std::string& port) 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;
@@ -57,9 +57,19 @@ public:
*@param backlog maximum number of pending connections.
*@return The bound port.
*/
- QPID_COMMON_EXTERN int listen(const std::string& host = "", const std::string& port = "0", int backlog = 10) const;
+ QPID_COMMON_EXTERN int listen(uint16_t port = 0, int backlog = 10) const;
QPID_COMMON_EXTERN int listen(const SocketAddress&, int backlog = 10) const;
+ /** Returns the "socket name" ie the address bound to
+ * the near end of the socket
+ */
+ QPID_COMMON_EXTERN std::string getSockname() const;
+
+ /** Returns the "peer name" ie the address bound to
+ * the remote end of the socket
+ */
+ std::string getPeername() const;
+
/**
* Returns an address (host and port) for the remote end of the
* socket
@@ -74,13 +84,16 @@ public:
/**
* Returns the full address of the connection: local and remote host and port.
*/
- QPID_COMMON_INLINE_EXTERN std::string getFullAddress() const { return getLocalAddress()+"-"+getPeerAddress(); }
+ QPID_COMMON_EXTERN std::string getFullAddress() const { return getLocalAddress()+"-"+getPeerAddress(); }
+
+ QPID_COMMON_EXTERN uint16_t getLocalPort() const;
+ uint16_t getRemotePort() const;
/**
* Returns the error code stored in the socket. This may be used
* to determine the result of a non-blocking connect.
*/
- QPID_COMMON_EXTERN int getError() const;
+ int getError() const;
/** Accept a connection from a socket that is already listening
* and has an incoming connection
@@ -95,11 +108,8 @@ private:
/** Create socket */
void createSocket(const SocketAddress&) const;
- /** Construct socket with existing handle */
Socket(IOHandlePrivate*);
-
- mutable std::string localname;
- mutable std::string peername;
+ mutable std::string connectname;
mutable bool nonblocking;
mutable bool nodelay;
};
diff --git a/cpp/src/qpid/sys/SocketAddress.h b/cpp/src/qpid/sys/SocketAddress.h
index dcca109d94..27b9642f2c 100644
--- a/cpp/src/qpid/sys/SocketAddress.h
+++ b/cpp/src/qpid/sys/SocketAddress.h
@@ -27,7 +27,6 @@
#include <string>
struct addrinfo;
-struct sockaddr;
namespace qpid {
namespace sys {
@@ -42,19 +41,12 @@ public:
QPID_COMMON_EXTERN SocketAddress& operator=(const SocketAddress&);
QPID_COMMON_EXTERN ~SocketAddress();
- QPID_COMMON_EXTERN bool nextAddress();
- QPID_COMMON_EXTERN std::string asString(bool numeric=true) const;
- QPID_COMMON_EXTERN void setAddrInfoPort(uint16_t port);
-
- QPID_COMMON_EXTERN static std::string asString(::sockaddr const * const addr, size_t addrlen);
- QPID_COMMON_EXTERN static uint16_t getPort(::sockaddr const * const addr);
-
+ std::string asString() const;
private:
std::string host;
std::string port;
mutable ::addrinfo* addrInfo;
- mutable ::addrinfo* currentAddrInfo;
};
}}
diff --git a/cpp/src/qpid/sys/SslPlugin.cpp b/cpp/src/qpid/sys/SslPlugin.cpp
index 471a0cef60..b0e791d60b 100644
--- a/cpp/src/qpid/sys/SslPlugin.cpp
+++ b/cpp/src/qpid/sys/SslPlugin.cpp
@@ -66,11 +66,12 @@ class SslProtocolFactory : public ProtocolFactory {
public:
SslProtocolFactory(const SslServerOptions&, int backlog, bool nodelay);
void accept(Poller::shared_ptr, ConnectionCodec::Factory*);
- void connect(Poller::shared_ptr, const std::string& host, const std::string& port,
+ void connect(Poller::shared_ptr, const std::string& host, int16_t port,
ConnectionCodec::Factory*,
boost::function2<void, int, std::string> failed);
uint16_t getPort() const;
+ std::string getHost() const;
bool supports(const std::string& capability);
private:
@@ -94,7 +95,7 @@ static struct SslPlugin : public Plugin {
// Only provide to a Broker
if (broker) {
if (options.certDbPath.empty()) {
- QPID_LOG(notice, "SSL plugin not enabled, you must set --ssl-cert-db to enable it.");
+ QPID_LOG(info, "SSL plugin not enabled, you must set --ssl-cert-db to enable it.");
} else {
try {
ssl::initNSS(options, true);
@@ -145,6 +146,10 @@ uint16_t SslProtocolFactory::getPort() const {
return listeningPort; // Immutable no need for lock.
}
+std::string SslProtocolFactory::getHost() const {
+ return listener.getSockname();
+}
+
void SslProtocolFactory::accept(Poller::shared_ptr poller,
ConnectionCodec::Factory* fact) {
acceptor.reset(
@@ -155,7 +160,7 @@ void SslProtocolFactory::accept(Poller::shared_ptr poller,
void SslProtocolFactory::connect(
Poller::shared_ptr poller,
- const std::string& host, const std::string& port,
+ const std::string& host, int16_t port,
ConnectionCodec::Factory* fact,
ConnectFailedCallback failed)
{
diff --git a/cpp/src/qpid/sys/StateMonitor.h b/cpp/src/qpid/sys/StateMonitor.h
index eac37a8543..5a92756f3a 100644
--- a/cpp/src/qpid/sys/StateMonitor.h
+++ b/cpp/src/qpid/sys/StateMonitor.h
@@ -41,9 +41,9 @@ class StateMonitor : public Waitable
struct Set : public std::bitset<MaxEnum + 1> {
Set() {}
Set(Enum s) { set(s); }
- Set(Enum s, Enum t) { std::bitset<MaxEnum + 1>::set(s).set(t); }
- Set(Enum s, Enum t, Enum u) { std::bitset<MaxEnum + 1>::set(s).set(t).set(u); }
- Set(Enum s, Enum t, Enum u, Enum v) { std::bitset<MaxEnum + 1>::set(s).set(t).set(u).set(v); }
+ Set(Enum s, Enum t) { set(s).set(t); }
+ Set(Enum s, Enum t, Enum u) { set(s).set(t).set(u); }
+ Set(Enum s, Enum t, Enum u, Enum v) { set(s).set(t).set(u).set(v); }
};
@@ -60,13 +60,13 @@ class StateMonitor : public Waitable
operator Enum() const { return state; }
/** @pre Caller holds a ScopedLock */
- void waitFor(Enum s) { ScopedWait w(*this); while (s != state) wait(); }
+ void waitFor(Enum s) { ScopedWait(*this); while (s != state) wait(); }
/** @pre Caller holds a ScopedLock */
- void waitFor(Set s) { ScopedWait w(*this); while (!s.test(state)) wait(); }
+ void waitFor(Set s) { ScopedWait(*this); while (!s.test(state)) wait(); }
/** @pre Caller holds a ScopedLock */
- void waitNot(Enum s) { ScopedWait w(*this); while (s == state) wait(); }
+ void waitNot(Enum s) { ScopedWait(*this); while (s == state) wait(); }
/** @pre Caller holds a ScopedLock */
- void waitNot(Set s) { ScopedWait w(*this); while (s.test(state)) wait(); }
+ void waitNot(Set s) { ScopedWait(*this); while (s.test(state)) wait(); }
private:
Enum state;
diff --git a/cpp/src/qpid/sys/TCPIOPlugin.cpp b/cpp/src/qpid/sys/TCPIOPlugin.cpp
index 85d8c1db87..a6528f9ad9 100644
--- a/cpp/src/qpid/sys/TCPIOPlugin.cpp
+++ b/cpp/src/qpid/sys/TCPIOPlugin.cpp
@@ -25,31 +25,31 @@
#include "qpid/Plugin.h"
#include "qpid/sys/Socket.h"
-#include "qpid/sys/SocketAddress.h"
#include "qpid/sys/Poller.h"
#include "qpid/broker/Broker.h"
#include "qpid/log/Statement.h"
#include <boost/bind.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
+#include <memory>
namespace qpid {
namespace sys {
class AsynchIOProtocolFactory : public ProtocolFactory {
const bool tcpNoDelay;
- boost::ptr_vector<Socket> listeners;
- boost::ptr_vector<AsynchAcceptor> acceptors;
- uint16_t listeningPort;
+ Socket listener;
+ const uint16_t listeningPort;
+ std::auto_ptr<AsynchAcceptor> acceptor;
public:
- AsynchIOProtocolFactory(const std::string& host, const std::string& port, int backlog, bool nodelay);
+ AsynchIOProtocolFactory(int16_t port, int backlog, bool nodelay);
void accept(Poller::shared_ptr, ConnectionCodec::Factory*);
- void connect(Poller::shared_ptr, const std::string& host, const std::string& port,
+ void connect(Poller::shared_ptr, const std::string& host, int16_t port,
ConnectionCodec::Factory*,
ConnectFailedCallback);
uint16_t getPort() const;
+ std::string getHost() const;
private:
void established(Poller::shared_ptr, const Socket&, ConnectionCodec::Factory*,
@@ -61,49 +61,23 @@ class AsynchIOProtocolFactory : public ProtocolFactory {
static class TCPIOPlugin : public Plugin {
void earlyInitialize(Target&) {
}
-
+
void initialize(Target& target) {
broker::Broker* broker = dynamic_cast<broker::Broker*>(&target);
// Only provide to a Broker
if (broker) {
const broker::Broker::Options& opts = broker->getOptions();
- ProtocolFactory::shared_ptr protocolt(
- new AsynchIOProtocolFactory(
- "", boost::lexical_cast<std::string>(opts.port),
- opts.connectionBacklog,
- opts.tcpNoDelay));
- QPID_LOG(notice, "Listening on TCP/TCP6 port " << protocolt->getPort());
- broker->registerProtocolFactory("tcp", protocolt);
+ ProtocolFactory::shared_ptr protocol(new AsynchIOProtocolFactory(opts.port, opts.connectionBacklog,
+ opts.tcpNoDelay));
+ QPID_LOG(notice, "Listening on TCP port " << protocol->getPort());
+ broker->registerProtocolFactory("tcp", protocol);
}
}
} tcpPlugin;
-AsynchIOProtocolFactory::AsynchIOProtocolFactory(const std::string& host, const std::string& port, int backlog, bool nodelay) :
- tcpNoDelay(nodelay)
-{
- SocketAddress sa(host, port);
-
- // We must have at least one resolved address
- QPID_LOG(info, "Listening to: " << sa.asString())
- Socket* s = new Socket;
- uint16_t lport = s->listen(sa, backlog);
- QPID_LOG(debug, "Listened to: " << lport);
- listeners.push_back(s);
-
- listeningPort = lport;
-
- // Try any other resolved addresses
- while (sa.nextAddress()) {
- // Hack to ensure that all listening connections are on the same port
- sa.setAddrInfoPort(listeningPort);
- QPID_LOG(info, "Listening to: " << sa.asString())
- Socket* s = new Socket;
- uint16_t lport = s->listen(sa, backlog);
- QPID_LOG(debug, "Listened to: " << lport);
- listeners.push_back(s);
- }
-
-}
+AsynchIOProtocolFactory::AsynchIOProtocolFactory(int16_t port, int backlog, bool nodelay) :
+ tcpNoDelay(nodelay), listeningPort(listener.listen(port, backlog))
+{}
void AsynchIOProtocolFactory::established(Poller::shared_ptr poller, const Socket& s,
ConnectionCodec::Factory* f, bool isClient) {
@@ -133,14 +107,16 @@ uint16_t AsynchIOProtocolFactory::getPort() const {
return listeningPort; // Immutable no need for lock.
}
+std::string AsynchIOProtocolFactory::getHost() const {
+ return listener.getSockname();
+}
+
void AsynchIOProtocolFactory::accept(Poller::shared_ptr poller,
ConnectionCodec::Factory* fact) {
- for (unsigned i = 0; i<listeners.size(); ++i) {
- acceptors.push_back(
- AsynchAcceptor::create(listeners[i],
- boost::bind(&AsynchIOProtocolFactory::established, this, poller, _1, fact, false)));
- acceptors[i].start(poller);
- }
+ acceptor.reset(
+ AsynchAcceptor::create(listener,
+ boost::bind(&AsynchIOProtocolFactory::established, this, poller, _1, fact, false)));
+ acceptor->start(poller);
}
void AsynchIOProtocolFactory::connectFailed(
@@ -154,7 +130,7 @@ void AsynchIOProtocolFactory::connectFailed(
void AsynchIOProtocolFactory::connect(
Poller::shared_ptr poller,
- const std::string& host, const std::string& port,
+ const std::string& host, int16_t port,
ConnectionCodec::Factory* fact,
ConnectFailedCallback failed)
{
@@ -163,8 +139,8 @@ void AsynchIOProtocolFactory::connect(
// upon connection failure or by the AsynchIO upon connection
// shutdown. The allocated AsynchConnector frees itself when it
// is no longer needed.
+
Socket* socket = new Socket();
- try {
AsynchConnector* c = AsynchConnector::create(
*socket,
host,
@@ -174,12 +150,6 @@ void AsynchIOProtocolFactory::connect(
boost::bind(&AsynchIOProtocolFactory::connectFailed,
this, _1, _2, _3, failed));
c->start(poller);
- } catch (std::exception&) {
- // TODO: Design question - should we do the error callback and also throw?
- int errCode = socket->getError();
- connectFailed(*socket, errCode, strError(errCode), failed);
- throw;
- }
}
}} // namespace qpid::sys
diff --git a/cpp/src/qpid/sys/Timer.cpp b/cpp/src/qpid/sys/Timer.cpp
index 47752e4584..a97ccd1bd1 100644
--- a/cpp/src/qpid/sys/Timer.cpp
+++ b/cpp/src/qpid/sys/Timer.cpp
@@ -75,12 +75,6 @@ void TimerTask::cancel() {
cancelled = true;
}
-void TimerTask::setFired() {
- // Set nextFireTime to just before now, making readyToFire() true.
- nextFireTime = AbsTime(sys::now(), Duration(-1));
-}
-
-
Timer::Timer() :
active(false),
late(50 * TIME_MSEC),
@@ -137,14 +131,12 @@ void Timer::run()
bool warningsEnabled;
QPID_LOG_TEST(warning, warningsEnabled);
if (warningsEnabled) {
- if (overrun > overran) {
- if (delay > overran) // if delay is significant to an overrun.
- warn.lateAndOverran(t->name, delay, overrun, Duration(start, end));
- else
- warn.overran(t->name, overrun, Duration(start, end));
- }
+ if (delay > late && overrun > overran)
+ warn.lateAndOverran(t->name, delay, overrun, Duration(start, end));
else if (delay > late)
warn.late(t->name, delay);
+ else if (overrun > overran)
+ warn.overran(t->name, overrun, Duration(start, end));
}
continue;
} else {
@@ -191,11 +183,7 @@ void Timer::stop()
// Allow subclasses to override behavior when firing a task.
void Timer::fire(boost::intrusive_ptr<TimerTask> t) {
- try {
- t->fireTask();
- } catch (const std::exception& e) {
- QPID_LOG(error, "Exception thrown by timer task " << t->getName() << ": " << e.what());
- }
+ t->fireTask();
}
// Provided for subclasses: called when a task is droped.
diff --git a/cpp/src/qpid/sys/Timer.h b/cpp/src/qpid/sys/Timer.h
index fccb17dbc2..98ba39ce38 100644
--- a/cpp/src/qpid/sys/Timer.h
+++ b/cpp/src/qpid/sys/Timer.h
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -64,10 +64,6 @@ class TimerTask : public RefCounted {
std::string getName() const { return name; }
- // Move the nextFireTime so readyToFire is true.
- // Used by the cluster, where tasks are fired on cluster events, not on local time.
- QPID_COMMON_EXTERN void setFired();
-
protected:
// Must be overridden with callback
virtual void fire() = 0;
diff --git a/cpp/src/qpid/sys/TimerWarnings.cpp b/cpp/src/qpid/sys/TimerWarnings.cpp
index 85e26da54a..48a56eb472 100644
--- a/cpp/src/qpid/sys/TimerWarnings.cpp
+++ b/cpp/src/qpid/sys/TimerWarnings.cpp
@@ -56,22 +56,20 @@ void TimerWarnings::log() {
std::string task = i->first;
TaskStats& stats = i->second;
if (stats.lateDelay.count)
- QPID_LOG(info, task << " task late "
+ QPID_LOG(warning, task << " task late "
<< stats.lateDelay.count << " times by "
<< stats.lateDelay.average()/TIME_MSEC << "ms on average.");
-
if (stats.overranOverrun.count)
- QPID_LOG(info, task << " task overran "
+ QPID_LOG(warning, task << " task overran "
<< stats.overranOverrun.count << " times by "
<< stats.overranOverrun.average()/TIME_MSEC << "ms (taking "
<< stats.overranTime.average() << "ns) on average.");
- if (stats.lateAndOverranOverrun.count)
- QPID_LOG(info, task << " task late and overran "
- << stats.lateAndOverranOverrun.count << " times: late "
- << stats.lateAndOverranDelay.average()/TIME_MSEC << "ms, overran "
- << stats.lateAndOverranOverrun.average()/TIME_MSEC << "ms (taking "
- << stats.lateAndOverranTime.average() << "ns) on average.");
+ if (stats.lateAndOverranDelay.count)
+ QPID_LOG(warning, task << " task overran "
+ << stats.overranOverrun.count << " times by "
+ << stats.overranOverrun.average()/TIME_MSEC << "ms (taking "
+ << stats.overranTime.average() << "ns) on average.");
}
nextReport = AbsTime(now(), interval);
diff --git a/cpp/src/qpid/sys/alloca.h b/cpp/src/qpid/sys/alloca.h
index b3f59b7c3f..e989670e4f 100644
--- a/cpp/src/qpid/sys/alloca.h
+++ b/cpp/src/qpid/sys/alloca.h
@@ -21,22 +21,19 @@
*
*/
-#if (defined(_WINDOWS) || defined (WIN32))
-# include <malloc.h>
-
-# if defined(_MSC_VER)
-# ifdef alloc
-# undef alloc
-# endif
-# define alloc _alloc
-# ifdef alloca
-# undef alloca
-# endif
-# define alloca _alloca
-# endif
+#if (defined(_WINDOWS) || defined (WIN32)) && defined(_MSC_VER)
+#include <malloc.h>
+#ifdef alloc
+# undef alloc
+#endif
+#define alloc _alloc
+#ifdef alloca
+# undef alloca
+#endif
+#define alloca _alloca
#endif
#if !defined _WINDOWS && !defined WIN32
-# include <alloca.h>
+#include <alloca.h>
#endif
#endif /*!QPID_SYS_ALLOCA_H*/
diff --git a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp
index 249b769051..454ce62495 100644
--- a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp
+++ b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp
@@ -57,7 +57,6 @@ size_t CyrusSecurityLayer::decode(const char* input, size_t size)
copied += count;
decodeBuffer.position += count;
size_t decodedSize = codec->decode(decodeBuffer.data, decodeBuffer.position);
- if (decodedSize == 0) break;
if (decodedSize < decodeBuffer.position) {
::memmove(decodeBuffer.data, decodeBuffer.data + decodedSize, decodeBuffer.position - decodedSize);
}
@@ -107,7 +106,7 @@ size_t CyrusSecurityLayer::encode(const char* buffer, size_t size)
bool CyrusSecurityLayer::canEncode()
{
- return codec && (encrypted || codec->canEncode());
+ return encrypted || codec->canEncode();
}
void CyrusSecurityLayer::init(qpid::sys::Codec* c)
diff --git a/cpp/src/qpid/sys/epoll/EpollPoller.cpp b/cpp/src/qpid/sys/epoll/EpollPoller.cpp
index dcc9d9181c..9ad05c71a3 100644
--- a/cpp/src/qpid/sys/epoll/EpollPoller.cpp
+++ b/cpp/src/qpid/sys/epoll/EpollPoller.cpp
@@ -384,12 +384,7 @@ void PollerPrivate::resetMode(PollerHandlePrivate& eh) {
epe.data.u64 = 0; // Keep valgrind happy
epe.data.ptr = &eh;
- int rc = ::epoll_ctl(epollFd, EPOLL_CTL_MOD, eh.fd(), &epe);
- // If something has closed the fd in the meantime try adding it back
- if (rc ==-1 && errno == ENOENT) {
- rc = ::epoll_ctl(epollFd, EPOLL_CTL_ADD, eh.fd(), &epe);
- }
- QPID_POSIX_CHECK(rc);
+ QPID_POSIX_CHECK(::epoll_ctl(epollFd, EPOLL_CTL_MOD, eh.fd(), &epe));
eh.setActive();
return;
diff --git a/cpp/src/qpid/sys/posix/AsynchIO.cpp b/cpp/src/qpid/sys/posix/AsynchIO.cpp
index dab8bd09c6..119a6aa8a4 100644
--- a/cpp/src/qpid/sys/posix/AsynchIO.cpp
+++ b/cpp/src/qpid/sys/posix/AsynchIO.cpp
@@ -149,12 +149,11 @@ private:
ConnectedCallback connCallback;
FailedCallback failCallback;
const Socket& socket;
- SocketAddress sa;
public:
AsynchConnector(const Socket& socket,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb);
void start(Poller::shared_ptr poller);
@@ -162,8 +161,8 @@ public:
};
AsynchConnector::AsynchConnector(const Socket& s,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb) :
DispatchHandle(s,
@@ -172,13 +171,11 @@ AsynchConnector::AsynchConnector(const Socket& s,
boost::bind(&AsynchConnector::connComplete, this, _1)),
connCallback(connCb),
failCallback(failCb),
- socket(s),
- sa(hostname, port)
+ socket(s)
{
socket.setNonblocking();
-
+ SocketAddress sa(hostname, boost::lexical_cast<std::string>(port));
// Note, not catching any exceptions here, also has effect of destructing
- QPID_LOG(info, "Connecting: " << sa.asString());
socket.connect(sa);
}
@@ -194,26 +191,11 @@ void AsynchConnector::stop()
void AsynchConnector::connComplete(DispatchHandle& h)
{
+ h.stopWatch();
int errCode = socket.getError();
if (errCode == 0) {
- h.stopWatch();
connCallback(socket);
} else {
- // Retry while we cause an immediate exception
- // (asynch failure will be handled by re-entering here at the top)
- while (sa.nextAddress()) {
- try {
- // Try next address without deleting ourselves
- QPID_LOG(debug, "Ignored socket connect error: " << strError(errCode));
- QPID_LOG(info, "Retrying connect: " << sa.asString());
- socket.connect(sa);
- return;
- } catch (const std::exception& e) {
- QPID_LOG(debug, "Ignored socket connect exception: " << e.what());
- }
- errCode = socket.getError();
- }
- h.stopWatch();
failCallback(socket, errCode, strError(errCode));
}
DispatchHandle::doDelete();
@@ -607,8 +589,8 @@ AsynchAcceptor* AsynchAcceptor::create(const Socket& s,
}
AsynchConnector* AsynchConnector::create(const Socket& s,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb)
{
diff --git a/cpp/src/qpid/sys/posix/LockFile.cpp b/cpp/src/qpid/sys/posix/LockFile.cpp
index f5a6c292cb..1862ff6ac9 100755
--- a/cpp/src/qpid/sys/posix/LockFile.cpp
+++ b/cpp/src/qpid/sys/posix/LockFile.cpp
@@ -58,7 +58,8 @@ LockFile::~LockFile() {
if (impl) {
int f = impl->fd;
if (f >= 0) {
- (void) ::lockf(f, F_ULOCK, 0); // Suppress warnings about ignoring return value.
+ int unused_ret;
+ unused_ret = ::lockf(f, F_ULOCK, 0); // Suppress warnings about ignoring return value.
::close(f);
impl->fd = -1;
}
diff --git a/cpp/src/qpid/sys/posix/Socket.cpp b/cpp/src/qpid/sys/posix/Socket.cpp
index 4a6dc66f80..7b906f33e8 100644
--- a/cpp/src/qpid/sys/posix/Socket.cpp
+++ b/cpp/src/qpid/sys/posix/Socket.cpp
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -34,35 +34,65 @@
#include <netdb.h>
#include <cstdlib>
#include <string.h>
+#include <iostream>
+
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
namespace qpid {
namespace sys {
namespace {
-std::string getName(int fd, bool local)
+std::string getName(int fd, bool local, bool includeService = false)
{
- ::sockaddr_storage name_s; // big enough for any socket address
- ::sockaddr* name = (::sockaddr*)&name_s;
- ::socklen_t namelen = sizeof(name_s);
-
+ ::sockaddr_storage name; // big enough for any socket address
+ ::socklen_t namelen = sizeof(name);
+
+ int result = -1;
if (local) {
- QPID_POSIX_CHECK( ::getsockname(fd, name, &namelen) );
+ result = ::getsockname(fd, (::sockaddr*)&name, &namelen);
} else {
- QPID_POSIX_CHECK( ::getpeername(fd, name, &namelen) );
+ result = ::getpeername(fd, (::sockaddr*)&name, &namelen);
}
- return SocketAddress::asString(name, namelen);
+ QPID_POSIX_CHECK(result);
+
+ char servName[NI_MAXSERV];
+ char dispName[NI_MAXHOST];
+ if (includeService) {
+ if (int rc=::getnameinfo((::sockaddr*)&name, namelen, dispName, sizeof(dispName),
+ servName, sizeof(servName),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ throw QPID_POSIX_ERROR(rc);
+ return std::string(dispName) + ":" + std::string(servName);
+
+ } else {
+ if (int rc=::getnameinfo((::sockaddr*)&name, namelen, dispName, sizeof(dispName), 0, 0, NI_NUMERICHOST) != 0)
+ throw QPID_POSIX_ERROR(rc);
+ return dispName;
+ }
}
-uint16_t getLocalPort(int fd)
+std::string getService(int fd, bool local)
{
- ::sockaddr_storage name_s; // big enough for any socket address
- ::sockaddr* name = (::sockaddr*)&name_s;
- ::socklen_t namelen = sizeof(name_s);
+ ::sockaddr_storage name; // big enough for any socket address
+ ::socklen_t namelen = sizeof(name);
+
+ int result = -1;
+ if (local) {
+ result = ::getsockname(fd, (::sockaddr*)&name, &namelen);
+ } else {
+ result = ::getpeername(fd, (::sockaddr*)&name, &namelen);
+ }
- QPID_POSIX_CHECK( ::getsockname(fd, name, &namelen) );
+ QPID_POSIX_CHECK(result);
- return SocketAddress::getPort(name);
+ char servName[NI_MAXSERV];
+ if (int rc=::getnameinfo((::sockaddr*)&name, namelen, 0, 0,
+ servName, sizeof(servName),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ throw QPID_POSIX_ERROR(rc);
+ return servName;
}
}
@@ -89,11 +119,6 @@ void Socket::createSocket(const SocketAddress& sa) const
try {
if (nonblocking) setNonblocking();
if (nodelay) setTcpNoDelay();
- if (getAddrInfo(sa).ai_family == AF_INET6) {
- int flag = 1;
- int result = ::setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&flag, sizeof(flag));
- QPID_POSIX_CHECK(result);
- }
} catch (std::exception&) {
::close(s);
socket = -1;
@@ -101,18 +126,13 @@ void Socket::createSocket(const SocketAddress& sa) const
}
}
-Socket* Socket::createSameTypeSocket() const {
- int& socket = impl->fd;
- // Socket currently has no actual socket attached
- if (socket == -1)
- return new Socket;
-
- ::sockaddr_storage sa;
- ::socklen_t salen = sizeof(sa);
- QPID_POSIX_CHECK(::getsockname(socket, (::sockaddr*)&sa, &salen));
- int s = ::socket(sa.ss_family, SOCK_STREAM, 0); // Currently only work with SOCK_STREAM
- if (s < 0) throw QPID_POSIX_ERROR(errno);
- return new Socket(new IOHandlePrivate(s));
+void Socket::setTimeout(const Duration& interval) const
+{
+ const int& socket = impl->fd;
+ struct timeval tv;
+ toTimeval(tv, interval);
+ setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+ setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
}
void Socket::setNonblocking() const {
@@ -129,27 +149,20 @@ void Socket::setTcpNoDelay() const
nodelay = true;
if (socket != -1) {
int flag = 1;
- int result = ::setsockopt(impl->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));
+ int result = setsockopt(impl->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));
QPID_POSIX_CHECK(result);
}
}
-void Socket::connect(const std::string& host, const std::string& port) const
+void Socket::connect(const std::string& host, uint16_t port) const
{
- SocketAddress sa(host, port);
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
connect(sa);
}
void Socket::connect(const SocketAddress& addr) const
{
- // The display name for an outbound connection needs to be the name that was specified
- // for the address rather than a resolved IP address as we don't know which of
- // the IP addresses is actually the one that will be connected to.
- peername = addr.asString(false);
-
- // However the string we compare with the local port must be numeric or it might not
- // match when it should as getLocalAddress() will always be numeric
- std::string connectname = addr.asString();
+ connectname = addr.asString();
createSocket(addr);
@@ -157,24 +170,7 @@ void Socket::connect(const SocketAddress& addr) const
// TODO the correct thing to do here is loop on failure until you've used all the returned addresses
if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) < 0) &&
(errno != EINPROGRESS)) {
- throw Exception(QPID_MSG(strError(errno) << ": " << peername));
- }
- // When connecting to a port on the same host which no longer has
- // a process associated with it, the OS occasionally chooses the
- // remote port (which is unoccupied) as the port to bind the local
- // end of the socket, resulting in a "circular" connection.
- //
- // This seems like something the OS should prevent but I have
- // confirmed that sporadic hangs in
- // cluster_tests.LongTests.test_failover on RHEL5 are caused by
- // such a circular connection.
- //
- // Raise an error if we see such a connection, since we know there is
- // no listener on the peer address.
- //
- if (getLocalAddress() == connectname) {
- close();
- throw Exception(QPID_MSG("Connection refused: " << peername));
+ throw Exception(QPID_MSG(strError(errno) << ": " << connectname));
}
}
@@ -187,9 +183,9 @@ Socket::close() const
socket = -1;
}
-int Socket::listen(const std::string& host, const std::string& port, int backlog) const
+int Socket::listen(uint16_t port, int backlog) const
{
- SocketAddress sa(host, port);
+ SocketAddress sa("", boost::lexical_cast<std::string>(port));
return listen(sa, backlog);
}
@@ -199,24 +195,26 @@ int Socket::listen(const SocketAddress& sa, int backlog) const
const int& socket = impl->fd;
int yes=1;
- QPID_POSIX_CHECK(::setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)));
+ QPID_POSIX_CHECK(setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)));
if (::bind(socket, getAddrInfo(sa).ai_addr, getAddrInfo(sa).ai_addrlen) < 0)
throw Exception(QPID_MSG("Can't bind to port " << sa.asString() << ": " << strError(errno)));
if (::listen(socket, backlog) < 0)
throw Exception(QPID_MSG("Can't listen on port " << sa.asString() << ": " << strError(errno)));
- return getLocalPort(socket);
+ struct sockaddr_in name;
+ socklen_t namelen = sizeof(name);
+ if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0)
+ throw QPID_POSIX_ERROR(errno);
+
+ return ntohs(name.sin_port);
}
Socket* Socket::accept() const
{
int afd = ::accept(impl->fd, 0, 0);
- if ( afd >= 0) {
- Socket* s = new Socket(new IOHandlePrivate(afd));
- s->localname = localname;
- return s;
- }
+ if ( afd >= 0)
+ return new Socket(new IOHandlePrivate(afd));
else if (errno == EAGAIN)
return 0;
else throw QPID_POSIX_ERROR(errno);
@@ -232,20 +230,37 @@ int Socket::write(const void *buf, size_t count) const
return ::write(impl->fd, buf, count);
}
+std::string Socket::getSockname() const
+{
+ return getName(impl->fd, true);
+}
+
+std::string Socket::getPeername() const
+{
+ return getName(impl->fd, false);
+}
+
std::string Socket::getPeerAddress() const
{
- if (peername.empty()) {
- peername = getName(impl->fd, false);
+ if (connectname.empty()) {
+ connectname = getName(impl->fd, false, true);
}
- return peername;
+ return connectname;
}
std::string Socket::getLocalAddress() const
{
- if (localname.empty()) {
- localname = getName(impl->fd, true);
- }
- return localname;
+ return getName(impl->fd, true, true);
+}
+
+uint16_t Socket::getLocalPort() const
+{
+ return std::atoi(getService(impl->fd, true).c_str());
+}
+
+uint16_t Socket::getRemotePort() const
+{
+ return std::atoi(getService(impl->fd, true).c_str());
}
int Socket::getError() const
diff --git a/cpp/src/qpid/sys/posix/SocketAddress.cpp b/cpp/src/qpid/sys/posix/SocketAddress.cpp
index 077942ef2f..8f5f29d793 100644
--- a/cpp/src/qpid/sys/posix/SocketAddress.cpp
+++ b/cpp/src/qpid/sys/posix/SocketAddress.cpp
@@ -21,13 +21,11 @@
#include "qpid/sys/SocketAddress.h"
-#include "qpid/Exception.h"
-#include "qpid/Msg.h"
+#include "qpid/sys/posix/check.h"
#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
#include <string.h>
+#include <netdb.h>
namespace qpid {
namespace sys {
@@ -48,9 +46,15 @@ SocketAddress::SocketAddress(const SocketAddress& sa) :
SocketAddress& SocketAddress::operator=(const SocketAddress& sa)
{
- SocketAddress temp(sa);
+ if (&sa != this) {
+ host = sa.host;
+ port = sa.port;
- std::swap(temp, *this);
+ if (addrInfo) {
+ ::freeaddrinfo(addrInfo);
+ addrInfo = 0;
+ }
+ }
return *this;
}
@@ -61,61 +65,9 @@ SocketAddress::~SocketAddress()
}
}
-std::string SocketAddress::asString(::sockaddr const * const addr, size_t addrlen)
-{
- char servName[NI_MAXSERV];
- char dispName[NI_MAXHOST];
- if (int rc=::getnameinfo(addr, addrlen,
- dispName, sizeof(dispName),
- servName, sizeof(servName),
- NI_NUMERICHOST | NI_NUMERICSERV) != 0)
- throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
- std::string s;
- switch (addr->sa_family) {
- case AF_INET: s += dispName; break;
- case AF_INET6: s += "["; s += dispName; s+= "]"; break;
- default: throw Exception(QPID_MSG("Unexpected socket type"));
- }
- s += ":";
- s += servName;
- return s;
-}
-
-uint16_t SocketAddress::getPort(::sockaddr const * const addr)
+std::string SocketAddress::asString() const
{
- switch (addr->sa_family) {
- case AF_INET: return ntohs(((::sockaddr_in*)addr)->sin_port);
- case AF_INET6: return ntohs(((::sockaddr_in6*)addr)->sin6_port);
- default:throw Exception(QPID_MSG("Unexpected socket type"));
- }
-}
-
-std::string SocketAddress::asString(bool numeric) const
-{
- if (!numeric)
- return host + ":" + port;
- // Canonicalise into numeric id
- const ::addrinfo& ai = getAddrInfo(*this);
-
- return asString(ai.ai_addr, ai.ai_addrlen);
-}
-
-bool SocketAddress::nextAddress() {
- bool r = currentAddrInfo->ai_next != 0;
- if (r)
- currentAddrInfo = currentAddrInfo->ai_next;
- return r;
-}
-
-void SocketAddress::setAddrInfoPort(uint16_t port) {
- if (!currentAddrInfo) return;
-
- ::addrinfo& ai = *currentAddrInfo;
- switch (ai.ai_family) {
- case AF_INET: ((::sockaddr_in*)ai.ai_addr)->sin_port = htons(port); return;
- case AF_INET6:((::sockaddr_in6*)ai.ai_addr)->sin6_port = htons(port); return;
- default: throw Exception(QPID_MSG("Unexpected socket type"));
- }
+ return host + ":" + port;
}
const ::addrinfo& getAddrInfo(const SocketAddress& sa)
@@ -123,8 +75,7 @@ const ::addrinfo& getAddrInfo(const SocketAddress& sa)
if (!sa.addrInfo) {
::addrinfo hints;
::memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for
- hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6
+ hints.ai_family = AF_INET; // Change this to support IPv6
hints.ai_socktype = SOCK_STREAM;
const char* node = 0;
@@ -137,11 +88,10 @@ const ::addrinfo& getAddrInfo(const SocketAddress& sa)
int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo);
if (n != 0)
- throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n)));
- sa.currentAddrInfo = sa.addrInfo;
+ throw Exception(QPID_MSG("Cannot resolve " << sa.host << ": " << ::gai_strerror(n)));
}
- return *sa.currentAddrInfo;
+ return *sa.addrInfo;
}
}}
diff --git a/cpp/src/qpid/sys/posix/Thread.cpp b/cpp/src/qpid/sys/posix/Thread.cpp
index a1d6396763..b466733260 100644
--- a/cpp/src/qpid/sys/posix/Thread.cpp
+++ b/cpp/src/qpid/sys/posix/Thread.cpp
@@ -37,8 +37,7 @@ void* runRunnable(void* p)
}
}
-class ThreadPrivate {
-public:
+struct ThreadPrivate {
pthread_t thread;
ThreadPrivate(Runnable* runnable) {
diff --git a/cpp/src/qpid/sys/posix/Time.cpp b/cpp/src/qpid/sys/posix/Time.cpp
index 9661f0c5e8..b3858279b4 100644
--- a/cpp/src/qpid/sys/posix/Time.cpp
+++ b/cpp/src/qpid/sys/posix/Time.cpp
@@ -27,7 +27,6 @@
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
-#include <iomanip>
namespace {
int64_t max_abstime() { return std::numeric_limits<int64_t>::max(); }
@@ -104,12 +103,6 @@ void outputFormattedNow(std::ostream& o) {
o << " ";
}
-void outputHiresNow(std::ostream& o) {
- ::timespec time;
- ::clock_gettime(CLOCK_REALTIME, &time);
- o << time.tv_sec << "." << std::setw(9) << std::setfill('0') << time.tv_nsec << "s ";
-}
-
void sleep(int secs) {
::sleep(secs);
}
diff --git a/cpp/src/qpid/sys/rdma/RdmaIO.cpp b/cpp/src/qpid/sys/rdma/RdmaIO.cpp
index 78bcdec68e..c80c94cba6 100644
--- a/cpp/src/qpid/sys/rdma/RdmaIO.cpp
+++ b/cpp/src/qpid/sys/rdma/RdmaIO.cpp
@@ -140,8 +140,8 @@ namespace Rdma {
// Prepost recv buffers before we go any further
qp->allocateRecvBuffers(recvBufferCount, bufferSize+FrameHeaderSize);
- // Create xmit buffers, reserve space for frame header.
- qp->createSendBuffers(xmitBufferCount, bufferSize, FrameHeaderSize);
+ // Create xmit buffers
+ qp->createSendBuffers(xmitBufferCount, bufferSize+FrameHeaderSize);
}
AsynchIO::~AsynchIO() {
@@ -210,14 +210,12 @@ namespace Rdma {
}
break;
case 1:
- if (!buff)
- buff = getSendBuffer();
+ Buffer* ob = buff ? buff : getSendBuffer();
// Add FrameHeader after frame data
FrameHeader header(credit);
- assert(buff->dataCount() <= buff->byteCount()); // ensure app data doesn't impinge on reserved space.
- ::memcpy(buff->bytes()+buff->dataCount(), &header, FrameHeaderSize);
- buff->dataCount(buff->dataCount()+FrameHeaderSize);
- qp->postSend(buff);
+ ::memcpy(ob->bytes()+ob->dataCount(), &header, FrameHeaderSize);
+ ob->dataCount(ob->dataCount()+FrameHeaderSize);
+ qp->postSend(ob);
break;
}
}
diff --git a/cpp/src/qpid/sys/rdma/rdma_wrap.cpp b/cpp/src/qpid/sys/rdma/rdma_wrap.cpp
index efe454c5be..6d38c42502 100644
--- a/cpp/src/qpid/sys/rdma/rdma_wrap.cpp
+++ b/cpp/src/qpid/sys/rdma/rdma_wrap.cpp
@@ -50,9 +50,8 @@ namespace Rdma {
return count;
}
- Buffer::Buffer(uint32_t lkey, char* bytes, const int32_t byteCount,
- const int32_t reserve) :
- bufferSize(byteCount + reserve), reserved(reserve)
+ Buffer::Buffer(uint32_t lkey, char* bytes, const int32_t byteCount) :
+ bufferSize(byteCount)
{
sge.addr = (uintptr_t) bytes;
sge.length = 0;
@@ -164,21 +163,21 @@ namespace Rdma {
}
// Create buffers to use for writing
- void QueuePair::createSendBuffers(int sendBufferCount, int bufferSize, int reserved)
+ void QueuePair::createSendBuffers(int sendBufferCount, int bufferSize)
{
assert(!smr);
// Round up buffersize to cacheline (64 bytes)
- int dataLength = (bufferSize+reserved+63) & (~63);
+ bufferSize = (bufferSize+63) & (~63);
// Allocate memory block for all receive buffers
- char* mem = new char [sendBufferCount * dataLength];
- smr = regMr(pd.get(), mem, sendBufferCount * dataLength, ::IBV_ACCESS_LOCAL_WRITE);
+ char* mem = new char [sendBufferCount * bufferSize];
+ smr = regMr(pd.get(), mem, sendBufferCount * bufferSize, ::IBV_ACCESS_LOCAL_WRITE);
sendBuffers.reserve(sendBufferCount);
freeBuffers.reserve(sendBufferCount);
for (int i = 0; i<sendBufferCount; ++i) {
// Allocate xmit buffer
- sendBuffers.push_back(Buffer(smr->lkey, &mem[i*dataLength], bufferSize, reserved));
+ sendBuffers.push_back(Buffer(smr->lkey, &mem[i*bufferSize], bufferSize));
freeBuffers.push_back(i);
}
}
diff --git a/cpp/src/qpid/sys/rdma/rdma_wrap.h b/cpp/src/qpid/sys/rdma/rdma_wrap.h
index 8e3429027b..28bddd2165 100644
--- a/cpp/src/qpid/sys/rdma/rdma_wrap.h
+++ b/cpp/src/qpid/sys/rdma/rdma_wrap.h
@@ -57,9 +57,8 @@ namespace Rdma {
void dataCount(int32_t);
private:
- Buffer(uint32_t lkey, char* bytes, const int32_t byteCount, const int32_t reserve=0);
+ Buffer(uint32_t lkey, char* bytes, const int32_t byteCount);
int32_t bufferSize;
- int32_t reserved; // for framing header
::ibv_sge sge;
};
@@ -67,9 +66,8 @@ namespace Rdma {
return (char*) sge.addr;
}
- /** return the number of bytes available for application data */
inline int32_t Buffer::byteCount() const {
- return bufferSize - reserved;
+ return bufferSize;
}
inline int32_t Buffer::dataCount() const {
@@ -77,8 +75,6 @@ namespace Rdma {
}
inline void Buffer::dataCount(int32_t s) {
- // catch any attempt to overflow a buffer
- assert(s <= bufferSize + reserved);
sge.length = s;
}
@@ -140,7 +136,7 @@ namespace Rdma {
typedef boost::intrusive_ptr<QueuePair> intrusive_ptr;
// Create a buffers to use for writing
- void createSendBuffers(int sendBufferCount, int dataSize, int headerSize);
+ void createSendBuffers(int sendBufferCount, int bufferSize);
// Get a send buffer
Buffer* getSendBuffer();
diff --git a/cpp/src/qpid/sys/ssl/SslHandler.h b/cpp/src/qpid/sys/ssl/SslHandler.h
index 400fa317fd..a340109966 100644
--- a/cpp/src/qpid/sys/ssl/SslHandler.h
+++ b/cpp/src/qpid/sys/ssl/SslHandler.h
@@ -35,7 +35,7 @@ namespace sys {
namespace ssl {
class SslIO;
-struct SslIOBufferBase;
+class SslIOBufferBase;
class SslSocket;
class SslHandler : public OutputControl {
diff --git a/cpp/src/qpid/sys/ssl/SslIo.cpp b/cpp/src/qpid/sys/ssl/SslIo.cpp
index 734ebb483a..a58a137473 100644
--- a/cpp/src/qpid/sys/ssl/SslIo.cpp
+++ b/cpp/src/qpid/sys/ssl/SslIo.cpp
@@ -117,7 +117,7 @@ void SslAcceptor::readable(DispatchHandle& h) {
SslConnector::SslConnector(const SslSocket& s,
Poller::shared_ptr poller,
std::string hostname,
- std::string port,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb) :
DispatchHandle(s,
diff --git a/cpp/src/qpid/sys/ssl/SslIo.h b/cpp/src/qpid/sys/ssl/SslIo.h
index 8785852c24..53ac69d8d6 100644
--- a/cpp/src/qpid/sys/ssl/SslIo.h
+++ b/cpp/src/qpid/sys/ssl/SslIo.h
@@ -73,7 +73,7 @@ public:
SslConnector(const SslSocket& socket,
Poller::shared_ptr poller,
std::string hostname,
- std::string port,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb = 0);
diff --git a/cpp/src/qpid/sys/ssl/SslSocket.cpp b/cpp/src/qpid/sys/ssl/SslSocket.cpp
index f7483a220c..01e2658877 100644
--- a/cpp/src/qpid/sys/ssl/SslSocket.cpp
+++ b/cpp/src/qpid/sys/ssl/SslSocket.cpp
@@ -158,7 +158,7 @@ void SslSocket::setNonblocking() const
PR_SetSocketOption(socket, &option);
}
-void SslSocket::connect(const std::string& host, const std::string& port) const
+void SslSocket::connect(const std::string& host, uint16_t port) const
{
std::stringstream namestream;
namestream << host << ":" << port;
@@ -180,7 +180,7 @@ void SslSocket::connect(const std::string& host, const std::string& port) const
PRHostEnt hostEntry;
PR_CHECK(PR_GetHostByName(host.data(), hostBuffer, PR_NETDB_BUF_SIZE, &hostEntry));
PRNetAddr address;
- int value = PR_EnumerateHostEnt(0, &hostEntry, boost::lexical_cast<PRUint16>(port), &address);
+ int value = PR_EnumerateHostEnt(0, &hostEntry, port, &address);
if (value < 0) {
throw Exception(QPID_MSG("Error getting address for host: " << ErrorString()));
} else if (value == 0) {
diff --git a/cpp/src/qpid/sys/ssl/SslSocket.h b/cpp/src/qpid/sys/ssl/SslSocket.h
index 993859495b..25712c98d5 100644
--- a/cpp/src/qpid/sys/ssl/SslSocket.h
+++ b/cpp/src/qpid/sys/ssl/SslSocket.h
@@ -53,7 +53,7 @@ public:
* NSSInit().*/
void setCertName(const std::string& certName);
- void connect(const std::string& host, const std::string& port) const;
+ void connect(const std::string& host, uint16_t port) const;
void close() const;
diff --git a/cpp/src/qpid/sys/windows/AsynchIO.cpp b/cpp/src/qpid/sys/windows/AsynchIO.cpp
index 30378d4c5f..38d8842521 100644
--- a/cpp/src/qpid/sys/windows/AsynchIO.cpp
+++ b/cpp/src/qpid/sys/windows/AsynchIO.cpp
@@ -30,7 +30,6 @@
#include "qpid/log/Statement.h"
#include "qpid/sys/windows/check.h"
-#include "qpid/sys/windows/mingw32_compat.h"
#include <boost/thread/once.hpp>
@@ -47,13 +46,16 @@ namespace {
/*
* The function pointers for AcceptEx and ConnectEx need to be looked up
- * at run time.
+ * at run time. Make sure this is done only once.
*/
-const LPFN_ACCEPTEX lookUpAcceptEx(const qpid::sys::Socket& s) {
- SOCKET h = toSocketHandle(s);
+boost::once_flag lookUpAcceptExOnce = BOOST_ONCE_INIT;
+LPFN_ACCEPTEX fnAcceptEx = 0;
+typedef void (*lookUpFunc)(const qpid::sys::Socket &);
+
+void lookUpAcceptEx() {
+ SOCKET h = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
GUID guidAcceptEx = WSAID_ACCEPTEX;
DWORD dwBytes = 0;
- LPFN_ACCEPTEX fnAcceptEx;
WSAIoctl(h,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&guidAcceptEx,
@@ -63,9 +65,9 @@ const LPFN_ACCEPTEX lookUpAcceptEx(const qpid::sys::Socket& s) {
&dwBytes,
NULL,
NULL);
+ closesocket(h);
if (fnAcceptEx == 0)
throw qpid::Exception(QPID_MSG("Failed to look up AcceptEx"));
- return fnAcceptEx;
}
}
@@ -92,15 +94,18 @@ private:
AsynchAcceptor::Callback acceptedCallback;
const Socket& socket;
- const LPFN_ACCEPTEX fnAcceptEx;
};
AsynchAcceptor::AsynchAcceptor(const Socket& s, Callback callback)
: acceptedCallback(callback),
- socket(s),
- fnAcceptEx(lookUpAcceptEx(s)) {
+ socket(s) {
s.setNonblocking();
+#if (BOOST_VERSION >= 103500) /* boost 1.35 or later reversed the args */
+ boost::call_once(lookUpAcceptExOnce, lookUpAcceptEx);
+#else
+ boost::call_once(lookUpAcceptEx, lookUpAcceptExOnce);
+#endif
}
AsynchAcceptor::~AsynchAcceptor()
@@ -109,8 +114,7 @@ AsynchAcceptor::~AsynchAcceptor()
}
void AsynchAcceptor::start(Poller::shared_ptr poller) {
- PollerHandle ph = PollerHandle(socket);
- poller->monitorHandle(ph, Poller::INPUT);
+ poller->monitorHandle(PollerHandle(socket), Poller::INPUT);
restart ();
}
@@ -118,26 +122,25 @@ void AsynchAcceptor::restart(void) {
DWORD bytesReceived = 0; // Not used, needed for AcceptEx API
AsynchAcceptResult *result = new AsynchAcceptResult(acceptedCallback,
this,
- socket);
+ toSocketHandle(socket));
BOOL status;
- status = fnAcceptEx(toSocketHandle(socket),
- toSocketHandle(*result->newSocket),
- result->addressBuffer,
- 0,
- AsynchAcceptResult::SOCKADDRMAXLEN,
- AsynchAcceptResult::SOCKADDRMAXLEN,
- &bytesReceived,
- result->overlapped());
+ status = ::fnAcceptEx(toSocketHandle(socket),
+ toSocketHandle(*result->newSocket),
+ result->addressBuffer,
+ 0,
+ AsynchAcceptResult::SOCKADDRMAXLEN,
+ AsynchAcceptResult::SOCKADDRMAXLEN,
+ &bytesReceived,
+ result->overlapped());
QPID_WINDOWS_CHECK_ASYNC_START(status);
}
AsynchAcceptResult::AsynchAcceptResult(AsynchAcceptor::Callback cb,
AsynchAcceptor *acceptor,
- const Socket& listener)
- : callback(cb), acceptor(acceptor),
- listener(toSocketHandle(listener)),
- newSocket(listener.createSameTypeSocket()) {
+ SOCKET listener)
+ : callback(cb), acceptor(acceptor), listener(listener) {
+ newSocket.reset (new Socket());
}
void AsynchAcceptResult::success(size_t /*bytesTransferred*/) {
@@ -151,7 +154,7 @@ void AsynchAcceptResult::success(size_t /*bytesTransferred*/) {
delete this;
}
-void AsynchAcceptResult::failure(int /*status*/) {
+void AsynchAcceptResult::failure(int status) {
//if (status != WSA_OPERATION_ABORTED)
// Can there be anything else? ;
delete this;
@@ -170,20 +173,20 @@ private:
FailedCallback failCallback;
const Socket& socket;
const std::string hostname;
- const std::string port;
+ const uint16_t port;
public:
AsynchConnector(const Socket& socket,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb = 0);
void start(Poller::shared_ptr poller);
};
AsynchConnector::AsynchConnector(const Socket& sock,
- const std::string& hname,
- const std::string& p,
+ std::string hname,
+ uint16_t p,
ConnectedCallback connCb,
FailedCallback failCb) :
connCallback(connCb), failCallback(failCb), socket(sock),
@@ -213,8 +216,8 @@ AsynchAcceptor* AsynchAcceptor::create(const Socket& s,
}
AsynchConnector* qpid::sys::AsynchConnector::create(const Socket& s,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb)
{
@@ -407,9 +410,8 @@ void AsynchIO::queueForDeletion() {
}
void AsynchIO::start(Poller::shared_ptr poller0) {
- PollerHandle ph = PollerHandle(socket);
poller = poller0;
- poller->monitorHandle(ph, Poller::INPUT);
+ poller->monitorHandle(PollerHandle(socket), Poller::INPUT);
if (writeQueue.size() > 0) // Already have data queued for write
notifyPendingWrite();
startReading();
@@ -582,6 +584,7 @@ void AsynchIO::notifyIdle(void) {
void AsynchIO::startWrite(AsynchIO::BufferBase* buff) {
writeInProgress = true;
InterlockedIncrement(&opsInProgress);
+ int writeCount = buff->byteCount-buff->dataCount;
AsynchWriteResult *result =
new AsynchWriteResult(boost::bind(&AsynchIO::completion, this, _1),
buff,
diff --git a/cpp/src/qpid/sys/windows/AsynchIoResult.h b/cpp/src/qpid/sys/windows/AsynchIoResult.h
index 27e4c22138..66c89efc11 100755
--- a/cpp/src/qpid/sys/windows/AsynchIoResult.h
+++ b/cpp/src/qpid/sys/windows/AsynchIoResult.h
@@ -83,22 +83,22 @@ class AsynchAcceptResult : public AsynchResult {
public:
AsynchAcceptResult(qpid::sys::AsynchAcceptor::Callback cb,
AsynchAcceptor *acceptor,
- const qpid::sys::Socket& listener);
+ SOCKET listener);
virtual void success (size_t bytesTransferred);
virtual void failure (int error);
private:
virtual void complete(void) {} // No-op for this class.
+ std::auto_ptr<qpid::sys::Socket> newSocket;
qpid::sys::AsynchAcceptor::Callback callback;
AsynchAcceptor *acceptor;
SOCKET listener;
- std::auto_ptr<qpid::sys::Socket> newSocket;
// AcceptEx needs a place to write the local and remote addresses
// when accepting the connection. Place those here; get enough for
// IPv6 addresses, even if the socket is IPv4.
- enum { SOCKADDRMAXLEN = sizeof(sockaddr_in6) + 16,
+ enum { SOCKADDRMAXLEN = sizeof sockaddr_in6 + 16,
SOCKADDRBUFLEN = 2 * SOCKADDRMAXLEN };
char addressBuffer[SOCKADDRBUFLEN];
};
diff --git a/cpp/src/qpid/sys/windows/IocpPoller.cpp b/cpp/src/qpid/sys/windows/IocpPoller.cpp
index 1805dd2cd8..d326ab02ac 100755
--- a/cpp/src/qpid/sys/windows/IocpPoller.cpp
+++ b/cpp/src/qpid/sys/windows/IocpPoller.cpp
@@ -152,9 +152,9 @@ void Poller::monitorHandle(PollerHandle& handle, Direction dir) {
}
// All no-ops...
-void Poller::unmonitorHandle(PollerHandle& /*handle*/, Direction /*dir*/) {}
-void Poller::registerHandle(PollerHandle& /*handle*/) {}
-void Poller::unregisterHandle(PollerHandle& /*handle*/) {}
+void Poller::unmonitorHandle(PollerHandle& handle, Direction dir) {}
+void Poller::registerHandle(PollerHandle& handle) {}
+void Poller::unregisterHandle(PollerHandle& handle) {}
Poller::Event Poller::wait(Duration timeout) {
DWORD timeoutMs = 0;
diff --git a/cpp/src/qpid/sys/windows/Shlib.cpp b/cpp/src/qpid/sys/windows/Shlib.cpp
index ba18747eb4..38027de93f 100644
--- a/cpp/src/qpid/sys/windows/Shlib.cpp
+++ b/cpp/src/qpid/sys/windows/Shlib.cpp
@@ -44,8 +44,7 @@ void Shlib::unload() {
}
void* Shlib::getSymbol(const char* name) {
- // Double cast avoids warning about casting function pointer to object
- void *sym = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(GetProcAddress(static_cast<HMODULE>(handle), name)));
+ void* sym = GetProcAddress(static_cast<HMODULE>(handle), name);
if (sym == NULL)
throw QPID_WINDOWS_ERROR(GetLastError());
return sym;
diff --git a/cpp/src/qpid/sys/windows/Socket.cpp b/cpp/src/qpid/sys/windows/Socket.cpp
index 1fa4768329..11fb8b4133 100644..100755
--- a/cpp/src/qpid/sys/windows/Socket.cpp
+++ b/cpp/src/qpid/sys/windows/Socket.cpp
@@ -20,18 +20,19 @@
*/
#include "qpid/sys/Socket.h"
-
#include "qpid/sys/SocketAddress.h"
-#include "qpid/sys/windows/check.h"
#include "qpid/sys/windows/IoHandlePrivate.h"
+#include "qpid/sys/windows/check.h"
+#include "qpid/sys/Time.h"
-// Ensure we get all of winsock2.h
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
+#include <cstdlib>
+#include <string.h>
#include <winsock2.h>
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
+
// Need to initialize WinSock. Ideally, this would be a singleton or embedded
// in some one-time initialization function. I tried boost singleton and could
// not get it to compile (and others located in google had the same problem).
@@ -83,30 +84,53 @@ namespace sys {
namespace {
-std::string getName(SOCKET fd, bool local)
+std::string getName(SOCKET fd, bool local, bool includeService = false)
{
- ::sockaddr_storage name_s; // big enough for any socket address
- ::sockaddr* name = (::sockaddr*)&name_s;
- ::socklen_t namelen = sizeof(name_s);
-
+ sockaddr_in name; // big enough for any socket address
+ socklen_t namelen = sizeof(name);
if (local) {
- QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen));
+ QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen));
} else {
- QPID_WINSOCK_CHECK(::getpeername(fd, name, &namelen));
+ QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen));
}
- return SocketAddress::asString(name, namelen);
+ char servName[NI_MAXSERV];
+ char dispName[NI_MAXHOST];
+ if (includeService) {
+ if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
+ dispName, sizeof(dispName),
+ servName, sizeof(servName),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
+ return std::string(dispName) + ":" + std::string(servName);
+ } else {
+ if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
+ dispName, sizeof(dispName),
+ 0, 0,
+ NI_NUMERICHOST) != 0)
+ throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
+ return dispName;
+ }
}
-uint16_t getLocalPort(int fd)
+std::string getService(SOCKET fd, bool local)
{
- ::sockaddr_storage name_s; // big enough for any socket address
- ::sockaddr* name = (::sockaddr*)&name_s;
- ::socklen_t namelen = sizeof(name_s);
-
- QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen));
+ sockaddr_in name; // big enough for any socket address
+ socklen_t namelen = sizeof(name);
+
+ if (local) {
+ QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen));
+ } else {
+ QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen));
+ }
- return SocketAddress::getPort(name);
+ char servName[NI_MAXSERV];
+ if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
+ 0, 0,
+ servName, sizeof(servName),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
+ return servName;
}
} // namespace
@@ -114,7 +138,13 @@ Socket::Socket() :
IOHandle(new IOHandlePrivate),
nonblocking(false),
nodelay(false)
-{}
+{
+ SOCKET& socket = impl->fd;
+ if (socket != INVALID_SOCKET) Socket::close();
+ SOCKET s = ::socket (PF_INET, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError());
+ socket = s;
+}
Socket::Socket(IOHandlePrivate* h) :
IOHandle(h),
@@ -122,7 +152,8 @@ Socket::Socket(IOHandlePrivate* h) :
nodelay(false)
{}
-void Socket::createSocket(const SocketAddress& sa) const
+void
+Socket::createSocket(const SocketAddress& sa) const
{
SOCKET& socket = impl->fd;
if (socket != INVALID_SOCKET) Socket::close();
@@ -137,24 +168,24 @@ void Socket::createSocket(const SocketAddress& sa) const
if (nonblocking) setNonblocking();
if (nodelay) setTcpNoDelay();
} catch (std::exception&) {
- ::closesocket(s);
+ closesocket(s);
socket = INVALID_SOCKET;
throw;
}
}
-Socket* Socket::createSameTypeSocket() const {
- SOCKET& socket = impl->fd;
- // Socket currently has no actual socket attached
- if (socket == INVALID_SOCKET)
- return new Socket;
-
- ::sockaddr_storage sa;
- ::socklen_t salen = sizeof(sa);
- QPID_WINSOCK_CHECK(::getsockname(socket, (::sockaddr*)&sa, &salen));
- SOCKET s = ::socket(sa.ss_family, SOCK_STREAM, 0); // Currently only work with SOCK_STREAM
- if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError());
- return new Socket(new IOHandlePrivate(s));
+void Socket::setTimeout(const Duration& interval) const
+{
+ const SOCKET& socket = impl->fd;
+ int64_t nanosecs = interval;
+ nanosecs /= (1000 * 1000); // nsecs -> usec -> msec
+ int msec = 0;
+ if (nanosecs > std::numeric_limits<int>::max())
+ msec = std::numeric_limits<int>::max();
+ else
+ msec = static_cast<int>(nanosecs);
+ setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&msec, sizeof(msec));
+ setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&msec, sizeof(msec));
}
void Socket::setNonblocking() const {
@@ -162,25 +193,30 @@ void Socket::setNonblocking() const {
QPID_WINSOCK_CHECK(ioctlsocket(impl->fd, FIONBIO, &nonblock));
}
-void Socket::connect(const std::string& host, const std::string& port) const
+void Socket::connect(const std::string& host, uint16_t port) const
{
- SocketAddress sa(host, port);
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
connect(sa);
}
void
Socket::connect(const SocketAddress& addr) const
{
- peername = addr.asString(false);
-
- createSocket(addr);
-
const SOCKET& socket = impl->fd;
- int err;
+ const addrinfo *addrs = &(getAddrInfo(addr));
+ int error = 0;
WSASetLastError(0);
- if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) != 0) &&
- ((err = ::WSAGetLastError()) != WSAEWOULDBLOCK))
- throw qpid::Exception(QPID_MSG(strError(err) << ": " << peername));
+ while (addrs != 0) {
+ if ((::connect(socket, addrs->ai_addr, addrs->ai_addrlen) == 0) ||
+ (WSAGetLastError() == WSAEWOULDBLOCK))
+ break;
+ // Error... save this error code and see if there are other address
+ // to try before throwing the exception.
+ error = WSAGetLastError();
+ addrs = addrs->ai_next;
+ }
+ if (error)
+ throw qpid::Exception(QPID_MSG(strError(error) << ": " << connectname));
}
void
@@ -211,26 +247,24 @@ int Socket::read(void *buf, size_t count) const
return received;
}
-int Socket::listen(const std::string& host, const std::string& port, int backlog) const
-{
- SocketAddress sa(host, port);
- return listen(sa, backlog);
-}
-
-int Socket::listen(const SocketAddress& addr, int backlog) const
+int Socket::listen(uint16_t port, int backlog) const
{
- createSocket(addr);
-
const SOCKET& socket = impl->fd;
BOOL yes=1;
QPID_WINSOCK_CHECK(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)));
-
- if (::bind(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) == SOCKET_ERROR)
- throw Exception(QPID_MSG("Can't bind to " << addr.asString() << ": " << strError(WSAGetLastError())));
+ struct sockaddr_in name;
+ memset(&name, 0, sizeof(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)) == SOCKET_ERROR)
+ throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(WSAGetLastError())));
if (::listen(socket, backlog) == SOCKET_ERROR)
- throw Exception(QPID_MSG("Can't listen on " <<addr.asString() << ": " << strError(WSAGetLastError())));
-
- return getLocalPort(socket);
+ throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(WSAGetLastError())));
+
+ socklen_t namelen = sizeof(name);
+ QPID_WINSOCK_CHECK(::getsockname(socket, (struct sockaddr*)&name, &namelen));
+ return ntohs(name.sin_port);
}
Socket* Socket::accept() const
@@ -243,20 +277,36 @@ Socket* Socket::accept() const
else throw QPID_WINDOWS_ERROR(WSAGetLastError());
}
+std::string Socket::getSockname() const
+{
+ return getName(impl->fd, true);
+}
+
+std::string Socket::getPeername() const
+{
+ return getName(impl->fd, false);
+}
+
std::string Socket::getPeerAddress() const
{
- if (peername.empty()) {
- peername = getName(impl->fd, false);
- }
- return peername;
+ if (!connectname.empty())
+ return std::string (connectname);
+ return getName(impl->fd, false, true);
}
std::string Socket::getLocalAddress() const
{
- if (localname.empty()) {
- localname = getName(impl->fd, true);
- }
- return localname;
+ return getName(impl->fd, true, true);
+}
+
+uint16_t Socket::getLocalPort() const
+{
+ return atoi(getService(impl->fd, true).c_str());
+}
+
+uint16_t Socket::getRemotePort() const
+{
+ return atoi(getService(impl->fd, true).c_str());
}
int Socket::getError() const
diff --git a/cpp/src/qpid/sys/windows/SocketAddress.cpp b/cpp/src/qpid/sys/windows/SocketAddress.cpp
index 77bbf85810..501cff1297 100644
--- a/cpp/src/qpid/sys/windows/SocketAddress.cpp
+++ b/cpp/src/qpid/sys/windows/SocketAddress.cpp
@@ -21,13 +21,7 @@
#include "qpid/sys/SocketAddress.h"
-#include "qpid/Exception.h"
-#include "qpid/Msg.h"
-
-// Ensure we get all of winsock2.h
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
+#include "qpid/sys/windows/check.h"
#include <winsock2.h>
#include <ws2tcpip.h>
@@ -41,111 +35,37 @@ SocketAddress::SocketAddress(const std::string& host0, const std::string& port0)
port(port0),
addrInfo(0)
{
-}
-
-SocketAddress::SocketAddress(const SocketAddress& sa) :
- host(sa.host),
- port(sa.port),
- addrInfo(0)
-{
-}
-
-SocketAddress& SocketAddress::operator=(const SocketAddress& sa)
-{
- SocketAddress temp(sa);
-
- std::swap(temp, *this);
- return *this;
-}
-
-SocketAddress::~SocketAddress()
-{
- if (addrInfo) {
- ::freeaddrinfo(addrInfo);
+ ::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();
-std::string SocketAddress::asString(::sockaddr const * const addr, size_t addrlen)
-{
- char servName[NI_MAXSERV];
- char dispName[NI_MAXHOST];
- if (int rc=::getnameinfo(addr, addrlen,
- dispName, sizeof(dispName),
- servName, sizeof(servName),
- NI_NUMERICHOST | NI_NUMERICSERV) != 0)
- throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
- std::string s;
- switch (addr->sa_family) {
- case AF_INET: s += dispName; break;
- case AF_INET6: s += "["; s += dispName; s+= "]"; break;
- default: throw Exception(QPID_MSG("Unexpected socket type"));
- }
- s += ":";
- s += servName;
- return s;
+ int n = ::getaddrinfo(node, service, &hints, &addrInfo);
+ if (n != 0)
+ throw Exception(QPID_MSG("Cannot resolve " << host << ": " << ::gai_strerror(n)));
}
-uint16_t SocketAddress::getPort(::sockaddr const * const addr)
+SocketAddress::~SocketAddress()
{
- switch (addr->sa_family) {
- case AF_INET: return ntohs(((::sockaddr_in*)addr)->sin_port);
- case AF_INET6: return ntohs(((::sockaddr_in6*)addr)->sin6_port);
- default:throw Exception(QPID_MSG("Unexpected socket type"));
- }
+ ::freeaddrinfo(addrInfo);
}
-std::string SocketAddress::asString(bool numeric) const
+std::string SocketAddress::asString() const
{
- if (!numeric)
- return host + ":" + port;
- // Canonicalise into numeric id
- const ::addrinfo& ai = getAddrInfo(*this);
-
- return asString(ai.ai_addr, ai.ai_addrlen);
-}
-
-bool SocketAddress::nextAddress() {
- bool r = currentAddrInfo->ai_next != 0;
- if (r)
- currentAddrInfo = currentAddrInfo->ai_next;
- return r;
-}
-
-void SocketAddress::setAddrInfoPort(uint16_t port) {
- if (!currentAddrInfo) return;
-
- ::addrinfo& ai = *currentAddrInfo;
- switch (ai.ai_family) {
- case AF_INET: ((::sockaddr_in*)ai.ai_addr)->sin_port = htons(port); return;
- case AF_INET6:((::sockaddr_in6*)ai.ai_addr)->sin6_port = htons(port); return;
- default: throw Exception(QPID_MSG("Unexpected socket type"));
- }
+ return host + ":" + port;
}
const ::addrinfo& getAddrInfo(const SocketAddress& sa)
{
- if (!sa.addrInfo) {
- ::addrinfo hints;
- ::memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for
- hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6
- hints.ai_socktype = SOCK_STREAM;
-
- const char* node = 0;
- if (sa.host.empty()) {
- hints.ai_flags |= AI_PASSIVE;
- } else {
- node = sa.host.c_str();
- }
- const char* service = sa.port.empty() ? "0" : sa.port.c_str();
-
- int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo);
- if (n != 0)
- throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n)));
- sa.currentAddrInfo = sa.addrInfo;
- }
-
- return *sa.currentAddrInfo;
+ return *sa.addrInfo;
}
}}
diff --git a/cpp/src/qpid/sys/windows/SslAsynchIO.h b/cpp/src/qpid/sys/windows/SslAsynchIO.h
index edec081ced..3cdf2c8f08 100644
--- a/cpp/src/qpid/sys/windows/SslAsynchIO.h
+++ b/cpp/src/qpid/sys/windows/SslAsynchIO.h
@@ -39,6 +39,9 @@ namespace qpid {
namespace sys {
namespace windows {
+class Socket;
+class Poller;
+
/*
* SSL/Schannel shim between the frame-handling and AsynchIO layers.
* SslAsynchIO creates a regular AsynchIO object to handle I/O and this class
diff --git a/cpp/src/qpid/sys/windows/StrError.cpp b/cpp/src/qpid/sys/windows/StrError.cpp
index 546d399d16..9c1bfcd79c 100755
--- a/cpp/src/qpid/sys/windows/StrError.cpp
+++ b/cpp/src/qpid/sys/windows/StrError.cpp
@@ -30,7 +30,6 @@ namespace sys {
std::string strError(int err) {
const size_t bufsize = 512;
char buf[bufsize];
- buf[0] = 0;
if (0 == FormatMessage (FORMAT_MESSAGE_MAX_WIDTH_MASK
| FORMAT_MESSAGE_FROM_SYSTEM,
0,
@@ -40,11 +39,7 @@ std::string strError(int err) {
bufsize,
0))
{
-#ifdef _MSC_VER
- strerror_s(buf, bufsize, err);
-#else
- return std::string(strerror(err));
-#endif
+ strerror_s (buf, bufsize, err);
}
return std::string(buf);
}
diff --git a/cpp/src/qpid/sys/windows/Thread.cpp b/cpp/src/qpid/sys/windows/Thread.cpp
index 23b0033be4..583a9613a3 100755
--- a/cpp/src/qpid/sys/windows/Thread.cpp
+++ b/cpp/src/qpid/sys/windows/Thread.cpp
@@ -19,11 +19,6 @@
*
*/
-// Ensure definition of OpenThread in mingw
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-
#include "qpid/sys/Thread.h"
#include "qpid/sys/Runnable.h"
#include "qpid/sys/windows/check.h"
@@ -31,204 +26,50 @@
#include <process.h>
#include <windows.h>
-/*
- * This implementation distinguishes between two types of thread: Qpid
- * threads (based on qpid::sys::Runnable) and the rest. It provides a
- * join() that will not deadlock against the Windows loader lock for
- * Qpid threads.
- *
- * System thread identifiers are unique per Windows thread; thread
- * handles are not. Thread identifiers can be recycled, but keeping a
- * handle open against the thread prevents recycling as long as
- * shared_ptr references to a ThreadPrivate structure remain.
- *
- * There is a 1-1 relationship between Qpid threads and their
- * ThreadPrivate structure. Non-Qpid threads do not need to find the
- * qpidThreadDone handle, so there may be a 1-many relationship for
- * them.
- *
- * TLS storage is used for a lockless solution for static library
- * builds. The special case of LoadLibrary/FreeLibrary requires
- * additional synchronization variables and resource cleanup in
- * DllMain. _DLL marks the dynamic case.
- */
+namespace {
+unsigned __stdcall runRunnable(void* p)
+{
+ static_cast<qpid::sys::Runnable*>(p)->run();
+ _endthreadex(0);
+ return 0;
+}
+}
namespace qpid {
namespace sys {
class ThreadPrivate {
-public:
friend class Thread;
- friend unsigned __stdcall runThreadPrivate(void*);
- typedef boost::shared_ptr<ThreadPrivate> shared_ptr;
- ~ThreadPrivate();
-private:
- unsigned threadId;
HANDLE threadHandle;
- HANDLE initCompleted;
- HANDLE qpidThreadDone;
- Runnable* runnable;
- shared_ptr keepAlive;
-
- ThreadPrivate() : threadId(GetCurrentThreadId()), initCompleted(NULL),
- qpidThreadDone(NULL), runnable(NULL) {
- threadHandle = OpenThread (SYNCHRONIZE, FALSE, threadId);
- QPID_WINDOWS_CHECK_CRT_NZ(threadHandle);
- }
-
- ThreadPrivate(Runnable* r) : threadHandle(NULL), initCompleted(NULL),
- qpidThreadDone(NULL), runnable(r) {}
-
- void start(shared_ptr& p);
- static shared_ptr createThread(Runnable* r);
-};
-
-}} // namespace qpid::sys
-
-
-namespace {
-using namespace qpid::sys;
-
-#ifdef _DLL
-class ScopedCriticalSection
-{
- public:
- ScopedCriticalSection(CRITICAL_SECTION& cs) : criticalSection(cs) { EnterCriticalSection(&criticalSection); }
- ~ScopedCriticalSection() { LeaveCriticalSection(&criticalSection); }
- private:
- CRITICAL_SECTION& criticalSection;
-};
-
-CRITICAL_SECTION threadLock;
-long runningThreads = 0;
-HANDLE threadsDone;
-bool terminating = false;
-#endif
-
-
-DWORD volatile tlsIndex = TLS_OUT_OF_INDEXES;
-
-DWORD getTlsIndex() {
- if (tlsIndex != TLS_OUT_OF_INDEXES)
- return tlsIndex; // already set
-
- DWORD trialIndex = TlsAlloc();
- QPID_WINDOWS_CHECK_NOT(trialIndex, TLS_OUT_OF_INDEXES); // No OS resource
+ unsigned threadId;
- // only one thread gets to set the value
- DWORD actualIndex = (DWORD) InterlockedCompareExchange((LONG volatile *) &tlsIndex, (LONG) trialIndex, (LONG) TLS_OUT_OF_INDEXES);
- if (actualIndex == TLS_OUT_OF_INDEXES)
- return trialIndex; // we won the race
- else {
- TlsFree(trialIndex);
- return actualIndex;
+ ThreadPrivate(Runnable* runnable) {
+ uintptr_t h = _beginthreadex(0,
+ 0,
+ runRunnable,
+ runnable,
+ 0,
+ &threadId);
+ QPID_WINDOWS_CHECK_CRT_NZ(h);
+ threadHandle = reinterpret_cast<HANDLE>(h);
}
-}
-
-} // namespace
-
-namespace qpid {
-namespace sys {
-
-unsigned __stdcall runThreadPrivate(void* p)
-{
- ThreadPrivate* threadPrivate = static_cast<ThreadPrivate*>(p);
- TlsSetValue(getTlsIndex(), threadPrivate);
-
- WaitForSingleObject (threadPrivate->initCompleted, INFINITE);
- CloseHandle (threadPrivate->initCompleted);
- threadPrivate->initCompleted = NULL;
-
- try {
- threadPrivate->runnable->run();
- } catch (...) {
- // not our concern
- }
-
- SetEvent (threadPrivate->qpidThreadDone); // allow join()
- threadPrivate->keepAlive.reset(); // may run ThreadPrivate destructor
-
-#ifdef _DLL
- {
- ScopedCriticalSection l(threadLock);
- if (--runningThreads == 0)
- SetEvent(threadsDone);
- }
-#endif
- return 0;
-}
-
-
-ThreadPrivate::shared_ptr ThreadPrivate::createThread(Runnable* runnable) {
- ThreadPrivate::shared_ptr tp(new ThreadPrivate(runnable));
- tp->start(tp);
- return tp;
-}
-
-void ThreadPrivate::start(ThreadPrivate::shared_ptr& tp) {
- getTlsIndex(); // fail here if OS problem, not in new thread
-
- initCompleted = CreateEvent (NULL, TRUE, FALSE, NULL);
- QPID_WINDOWS_CHECK_CRT_NZ(initCompleted);
- qpidThreadDone = CreateEvent (NULL, TRUE, FALSE, NULL);
- QPID_WINDOWS_CHECK_CRT_NZ(qpidThreadDone);
-
-#ifdef _DLL
- {
- ScopedCriticalSection l(threadLock);
- if (terminating)
- throw qpid::Exception(QPID_MSG("creating thread after exit/FreeLibrary"));
- runningThreads++;
- }
-#endif
-
- uintptr_t h = _beginthreadex(0,
- 0,
- runThreadPrivate,
- (void *)this,
- 0,
- &threadId);
-
-#ifdef _DLL
- if (h == NULL) {
- ScopedCriticalSection l(threadLock);
- if (--runningThreads == 0)
- SetEvent(threadsDone);
- }
-#endif
-
- QPID_WINDOWS_CHECK_CRT_NZ(h);
-
- // Success
- keepAlive = tp;
- threadHandle = reinterpret_cast<HANDLE>(h);
- SetEvent (initCompleted);
-}
-
-ThreadPrivate::~ThreadPrivate() {
- if (threadHandle)
- CloseHandle (threadHandle);
- if (initCompleted)
- CloseHandle (initCompleted);
- if (qpidThreadDone)
- CloseHandle (qpidThreadDone);
-}
-
+
+ ThreadPrivate()
+ : threadHandle(GetCurrentThread()), threadId(GetCurrentThreadId()) {}
+};
Thread::Thread() {}
-Thread::Thread(Runnable* runnable) : impl(ThreadPrivate::createThread(runnable)) {}
+Thread::Thread(Runnable* runnable) : impl(new ThreadPrivate(runnable)) {}
-Thread::Thread(Runnable& runnable) : impl(ThreadPrivate::createThread(&runnable)) {}
+Thread::Thread(Runnable& runnable) : impl(new ThreadPrivate(&runnable)) {}
Thread::operator bool() {
return impl;
}
bool Thread::operator==(const Thread& t) const {
- if (!impl || !t.impl)
- return false;
return impl->threadId == t.impl->threadId;
}
@@ -238,17 +79,10 @@ bool Thread::operator!=(const Thread& t) const {
void Thread::join() {
if (impl) {
- DWORD status;
- if (impl->runnable) {
- HANDLE handles[2] = {impl->qpidThreadDone, impl->threadHandle};
- // wait for either. threadHandle not signalled if loader
- // lock held (FreeLibrary). qpidThreadDone not signalled
- // if thread terminated by exit().
- status = WaitForMultipleObjects (2, handles, false, INFINITE);
- }
- else
- status = WaitForSingleObject (impl->threadHandle, INFINITE);
+ DWORD status = WaitForSingleObject (impl->threadHandle, INFINITE);
QPID_WINDOWS_CHECK_NOT(status, WAIT_FAILED);
+ CloseHandle (impl->threadHandle);
+ impl->threadHandle = 0;
}
}
@@ -258,70 +92,9 @@ unsigned long Thread::logId() {
/* static */
Thread Thread::current() {
- ThreadPrivate* tlsValue = (ThreadPrivate *) TlsGetValue(getTlsIndex());
Thread t;
- if (tlsValue != NULL) {
- // called from within Runnable->run(), so keepAlive has positive use count
- t.impl = tlsValue->keepAlive;
- }
- else
- t.impl.reset(new ThreadPrivate());
+ t.impl.reset(new ThreadPrivate());
return t;
}
-}} // namespace qpid::sys
-
-
-#ifdef _DLL
-
-// DllMain: called possibly many times in a process lifetime if dll
-// loaded and freed repeatedly . Be mindful of Windows loader lock
-// and other DllMain restrictions.
-
-BOOL APIENTRY DllMain(HMODULE hm, DWORD reason, LPVOID reserved) {
- switch (reason) {
- case DLL_PROCESS_ATTACH:
- InitializeCriticalSection(&threadLock);
- threadsDone = CreateEvent(NULL, TRUE, FALSE, NULL);
- break;
-
- case DLL_PROCESS_DETACH:
- terminating = true;
- if (reserved != NULL) {
- // process exit(): threads are stopped arbitrarily and
- // possibly in an inconsistent state. Not even threadLock
- // can be trusted. All static destructors have been
- // called at this point and any resources this unit knows
- // about will be released as part of process tear down by
- // the OS. Accordingly, do nothing.
- return TRUE;
- }
- else {
- // FreeLibrary(): threads are still running and we are
- // encouraged to clean up to avoid leaks. Mostly we just
- // want any straggler threads to finish and notify
- // threadsDone as the last thing they do.
- while (1) {
- {
- ScopedCriticalSection l(threadLock);
- if (runningThreads == 0)
- break;
- ResetEvent(threadsDone);
- }
- WaitForSingleObject(threadsDone, INFINITE);
- }
- if (tlsIndex != TLS_OUT_OF_INDEXES)
- TlsFree(getTlsIndex());
- CloseHandle(threadsDone);
- DeleteCriticalSection(&threadLock);
- }
- break;
-
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- break;
- }
- return TRUE;
-}
-
-#endif
+}} /* qpid::sys */
diff --git a/cpp/src/qpid/sys/windows/Time.cpp b/cpp/src/qpid/sys/windows/Time.cpp
index 25c50819cd..16d09fcdc0 100644
--- a/cpp/src/qpid/sys/windows/Time.cpp
+++ b/cpp/src/qpid/sys/windows/Time.cpp
@@ -27,17 +27,6 @@
using namespace boost::posix_time;
-namespace {
-
-// High-res timing support. This will display times since program start,
-// more or less. Keep track of the start value and the conversion factor to
-// seconds.
-bool timeInitialized = false;
-LARGE_INTEGER start;
-double freq = 1.0;
-
-}
-
namespace qpid {
namespace sys {
@@ -102,35 +91,10 @@ void outputFormattedNow(std::ostream& o) {
char time_string[100];
::time( &rawtime );
-#ifdef _MSC_VER
::localtime_s(&timeinfo, &rawtime);
-#else
- timeinfo = *(::localtime(&rawtime));
-#endif
::strftime(time_string, 100,
"%Y-%m-%d %H:%M:%S",
&timeinfo);
o << time_string << " ";
}
-
-void outputHiresNow(std::ostream& o) {
- if (!timeInitialized) {
- start.QuadPart = 0;
- LARGE_INTEGER iFreq;
- iFreq.QuadPart = 1;
- QueryPerformanceCounter(&start);
- QueryPerformanceFrequency(&iFreq);
- freq = static_cast<double>(iFreq.QuadPart);
- timeInitialized = true;
- }
- LARGE_INTEGER iNow;
- iNow.QuadPart = 0;
- QueryPerformanceCounter(&iNow);
- iNow.QuadPart -= start.QuadPart;
- if (iNow.QuadPart < 0)
- iNow.QuadPart = 0;
- double now = static_cast<double>(iNow.QuadPart);
- now /= freq; // now is seconds after this
- o << std::fixed << std::setprecision(8) << std::setw(16) << std::setfill('0') << now << "s ";
-}
}}
diff --git a/cpp/src/qpid/sys/windows/uuid.cpp b/cpp/src/qpid/sys/windows/uuid.cpp
index 3316ecbc00..b5360622dc 100644
--- a/cpp/src/qpid/sys/windows/uuid.cpp
+++ b/cpp/src/qpid/sys/windows/uuid.cpp
@@ -19,7 +19,7 @@
*
*/
-#include <rpc.h>
+#include <Rpc.h>
#ifdef uuid_t /* Done in rpcdce.h */
# undef uuid_t
#endif
@@ -52,11 +52,7 @@ int uuid_parse (const char *in, uuid_t uu) {
void uuid_unparse (const uuid_t uu, char *out) {
unsigned char *formatted;
if (UuidToString((UUID*)uu, &formatted) == RPC_S_OK) {
-#ifdef _MSC_VER
strncpy_s (out, 36+1, (char*)formatted, _TRUNCATE);
-#else
- strncpy (out, (char*)formatted, 36+1);
-#endif
RpcStringFree(&formatted);
}
}
diff --git a/cpp/src/qpid/types/Uuid.cpp b/cpp/src/qpid/types/Uuid.cpp
index 9862fa8946..9face4e5d2 100644
--- a/cpp/src/qpid/types/Uuid.cpp
+++ b/cpp/src/qpid/types/Uuid.cpp
@@ -20,7 +20,6 @@
*/
#include "qpid/types/Uuid.h"
#include "qpid/sys/uuid.h"
-#include "qpid/sys/IntegerTypes.h"
#include <sstream>
#include <iostream>
#include <string.h>
@@ -72,8 +71,7 @@ void Uuid::clear()
// Force int 0/!0 to false/true; avoids compile warnings.
bool Uuid::isNull() const
{
- // This const cast is for Solaris which has non const arguments
- return !!uuid_is_null(const_cast<uint8_t*>(bytes));
+ return !!uuid_is_null(bytes);
}
Uuid::operator bool() const { return !isNull(); }
@@ -88,8 +86,7 @@ const unsigned char* Uuid::data() const
bool operator==(const Uuid& a, const Uuid& b)
{
- // This const cast is for Solaris which has non const arguments
- return uuid_compare(const_cast<uint8_t*>(a.bytes), const_cast<uint8_t*>(b.bytes)) == 0;
+ return uuid_compare(a.bytes, b.bytes) == 0;
}
bool operator!=(const Uuid& a, const Uuid& b)
@@ -99,26 +96,22 @@ bool operator!=(const Uuid& a, const Uuid& b)
bool operator<(const Uuid& a, const Uuid& b)
{
- // This const cast is for Solaris which has non const arguments
- return uuid_compare(const_cast<uint8_t*>(a.bytes), const_cast<uint8_t*>(b.bytes)) < 0;
+ return uuid_compare(a.bytes, b.bytes) < 0;
}
bool operator>(const Uuid& a, const Uuid& b)
{
- // This const cast is for Solaris which has non const arguments
- return uuid_compare(const_cast<uint8_t*>(a.bytes), const_cast<uint8_t*>(b.bytes)) > 0;
+ return uuid_compare(a.bytes, b.bytes) > 0;
}
bool operator<=(const Uuid& a, const Uuid& b)
{
- // This const cast is for Solaris which has non const arguments
- return uuid_compare(const_cast<uint8_t*>(a.bytes), const_cast<uint8_t*>(b.bytes)) <= 0;
+ return uuid_compare(a.bytes, b.bytes) <= 0;
}
bool operator>=(const Uuid& a, const Uuid& b)
{
- // This const cast is for Solaris which has non const arguments
- return uuid_compare(const_cast<uint8_t*>(a.bytes), const_cast<uint8_t*>(b.bytes)) >= 0;
+ return uuid_compare(a.bytes, b.bytes) >= 0;
}
ostream& operator<<(ostream& out, Uuid uuid)
diff --git a/cpp/src/qpid/types/Variant.cpp b/cpp/src/qpid/types/Variant.cpp
index f563d5de5b..5d8878bdac 100644
--- a/cpp/src/qpid/types/Variant.cpp
+++ b/cpp/src/qpid/types/Variant.cpp
@@ -19,6 +19,7 @@
*
*/
#include "qpid/types/Variant.h"
+#include "qpid/Msg.h"
#include "qpid/log/Statement.h"
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
@@ -107,27 +108,15 @@ class VariantImpl
} value;
std::string encoding;//optional encoding for variable length data
+ std::string getTypeName(VariantType type) const;
template<class T> T convertFromString() const
{
std::string* s = reinterpret_cast<std::string*>(value.v);
- if (std::numeric_limits<T>::is_signed || s->find('-') != 0) {
- //lexical_cast won't fail if string is a negative number and T is unsigned
- try {
- return boost::lexical_cast<T>(*s);
- } catch(const boost::bad_lexical_cast&) {
- //don't return, throw exception below
- }
- } else {
- //T is unsigned and number starts with '-'
- try {
- //handle special case of negative zero
- if (boost::lexical_cast<int>(*s) == 0) return 0;
- //else its a non-zero negative number so throw exception at end of function
- } catch(const boost::bad_lexical_cast&) {
- //wasn't a valid int, therefore not a valid uint
- }
+ try {
+ return boost::lexical_cast<T>(*s);
+ } catch(const boost::bad_lexical_cast&) {
+ throw InvalidConversion(QPID_MSG("Cannot convert " << *s));
}
- throw InvalidConversion(QPID_MSG("Cannot convert " << *s));
}
};
@@ -381,11 +370,11 @@ int8_t VariantImpl::asInt8() const
return int8_t(value.ui16);
break;
case VAR_UINT32:
- if (value.ui32 <= (uint32_t) std::numeric_limits<int8_t>::max())
+ if (value.ui32 <= (uint) std::numeric_limits<int8_t>::max())
return int8_t(value.ui32);
break;
case VAR_UINT64:
- if (value.ui64 <= (uint64_t) std::numeric_limits<int8_t>::max())
+ if (value.ui64 <= (uint) std::numeric_limits<int8_t>::max())
return int8_t(value.ui64);
break;
case VAR_STRING: return convertFromString<int8_t>();
@@ -412,11 +401,11 @@ int16_t VariantImpl::asInt16() const
return int16_t(value.ui16);
break;
case VAR_UINT32:
- if (value.ui32 <= (uint32_t) std::numeric_limits<int16_t>::max())
+ if (value.ui32 <= (uint) std::numeric_limits<int16_t>::max())
return int16_t(value.ui32);
break;
case VAR_UINT64:
- if (value.ui64 <= (uint64_t) std::numeric_limits<int16_t>::max())
+ if (value.ui64 <= (uint) std::numeric_limits<int16_t>::max())
return int16_t(value.ui64);
break;
case VAR_STRING: return convertFromString<int16_t>();
@@ -441,7 +430,7 @@ int32_t VariantImpl::asInt32() const
return int32_t(value.ui32);
break;
case VAR_UINT64:
- if (value.ui64 <= (uint64_t) std::numeric_limits<int32_t>::max())
+ if (value.ui64 <= (uint32_t) std::numeric_limits<int32_t>::max())
return int32_t(value.ui64);
break;
case VAR_STRING: return convertFromString<int32_t>();
@@ -593,7 +582,7 @@ const std::string& VariantImpl::getString() const
void VariantImpl::setEncoding(const std::string& s) { encoding = s; }
const std::string& VariantImpl::getEncoding() const { return encoding; }
-std::string getTypeName(VariantType type)
+std::string VariantImpl::getTypeName(VariantType type) const
{
switch (type) {
case VAR_VOID: return "void";
diff --git a/cpp/src/replication.mk b/cpp/src/replication.mk
index e5da32f88b..dbe071f405 100644
--- a/cpp/src/replication.mk
+++ b/cpp/src/replication.mk
@@ -19,14 +19,14 @@
# Make file for building two plugins for asynchronously replicating
# queues.
-dmoduleexec_LTLIBRARIES += replicating_listener.la replication_exchange.la
+dmodule_LTLIBRARIES += replicating_listener.la replication_exchange.la
# a queue event listener plugin that creates messages on a replication
# queue corresponding to enqueue and dequeue events:
replicating_listener_la_SOURCES = \
qpid/replication/constants.h \
qpid/replication/ReplicatingEventListener.cpp \
- qpid/replication/ReplicatingEventListener.h
+ qpid/replication/ReplicatingEventListener.h
replicating_listener_la_LIBADD = libqpidbroker.la
if SUNOS
@@ -41,7 +41,7 @@ replicating_listener_la_LDFLAGS = $(PLUGINLDFLAGS)
replication_exchange_la_SOURCES = \
qpid/replication/constants.h \
qpid/replication/ReplicationExchange.cpp \
- qpid/replication/ReplicationExchange.h
+ qpid/replication/ReplicationExchange.h
replication_exchange_la_LIBADD = libqpidbroker.la
diff --git a/cpp/src/ssl.mk b/cpp/src/ssl.mk
index 4dba9bb61c..5fbdd55438 100644
--- a/cpp/src/ssl.mk
+++ b/cpp/src/ssl.mk
@@ -18,7 +18,7 @@
#
#
# Makefile fragment, conditionally included in Makefile.am
-#
+#
libsslcommon_la_SOURCES = \
qpid/sys/ssl/check.h \
qpid/sys/ssl/check.cpp \
@@ -47,7 +47,7 @@ ssl_la_CXXFLAGS=$(AM_CXXFLAGS) $(SSL_CFLAGS)
ssl_la_LDFLAGS = $(PLUGINLDFLAGS)
-dmoduleexec_LTLIBRARIES += ssl.la
+dmodule_LTLIBRARIES += ssl.la
sslconnector_la_SOURCES = \
qpid/client/SslConnector.cpp
@@ -60,5 +60,5 @@ sslconnector_la_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDC_CONF_FILE=\"$(confdir)/qpidc.c
sslconnector_la_LDFLAGS = $(PLUGINLDFLAGS)
-cmoduleexec_LTLIBRARIES += \
+cmodule_LTLIBRARIES += \
sslconnector.la
diff --git a/cpp/src/tests/.valgrind.supp b/cpp/src/tests/.valgrind.supp
index 2c6a1509ff..0e3e045437 100644
--- a/cpp/src/tests/.valgrind.supp
+++ b/cpp/src/tests/.valgrind.supp
@@ -73,6 +73,61 @@
}
{
+ boost 103200 -- we think Boost is responsible for these leaks.
+ Memcheck:Leak
+ fun:_Znwm
+ fun:_ZN5boost15program_options??options_description*
+}
+
+{
+ boost 103200 -- we think Boost is responsible for these leaks.
+ Memcheck:Leak
+ fun:_Znwm
+ fun:_ZN5boost9unit_test9test_case*
+}
+
+{
+ boost 103200 -- we think Boost is responsible for these leaks.
+ Memcheck:Leak
+ fun:calloc
+ fun:_dlerror_run
+ fun:dlopen@@GLIBC_2.2.5
+ fun:_ZN4qpid3sys5Shlib4loadEPKc
+ fun:_Z9testShlibv
+ fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor8functionEv
+ obj:/usr/lib64/libboost_unit_test_framework.so.1.32.0
+ fun:_ZN5boost17execution_monitor7executeEbi
+ fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor21execute_and_translateEPNS0_9test_caseEMS3_FvvEi
+ fun:_ZN5boost9unit_test9test_case3runEv
+ fun:_ZN5boost9unit_test10test_suite6do_runEv
+ fun:_ZN5boost9unit_test9test_case3runEv
+ fun:main
+}
+
+{
+ boost 103200 -- we think Boost is responsible for these leaks.
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_allocate_tls
+ fun:pthread_create@@GLIBC_2.2.5
+ fun:_ZN4qpid6broker5Timer5startEv
+ fun:_ZN4qpid6broker5TimerC1Ev
+ fun:_ZN4qpid6broker10DtxManagerC1Ev
+ fun:_ZN4qpid6broker6BrokerC1ERKNS1_7OptionsE
+ fun:_ZN4qpid6broker6Broker6createERKNS1_7OptionsE
+ fun:_ZN15SessionFixtureTI15ProxyConnectionEC2Ev
+ fun:_Z14testQueueQueryv
+ fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor8functionEv
+ obj:/usr/lib64/libboost_unit_test_framework.so.1.32.0
+ fun:_ZN5boost17execution_monitor7executeEbi
+ fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor21execute_and_translateEPNS0_9test_caseEMS3_FvvEi
+ fun:_ZN5boost9unit_test9test_case3runEv
+ fun:_ZN5boost9unit_test10test_suite6do_runEv
+ fun:_ZN5boost9unit_test9test_case3runEv
+ fun:main
+}
+
+{
INVESTIGATE
Memcheck:Leak
fun:calloc
@@ -100,6 +155,25 @@
}
{
+ boost 103200 -- mgoulish -- fix this, sometime
+ Memcheck:Leak
+ fun:*
+ fun:*
+ obj:*
+ fun:*
+ fun:_ZN4qpid34options_description_less_easy_initclEPKcPKN5boost15program_options14value_semanticES2_
+}
+
+{
+ boost 103200 -- mgoulish -- fix this, sometime
+ Memcheck:Leak
+ fun:*
+ fun:*
+ fun:*
+ fun:_ZN4qpid34options_description_less_easy_initclEPKcPKN5boost15program_options14value_semanticES2_
+}
+
+{
INVESTIGATE
Memcheck:Param
socketcall.sendto(msg)
diff --git a/cpp/src/tests/Address.cpp b/cpp/src/tests/Address.cpp
index 0fd3585958..f41f27b6df 100644
--- a/cpp/src/tests/Address.cpp
+++ b/cpp/src/tests/Address.cpp
@@ -119,17 +119,6 @@ QPID_AUTO_TEST_CASE(testParseQuotedNameAndSubject)
BOOST_CHECK_EQUAL(std::string("my subject with ; in it"), address.getSubject());
}
-QPID_AUTO_TEST_CASE(testParseOptionsWithEmptyStringAsValue)
-{
- Address address("my-topic; {a:'', x:101}");
- BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName());
- Variant a = address.getOptions()["a"];
- BOOST_CHECK_EQUAL(VAR_STRING, a.getType());
- std::string aVal = a;
- BOOST_CHECK(aVal.size() == 0);
- BOOST_CHECK_EQUAL((uint16_t) 101, address.getOptions()["x"].asInt64());
-}
-
QPID_AUTO_TEST_SUITE_END()
}}
diff --git a/cpp/src/tests/BrokerFixture.h b/cpp/src/tests/BrokerFixture.h
index 92c6d22b57..672d954572 100644
--- a/cpp/src/tests/BrokerFixture.h
+++ b/cpp/src/tests/BrokerFixture.h
@@ -22,6 +22,8 @@
*
*/
+#include "SocketProxy.h"
+
#include "qpid/broker/Broker.h"
#include "qpid/client/Connection.h"
#include "qpid/client/ConnectionImpl.h"
@@ -69,15 +71,16 @@ struct BrokerFixture : private boost::noncopyable {
brokerThread = qpid::sys::Thread(*broker);
};
- void shutdownBroker() {
- if (broker) {
- broker->shutdown();
- brokerThread.join();
- broker = BrokerPtr();
- }
+ void shutdownBroker()
+ {
+ broker->shutdown();
+ broker = BrokerPtr();
}
- ~BrokerFixture() { shutdownBroker(); }
+ ~BrokerFixture() {
+ if (broker) broker->shutdown();
+ brokerThread.join();
+ }
/** Open a connection to the broker. */
void open(qpid::client::Connection& c) {
@@ -94,6 +97,20 @@ struct LocalConnection : public qpid::client::Connection {
~LocalConnection() { close(); }
};
+/** A local client connection via a socket proxy. */
+struct ProxyConnection : public qpid::client::Connection {
+ SocketProxy proxy;
+ ProxyConnection(int brokerPort) : proxy(brokerPort) {
+ open("localhost", proxy.getPort());
+ }
+ ProxyConnection(const qpid::client::ConnectionSettings& s) : proxy(s.port) {
+ qpid::client::ConnectionSettings proxySettings(s);
+ proxySettings.port = proxy.getPort();
+ open(proxySettings);
+ }
+ ~ProxyConnection() { close(); }
+};
+
/** Convenience class to create and open a connection and session
* and some related useful objects.
*/
@@ -130,6 +147,7 @@ struct SessionFixtureT : BrokerFixture, ClientT<ConnectionType,SessionType> {
};
typedef SessionFixtureT<LocalConnection> SessionFixture;
+typedef SessionFixtureT<ProxyConnection> ProxySessionFixture;
}} // namespace qpid::tests
diff --git a/cpp/src/tests/BrokerMgmtAgent.cpp b/cpp/src/tests/BrokerMgmtAgent.cpp
index 1d5289dc90..d0c6668b72 100644
--- a/cpp/src/tests/BrokerMgmtAgent.cpp
+++ b/cpp/src/tests/BrokerMgmtAgent.cpp
@@ -599,12 +599,13 @@ namespace qpid {
// populate the agent with multiple test objects
const size_t objCount = 50;
std::vector<TestManageable *> tmv;
+ uint32_t objLen;
for (size_t i = 0; i < objCount; i++) {
std::stringstream key;
key << "testobj-" << i;
TestManageable *tm = new TestManageable(agent, key.str());
- (void) tm->GetManagementObject()->writePropertiesSize();
+ objLen = tm->GetManagementObject()->writePropertiesSize();
agent->addObject(tm->GetManagementObject(), key.str());
tmv.push_back(tm);
}
diff --git a/cpp/src/tests/BrokerOptions.cpp b/cpp/src/tests/BrokerOptions.cpp
deleted file mode 100644
index b36d96916a..0000000000
--- a/cpp/src/tests/BrokerOptions.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *
- * Copyright (c) 2006 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/** Unit tests for various broker configuration options **/
-
-#include "unit_test.h"
-#include "test_tools.h"
-#include "MessagingFixture.h"
-
-#include "qpid/messaging/Address.h"
-#include "qpid/messaging/Connection.h"
-#include "qpid/messaging/Message.h"
-#include "qpid/messaging/Receiver.h"
-#include "qpid/messaging/Sender.h"
-#include "qpid/messaging/Session.h"
-
-namespace qpid {
-namespace tests {
-
-QPID_AUTO_TEST_SUITE(BrokerOptionsTestSuite)
-
-using namespace qpid::broker;
-using namespace qpid::messaging;
-using namespace qpid::types;
-using namespace qpid;
-
-QPID_AUTO_TEST_CASE(testDisabledTimestamp)
-{
- // by default, there should be no timestamp added by the broker
- MessagingFixture fix;
-
- Sender sender = fix.session.createSender("test-q; {create:always, delete:sender}");
- messaging::Message msg("hi");
- sender.send(msg);
-
- Receiver receiver = fix.session.createReceiver("test-q");
- messaging::Message in;
- BOOST_CHECK(receiver.fetch(in, Duration::IMMEDIATE));
- Variant::Map props = in.getProperties();
- BOOST_CHECK(props.find("x-amqp-0-10.timestamp") == props.end());
-}
-
-QPID_AUTO_TEST_CASE(testEnabledTimestamp)
-{
- // when enabled, the 0.10 timestamp is added by the broker
- Broker::Options opts;
- opts.timestampRcvMsgs = true;
- MessagingFixture fix(opts, true);
-
- Sender sender = fix.session.createSender("test-q; {create:always, delete:sender}");
- messaging::Message msg("one");
- sender.send(msg);
-
- Receiver receiver = fix.session.createReceiver("test-q");
- messaging::Message in;
- BOOST_CHECK(receiver.fetch(in, Duration::IMMEDIATE));
- Variant::Map props = in.getProperties();
- BOOST_CHECK(props.find("x-amqp-0-10.timestamp") != props.end());
- BOOST_CHECK(props["x-amqp-0-10.timestamp"]);
-}
-
-QPID_AUTO_TEST_SUITE_END()
-
-}}
diff --git a/cpp/src/tests/CMakeLists.txt b/cpp/src/tests/CMakeLists.txt
index 7d781e5eb3..3b3b232671 100644
--- a/cpp/src/tests/CMakeLists.txt
+++ b/cpp/src/tests/CMakeLists.txt
@@ -107,6 +107,7 @@ set(unit_tests_to_build
MessagingSessionTests
SequenceSet
StringUtils
+ IncompleteMessageList
RangeSet
AtomicValue
QueueTest
@@ -118,7 +119,6 @@ set(unit_tests_to_build
MessageTest
QueueRegistryTest
QueuePolicyTest
- QueueFlowLimitTest
FramingTest
HeaderTest
SequenceNumberTest
@@ -264,19 +264,6 @@ add_executable (qpid-send qpid-send.cpp Statistics.cpp ${platform_test_additions
target_link_libraries (qpid-send qpidmessaging)
remember_location(qpid-send)
-add_executable (qpid-ping qpid-ping.cpp ${platform_test_additions})
-target_link_libraries (qpid-ping qpidclient)
-remember_location(qpid-ping)
-
-add_executable (datagen datagen.cpp ${platform_test_additions})
-target_link_libraries (datagen qpidclient)
-remember_location(datagen)
-
-add_executable (msg_group_test msg_group_test.cpp ${platform_test_additions})
-target_link_libraries (msg_group_test qpidmessaging)
-remember_location(msg_group_test)
-
-
# qpid-perftest and qpid-latency-test are generally useful so install them
install (TARGETS qpid-perftest qpid-latency-test RUNTIME
DESTINATION ${QPID_INSTALL_BINDIR})
@@ -291,7 +278,7 @@ set(test_wrap ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_test${test_script_suffix}
add_test (unit_test ${test_wrap} ${unit_test_LOCATION})
add_test (start_broker ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/start_broker${test_script_suffix})
-add_test (qpid-client-test ${test_wrap} ${qpid-client-test_LOCATION})
+add_test (qpid-client-test ${test_wrap} ${qpid-client_test_LOCATION})
add_test (quick_perftest ${test_wrap} ${qpid-perftest_LOCATION} --summary --count 100)
add_test (quick_topictest ${test_wrap} ${CMAKE_CURRENT_SOURCE_DIR}/quick_topictest${test_script_suffix})
add_test (quick_txtest ${test_wrap} ${qpid-txtest_LOCATION} --queues 4 --tx-count 10 --quiet)
@@ -301,7 +288,6 @@ if (PYTHON_EXECUTABLE)
endif (PYTHON_EXECUTABLE)
add_test (stop_broker ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/stop_broker${test_script_suffix})
if (PYTHON_EXECUTABLE)
- add_test (ipv6_test ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/ipv6_test${test_script_suffix})
add_test (federation_tests ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_federation_tests${test_script_suffix})
if (BUILD_ACL)
add_test (acl_tests ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_acl_tests${test_script_suffix})
diff --git a/cpp/src/tests/ClientSessionTest.cpp b/cpp/src/tests/ClientSessionTest.cpp
index 30441cd03c..939f8f2b88 100644
--- a/cpp/src/tests/ClientSessionTest.cpp
+++ b/cpp/src/tests/ClientSessionTest.cpp
@@ -102,9 +102,9 @@ struct SimpleListener : public MessageListener
}
};
-struct ClientSessionFixture : public SessionFixture
+struct ClientSessionFixture : public ProxySessionFixture
{
- ClientSessionFixture(Broker::Options opts = Broker::Options()) : SessionFixture(opts) {
+ ClientSessionFixture(Broker::Options opts = Broker::Options()) : ProxySessionFixture(opts) {
session.queueDeclare(arg::queue="my-queue");
}
};
@@ -150,6 +150,16 @@ QPID_AUTO_TEST_CASE(testDispatcherThread)
BOOST_CHECK_EQUAL(boost::lexical_cast<string>(i), listener.messages[i].getData());
}
+// FIXME aconway 2009-06-17: test for unimplemented feature, enable when implemented.
+void testSuspend0Timeout() {
+ ClientSessionFixture fix;
+ fix.session.suspend(); // session has 0 timeout.
+ try {
+ fix.connection.resume(fix.session);
+ BOOST_FAIL("Expected InvalidArgumentException.");
+ } catch(const InternalErrorException&) {}
+}
+
QPID_AUTO_TEST_CASE(testUseSuspendedError)
{
ClientSessionFixture fix;
@@ -161,6 +171,18 @@ QPID_AUTO_TEST_CASE(testUseSuspendedError)
} catch(const NotAttachedException&) {}
}
+// FIXME aconway 2009-06-17: test for unimplemented feature, enable when implemented.
+void testSuspendResume() {
+ ClientSessionFixture fix;
+ fix.session.timeout(60);
+ fix.session.suspend();
+ // Make sure we are still subscribed after resume.
+ fix.connection.resume(fix.session);
+ fix.session.messageTransfer(arg::content=Message("my-message", "my-queue"));
+ BOOST_CHECK_EQUAL("my-message", fix.subs.get("my-queue", TIME_SEC).getData());
+}
+
+
QPID_AUTO_TEST_CASE(testSendToSelf) {
ClientSessionFixture fix;
SimpleListener mylistener;
@@ -249,12 +271,8 @@ QPID_AUTO_TEST_CASE(testOpenFailure) {
QPID_AUTO_TEST_CASE(testPeriodicExpiration) {
Broker::Options opts;
opts.queueCleanInterval = 1;
- opts.queueFlowStopRatio = 0;
- opts.queueFlowResumeRatio = 0;
ClientSessionFixture fix(opts);
- FieldTable args;
- args.setInt("qpid.max_count",10);
- fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
+ fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true);
for (uint i = 0; i < 10; i++) {
Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue");
@@ -265,7 +283,6 @@ QPID_AUTO_TEST_CASE(testPeriodicExpiration) {
BOOST_CHECK_EQUAL(fix.session.queueQuery(string("my-queue")).getMessageCount(), 10u);
qpid::sys::sleep(2);
BOOST_CHECK_EQUAL(fix.session.queueQuery(string("my-queue")).getMessageCount(), 5u);
- fix.session.messageTransfer(arg::content=Message("Message_11", "my-queue"));//ensure policy is also updated
}
QPID_AUTO_TEST_CASE(testExpirationOnPop) {
diff --git a/cpp/src/tests/ExchangeTest.cpp b/cpp/src/tests/ExchangeTest.cpp
index fe72f42a46..88a1cd99c2 100644
--- a/cpp/src/tests/ExchangeTest.cpp
+++ b/cpp/src/tests/ExchangeTest.cpp
@@ -253,7 +253,7 @@ QPID_AUTO_TEST_CASE(testIVEOption)
TopicExchange topic ("topic1", false, args);
intrusive_ptr<Message> msg1 = cmessage("direct1", "abc");
- msg1->insertCustomProperty("a", "abc");
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString("a", "abc");
DeliverableMessage dmsg1(msg1);
FieldTable args2;
diff --git a/cpp/src/tests/ForkedBroker.cpp b/cpp/src/tests/ForkedBroker.cpp
index 10674b5175..53eaa7e1ce 100644
--- a/cpp/src/tests/ForkedBroker.cpp
+++ b/cpp/src/tests/ForkedBroker.cpp
@@ -68,7 +68,8 @@ ForkedBroker::~ForkedBroker() {
}
if (!dataDir.empty())
{
- (void) ::system(("rm -rf "+dataDir).c_str());
+ int unused_ret; // Suppress warnings about ignoring return value.
+ unused_ret = ::system(("rm -rf "+dataDir).c_str());
}
}
diff --git a/cpp/src/tests/IncompleteMessageList.cpp b/cpp/src/tests/IncompleteMessageList.cpp
new file mode 100644
index 0000000000..10782572e5
--- /dev/null
+++ b/cpp/src/tests/IncompleteMessageList.cpp
@@ -0,0 +1,134 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include <iostream>
+#include <sstream>
+#include "qpid/broker/Message.h"
+#include "qpid/broker/NullMessageStore.h"
+#include "qpid/broker/Queue.h"
+#include "qpid/broker/IncompleteMessageList.h"
+
+#include "unit_test.h"
+
+namespace qpid {
+namespace tests {
+
+QPID_AUTO_TEST_SUITE(IncompleteMessageListTestSuite)
+
+using namespace qpid::broker;
+using namespace qpid::framing;
+
+struct Checker
+{
+ std::list<SequenceNumber> ids;
+
+ Checker() { }
+
+ Checker(uint start, uint end) {
+ for (uint i = start; i <= end; i++) {
+ ids.push_back(i);
+ }
+ }
+
+ Checker& expect(const SequenceNumber& id) {
+ ids.push_back(id);
+ return *this;
+ }
+
+ void operator()(boost::intrusive_ptr<Message> msg) {
+ BOOST_CHECK(!ids.empty());
+ BOOST_CHECK_EQUAL(msg->getCommandId(), ids.front());
+ ids.pop_front();
+ }
+};
+
+QPID_AUTO_TEST_CASE(testProcessSimple)
+{
+ IncompleteMessageList list;
+ SequenceNumber counter(1);
+ //fill up list with messages
+ for (int i = 0; i < 5; i++) {
+ boost::intrusive_ptr<Message> msg(new Message(counter++));
+ list.add(msg);
+ }
+ //process and ensure they are all passed to completion listener
+ list.process(Checker(1, 5), false);
+ //process again and ensure none are resent to listener
+ list.process(Checker(), false);
+}
+
+QPID_AUTO_TEST_CASE(testProcessWithIncomplete)
+{
+ Queue::shared_ptr queue;
+ IncompleteMessageList list;
+ SequenceNumber counter(1);
+ boost::intrusive_ptr<Message> middle;
+ //fill up list with messages
+ for (int i = 0; i < 5; i++) {
+ boost::intrusive_ptr<Message> msg(new Message(counter++));
+ list.add(msg);
+ if (i == 2) {
+ //mark a message in the middle as incomplete
+ msg->enqueueAsync(queue, 0);
+ middle = msg;
+ }
+ }
+ //process and ensure only message upto incomplete message are passed to listener
+ list.process(Checker(1, 2), false);
+ //mark message complete and re-process to get remaining messages sent to listener
+ middle->enqueueComplete();
+ list.process(Checker(3, 5), false);
+}
+
+
+struct MockStore : public NullMessageStore
+{
+ Queue::shared_ptr queue;
+ boost::intrusive_ptr<Message> msg;
+
+ void flush(const qpid::broker::PersistableQueue& q) {
+ BOOST_CHECK_EQUAL(queue.get(), &q);
+ msg->enqueueComplete();
+ }
+};
+
+QPID_AUTO_TEST_CASE(testSyncProcessWithIncomplete)
+{
+ IncompleteMessageList list;
+ SequenceNumber counter(1);
+ MockStore store;
+ store.queue = Queue::shared_ptr(new Queue("mock-queue", false, &store));
+ //fill up list with messages
+ for (int i = 0; i < 5; i++) {
+ boost::intrusive_ptr<Message> msg(new Message(counter++));
+ list.add(msg);
+ if (i == 2) {
+ //mark a message in the middle as incomplete
+ msg->enqueueAsync(store.queue, &store);
+ store.msg = msg;
+ }
+ }
+ //process with sync bit specified and ensure that all messages are passed to listener
+ list.process(Checker(1, 5), true);
+}
+
+QPID_AUTO_TEST_SUITE_END()
+
+}} // namespace qpid::tests
diff --git a/cpp/src/tests/Makefile.am b/cpp/src/tests/Makefile.am
index 3c9ca1b70f..07405bcd8f 100644
--- a/cpp/src/tests/Makefile.am
+++ b/cpp/src/tests/Makefile.am
@@ -75,7 +75,7 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \
MessagingThreadTests.cpp \
MessagingFixture.h \
ClientSessionTest.cpp \
- BrokerFixture.h \
+ BrokerFixture.h SocketProxy.h \
exception_test.cpp \
RefCounted.cpp \
SessionState.cpp logging.cpp \
@@ -87,6 +87,7 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \
InlineVector.cpp \
SequenceSet.cpp \
StringUtils.cpp \
+ IncompleteMessageList.cpp \
RangeSet.cpp \
AtomicValue.cpp \
QueueTest.cpp \
@@ -98,7 +99,6 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \
MessageTest.cpp \
QueueRegistryTest.cpp \
QueuePolicyTest.cpp \
- QueueFlowLimitTest.cpp \
FramingTest.cpp \
HeaderTest.cpp \
SequenceNumberTest.cpp \
@@ -124,8 +124,7 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \
Variant.cpp \
Address.cpp \
ClientMessage.cpp \
- Qmf2.cpp \
- BrokerOptions.cpp
+ Qmf2.cpp
if HAVE_XML
unit_test_SOURCES+= XmlClientSessionTest.cpp
@@ -287,27 +286,31 @@ check_PROGRAMS+=datagen
datagen_SOURCES=datagen.cpp
datagen_LDADD=$(lib_common) $(lib_client)
+check_PROGRAMS+=qrsh_server
+qrsh_server_SOURCES=qrsh_server.cpp
+qrsh_server_LDADD=$(lib_client)
+
+check_PROGRAMS+=qrsh_run
+qrsh_run_SOURCES=qrsh_run.cpp
+qrsh_run_LDADD=$(lib_client)
+
+check_PROGRAMS+=qrsh
+qrsh_SOURCES=qrsh.cpp
+qrsh_LDADD=$(lib_client)
+
check_PROGRAMS+=qpid-stream
qpid_stream_INCLUDES=$(PUBLIC_INCLUDES)
qpid_stream_SOURCES=qpid-stream.cpp
qpid_stream_LDADD=$(lib_messaging)
-check_PROGRAMS+=msg_group_test
-msg_group_test_INCLUDES=$(PUBLIC_INCLUDES)
-msg_group_test_SOURCES=msg_group_test.cpp
-msg_group_test_LDADD=$(lib_messaging)
-
TESTS_ENVIRONMENT = \
VALGRIND=$(VALGRIND) \
LIBTOOL="$(LIBTOOL)" \
QPID_DATA_DIR= \
$(srcdir)/run_test
-system_tests = qpid-client-test quick_perftest quick_topictest run_header_test quick_txtest \
- run_msg_group_tests
-TESTS += start_broker $(system_tests) python_tests stop_broker run_federation_tests run_federation_sys_tests \
- run_acl_tests run_cli_tests replication_test dynamic_log_level_test \
- run_queue_flow_limit_tests ipv6_test
+system_tests = qpid-client-test quick_perftest quick_topictest run_header_test quick_txtest
+TESTS += start_broker $(system_tests) python_tests stop_broker run_federation_tests run_acl_tests run_cli_tests replication_test dynamic_log_level_test
EXTRA_DIST += \
run_test vg_check \
@@ -322,8 +325,6 @@ EXTRA_DIST += \
config.null \
ais_check \
run_federation_tests \
- run_federation_sys_tests \
- run_long_federation_sys_tests \
run_cli_tests \
run_acl_tests \
.valgrind.supp \
@@ -348,10 +349,7 @@ EXTRA_DIST += \
run_test.ps1 \
start_broker.ps1 \
stop_broker.ps1 \
- topictest.ps1 \
- run_queue_flow_limit_tests \
- run_msg_group_tests \
- ipv6_test
+ topictest.ps1
check_LTLIBRARIES += libdlclose_noop.la
libdlclose_noop_la_LDFLAGS = -module -rpath $(abs_builddir)
@@ -362,11 +360,7 @@ CLEANFILES+=valgrind.out *.log *.vglog* dummy_test qpidd.port $(unit_wrappers)
# Longer running stability tests, not run by default check: target.
# Not run under valgrind, too slow
-LONG_TESTS+=start_broker \
- fanout_perftest shared_perftest multiq_perftest topic_perftest run_ring_queue_test \
- run_msg_group_tests_soak \
- stop_broker \
- run_long_federation_sys_tests \
+LONG_TESTS+=start_broker fanout_perftest shared_perftest multiq_perftest topic_perftest run_ring_queue_test stop_broker \
run_failover_soak reliable_replication_test \
federated_cluster_test_with_node_failure
@@ -378,8 +372,7 @@ EXTRA_DIST+= \
run_failover_soak \
reliable_replication_test \
federated_cluster_test_with_node_failure \
- sasl_test_setup.sh \
- run_msg_group_tests_soak
+ sasl_test_setup.sh
check-long:
$(MAKE) check TESTS="$(LONG_TESTS)" VALGRIND=
diff --git a/cpp/src/tests/MessageReplayTracker.cpp b/cpp/src/tests/MessageReplayTracker.cpp
index e35f673683..3d79ee53c2 100644
--- a/cpp/src/tests/MessageReplayTracker.cpp
+++ b/cpp/src/tests/MessageReplayTracker.cpp
@@ -51,7 +51,7 @@ class ReplayBufferChecker
QPID_AUTO_TEST_CASE(testReplay)
{
- SessionFixture fix;
+ ProxySessionFixture fix;
fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true);
MessageReplayTracker tracker(10);
@@ -77,7 +77,7 @@ QPID_AUTO_TEST_CASE(testReplay)
QPID_AUTO_TEST_CASE(testCheckCompletion)
{
- SessionFixture fix;
+ ProxySessionFixture fix;
fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true);
MessageReplayTracker tracker(10);
diff --git a/cpp/src/tests/MessagingFixture.h b/cpp/src/tests/MessagingFixture.h
index 2312a87e9d..715de09bad 100644
--- a/cpp/src/tests/MessagingFixture.h
+++ b/cpp/src/tests/MessagingFixture.h
@@ -27,19 +27,15 @@
#include "qpid/client/Connection.h"
#include "qpid/client/Session.h"
#include "qpid/framing/Uuid.h"
-#include "qpid/messaging/Address.h"
#include "qpid/messaging/Connection.h"
#include "qpid/messaging/Session.h"
#include "qpid/messaging/Sender.h"
#include "qpid/messaging/Receiver.h"
#include "qpid/messaging/Message.h"
-#include "qpid/types/Variant.h"
namespace qpid {
namespace tests {
-using qpid::types::Variant;
-
struct BrokerAdmin
{
qpid::client::Connection connection;
@@ -227,119 +223,6 @@ inline void receive(messaging::Receiver& receiver, uint count = 1, uint start =
}
}
-
-class MethodInvoker
-{
- public:
- MethodInvoker(messaging::Session& session) : replyTo("#; {create:always, node:{x-declare:{auto-delete:true}}}"),
- sender(session.createSender("qmf.default.direct/broker")),
- receiver(session.createReceiver(replyTo)) {}
-
- void createExchange(const std::string& name, const std::string& type, bool durable=false)
- {
- Variant::Map params;
- params["name"]=name;
- params["type"]="exchange";
- params["properties"] = Variant::Map();
- params["properties"].asMap()["exchange-type"] = type;
- params["properties"].asMap()["durable"] = durable;
- methodRequest("create", params);
- }
-
- void deleteExchange(const std::string& name)
- {
- Variant::Map params;
- params["name"]=name;
- params["type"]="exchange";
- methodRequest("delete", params);
- }
-
- void createQueue(const std::string& name, bool durable=false, bool autodelete=false,
- const Variant::Map& options=Variant::Map())
- {
- Variant::Map params;
- params["name"]=name;
- params["type"]="queue";
- params["properties"] = options;
- params["properties"].asMap()["durable"] = durable;
- params["properties"].asMap()["auto-delete"] = autodelete;
- methodRequest("create", params);
- }
-
- void deleteQueue(const std::string& name)
- {
- Variant::Map params;
- params["name"]=name;
- params["type"]="queue";
- methodRequest("delete", params);
- }
-
- void bind(const std::string& exchange, const std::string& queue, const std::string& key,
- const Variant::Map& options=Variant::Map())
- {
- Variant::Map params;
- params["name"]=(boost::format("%1%/%2%/%3%") % (exchange) % (queue) % (key)).str();
- params["type"]="binding";
- params["properties"] = options;
- methodRequest("create", params);
- }
-
- void unbind(const std::string& exchange, const std::string& queue, const std::string& key)
- {
- Variant::Map params;
- params["name"]=(boost::format("%1%/%2%/%3%") % (exchange) % (queue) % (key)).str();
- params["type"]="binding";
- methodRequest("delete", params);
- }
-
- void methodRequest(const std::string& method, const Variant::Map& inParams, Variant::Map* outParams = 0)
- {
- Variant::Map content;
- Variant::Map objectId;
- objectId["_object_name"] = "org.apache.qpid.broker:broker:amqp-broker";
- content["_object_id"] = objectId;
- content["_method_name"] = method;
- content["_arguments"] = inParams;
-
- messaging::Message request;
- request.setReplyTo(replyTo);
- request.getProperties()["x-amqp-0-10.app-id"] = "qmf2";
- request.getProperties()["qmf.opcode"] = "_method_request";
- encode(content, request);
-
- sender.send(request);
-
- messaging::Message response;
- if (receiver.fetch(response, messaging::Duration::SECOND*5)) {
- if (response.getProperties()["x-amqp-0-10.app-id"] == "qmf2") {
- std::string opcode = response.getProperties()["qmf.opcode"];
- if (opcode == "_method_response") {
- if (outParams) {
- Variant::Map m;
- decode(response, m);
- *outParams = m["_arguments"].asMap();
- }
- } else if (opcode == "_exception") {
- Variant::Map m;
- decode(response, m);
- throw Exception(QPID_MSG("Error: " << m["_values"]));
- } else {
- throw Exception(QPID_MSG("Invalid response received, unexpected opcode: " << opcode));
- }
- } else {
- throw Exception(QPID_MSG("Invalid response received, not a qmfv2 message: app-id="
- << response.getProperties()["x-amqp-0-10.app-id"]));
- }
- } else {
- throw Exception(QPID_MSG("No response received"));
- }
- }
- private:
- messaging::Address replyTo;
- messaging::Sender sender;
- messaging::Receiver receiver;
-};
-
}} // namespace qpid::tests
#endif /*!TESTS_MESSAGINGFIXTURE_H*/
diff --git a/cpp/src/tests/MessagingSessionTests.cpp b/cpp/src/tests/MessagingSessionTests.cpp
index 9d5db84bb4..991ec847bf 100644
--- a/cpp/src/tests/MessagingSessionTests.cpp
+++ b/cpp/src/tests/MessagingSessionTests.cpp
@@ -611,28 +611,6 @@ QPID_AUTO_TEST_CASE(testAssertPolicyQueue)
fix.admin.deleteQueue("q");
}
-QPID_AUTO_TEST_CASE(testAssertExchangeOption)
-{
- MessagingFixture fix;
- std::string a1 = "e; {create:always, assert:always, node:{type:topic, x-declare:{type:direct, arguments:{qpid.msg_sequence:True}}}}";
- Sender s1 = fix.session.createSender(a1);
- s1.close();
- Receiver r1 = fix.session.createReceiver(a1);
- r1.close();
-
- std::string a2 = "e; {assert:receiver, node:{type:topic, x-declare:{type:fanout, arguments:{qpid.msg_sequence:True}}}}";
- Sender s2 = fix.session.createSender(a2);
- s2.close();
- BOOST_CHECK_THROW(fix.session.createReceiver(a2), qpid::messaging::AssertionFailed);
-
- std::string a3 = "e; {assert:sender, node:{x-declare:{arguments:{qpid.msg_sequence:False}}}}";
- BOOST_CHECK_THROW(fix.session.createSender(a3), qpid::messaging::AssertionFailed);
- Receiver r3 = fix.session.createReceiver(a3);
- r3.close();
-
- fix.admin.deleteExchange("e");
-}
-
QPID_AUTO_TEST_CASE(testGetSender)
{
QueueFixture fix;
@@ -912,212 +890,6 @@ QPID_AUTO_TEST_CASE(testAcknowledge)
BOOST_CHECK(!fix.session.createReceiver(fix.queue).fetch(m, Duration::IMMEDIATE));
}
-QPID_AUTO_TEST_CASE(testQmfCreateAndDelete)
-{
- MessagingFixture fix(Broker::Options(), true/*enable management*/);
- MethodInvoker control(fix.session);
- control.createQueue("my-queue");
- control.createExchange("my-exchange", "topic");
- control.bind("my-exchange", "my-queue", "subject1");
-
- Sender sender = fix.session.createSender("my-exchange");
- Receiver receiver = fix.session.createReceiver("my-queue");
- Message out;
- out.setSubject("subject1");
- out.setContent("one");
- sender.send(out);
- Message in;
- BOOST_CHECK(receiver.fetch(in, Duration::SECOND*5));
- BOOST_CHECK_EQUAL(out.getContent(), in.getContent());
- control.unbind("my-exchange", "my-queue", "subject1");
- control.bind("my-exchange", "my-queue", "subject2");
-
- out.setContent("two");
- sender.send(out);//should be dropped
-
- out.setSubject("subject2");
- out.setContent("three");
- sender.send(out);//should not be dropped
-
- BOOST_CHECK(receiver.fetch(in, Duration::SECOND*5));
- BOOST_CHECK_EQUAL(out.getContent(), in.getContent());
- BOOST_CHECK(!receiver.fetch(in, Duration::IMMEDIATE));
- sender.close();
- receiver.close();
-
- control.deleteExchange("my-exchange");
- messaging::Session other = fix.connection.createSession();
- {
- ScopedSuppressLogging sl;
- BOOST_CHECK_THROW(other.createSender("my-exchange"), qpid::messaging::NotFound);
- }
- control.deleteQueue("my-queue");
- other = fix.connection.createSession();
- {
- ScopedSuppressLogging sl;
- BOOST_CHECK_THROW(other.createReceiver("my-queue"), qpid::messaging::NotFound);
- }
-}
-
-QPID_AUTO_TEST_CASE(testRejectAndCredit)
-{
- //Ensure credit is restored on completing rejected messages
- QueueFixture fix;
- Sender sender = fix.session.createSender(fix.queue);
- Receiver receiver = fix.session.createReceiver(fix.queue);
-
- const uint count(10);
- receiver.setCapacity(count);
- for (uint i = 0; i < count; i++) {
- sender.send(Message((boost::format("Message_%1%") % (i+1)).str()));
- }
-
- Message in;
- for (uint i = 0; i < count; ++i) {
- if (receiver.fetch(in, Duration::SECOND)) {
- BOOST_CHECK_EQUAL(in.getContent(), (boost::format("Message_%1%") % (i+1)).str());
- fix.session.reject(in);
- } else {
- BOOST_FAIL((boost::format("Message_%1% not received as expected") % (i+1)).str());
- break;
- }
- }
- //send another batch of messages
- for (uint i = 0; i < count; i++) {
- sender.send(Message((boost::format("Message_%1%") % (i+count)).str()));
- }
-
- for (uint i = 0; i < count; ++i) {
- if (receiver.fetch(in, Duration::SECOND)) {
- BOOST_CHECK_EQUAL(in.getContent(), (boost::format("Message_%1%") % (i+count)).str());
- } else {
- BOOST_FAIL((boost::format("Message_%1% not received as expected") % (i+count)).str());
- break;
- }
- }
- fix.session.acknowledge();
- receiver.close();
- sender.close();
-}
-
-QPID_AUTO_TEST_CASE(testTtlForever)
-{
- QueueFixture fix;
- Sender sender = fix.session.createSender(fix.queue);
- Message out("I want to live forever!");
- out.setTtl(Duration::FOREVER);
- sender.send(out, true);
- Receiver receiver = fix.session.createReceiver(fix.queue);
- Message in = receiver.fetch(Duration::IMMEDIATE);
- fix.session.acknowledge();
- BOOST_CHECK_EQUAL(in.getContent(), out.getContent());
- BOOST_CHECK(in.getTtl() == Duration::FOREVER);
-}
-
-QPID_AUTO_TEST_CASE(testExclusiveTopicSubscriber)
-{
- TopicFixture fix;
- std::string address = (boost::format("%1%; { link: { name: 'my-subscription', x-declare: { auto-delete: true, exclusive: true }}}") % fix.topic).str();
- Sender sender = fix.session.createSender(fix.topic);
- Receiver receiver1 = fix.session.createReceiver(address);
- {
- ScopedSuppressLogging sl;
- try {
- fix.session.createReceiver(address);
- fix.session.sync();
- BOOST_FAIL("Expected exception.");
- } catch (const MessagingException& /*e*/) {}
- }
-}
-
-QPID_AUTO_TEST_CASE(testNonExclusiveSubscriber)
-{
- TopicFixture fix;
- std::string address = (boost::format("%1%; {node:{type:topic}, link:{name:'my-subscription', x-declare:{auto-delete:true, exclusive:false}}}") % fix.topic).str();
- Receiver receiver1 = fix.session.createReceiver(address);
- Receiver receiver2 = fix.session.createReceiver(address);
- Sender sender = fix.session.createSender(fix.topic);
- sender.send(Message("one"), true);
- Message in = receiver1.fetch(Duration::IMMEDIATE);
- BOOST_CHECK_EQUAL(in.getContent(), std::string("one"));
- sender.send(Message("two"), true);
- in = receiver2.fetch(Duration::IMMEDIATE);
- BOOST_CHECK_EQUAL(in.getContent(), std::string("two"));
- fix.session.acknowledge();
-}
-
-QPID_AUTO_TEST_CASE(testAcknowledgeUpTo)
-{
- QueueFixture fix;
- Sender sender = fix.session.createSender(fix.queue);
- const uint count(20);
- for (uint i = 0; i < count; ++i) {
- sender.send(Message((boost::format("Message_%1%") % (i+1)).str()));
- }
-
- Session other = fix.connection.createSession();
- Receiver receiver = other.createReceiver(fix.queue);
- std::vector<Message> messages;
- for (uint i = 0; i < count; ++i) {
- Message msg = receiver.fetch();
- BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1)).str());
- messages.push_back(msg);
- }
- const uint batch = 10;
- other.acknowledgeUpTo(messages[batch-1]);//acknowledge first 10 messages only
-
- messages.clear();
- other.sync();
- other.close();
-
- other = fix.connection.createSession();
- receiver = other.createReceiver(fix.queue);
- Message msg;
- for (uint i = 0; i < (count-batch); ++i) {
- msg = receiver.fetch();
- BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1+batch)).str());
- }
- other.acknowledgeUpTo(msg);
- other.sync();
- other.close();
-
- Message m;
- //check queue is empty
- BOOST_CHECK(!fix.session.createReceiver(fix.queue).fetch(m, Duration::IMMEDIATE));
-}
-
-QPID_AUTO_TEST_CASE(testCreateBindingsOnStandardExchange)
-{
- QueueFixture fix;
- Sender sender = fix.session.createSender((boost::format("amq.direct; {create:always, node:{type:topic, x-bindings:[{queue:%1%, key:my-subject}]}}") % fix.queue).str());
- Message out("test-message");
- out.setSubject("my-subject");
- sender.send(out);
- Receiver receiver = fix.session.createReceiver(fix.queue);
- Message in = receiver.fetch(Duration::SECOND * 5);
- fix.session.acknowledge();
- BOOST_CHECK_EQUAL(in.getContent(), out.getContent());
- BOOST_CHECK_EQUAL(in.getSubject(), out.getSubject());
-}
-
-QPID_AUTO_TEST_CASE(testUnsubscribeOnClose)
-{
- MessagingFixture fix;
- Sender sender = fix.session.createSender("my-exchange/my-subject; {create: always, delete:sender, node:{type:topic, x-declare:{alternate-exchange:amq.fanout}}}");
- Receiver receiver = fix.session.createReceiver("my-exchange/my-subject");
- Receiver deadletters = fix.session.createReceiver("amq.fanout");
-
- sender.send(Message("first"));
- Message in = receiver.fetch(Duration::SECOND);
- BOOST_CHECK_EQUAL(in.getContent(), std::string("first"));
- fix.session.acknowledge();
- receiver.close();
- sender.send(Message("second"));
- in = deadletters.fetch(Duration::SECOND);
- BOOST_CHECK_EQUAL(in.getContent(), std::string("second"));
- fix.session.acknowledge();
-}
-
QPID_AUTO_TEST_SUITE_END()
}} // namespace qpid::tests
diff --git a/cpp/src/tests/Qmf2.cpp b/cpp/src/tests/Qmf2.cpp
index bc263d5c6d..66c774accd 100644
--- a/cpp/src/tests/Qmf2.cpp
+++ b/cpp/src/tests/Qmf2.cpp
@@ -23,36 +23,12 @@
#include "qmf/QueryImpl.h"
#include "qmf/SchemaImpl.h"
#include "qmf/exceptions.h"
-#include "qpid/messaging/Connection.h"
-#include "qmf/PosixEventNotifierImpl.h"
-#include "qmf/AgentSession.h"
-#include "qmf/AgentSessionImpl.h"
-#include "qmf/ConsoleSession.h"
-#include "qmf/ConsoleSessionImpl.h"
+
#include "unit_test.h"
-using namespace std;
using namespace qpid::types;
-using namespace qpid::messaging;
using namespace qmf;
-bool isReadable(int fd)
-{
- fd_set rfds;
- struct timeval tv;
- int nfds, result;
-
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
- nfds = fd + 1;
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- result = select(nfds, &rfds, NULL, NULL, &tv);
-
- return result > 0;
-}
-
namespace qpid {
namespace tests {
@@ -339,84 +315,6 @@ QPID_AUTO_TEST_CASE(testSchema)
BOOST_CHECK_THROW(method.getArgument(3), QmfException);
}
-QPID_AUTO_TEST_CASE(testAgentSessionEventListener)
-{
- Connection connection("localhost");
- AgentSession session(connection, "");
- posix::EventNotifier notifier(session);
-
- AgentSessionImpl& sessionImpl = AgentSessionImplAccess::get(session);
-
- BOOST_CHECK(sessionImpl.getEventNotifier() != 0);
-}
-
-QPID_AUTO_TEST_CASE(testConsoleSessionEventListener)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- posix::EventNotifier notifier(session);
-
- ConsoleSessionImpl& sessionImpl = ConsoleSessionImplAccess::get(session);
-
- BOOST_CHECK(sessionImpl.getEventNotifier() != 0);
-}
-
-QPID_AUTO_TEST_CASE(testGetHandle)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- posix::EventNotifier notifier(session);
-
- BOOST_CHECK(notifier.getHandle() > 0);
-}
-
-QPID_AUTO_TEST_CASE(testSetReadableToFalse)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- posix::EventNotifier notifier(session);
- PosixEventNotifierImplAccess::get(notifier).setReadable(false);
-
- bool readable(isReadable(notifier.getHandle()));
- BOOST_CHECK(!readable);
-}
-
-QPID_AUTO_TEST_CASE(testSetReadable)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- posix::EventNotifier notifier(session);
- PosixEventNotifierImplAccess::get(notifier).setReadable(true);
-
- bool readable(isReadable(notifier.getHandle()));
- BOOST_CHECK(readable);
-}
-
-QPID_AUTO_TEST_CASE(testSetReadableMultiple)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- posix::EventNotifier notifier(session);
- for (int i = 0; i < 15; i++)
- PosixEventNotifierImplAccess::get(notifier).setReadable(true);
- PosixEventNotifierImplAccess::get(notifier).setReadable(false);
-
- bool readable(isReadable(notifier.getHandle()));
- BOOST_CHECK(!readable);
-}
-
-QPID_AUTO_TEST_CASE(testDeleteNotifier)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- ConsoleSessionImpl& sessionImpl = ConsoleSessionImplAccess::get(session);
- {
- posix::EventNotifier notifier(session);
- BOOST_CHECK(sessionImpl.getEventNotifier() != 0);
- }
- BOOST_CHECK(sessionImpl.getEventNotifier() == 0);
-}
-
QPID_AUTO_TEST_SUITE_END()
}} // namespace qpid::tests
diff --git a/cpp/src/tests/QueueEvents.cpp b/cpp/src/tests/QueueEvents.cpp
index cea8bbf0db..bd18fa45fb 100644
--- a/cpp/src/tests/QueueEvents.cpp
+++ b/cpp/src/tests/QueueEvents.cpp
@@ -147,7 +147,7 @@ struct EventRecorder
QPID_AUTO_TEST_CASE(testSystemLevelEventProcessing)
{
- SessionFixture fixture;
+ ProxySessionFixture fixture;
//register dummy event listener to broker
EventRecorder listener;
fixture.broker->getQueueEvents().registerListener("recorder", boost::bind(&EventRecorder::handle, &listener, _1));
@@ -194,7 +194,7 @@ QPID_AUTO_TEST_CASE(testSystemLevelEventProcessing)
QPID_AUTO_TEST_CASE(testSystemLevelEventProcessing_enqueuesOnly)
{
- SessionFixture fixture;
+ ProxySessionFixture fixture;
//register dummy event listener to broker
EventRecorder listener;
fixture.broker->getQueueEvents().registerListener("recorder", boost::bind(&EventRecorder::handle, &listener, _1));
diff --git a/cpp/src/tests/QueueFlowLimitTest.cpp b/cpp/src/tests/QueueFlowLimitTest.cpp
deleted file mode 100644
index 8a6923fb09..0000000000
--- a/cpp/src/tests/QueueFlowLimitTest.cpp
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-#include <sstream>
-#include <deque>
-#include "unit_test.h"
-#include "test_tools.h"
-
-#include "qpid/broker/QueuePolicy.h"
-#include "qpid/broker/QueueFlowLimit.h"
-#include "qpid/sys/Time.h"
-#include "qpid/framing/reply_exceptions.h"
-#include "MessageUtils.h"
-#include "BrokerFixture.h"
-
-using namespace qpid::broker;
-using namespace qpid::framing;
-
-namespace qpid {
-namespace tests {
-
-QPID_AUTO_TEST_SUITE(QueueFlowLimitTestSuite)
-
-namespace {
-
-class TestFlow : public QueueFlowLimit
-{
-public:
- TestFlow(uint32_t flowStopCount, uint32_t flowResumeCount,
- uint64_t flowStopSize, uint64_t flowResumeSize) :
- QueueFlowLimit(0, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize)
- {}
- virtual ~TestFlow() {}
-
- static TestFlow *createTestFlow(const qpid::framing::FieldTable& settings)
- {
- FieldTable::ValuePtr v;
-
- v = settings.get(flowStopCountKey);
- uint32_t flowStopCount = (v) ? (uint32_t)v->get<int64_t>() : 0;
- v = settings.get(flowResumeCountKey);
- uint32_t flowResumeCount = (v) ? (uint32_t)v->get<int64_t>() : 0;
- v = settings.get(flowStopSizeKey);
- uint64_t flowStopSize = (v) ? (uint64_t)v->get<int64_t>() : 0;
- v = settings.get(flowResumeSizeKey);
- uint64_t flowResumeSize = (v) ? (uint64_t)v->get<int64_t>() : 0;
-
- return new TestFlow(flowStopCount, flowResumeCount, flowStopSize, flowResumeSize);
- }
-
- static QueueFlowLimit *getQueueFlowLimit(const qpid::framing::FieldTable& settings)
- {
- return QueueFlowLimit::createLimit(0, settings);
- }
-};
-
-
-
-QueuedMessage createMessage(uint32_t size)
-{
- static uint32_t seqNum;
- QueuedMessage msg;
- msg.payload = MessageUtils::createMessage();
- msg.position = ++seqNum;
- MessageUtils::addContent(msg.payload, std::string (size, 'x'));
- return msg;
-}
-}
-
-QPID_AUTO_TEST_CASE(testFlowCount)
-{
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopCountKey, 7);
- args.setInt(QueueFlowLimit::flowResumeCountKey, 5);
-
- std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args));
-
- BOOST_CHECK_EQUAL((uint32_t) 7, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 5, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
-
- std::deque<QueuedMessage> msgs;
- for (size_t i = 0; i < 6; i++) {
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(!flow->isFlowControlActive());
- }
- BOOST_CHECK(!flow->isFlowControlActive()); // 6 on queue
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(!flow->isFlowControlActive()); // 7 on queue
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(flow->isFlowControlActive()); // 8 on queue, ON
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(flow->isFlowControlActive()); // 9 on queue, no change to flow control
-
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 8 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 7 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 6 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 5 on queue, no change
-
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive()); // 4 on queue, OFF
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowSize)
-{
- FieldTable args;
- args.setUInt64(QueueFlowLimit::flowStopSizeKey, 70);
- args.setUInt64(QueueFlowLimit::flowResumeSizeKey, 50);
-
- std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args));
-
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL((uint32_t) 70, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint32_t) 50, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
-
- std::deque<QueuedMessage> msgs;
- for (size_t i = 0; i < 6; i++) {
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(!flow->isFlowControlActive());
- }
- BOOST_CHECK(!flow->isFlowControlActive()); // 60 on queue
- BOOST_CHECK_EQUAL(6u, flow->getFlowCount());
- BOOST_CHECK_EQUAL(60u, flow->getFlowSize());
-
- QueuedMessage msg_9 = createMessage(9);
- flow->enqueued(msg_9);
- BOOST_CHECK(!flow->isFlowControlActive()); // 69 on queue
- QueuedMessage tinyMsg_1 = createMessage(1);
- flow->enqueued(tinyMsg_1);
- BOOST_CHECK(!flow->isFlowControlActive()); // 70 on queue
-
- QueuedMessage tinyMsg_2 = createMessage(1);
- flow->enqueued(tinyMsg_2);
- BOOST_CHECK(flow->isFlowControlActive()); // 71 on queue, ON
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(flow->isFlowControlActive()); // 81 on queue
- BOOST_CHECK_EQUAL(10u, flow->getFlowCount());
- BOOST_CHECK_EQUAL(81u, flow->getFlowSize());
-
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 71 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 61 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 51 on queue
-
- flow->dequeued(tinyMsg_1);
- BOOST_CHECK(flow->isFlowControlActive()); // 50 on queue
- flow->dequeued(tinyMsg_2);
- BOOST_CHECK(!flow->isFlowControlActive()); // 49 on queue, OFF
-
- flow->dequeued(msg_9);
- BOOST_CHECK(!flow->isFlowControlActive()); // 40 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive()); // 30 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive()); // 20 on queue
- BOOST_CHECK_EQUAL(2u, flow->getFlowCount());
- BOOST_CHECK_EQUAL(20u, flow->getFlowSize());
-}
-
-QPID_AUTO_TEST_CASE(testFlowArgs)
-{
- FieldTable args;
- const uint64_t stop(0x2FFFFFFFFull);
- const uint64_t resume(0x1FFFFFFFFull);
- args.setInt(QueueFlowLimit::flowStopCountKey, 30);
- args.setInt(QueueFlowLimit::flowResumeCountKey, 21);
- args.setUInt64(QueueFlowLimit::flowStopSizeKey, stop);
- args.setUInt64(QueueFlowLimit::flowResumeSizeKey, resume);
-
- std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args));
-
- BOOST_CHECK_EQUAL((uint32_t) 30, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 21, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL(stop, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL(resume, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowCombo)
-{
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopCountKey, 10);
- args.setInt(QueueFlowLimit::flowResumeCountKey, 5);
- args.setUInt64(QueueFlowLimit::flowStopSizeKey, 200);
- args.setUInt64(QueueFlowLimit::flowResumeSizeKey, 100);
-
- std::deque<QueuedMessage> msgs_1;
- std::deque<QueuedMessage> msgs_10;
- std::deque<QueuedMessage> msgs_50;
- std::deque<QueuedMessage> msgs_100;
-
- QueuedMessage msg;
-
- std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args));
- BOOST_CHECK(!flow->isFlowControlActive()); // count:0 size:0
-
- // verify flow control comes ON when only count passes its stop point.
-
- for (size_t i = 0; i < 10; i++) {
- msgs_10.push_back(createMessage(10));
- flow->enqueued(msgs_10.back());
- BOOST_CHECK(!flow->isFlowControlActive());
- }
- // count:10 size:100
-
- msgs_1.push_back(createMessage(1));
- flow->enqueued(msgs_1.back()); // count:11 size: 101 ->ON
- BOOST_CHECK(flow->isFlowControlActive());
-
- for (size_t i = 0; i < 6; i++) {
- flow->dequeued(msgs_10.front());
- msgs_10.pop_front();
- BOOST_CHECK(flow->isFlowControlActive());
- }
- // count:5 size: 41
-
- flow->dequeued(msgs_1.front()); // count: 4 size: 40 ->OFF
- msgs_1.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive());
-
- for (size_t i = 0; i < 4; i++) {
- flow->dequeued(msgs_10.front());
- msgs_10.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive());
- }
- // count:0 size:0
-
- // verify flow control comes ON when only size passes its stop point.
-
- msgs_100.push_back(createMessage(100));
- flow->enqueued(msgs_100.back()); // count:1 size: 100
- BOOST_CHECK(!flow->isFlowControlActive());
-
- msgs_50.push_back(createMessage(50));
- flow->enqueued(msgs_50.back()); // count:2 size: 150
- BOOST_CHECK(!flow->isFlowControlActive());
-
- msgs_50.push_back(createMessage(50));
- flow->enqueued(msgs_50.back()); // count:3 size: 200
- BOOST_CHECK(!flow->isFlowControlActive());
-
- msgs_1.push_back(createMessage(1));
- flow->enqueued(msgs_1.back()); // count:4 size: 201 ->ON
- BOOST_CHECK(flow->isFlowControlActive());
-
- flow->dequeued(msgs_100.front()); // count:3 size:101
- msgs_100.pop_front();
- BOOST_CHECK(flow->isFlowControlActive());
-
- flow->dequeued(msgs_1.front()); // count:2 size:100
- msgs_1.pop_front();
- BOOST_CHECK(flow->isFlowControlActive());
-
- flow->dequeued(msgs_50.front()); // count:1 size:50 ->OFF
- msgs_50.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive());
-
- // verify flow control remains ON until both thresholds drop below their
- // resume point.
-
- for (size_t i = 0; i < 8; i++) {
- msgs_10.push_back(createMessage(10));
- flow->enqueued(msgs_10.back());
- BOOST_CHECK(!flow->isFlowControlActive());
- }
- // count:9 size:130
-
- msgs_10.push_back(createMessage(10));
- flow->enqueued(msgs_10.back()); // count:10 size: 140
- BOOST_CHECK(!flow->isFlowControlActive());
-
- msgs_1.push_back(createMessage(1));
- flow->enqueued(msgs_1.back()); // count:11 size: 141 ->ON
- BOOST_CHECK(flow->isFlowControlActive());
-
- msgs_100.push_back(createMessage(100));
- flow->enqueued(msgs_100.back()); // count:12 size: 241 (both thresholds crossed)
- BOOST_CHECK(flow->isFlowControlActive());
-
- // at this point: 9@10 + 1@50 + 1@100 + 1@1 == 12@241
-
- flow->dequeued(msgs_50.front()); // count:11 size:191
- msgs_50.pop_front();
- BOOST_CHECK(flow->isFlowControlActive());
-
- for (size_t i = 0; i < 9; i++) {
- flow->dequeued(msgs_10.front());
- msgs_10.pop_front();
- BOOST_CHECK(flow->isFlowControlActive());
- }
- // count:2 size:101
- flow->dequeued(msgs_1.front()); // count:1 size:100
- msgs_1.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // still active due to size
-
- flow->dequeued(msgs_100.front()); // count:0 size:0 ->OFF
- msgs_100.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive());
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowDefaultArgs)
-{
- QueueFlowLimit::setDefaults(2950001, // max queue byte count
- 80, // 80% stop threshold
- 70); // 70% resume threshold
- FieldTable args;
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
-
- BOOST_CHECK(ptr);
- std::auto_ptr<QueueFlowLimit> flow(ptr);
- BOOST_CHECK_EQUAL((uint64_t) 2360001, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint64_t) 2065000, flow->getFlowResumeSize());
- BOOST_CHECK_EQUAL( 0u, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL( 0u, flow->getFlowResumeCount());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowOverrideArgs)
-{
- QueueFlowLimit::setDefaults(2950001, // max queue byte count
- 80, // 80% stop threshold
- 70); // 70% resume threshold
- {
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopCountKey, 35000);
- args.setInt(QueueFlowLimit::flowResumeCountKey, 30000);
-
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(ptr);
- std::auto_ptr<QueueFlowLimit> flow(ptr);
-
- BOOST_CHECK_EQUAL((uint32_t) 35000, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 30000, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL((uint64_t) 0, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint64_t) 0, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
- }
- {
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopSizeKey, 350000);
- args.setInt(QueueFlowLimit::flowResumeSizeKey, 300000);
-
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(ptr);
- std::auto_ptr<QueueFlowLimit> flow(ptr);
-
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL((uint64_t) 350000, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint64_t) 300000, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
- }
- {
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopCountKey, 35000);
- args.setInt(QueueFlowLimit::flowResumeCountKey, 30000);
- args.setInt(QueueFlowLimit::flowStopSizeKey, 350000);
- args.setInt(QueueFlowLimit::flowResumeSizeKey, 300000);
-
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(ptr);
- std::auto_ptr<QueueFlowLimit> flow(ptr);
-
- BOOST_CHECK_EQUAL((uint32_t) 35000, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 30000, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL((uint64_t) 350000, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint64_t) 300000, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
- }
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowOverrideDefaults)
-{
- QueueFlowLimit::setDefaults(2950001, // max queue byte count
- 97, // stop threshold
- 73); // resume threshold
- FieldTable args;
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(ptr);
- std::auto_ptr<QueueFlowLimit> flow(ptr);
-
- BOOST_CHECK_EQUAL((uint32_t) 2861501, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint32_t) 2153500, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowDisable)
-{
- {
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopCountKey, 0);
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(!ptr);
- }
- {
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopSizeKey, 0);
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(!ptr);
- }
-}
-
-
-QPID_AUTO_TEST_SUITE_END()
-
-}} // namespace qpid::tests
diff --git a/cpp/src/tests/QueuePolicyTest.cpp b/cpp/src/tests/QueuePolicyTest.cpp
index f735e09449..90af9c7dd9 100644
--- a/cpp/src/tests/QueuePolicyTest.cpp
+++ b/cpp/src/tests/QueuePolicyTest.cpp
@@ -23,7 +23,6 @@
#include "test_tools.h"
#include "qpid/broker/QueuePolicy.h"
-#include "qpid/broker/QueueFlowLimit.h"
#include "qpid/client/QueueOptions.h"
#include "qpid/sys/Time.h"
#include "qpid/framing/reply_exceptions.h"
@@ -39,7 +38,6 @@ namespace tests {
QPID_AUTO_TEST_SUITE(QueuePolicyTestSuite)
-namespace {
QueuedMessage createMessage(uint32_t size)
{
QueuedMessage msg;
@@ -47,7 +45,7 @@ QueuedMessage createMessage(uint32_t size)
MessageUtils::addContent(msg.payload, std::string (size, 'x'));
return msg;
}
-}
+
QPID_AUTO_TEST_CASE(testCount)
{
@@ -152,7 +150,7 @@ QPID_AUTO_TEST_CASE(testRingPolicyCount)
std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::RING);
policy->update(args);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("my-ring-queue");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
for (int i = 0; i < 10; i++) {
@@ -187,7 +185,7 @@ QPID_AUTO_TEST_CASE(testRingPolicySize)
std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 0, 500, QueuePolicy::RING);
policy->update(args);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("my-ring-queue");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
@@ -259,7 +257,7 @@ QPID_AUTO_TEST_CASE(testStrictRingPolicy)
std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::RING_STRICT);
policy->update(args);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("my-ring-queue");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
LocalQueue incoming;
@@ -285,7 +283,7 @@ QPID_AUTO_TEST_CASE(testPolicyWithDtx)
std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::REJECT);
policy->update(args);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("my-policy-queue");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
LocalQueue incoming;
@@ -342,10 +340,8 @@ QPID_AUTO_TEST_CASE(testFlowToDiskWithNoStore)
//fallback to rejecting messages
QueueOptions args;
args.setSizePolicy(FLOW_TO_DISK, 0, 5);
- // Disable flow control, or else we'll never hit the max limit
- args.setInt(QueueFlowLimit::flowStopCountKey, 0);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("my-queue");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
LocalQueue incoming;
@@ -371,7 +367,7 @@ QPID_AUTO_TEST_CASE(testPolicyFailureOnCommit)
std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::REJECT);
policy->update(args);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("q");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
f.session.txSelect();
@@ -386,9 +382,8 @@ QPID_AUTO_TEST_CASE(testCapacityConversion)
{
FieldTable args;
args.setString("qpid.max_count", "5");
- args.setString("qpid.flow_stop_count", "0");
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("q");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
for (int i = 0; i < 5; i++) {
diff --git a/cpp/src/tests/QueueTest.cpp b/cpp/src/tests/QueueTest.cpp
index aaa2721021..80c69ac386 100644
--- a/cpp/src/tests/QueueTest.cpp
+++ b/cpp/src/tests/QueueTest.cpp
@@ -36,9 +36,6 @@
#include "qpid/framing/AMQFrame.h"
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/framing/reply_exceptions.h"
-#include "qpid/broker/QueuePolicy.h"
-#include "qpid/broker/QueueFlowLimit.h"
-
#include <iostream>
#include "boost/format.hpp"
@@ -56,12 +53,12 @@ class TestConsumer : public virtual Consumer{
public:
typedef boost::shared_ptr<TestConsumer> shared_ptr;
- QueuedMessage last;
+ intrusive_ptr<Message> last;
bool received;
- TestConsumer(std::string name="test", bool acquire = true):Consumer(name, acquire), received(false) {};
+ TestConsumer(bool acquire = true):Consumer(acquire), received(false) {};
virtual bool deliver(QueuedMessage& msg){
- last = msg;
+ last = msg.payload;
received = true;
return true;
};
@@ -81,14 +78,13 @@ public:
Message& getMessage() { return *(msg.get()); }
};
-intrusive_ptr<Message> create_message(std::string exchange, std::string routingKey, uint64_t ttl = 0) {
+intrusive_ptr<Message> create_message(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);
- if (ttl) msg->getFrames().getHeaders()->get<DeliveryProperties>(true)->setTtl(ttl);
return msg;
}
@@ -149,16 +145,16 @@ QPID_AUTO_TEST_CASE(testConsumers){
queue->deliver(msg1);
BOOST_CHECK(queue->dispatch(c1));
- BOOST_CHECK_EQUAL(msg1.get(), c1->last.payload.get());
+ BOOST_CHECK_EQUAL(msg1.get(), c1->last.get());
queue->deliver(msg2);
BOOST_CHECK(queue->dispatch(c2));
- BOOST_CHECK_EQUAL(msg2.get(), c2->last.payload.get());
+ BOOST_CHECK_EQUAL(msg2.get(), c2->last.get());
c1->received = false;
queue->deliver(msg3);
BOOST_CHECK(queue->dispatch(c1));
- BOOST_CHECK_EQUAL(msg3.get(), c1->last.payload.get());
+ BOOST_CHECK_EQUAL(msg3.get(), c1->last.get());
//Test cancellation:
queue->cancel(c1);
@@ -214,7 +210,7 @@ QPID_AUTO_TEST_CASE(testDequeue){
if (!consumer->received)
sleep(2);
- BOOST_CHECK_EQUAL(msg3.get(), consumer->last.payload.get());
+ BOOST_CHECK_EQUAL(msg3.get(), consumer->last.get());
BOOST_CHECK_EQUAL(uint32_t(0), queue->getMessageCount());
received = queue->get().payload;
@@ -248,7 +244,7 @@ QPID_AUTO_TEST_CASE(testBound){
exchange2.reset();
//unbind the queue from all exchanges it knows it has been bound to:
- queue->unbind(exchanges);
+ queue->unbind(exchanges, queue);
//ensure the remaining exchanges don't still have the queue bound to them:
FailOnDeliver deliverable;
@@ -258,26 +254,26 @@ QPID_AUTO_TEST_CASE(testBound){
QPID_AUTO_TEST_CASE(testPersistLastNodeStanding){
client::QueueOptions args;
- args.setPersistLastNode();
+ args.setPersistLastNode();
- Queue::shared_ptr queue(new Queue("my-queue", true));
+ Queue::shared_ptr queue(new Queue("my-queue", true));
queue->configure(args);
intrusive_ptr<Message> msg1 = create_message("e", "A");
intrusive_ptr<Message> msg2 = create_message("e", "B");
intrusive_ptr<Message> msg3 = create_message("e", "C");
- //enqueue 2 messages
+ //enqueue 2 messages
queue->deliver(msg1);
queue->deliver(msg2);
- //change mode
- queue->setLastNodeFailure();
+ //change mode
+ queue->setLastNodeFailure();
- //enqueue 1 message
+ //enqueue 1 message
queue->deliver(msg3);
- //check all have persistent ids.
+ //check all have persistent ids.
BOOST_CHECK(msg1->isPersistent());
BOOST_CHECK(msg2->isPersistent());
BOOST_CHECK(msg3->isPersistent());
@@ -287,58 +283,54 @@ QPID_AUTO_TEST_CASE(testPersistLastNodeStanding){
QPID_AUTO_TEST_CASE(testSeek){
- Queue::shared_ptr queue(new Queue("my-queue", true));
+ Queue::shared_ptr queue(new Queue("my-queue", true));
intrusive_ptr<Message> msg1 = create_message("e", "A");
intrusive_ptr<Message> msg2 = create_message("e", "B");
intrusive_ptr<Message> msg3 = create_message("e", "C");
- //enqueue 2 messages
+ //enqueue 2 messages
queue->deliver(msg1);
queue->deliver(msg2);
queue->deliver(msg3);
- TestConsumer::shared_ptr consumer(new TestConsumer("test", false));
+ TestConsumer::shared_ptr consumer(new TestConsumer(false));
SequenceNumber seq(2);
consumer->position = seq;
QueuedMessage qm;
queue->dispatch(consumer);
-
- BOOST_CHECK_EQUAL(msg3.get(), consumer->last.payload.get());
+
+ BOOST_CHECK_EQUAL(msg3.get(), consumer->last.get());
queue->dispatch(consumer);
queue->dispatch(consumer); // make sure over-run is safe
-
+
}
QPID_AUTO_TEST_CASE(testSearch){
- Queue::shared_ptr queue(new Queue("my-queue", true));
+ Queue::shared_ptr queue(new Queue("my-queue", true));
intrusive_ptr<Message> msg1 = create_message("e", "A");
intrusive_ptr<Message> msg2 = create_message("e", "B");
intrusive_ptr<Message> msg3 = create_message("e", "C");
- //enqueue 2 messages
+ //enqueue 2 messages
queue->deliver(msg1);
queue->deliver(msg2);
queue->deliver(msg3);
SequenceNumber seq(2);
- QueuedMessage qm;
- TestConsumer::shared_ptr c1(new TestConsumer());
-
- BOOST_CHECK(queue->find(seq, qm));
-
+ QueuedMessage qm = queue->find(seq);
+
BOOST_CHECK_EQUAL(seq.getValue(), qm.position.getValue());
-
- queue->acquire(qm, c1->getName());
+
+ queue->acquire(qm);
BOOST_CHECK_EQUAL(queue->getMessageCount(), 2u);
SequenceNumber seq1(3);
- QueuedMessage qm1;
- BOOST_CHECK(queue->find(seq1, qm1));
+ QueuedMessage qm1 = queue->find(seq1);
BOOST_CHECK_EQUAL(seq1.getValue(), qm1.position.getValue());
-
+
}
const std::string nullxid = "";
@@ -424,10 +416,10 @@ QPID_AUTO_TEST_CASE(testLVQOrdering){
client::QueueOptions args;
// set queue mode
- args.setOrdering(client::LVQ);
+ args.setOrdering(client::LVQ);
- Queue::shared_ptr queue(new Queue("my-queue", true ));
- queue->configure(args);
+ Queue::shared_ptr queue(new Queue("my-queue", true ));
+ queue->configure(args);
intrusive_ptr<Message> msg1 = create_message("e", "A");
intrusive_ptr<Message> msg2 = create_message("e", "B");
@@ -438,16 +430,16 @@ QPID_AUTO_TEST_CASE(testLVQOrdering){
//set deliever match for LVQ a,b,c,a
string key;
- args.getLVQKey(key);
+ args.getLVQKey(key);
BOOST_CHECK_EQUAL(key, "qpid.LVQ_key");
- msg1->insertCustomProperty(key,"a");
- msg2->insertCustomProperty(key,"b");
- msg3->insertCustomProperty(key,"c");
- msg4->insertCustomProperty(key,"a");
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b");
+ msg3->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c");
+ msg4->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
- //enqueue 4 message
+ //enqueue 4 message
queue->deliver(msg1);
queue->deliver(msg2);
queue->deliver(msg3);
@@ -467,9 +459,9 @@ QPID_AUTO_TEST_CASE(testLVQOrdering){
intrusive_ptr<Message> msg5 = create_message("e", "A");
intrusive_ptr<Message> msg6 = create_message("e", "B");
intrusive_ptr<Message> msg7 = create_message("e", "C");
- msg5->insertCustomProperty(key,"a");
- msg6->insertCustomProperty(key,"b");
- msg7->insertCustomProperty(key,"c");
+ msg5->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg6->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b");
+ msg7->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c");
queue->deliver(msg5);
queue->deliver(msg6);
queue->deliver(msg7);
@@ -504,7 +496,7 @@ QPID_AUTO_TEST_CASE(testLVQEmptyKey){
BOOST_CHECK_EQUAL(key, "qpid.LVQ_key");
- msg1->insertCustomProperty(key,"a");
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
queue->deliver(msg1);
queue->deliver(msg2);
BOOST_CHECK_EQUAL(queue->getMessageCount(), 2u);
@@ -516,8 +508,6 @@ QPID_AUTO_TEST_CASE(testLVQAcquire){
client::QueueOptions args;
// set queue mode
args.setOrdering(client::LVQ);
- // disable flow control, as this test violates the enqueue/dequeue sequence.
- args.setInt(QueueFlowLimit::flowStopCountKey, 0);
Queue::shared_ptr queue(new Queue("my-queue", true ));
queue->configure(args);
@@ -536,12 +526,12 @@ QPID_AUTO_TEST_CASE(testLVQAcquire){
BOOST_CHECK_EQUAL(key, "qpid.LVQ_key");
- msg1->insertCustomProperty(key,"a");
- msg2->insertCustomProperty(key,"b");
- msg3->insertCustomProperty(key,"c");
- msg4->insertCustomProperty(key,"a");
- msg5->insertCustomProperty(key,"b");
- msg6->insertCustomProperty(key,"c");
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b");
+ msg3->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c");
+ msg4->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg5->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b");
+ msg6->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c");
//enqueue 4 message
queue->deliver(msg1);
@@ -556,13 +546,12 @@ QPID_AUTO_TEST_CASE(testLVQAcquire){
QueuedMessage qmsg2(queue.get(), msg2, ++sequence);
framing::SequenceNumber sequence1(10);
QueuedMessage qmsg3(queue.get(), 0, sequence1);
- TestConsumer::shared_ptr dummy(new TestConsumer());
- BOOST_CHECK(!queue->acquire(qmsg, dummy->getName()));
- BOOST_CHECK(queue->acquire(qmsg2, dummy->getName()));
+ BOOST_CHECK(!queue->acquire(qmsg));
+ BOOST_CHECK(queue->acquire(qmsg2));
// Acquire the massage again to test failure case.
- BOOST_CHECK(!queue->acquire(qmsg2, dummy->getName()));
- BOOST_CHECK(!queue->acquire(qmsg3, dummy->getName()));
+ BOOST_CHECK(!queue->acquire(qmsg2));
+ BOOST_CHECK(!queue->acquire(qmsg3));
BOOST_CHECK_EQUAL(queue->getMessageCount(), 2u);
@@ -572,7 +561,7 @@ QPID_AUTO_TEST_CASE(testLVQAcquire){
// set mode to no browse and check
args.setOrdering(client::LVQ_NO_BROWSE);
queue->configure(args);
- TestConsumer::shared_ptr c1(new TestConsumer("test", false));
+ TestConsumer::shared_ptr c1(new TestConsumer(false));
queue->dispatch(c1);
queue->dispatch(c1);
@@ -606,8 +595,8 @@ QPID_AUTO_TEST_CASE(testLVQMultiQueue){
args.getLVQKey(key);
BOOST_CHECK_EQUAL(key, "qpid.LVQ_key");
- msg1->insertCustomProperty(key,"a");
- msg2->insertCustomProperty(key,"a");
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
queue1->deliver(msg1);
queue2->deliver(msg1);
@@ -641,7 +630,7 @@ QPID_AUTO_TEST_CASE(testLVQRecover){
Queue::shared_ptr queue1(new Queue("my-queue", true, &testStore));
intrusive_ptr<Message> received;
- queue1->create(args);
+ queue1->configure(args);
intrusive_ptr<Message> msg1 = create_message("e", "A");
intrusive_ptr<Message> msg2 = create_message("e", "A");
@@ -650,9 +639,9 @@ QPID_AUTO_TEST_CASE(testLVQRecover){
args.getLVQKey(key);
BOOST_CHECK_EQUAL(key, "qpid.LVQ_key");
- msg1->insertCustomProperty(key,"a");
- msg2->insertCustomProperty(key,"a");
- // 3
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ // 3
queue1->deliver(msg1);
// 4
queue1->setLastNodeFailure();
@@ -671,8 +660,13 @@ QPID_AUTO_TEST_CASE(testLVQRecover){
void addMessagesToQueue(uint count, Queue& queue, uint oddTtl = 200, uint evenTtl = 0)
{
for (uint i = 0; i < count; i++) {
- intrusive_ptr<Message> m = create_message("exchange", "key", i % 2 ? oddTtl : evenTtl);
- m->computeExpiration(new broker::ExpiryPolicy);
+ intrusive_ptr<Message> m = create_message("exchange", "key");
+ if (i % 2) {
+ if (oddTtl) m->getProperties<DeliveryProperties>()->setTtl(oddTtl);
+ } else {
+ if (evenTtl) m->getProperties<DeliveryProperties>()->setTtl(evenTtl);
+ }
+ m->setTimestamp(new broker::ExpiryPolicy);
queue.deliver(m);
}
}
@@ -682,7 +676,7 @@ QPID_AUTO_TEST_CASE(testPurgeExpired) {
addMessagesToQueue(10, queue);
BOOST_CHECK_EQUAL(queue.getMessageCount(), 10u);
::usleep(300*1000);
- queue.purgeExpired(0);
+ queue.purgeExpired();
BOOST_CHECK_EQUAL(queue.getMessageCount(), 5u);
}
@@ -693,7 +687,7 @@ QPID_AUTO_TEST_CASE(testQueueCleaner) {
addMessagesToQueue(10, *queue, 200, 400);
BOOST_CHECK_EQUAL(queue->getMessageCount(), 10u);
- QueueCleaner cleaner(queues, &timer);
+ QueueCleaner cleaner(queues, timer);
cleaner.start(100 * qpid::sys::TIME_MSEC);
::usleep(300*1000);
BOOST_CHECK_EQUAL(queue->getMessageCount(), 5u);
@@ -701,280 +695,6 @@ QPID_AUTO_TEST_CASE(testQueueCleaner) {
BOOST_CHECK_EQUAL(queue->getMessageCount(), 0u);
}
-
-namespace {
- // helper for group tests
- void verifyAcquire( Queue::shared_ptr queue,
- TestConsumer::shared_ptr c,
- std::deque<QueuedMessage>& results,
- const std::string& expectedGroup,
- const int expectedId )
- {
- queue->dispatch(c);
- results.push_back(c->last);
- std::string group = c->last.payload->getProperties<MessageProperties>()->getApplicationHeaders().getAsString("GROUP-ID");
- int id = c->last.payload->getProperties<MessageProperties>()->getApplicationHeaders().getAsInt("MY-ID");
- BOOST_CHECK_EQUAL( group, expectedGroup );
- BOOST_CHECK_EQUAL( id, expectedId );
- }
-}
-
-QPID_AUTO_TEST_CASE(testGroupsMultiConsumer) {
- //
- // Verify that consumers of grouped messages own the groups once a message is acquired,
- // and release the groups once all acquired messages have been dequeued or requeued
- //
- FieldTable args;
- Queue::shared_ptr queue(new Queue("my_queue", true));
- args.setString("qpid.group_header_key", "GROUP-ID");
- args.setInt("qpid.shared_msg_group", 1);
- queue->configure(args);
-
- std::string groups[] = { std::string("a"), std::string("a"), std::string("a"),
- std::string("b"), std::string("b"), std::string("b"),
- std::string("c"), std::string("c"), std::string("c") };
- for (int i = 0; i < 9; ++i) {
- intrusive_ptr<Message> msg = create_message("e", "A");
- msg->insertCustomProperty("GROUP-ID", groups[i]);
- msg->insertCustomProperty("MY-ID", i);
- queue->deliver(msg);
- }
-
- // Queue = a-0, a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- // Owners= ---, ---, ---, ---, ---, ---, ---, ---, ---,
-
- BOOST_CHECK_EQUAL(uint32_t(9), queue->getMessageCount());
-
- TestConsumer::shared_ptr c1(new TestConsumer("C1"));
- TestConsumer::shared_ptr c2(new TestConsumer("C2"));
-
- queue->consume(c1);
- queue->consume(c2);
-
- std::deque<QueuedMessage> dequeMeC1;
- std::deque<QueuedMessage> dequeMeC2;
-
-
- verifyAcquire(queue, c1, dequeMeC1, "a", 0 ); // c1 now owns group "a" (acquire a-0)
- verifyAcquire(queue, c2, dequeMeC2, "b", 3 ); // c2 should now own group "b" (acquire b-3)
-
- // now let c1 complete the 'a-0' message - this should free the 'a' group
- queue->dequeue( 0, dequeMeC1.front() );
- dequeMeC1.pop_front();
-
- // Queue = a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- // Owners= ---, ---, ^C2, ^C2, ^C2, ---, ---, ---
-
- // now c2 should pick up the next 'a-1', since it is oldest free
- verifyAcquire(queue, c2, dequeMeC2, "a", 1 ); // c2 should now own groups "a" and "b"
-
- // Queue = a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- // Owners= ^C2, ^C2, ^C2, ^C2, ^C2, ---, ---, ---
-
- // c1 should only be able to snarf up the first "c" message now...
- verifyAcquire(queue, c1, dequeMeC1, "c", 6 ); // should skip to the first "c"
-
- // Queue = a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- // Owners= ^C2, ^C2, ^C2, ^C2, ^C2, ^C1, ^C1, ^C1
-
- // hmmm... what if c2 now dequeues "b-3"? (now only has a-1 acquired)
- queue->dequeue( 0, dequeMeC2.front() );
- dequeMeC2.pop_front();
-
- // Queue = a-1, a-2, b-4, b-5, c-6, c-7, c-8...
- // Owners= ^C2, ^C2, ---, ---, ^C1, ^C1, ^C1
-
- // b group is free, c is owned by c1 - c1's next get should grab 'b-4'
- verifyAcquire(queue, c1, dequeMeC1, "b", 4 );
-
- // Queue = a-1, a-2, b-4, b-5, c-6, c-7, c-8...
- // Owners= ^C2, ^C2, ^C1, ^C1, ^C1, ^C1, ^C1
-
- // c2 can now only grab a-2, and that's all
- verifyAcquire(queue, c2, dequeMeC2, "a", 2 );
-
- // now C2 can't get any more, since C1 owns "b" and "c" group...
- bool gotOne = queue->dispatch(c2);
- BOOST_CHECK( !gotOne );
-
- // hmmm... what if c1 now dequeues "c-6"? (now only own's b-4)
- queue->dequeue( 0, dequeMeC1.front() );
- dequeMeC1.pop_front();
-
- // Queue = a-1, a-2, b-4, b-5, c-7, c-8...
- // Owners= ^C2, ^C2, ^C1, ^C1, ---, ---
-
- // c2 can now grab c-7
- verifyAcquire(queue, c2, dequeMeC2, "c", 7 );
-
- // Queue = a-1, a-2, b-4, b-5, c-7, c-8...
- // Owners= ^C2, ^C2, ^C1, ^C1, ^C2, ^C2
-
- // what happens if C-2 "requeues" a-1 and a-2?
- queue->requeue( dequeMeC2.front() );
- dequeMeC2.pop_front();
- queue->requeue( dequeMeC2.front() );
- dequeMeC2.pop_front(); // now just has c-7 acquired
-
- // Queue = a-1, a-2, b-4, b-5, c-7, c-8...
- // Owners= ---, ---, ^C1, ^C1, ^C2, ^C2
-
- // now c1 will grab a-1 and a-2...
- verifyAcquire(queue, c1, dequeMeC1, "a", 1 );
- verifyAcquire(queue, c1, dequeMeC1, "a", 2 );
-
- // Queue = a-1, a-2, b-4, b-5, c-7, c-8...
- // Owners= ^C1, ^C1, ^C1, ^C1, ^C2, ^C2
-
- // c2 can now acquire c-8 only
- verifyAcquire(queue, c2, dequeMeC2, "c", 8 );
-
- // and c1 can get b-5
- verifyAcquire(queue, c1, dequeMeC1, "b", 5 );
-
- // should be no more acquire-able for anyone now:
- gotOne = queue->dispatch(c1);
- BOOST_CHECK( !gotOne );
- gotOne = queue->dispatch(c2);
- BOOST_CHECK( !gotOne );
-
- // requeue all of C1's acquired messages, then cancel C1
- while (!dequeMeC1.empty()) {
- queue->requeue(dequeMeC1.front());
- dequeMeC1.pop_front();
- }
- queue->cancel(c1);
-
- // Queue = a-1, a-2, b-4, b-5, c-7, c-8...
- // Owners= ---, ---, ---, ---, ^C2, ^C2
-
- // b-4, a-1, a-2, b-5 all should be available, right?
- verifyAcquire(queue, c2, dequeMeC2, "a", 1 );
-
- while (!dequeMeC2.empty()) {
- queue->dequeue(0, dequeMeC2.front());
- dequeMeC2.pop_front();
- }
-
- // Queue = a-2, b-4, b-5
- // Owners= ---, ---, ---
-
- TestConsumer::shared_ptr c3(new TestConsumer("C3"));
- std::deque<QueuedMessage> dequeMeC3;
-
- verifyAcquire(queue, c3, dequeMeC3, "a", 2 );
- verifyAcquire(queue, c2, dequeMeC2, "b", 4 );
-
- // Queue = a-2, b-4, b-5
- // Owners= ^C3, ^C2, ^C2
-
- gotOne = queue->dispatch(c3);
- BOOST_CHECK( !gotOne );
-
- verifyAcquire(queue, c2, dequeMeC2, "b", 5 );
-
- while (!dequeMeC2.empty()) {
- queue->dequeue(0, dequeMeC2.front());
- dequeMeC2.pop_front();
- }
-
- // Queue = a-2,
- // Owners= ^C3,
-
- intrusive_ptr<Message> msg = create_message("e", "A");
- msg->insertCustomProperty("GROUP-ID", "a");
- msg->insertCustomProperty("MY-ID", 9);
- queue->deliver(msg);
-
- // Queue = a-2, a-9
- // Owners= ^C3, ^C3
-
- gotOne = queue->dispatch(c2);
- BOOST_CHECK( !gotOne );
-
- msg = create_message("e", "A");
- msg->insertCustomProperty("GROUP-ID", "b");
- msg->insertCustomProperty("MY-ID", 10);
- queue->deliver(msg);
-
- // Queue = a-2, a-9, b-10
- // Owners= ^C3, ^C3, ----
-
- verifyAcquire(queue, c2, dequeMeC2, "b", 10 );
- verifyAcquire(queue, c3, dequeMeC3, "a", 9 );
-
- gotOne = queue->dispatch(c3);
- BOOST_CHECK( !gotOne );
-
- queue->cancel(c2);
- queue->cancel(c3);
-}
-
-
-QPID_AUTO_TEST_CASE(testGroupsMultiConsumerDefaults) {
- //
- // Verify that the same default group name is automatically applied to messages that
- // do not specify a group name.
- //
- FieldTable args;
- Queue::shared_ptr queue(new Queue("my_queue", true));
- args.setString("qpid.group_header_key", "GROUP-ID");
- args.setInt("qpid.shared_msg_group", 1);
- queue->configure(args);
-
- for (int i = 0; i < 3; ++i) {
- intrusive_ptr<Message> msg = create_message("e", "A");
- // no "GROUP-ID" header
- msg->insertCustomProperty("MY-ID", i);
- queue->deliver(msg);
- }
-
- // Queue = 0, 1, 2
-
- BOOST_CHECK_EQUAL(uint32_t(3), queue->getMessageCount());
-
- TestConsumer::shared_ptr c1(new TestConsumer("C1"));
- TestConsumer::shared_ptr c2(new TestConsumer("C2"));
-
- queue->consume(c1);
- queue->consume(c2);
-
- std::deque<QueuedMessage> dequeMeC1;
- std::deque<QueuedMessage> dequeMeC2;
-
- queue->dispatch(c1); // c1 now owns default group (acquired 0)
- dequeMeC1.push_back(c1->last);
- int id = c1->last.payload->getProperties<MessageProperties>()->getApplicationHeaders().getAsInt("MY-ID");
- BOOST_CHECK_EQUAL( id, 0 );
-
- bool gotOne = queue->dispatch(c2); // c2 should get nothing
- BOOST_CHECK( !gotOne );
-
- queue->dispatch(c1); // c1 now acquires 1
- dequeMeC1.push_back(c1->last);
- id = c1->last.payload->getProperties<MessageProperties>()->getApplicationHeaders().getAsInt("MY-ID");
- BOOST_CHECK_EQUAL( id, 1 );
-
- gotOne = queue->dispatch(c2); // c2 should still get nothing
- BOOST_CHECK( !gotOne );
-
- while (!dequeMeC1.empty()) {
- queue->dequeue(0, dequeMeC1.front());
- dequeMeC1.pop_front();
- }
-
- // now default group should be available...
- queue->dispatch(c2); // c2 now owns default group (acquired 2)
- id = c2->last.payload->getProperties<MessageProperties>()->getApplicationHeaders().getAsInt("MY-ID");
- BOOST_CHECK_EQUAL( id, 2 );
-
- gotOne = queue->dispatch(c1); // c1 should get nothing
- BOOST_CHECK( !gotOne );
-
- queue->cancel(c1);
- queue->cancel(c2);
-}
-
QPID_AUTO_TEST_CASE(testMultiQueueLastNode){
TestMessageStoreOC testStore;
@@ -982,9 +702,9 @@ QPID_AUTO_TEST_CASE(testMultiQueueLastNode){
args.setPersistLastNode();
Queue::shared_ptr queue1(new Queue("queue1", true, &testStore ));
- queue1->create(args);
+ queue1->configure(args);
Queue::shared_ptr queue2(new Queue("queue2", true, &testStore ));
- queue2->create(args);
+ queue2->configure(args);
intrusive_ptr<Message> msg1 = create_message("e", "A");
@@ -1070,7 +790,7 @@ not requeued to the store.
Queue::shared_ptr queue1(new Queue("my-queue", true, &testStore));
intrusive_ptr<Message> received;
- queue1->create(args);
+ queue1->configure(args);
// check requeue 1
intrusive_ptr<Message> msg1 = create_message("e", "C");
@@ -1150,40 +870,28 @@ QPID_AUTO_TEST_CASE(testFlowToDiskBlocking){
intrusive_ptr<Message> msg02 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
DeliverableMessage dmsg02(msg02);
- {
- ScopedSuppressLogging sl; // suppress expected error messages.
- BOOST_CHECK_THROW(sbtFanout1.route(dmsg02, "", 0), ResourceLimitExceededException);
- }
+ 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);
- {
- ScopedSuppressLogging sl; // suppress expected error messages.
- BOOST_CHECK_THROW(sbtFanout1.route(dmsg03, "", 0), ResourceLimitExceededException);
- }
+ 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);
- {
- ScopedSuppressLogging sl; // suppress expected error messages.
- BOOST_CHECK_THROW(sbtFanout1.route(dmsg04, "", 0), ResourceLimitExceededException);
- }
+ 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);
- {
- ScopedSuppressLogging sl; // suppress expected error messages.
- BOOST_CHECK_THROW(sbtFanout1.route(dmsg05, "", 0), ResourceLimitExceededException);
- }
+ BOOST_CHECK_THROW(sbtFanout1.route(dmsg05, "", 0), ResourceLimitExceededException);
msg05->tryReleaseContent();
BOOST_CHECK_EQUAL(msg05->isContentReleased(), false);
BOOST_CHECK_EQUAL(1u, tq1->getMessageCount());
diff --git a/cpp/src/tests/ReplicationTest.cpp b/cpp/src/tests/ReplicationTest.cpp
index 1219a6b59e..7310a3fe20 100644
--- a/cpp/src/tests/ReplicationTest.cpp
+++ b/cpp/src/tests/ReplicationTest.cpp
@@ -74,7 +74,7 @@ QPID_AUTO_TEST_CASE(testReplicationExchange)
{
qpid::broker::Broker::Options brokerOpts(getBrokerOpts(list_of<string>("qpidd")
("--replication-exchange-name=qpid.replication")));
- SessionFixture f(brokerOpts);
+ ProxySessionFixture f(brokerOpts);
std::string dataQ("queue-1");
diff --git a/cpp/src/tests/SessionState.cpp b/cpp/src/tests/SessionState.cpp
index 3be9bb0cbc..157cabfb63 100644
--- a/cpp/src/tests/SessionState.cpp
+++ b/cpp/src/tests/SessionState.cpp
@@ -43,7 +43,7 @@ using namespace qpid::framing;
// Apply f to [begin, end) and accumulate the result
template <class Iter, class T, class F>
T applyAccumulate(Iter begin, Iter end, T seed, const F& f) {
- return std::accumulate(begin, end, seed, boost::bind(std::plus<T>(), _1, boost::bind(f, _2)));
+ return std::accumulate(begin, end, seed, bind(std::plus<T>(), _1, bind(f, _2)));
}
// Create a frame with a one-char string.
@@ -105,8 +105,8 @@ size_t transferN(qpid::SessionState& s, string content) {
char last = content[content.size()-1];
content.resize(content.size()-1);
size += applyAccumulate(content.begin(), content.end(), 0,
- boost::bind(&send, boost::ref(s),
- boost::bind(contentFrameChar, _1, false)));
+ bind(&send, ref(s),
+ bind(contentFrameChar, _1, false)));
size += send(s, contentFrameChar(last, true));
}
return size;
@@ -115,7 +115,7 @@ size_t transferN(qpid::SessionState& s, string content) {
// Send multiple transfers with single-byte content.
size_t transfers(qpid::SessionState& s, string content) {
return applyAccumulate(content.begin(), content.end(), 0,
- boost::bind(transfer1Char, boost::ref(s), _1));
+ bind(transfer1Char, ref(s), _1));
}
size_t contentFrameSize(size_t n=1) { return AMQFrame(( AMQContentBody())).encodedSize() + n; }
diff --git a/cpp/src/tests/SocketProxy.h b/cpp/src/tests/SocketProxy.h
new file mode 100644
index 0000000000..0c6f39d62e
--- /dev/null
+++ b/cpp/src/tests/SocketProxy.h
@@ -0,0 +1,181 @@
+#ifndef SOCKETPROXY_H
+#define SOCKETPROXY_H
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/sys/IOHandle.h"
+#ifdef _WIN32
+# include "qpid/sys/windows/IoHandlePrivate.h"
+ typedef SOCKET FdType;
+#else
+# include "qpid/sys/posix/PrivatePosix.h"
+ typedef int FdType;
+#endif
+#include "qpid/sys/Socket.h"
+#include "qpid/sys/Runnable.h"
+#include "qpid/sys/Thread.h"
+#include "qpid/sys/Mutex.h"
+#include "qpid/log/Statement.h"
+
+namespace qpid {
+namespace tests {
+
+/**
+ * A simple socket proxy that forwards to another socket.
+ * Used between client & local broker to simulate network failures.
+ */
+class SocketProxy : private qpid::sys::Runnable
+{
+ // Need a Socket we can get the fd from
+ class LowSocket : public qpid::sys::Socket {
+ public:
+#ifdef _WIN32
+ FdType getFd() { return toSocketHandle(*this); }
+#else
+ FdType getFd() { return toFd(impl); }
+#endif
+ };
+
+ public:
+ /** Connect to connectPort on host, start a forwarding thread.
+ * Listen for connection on getPort().
+ */
+ SocketProxy(int connectPort, const std::string host="localhost")
+ : closed(false), joined(true),
+ port(listener.listen()), dropClient(), dropServer()
+ {
+ client.connect(host, connectPort);
+ joined = false;
+ thread = qpid::sys::Thread(static_cast<qpid::sys::Runnable*>(this));
+ }
+
+ ~SocketProxy() { close(); if (!joined) thread.join(); }
+
+ /** Simulate a network disconnect. */
+ void close() {
+ {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ if (closed) { return; }
+ closed=true;
+ }
+ if (thread && thread != qpid::sys::Thread::current()) {
+ thread.join();
+ joined = true;
+ }
+ client.close();
+ }
+
+ /** Simulate lost packets, drop data from client */
+ void dropClientData(bool drop=true) { dropClient=drop; }
+
+ /** Simulate lost packets, drop data from server */
+ void dropServerData(bool drop=true) { dropServer=drop; }
+
+ bool isClosed() const {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ return closed;
+ }
+
+ uint16_t getPort() const { return port; }
+
+ private:
+ static void throwErrno(const std::string& msg) {
+ throw qpid::Exception(msg+":"+qpid::sys::strError(errno));
+ }
+ static void throwIf(bool condition, const std::string& msg) {
+ if (condition) throw qpid::Exception(msg);
+ }
+
+ void run() {
+ std::auto_ptr<LowSocket> server;
+ try {
+ fd_set socks;
+ FdType maxFd = listener.getFd();
+ struct timeval tmo;
+ for (;;) {
+ FD_ZERO(&socks);
+ FD_SET(maxFd, &socks);
+ tmo.tv_sec = 0;
+ tmo.tv_usec = 500 * 1000;
+ if (select(maxFd+1, &socks, 0, 0, &tmo) == 0) {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ throwIf(closed, "SocketProxy: Closed by close()");
+ continue;
+ }
+ throwIf(!FD_ISSET(maxFd, &socks), "SocketProxy: Accept failed");
+ break; // Accept ready... go to next step
+ }
+ server.reset(reinterpret_cast<LowSocket *>(listener.accept()));
+ maxFd = server->getFd();
+ if (client.getFd() > maxFd)
+ maxFd = client.getFd();
+ char buffer[1024];
+ for (;;) {
+ FD_ZERO(&socks);
+ tmo.tv_sec = 0;
+ tmo.tv_usec = 500 * 1000;
+ FD_SET(client.getFd(), &socks);
+ FD_SET(server->getFd(), &socks);
+ if (select(maxFd+1, &socks, 0, 0, &tmo) == 0) {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ throwIf(closed, "SocketProxy: Closed by close()");
+ continue;
+ }
+ // Something is set; relay data as needed until something closes
+ if (FD_ISSET(server->getFd(), &socks)) {
+ int n = server->read(buffer, sizeof(buffer));
+ throwIf(n <= 0, "SocketProxy: server disconnected");
+ if (!dropServer) client.write(buffer, n);
+ }
+ if (FD_ISSET(client.getFd(), &socks)) {
+ int n = client.read(buffer, sizeof(buffer));
+ throwIf(n <= 0, "SocketProxy: client disconnected");
+ if (!dropServer) server->write(buffer, n);
+ }
+ if (!FD_ISSET(client.getFd(), &socks) &&
+ !FD_ISSET(server->getFd(), &socks))
+ throwIf(true, "SocketProxy: No handle ready");
+ }
+ }
+ catch (const std::exception& e) {
+ QPID_LOG(debug, "SocketProxy::run exception: " << e.what());
+ }
+ try {
+ if (server.get()) server->close();
+ close();
+ }
+ catch (const std::exception& e) {
+ QPID_LOG(debug, "SocketProxy::run exception in client/server close()" << e.what());
+ }
+ }
+
+ mutable qpid::sys::Mutex lock;
+ mutable bool closed;
+ bool joined;
+ LowSocket client, listener;
+ uint16_t port;
+ qpid::sys::Thread thread;
+ bool dropClient, dropServer;
+};
+
+}} // namespace qpid::tests
+
+#endif
diff --git a/cpp/src/tests/TimerTest.cpp b/cpp/src/tests/TimerTest.cpp
index 6a0a196f4e..7df94164e0 100644
--- a/cpp/src/tests/TimerTest.cpp
+++ b/cpp/src/tests/TimerTest.cpp
@@ -77,10 +77,8 @@ class TestTask : public TimerTask
BOOST_CHECK(fired);
BOOST_CHECK_EQUAL(expected_position, position);
Duration actual(start, end);
-#ifdef _MSC_VER
+#ifdef _WIN32
uint64_t difference = _abs64(expected - actual);
-#elif defined(_WIN32)
- uint64_t difference = labs(expected - actual);
#else
uint64_t difference = abs(expected - actual);
#endif
diff --git a/cpp/src/tests/TxPublishTest.cpp b/cpp/src/tests/TxPublishTest.cpp
index 152581e4ba..6b44d95baa 100644
--- a/cpp/src/tests/TxPublishTest.cpp
+++ b/cpp/src/tests/TxPublishTest.cpp
@@ -50,9 +50,10 @@ struct TxPublishTest
TxPublishTest() :
queue1(new Queue("queue1", false, &store, 0)),
queue2(new Queue("queue2", false, &store, 0)),
- msg(MessageUtils::createMessage("exchange", "routing_key", true)),
+ msg(MessageUtils::createMessage("exchange", "routing_key", false, "id")),
op(msg)
{
+ msg->getProperties<DeliveryProperties>()->setDeliveryMode(PERSISTENT);
op.deliverTo(queue1);
op.deliverTo(queue2);
}
@@ -73,7 +74,7 @@ QPID_AUTO_TEST_CASE(testPrepare)
BOOST_CHECK_EQUAL(pmsg, t.store.enqueued[0].second);
BOOST_CHECK_EQUAL(string("queue2"), t.store.enqueued[1].first);
BOOST_CHECK_EQUAL(pmsg, t.store.enqueued[1].second);
- BOOST_CHECK_EQUAL( true, ( boost::static_pointer_cast<PersistableMessage>(t.msg))->isIngressComplete());
+ BOOST_CHECK_EQUAL( true, ( boost::static_pointer_cast<PersistableMessage>(t.msg))->isEnqueueComplete());
}
QPID_AUTO_TEST_CASE(testCommit)
@@ -86,7 +87,7 @@ QPID_AUTO_TEST_CASE(testCommit)
BOOST_CHECK_EQUAL((uint32_t) 1, t.queue1->getMessageCount());
intrusive_ptr<Message> msg_dequeue = t.queue1->get().payload;
- BOOST_CHECK_EQUAL( true, (boost::static_pointer_cast<PersistableMessage>(msg_dequeue))->isIngressComplete());
+ BOOST_CHECK_EQUAL( true, (boost::static_pointer_cast<PersistableMessage>(msg_dequeue))->isEnqueueComplete());
BOOST_CHECK_EQUAL(t.msg, msg_dequeue);
BOOST_CHECK_EQUAL((uint32_t) 1, t.queue2->getMessageCount());
diff --git a/cpp/src/tests/Url.cpp b/cpp/src/tests/Url.cpp
index b30de682bc..234a62ee91 100644
--- a/cpp/src/tests/Url.cpp
+++ b/cpp/src/tests/Url.cpp
@@ -60,32 +60,6 @@ QPID_AUTO_TEST_CASE(TestParseXyz) {
BOOST_CHECK_EQUAL(Url("xyz:host").str(), "amqp:xyz:host:5672");
}
-QPID_AUTO_TEST_CASE(TestParseTricky) {
- BOOST_CHECK_EQUAL(Url("amqp").str(), "amqp:tcp:amqp:5672");
- BOOST_CHECK_EQUAL(Url("amqp:tcp").str(), "amqp:tcp:tcp:5672");
- // These are ambiguous parses and arguably not the best result
- BOOST_CHECK_EQUAL(Url("amqp:876").str(), "amqp:tcp:876:5672");
- BOOST_CHECK_EQUAL(Url("tcp:567").str(), "amqp:tcp:567:5672");
-}
-
-QPID_AUTO_TEST_CASE(TestParseIPv6) {
- Url u1("[::]");
- BOOST_CHECK_EQUAL(u1[0].host, "::");
- BOOST_CHECK_EQUAL(u1[0].port, 5672);
- Url u2("[::1]");
- BOOST_CHECK_EQUAL(u2[0].host, "::1");
- BOOST_CHECK_EQUAL(u2[0].port, 5672);
- Url u3("[::127.0.0.1]");
- BOOST_CHECK_EQUAL(u3[0].host, "::127.0.0.1");
- BOOST_CHECK_EQUAL(u3[0].port, 5672);
- Url u4("[2002::222:68ff:fe0b:e61a]");
- BOOST_CHECK_EQUAL(u4[0].host, "2002::222:68ff:fe0b:e61a");
- BOOST_CHECK_EQUAL(u4[0].port, 5672);
- Url u5("[2002::222:68ff:fe0b:e61a]:123");
- BOOST_CHECK_EQUAL(u5[0].host, "2002::222:68ff:fe0b:e61a");
- BOOST_CHECK_EQUAL(u5[0].port, 123);
-}
-
QPID_AUTO_TEST_CASE(TestParseMultiAddress) {
Url::addProtocol("xyz");
URL_CHECK_STR("amqp:tcp:host:0,xyz:foo:123,tcp:foo:0,xyz:bar:1");
diff --git a/cpp/src/tests/Variant.cpp b/cpp/src/tests/Variant.cpp
index 40f1c0cf75..b4188f524b 100644
--- a/cpp/src/tests/Variant.cpp
+++ b/cpp/src/tests/Variant.cpp
@@ -86,64 +86,6 @@ QPID_AUTO_TEST_CASE(testConversions)
BOOST_CHECK_THROW(value.asBool(), InvalidConversion);
}
-QPID_AUTO_TEST_CASE(testConversionsFromString)
-{
- Variant value;
- value = "5";
- BOOST_CHECK_EQUAL(5, value.asInt16());
- BOOST_CHECK_EQUAL(5u, value.asUint16());
-
- value = "-5";
- BOOST_CHECK_EQUAL(-5, value.asInt16());
- BOOST_CHECK_THROW(value.asUint16(), InvalidConversion);
-
- value = "18446744073709551615";
- BOOST_CHECK_EQUAL(18446744073709551615ull, value.asUint64());
- BOOST_CHECK_THROW(value.asInt64(), InvalidConversion);
-
- value = "9223372036854775808";
- BOOST_CHECK_EQUAL(9223372036854775808ull, value.asUint64());
- BOOST_CHECK_THROW(value.asInt64(), InvalidConversion);
-
- value = "-9223372036854775809";
- BOOST_CHECK_THROW(value.asUint64(), InvalidConversion);
- BOOST_CHECK_THROW(value.asInt64(), InvalidConversion);
-
- value = "2147483648";
- BOOST_CHECK_EQUAL(2147483648ul, value.asUint32());
- BOOST_CHECK_THROW(value.asInt32(), InvalidConversion);
-
- value = "-2147483649";
- BOOST_CHECK_THROW(value.asUint32(), InvalidConversion);
- BOOST_CHECK_THROW(value.asInt32(), InvalidConversion);
-
- value = "32768";
- BOOST_CHECK_EQUAL(32768u, value.asUint16());
- BOOST_CHECK_THROW(value.asInt16(), InvalidConversion);
-
- value = "-32769";
- BOOST_CHECK_THROW(value.asUint16(), InvalidConversion);
- BOOST_CHECK_THROW(value.asInt16(), InvalidConversion);
-
- value = "-2.5";
- BOOST_CHECK_EQUAL(-2.5, value.asFloat());
-
- value = "-0.875432e10";
- BOOST_CHECK_EQUAL(-0.875432e10, value.asDouble());
-
- value = "-0";
- BOOST_CHECK_EQUAL(0, value.asInt16());
- BOOST_CHECK_EQUAL(0u, value.asUint16());
-
- value = "-000";
- BOOST_CHECK_EQUAL(0, value.asInt16());
- BOOST_CHECK_EQUAL(0u, value.asUint16());
-
- value = "-0010";
- BOOST_CHECK_EQUAL(-10, value.asInt16());
- BOOST_CHECK_THROW(value.asUint16(), InvalidConversion);
-}
-
QPID_AUTO_TEST_CASE(testSizeConversionsUint)
{
Variant value;
diff --git a/cpp/src/tests/XmlClientSessionTest.cpp b/cpp/src/tests/XmlClientSessionTest.cpp
index b94c35ece0..b3b7f12b53 100644
--- a/cpp/src/tests/XmlClientSessionTest.cpp
+++ b/cpp/src/tests/XmlClientSessionTest.cpp
@@ -90,7 +90,7 @@ struct SimpleListener : public MessageListener
}
};
-struct ClientSessionFixture : public SessionFixture
+struct ClientSessionFixture : public ProxySessionFixture
{
void declareSubscribe(const string& q="odd_blue",
const string& dest="xml")
diff --git a/cpp/src/tests/acl.py b/cpp/src/tests/acl.py
index 65d5242e51..2d6a5b489d 100755
--- a/cpp/src/tests/acl.py
+++ b/cpp/src/tests/acl.py
@@ -26,11 +26,10 @@ from qpid.datatypes import uuid4
from qpid.testlib import TestBase010
from qmf.console import Session
from qpid.datatypes import Message
-import qpid.messaging
class ACLFile:
- def __init__(self, policy='data_dir/policy.acl'):
- self.f = open(policy,'w')
+ def __init__(self):
+ self.f = open('data_dir/policy.acl','w');
def write(self,line):
self.f.write(line)
@@ -51,24 +50,14 @@ class ACLTests(TestBase010):
acl = self.qmf.getObjects(_class="acl")[0]
return acl.reloadACLFile()
- def get_acl_file(self):
- return ACLFile(self.config.defines.get("policy-file", "data_dir/policy.acl"))
-
def setUp(self):
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl allow all all\n')
aclf.close()
TestBase010.setUp(self)
self.startQmf()
self.reload_acl()
-
- def tearDown(self):
- aclf = self.get_acl_file()
- aclf.write('acl allow all all\n')
- aclf.close()
- self.reload_acl()
- TestBase010.tearDown(self)
-
+
#=====================================
# ACL general tests
#=====================================
@@ -77,7 +66,7 @@ class ACLTests(TestBase010):
"""
Test the deny all mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl allow anonymous all all\n')
aclf.write('acl allow bob@QPID create queue\n')
aclf.write('acl deny all all')
@@ -105,7 +94,7 @@ class ACLTests(TestBase010):
"""
Test the allow all mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID bind exchange\n')
aclf.write('acl allow all all')
aclf.close()
@@ -137,7 +126,7 @@ class ACLTests(TestBase010):
"""
Test empty groups
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl group\n')
aclf.write('acl group admins bob@QPID joe@QPID\n')
aclf.write('acl allow all all')
@@ -151,7 +140,7 @@ class ACLTests(TestBase010):
"""
Test illegal acl formats
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl group admins bob@QPID joe@QPID\n')
aclf.write('acl allow all all')
aclf.close()
@@ -165,7 +154,7 @@ class ACLTests(TestBase010):
Test illegal extension lines
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('group admins bob@QPID \n')
aclf.write(' \ \n')
aclf.write('joe@QPID \n')
@@ -183,7 +172,7 @@ class ACLTests(TestBase010):
"""
Test proper extention lines
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('group test1 joe@EXAMPLE.com \\ \n') # should be allowed
aclf.write(' jack@EXAMPLE.com \\ \n') # should be allowed
aclf.write('jill@TEST.COM \\ \n') # should be allowed
@@ -200,7 +189,7 @@ class ACLTests(TestBase010):
Test a user defined without a realm
Ex. group admin rajith
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('group admin bob\n') # shouldn't be allowed
aclf.write('acl deny admin bind exchange\n')
aclf.write('acl allow all all')
@@ -215,7 +204,7 @@ class ACLTests(TestBase010):
Test a user defined without a realm
Ex. group admin rajith
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('group test1 joe@EXAMPLE.com\n') # should be allowed
aclf.write('group test2 jack_123-jill@EXAMPLE.com\n') # should be allowed
aclf.write('group test4 host/somemachine.example.com@EXAMPLE.COM\n') # should be allowed
@@ -226,7 +215,7 @@ class ACLTests(TestBase010):
if (result.text.find("ACL format error",0,len(result.text)) != -1):
self.fail(result)
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('group test1 joe$H@EXAMPLE.com\n') # shouldn't be allowed
aclf.write('acl allow all all')
aclf.close()
@@ -244,7 +233,7 @@ class ACLTests(TestBase010):
Test illegal queue policy
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true policytype=ding\n')
aclf.write('acl allow all all')
aclf.close()
@@ -260,7 +249,7 @@ class ACLTests(TestBase010):
Test illegal queue policy
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q2 maxqueuesize=-1\n')
aclf.write('acl allow all all')
aclf.close()
@@ -271,7 +260,7 @@ class ACLTests(TestBase010):
if (result.text != expected):
self.fail(result)
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q2 maxqueuesize=9223372036854775808\n')
aclf.write('acl allow all all')
aclf.close()
@@ -288,7 +277,7 @@ class ACLTests(TestBase010):
Test illegal queue policy
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q2 maxqueuecount=-1\n')
aclf.write('acl allow all all')
aclf.close()
@@ -299,7 +288,7 @@ class ACLTests(TestBase010):
if (result.text != expected):
self.fail(result)
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q2 maxqueuecount=9223372036854775808\n')
aclf.write('acl allow all all')
aclf.close()
@@ -319,7 +308,7 @@ class ACLTests(TestBase010):
"""
Test cases for queue acl in allow mode
"""
- aclf = self.get_acl_file()
+ 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 policytype=ring\n')
aclf.write('acl deny bob@QPID access queue name=q3\n')
@@ -422,7 +411,7 @@ class ACLTests(TestBase010):
"""
Test cases for queue acl in deny mode
"""
- aclf = self.get_acl_file()
+ 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 policytype=ring\n')
aclf.write('acl allow bob@QPID access queue name=q3\n')
@@ -545,7 +534,7 @@ class ACLTests(TestBase010):
"""
Test cases for exchange acl in allow mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create exchange name=testEx durable=true passive=true\n')
aclf.write('acl deny bob@QPID create exchange name=ex1 type=direct\n')
aclf.write('acl deny bob@QPID access exchange name=myEx queuename=q1 routingkey=rk1.*\n')
@@ -676,7 +665,7 @@ class ACLTests(TestBase010):
"""
Test cases for exchange acl in deny mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl allow bob@QPID create exchange name=myEx durable=true passive=false\n')
aclf.write('acl allow bob@QPID bind exchange name=amq.topic queuename=bar routingkey=foo.*\n')
aclf.write('acl allow bob@QPID unbind exchange name=amq.topic queuename=bar routingkey=foo.*\n')
@@ -783,52 +772,6 @@ class ACLTests(TestBase010):
if (403 == e.args[0].error_code):
self.fail("ACL should allow exchange delete request for myEx");
- def test_create_and_delete_exchange_via_qmf(self):
- """
- Test acl is enforced when creating/deleting via QMF
- methods. Note that in order to be able to send the QMF methods
- and receive the responses a significant amount of permissions
- need to be enabled (TODO: can the set below be narrowed down
- at all?)
- """
- aclf = self.get_acl_file()
- aclf.write('acl allow bob@QPID create exchange\n')
- aclf.write('acl allow admin@QPID delete exchange\n')
- aclf.write('acl allow all access exchange\n')
- aclf.write('acl allow all bind exchange\n')
- aclf.write('acl allow all create queue\n')
- aclf.write('acl allow all access queue\n')
- aclf.write('acl allow all delete queue\n')
- aclf.write('acl allow all consume queue\n')
- aclf.write('acl allow all access method\n')
- aclf.write('acl deny all all')
- aclf.close()
-
- result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
- self.fail(result)
-
- bob = BrokerAdmin(self.config.broker, "bob", "bob")
- bob.create_exchange("my-exchange") #should pass
- #cleanup by deleting exchange
- try:
- bob.delete_exchange("my-exchange") #should fail
- self.fail("ACL should deny exchange delete request for my-exchange");
- except Exception, e:
- self.assertEqual(7,e.args[0]["error_code"])
- assert e.args[0]["error_text"].find("unauthorized-access") == 0
- admin = BrokerAdmin(self.config.broker, "admin", "admin")
- admin.delete_exchange("my-exchange") #should pass
-
- anonymous = BrokerAdmin(self.config.broker)
- try:
- anonymous.create_exchange("another-exchange") #should fail
- self.fail("ACL should deny exchange create request for another-exchange");
- except Exception, e:
- self.assertEqual(7,e.args[0]["error_code"])
- assert e.args[0]["error_text"].find("unauthorized-access") == 0
-
-
#=====================================
# ACL consume tests
#=====================================
@@ -837,7 +780,7 @@ class ACLTests(TestBase010):
"""
Test cases for consume in allow mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID consume queue name=q1\n')
aclf.write('acl deny bob@QPID consume queue name=q2\n')
aclf.write('acl allow all all')
@@ -883,7 +826,7 @@ class ACLTests(TestBase010):
"""
Test cases for consume in allow mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl allow bob@QPID consume queue name=q1\n')
aclf.write('acl allow bob@QPID consume queue name=q2\n')
aclf.write('acl allow bob@QPID create queue\n')
@@ -929,7 +872,7 @@ class ACLTests(TestBase010):
"""
Test various publish acl
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID publish exchange name=amq.direct routingkey=rk1\n')
aclf.write('acl deny bob@QPID publish exchange name=amq.topic\n')
aclf.write('acl deny bob@QPID publish exchange name=myEx routingkey=rk2\n')
@@ -978,7 +921,7 @@ class ACLTests(TestBase010):
"""
Test various publish acl
"""
- aclf = self.get_acl_file()
+ 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')
@@ -1029,113 +972,3 @@ class ACLTests(TestBase010):
except qpid.session.SessionException, e:
if (403 == e.args[0].error_code):
self.fail("ACL should allow message transfer to exchange amq.direct with routing key rk1");
-
- #=====================================
- # ACL broker configuration tests
- #=====================================
-
- def test_broker_timestamp_config(self):
- """
- Test ACL control of the broker timestamp configuration
- """
- aclf = self.get_acl_file()
- # enable lots of stuff to allow QMF to work
- aclf.write('acl allow all create exchange\n')
- aclf.write('acl allow all access exchange\n')
- aclf.write('acl allow all bind exchange\n')
- aclf.write('acl allow all publish exchange\n')
- aclf.write('acl allow all create queue\n')
- aclf.write('acl allow all access queue\n')
- aclf.write('acl allow all delete queue\n')
- aclf.write('acl allow all consume queue\n')
- aclf.write('acl allow all access method\n')
- # this should let bob access the timestamp configuration
- aclf.write('acl allow bob@QPID access broker\n')
- aclf.write('acl allow admin@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)
-
- ts = None
- bob = BrokerAdmin(self.config.broker, "bob", "bob")
- ts = bob.get_timestamp_cfg() #should work
- bob.set_timestamp_cfg(ts); #should work
-
- obo = BrokerAdmin(self.config.broker, "obo", "obo")
- try:
- ts = obo.get_timestamp_cfg() #should fail
- failed = False
- except Exception, e:
- failed = True
- self.assertEqual(7,e.args[0]["error_code"])
- assert e.args[0]["error_text"].find("unauthorized-access") == 0
- assert(failed)
-
- try:
- obo.set_timestamp_cfg(ts) #should fail
- failed = False
- except Exception, e:
- failed = True
- self.assertEqual(7,e.args[0]["error_code"])
- assert e.args[0]["error_text"].find("unauthorized-access") == 0
- assert(failed)
-
- admin = BrokerAdmin(self.config.broker, "admin", "admin")
- ts = admin.get_timestamp_cfg() #should pass
- admin.set_timestamp_cfg(ts) #should pass
-
-
-class BrokerAdmin:
- def __init__(self, broker, username=None, password=None):
- self.connection = qpid.messaging.Connection(broker)
- if username:
- self.connection.username = username
- self.connection.password = password
- self.connection.sasl_mechanisms = "PLAIN"
- self.connection.open()
- self.session = self.connection.session()
- self.sender = self.session.sender("qmf.default.direct/broker")
- self.reply_to = "responses-#; {create:always}"
- self.receiver = self.session.receiver(self.reply_to)
-
- def invoke(self, method, arguments):
- content = {
- "_object_id": {"_object_name": "org.apache.qpid.broker:broker:amqp-broker"},
- "_method_name": method,
- "_arguments": arguments
- }
- request = qpid.messaging.Message(reply_to=self.reply_to, content=content)
- request.properties["x-amqp-0-10.app-id"] = "qmf2"
- request.properties["qmf.opcode"] = "_method_request"
- self.sender.send(request)
- response = self.receiver.fetch()
- self.session.acknowledge()
- if response.properties['x-amqp-0-10.app-id'] == 'qmf2':
- if response.properties['qmf.opcode'] == '_method_response':
- return response.content['_arguments']
- elif response.properties['qmf.opcode'] == '_exception':
- raise Exception(response.content['_values'])
- else: raise Exception("Invalid response received, unexpected opcode: %s" % response.properties['qmf.opcode'])
- else: raise Exception("Invalid response received, not a qmfv2 method: %s" % response.properties['x-amqp-0-10.app-id'])
- def create_exchange(self, name, exchange_type=None, options={}):
- properties = options
- if exchange_type: properties["exchange_type"] = exchange_type
- self.invoke("create", {"type": "exchange", "name":name, "properties":properties})
-
- def create_queue(self, name, properties={}):
- self.invoke("create", {"type": "queue", "name":name, "properties":properties})
-
- def delete_exchange(self, name):
- self.invoke("delete", {"type": "exchange", "name":name})
-
- def delete_queue(self, name):
- self.invoke("delete", {"type": "queue", "name":name})
-
- def get_timestamp_cfg(self):
- return self.invoke("getTimestampConfig", {})
-
- def set_timestamp_cfg(self, receive):
- return self.invoke("getTimestampConfig", {"receive":receive})
diff --git a/cpp/src/tests/allhosts b/cpp/src/tests/allhosts
index 4b4b943156..e43571aed4 100755
--- a/cpp/src/tests/allhosts
+++ b/cpp/src/tests/allhosts
@@ -29,12 +29,11 @@ Options:
-s SECONDS sleep between starting commands.
-q don't print banner lines for each host.
-o SUFFIX log output of each command to <host>.SUFFIX
- -X passed to ssh - forward X connection.
"
exit 1
}
-while getopts "tl:bs:dqo:X" opt; do
+while getopts "tl:bs:dqo:" opt; do
case $opt in
l) SSHOPTS="-l$OPTARG $SSHOPTS" ;;
t) SSHOPTS="-t $SSHOPTS" ;;
@@ -43,7 +42,6 @@ while getopts "tl:bs:dqo:X" opt; do
s) SLEEP="sleep $OPTARG" ;;
q) NOBANNER=1 ;;
o) SUFFIX=$OPTARG ;;
- X) SSHOPTS="-X $SSHOPTS" ;;
*) usage;;
esac
done
diff --git a/cpp/src/tests/brokertest.py b/cpp/src/tests/brokertest.py
index 16d7fb0b78..98f58ebfdd 100644
--- a/cpp/src/tests/brokertest.py
+++ b/cpp/src/tests/brokertest.py
@@ -29,7 +29,6 @@ from unittest import TestCase
from copy import copy
from threading import Thread, Lock, Condition
from logging import getLogger
-import qmf.console
log = getLogger("qpid.brokertest")
@@ -62,6 +61,24 @@ def is_running(pid):
class BadProcessStatus(Exception):
pass
+class ExceptionWrapper:
+ """Proxy object that adds a message to exceptions raised"""
+ def __init__(self, obj, msg):
+ self.obj = obj
+ self.msg = msg
+
+ def __getattr__(self, name):
+ func = getattr(self.obj, name)
+ if type(func) != callable:
+ return func
+ return lambda *args, **kwargs: self._wrap(func, args, kwargs)
+
+ def _wrap(self, func, args, kwargs):
+ try:
+ return func(*args, **kwargs)
+ except Exception, e:
+ raise Exception("%s: %s" %(self.msg, str(e)))
+
def error_line(filename, n=1):
"""Get the last n line(s) of filename for error messages"""
result = []
@@ -71,8 +88,7 @@ def error_line(filename, n=1):
for l in f:
if len(result) == n: result.pop(0)
result.append(" "+l)
- finally:
- f.close()
+ finally: f.close()
except: return ""
return ":\n" + "".join(result)
@@ -80,90 +96,111 @@ def retry(function, timeout=10, delay=.01):
"""Call function until it returns True or timeout expires.
Double the delay for each retry. Return True if function
returns true, False if timeout expires."""
- deadline = time.time() + timeout
while not function():
- remaining = deadline - time.time()
- if remaining <= 0: return False
- delay = min(delay, remaining)
+ if delay > timeout: delay = timeout
time.sleep(delay)
+ timeout -= delay
+ if timeout <= 0: return False
delay *= 2
return True
-class AtomicCounter:
- def __init__(self):
- self.count = 0
- self.lock = Lock()
-
- def next(self):
- self.lock.acquire();
- ret = self.count
- self.count += 1
- self.lock.release();
- return ret
-
-_popen_id = AtomicCounter() # Popen identifier for use in output file names.
-
-# Constants for file descriptor arguments to Popen
-FILE = "FILE" # Write to file named after process
-PIPE = subprocess.PIPE
-
class Popen(subprocess.Popen):
"""
Can set and verify expectation of process status at end of test.
Dumps command line, stdout, stderr to data dir for debugging.
"""
- def __init__(self, cmd, expect=EXPECT_EXIT_OK, stdin=None, stdout=FILE, stderr=FILE):
- """Run cmd (should be a list of program and arguments)
+ class DrainThread(Thread):
+ """Thread to drain a file object and write the data to a file."""
+ def __init__(self, infile, outname):
+ Thread.__init__(self)
+ self.infile, self.outname = infile, outname
+ self.outfile = None
+
+ def run(self):
+ try:
+ for line in self.infile:
+ if self.outfile is None:
+ self.outfile = open(self.outname, "w")
+ self.outfile.write(line)
+ finally:
+ self.infile.close()
+ if self.outfile is not None: self.outfile.close()
+
+ class OutStream(ExceptionWrapper):
+ """Wrapper for output streams, handles exceptions & draining output"""
+ def __init__(self, infile, outfile, msg):
+ ExceptionWrapper.__init__(self, infile, msg)
+ self.infile, self.outfile = infile, outfile
+ self.thread = None
+
+ def drain(self):
+ if self.thread is None:
+ self.thread = Popen.DrainThread(self.infile, self.outfile)
+ self.thread.start()
+
+ def outfile(self, ext): return "%s.%s" % (self.pname, ext)
+
+ def __init__(self, cmd, expect=EXPECT_EXIT_OK, drain=True):
+ """Run cmd (should be a list of arguments)
expect - if set verify expectation at end of test.
- stdout, stderr - can have the same values as for subprocess.Popen as well as
- FILE (the default) which means write to a file named after the process.
- stdin - like subprocess.Popen but defauts to PIPE
+ drain - if true (default) drain stdout/stderr to files.
"""
self._clean = False
self._clean_lock = Lock()
assert find_exe(cmd[0]), "executable not found: "+cmd[0]
if type(cmd) is type(""): cmd = [cmd] # Make it a list.
self.cmd = [ str(x) for x in cmd ]
+ self.returncode = None
self.expect = expect
- self.id = _popen_id.next()
- self.pname = "%s-%d" % (os.path.split(self.cmd[0])[1], self.id)
- if stdout == FILE: stdout = open(self.outfile("out"), "w")
- if stderr == FILE: stderr = open(self.outfile("err"), "w")
try:
- subprocess.Popen.__init__(self, self.cmd, bufsize=0, executable=None,
- stdin=stdin, stdout=stdout, stderr=stderr,
- close_fds=True)
- except ValueError: # Windows can't do close_fds
- subprocess.Popen.__init__(self, self.cmd, bufsize=0, executable=None,
- stdin=stdin, stdout=stdout, stderr=stderr)
-
+ subprocess.Popen.__init__(self, self.cmd, 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE, close_fds=True)
+ except ValueError: # Windows can't do close_fds
+ subprocess.Popen.__init__(self, self.cmd, 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE)
+ self.pname = "%s-%d" % (os.path.split(self.cmd[0])[1], self.pid)
+ msg = "Process %s" % self.pname
+ self.stdin = ExceptionWrapper(self.stdin, msg)
+ self.stdout = Popen.OutStream(self.stdout, self.outfile("out"), msg)
+ self.stderr = Popen.OutStream(self.stderr, self.outfile("err"), msg)
f = open(self.outfile("cmd"), "w")
- try: f.write("%s\n%d"%(self.cmd_str(), self.pid))
+ try: f.write(self.cmd_str())
finally: f.close()
log.debug("Started process %s: %s" % (self.pname, " ".join(self.cmd)))
+ if drain: self.drain()
- def __str__(self): return "Popen<%s>"%(self.pname)
+ def __str__(self): return "Popen<%s>"%(self.pname)
- def outfile(self, ext): return "%s.%s" % (self.pname, ext)
+ def drain(self):
+ """Start threads to drain stdout/err"""
+ self.stdout.drain()
+ self.stderr.drain()
+
+ def _cleanup(self):
+ """Close pipes to sub-process"""
+ self._clean_lock.acquire()
+ try:
+ if self._clean: return
+ self._clean = True
+ self.stdin.close()
+ self.drain() # Drain output pipes.
+ self.stdout.thread.join() # Drain thread closes pipe.
+ self.stderr.thread.join()
+ finally: self._clean_lock.release()
def unexpected(self,msg):
err = error_line(self.outfile("err")) or error_line(self.outfile("out"))
raise BadProcessStatus("%s %s%s" % (self.pname, msg, err))
-
+
def stop(self): # Clean up at end of test.
try:
if self.expect == EXPECT_UNKNOWN:
try: self.kill() # Just make sure its dead
except: pass
elif self.expect == EXPECT_RUNNING:
- if self.poll() != None:
- self.unexpected("expected running, exit code %d" % self.returncode)
- else:
- try:
- self.kill()
- except Exception,e:
- self.unexpected("exception from kill: %s" % str(e))
+ try:
+ self.kill()
+ except:
+ self.unexpected("expected running, exit code %d" % self.wait())
else:
retry(lambda: self.poll() is not None)
if self.returncode is None: # Still haven't stopped
@@ -175,21 +212,40 @@ class Popen(subprocess.Popen):
self.unexpected("expected error")
finally:
self.wait() # Clean up the process.
-
+
def communicate(self, input=None):
- ret = subprocess.Popen.communicate(self, input)
- self.cleanup()
- return ret
+ if input:
+ self.stdin.write(input)
+ self.stdin.close()
+ outerr = (self.stdout.read(), self.stderr.read())
+ self.wait()
+ return outerr
- def is_running(self): return self.poll() is None
+ def is_running(self):
+ return self.poll() is None
def assert_running(self):
if not self.is_running(): self.unexpected("Exit code %d" % self.returncode)
+ def poll(self, _deadstate=None): # _deadstate required by base class in python 2.4
+ if self.returncode is None:
+ # Pass _deadstate only if it has been set, there is no _deadstate
+ # parameter in Python 2.6
+ if _deadstate is None: ret = subprocess.Popen.poll(self)
+ else: ret = subprocess.Popen.poll(self, _deadstate)
+
+ if (ret != -1):
+ self.returncode = ret
+ self._cleanup()
+ return self.returncode
+
def wait(self):
- ret = subprocess.Popen.wait(self)
- self._cleanup()
- return ret
+ if self.returncode is None:
+ self.drain()
+ try: self.returncode = subprocess.Popen.wait(self)
+ except OSError,e: raise OSError("Wait failed %s: %s"%(self.pname, e))
+ self._cleanup()
+ return self.returncode
def terminate(self):
try: subprocess.Popen.terminate(self)
@@ -198,8 +254,7 @@ class Popen(subprocess.Popen):
os.kill( self.pid , signal.SIGTERM)
except AttributeError: # no os.kill, using taskkill.. (Windows only)
os.popen('TASKKILL /PID ' +str(self.pid) + ' /F')
- self._cleanup()
-
+
def kill(self):
try: subprocess.Popen.kill(self)
except AttributeError: # No terminate method
@@ -207,20 +262,6 @@ class Popen(subprocess.Popen):
os.kill( self.pid , signal.SIGKILL)
except AttributeError: # no os.kill, using taskkill.. (Windows only)
os.popen('TASKKILL /PID ' +str(self.pid) + ' /F')
- self._cleanup()
-
- def _cleanup(self):
- """Clean up after a dead process"""
- self._clean_lock.acquire()
- if not self._clean:
- self._clean = True
- try: self.stdin.close()
- except: pass
- try: self.stdout.close()
- except: pass
- try: self.stderr.close()
- except: pass
- self._clean_lock.release()
def cmd_str(self): return " ".join([str(s) for s in self.cmd])
@@ -247,11 +288,11 @@ class Broker(Popen):
while (os.path.exists(self.log)):
self.log = "%s-%d.log" % (self.name, i)
i += 1
-
+
def get_log(self):
return os.path.abspath(self.log)
- def __init__(self, test, args=[], name=None, expect=EXPECT_RUNNING, port=0, log_level=None, wait=None, show_cmd=False):
+ def __init__(self, test, args=[], name=None, expect=EXPECT_RUNNING, port=0, log_level=None, wait=None):
"""Start a broker daemon. name determines the data-dir and log
file names."""
@@ -277,20 +318,15 @@ class Broker(Popen):
cmd += ["--log-to-file", self.log]
cmd += ["--log-to-stderr=no"]
if log_level != None:
- cmd += ["--log-enable=%s" % log_level]
+ cmd += ["--log-enable=%s" % log_level]
self.datadir = self.name
cmd += ["--data-dir", self.datadir]
- if show_cmd: print cmd
- Popen.__init__(self, cmd, expect, stdout=PIPE)
+ Popen.__init__(self, cmd, expect, drain=False)
test.cleanup_stop(self)
self._host = "127.0.0.1"
log.debug("Started broker %s (%s, %s)" % (self.name, self.pname, self.log))
self._log_ready = False
- def startQmf(self, handler=None):
- self.qmf_session = qmf.console.Session(handler)
- self.qmf_broker = self.qmf_session.addBroker("%s:%s" % (self.host(), self.port()))
-
def host(self): return self._host
def port(self):
@@ -321,7 +357,7 @@ class Broker(Popen):
s = c.session(str(qpid.datatypes.uuid4()))
s.queue_declare(queue=queue)
c.close()
-
+
def _prep_sender(self, queue, durable, xprops):
s = queue + "; {create:always, node:{durable:" + str(durable)
if xprops != None: s += ", x-declare:{" + xprops + "}"
@@ -365,14 +401,13 @@ class Broker(Popen):
def log_ready(self):
"""Return true if the log file exists and contains a broker ready message"""
- if not self._log_ready:
- self._log_ready = find_in_file("notice Broker running", self.log)
- return self._log_ready
+ if self._log_ready: return True
+ self._log_ready = find_in_file("notice Broker running", self.log)
def ready(self, **kwargs):
"""Wait till broker is ready to serve clients"""
# First make sure the broker is listening by checking the log.
- if not retry(self.log_ready, timeout=60):
+ if not retry(self.log_ready, timeout=30):
raise Exception(
"Timed out waiting for broker %s%s"%(self.name, error_line(self.log,5)))
# Create a connection and a session. For a cluster broker this will
@@ -381,27 +416,23 @@ class Broker(Popen):
c = self.connect(**kwargs)
try: c.session()
finally: c.close()
- except Exception,e: raise RethrownException(
- "Broker %s not responding: (%s)%s"%(self.name,e,error_line(self.log, 5)))
+ except: raise RethrownException(
+ "Broker %s failed ready test%s"%(self.name,error_line(self.log, 5)))
def store_state(self):
- f = open(os.path.join(self.datadir, "cluster", "store.status"))
- try: uuids = f.readlines()
- finally: f.close()
+ uuids = open(os.path.join(self.datadir, "cluster", "store.status")).readlines()
null_uuid="00000000-0000-0000-0000-000000000000\n"
if len(uuids) < 2: return "unknown" # we looked while the file was being updated.
if uuids[0] == null_uuid: return "empty"
if uuids[1] == null_uuid: return "dirty"
return "clean"
-
+
class Cluster:
"""A cluster of brokers in a test."""
- # Client connection options for use in failover tests.
- CONNECTION_OPTIONS = "reconnect:true,reconnect-timeout:10,reconnect-urls-replace:true"
_cluster_count = 0
- def __init__(self, test, count=0, args=[], expect=EXPECT_RUNNING, wait=True, show_cmd=False):
+ def __init__(self, test, count=0, args=[], expect=EXPECT_RUNNING, wait=True):
self.test = test
self._brokers=[]
self.name = "cluster%d" % Cluster._cluster_count
@@ -412,19 +443,16 @@ class Cluster:
self.args += [ "--log-enable=info+", "--log-enable=debug+:cluster"]
assert BrokerTest.cluster_lib, "Cannot locate cluster plug-in"
self.args += [ "--load-module", BrokerTest.cluster_lib ]
- self.start_n(count, expect=expect, wait=wait, show_cmd=show_cmd)
+ self.start_n(count, expect=expect, wait=wait)
- def start(self, name=None, expect=EXPECT_RUNNING, wait=True, args=[], port=0, show_cmd=False):
+ def start(self, name=None, expect=EXPECT_RUNNING, wait=True, args=[], port=0):
"""Add a broker to the cluster. Returns the index of the new broker."""
if not name: name="%s-%d" % (self.name, len(self._brokers))
- self._brokers.append(self.test.broker(self.args+args, name, expect, wait, port=port, show_cmd=show_cmd))
+ self._brokers.append(self.test.broker(self.args+args, name, expect, wait, port=port))
return self._brokers[-1]
- def ready(self):
- for b in self: b.ready()
-
- def start_n(self, count, expect=EXPECT_RUNNING, wait=True, args=[], show_cmd=False):
- for i in range(count): self.start(expect=expect, wait=wait, args=args, show_cmd=show_cmd)
+ def start_n(self, count, expect=EXPECT_RUNNING, wait=True, args=[]):
+ for i in range(count): self.start(expect=expect, wait=wait, args=args)
# Behave like a list of brokers.
def __len__(self): return len(self._brokers)
@@ -453,7 +481,7 @@ class BrokerTest(TestCase):
rootdir = os.getcwd()
def configure(self, config): self.config=config
-
+
def setUp(self):
outdir = self.config.defines.get("OUTDIR") or "brokertest.tmp"
self.dir = os.path.join(self.rootdir, outdir, self.id())
@@ -474,49 +502,40 @@ class BrokerTest(TestCase):
"""Call thing.stop at end of test"""
self.stopem.append(stopable)
- def popen(self, cmd, expect=EXPECT_EXIT_OK, stdin=None, stdout=FILE, stderr=FILE):
+ def popen(self, cmd, expect=EXPECT_EXIT_OK, drain=True):
"""Start a process that will be killed at end of test, in the test dir."""
os.chdir(self.dir)
- p = Popen(cmd, expect, stdin=stdin, stdout=stdout, stderr=stderr)
+ p = Popen(cmd, expect, drain)
self.cleanup_stop(p)
return p
- def broker(self, args=[], name=None, expect=EXPECT_RUNNING, wait=True, port=0, log_level=None, show_cmd=False):
+ def broker(self, args=[], name=None, expect=EXPECT_RUNNING, wait=True, port=0, log_level=None):
"""Create and return a broker ready for use"""
- b = Broker(self, args=args, name=name, expect=expect, port=port, log_level=log_level, show_cmd=show_cmd)
+ b = Broker(self, args=args, name=name, expect=expect, port=port, log_level=log_level)
if (wait):
try: b.ready()
except Exception, e:
raise RethrownException("Failed to start broker %s(%s): %s" % (b.name, b.log, e))
return b
- def cluster(self, count=0, args=[], expect=EXPECT_RUNNING, wait=True, show_cmd=False):
+ def cluster(self, count=0, args=[], expect=EXPECT_RUNNING, wait=True):
"""Create and return a cluster ready for use"""
- cluster = Cluster(self, count, args, expect=expect, wait=wait, show_cmd=show_cmd)
+ cluster = Cluster(self, count, args, expect=expect, wait=wait)
return cluster
- def browse(self, session, queue, timeout=0):
- """Return a list with the contents of each message on queue."""
- r = session.receiver("%s;{mode:browse}"%(queue))
- r.capacity = 100
- try:
- contents = []
- try:
- while True: contents.append(r.fetch(timeout=timeout).content)
- except messaging.Empty: pass
- finally: r.close()
- return contents
-
def assert_browse(self, session, queue, expect_contents, timeout=0):
"""Assert that the contents of messages on queue (as retrieved
using session and timeout) exactly match the strings in
expect_contents"""
- actual_contents = self.browse(session, queue, timeout)
- self.assertEqual(expect_contents, actual_contents)
-def join(thread, timeout=10):
- thread.join(timeout)
- if thread.isAlive(): raise Exception("Timed out joining thread %s"%thread)
+ r = session.receiver("%s;{mode:browse}"%(queue))
+ actual_contents = []
+ try:
+ for c in expect_contents: actual_contents.append(r.fetch(timeout=timeout).content)
+ while True: actual_contents.append(r.fetch(timeout=0).content) # Check for extra messages.
+ except messaging.Empty: pass
+ r.close()
+ self.assertEqual(expect_contents, actual_contents)
class RethrownException(Exception):
"""Captures the stack trace of the current exception to be thrown later"""
@@ -535,16 +554,15 @@ class StoppableThread(Thread):
def stop(self):
self.stopped = True
- join(self)
+ self.join()
if self.error: raise self.error
-
+
class NumberedSender(Thread):
"""
Thread to run a sender client and send numbered messages until stopped.
"""
- def __init__(self, broker, max_depth=None, queue="test-queue",
- connection_options=Cluster.CONNECTION_OPTIONS):
+ def __init__(self, broker, max_depth=None, queue="test-queue"):
"""
max_depth: enable flow control, ensure sent - received <= max_depth.
Requires self.notify_received(n) to be called each time messages are received.
@@ -555,11 +573,9 @@ class NumberedSender(Thread):
"--broker", "localhost:%s"%broker.port(),
"--address", "%s;{create:always}"%queue,
"--failover-updates",
- "--connection-options", "{%s}"%(connection_options),
"--content-stdin"
],
- expect=EXPECT_RUNNING,
- stdin=PIPE)
+ expect=EXPECT_RUNNING)
self.condition = Condition()
self.max = max_depth
self.received = 0
@@ -574,7 +590,6 @@ class NumberedSender(Thread):
try:
self.sent = 0
while not self.stopped:
- self.sender.assert_running()
if self.max:
self.condition.acquire()
while not self.stopped and self.sent - self.received > self.max:
@@ -597,17 +612,16 @@ class NumberedSender(Thread):
self.stopped = True
self.condition.notify()
finally: self.condition.release()
- join(self)
+ self.join()
self.write_message(-1) # end-of-messages marker.
if self.error: raise self.error
-
+
class NumberedReceiver(Thread):
"""
Thread to run a receiver client and verify it receives
sequentially numbered messages.
"""
- def __init__(self, broker, sender = None, queue="test-queue",
- connection_options=Cluster.CONNECTION_OPTIONS):
+ def __init__(self, broker, sender = None, queue="test-queue"):
"""
sender: enable flow control. Call sender.received(n) for each message received.
"""
@@ -618,24 +632,22 @@ class NumberedReceiver(Thread):
"--broker", "localhost:%s"%broker.port(),
"--address", "%s;{create:always}"%queue,
"--failover-updates",
- "--connection-options", "{%s}"%(connection_options),
"--forever"
],
expect=EXPECT_RUNNING,
- stdout=PIPE)
+ drain=False)
self.lock = Lock()
self.error = None
self.sender = sender
- self.received = 0
def read_message(self):
return int(self.receiver.stdout.readline())
-
+
def run(self):
try:
+ self.received = 0
m = self.read_message()
while m != -1:
- self.receiver.assert_running()
assert(m <= self.received) # Check for missing messages
if (m == self.received): # Ignore duplicates
self.received += 1
@@ -647,7 +659,7 @@ class NumberedReceiver(Thread):
def stop(self):
"""Returns when termination message is received"""
- join(self)
+ self.join()
if self.error: raise self.error
class ErrorGenerator(StoppableThread):
@@ -662,7 +674,7 @@ class ErrorGenerator(StoppableThread):
self.broker=broker
broker.test.cleanup_stop(self)
self.start()
-
+
def run(self):
c = self.broker.connect_old()
try:
diff --git a/cpp/src/tests/cli_tests.py b/cpp/src/tests/cli_tests.py
index 6c75927461..deef03279d 100755
--- a/cpp/src/tests/cli_tests.py
+++ b/cpp/src/tests/cli_tests.py
@@ -365,26 +365,6 @@ class CliTests(TestBase010):
self.assertEqual(queue._altExchange_.name, altName)
self.assertEqual(found, True)
- def test_qpid_config_list_queues_arguments(self):
- """
- Test to verify that when the type of a policy limit is
- actually a string (though still a valid value), it does not
- upset qpid-config
- """
- self.startQmf();
- qmf = self.qmf
-
- names = ["queue_capacity%s" % (i) for i in range(1, 6)]
- for name in names:
- self.session.queue_declare(queue=name, exclusive=True,
- arguments={'qpid.max_count' : str(i), 'qpid.max_size': '100'})
-
- output = os.popen(self.qpid_config_command(" queues")).readlines()
- queues = [line.split()[0] for line in output[2:len(output)]] #ignore first two lines (header)
-
- for name in names:
- assert name in queues, "%s not in %s" % (name, queues)
-
def test_qpid_route(self):
self.startQmf();
qmf = self.qmf
@@ -425,7 +405,7 @@ class CliTests(TestBase010):
qmf = self.qmf
ret = self.qpid_route_api("dynamic add "
- + " --client-sasl-mechanism PLAIN "
+ + " --sasl-mechanism PLAIN "
+ "guest/guest@localhost:"+str(self.broker.port) + " "
+ str(self.remote_host())+":"+str(self.remote_port()) + " "
+"amq.direct")
@@ -444,7 +424,7 @@ class CliTests(TestBase010):
qmf = self.qmf
ret = self.qpid_route_api("dynamic add "
- + " --client-sasl-mechanism PLAIN "
+ + " --sasl-mechanism PLAIN "
+ "localhost:"+str(self.broker.port) + " "
+ str(self.remote_host())+":"+str(self.remote_port()) + " "
+"amq.direct")
diff --git a/cpp/src/tests/cluster_python_tests_failing.txt b/cpp/src/tests/cluster_python_tests_failing.txt
index f8639d7b59..7ba8089946 100644
--- a/cpp/src/tests/cluster_python_tests_failing.txt
+++ b/cpp/src/tests/cluster_python_tests_failing.txt
@@ -1,4 +1,32 @@
qpid_tests.broker_0_10.management.ManagementTest.test_purge_queue
qpid_tests.broker_0_10.management.ManagementTest.test_connection_close
+qpid_tests.broker_0_10.dtx.DtxTests.test_bad_resume
+qpid_tests.broker_0_10.dtx.DtxTests.test_commit_unknown
+qpid_tests.broker_0_10.dtx.DtxTests.test_end
+qpid_tests.broker_0_10.dtx.DtxTests.test_end_suspend_and_fail
+qpid_tests.broker_0_10.dtx.DtxTests.test_end_unknown_xid
+qpid_tests.broker_0_10.dtx.DtxTests.test_forget_xid_on_completion
+qpid_tests.broker_0_10.dtx.DtxTests.test_get_timeout
+qpid_tests.broker_0_10.dtx.DtxTests.test_get_timeout_unknown
+qpid_tests.broker_0_10.dtx.DtxTests.test_implicit_end
+qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_commit_not_ended
+qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_commit_one_phase_false
+qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_commit_one_phase_true
+qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_prepare_not_ended
+qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_rollback_not_ended
+qpid_tests.broker_0_10.dtx.DtxTests.test_prepare_unknown
+qpid_tests.broker_0_10.dtx.DtxTests.test_recover
+qpid_tests.broker_0_10.dtx.DtxTests.test_rollback_unknown
+qpid_tests.broker_0_10.dtx.DtxTests.test_select_required
+qpid_tests.broker_0_10.dtx.DtxTests.test_set_timeout
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_commit
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_prepare_commit
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_prepare_rollback
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_rollback
+qpid_tests.broker_0_10.dtx.DtxTests.test_start_already_known
+qpid_tests.broker_0_10.dtx.DtxTests.test_start_join
+qpid_tests.broker_0_10.dtx.DtxTests.test_start_join_and_resume
+qpid_tests.broker_0_10.dtx.DtxTests.test_suspend_resume
+qpid_tests.broker_0_10.dtx.DtxTests.test_suspend_start_end_resume
qpid_tests.broker_0_10.message.MessageTests.test_ttl
qpid_tests.broker_0_10.management.ManagementTest.test_broker_connectivity_oldAPI
diff --git a/cpp/src/tests/cluster_test_logs.py b/cpp/src/tests/cluster_test_logs.py
index 3c7e8e8020..1fa9014d11 100755
--- a/cpp/src/tests/cluster_test_logs.py
+++ b/cpp/src/tests/cluster_test_logs.py
@@ -53,19 +53,16 @@ def filter_log(log):
'stall for update|unstall, ignore update|cancelled offer .* unstall',
'caught up',
'active for links|Passivating links|Activating links',
- 'info Connecting: .*', # UpdateClient connection
'info Connection.* connected to', # UpdateClient connection
- 'warning Connection \\[[-0-9.: ]+\\] closed', # UpdateClient connection
+ 'warning Connection [\d+ [0-9.:]+] closed', # UpdateClient connection
'warning Broker closed connection: 200, OK',
'task late',
'task overran',
'warning CLOSING .* unsent data',
'Inter-broker link ',
- 'Running in a cluster, marking store',
- 'debug Sending keepalive signal to watchdog', # Watchdog timer thread
- 'last broker standing joined by 1 replicas, updating queue policies.',
- 'Connection .* timed out: closing' # heartbeat connection close
+ 'Running in a cluster, marking store'
])
+ skip_re = re.compile(skip)
# Regex to match a UUID
uuid='\w\w\w\w\w\w\w\w-\w\w\w\w-\w\w\w\w-\w\w\w\w-\w\w\w\w\w\w\w\w\w\w\w\w'
# Substitutions to remove expected differences
@@ -83,13 +80,6 @@ def filter_log(log):
(r' map={.*_object_name:([^,}]*)[,}].*', r' \1'), # V2 map - just keep name
(r'\d+-\d+-\d+--\d+', 'X-X-X--X'), # V1 Object IDs
]
- # Substitutions to mask known issue: durable test shows inconsistent "changed stats for com.redhat.rhm.store:journal" messages.
- skip += '|Changed V[12] statistics com.redhat.rhm.store:journal'
- subs += [(r'to=console.obj.1.0.com.redhat.rhm.store.journal props=\d+ stats=\d+',
- 'to=console.obj.1.0.com.redhat.rhm.store.journal props=NN stats=NN')]
-
- skip_re = re.compile(skip)
- subs = [(re.compile(pattern), subst) for pattern, subst in subs]
for l in open(log):
if skip_re.search(l): continue
for pattern,subst in subs: l = re.sub(pattern,subst,l)
diff --git a/cpp/src/tests/cluster_tests.py b/cpp/src/tests/cluster_tests.py
index 0e80e06d34..cbad4010b4 100755
--- a/cpp/src/tests/cluster_tests.py
+++ b/cpp/src/tests/cluster_tests.py
@@ -18,13 +18,12 @@
# under the License.
#
-import os, signal, sys, time, imp, re, subprocess, glob, random, logging
-import cluster_test_logs
+import os, signal, sys, time, imp, re, subprocess, glob, cluster_test_logs
from qpid import datatypes, messaging
from brokertest import *
from qpid.harness import Skipped
-from qpid.messaging import Message, Empty, Disposition, REJECTED, util
-from threading import Thread, Lock, Condition
+from qpid.messaging import Message, Empty
+from threading import Thread, Lock
from logging import getLogger
from itertools import chain
from tempfile import NamedTemporaryFile
@@ -97,15 +96,9 @@ class ShortTests(BrokerTest):
destination="amq.direct",
message=qpid.datatypes.Message(props, "content"))
- # Try message with TTL and differnet headers/properties
- cluster[0].send_message("q", Message(durable=True, ttl=100000))
- cluster[0].send_message("q", Message(durable=True, properties={}, ttl=100000))
- cluster[0].send_message("q", Message(durable=True, properties={"x":10}, ttl=100000))
-
# Now update a new member and compare their dumps.
cluster.start(args=["--test-store-dump", "updatee.dump"])
assert readfile("direct.dump") == readfile("updatee.dump")
-
os.remove("direct.dump")
os.remove("updatee.dump")
@@ -115,22 +108,19 @@ class ShortTests(BrokerTest):
acl=os.path.join(os.getcwd(), "policy.acl")
aclf=file(acl,"w")
aclf.write("""
-acl allow zig@QPID all all
-acl deny all all
+acl deny zag@QPID create queue
+acl allow all all
""")
aclf.close()
- cluster = self.cluster(1, args=["--auth", "yes",
+ cluster = self.cluster(2, args=["--auth", "yes",
"--sasl-config", sasl_config,
"--load-module", os.getenv("ACL_LIB"),
"--acl-file", acl])
# Valid user/password, ensure queue is created.
c = cluster[0].connect(username="zig", password="zig")
- c.session().sender("ziggy;{create:always,node:{x-declare:{exclusive:true}}}")
+ c.session().sender("ziggy;{create:always}")
c.close()
- cluster.start() # Start second node.
-
- # Check queue is created on second node.
c = cluster[1].connect(username="zig", password="zig")
c.session().receiver("ziggy;{assert:always}")
c.close()
@@ -159,7 +149,7 @@ acl deny all all
self.fail("Expected exception")
except messaging.exceptions.UnauthorizedAccess: pass
# make sure the queue was not created at the other node.
- c = cluster[1].connect(username="zig", password="zig")
+ c = cluster[0].connect(username="zag", password="zag")
try:
s = c.session()
s.sender("zaggy;{assert:always}")
@@ -167,35 +157,6 @@ acl deny all all
self.fail("Expected exception")
except messaging.exceptions.NotFound: pass
- def test_sasl_join(self):
- """Verify SASL authentication between brokers when joining a cluster."""
- sasl_config=os.path.join(self.rootdir, "sasl_config")
- # Test with a valid username/password
- cluster = self.cluster(1, args=["--auth", "yes",
- "--sasl-config", sasl_config,
- "--load-module", os.getenv("ACL_LIB"),
- "--cluster-username=zig",
- "--cluster-password=zig",
- "--cluster-mechanism=PLAIN"
- ])
- cluster.start()
- cluster.ready()
- c = cluster[1].connect(username="zag", password="zag")
-
- # Test with an invalid username/password
- cluster = self.cluster(1, args=["--auth", "yes",
- "--sasl-config", sasl_config,
- "--load-module", os.getenv("ACL_LIB"),
- "--cluster-username=x",
- "--cluster-password=y",
- "--cluster-mechanism=PLAIN"
- ])
- try:
- cluster.start(expect=EXPECT_EXIT_OK)
- cluster[1].ready()
- self.fail("Expected exception")
- except: pass
-
def test_user_id_update(self):
"""Ensure that user-id of an open session is updated to new cluster members"""
sasl_config=os.path.join(self.rootdir, "sasl_config")
@@ -285,6 +246,25 @@ acl deny all all
session1 = cluster[1].connect().session()
for q in queues: self.assert_browse(session1, "q1", ["foo"])
+ def test_dr_no_message(self):
+ """Regression test for https://bugzilla.redhat.com/show_bug.cgi?id=655141
+ Joining broker crashes with 'error deliveryRecord no update message'
+ """
+
+ cluster = self.cluster(1)
+ session0 = cluster[0].connect().session()
+ s = session0.sender("q1;{create:always}")
+ s.send(Message("a", ttl=0.05), sync=False)
+ s.send(Message("b", ttl=0.05), sync=False)
+ r1 = session0.receiver("q1")
+ self.assertEqual("a", r1.fetch(timeout=0).content)
+ r2 = session0.receiver("q1;{mode:browse}")
+ self.assertEqual("b", r2.fetch(timeout=0).content)
+ # Leave messages un-acknowledged, let the expire, then start new broker.
+ time.sleep(.1)
+ cluster.start()
+ self.assertRaises(Empty, cluster[1].connect().session().receiver("q1").fetch,0)
+
def test_route_update(self):
"""Regression test for https://issues.apache.org/jira/browse/QPID-2982
Links and bridges associated with routes were not replicated on update.
@@ -292,7 +272,6 @@ acl deny all all
client was attached.
"""
args=["--mgmt-pub-interval=1","--log-enable=trace+:management"]
- # First broker will be killed.
cluster0 = self.cluster(1, args=args)
cluster1 = self.cluster(1, args=args)
assert 0 == subprocess.call(
@@ -322,695 +301,9 @@ acl deny all all
qpid_tool.wait()
scanner.join()
assert scanner.found
- # Regression test for https://issues.apache.org/jira/browse/QPID-3235
- # Inconsistent stats when changing elder.
-
- # Force a change of elder
- cluster0.start()
- cluster0[0].expect=EXPECT_EXIT_FAIL # About to die.
- cluster0[0].kill()
- time.sleep(2) # Allow a management interval to pass.
# Verify logs are consistent
cluster_test_logs.verify_logs()
- def test_redelivered(self):
- """Verify that redelivered flag is set correctly on replayed messages"""
- cluster = self.cluster(2, expect=EXPECT_EXIT_FAIL)
- url = "amqp:tcp:%s,tcp:%s" % (cluster[0].host_port(), cluster[1].host_port())
- queue = "my-queue"
- cluster[0].declare_queue(queue)
- self.sender = self.popen(
- ["qpid-send",
- "--broker", url,
- "--address", queue,
- "--sequence=true",
- "--send-eos=1",
- "--messages=100000",
- "--connection-options={%s}"%(Cluster.CONNECTION_OPTIONS)
- ])
- self.receiver = self.popen(
- ["qpid-receive",
- "--broker", url,
- "--address", queue,
- "--ignore-duplicates",
- "--check-redelivered",
- "--connection-options={%s}"%(Cluster.CONNECTION_OPTIONS),
- "--forever"
- ])
- time.sleep(1)#give sender enough time to have some messages to replay
- cluster[0].kill()
- self.sender.wait()
- self.receiver.wait()
- cluster[1].kill()
-
- class BlockedSend(Thread):
- """Send a message, send is expected to block.
- Verify that it does block (for a given timeout), then allow
- waiting till it unblocks when it is expected to do so."""
- def __init__(self, sender, msg):
- self.sender, self.msg = sender, msg
- self.blocked = True
- self.condition = Condition()
- self.timeout = 0.1 # Time to wait for expected results.
- Thread.__init__(self)
- def run(self):
- try:
- self.sender.send(self.msg, sync=True)
- self.condition.acquire()
- try:
- self.blocked = False
- self.condition.notify()
- finally: self.condition.release()
- except Exception,e: print "BlockedSend exception: %s"%e
- def start(self):
- Thread.start(self)
- time.sleep(self.timeout)
- assert self.blocked # Expected to block
- def assert_blocked(self): assert self.blocked
- def wait(self): # Now expecting to unblock
- self.condition.acquire()
- try:
- while self.blocked:
- self.condition.wait(self.timeout)
- if self.blocked: raise Exception("Timed out waiting for send to unblock")
- finally: self.condition.release()
- self.join()
-
- def queue_flowlimit_test(self, brokers):
- """Verify that the queue's flowlimit configuration and state are
- correctly replicated.
- The brokers argument allows this test to run on single broker,
- cluster of 2 pre-startd brokers or cluster where second broker
- starts after queue is in flow control.
- """
- # configure a queue with a specific flow limit on first broker
- ssn0 = brokers.first().connect().session()
- s0 = ssn0.sender("flq; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':5, 'qpid.flow_resume_count':3}}}}")
- brokers.first().startQmf()
- q1 = [q for q in brokers.first().qmf_session.getObjects(_class="queue") if q.name == "flq"][0]
- oid = q1.getObjectId()
- self.assertEqual(q1.name, "flq")
- self.assertEqual(q1.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L})
- assert not q1.flowStopped
- self.assertEqual(q1.flowStoppedCount, 0)
-
- # fill the queue on one broker until flow control is active
- for x in range(5): s0.send(Message(str(x)))
- sender = ShortTests.BlockedSend(s0, Message(str(6)))
- sender.start() # Tests that sender does block
- # Verify the broker queue goes into a flowStopped state
- deadline = time.time() + 1
- while not q1.flowStopped and time.time() < deadline: q1.update()
- assert q1.flowStopped
- self.assertEqual(q1.flowStoppedCount, 1)
- sender.assert_blocked() # Still blocked
-
- # Now verify the both brokers in cluster have same configuration
- brokers.second().startQmf()
- qs = brokers.second().qmf_session.getObjects(_objectId=oid)
- self.assertEqual(len(qs), 1)
- q2 = qs[0]
- self.assertEqual(q2.name, "flq")
- self.assertEqual(q2.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L})
- assert q2.flowStopped
- self.assertEqual(q2.flowStoppedCount, 1)
-
- # now drain the queue using a session to the other broker
- ssn1 = brokers.second().connect().session()
- r1 = ssn1.receiver("flq", capacity=6)
- for x in range(4):
- r1.fetch(timeout=0)
- ssn1.acknowledge()
- sender.wait() # Verify no longer blocked.
-
- # and re-verify state of queue on both brokers
- q1.update()
- assert not q1.flowStopped
- q2.update()
- assert not q2.flowStopped
-
- ssn0.connection.close()
- ssn1.connection.close()
- cluster_test_logs.verify_logs()
-
- def test_queue_flowlimit(self):
- """Test flow limits on a standalone broker"""
- broker = self.broker()
- class Brokers:
- def first(self): return broker
- def second(self): return broker
- self.queue_flowlimit_test(Brokers())
-
- def test_queue_flowlimit_cluster(self):
- cluster = self.cluster(2)
- class Brokers:
- def first(self): return cluster[0]
- def second(self): return cluster[1]
- self.queue_flowlimit_test(Brokers())
-
- def test_queue_flowlimit_cluster_join(self):
- cluster = self.cluster(1)
- class Brokers:
- def first(self): return cluster[0]
- def second(self):
- if len(cluster) == 1: cluster.start()
- return cluster[1]
- self.queue_flowlimit_test(Brokers())
-
- def test_queue_flowlimit_replicate(self):
- """ Verify that a queue which is in flow control BUT has drained BELOW
- the flow control 'stop' threshold, is correctly replicated when a new
- broker is added to the cluster.
- """
-
- class AsyncSender(Thread):
- """Send a fixed number of msgs from a sender in a separate thread
- so it may block without blocking the test.
- """
- def __init__(self, broker, address, count=1, size=4):
- Thread.__init__(self)
- self.daemon = True
- self.broker = broker
- self.queue = address
- self.count = count
- self.size = size
- self.done = False
-
- def run(self):
- self.sender = subprocess.Popen(["qpid-send",
- "--capacity=1",
- "--content-size=%s" % self.size,
- "--messages=%s" % self.count,
- "--failover-updates",
- "--connection-options={%s}"%(Cluster.CONNECTION_OPTIONS),
- "--address=%s" % self.queue,
- "--broker=%s" % self.broker.host_port()])
- self.sender.wait()
- self.done = True
-
- cluster = self.cluster(2)
- # create a queue with rather draconian flow control settings
- ssn0 = cluster[0].connect().session()
- s0 = ssn0.sender("flq; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':100, 'qpid.flow_resume_count':20}}}}")
-
- # fire off the sending thread to broker[0], and wait until the queue
- # hits flow control on broker[1]
- sender = AsyncSender(cluster[0], "flq", count=110);
- sender.start();
-
- cluster[1].startQmf()
- q_obj = [q for q in cluster[1].qmf_session.getObjects(_class="queue") if q.name == "flq"][0]
- deadline = time.time() + 10
- while not q_obj.flowStopped and time.time() < deadline:
- q_obj.update()
- assert q_obj.flowStopped
- assert not sender.done
- assert q_obj.msgDepth < 110
-
- # Now drain enough messages on broker[1] to drop below the flow stop
- # threshold, but not relieve flow control...
- receiver = subprocess.Popen(["qpid-receive",
- "--messages=15",
- "--timeout=1",
- "--print-content=no",
- "--failover-updates",
- "--connection-options={%s}"%(Cluster.CONNECTION_OPTIONS),
- "--ack-frequency=1",
- "--address=flq",
- "--broker=%s" % cluster[1].host_port()])
- receiver.wait()
- q_obj.update()
- assert q_obj.flowStopped
- assert not sender.done
- current_depth = q_obj.msgDepth
-
- # add a new broker to the cluster, and verify that the queue is in flow
- # control on that broker
- cluster.start()
- cluster[2].startQmf()
- q_obj = [q for q in cluster[2].qmf_session.getObjects(_class="queue") if q.name == "flq"][0]
- assert q_obj.flowStopped
- assert q_obj.msgDepth == current_depth
-
- # now drain the queue on broker[2], and verify that the sender becomes
- # unblocked
- receiver = subprocess.Popen(["qpid-receive",
- "--messages=95",
- "--timeout=1",
- "--print-content=no",
- "--failover-updates",
- "--connection-options={%s}"%(Cluster.CONNECTION_OPTIONS),
- "--ack-frequency=1",
- "--address=flq",
- "--broker=%s" % cluster[2].host_port()])
- receiver.wait()
- q_obj.update()
- assert not q_obj.flowStopped
- self.assertEqual(q_obj.msgDepth, 0)
-
- # verify that the sender has become unblocked
- sender.join(timeout=5)
- assert not sender.isAlive()
- assert sender.done
-
- def test_blocked_queue_delete(self):
- """Verify that producers which are blocked on a queue due to flow
- control are unblocked when that queue is deleted.
- """
-
- cluster = self.cluster(2)
- cluster[0].startQmf()
- cluster[1].startQmf()
-
- # configure a queue with a specific flow limit on first broker
- ssn0 = cluster[0].connect().session()
- s0 = ssn0.sender("flq; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':5, 'qpid.flow_resume_count':3}}}}")
- q1 = [q for q in cluster[0].qmf_session.getObjects(_class="queue") if q.name == "flq"][0]
- oid = q1.getObjectId()
- self.assertEqual(q1.name, "flq")
- self.assertEqual(q1.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L})
- assert not q1.flowStopped
- self.assertEqual(q1.flowStoppedCount, 0)
-
- # fill the queue on one broker until flow control is active
- for x in range(5): s0.send(Message(str(x)))
- sender = ShortTests.BlockedSend(s0, Message(str(6)))
- sender.start() # Tests that sender does block
- # Verify the broker queue goes into a flowStopped state
- deadline = time.time() + 1
- while not q1.flowStopped and time.time() < deadline: q1.update()
- assert q1.flowStopped
- self.assertEqual(q1.flowStoppedCount, 1)
- sender.assert_blocked() # Still blocked
-
- # Now verify the both brokers in cluster have same configuration
- qs = cluster[1].qmf_session.getObjects(_objectId=oid)
- self.assertEqual(len(qs), 1)
- q2 = qs[0]
- self.assertEqual(q2.name, "flq")
- self.assertEqual(q2.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L})
- assert q2.flowStopped
- self.assertEqual(q2.flowStoppedCount, 1)
-
- # now delete the blocked queue from other broker
- ssn1 = cluster[1].connect().session()
- self.evaluate_address(ssn1, "flq;{delete:always}")
- sender.wait() # Verify no longer blocked.
-
- ssn0.connection.close()
- ssn1.connection.close()
- cluster_test_logs.verify_logs()
-
-
- def test_alternate_exchange_update(self):
- """Verify that alternate-exchange on exchanges and queues is propagated to new members of a cluster. """
- cluster = self.cluster(1)
- s0 = cluster[0].connect().session()
- # create alt queue bound to amq.fanout exchange, will be destination for alternate exchanges
- self.evaluate_address(s0, "alt;{create:always,node:{x-bindings:[{exchange:'amq.fanout',queue:alt}]}}")
- # create direct exchange ex with alternate-exchange amq.fanout and no queues bound
- self.evaluate_address(s0, "ex;{create:always,node:{type:topic, x-declare:{type:'direct', alternate-exchange:'amq.fanout'}}}")
- # create queue q with alternate-exchange amq.fanout
- self.evaluate_address(s0, "q;{create:always,node:{type:queue, x-declare:{alternate-exchange:'amq.fanout'}}}")
-
- def verify(broker):
- s = broker.connect().session()
- # Verify unmatched message goes to ex's alternate.
- s.sender("ex").send("foo")
- self.assertEqual("foo", s.receiver("alt").fetch(timeout=0).content)
- # Verify rejected message goes to q's alternate.
- s.sender("q").send("bar")
- msg = s.receiver("q").fetch(timeout=0)
- self.assertEqual("bar", msg.content)
- s.acknowledge(msg, Disposition(REJECTED)) # Reject the message
- self.assertEqual("bar", s.receiver("alt").fetch(timeout=0).content)
-
- verify(cluster[0])
- cluster.start()
- verify(cluster[1])
-
- def test_binding_order(self):
- """Regression test for binding order inconsistency in cluster"""
- cluster = self.cluster(1)
- c0 = cluster[0].connect()
- s0 = c0.session()
- # Declare multiple queues bound to same key on amq.topic
- def declare(q,max=0):
- if max: declare = 'x-declare:{arguments:{"qpid.max_count":%d, "qpid.flow_stop_count":0}}'%max
- else: declare = 'x-declare:{}'
- bind='x-bindings:[{queue:%s,key:key,exchange:"amq.topic"}]'%(q)
- s0.sender("%s;{create:always,node:{%s,%s}}" % (q,declare,bind))
- declare('d',max=4) # Only one with a limit
- for q in ['c', 'b','a']: declare(q)
- # Add a cluster member, send enough messages to exceed the max count
- cluster.start()
- try:
- s = s0.sender('amq.topic/key')
- for m in xrange(1,6): s.send(Message(str(m)))
- self.fail("Expected capacity exceeded exception")
- except messaging.exceptions.TargetCapacityExceeded: pass
- c1 = cluster[1].connect()
- s1 = c1.session()
- s0 = c0.session() # Old session s0 is broken by exception.
- # Verify queue contents are consistent.
- for q in ['a','b','c','d']:
- self.assertEqual(self.browse(s0, q), self.browse(s1, q))
- # Verify queue contents are "best effort"
- for q in ['a','b','c']: self.assert_browse(s1,q,[str(n) for n in xrange(1,6)])
- self.assert_browse(s1,'d',[str(n) for n in xrange(1,5)])
-
- def test_deleted_exchange(self):
- """QPID-3215: cached exchange reference can cause cluster inconsistencies
- if exchange is deleted/recreated
- Verify stand-alone case
- """
- cluster = self.cluster()
- # Verify we do not route message via an exchange that has been destroyed.
- cluster.start()
- s0 = cluster[0].connect().session()
- self.evaluate_address(s0, "ex;{create:always,node:{type:topic}}")
- self.evaluate_address(s0, "q;{create:always,node:{x-bindings:[{exchange:'ex',queue:q,key:foo}]}}")
- send0 = s0.sender("ex/foo")
- send0.send("foo")
- self.assert_browse(s0, "q", ["foo"])
- self.evaluate_address(s0, "ex;{delete:always}")
- try:
- send0.send("bar") # Should fail, exchange is deleted.
- self.fail("Expected not-found exception")
- except qpid.messaging.NotFound: pass
- self.assert_browse(cluster[0].connect().session(), "q", ["foo"])
-
- def test_deleted_exchange_inconsistent(self):
- """QPID-3215: cached exchange reference can cause cluster inconsistencies
- if exchange is deleted/recreated
-
- Verify cluster inconsistency.
- """
- cluster = self.cluster()
- cluster.start()
- s0 = cluster[0].connect().session()
- self.evaluate_address(s0, "ex;{create:always,node:{type:topic}}")
- self.evaluate_address(s0, "q;{create:always,node:{x-bindings:[{exchange:'ex',queue:q,key:foo}]}}")
- send0 = s0.sender("ex/foo")
- send0.send("foo")
- self.assert_browse(s0, "q", ["foo"])
-
- cluster.start()
- s1 = cluster[1].connect().session()
- self.evaluate_address(s0, "ex;{delete:always}")
- try:
- send0.send("bar")
- self.fail("Expected not-found exception")
- except qpid.messaging.NotFound: pass
-
- self.assert_browse(s1, "q", ["foo"])
-
-
- def test_ttl_consistent(self):
- """Ensure we don't get inconsistent errors with message that have TTL very close together"""
- messages = [ Message(str(i), ttl=i/1000.0) for i in xrange(0,1000)]
- messages.append(Message("x"))
- cluster = self.cluster(2)
- sender = cluster[0].connect().session().sender("q;{create:always}")
-
- def fetch(b):
- receiver = b.connect().session().receiver("q;{create:always}")
- while receiver.fetch().content != "x": pass
-
- for m in messages: sender.send(m, sync=False)
- for m in messages: sender.send(m, sync=False)
- fetch(cluster[0])
- fetch(cluster[1])
- for m in messages: sender.send(m, sync=False)
- cluster.start()
- fetch(cluster[2])
-
-# Some utility code for transaction tests
-XA_RBROLLBACK = 1
-XA_RBTIMEOUT = 2
-XA_OK = 0
-dtx_branch_counter = 0
-
-class DtxStatusException(Exception):
- def __init__(self, expect, actual):
- self.expect = expect
- self.actual = actual
-
- def str(self):
- return "DtxStatusException(expect=%s, actual=%s)"%(self.expect, self.actual)
-
-class DtxTestFixture:
- """Bundle together some common requirements for dtx tests."""
- def __init__(self, test, broker, name, exclusive=False):
- self.test = test
- self.broker = broker
- self.name = name
- # Use old API. DTX is not supported in messaging API.
- self.connection = broker.connect_old()
- self.session = self.connection.session(name, 1) # 1 second timeout
- self.queue = self.session.queue_declare(name, exclusive=exclusive)
- self.session.dtx_select()
- self.consumer = None
-
- def xid(self, id=None):
- if id is None: id = self.name
- return self.session.xid(format=0, global_id=id)
-
- def check_status(self, expect, actual):
- if expect != actual: raise DtxStatusException(expect, actual)
-
- def start(self, id=None, resume=False):
- self.check_status(XA_OK, self.session.dtx_start(xid=self.xid(id), resume=resume).status)
-
- def end(self, id=None, suspend=False):
- self.check_status(XA_OK, self.session.dtx_end(xid=self.xid(id), suspend=suspend).status)
-
- def prepare(self, id=None):
- self.check_status(XA_OK, self.session.dtx_prepare(xid=self.xid(id)).status)
-
- def commit(self, id=None, one_phase=True):
- self.check_status(
- XA_OK, self.session.dtx_commit(xid=self.xid(id), one_phase=one_phase).status)
-
- def rollback(self, id=None):
- self.check_status(XA_OK, self.session.dtx_rollback(xid=self.xid(id)).status)
-
- def set_timeout(self, timeout, id=None):
- self.session.dtx_set_timeout(xid=self.xid(id),timeout=timeout)
-
- def send(self, messages):
- for m in messages:
- dp=self.session.delivery_properties(routing_key=self.name)
- mp=self.session.message_properties()
- self.session.message_transfer(message=qpid.datatypes.Message(dp, mp, m))
-
- def accept(self):
- """Accept 1 message from queue"""
- consumer_tag="%s-consumer"%(self.name)
- self.session.message_subscribe(queue=self.name, destination=consumer_tag)
- self.session.message_flow(unit = self.session.credit_unit.message, value = 1, destination = consumer_tag)
- self.session.message_flow(unit = self.session.credit_unit.byte, value = 0xFFFFFFFFL, destination = consumer_tag)
- msg = self.session.incoming(consumer_tag).get(timeout=1)
- self.session.message_cancel(destination=consumer_tag)
- self.session.message_accept(qpid.datatypes.RangedSet(msg.id))
- return msg
-
-
- def verify(self, sessions, messages):
- for s in sessions:
- self.test.assert_browse(s, self.name, messages)
-
-class DtxTests(BrokerTest):
-
- def test_dtx_update(self):
- """Verify that DTX transaction state is updated to a new broker.
- Start a collection of transactions, then add a new cluster member,
- then verify they commit/rollback correctly on the new broker."""
-
- # Note: multiple test have been bundled into one to avoid the need to start/stop
- # multiple brokers per test.
-
- cluster=self.cluster(1)
- sessions = [cluster[0].connect().session()] # For verify
-
- # Transaction that will be open when new member joins, then committed.
- t1 = DtxTestFixture(self, cluster[0], "t1")
- t1.start()
- t1.send(["1", "2"])
- t1.verify(sessions, []) # Not visible outside of transaction
-
- # Transaction that will be open when new member joins, then rolled back.
- t2 = DtxTestFixture(self, cluster[0], "t2")
- t2.start()
- t2.send(["1", "2"])
-
- # Transaction that will be prepared when new member joins, then committed.
- t3 = DtxTestFixture(self, cluster[0], "t3")
- t3.start()
- t3.send(["1", "2"])
- t3.end()
- t3.prepare()
- t1.verify(sessions, []) # Not visible outside of transaction
-
- # Transaction that will be prepared when new member joins, then rolled back.
- t4 = DtxTestFixture(self, cluster[0], "t4")
- t4.start()
- t4.send(["1", "2"])
- t4.end()
- t4.prepare()
-
- # Transaction using an exclusive queue
- t5 = DtxTestFixture(self, cluster[0], "t5", exclusive=True)
- t5.start()
- t5.send(["1", "2"])
-
- # Accept messages in a transaction before/after join then commit
- t6 = DtxTestFixture(self, cluster[0], "t6")
- t6.send(["a","b","c"])
- t6.start()
- self.assertEqual(t6.accept().body, "a");
-
- # Accept messages in a transaction before/after join then roll back
- t7 = DtxTestFixture(self, cluster[0], "t7")
- t7.send(["a","b","c"])
- t7.start()
- self.assertEqual(t7.accept().body, "a");
-
- # Ended, suspended transactions across join.
- t8 = DtxTestFixture(self, cluster[0], "t8")
- t8.start(id="1")
- t8.send(["x"])
- t8.end(id="1", suspend=True)
- t8.start(id="2")
- t8.send(["y"])
- t8.end(id="2")
- t8.start()
- t8.send("z")
-
-
- # Start new cluster member
- cluster.start()
- sessions.append(cluster[1].connect().session())
-
- # Commit t1
- t1.send(["3","4"])
- t1.verify(sessions, [])
- t1.end()
- t1.commit(one_phase=True)
- t1.verify(sessions, ["1","2","3","4"])
-
- # Rollback t2
- t2.send(["3","4"])
- t2.end()
- t2.rollback()
- t2.verify(sessions, [])
-
- # Commit t3
- t3.commit(one_phase=False)
- t3.verify(sessions, ["1","2"])
-
- # Rollback t4
- t4.rollback()
- t4.verify(sessions, [])
-
- # Commit t5
- t5.send(["3","4"])
- t5.verify(sessions, [])
- t5.end()
- t5.commit(one_phase=True)
- t5.verify(sessions, ["1","2","3","4"])
-
- # Commit t6
- self.assertEqual(t6.accept().body, "b");
- t6.verify(sessions, ["c"])
- t6.end()
- t6.commit(one_phase=True)
- t6.session.close() # Make sure they're not requeued by the session.
- t6.verify(sessions, ["c"])
-
- # Rollback t7
- self.assertEqual(t7.accept().body, "b");
- t7.end()
- t7.rollback()
- t7.verify(sessions, ["a", "b", "c"])
-
- # Resume t8
- t8.end()
- t8.commit(one_phase=True)
- t8.start("1", resume=True)
- t8.end("1")
- t8.commit("1", one_phase=True)
- t8.commit("2", one_phase=True)
- t8.verify(sessions, ["z", "x","y"])
-
-
- def test_dtx_failover_rollback(self):
- """Kill a broker during a transaction, verify we roll back correctly"""
- cluster=self.cluster(1, expect=EXPECT_EXIT_FAIL)
- cluster.start(expect=EXPECT_RUNNING)
-
- # Test unprepared at crash
- t1 = DtxTestFixture(self, cluster[0], "t1")
- t1.send(["a"]) # Not in transaction
- t1.start()
- t1.send(["b"]) # In transaction
-
- # Test prepared at crash
- t2 = DtxTestFixture(self, cluster[0], "t2")
- t2.send(["a"]) # Not in transaction
- t2.start()
- t2.send(["b"]) # In transaction
- t2.end()
- t2.prepare()
-
- # Crash the broker
- cluster[0].kill()
-
- # Transactional changes should not appear
- s = cluster[1].connect().session();
- self.assert_browse(s, "t1", ["a"])
- self.assert_browse(s, "t2", ["a"])
-
- def test_dtx_timeout(self):
- """Verify that dtx timeout works"""
- cluster = self.cluster(1)
- t1 = DtxTestFixture(self, cluster[0], "t1")
- t1.start()
- t1.set_timeout(1)
- time.sleep(1.1)
- try:
- t1.end()
- self.fail("Expected rollback timeout.")
- except DtxStatusException, e:
- self.assertEqual(e.actual, XA_RBTIMEOUT)
-
-class TxTests(BrokerTest):
-
- def test_tx_update(self):
- """Verify that transaction state is updated to a new broker"""
-
- def make_message(session, body=None, key=None, id=None):
- dp=session.delivery_properties(routing_key=key)
- mp=session.message_properties(correlation_id=id)
- return qpid.datatypes.Message(dp, mp, body)
-
- cluster=self.cluster(1)
- # Use old API. TX is not supported in messaging API.
- c = cluster[0].connect_old()
- s = c.session("tx-session", 1)
- s.queue_declare(queue="q")
- # Start transaction
- s.tx_select()
- s.message_transfer(message=make_message(s, "1", "q"))
- # Start new member mid-transaction
- cluster.start()
- # Do more work
- s.message_transfer(message=make_message(s, "2", "q"))
- # Commit the transaction and verify the results.
- s.tx_commit()
- for b in cluster: self.assert_browse(b.connect().session(), "q", ["1","2"])
-
-
class LongTests(BrokerTest):
"""Tests that can run for a long time if -DDURATION=<minutes> is set"""
def duration(self):
@@ -1023,28 +316,22 @@ class LongTests(BrokerTest):
# Original cluster will all be killed so expect exit with failure
cluster = self.cluster(3, expect=EXPECT_EXIT_FAIL)
- for b in cluster: b.ready() # Wait for brokers to be ready
for b in cluster: ErrorGenerator(b)
# Start sender and receiver threads
cluster[0].declare_queue("test-queue")
- sender = NumberedSender(cluster[0], 1000) # Max queue depth
- receiver = NumberedReceiver(cluster[0], sender)
+ sender = NumberedSender(cluster[1], 1000) # Max queue depth
+ receiver = NumberedReceiver(cluster[2], sender)
receiver.start()
sender.start()
- # Wait for sender & receiver to get up and running
- retry(lambda: receiver.received > 0)
# Kill original brokers, start new ones for the duration.
endtime = time.time() + self.duration()
i = 0
while time.time() < endtime:
- sender.sender.assert_running()
- receiver.receiver.assert_running()
cluster[i].kill()
i += 1
b = cluster.start(expect=EXPECT_EXIT_FAIL)
- for b in cluster[i:]: b.ready()
ErrorGenerator(b)
time.sleep(5)
sender.stop()
@@ -1075,24 +362,24 @@ class LongTests(BrokerTest):
if self.stopped: break
self.process = self.broker.test.popen(
self.cmd, expect=EXPECT_UNKNOWN)
- finally:
- self.lock.release()
- try:
- exit = self.process.wait()
+ finally: self.lock.release()
+ try: exit = self.process.wait()
except OSError, e:
- # Process may already have been killed by self.stop()
- break
+ # Seems to be a race in wait(), it throws
+ # "no such process" during test shutdown.
+ # Doesn't indicate a test error, ignore.
+ return
except Exception, e:
self.process.unexpected(
"client of %s: %s"%(self.broker.name, e))
self.lock.acquire()
try:
+ # Quit and ignore errors if stopped or expecting failure.
if self.stopped: break
if exit != 0:
self.process.unexpected(
"client of %s exit code %s"%(self.broker.name, exit))
- finally:
- self.lock.release()
+ finally: self.lock.release()
except Exception, e:
self.error = RethrownException("Error in ClientLoop.run")
@@ -1114,7 +401,7 @@ class LongTests(BrokerTest):
args += ["--log-enable=trace+:management"]
# Use store if present.
if BrokerTest.store_lib: args +=["--load-module", BrokerTest.store_lib]
- cluster = self.cluster(3, args, expect=EXPECT_EXIT_FAIL) # brokers will be killed
+ cluster = self.cluster(3, args)
clients = [] # Per-broker list of clients that only connect to one broker.
mclients = [] # Management clients that connect to every broker in the cluster.
@@ -1123,12 +410,10 @@ class LongTests(BrokerTest):
"""Start ordinary clients for a broker."""
cmds=[
["qpid-tool", "localhost:%s"%(broker.port())],
- ["qpid-perftest", "--count=5000", "--durable=yes",
+ ["qpid-perftest", "--count", 50000,
"--base-name", str(qpid.datatypes.uuid4()), "--port", broker.port()],
- ["qpid-txtest", "--queue-base-name", "tx-%s"%str(qpid.datatypes.uuid4()),
- "--port", broker.port()],
- ["qpid-queue-stats", "-a", "localhost:%s" %(broker.port())]
- ]
+ ["qpid-queue-stats", "-a", "localhost:%s" %(broker.port())],
+ ["testagent", "localhost", str(broker.port())] ]
clients.append([ClientLoop(broker, cmd) for cmd in cmds])
def start_mclients(broker):
@@ -1137,8 +422,7 @@ class LongTests(BrokerTest):
mclients.append(ClientLoop(broker, cmd))
endtime = time.time() + self.duration()
- # For long duration, first run is a quarter of the duration.
- runtime = min(5.0, self.duration() / 3.0)
+ runtime = self.duration() / 4 # First run is longer, use quarter of duration.
alive = 0 # First live cluster member
for i in range(len(cluster)): start_clients(cluster[i])
start_mclients(cluster[alive])
@@ -1149,7 +433,7 @@ class LongTests(BrokerTest):
for b in cluster[alive:]: b.ready() # Check if a broker crashed.
# Kill the first broker, expect the clients to fail.
b = cluster[alive]
- b.ready()
+ b.expect = EXPECT_EXIT_FAIL
b.kill()
# Stop the brokers clients and all the mclients.
for c in clients[alive] + mclients:
@@ -1159,251 +443,26 @@ class LongTests(BrokerTest):
mclients = []
# Start another broker and clients
alive += 1
- cluster.start(expect=EXPECT_EXIT_FAIL)
- cluster[-1].ready() # Wait till its ready
+ cluster.start()
start_clients(cluster[-1])
start_mclients(cluster[alive])
for c in chain(mclients, *clients):
c.stop()
- for b in cluster[alive:]:
- b.ready() # Verify still alive
- b.kill()
+
# Verify that logs are consistent
cluster_test_logs.verify_logs()
def test_management_qmf2(self):
self.test_management(args=["--mgmt-qmf2=yes"])
- def test_connect_consistent(self):
+ def test_connect_consistent(self): # FIXME aconway 2011-01-18:
args=["--mgmt-pub-interval=1","--log-enable=trace+:management"]
cluster = self.cluster(2, args=args)
end = time.time() + self.duration()
while (time.time() < end): # Get a management interval
for i in xrange(1000): cluster[0].connect().close()
- cluster_test_logs.verify_logs()
-
- def test_flowlimit_failover(self):
- """Test fail-over during continuous send-receive with flow control
- active.
- """
-
- # Original cluster will all be killed so expect exit with failure
- cluster = self.cluster(3, expect=EXPECT_EXIT_FAIL)
- for b in cluster: b.ready() # Wait for brokers to be ready
-
- # create a queue with rather draconian flow control settings
- ssn0 = cluster[0].connect().session()
- s0 = ssn0.sender("test-queue; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':2000, 'qpid.flow_resume_count':100}}}}")
-
- receiver = NumberedReceiver(cluster[0])
- receiver.start()
- senders = [NumberedSender(cluster[0]) for i in range(1,3)]
- for s in senders:
- s.start()
- # Wait for senders & receiver to get up and running
- retry(lambda: receiver.received > 2*senders)
-
- # Kill original brokers, start new ones for the duration.
- endtime = time.time() + self.duration();
- i = 0
- while time.time() < endtime:
- for s in senders: s.sender.assert_running()
- receiver.receiver.assert_running()
- for b in cluster[i:]: b.ready() # Check if any broker crashed.
- cluster[i].kill()
- i += 1
- b = cluster.start(expect=EXPECT_EXIT_FAIL)
- time.sleep(5)
- for s in senders:
- s.stop()
- receiver.stop()
- for i in range(i, len(cluster)): cluster[i].kill()
-
- def test_ttl_failover(self):
- """Test that messages with TTL don't cause problems in a cluster with failover"""
-
- class Client(StoppableThread):
-
- def __init__(self, broker):
- StoppableThread.__init__(self)
- self.connection = broker.connect(reconnect=True)
- self.auto_fetch_reconnect_urls(self.connection)
- self.session = self.connection.session()
-
- def auto_fetch_reconnect_urls(self, conn):
- """Replacment for qpid.messaging.util version which is noisy"""
- ssn = conn.session("auto-fetch-reconnect-urls")
- rcv = ssn.receiver("amq.failover")
- rcv.capacity = 10
-
- def main():
- while True:
- try:
- msg = rcv.fetch()
- qpid.messaging.util.set_reconnect_urls(conn, msg)
- ssn.acknowledge(msg, sync=False)
- except messaging.exceptions.LinkClosed: return
- except messaging.exceptions.ConnectionError: return
-
- thread = Thread(name="auto-fetch-reconnect-urls", target=main)
- thread.setDaemon(True)
- thread.start()
-
- def stop(self):
- StoppableThread.stop(self)
- self.connection.detach()
-
- class Sender(Client):
- def __init__(self, broker, address):
- Client.__init__(self, broker)
- self.sent = 0 # Number of messages _reliably_ sent.
- self.sender = self.session.sender(address, capacity=1000)
-
- def send_counted(self, ttl):
- self.sender.send(Message(str(self.sent), ttl=ttl))
- self.sent += 1
-
- def run(self):
- while not self.stopped:
- choice = random.randint(0,4)
- if choice == 0: self.send_counted(None) # No ttl
- elif choice == 1: self.send_counted(100000) # Large ttl
- else: # Small ttl, might expire
- self.sender.send(Message("", ttl=random.random()/10))
- self.sender.send(Message("z"), sync=True) # Chaser.
-
- class Receiver(Client):
-
- def __init__(self, broker, address):
- Client.__init__(self, broker)
- self.received = 0 # Number of non-empty (reliable) messages received.
- self.receiver = self.session.receiver(address, capacity=1000)
- def run(self):
- try:
- while True:
- m = self.receiver.fetch(1)
- if m.content == "z": break
- if m.content: # Ignore unreliable messages
- # Ignore duplicates
- if int(m.content) == self.received: self.received += 1
- except Exception,e: self.error = e
-
- # def test_ttl_failover
-
- # Original cluster will all be killed so expect exit with failure
- # Set small purge interval.
- cluster = self.cluster(3, expect=EXPECT_EXIT_FAIL, args=["--queue-purge-interval=1"])
- for b in cluster: b.ready() # Wait for brokers to be ready
-
- # Python client failover produces noisy WARN logs, disable temporarily
- logger = logging.getLogger()
- log_level = logger.getEffectiveLevel()
- logger.setLevel(logging.ERROR)
- sender = None
- receiver = None
- try:
- # Start sender and receiver threads
- receiver = Receiver(cluster[0], "q;{create:always}")
- receiver.start()
- sender = Sender(cluster[0], "q;{create:always}")
- sender.start()
- # Wait for sender & receiver to get up and running
- retry(lambda: receiver.received > 0)
-
- # Kill brokers in a cycle.
- endtime = time.time() + self.duration()
- runtime = min(5.0, self.duration() / 4.0)
- i = 0
- while time.time() < endtime:
- for b in cluster[i:]: b.ready() # Check if any broker crashed.
- cluster[i].kill()
- i += 1
- b = cluster.start(expect=EXPECT_EXIT_FAIL)
- b.ready()
- time.sleep(runtime)
- sender.stop()
- receiver.stop()
- for b in cluster[i:]:
- b.ready() # Check it didn't crash
- b.kill()
- self.assertEqual(sender.sent, receiver.received)
cluster_test_logs.verify_logs()
- finally:
- # Detach to avoid slow reconnect attempts during shut-down if test fails.
- if sender: sender.connection.detach()
- if receiver: receiver.connection.detach()
- logger.setLevel(log_level)
-
- def test_msg_group_failover(self):
- """Test fail-over during continuous send-receive of grouped messages.
- """
-
- class GroupedTrafficGenerator(Thread):
- def __init__(self, url, queue, group_key):
- Thread.__init__(self)
- self.url = url
- self.queue = queue
- self.group_key = group_key
- self.status = -1
-
- def run(self):
- # generate traffic for approx 10 seconds (2011msgs / 200 per-sec)
- cmd = ["msg_group_test",
- "--broker=%s" % self.url,
- "--address=%s" % self.queue,
- "--connection-options={%s}" % (Cluster.CONNECTION_OPTIONS),
- "--group-key=%s" % self.group_key,
- "--receivers=2",
- "--senders=3",
- "--messages=2011",
- "--send-rate=200",
- "--capacity=11",
- "--ack-frequency=23",
- "--allow-duplicates",
- "--group-size=37",
- "--randomize-group-size",
- "--interleave=13"]
- # "--trace"]
- self.generator = Popen( cmd );
- self.status = self.generator.wait()
- return self.status
-
- def results(self):
- self.join(timeout=30) # 3x assumed duration
- if self.isAlive(): return -1
- return self.status
-
- # Original cluster will all be killed so expect exit with failure
- cluster = self.cluster(3, expect=EXPECT_EXIT_FAIL, args=["-t"])
- for b in cluster: b.ready() # Wait for brokers to be ready
-
- # create a queue with rather draconian flow control settings
- ssn0 = cluster[0].connect().session()
- q_args = "{'qpid.group_header_key':'group-id', 'qpid.shared_msg_group':1}"
- s0 = ssn0.sender("test-group-q; {create:always, node:{type:queue, x-declare:{arguments:%s}}}" % q_args)
-
- # Kill original brokers, start new ones for the duration.
- endtime = time.time() + self.duration();
- i = 0
- while time.time() < endtime:
- traffic = GroupedTrafficGenerator( cluster[i].host_port(),
- "test-group-q", "group-id" )
- traffic.start()
- time.sleep(1)
-
- for x in range(2):
- for b in cluster[i:]: b.ready() # Check if any broker crashed.
- cluster[i].kill()
- i += 1
- b = cluster.start(expect=EXPECT_EXIT_FAIL)
- time.sleep(1)
-
- # wait for traffic to finish, verify success
- self.assertEqual(0, traffic.results())
-
- for i in range(i, len(cluster)): cluster[i].kill()
-
class StoreTests(BrokerTest):
"""
diff --git a/cpp/src/tests/exception_test.cpp b/cpp/src/tests/exception_test.cpp
index 3e844b4e58..3536ffddbe 100644
--- a/cpp/src/tests/exception_test.cpp
+++ b/cpp/src/tests/exception_test.cpp
@@ -92,30 +92,32 @@ QPID_AUTO_TEST_CASE(TestSessionBusy) {
}
QPID_AUTO_TEST_CASE(DisconnectedPop) {
- SessionFixture fix;
+ ProxySessionFixture fix;
+ ProxyConnection c(fix.broker->getPort(Broker::TCP_TRANSPORT));
fix.session.queueDeclare(arg::queue="q");
fix.subs.subscribe(fix.lq, "q");
Catcher<TransportFailure> pop(bind(&LocalQueue::pop, &fix.lq, sys::TIME_SEC));
- fix.shutdownBroker();
+ fix.connection.proxy.close();
BOOST_CHECK(pop.join());
}
QPID_AUTO_TEST_CASE(DisconnectedListen) {
- SessionFixture fix;
+ ProxySessionFixture fix;
struct NullListener : public MessageListener {
void received(Message&) { BOOST_FAIL("Unexpected message"); }
} l;
+ ProxyConnection c(fix.broker->getPort(Broker::TCP_TRANSPORT));
fix.session.queueDeclare(arg::queue="q");
fix.subs.subscribe(l, "q");
Catcher<TransportFailure> runner(bind(&SubscriptionManager::run, boost::ref(fix.subs)));
- fix.shutdownBroker();
- runner.join();
+ fix.connection.proxy.close();
+ runner.join();
BOOST_CHECK_THROW(fix.session.queueDeclare(arg::queue="x"), TransportFailure);
}
QPID_AUTO_TEST_CASE(NoSuchQueueTest) {
- SessionFixture fix;
+ ProxySessionFixture fix;
ScopedSuppressLogging sl; // Suppress messages for expected errors.
BOOST_CHECK_THROW(fix.subs.subscribe(fix.lq, "no such queue"), NotFoundException);
}
diff --git a/cpp/src/tests/federated_topic_test b/cpp/src/tests/federated_topic_test
index 2e55ddcfaa..b1063c7e8c 100755
--- a/cpp/src/tests/federated_topic_test
+++ b/cpp/src/tests/federated_topic_test
@@ -42,12 +42,13 @@ while getopts "s:m:b:" opt ; do
esac
done
+MY_DIR=$(dirname $(which $0))
source ./test_env.sh
trap stop_brokers EXIT
start_broker() {
- $QPIDD_EXEC --daemon --port 0 --no-module-dir --no-data-dir --auth no > qpidd.port
+ ${MY_DIR}/../qpidd --daemon --port 0 --no-module-dir --no-data-dir --auth no > qpidd.port
}
start_brokers() {
@@ -75,39 +76,39 @@ subscribe() {
echo Subscriber $1 connecting on $MY_PORT
LOG="subscriber_$1.log"
- ./qpid-topic-listener -p $MY_PORT > $LOG 2>&1 && rm -f $LOG
+ ${MY_DIR}/topic_listener -p $MY_PORT > $LOG 2>&1 && rm -f $LOG
}
publish() {
- ./qpid-topic-publisher --messages $MESSAGES --batches $BATCHES --subscribers $SUBSCRIBERS -p $PORT_A
+ ${MY_DIR}/topic_publisher --messages $MESSAGES --batches $BATCHES --subscribers $SUBSCRIBERS -p $PORT_A
}
setup_routes() {
- BROKER_A="daffodil:$PORT_A"
- BROKER_B="daffodil:$PORT_B"
- BROKER_C="daffodil:$PORT_C"
+ BROKER_A="localhost:$PORT_A"
+ BROKER_B="localhost:$PORT_B"
+ BROKER_C="localhost:$PORT_C"
if (($VERBOSE)); then
echo "Establishing routes for topic..."
fi
- $QPID_ROUTE_EXEC route add $BROKER_B $BROKER_A amq.topic topic_control B B
- $QPID_ROUTE_EXEC 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
- $QPID_ROUTE_EXEC route add $BROKER_B $BROKER_C amq.topic topic_control B B
- $QPID_ROUTE_EXEC 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
- $QPID_ROUTE_EXEC route add $BROKER_B $BROKER_C amq.direct response B B
- $QPID_ROUTE_EXEC 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"
- $QPID_ROUTE_EXEC route list $b
+ $PYTHON_COMMANDS/qpid-route route list $b
done
fi
}
diff --git a/cpp/src/tests/federation.py b/cpp/src/tests/federation.py
index 7d613b98ce..973a1d366c 100755
--- a/cpp/src/tests/federation.py
+++ b/cpp/src/tests/federation.py
@@ -23,7 +23,7 @@ from qpid.testlib import TestBase010
from qpid.datatypes import Message
from qpid.queue import Empty
from qpid.util import URL
-from time import sleep, time
+from time import sleep
class _FedBroker(object):
@@ -111,18 +111,18 @@ class FederationTests(TestBase010):
broker = qmf.getObjects(_class="broker")[0]
result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
link = qmf.getObjects(_class="link")[0]
result = link.bridge(False, "amq.direct", "amq.direct", "my-key", "", "", False, False, False, 0)
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
bridge = qmf.getObjects(_class="bridge")[0]
result = bridge.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
result = link.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
self.verify_cleanup()
@@ -133,11 +133,11 @@ class FederationTests(TestBase010):
qmf = self.qmf
broker = qmf.getObjects(_class="broker")[0]
result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
link = qmf.getObjects(_class="link")[0]
result = link.bridge(False, "amq.direct", "amq.fanout", "my-key", "", "", False, False, False, 0)
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
bridge = qmf.getObjects(_class="bridge")[0]
@@ -165,9 +165,9 @@ class FederationTests(TestBase010):
except Empty: None
result = bridge.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
result = link.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
self.verify_cleanup()
@@ -178,11 +178,11 @@ class FederationTests(TestBase010):
qmf = self.qmf
broker = qmf.getObjects(_class="broker")[0]
result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
link = qmf.getObjects(_class="link")[0]
result = link.bridge(False, "amq.direct", "amq.fanout", "my-key", "", "", False, True, False, 0)
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
bridge = qmf.getObjects(_class="bridge")[0]
@@ -209,9 +209,9 @@ class FederationTests(TestBase010):
except Empty: None
result = bridge.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
result = link.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
self.verify_cleanup()
@@ -236,11 +236,11 @@ class FederationTests(TestBase010):
qmf = self.qmf
broker = qmf.getObjects(_class="broker")[0]
result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
link = qmf.getObjects(_class="link")[0]
result = link.bridge(False, "my-bridge-queue", "amq.fanout", "my-key", "", "", True, False, False, 1)
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
bridge = qmf.getObjects(_class="bridge")[0]
sleep(3)
@@ -262,63 +262,6 @@ class FederationTests(TestBase010):
except Empty: None
result = bridge.close()
- self.assertEqual(result.status, 0, result)
- result = link.close()
- self.assertEqual(result.status, 0, result)
-
- self.verify_cleanup()
-
- def test_pull_from_queue_recovery(self):
- session = self.session
-
- #setup queue on remote broker and add some messages
- r_conn = self.connect(host=self.remote_host(), port=self.remote_port())
- r_session = r_conn.session("test_pull_from_queue_recovery")
- r_session.queue_declare(queue="my-bridge-queue", auto_delete=True)
- for i in range(1, 6):
- dp = r_session.delivery_properties(routing_key="my-bridge-queue")
- r_session.message_transfer(message=Message(dp, "Message %d" % i))
-
- #setup queue to receive messages from local broker
- session.queue_declare(queue="fed1", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="fed1", exchange="amq.fanout")
- self.subscribe(queue="fed1", destination="f1")
- queue = session.incoming("f1")
-
- self.startQmf()
- qmf = self.qmf
- broker = qmf.getObjects(_class="broker")[0]
- result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0, result)
-
- link = qmf.getObjects(_class="link")[0]
- result = link.bridge(False, "my-bridge-queue", "amq.fanout", "my-key", "", "", True, False, False, 1)
- self.assertEqual(result.status, 0, result)
-
- bridge = qmf.getObjects(_class="bridge")[0]
- sleep(5)
-
- #recreate the remote bridge queue to invalidate the bridge session
- r_session.queue_delete (queue="my-bridge-queue", if_empty=False, if_unused=False)
- r_session.queue_declare(queue="my-bridge-queue", auto_delete=True)
-
- #add some more messages (i.e. after bridge was created)
- for i in range(6, 11):
- dp = r_session.delivery_properties(routing_key="my-bridge-queue")
- r_session.message_transfer(message=Message(dp, "Message %d" % i))
-
- for i in range(1, 11):
- try:
- msg = queue.get(timeout=5)
- self.assertEqual("Message %d" % i, msg.body)
- except Empty:
- self.fail("Failed to find expected message containing 'Message %d'" % i)
- try:
- extra = queue.get(timeout=1)
- self.fail("Got unexpected message in queue: " + extra.body)
- except Empty: None
-
- result = bridge.close()
self.assertEqual(result.status, 0)
result = link.close()
self.assertEqual(result.status, 0)
@@ -706,17 +649,10 @@ class FederationTests(TestBase010):
self.verify_cleanup()
- def test_dynamic_headers_any(self):
- self.do_test_dynamic_headers('any')
-
- def test_dynamic_headers_all(self):
- self.do_test_dynamic_headers('all')
-
-
- def do_test_dynamic_headers(self, match_mode):
+ def test_dynamic_headers(self):
session = self.session
r_conn = self.connect(host=self.remote_host(), port=self.remote_port())
- r_session = r_conn.session("test_dynamic_headers_%s" % match_mode)
+ r_session = r_conn.session("test_dynamic_headers")
session.exchange_declare(exchange="fed.headers", type="headers")
r_session.exchange_declare(exchange="fed.headers", type="headers")
@@ -735,7 +671,7 @@ class FederationTests(TestBase010):
sleep(5)
session.queue_declare(queue="fed1", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="fed1", exchange="fed.headers", binding_key="key1", arguments={'x-match':match_mode, 'class':'first'})
+ session.exchange_bind(queue="fed1", exchange="fed.headers", binding_key="key1", arguments={'x-match':'any', 'class':'first'})
self.subscribe(queue="fed1", destination="f1")
queue = session.incoming("f1")
@@ -1855,301 +1791,3 @@ class FederationTests(TestBase010):
if headers:
return headers[name]
return None
-
- def test_dynamic_topic_bounce(self):
- """ Bounce the connection between federated Topic Exchanges.
- """
- class Params:
- def exchange_type(self): return "topic"
- def bind_queue(self, ssn, qname, ename):
- ssn.exchange_bind(queue=qname, exchange=ename,
- binding_key="spud.*")
- def unbind_queue(self, ssn, qname, ename):
- ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud.*")
- def delivery_properties(self, ssn):
- return ssn.delivery_properties(routing_key="spud.boy")
-
- self.generic_dynamic_bounce_test(Params())
-
- def test_dynamic_direct_bounce(self):
- """ Bounce the connection between federated Direct Exchanges.
- """
- class Params:
- def exchange_type(self): return "direct"
- def bind_queue(self, ssn, qname, ename):
- ssn.exchange_bind(queue=qname, exchange=ename, binding_key="spud")
- def unbind_queue(self, ssn, qname, ename):
- ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud")
- def delivery_properties(self, ssn):
- return ssn.delivery_properties(routing_key="spud")
- self.generic_dynamic_bounce_test(Params())
-
- def test_dynamic_fanout_bounce(self):
- """ Bounce the connection between federated Fanout Exchanges.
- """
- class Params:
- def exchange_type(self): return "fanout"
- def bind_queue(self, ssn, qname, ename):
- ssn.exchange_bind(queue=qname, exchange=ename)
- def unbind_queue(self, ssn, qname, ename):
- ssn.exchange_unbind(queue=qname, exchange=ename)
- def delivery_properties(self, ssn):
- return ssn.delivery_properties(routing_key="spud")
- self.generic_dynamic_bounce_test(Params())
-
- def test_dynamic_headers_bounce(self):
- """ Bounce the connection between federated Headers Exchanges.
- """
- class Params:
- def exchange_type(self): return "headers"
- def bind_queue(self, ssn, qname, ename):
- ssn.exchange_bind(queue=qname, exchange=ename,
- binding_key="spud", arguments={'x-match':'any', 'class':'first'})
- def unbind_queue(self, ssn, qname, ename):
- ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud")
- def delivery_properties(self, ssn):
- return ssn.message_properties(application_headers={'class':'first'})
- ## @todo KAG - re-enable once federation bugs with headers exchanges
- ## are fixed.
- #self.generic_dynamic_bounce_test(Params())
- return
-
-
- def generic_dynamic_bounce_test(self, params):
- """ Verify that a federated broker can maintain a binding to a local
- queue using the same key as a remote binding. Destroy and reconnect
- the federation link, and verify routes are restored correctly.
- See QPID-3170.
- Topology:
-
- Queue1 <---"Key"---B0<==[Federated Exchange]==>B1---"Key"--->Queue2
- """
- session = self.session
-
- # create the federation
-
- self.startQmf()
- qmf = self.qmf
-
- self._setup_brokers()
-
- # create exchange on each broker, and retrieve the corresponding
- # management object for that exchange
-
- exchanges=[]
- for _b in self._brokers[0:2]:
- _b.client_session.exchange_declare(exchange="fedX", type=params.exchange_type())
- self.assertEqual(_b.client_session.exchange_query(name="fedX").type,
- params.exchange_type(), "exchange_declare failed!")
- # pull the exchange out of qmf...
- retries = 0
- my_exchange = None
- timeout = time() + 10
- while my_exchange is None and time() <= timeout:
- objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange")
- for ooo in objs:
- if ooo.name == "fedX":
- my_exchange = ooo
- break
- if my_exchange is None:
- self.fail("QMF failed to find new exchange!")
- exchanges.append(my_exchange)
-
- #
- # on each broker, create a local queue bound to the exchange with the
- # same key value.
- #
-
- self._brokers[0].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True)
- params.bind_queue(self._brokers[0].client_session, "fedX1", "fedX")
- self.subscribe(self._brokers[0].client_session, queue="fedX1", destination="f1")
- queue_0 = self._brokers[0].client_session.incoming("f1")
-
- self._brokers[1].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True)
- params.bind_queue(self._brokers[1].client_session, "fedX1", "fedX")
- self.subscribe(self._brokers[1].client_session, queue="fedX1", destination="f1")
- queue_1 = self._brokers[1].client_session.incoming("f1")
-
- # now federate the two brokers
-
- # connect B0 --> B1
- result = self._brokers[1].qmf_object.connect(self._brokers[0].host,
- self._brokers[0].port,
- False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0)
-
- # connect B1 --> B0
- result = self._brokers[0].qmf_object.connect(self._brokers[1].host,
- self._brokers[1].port,
- False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0)
-
- # for each link, bridge the "fedX" exchanges:
-
- for _l in qmf.getObjects(_class="link"):
- # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker())))
- result = _l.bridge(False, # durable
- "fedX", # src
- "fedX", # dst
- "", # key
- "", # tag
- "", # excludes
- False, # srcIsQueue
- False, # srcIsLocal
- True, # dynamic
- 0) # sync
- self.assertEqual(result.status, 0)
-
- # wait for all the inter-broker links to become operational
- operational = False
- timeout = time() + 10
- while not operational and time() <= timeout:
- operational = True
- for _l in qmf.getObjects(_class="link"):
- #print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state)))
- if _l.state != "Operational":
- operational = False
- self.failUnless(operational, "inter-broker links failed to become operational.")
-
- # @todo - There is no way to determine when the bridge objects become
- # active.
-
- # wait until the binding key has propagated to each broker - each
- # broker should see 2 bindings (1 local, 1 remote)
-
- binding_counts = [2, 2]
- self.assertEqual(len(binding_counts), len(exchanges), "Update Test!")
- for i in range(2):
- exchanges[i].update()
- timeout = time() + 10
- while exchanges[i].bindingCount < binding_counts[i] and time() <= timeout:
- exchanges[i].update()
- self.failUnless(exchanges[i].bindingCount == binding_counts[i])
-
- # send 10 msgs to B0
- for i in range(1, 11):
- # dp = self._brokers[0].client_session.delivery_properties(routing_key=params.routing_key())
- dp = params.delivery_properties(self._brokers[0].client_session)
- self._brokers[0].client_session.message_transfer(destination="fedX", message=Message(dp, "Message_trp %d" % i))
-
- # get exactly 10 msgs on B0's local queue and B1's queue
- for i in range(1, 11):
- try:
- msg = queue_0.get(timeout=5)
- self.assertEqual("Message_trp %d" % i, msg.body)
- msg = queue_1.get(timeout=5)
- self.assertEqual("Message_trp %d" % i, msg.body)
- except Empty:
- self.fail("Only got %d msgs - expected 10" % i)
- try:
- extra = queue_0.get(timeout=1)
- self.fail("Got unexpected message in queue_0: " + extra.body)
- except Empty: None
-
- try:
- extra = queue_1.get(timeout=1)
- self.fail("Got unexpected message in queue_1: " + extra.body)
- except Empty: None
-
- #
- # Tear down the bridges between the two exchanges, then wait
- # for the bindings to be cleaned up
- #
-
- for _b in qmf.getObjects(_class="bridge"):
- result = _b.close()
- self.assertEqual(result.status, 0)
-
- binding_counts = [1, 1]
- self.assertEqual(len(binding_counts), len(exchanges), "Update Test!")
- for i in range(2):
- exchanges[i].update()
- timeout = time() + 10
- while exchanges[i].bindingCount != binding_counts[i] and time() <= timeout:
- exchanges[i].update()
- self.failUnless(exchanges[i].bindingCount == binding_counts[i])
-
- #
- # restore the bridges between the two exchanges, and wait for the
- # bindings to propagate.
- #
-
- for _l in qmf.getObjects(_class="link"):
- # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker())))
- result = _l.bridge(False, # durable
- "fedX", # src
- "fedX", # dst
- "", # key
- "", # tag
- "", # excludes
- False, # srcIsQueue
- False, # srcIsLocal
- True, # dynamic
- 0) # sync
- self.assertEqual(result.status, 0)
-
- binding_counts = [2, 2]
- self.assertEqual(len(binding_counts), len(exchanges), "Update Test!")
- for i in range(2):
- exchanges[i].update()
- timeout = time() + 10
- while exchanges[i].bindingCount != binding_counts[i] and time() <= timeout:
- exchanges[i].update()
- self.failUnless(exchanges[i].bindingCount == binding_counts[i])
-
- #
- # verify traffic flows correctly
- #
-
- for i in range(1, 11):
- #dp = self._brokers[1].client_session.delivery_properties(routing_key=params.routing_key())
- dp = params.delivery_properties(self._brokers[1].client_session)
- self._brokers[1].client_session.message_transfer(destination="fedX", message=Message(dp, "Message_trp %d" % i))
-
- # get exactly 10 msgs on B0's queue and B1's queue
- for i in range(1, 11):
- try:
- msg = queue_0.get(timeout=5)
- self.assertEqual("Message_trp %d" % i, msg.body)
- msg = queue_1.get(timeout=5)
- self.assertEqual("Message_trp %d" % i, msg.body)
- except Empty:
- self.fail("Only got %d msgs - expected 10" % i)
- try:
- extra = queue_0.get(timeout=1)
- self.fail("Got unexpected message in queue_0: " + extra.body)
- except Empty: None
-
- try:
- extra = queue_1.get(timeout=1)
- self.fail("Got unexpected message in queue_1: " + extra.body)
- except Empty: None
-
-
- #
- # cleanup
- #
- params.unbind_queue(self._brokers[0].client_session, "fedX1", "fedX")
- self._brokers[0].client_session.message_cancel(destination="f1")
- self._brokers[0].client_session.queue_delete(queue="fedX1")
-
- params.unbind_queue(self._brokers[1].client_session, "fedX1", "fedX")
- self._brokers[1].client_session.message_cancel(destination="f1")
- self._brokers[1].client_session.queue_delete(queue="fedX1")
-
- for _b in qmf.getObjects(_class="bridge"):
- result = _b.close()
- self.assertEqual(result.status, 0)
-
- for _l in qmf.getObjects(_class="link"):
- result = _l.close()
- self.assertEqual(result.status, 0)
-
- for _b in self._brokers[0:2]:
- _b.client_session.exchange_delete(exchange="fedX")
-
- self._teardown_brokers()
-
- self.verify_cleanup()
-
-
diff --git a/cpp/src/tests/federation_sys.py b/cpp/src/tests/federation_sys.py
deleted file mode 100755
index 11590f684e..0000000000
--- a/cpp/src/tests/federation_sys.py
+++ /dev/null
@@ -1,1900 +0,0 @@
-#!/usr/bin/env python
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-from inspect import stack
-from qpid import messaging
-from qpid.messaging import Message
-from qpid.messaging.exceptions import Empty
-from qpid.testlib import TestBase010
-from random import randint
-from sys import stdout
-from time import sleep
-
-
-class Enum(object):
- def __init__(self, **entries):
- self.__dict__.update(entries)
- def __repr__(self):
- args = ['%s=%s' % (k, repr(v)) for (k,v) in vars(self).items()]
- return 'Enum(%s)' % ', '.join(args)
-
-
-class QmfTestBase010(TestBase010):
-
- _brokers = []
- _links = []
- _bridges = []
- _alt_exch_ops = Enum(none=0, create=1, delete=2)
-
- class _Broker(object):
- """
- This broker proxy object holds the Qmf proxy to a broker of known address as well as the QMF broker
- object, connection and sessions to the broker.
- """
- def __init__(self, url):
- self.url = url # format: "host:port"
- url_parts = url.split(':')
- self.host = url_parts[0]
- self.port = int(url_parts[1])
- self.qmf_broker = None
- self.connection = messaging.Connection.establish(self.url)
- self.sessions = []
- def __str__(self):
- return "_Broker %s:%s (%d open sessions)" % (self.host, self.port, len(self.sessions))
- def destroy(self, qmf = None):
- if qmf is not None:
- qmf.delBroker(self.qmf_broker.getBroker())
- for session in self.sessions:
- try: # Session may have been closed by broker error
- session.close()
- except Exception, e: print "WARNING: %s: Unable to close session %s (%s): %s %s" % (self, session, hex(id(session)), type(e), e)
- try: # Connection may have been closed by broker error
- self.connection.close()
- except Exception, e: print "WARNING: %s: Unable to close connection %s (%s): %s %s" % (self, self.connection, hex(id(self.connection)), type(e), e)
- def session(self, name, transactional_flag = False):
- session = self.connection.session(name, transactional_flag)
- self.sessions.append(session)
- return session
-
- def setUp(self):
- """
- Called one before each test starts
- """
- TestBase010.setUp(self)
- self.startQmf();
-
- def tearDown(self):
- """
- Called once after each test competes. Close all Qmf objects (bridges, links and brokers)
- """
- while len(self._bridges):
- self._bridges.pop().close()
- while len(self._links):
- self._links.pop().close()
- while len(self._brokers):
- b = self._brokers.pop()
- if len(self._brokers) <= 1:
- b.destroy(None)
- else:
- b.destroy(self.qmf)
- TestBase010.tearDown(self)
- self.qmf.close()
-
- #--- General test utility functions
-
- def _get_name(self):
- """
- Return the name of method which called this method stripped of "test_" prefix. Used for naming
- queues and exchanges on a per-test basis.
- """
- return stack()[1][3][5:]
-
- def _get_broker_port(self, key):
- """
- Get the port of a broker defined in the environment using -D<key>=portno
- """
- return int(self.defines[key])
-
- def _get_cluster_ports(self, key):
- """
- Get the cluster ports from the parameters of the test which place it in the environment using
- -D<key>="port0 port1 ... portN" (space-separated)
- """
- ports = []
- ports_str = self.defines[key]
- if ports_str:
- for p in ports_str.split():
- ports.append(int(p))
- return ports
-
- def _get_send_address(self, exch_name, queue_name):
- """
- Get an address to which to send messages based on the exchange name and queue name, but taking into account
- that the exchange name may be "" (the default exchange), in whcih case the format changes slightly.
- """
- if len(exch_name) == 0: # Default exchange
- return queue_name
- return "%s/%s" % (exch_name, queue_name)
-
- def _get_broker(self, cluster_flag, broker_port_key, cluster_ports_key):
- """
- Read the port numbers for pre-started brokers from the environment using keys, then find or create and return
- the Qmf broker proxy for the appropriate broker
- """
- if cluster_flag:
- port = self._get_cluster_ports(cluster_ports_key)[0] # Always use the first node in the cluster
- else:
- port = self._get_broker_port(broker_port_key)
- return self._find_create_broker("localhost:%s" % port)
-
- def _get_msg_subject(self, topic_key):
- """
- Return an appropriate subject for sending a message to a known topic. Return None if there is no topic.
- """
- if len(topic_key) == 0: return None
- if "*" in topic_key: return topic_key.replace("*", "test")
- if "#" in topic_key: return topic_key.replace("#", "multipart.test")
- return topic_key
-
- def _send_msgs(self, session_name, broker, addr, msg_count, msg_content = "Message_%03d", topic_key = "",
- msg_durable_flag = False, enq_txn_size = 0):
- """
- Send messages to a broker using address addr
- """
- send_session = broker.session(session_name, transactional_flag = enq_txn_size > 0)
- sender = send_session.sender(addr)
- txn_cnt = 0
- for i in range(0, msg_count):
- sender.send(Message(msg_content % (i + 1), subject = self._get_msg_subject(topic_key), durable = msg_durable_flag))
- if enq_txn_size > 0:
- txn_cnt += 1
- if txn_cnt >= enq_txn_size:
- send_session.commit()
- txn_cnt = 0
- if enq_txn_size > 0 and txn_cnt > 0:
- send_session.commit()
- sender.close()
- send_session.close()
-
- def _receive_msgs(self, session_name, broker, addr, msg_count, msg_content = "Message_%03d", deq_txn_size = 0,
- timeout = 0):
- """
- Receive messages from a broker
- """
- receive_session = broker.session(session_name, transactional_flag = deq_txn_size > 0)
- receiver = receive_session.receiver(addr)
- txn_cnt = 0
- for i in range(0, msg_count):
- try:
- msg = receiver.fetch(timeout = timeout)
- if deq_txn_size > 0:
- txn_cnt += 1
- if txn_cnt >= deq_txn_size:
- receive_session.commit()
- txn_cnt = 0
- receive_session.acknowledge()
- except Empty:
- if deq_txn_size > 0: receive_session.rollback()
- receiver.close()
- receive_session.close()
- if i == 0:
- self.fail("Broker %s queue \"%s\" is empty" % (broker.qmf_broker.getBroker().getUrl(), addr))
- else:
- self.fail("Unable to receive message %d from broker %s queue \"%s\"" % (i, broker.qmf_broker.getBroker().getUrl(), addr))
- if msg.content != msg_content % (i + 1):
- receiver.close()
- receive_session.close()
- self.fail("Unexpected message \"%s\", was expecting \"%s\"." % (msg.content, msg_content % (i + 1)))
- try:
- msg = receiver.fetch(timeout = 0)
- if deq_txn_size > 0: receive_session.rollback()
- receiver.close()
- receive_session.close()
- self.fail("Extra message \"%s\" found on broker %s address \"%s\"" % (msg.content, broker.qmf_broker.getBroker().getUrl(), addr))
- except Empty:
- pass
- if deq_txn_size > 0 and txn_cnt > 0:
- receive_session.commit()
- receiver.close()
- receive_session.close()
-
- #--- QMF-specific utility functions
-
- def _get_qmf_property(self, props, key):
- """
- Get the value of a named property key kj from a property list [(k0, v0), (k1, v1), ... (kn, vn)].
- """
- for k,v in props:
- if k.name == key:
- return v
- return None
-
- def _check_qmf_return(self, method_result):
- """
- Check the result of a Qmf-defined method call
- """
- self.assertTrue(method_result.status == 0, method_result.text)
-
- def _check_optional_qmf_property(self, qmf_broker, type, qmf_object, key, expected_val, obj_ref_flag):
- """
- Optional Qmf properties don't show up in the properties list when they are not specified. Checks for
- these property types involve searching the properties list and making sure it is present or not as
- expected.
- """
- val = self._get_qmf_property(qmf_object.getProperties(), key)
- if val is None:
- if len(expected_val) > 0:
- self.fail("%s %s exists, but has does not have %s property. Expected value: \"%s\"" %
- (type, qmf_object.name, key, expected_val))
- else:
- if len(expected_val) > 0:
- if obj_ref_flag:
- obj = self.qmf.getObjects(_objectId = val, _broker = qmf_broker.getBroker())
- self.assertEqual(len(obj), 1, "More than one object with the same objectId: %s" % obj)
- val = obj[0].name
- self.assertEqual(val, expected_val, "%s %s exists, but has incorrect %s property. Found \"%s\", expected \"%s\"" %
- (type, qmf_object.name, key, val, expected_val))
- else:
- self.fail("%s %s exists, but has an unexpected %s property \"%s\" set." % (type, qmf_object.name, key, val))
-
- #--- Find/create Qmf broker objects
-
- def _find_qmf_broker(self, url):
- """
- Find the Qmf broker object for the given broker URL. The broker must have been previously added to Qmf through
- addBroker()
- """
- for b in self.qmf.getObjects(_class="broker"):
- if b.getBroker().getUrl() == url:
- return b
- return None
-
- def _find_create_broker(self, url):
- """
- Find a running broker through Qmf. If it does not exist, add it (assuming the broker is already running).
- """
- broker = self._Broker(url)
- self._brokers.append(broker)
- if self.qmf is not None:
- qmf_broker = self._find_qmf_broker(broker.url)
- if qmf_broker is None:
- self.qmf.addBroker(broker.url)
- broker.qmf_broker = self._find_qmf_broker(broker.url)
- else:
- broker.qmf_broker = qmf_broker
- return broker
-
- #--- Find/create/delete exchanges
-
- def _find_qmf_exchange(self, qmf_broker, name, type, alternate, durable, auto_delete):
- """
- Find Qmf exchange object
- """
- for e in self.qmf.getObjects(_class="exchange", _broker = qmf_broker.getBroker()):
- if e.name == name:
- if len(name) == 0 or (len(name) >= 4 and name[:4] == "amq."): return e # skip checks for special exchanges
- self.assertEqual(e.type, type,
- "Exchange \"%s\" exists, but is of unexpected type %s; expected type %s." %
- (name, e.type, type))
- self._check_optional_qmf_property(qmf_broker, "Exchange", e, "altExchange", alternate, True)
- self.assertEqual(e.durable, durable,
- "Exchange \"%s\" exists, but has incorrect durability. Found durable=%s, expected durable=%s" %
- (name, e.durable, durable))
- self.assertEqual(e.autoDelete, auto_delete,
- "Exchange \"%s\" exists, but has incorrect auto-delete property. Found %s, expected %s" %
- (name, e.autoDelete, auto_delete))
- return e
- return None
-
- def _find_create_qmf_exchange(self, qmf_broker, name, type, alternate, durable, auto_delete, args):
- """
- Find Qmf exchange object if exchange exists, create exchange and return its Qmf object if not
- """
- e = self._find_qmf_exchange(qmf_broker, name, type, alternate, durable, auto_delete)
- if e is not None: return e
- # Does not exist, so create it
- props = dict({"exchange-type": type, "type": type, "durable": durable, "auto-delete": auto_delete, "alternate-exchange": alternate}, **args)
- self._check_qmf_return(qmf_broker.create(type="exchange", name=name, properties=props, strict=True))
- e = self._find_qmf_exchange(qmf_broker, name, type, alternate, durable, auto_delete)
- self.assertNotEqual(e, None, "Creation of exchange %s on broker %s failed" % (name, qmf_broker.getBroker().getUrl()))
- return e
-
- def _find_delete_qmf_exchange(self, qmf_broker, name, type, alternate, durable, auto_delete):
- """
- Find and delete Qmf exchange object if it exists
- """
- e = self._find_qmf_exchange(qmf_broker, name, type, alternate, durable, auto_delete)
- if e is not None and not auto_delete:
- self._check_qmf_return(qmf_broker.delete(type="exchange", name=name, options={}))
-
- #--- Find/create/delete queues
-
- def _find_qmf_queue(self, qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete):
- """
- Find a Qmf queue object
- """
- for q in self.qmf.getObjects(_class="queue", _broker = qmf_broker.getBroker()):
- if q.name == name:
- self._check_optional_qmf_property(qmf_broker, "Queue", q, "altExchange", alternate_exchange, True)
- self.assertEqual(q.durable, durable,
- "Queue \"%s\" exists, but has incorrect durable property. Found %s, expected %s" %
- (name, q.durable, durable))
- self.assertEqual(q.exclusive, exclusive,
- "Queue \"%s\" exists, but has incorrect exclusive property. Found %s, expected %s" %
- (name, q.exclusive, exclusive))
- self.assertEqual(q.autoDelete, auto_delete,
- "Queue \"%s\" exists, but has incorrect auto-delete property. Found %s, expected %s" %
- (name, q.autoDelete, auto_delete))
- return q
- return None
-
- def _find_create_qmf_queue(self, qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete, args):
- """
- Find Qmf queue object if queue exists, create queue and return its Qmf object if not
- """
- q = self._find_qmf_queue(qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete)
- if q is not None: return q
- # Queue does not exist, so create it
- props = dict({"durable": durable, "auto-delete": auto_delete, "exclusive": exclusive, "alternate-exchange": alternate_exchange}, **args)
- self._check_qmf_return(qmf_broker.create(type="queue", name=name, properties=props, strict=True))
- q = self._find_qmf_queue(qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete)
- self.assertNotEqual(q, None, "Creation of queue %s on broker %s failed" % (name, qmf_broker.getBroker().getUrl()))
- return q
-
- def _find_delete_qmf_queue(self, qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete, args):
- """
- Find and delete Qmf queue object if it exists
- """
- q = self._find_qmf_queue(qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete)
- if q is not None and not auto_delete:
- self._check_qmf_return(qmf_broker.delete(type="queue", name=name, options={}))
-
- #--- Find/create/delete bindings (between an exchange and a queue)
-
- def _find_qmf_binding(self, qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args):
- """
- Find a Qmf binding object
- """
- for b in self.qmf.getObjects(_class="binding", _broker = qmf_broker.getBroker()):
- if b.exchangeRef == qmf_exchange.getObjectId() and b.queueRef == qmf_queue.getObjectId():
- if qmf_exchange.type != "fanout": # Fanout ignores the binding key, and always returns "" as the key
- self.assertEqual(b.bindingKey, binding_key,
- "Binding between exchange %s and queue %s exists, but has mismatching binding key: Found %s, expected %s." %
- (qmf_exchange.name, qmf_queue.name, b.bindingKey, binding_key))
- self.assertEqual(b.arguments, binding_args,
- "Binding between exchange %s and queue %s exists, but has mismatching arguments: Found %s, expected %s" %
- (qmf_exchange.name, qmf_queue.name, b.arguments, binding_args))
- return b
- return None
-
- def _find_create_qmf_binding(self, qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args):
- """
- Find Qmf binding object if it exists, create binding and return its Qmf object if not
- """
- b = self._find_qmf_binding(qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args)
- if b is not None: return b
- # Does not exist, so create it
- self._check_qmf_return(qmf_broker.create(type="binding", name="%s/%s/%s" % (qmf_exchange.name, qmf_queue.name, binding_key), properties=binding_args, strict=True))
- b = self._find_qmf_binding(qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args)
- self.assertNotEqual(b, None, "Creation of binding between exchange %s and queue %s with key %s failed" %
- (qmf_exchange.name, qmf_queue.name, binding_key))
- return b
-
- def _find_delete_qmf_binding(self, qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args):
- """
- Find and delete Qmf binding object if it exists
- """
- b = self._find_qmf_binding(qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args)
- if b is not None:
- if len(qmf_exchange.name) > 0: # not default exchange
- self._check_qmf_return(qmf_broker.delete(type="binding", name="%s/%s/%s" % (qmf_exchange.name, qmf_queue.name, binding_key), options={}))
-
- #--- Find/create a link
-
- def _find_qmf_link(self, qmf_from_broker_proxy, host, port):
- """
- Find a Qmf link object
- """
- for l in self.qmf.getObjects(_class="link", _broker=qmf_from_broker_proxy):
- if l.host == host and l.port == port:
- return l
- return None
-
- def _find_create_qmf_link(self, qmf_from_broker, qmf_to_broker_proxy, link_durable_flag, auth_mechanism, user_id,
- password, transport, pause_interval, link_ready_timeout):
- """
- Find a Qmf link object if it exists, create it and return its Qmf link object if not
- """
- to_broker_host = qmf_to_broker_proxy.host
- to_broker_port = qmf_to_broker_proxy.port
- l = self._find_qmf_link(qmf_from_broker.getBroker(), to_broker_host, to_broker_port)
- if l is not None: return l
- # Does not exist, so create it
- self._check_qmf_return(qmf_from_broker.connect(to_broker_host, to_broker_port, link_durable_flag, auth_mechanism, user_id, password, transport))
- l = self._find_qmf_link(qmf_from_broker.getBroker(), to_broker_host, to_broker_port)
- self.assertNotEqual(l, None, "Creation of link from broker %s to broker %s failed" %
- (qmf_from_broker.getBroker().getUrl(), qmf_to_broker_proxy.getUrl()))
- self._wait_for_link(l, pause_interval, link_ready_timeout)
- return l
-
- def _wait_for_link(self, link, pause_interval, link_ready_timeout):
- """
- Wait for link to become active (state=Operational)
- """
- tot_time = 0
- link.update()
- if link.state == "":
- # Link mgmt updates for the c++ link object are disabled when in a cluster because of inconsistent state:
- # one is "Operational", the other "Passive". In this case, wait a bit and hope for the best...
- sleep(2*pause_interval)
- else:
- while link.state != "Operational" and tot_time < link_ready_timeout:
- sleep(pause_interval)
- tot_time += pause_interval
- link.update()
- self.assertEqual(link.state, "Operational", "Timeout: Link not operational, state=%s" % link.state)
-
- #--- Find/create a bridge
-
- def _find_qmf_bridge(self, qmf_broker_proxy, qmf_link, source, destination, key):
- """
- Find a Qmf link object
- """
- for b in self.qmf.getObjects(_class="bridge", _broker=qmf_broker_proxy):
- if b.linkRef == qmf_link.getObjectId() and b.src == source and b.dest == destination and b.key == key:
- return b
- return None
-
- def _find_create_qmf_bridge(self, qmf_broker_proxy, qmf_link, queue_name, exch_name, topic_key,
- queue_route_type_flag, bridge_durable_flag):
- """
- Find a Qmf bridge object if it exists, create it and return its Qmf object if not
- """
- if queue_route_type_flag:
- src = queue_name
- dest = exch_name
- key = ""
- else:
- src = exch_name
- dest = exch_name
- if len(topic_key) > 0:
- key = topic_key
- else:
- key = queue_name
- b = self._find_qmf_bridge(qmf_broker_proxy, qmf_link, src, dest, key)
- if b is not None:
- return b
- # Does not exist, so create it
- self._check_qmf_return(qmf_link.bridge(bridge_durable_flag, src, dest, key, "", "", queue_route_type_flag, False, False, 1))
- b = self._find_qmf_bridge(qmf_broker_proxy, qmf_link, src, dest, key)
- self.assertNotEqual(b, None, "Bridge creation failed: src=%s dest=%s key=%s" % (src, dest, key))
- return b
-
- def _wait_for_bridge(self, bridge, src_broker, dest_broker, exch_name, queue_name, topic_key, pause_interval,
- bridge_ready_timeout):
- """
- Wait for bridge to become active by sending messages over the bridge at 1 sec intervals until they are
- observed at the destination.
- """
- tot_time = 0
- active = False
- send_session = src_broker.session("tx")
- sender = send_session.sender(self._get_send_address(exch_name, queue_name))
- src_receive_session = src_broker.session("src_rx")
- src_receiver = src_receive_session.receiver(queue_name)
- dest_receive_session = dest_broker.session("dest_rx")
- dest_receiver = dest_receive_session.receiver(queue_name)
- while not active and tot_time < bridge_ready_timeout:
- sender.send(Message("xyz123", subject = self._get_msg_subject(topic_key)))
- try:
- src_receiver.fetch(timeout = 0)
- src_receive_session.acknowledge()
- # Keep receiving msgs, as several may have accumulated
- while True:
- dest_receiver.fetch(timeout = 0)
- dest_receive_session.acknowledge()
- sleep(1)
- active = True
- except Empty:
- sleep(pause_interval)
- tot_time += pause_interval
- dest_receiver.close()
- dest_receive_session.close()
- src_receiver.close()
- src_receive_session.close()
- sender.close()
- send_session.close()
- self.assertTrue(active, "Bridge failed to become active after %ds: %s" % (bridge_ready_timeout, bridge))
-
- #--- Find/create/delete utility functions
-
- def _create_and_bind(self, qmf_broker, exchange_args, queue_args, binding_args):
- """
- Create a binding between a named exchange and queue on a broker
- """
- e = self._find_create_qmf_exchange(qmf_broker, **exchange_args)
- q = self._find_create_qmf_queue(qmf_broker, **queue_args)
- return self._find_create_qmf_binding(qmf_broker, e, q, **binding_args)
-
- def _check_alt_exchange(self, qmf_broker, alt_exch_name, alt_exch_type, alt_exch_op):
- """
- Check for existence of alternate exchange. Return the Qmf exchange proxy object for the alternate exchange
- """
- if len(alt_exch_name) == 0: return None
- if alt_exch_op == _alt_exch_ops.create:
- return self._find_create_qmf_exchange(qmf_broker=qmf_broker, name=alt_exch_name, type=alt_exch_type,
- alternate="", durable=False, auto_delete=False, args={})
- if alt_exch_op == _alt_exch_ops.delete:
- return self._find_delete_qmf_exchange(qmf_broker=qmf_broker, name=alt_exch_name, type=alt_exch_type,
- alternate="", durable=False, auto_delete=False)
- return self._find_qmf_exchange(qmf_broker=qmf_broker, name=alt_exchange_name, type=alt_exchange_type,
- alternate="", durable=False, auto_delete=False)
-
- def _delete_queue_binding(self, qmf_broker, exchange_args, queue_args, binding_args):
- """
- Delete a queue and the binding between it and the exchange
- """
- e = self._find_qmf_exchange(qmf_broker, exchange_args["name"], exchange_args["type"], exchange_args["alternate"], exchange_args["durable"], exchange_args["auto_delete"])
- q = self._find_qmf_queue(qmf_broker, queue_args["name"], queue_args["alternate_exchange"], queue_args["durable"], queue_args["exclusive"], queue_args["auto_delete"])
- self._find_delete_qmf_binding(qmf_broker, e, q, **binding_args)
- self._find_delete_qmf_queue(qmf_broker, **queue_args)
-
- def _create_route(self, queue_route_type_flag, src_broker, dest_broker, exch_name, queue_name, topic_key,
- link_durable_flag, bridge_durable_flag, auth_mechanism, user_id, password, transport,
- pause_interval = 1, link_ready_timeout = 20, bridge_ready_timeout = 20):
- """
- Create a route from a source broker to a destination broker
- """
- l = self._find_create_qmf_link(dest_broker.qmf_broker, src_broker.qmf_broker.getBroker(), link_durable_flag,
- auth_mechanism, user_id, password, transport, pause_interval, link_ready_timeout)
- self._links.append(l)
- b = self._find_create_qmf_bridge(dest_broker.qmf_broker.getBroker(), l, queue_name, exch_name, topic_key,
- queue_route_type_flag, bridge_durable_flag)
- self._bridges.append(b)
- self._wait_for_bridge(b, src_broker, dest_broker, exch_name, queue_name, topic_key, pause_interval, bridge_ready_timeout)
-
- # Parameterized test - entry point for tests
-
- def _do_test(self,
- test_name, # Name of test
- exch_name = "amq.direct", # Remote exchange name
- exch_type = "direct", # Remote exchange type
- exch_alt_exch = "", # Remote exchange alternate exchange
- exch_alt_exch_type = "direct", # Remote exchange alternate exchange type
- exch_durable_flag = False, # Remote exchange durability
- exch_auto_delete_flag = False, # Remote exchange auto-delete property
- exch_x_args = {}, # Remote exchange args
- queue_alt_exch = "", # Remote queue alternate exchange
- queue_alt_exch_type = "direct", # Remote queue alternate exchange type
- queue_durable_flag = False, # Remote queue durability
- queue_exclusive_flag = False, # Remote queue exclusive property
- queue_auto_delete_flag = False, # Remote queue auto-delete property
- queue_x_args = {}, # Remote queue args
- binding_durable_flag = False, # Remote binding durability
- binding_x_args = {}, # Remote binding args
- topic_key = "", # Binding key For remote topic exchanges only
- msg_count = 10, # Number of messages to send
- msg_durable_flag = False, # Message durability
- link_durable_flag = False, # Route link durability
- bridge_durable_flag = False, # Route bridge durability
- queue_route_type_flag = False, # Route type: false = bridge route, true = queue route
- enq_txn_size = 0, # Enqueue transaction size, 0 = no transactions
- deq_txn_size = 0, # Dequeue transaction size, 0 = no transactions
- local_cluster_flag = False, # Use a node from the local cluster, otherwise use single local broker
- remote_cluster_flag = False, # Use a node from the remote cluster, otherwise use single remote broker
- alt_exch_op = _alt_exch_ops.create,# Op on alt exch [create (ensure present), delete (ensure not present), none (neither create nor delete)]
- auth_mechanism = "", # Authorization mechanism for linked broker
- user_id = "", # User ID for authorization on linked broker
- password = "", # Password for authorization on linked broker
- transport = "tcp" # Transport for route to linked broker
- ):
- """
- Parameterized federation test. Sets up a federated link between a source broker and a destination broker and
- checks that messages correctly pass over the link to the destination. Where appropriate (non-queue-routes), also
- checks for the presence of messages on the source broker.
-
- In these tests, the concept is to create a LOCAL broker, then create a link to a REMOTE broker using federation.
- In other words, the messages sent to the LOCAL broker will be replicated on the REMOTE broker, and tests are
- performed on the REMOTE broker to check that the required messages are present. In the case of regular routes,
- the LOCAL broker will also retain the messages, and a similar test is performed on this broker.
-
- TODO: There are several items to improve here:
- 1. _do_test() is rather general. Rather create a version for each exchange type and test the exchange/queue
- interaction in more detail based on the exchange type
- 2. Add a headers and an xml exchange type
- 3. Restructure the tests to start and stop brokers and clusters directly rather than relying on previously
- started brokers. Then persistence can be checked by stopping and restarting the brokers/clusters. In particular,
- test the persistence of links and bridges, both of which take a persistence flag.
- 4. Test the behavior of the alternate exchanges when messages are sourced through a link. Also check behavior
- when the alternate exchange is not present or is deleted after the reference is made.
- 5. Test special queue types (eg LVQ)
- """
- local_broker = self._get_broker(local_cluster_flag, "local-port", "local-cluster-ports")
- remote_broker = self._get_broker(remote_cluster_flag, "remote-port", "remote-cluster-ports")
-
- # Check alternate exchanges exist (and create them if not) on both local and remote brokers
- self._check_alt_exchange(local_broker.qmf_broker, exch_alt_exch, exch_alt_exch_type, alt_exch_op)
- self._check_alt_exchange(local_broker.qmf_broker, queue_alt_exch, queue_alt_exch_type, alt_exch_op)
- self._check_alt_exchange(remote_broker.qmf_broker, exch_alt_exch, exch_alt_exch_type, alt_exch_op)
- self._check_alt_exchange(remote_broker.qmf_broker, queue_alt_exch, queue_alt_exch_type, alt_exch_op)
-
- queue_name = "queue_%s" % test_name
- exchange_args = {"name": exch_name, "type": exch_type, "alternate": exch_alt_exch,
- "durable": exch_durable_flag, "auto_delete": exch_auto_delete_flag, "args": exch_x_args}
- queue_args = {"name": queue_name, "alternate_exchange": queue_alt_exch, "durable": queue_durable_flag,
- "exclusive": queue_exclusive_flag, "auto_delete": queue_auto_delete_flag, "args": queue_x_args}
- binding_args = {"binding_args": binding_x_args}
- if exch_type == "topic":
- self.assertTrue(len(topic_key) > 0, "Topic exchange selected, but no topic key was set.")
- binding_args["binding_key"] = topic_key
- elif exch_type == "direct":
- binding_args["binding_key"] = queue_name
- else:
- binding_args["binding_key"] = ""
- self._create_and_bind(qmf_broker=local_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args)
- self._create_and_bind(qmf_broker=remote_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args)
- self._create_route(queue_route_type_flag, local_broker, remote_broker, exch_name, queue_name, topic_key,
- link_durable_flag, bridge_durable_flag, auth_mechanism, user_id, password, transport)
-
- self._send_msgs("send_session", local_broker, addr = self._get_send_address(exch_name, queue_name),
- msg_count = msg_count, topic_key = topic_key, msg_durable_flag = msg_durable_flag, enq_txn_size = enq_txn_size)
- if not queue_route_type_flag:
- self._receive_msgs("local_receive_session", local_broker, addr = queue_name, msg_count = msg_count, deq_txn_size = deq_txn_size)
- self._receive_msgs("remote_receive_session", remote_broker, addr = queue_name, msg_count = msg_count, deq_txn_size = deq_txn_size, timeout = 5)
-
- # Clean up
- self._delete_queue_binding(qmf_broker=local_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args)
- self._delete_queue_binding(qmf_broker=remote_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args)
-
-class A_ShortTests(QmfTestBase010):
-
- def test_route_defaultExch(self):
- self._do_test(self._get_name())
-
- def test_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True)
-
-
-class A_LongTests(QmfTestBase010):
-
- def test_route_amqDirectExch(self):
- self._do_test(self._get_name(), exch_name="amq.direct")
-
- def test_queueRoute_amqDirectExch(self):
- self._do_test(self._get_name(), exch_name="amq.direct", queue_route_type_flag=True)
-
-
- def test_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange")
-
- def test_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True)
-
-
- def test_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout")
-
- def test_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True)
-
-
- def test_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#")
-
- def test_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True)
-
-
-class B_ShortTransactionTests(QmfTestBase010):
-
- def test_txEnq01_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1)
-
- def test_txEnq01_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
-class B_LongTransactionTests(QmfTestBase010):
-
- def test_txEnq10_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
-
-
-
- def test_txEnq01_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1)
-
- def test_txEnq01_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
- def test_txEnq01_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1)
-
- def test_txEnq01_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
- def test_txEnq01_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1)
-
- def test_txEnq01_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
-class C_ShortClusterTests(QmfTestBase010):
-
- def test_locCluster_route_defaultExch(self):
- self._do_test(self._get_name(), local_cluster_flag=True)
-
- def test_locCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class C_LongClusterTests(QmfTestBase010):
-
- def test_locCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", local_cluster_flag=True)
-
- def test_locCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_locCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", local_cluster_flag=True)
-
- def test_locCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_locCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", local_cluster_flag=True)
-
- def test_locCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class D_ShortClusterTransactionTests(QmfTestBase010):
-
- def test_txEnq01_locCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class D_LongClusterTransactionTests(QmfTestBase010):
-
- def test_txEnq10_locCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_txEnq01_locCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_txEnq01_locCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_txEnq01_locCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class E_ShortPersistenceTests(QmfTestBase010):
-
- def test_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True)
-
- def test_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True)
-
- def test_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True)
-
- def test_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True)
-
-
-class E_LongPersistenceTests(QmfTestBase010):
-
-
- def test_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True)
-
- def test_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True)
-
- def test_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True)
-
- def test_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True)
-
-
- def test_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True)
-
- def test_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True)
-
- def test_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True)
-
- def test_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True)
-
-
- def test_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True)
-
- def test_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True)
-
- def test_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True)
-
- def test_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True)
-
-
-class F_ShortPersistenceTransactionTests(QmfTestBase010):
-
- def test_txEnq01_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
-class F_LongPersistenceTransactionTests(QmfTestBase010):
-
- def test_txEnq10_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
-
-
-
- def test_txEnq01_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
- def test_txEnq01_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
- def test_txEnq01_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
-class G_ShortPersistenceClusterTests(QmfTestBase010):
-
- def test_locCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class G_LongPersistenceClusterTests(QmfTestBase010):
-
-
-
- def test_locCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_locCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_locCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class H_ShortPersistenceClusterTransactionTests(QmfTestBase010):
-
- def test_txEnq01_locCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class H_LongPersistenceClusterTransactionTests(QmfTestBase010):
-
- def test_txEnq10_locCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-
-
- def test_txEnq01_locCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_txEnq01_locCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_txEnq01_locCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
diff --git a/cpp/src/tests/ipv6_test b/cpp/src/tests/ipv6_test
deleted file mode 100755
index d75d50fd0a..0000000000
--- a/cpp/src/tests/ipv6_test
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Run a simple test over IPv6
-source ./test_env.sh
-
-CONFIG=$(dirname $0)/config.null
-TEST_HOSTNAME=::1
-COUNT=10
-
-trap cleanup EXIT
-
-error() { echo $*; exit 1; }
-
-# Don't need --no-module-dir or --no-data-dir as they are set as env vars in test_env.sh
-COMMON_OPTS="--daemon --auth no --config $CONFIG"
-
-# Record all broker ports started
-unset PORTS
-declare -a PORTS
-
-# Start new brokers:
-# $1 must be integer
-# $2 = extra opts
-# Append used ports to PORTS variable
-start_brokers() {
- local -a ports
- for (( i=0; $i<$1; i++)) do
- ports[$i]=$($QPIDD_EXEC --port 0 $COMMON_OPTS $2)
- done
- PORTS=( ${PORTS[@]} ${ports[@]} )
-}
-
-stop_brokers() {
- for port in "${PORTS[@]}";
- do
- $QPIDD_EXEC -qp $port
- done
- PORTS=()
-}
-
-cleanup() {
- stop_brokers
-}
-
-start_brokers 1
-PORT=${PORTS[0]}
-echo "Started IPv6 smoke perftest on broker port $PORT"
-
-## Test connection via connection settings
-./qpid-perftest --count ${COUNT} --port ${PORT} -b $TEST_HOSTNAME --summary
-
-## Test connection with a URL
-URL="amqp:[$TEST_HOSTNAME]:$PORT"
-
-./qpid-send -b $URL --content-string=hello -a "foo;{create:always}"
-MSG=`./qpid-receive -b $URL -a "foo;{create:always}" --messages 1`
-test "$MSG" = "hello" || { echo "receive failed '$MSG' != 'hello'"; exit 1; }
-
-stop_brokers
-
-# Federation smoke test follows
-
-# Start 2 brokers
-
-# In a distribution, the python tools will be absent.
-if [ ! -f $QPID_CONFIG_EXEC ] || [ ! -f $QPID_ROUTE_EXEC ] ; then
- echo "python tools absent - skipping federation test."
-else
-
- start_brokers 2
- echo "Started Federated brokers on ports ${PORTS[*]}"
- # Make broker urls
- BROKER0="[::1]:${PORTS[0]}"
- BROKER1="[::1]:${PORTS[1]}"
- TEST_QUEUE=ipv6-fed-test
-
- $QPID_CONFIG_EXEC -a $BROKER0 add queue $TEST_QUEUE
- $QPID_CONFIG_EXEC -a $BROKER1 add queue $TEST_QUEUE
- $QPID_ROUTE_EXEC dynamic add $BROKER1 $BROKER0 amq.direct
- $QPID_CONFIG_EXEC -a $BROKER1 bind amq.direct $TEST_QUEUE $TEST_QUEUE
- $QPID_ROUTE_EXEC route map $BROKER1
-
- ./datagen --count 100 | tee rdata-in |
- ./qpid-send -b amqp:$BROKER0 -a amq.direct/$TEST_QUEUE --content-stdin
- ./qpid-receive -b amqp:$BROKER1 -a $TEST_QUEUE --print-content yes -m 0 > rdata-out
-
- cmp rdata-in rdata-out || { echo "Federated data over IPv6 does not compare"; exit 1; }
-
- stop_brokers
- rm rdata-in rdata-out
-fi
-
-# Cluster smoke test follows
-test -z $CLUSTER_LIB && exit 0 # Exit if cluster not supported.
-
-## Test failover in a cluster using IPv6 only
-. $srcdir/ais_check # Will exit if clustering not enabled.
-
-pick_port() {
- # We need a fixed port to set --cluster-url. Use qpidd to pick a free port.
- # Note this method is racy
- PICK=$($QPIDD_EXEC -dp0)
- $QPIDD_EXEC -qp $PICK
- echo $PICK
-}
-
-ssl_cluster_broker() { # $1 = port
- $QPIDD_EXEC $COMMON_OPTS --load-module $CLUSTER_LIB --cluster-name ipv6_test.$HOSTNAME.$$ --cluster-url amqp:[$TEST_HOSTNAME]:$1 --port $1
- # Wait for broker to be ready
- ./qpid-ping -b $TEST_HOSTNAME -qp $1 || { echo "Cannot connect to broker on $1"; exit 1; }
- echo "Running IPv6 cluster broker on port $1"
-}
-
-PORT1=`pick_port`; ssl_cluster_broker $PORT1
-PORT2=`pick_port`; ssl_cluster_broker $PORT2
-
-# Pipe receive output to uniq to remove duplicates
-./qpid-receive --connection-options "{reconnect:true, reconnect-timeout:5}" --failover-updates -b amqp:[$TEST_HOSTNAME]:$PORT1 -a "foo;{create:always}" -f | uniq > ssl_test_receive.tmp &
-
-./qpid-send -b amqp:[$TEST_HOSTNAME]:$PORT2 --content-string=one -a "foo;{create:always}"
-
-$QPIDD_EXEC -qp $PORT1 # Kill broker 1 receiver should fail-over.
-./qpid-send -b amqp:[$TEST_HOSTNAME]:$PORT2 --content-string=two -a "foo;{create:always}" --send-eos 1
-wait # Wait for qpid-receive
-{ echo one; echo two; } > ssl_test_receive.cmp
-diff ssl_test_receive.tmp ssl_test_receive.cmp || { echo "Failover failed"; exit 1; }
-
-$QPIDD_EXEC -qp $PORT2
-
-rm -f ssl_test_receive.*
-
diff --git a/cpp/src/tests/msg_group_test.cpp b/cpp/src/tests/msg_group_test.cpp
deleted file mode 100644
index 6b9d09b89a..0000000000
--- a/cpp/src/tests/msg_group_test.cpp
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include <qpid/messaging/Address.h>
-#include <qpid/messaging/Connection.h>
-#include <qpid/messaging/Receiver.h>
-#include <qpid/messaging/Sender.h>
-#include <qpid/messaging/Session.h>
-#include <qpid/messaging/Message.h>
-#include <qpid/messaging/FailoverUpdates.h>
-#include <qpid/Options.h>
-#include <qpid/log/Logger.h>
-#include <qpid/log/Options.h>
-#include "qpid/log/Statement.h"
-#include "qpid/sys/Time.h"
-#include "qpid/sys/Runnable.h"
-#include "qpid/sys/Thread.h"
-#include "qpid/sys/SystemInfo.h"
-
-#include <iostream>
-#include <memory>
-#include <stdlib.h>
-
-using namespace qpid::messaging;
-using namespace qpid::types;
-using namespace std;
-
-namespace qpid {
-namespace tests {
-
-struct Options : public qpid::Options
-{
- bool help;
- std::string url;
- std::string address;
- std::string connectionOptions;
- uint messages;
- uint capacity;
- uint ackFrequency;
- bool failoverUpdates;
- qpid::log::Options log;
- uint senders;
- uint receivers;
- uint groupSize;
- bool printReport;
- std::string groupKey;
- bool durable;
- bool allowDuplicates;
- bool randomizeSize;
- bool stickyConsumer;
- uint timeout;
- uint interleave;
- std::string prefix;
- uint sendRate;
-
- Options(const std::string& argv0=std::string())
- : qpid::Options("Options"),
- help(false),
- url("amqp:tcp:127.0.0.1"),
- messages(10000),
- capacity(1000),
- ackFrequency(100),
- failoverUpdates(false),
- log(argv0),
- senders(2),
- receivers(2),
- groupSize(10),
- printReport(false),
- groupKey("qpid.no_group"),
- durable(false),
- allowDuplicates(false),
- randomizeSize(false),
- stickyConsumer(false),
- timeout(10),
- interleave(1),
- sendRate(0)
- {
- addOptions()
- ("ack-frequency", qpid::optValue(ackFrequency, "N"), "Ack frequency (0 implies none of the messages will get accepted)")
- ("address,a", qpid::optValue(address, "ADDRESS"), "address to send and receive from")
- ("allow-duplicates", qpid::optValue(allowDuplicates), "Ignore the delivery of duplicated messages")
- ("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to")
- ("capacity", qpid::optValue(capacity, "N"), "Pre-fetch window (0 implies no pre-fetch)")
- ("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection")
- ("durable", qpid::optValue(durable, "yes|no"), "Mark messages as durable.")
- ("failover-updates", qpid::optValue(failoverUpdates), "Listen for membership updates distributed via amq.failover")
- ("group-key", qpid::optValue(groupKey, "KEY"), "Key of the message header containing the group identifier.")
- ("group-prefix", qpid::optValue(prefix, "STRING"), "Add 'prefix' to the start of all generated group identifiers.")
- ("group-size", qpid::optValue(groupSize, "N"), "Number of messages per a group.")
- ("interleave", qpid::optValue(interleave, "N"), "Simultaineously interleave messages from N different groups.")
- ("messages,m", qpid::optValue(messages, "N"), "Number of messages to send per each sender.")
- ("receivers,r", qpid::optValue(receivers, "N"), "Number of message consumers.")
- ("randomize-group-size", qpid::optValue(randomizeSize), "Randomize the number of messages per group to [1...group-size].")
- ("send-rate", qpid::optValue(sendRate,"N"), "Send at rate of N messages/second. 0 means send as fast as possible.")
- ("senders,s", qpid::optValue(senders, "N"), "Number of message producers.")
- ("sticky-consumers", qpid::optValue(stickyConsumer), "If set, verify that all messages in a group are consumed by the same client [TBD].")
- ("timeout", qpid::optValue(timeout, "N"), "Fail with a stall error should all consumers remain idle for timeout seconds.")
- ("print-report", qpid::optValue(printReport), "Dump message group statistics to stdout.")
- ("help", qpid::optValue(help), "print this usage statement");
- add(log);
- //("check-redelivered", qpid::optValue(checkRedelivered), "Fails with exception if a duplicate is not marked as redelivered (only relevant when ignore-duplicates is selected)")
- //("tx", qpid::optValue(tx, "N"), "batch size for transactions (0 implies transaction are not used)")
- //("rollback-frequency", qpid::optValue(rollbackFrequency, "N"), "rollback frequency (0 implies no transaction will be rolledback)")
- }
-
- bool parse(int argc, char** argv)
- {
- try {
- qpid::Options::parse(argc, argv);
- if (address.empty()) throw qpid::Exception("Address must be specified!");
- qpid::log::Logger::instance().configure(log);
- if (help) {
- std::ostringstream msg;
- std::cout << msg << *this << std::endl << std::endl
- << "Verifies the behavior of grouped messages." << std::endl;
- return false;
- } else {
- return true;
- }
- } catch (const std::exception& e) {
- std::cerr << *this << std::endl << std::endl << e.what() << std::endl;
- return false;
- }
- }
-};
-
-const string EOS("eos");
-const string SN("sn");
-
-
-// class that monitors group state across all publishers and consumers. tracks the next
-// expected sequence for each group, and total messages consumed.
-class GroupChecker
-{
- qpid::sys::Mutex lock;
-
- const uint totalMsgs;
- uint totalMsgsConsumed;
- uint totalMsgsPublished;
- bool allowDuplicates;
- uint duplicateMsgs;
-
- typedef std::map<std::string, uint> SequenceMap;
- SequenceMap sequenceMap;
-
- // Statistics - for each group, store the names of all clients that consumed messages
- // from that group, and the number of messages consumed per client.
- typedef std::map<std::string, uint> ClientCounter;
- typedef std::map<std::string, ClientCounter> GroupStatistics;
- GroupStatistics statistics;
-
-public:
-
- GroupChecker( uint t, bool d ) :
- totalMsgs(t), totalMsgsConsumed(0), totalMsgsPublished(0), allowDuplicates(d),
- duplicateMsgs(0) {}
-
- bool checkSequence( const std::string& groupId,
- uint sequence, const std::string& client )
- {
- qpid::sys::Mutex::ScopedLock l(lock);
-
- QPID_LOG(debug, "Client " << client << " has received " << groupId << ":" << sequence);
-
- GroupStatistics::iterator gs = statistics.find(groupId);
- if (gs == statistics.end()) {
- statistics[groupId][client] = 1;
- } else {
- gs->second[client]++;
- }
- // now verify
- SequenceMap::iterator s = sequenceMap.find(groupId);
- if (s == sequenceMap.end()) {
- QPID_LOG(debug, "Client " << client << " thinks this is the first message from group " << groupId << ":" << sequence);
- // if duplication allowed, it is possible that the last msg(s) of an old sequence are redelivered on reconnect.
- // in this case, set the sequence from the first msg.
- sequenceMap[groupId] = (allowDuplicates) ? sequence : 0;
- s = sequenceMap.find(groupId);
- } else if (sequence < s->second) {
- duplicateMsgs++;
- QPID_LOG(debug, "Client " << client << " thinks this message is a duplicate! " << groupId << ":" << sequence);
- return allowDuplicates;
- }
- totalMsgsConsumed++;
- return sequence == s->second++;
- }
-
- void sendingSequence( const std::string& groupId,
- uint sequence, bool eos,
- const std::string& client )
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- ++totalMsgsPublished;
-
- QPID_LOG(debug, "Client " << client << " sending " << groupId << ":" << sequence <<
- ((eos) ? " (last)" : ""));
- }
-
- bool eraseGroup( const std::string& groupId, const std::string& name )
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- QPID_LOG(debug, "Deleting group " << groupId << " (by client " << name << ")");
- return sequenceMap.erase( groupId ) == 1;
- }
-
- uint getNextExpectedSequence( const std::string& groupId )
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- return sequenceMap[groupId];
- }
-
- bool allMsgsConsumed() // true when done processing msgs
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- return (totalMsgsPublished >= totalMsgs) &&
- (totalMsgsConsumed >= totalMsgsPublished) &&
- sequenceMap.size() == 0;
- }
-
- uint getConsumedTotal()
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- return totalMsgsConsumed;
- }
-
- uint getPublishedTotal()
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- return totalMsgsPublished;
- }
-
- ostream& print(ostream& out)
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- out << "Total Published: " << totalMsgsPublished << ", Total Consumed: " << totalMsgsConsumed <<
- ", Duplicates detected: " << duplicateMsgs << std::endl;
- out << "Total Groups: " << statistics.size() << std::endl;
- unsigned long consumers = 0;
- for (GroupStatistics::iterator gs = statistics.begin(); gs != statistics.end(); ++gs) {
- out << " GroupId: " << gs->first;
- consumers += gs->second.size(); // # of consumers that processed this group
- if (gs->second.size() == 1)
- out << " completely consumed by a single client." << std::endl;
- else
- out << " consumed by " << gs->second.size() << " different clients." << std::endl;
-
- for (ClientCounter::iterator cc = gs->second.begin(); cc != gs->second.end(); ++cc) {
- out << " Client: " << cc->first << " consumed " << cc->second << " messages from the group." << std::endl;
- }
- }
- out << "Average # of consumers per group: " << ((statistics.size() != 0) ? (double(consumers)/statistics.size()) : 0) << std::endl;
- return out;
- }
-};
-
-
-namespace {
- // rand() is not thread safe. Create a singleton obj to hold a lock while calling
- // rand() so it can be called safely by multiple concurrent clients.
- class Randomizer {
- qpid::sys::Mutex lock;
- public:
- uint operator()(uint max) {
- qpid::sys::Mutex::ScopedLock l(lock);
- return (rand() % max) + 1;
- }
- };
-
- static Randomizer randomizer;
-}
-
-
-// tag each generated message with a group identifer
-//
-class GroupGenerator {
-
- const std::string groupPrefix;
- const uint groupSize;
- const bool randomizeSize;
- const uint interleave;
-
- uint groupSuffix;
- uint total;
-
- struct GroupState {
- std::string id;
- const uint size;
- uint count;
- GroupState( const std::string& i, const uint s )
- : id(i), size(s), count(0) {}
- };
- typedef std::list<GroupState> GroupList;
- GroupList groups;
- GroupList::iterator current;
-
- // add a new group identifier to the list
- void newGroup() {
- std::ostringstream groupId(groupPrefix, ios_base::out|ios_base::ate);
- groupId << std::string(":") << groupSuffix++;
- uint size = (randomizeSize) ? randomizer(groupSize) : groupSize;
- QPID_LOG(trace, "New group: GROUPID=[" << groupId.str() << "] size=" << size << " this=" << this);
- GroupState group( groupId.str(), size );
- groups.push_back( group );
- }
-
-public:
- GroupGenerator( const std::string& prefix,
- const uint t,
- const uint size,
- const bool randomize,
- const uint i)
- : groupPrefix(prefix), groupSize(size),
- randomizeSize(randomize), interleave(i), groupSuffix(0), total(t)
- {
- QPID_LOG(trace, "New group generator: PREFIX=[" << prefix << "] total=" << total << " size=" << size << " rand=" << randomize << " interleave=" << interleave << " this=" << this);
- for (uint i = 0; i < 1 || i < interleave; ++i) {
- newGroup();
- }
- current = groups.begin();
- }
-
- bool genGroup(std::string& groupId, uint& seq, bool& eos)
- {
- if (!total) return false;
- --total;
- if (current == groups.end())
- current = groups.begin();
- groupId = current->id;
- seq = current->count++;
- if (current->count == current->size) {
- QPID_LOG(trace, "Last msg for " << current->id << ", " << current->count << " this=" << this);
- eos = true;
- if (total >= interleave) { // need a new group to replace this one
- newGroup();
- groups.erase(current++);
- } else ++current;
- } else {
- ++current;
- eos = total < interleave; // mark eos on the last message of each group
- }
- QPID_LOG(trace, "SENDING GROUPID=[" << groupId << "] seq=" << seq << " eos=" << eos << " this=" << this);
- return true;
- }
-};
-
-
-
-class Client : public qpid::sys::Runnable
-{
-public:
- typedef boost::shared_ptr<Client> shared_ptr;
- enum State {ACTIVE, DONE, FAILURE};
- Client( const std::string& n, const Options& o ) : name(n), opts(o), state(ACTIVE), stopped(false) {}
- virtual ~Client() {}
- State getState() { return state; }
- void testFailed( const std::string& reason ) { state = FAILURE; error << "Client '" << name << "' failed: " << reason; }
- void clientDone() { if (state == ACTIVE) state = DONE; }
- qpid::sys::Thread& getThread() { return thread; }
- const std::string getErrorMsg() { return error.str(); }
- void stop() {stopped = true;}
- const std::string& getName() { return name; }
-
-protected:
- const std::string name;
- const Options& opts;
- qpid::sys::Thread thread;
- ostringstream error;
- State state;
- bool stopped;
-};
-
-
-class Consumer : public Client
-{
- GroupChecker& checker;
-
-public:
- Consumer(const std::string& n, const Options& o, GroupChecker& c ) : Client(n, o), checker(c) {};
- virtual ~Consumer() {};
-
- void run()
- {
- Connection connection;
- try {
- connection = Connection(opts.url, opts.connectionOptions);
- connection.open();
- std::auto_ptr<FailoverUpdates> updates(opts.failoverUpdates ? new FailoverUpdates(connection) : 0);
- Session session = connection.createSession();
- Receiver receiver = session.createReceiver(opts.address);
- receiver.setCapacity(opts.capacity);
- Message msg;
- uint count = 0;
-
- while (!stopped) {
- if (receiver.fetch(msg, Duration::SECOND)) { // msg retrieved
- qpid::types::Variant::Map& properties = msg.getProperties();
- std::string groupId = properties[opts.groupKey];
- uint groupSeq = properties[SN];
- bool eof = properties[EOS];
-
- QPID_LOG(trace, "RECVING GROUPID=[" << groupId << "] seq=" << groupSeq << " eos=" << eof << " name=" << name);
-
- qpid::sys::usleep(10);
-
- if (!checker.checkSequence( groupId, groupSeq, name )) {
- ostringstream msg;
- msg << "Check sequence failed. Group=" << groupId << " rcvd seq=" << groupSeq << " expected=" << checker.getNextExpectedSequence( groupId );
- testFailed( msg.str() );
- break;
- } else if (eof) {
- if (!checker.eraseGroup( groupId, name )) {
- ostringstream msg;
- msg << "Erase group failed. Group=" << groupId << " rcvd seq=" << groupSeq;
- testFailed( msg.str() );
- break;
- }
- }
-
- ++count;
- if (opts.ackFrequency && (count % opts.ackFrequency == 0)) {
- session.acknowledge();
- }
- // Clear out message properties & content for next iteration.
- msg = Message(); // TODO aconway 2010-12-01: should be done by fetch
- } else if (checker.allMsgsConsumed()) // timed out, nothing else to do?
- break;
- }
- session.acknowledge();
- session.close();
- connection.close();
- } catch(const std::exception& error) {
- ostringstream msg;
- msg << "consumer error: " << error.what();
- testFailed( msg.str() );
- connection.close();
- }
- clientDone();
- QPID_LOG(trace, "Consuming client " << name << " completed.");
- }
-};
-
-
-
-class Producer : public Client
-{
- GroupChecker& checker;
- GroupGenerator generator;
-
-public:
- Producer(const std::string& n, const Options& o, GroupChecker& c)
- : Client(n, o), checker(c),
- generator( n, o.messages, o.groupSize, o.randomizeSize, o.interleave )
- {};
- virtual ~Producer() {};
-
- void run()
- {
- Connection connection;
- try {
- connection = Connection(opts.url, opts.connectionOptions);
- connection.open();
- std::auto_ptr<FailoverUpdates> updates(opts.failoverUpdates ? new FailoverUpdates(connection) : 0);
- Session session = connection.createSession();
- Sender sender = session.createSender(opts.address);
- if (opts.capacity) sender.setCapacity(opts.capacity);
- Message msg;
- msg.setDurable(opts.durable);
- std::string groupId;
- uint seq;
- bool eos;
- uint sent = 0;
-
- qpid::sys::AbsTime start = qpid::sys::now();
- int64_t interval = 0;
- if (opts.sendRate) interval = qpid::sys::TIME_SEC/opts.sendRate;
-
- while (!stopped && generator.genGroup(groupId, seq, eos)) {
- msg.getProperties()[opts.groupKey] = groupId;
- msg.getProperties()[SN] = seq;
- msg.getProperties()[EOS] = eos;
- checker.sendingSequence( groupId, seq, eos, name );
-
- sender.send(msg);
- ++sent;
-
- if (opts.sendRate) {
- qpid::sys::AbsTime waitTill(start, sent*interval);
- int64_t delay = qpid::sys::Duration(qpid::sys::now(), waitTill);
- if (delay > 0) qpid::sys::usleep(delay/qpid::sys::TIME_USEC);
- }
- }
- session.sync();
- session.close();
- connection.close();
- } catch(const std::exception& error) {
- ostringstream msg;
- msg << "producer '" << name << "' error: " << error.what();
- testFailed(msg.str());
- connection.close();
- }
- clientDone();
- QPID_LOG(trace, "Producing client " << name << " completed.");
- }
-};
-
-
-}} // namespace qpid::tests
-
-using namespace qpid::tests;
-
-int main(int argc, char ** argv)
-{
- int status = 0;
- try {
- Options opts;
- if (opts.parse(argc, argv)) {
-
- GroupChecker state( opts.senders * opts.messages,
- opts.allowDuplicates);
- std::vector<Client::shared_ptr> clients;
-
- if (opts.randomizeSize) srand((unsigned int)qpid::sys::SystemInfo::getProcessId());
-
- // fire off the producers && consumers
- for (size_t j = 0; j < opts.senders; ++j) {
- ostringstream name;
- name << opts.prefix << "P_" << j;
- clients.push_back(Client::shared_ptr(new Producer( name.str(), opts, state )));
- clients.back()->getThread() = qpid::sys::Thread(*clients.back());
- }
- for (size_t j = 0; j < opts.receivers; ++j) {
- ostringstream name;
- name << opts.prefix << "C_" << j;
- clients.push_back(Client::shared_ptr(new Consumer( name.str(), opts, state )));
- clients.back()->getThread() = qpid::sys::Thread(*clients.back());
- }
-
- // wait for all pubs/subs to finish.... or for consumers to fail or stall.
- uint stalledTime = 0;
- bool done;
- bool clientFailed = false;
- do {
- uint lastCount = state.getConsumedTotal();
- qpid::sys::usleep( 1000000 );
-
- // check each client for status
- done = true;
- for (std::vector<Client::shared_ptr>::iterator i = clients.begin();
- i != clients.end(); ++i) {
- QPID_LOG(debug, "Client " << (*i)->getName() << " state=" << (*i)->getState());
- if ((*i)->getState() == Client::FAILURE) {
- QPID_LOG(error, argv[0] << ": test failed with client error: " << (*i)->getErrorMsg());
- clientFailed = true;
- done = true;
- break; // exit test.
- } else if ((*i)->getState() != Client::DONE) {
- done = false;
- }
- }
-
- if (!done) {
- // check that consumers are still receiving messages
- if (lastCount == state.getConsumedTotal())
- stalledTime++;
- else {
- lastCount = state.getConsumedTotal();
- stalledTime = 0;
- }
- }
-
- QPID_LOG(debug, "Consumed to date = " << state.getConsumedTotal() <<
- " Published to date = " << state.getPublishedTotal() <<
- " total=" << opts.senders * opts.messages );
-
- } while (!done && stalledTime < opts.timeout);
-
- if (clientFailed) {
- status = 1;
- } else if (stalledTime >= opts.timeout) {
- QPID_LOG(error, argv[0] << ": test failed due to stalled consumer." );
- status = 2;
- }
-
- // Wait for started threads.
- for (std::vector<Client::shared_ptr>::iterator i = clients.begin();
- i != clients.end(); ++i) {
- (*i)->stop();
- (*i)->getThread().join();
- }
-
- if (opts.printReport && !status) state.print(std::cout);
- } else status = 4;
- } catch(const std::exception& error) {
- QPID_LOG(error, argv[0] << ": " << error.what());
- status = 3;
- }
- QPID_LOG(trace, "TEST DONE [" << status << "]");
-
- return status;
-}
diff --git a/cpp/src/tests/python_tests b/cpp/src/tests/python_tests
index 0216b5ca7b..e367004a71 100755
--- a/cpp/src/tests/python_tests
+++ b/cpp/src/tests/python_tests
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
diff --git a/cpp/src/tests/qpid-cluster-benchmark b/cpp/src/tests/qpid-cluster-benchmark
index ff787a46dd..4408e63866 100755
--- a/cpp/src/tests/qpid-cluster-benchmark
+++ b/cpp/src/tests/qpid-cluster-benchmark
@@ -7,9 +7,9 @@
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -19,40 +19,21 @@
#
# Benchmark script for comparing cluster performance.
+#PORT=":5555"
+BROKER=`echo $HOSTS | awk '{print $1}'` # Single broker
+BROKERS=`echo $HOSTS | sed "s/\>/$PORT/g;s/ /,/g"` # Broker URL list
+COUNT=100000
+RATE=20000 # Rate to throttle senders for latency results
+run_test() { echo $*; "$@"; echo; echo; echo; }
-# Default values
-PORT="5672"
-COUNT=10000
-FLOW=100 # Flow control limit on queue depth for latency.
-REPEAT=10
-QUEUES=4
-CLIENTS=3
-
-while getopts "p:c:f:r:t:b:q:c" opt; do
- case $opt in
- p) PORT=$OPTARG;;
- c) COUNT=$OPTARG;;
- f) FLOW=$OPTARG;;
- r) REPEAT=$OPTARG;;
- s) SCALE=$OPTARG;;
- b) BROKERS=$OPTARG;;
- q) QUEUES=$OPTARG;;
- c) CLIENTS=$OPTARG;;
- *) echo "Unknown option"; exit 1;;
- esac
-done
-
-BROKERS=${BROKERS:-$(echo $HOSTS | sed "s/\>/:$PORT/g;s/ /,/g")} # Broker URL list
-BROKER=`echo $BROKERS | awk -F, '{print $1}'` # First broker
+# Thruput, unshared queue
+run_test qpid-cpp-benchmark --repeat 10 -b $BROKER --no-timestamp -m $COUNT
-run_test() { echo $*; shift; "$@"; echo; echo; echo; }
+# Latency
+run_test qpid-cpp-benchmark --repeat 10 -b $BROKER --connection-options '{tcp-nodelay:true}' -m `expr $COUNT / 2` --send-rate $RATE
# Multiple pubs/subs connect via multiple brokers (active-active)
-run_test "multi-host-thruput" qpid-cpp-benchmark --repeat $REPEAT -b $BROKERS --no-timestamp --summarize -q$QUEUES -s$CLIENTS -r$CLIENTS -m $COUNT
+run_test qpid-cpp-benchmark --repeat 10 -b $BROKERS --no-timestamp --summarize -s10 -r10 -m `expr $COUNT / 10`
# Multiple pubs/subs connect via single broker (active-passive)
-run_test "single-host-thruput" qpid-cpp-benchmark --repeat $REPEAT -b $BROKER --no-timestamp --summarize -q$QUEUES -s$CLIENTS -r$CLIENTS -m $COUNT
-
-# Latency
-run_test "latency" qpid-cpp-benchmark --repeat $REPEAT -b $BROKER --connection-options '{tcp-nodelay:true}' -m $COUNT --flow-control $FLOW
-
+run_test qpid-cpp-benchmark --repeat 10 -b $BROKER --no-timestamp --summarize -s10 -r10 -m `expr $COUNT / 10`
diff --git a/cpp/src/tests/qpid-cpp-benchmark b/cpp/src/tests/qpid-cpp-benchmark
index 300d34774f..1f77226b4d 100755
--- a/cpp/src/tests/qpid-cpp-benchmark
+++ b/cpp/src/tests/qpid-cpp-benchmark
@@ -77,20 +77,6 @@ def ssh_command(host, command):
"""Convert command into an ssh command on host with quoting"""
return ["ssh", host] + [posix_quote(arg) for arg in command]
-class Clients:
- def __init__(self): self.clients=[]
-
- def add(self, client):
- self.clients.append(client)
- return client
-
- def kill(self):
- for c in self.clients:
- try: c.kill()
- except: pass
-
-clients = Clients()
-
def start_receive(queue, index, opts, ready_queue, broker, host):
address_opts=["create:receiver"] + opts.receive_option
if opts.durable: address_opts += ["node:{durable:true}"]
@@ -115,7 +101,7 @@ def start_receive(queue, index, opts, ready_queue, broker, host):
if opts.connection_options:
command += ["--connection-options",opts.connection_options]
if host: command = ssh_command(host, command)
- return clients.add(Popen(command, stdout=PIPE))
+ return Popen(command, stdout=PIPE)
def start_send(queue, opts, broker, host):
address="%s;{%s}"%(queue,",".join(opts.send_option))
@@ -136,7 +122,7 @@ def start_send(queue, opts, broker, host):
if opts.connection_options:
command += ["--connection-options",opts.connection_options]
if host: command = ssh_command(host, command)
- return clients.add(Popen(command, stdout=PIPE))
+ return Popen(command, stdout=PIPE)
def first_line(p):
out,err=p.communicate()
@@ -147,11 +133,7 @@ def delete_queues(queues, broker):
c = qpid.messaging.Connection(broker)
c.open()
for q in queues:
- try:
- s = c.session()
- snd = s.sender("%s;{delete:always}"%(q))
- snd.close()
- s.sync()
+ try: s = c.session().sender("%s;{delete:always}"%(q))
except qpid.messaging.exceptions.NotFound: pass # Ignore "no such queue"
c.close()
@@ -163,6 +145,7 @@ def print_header(timestamp):
def parse(parser, lines): # Parse sender/receiver output
for l in lines:
fn_val = zip(parser, l)
+
return [map(lambda p: p[0](p[1]), zip(parser,line.split())) for line in lines]
def parse_senders(senders):
@@ -173,12 +156,11 @@ def parse_receivers(receivers):
def print_data(send_stats, recv_stats):
for send,recv in map(None, send_stats, recv_stats):
- line=""
- if send: line += "%d"%send[0]
+ if send: print send[0],
if recv:
- line += "\t\t%d"%recv[0]
- if len(recv) == 4: line += "\t%.2f\t%.2f\t%.2f"%tuple(recv[1:])
- print line
+ print "\t\t%d"%recv[0],
+ if len(recv) == 4: print "\t%.2f\t%.2f\t%.2f"%tuple(recv[1:]),
+ print
def print_summary(send_stats, recv_stats):
def avg(s): sum(s) / len(s)
@@ -202,11 +184,11 @@ class ReadyReceiver:
self.receiver = self.connection.session().receiver(
"%s;{create:receiver,delete:receiver,node:{durable:false}}"%(queue))
self.receiver.session.sync()
- self.timeout=10
+ self.timeout=2
def wait(self, receivers):
try:
- for i in receivers: self.receiver.fetch(self.timeout)
+ for i in xrange(len(receivers)): self.receiver.fetch(self.timeout)
self.connection.close()
except qpid.messaging.Empty:
for r in receivers:
@@ -215,8 +197,7 @@ class ReadyReceiver:
raise Exception("Receiver error: %s"%(out))
raise Exception("Timed out waiting for receivers to be ready")
-def flatten(l):
- return sum(map(lambda s: re.split(re.compile("\s*,\s*|\s+"), s), l), [])
+def flatten(l): return sum(map(lambda s: s.split(","), l),[])
class RoundRobin:
def __init__(self,items):
@@ -240,22 +221,20 @@ def main():
receive_out = ""
ready_queue="%s-ready"%(opts.queue_name)
queues = ["%s-%s"%(opts.queue_name, i) for i in xrange(opts.queues)]
- try:
- for i in xrange(opts.repeat):
- delete_queues(queues, opts.broker[0])
- ready_receiver = ReadyReceiver(ready_queue, opts.broker[0])
- receivers = [start_receive(q, j, opts, ready_queue, brokers.next(), client_hosts.next())
- for q in queues for j in xrange(opts.receivers)]
- ready_receiver.wait(filter(None, receivers)) # Wait for receivers to be ready.
- senders = [start_send(q, opts,brokers.next(), client_hosts.next())
- for q in queues for j in xrange(opts.senders)]
- if opts.report_header and i == 0: print_header(opts.timestamp)
- send_stats=parse_senders(senders)
- recv_stats=parse_receivers(receivers)
- if opts.summarize: print_summary(send_stats, recv_stats)
- else: print_data(send_stats, recv_stats)
- delete_queues(queues, opts.broker[0])
- finally: clients.kill() # No strays
+ for i in xrange(opts.repeat):
+ delete_queues(queues, opts.broker[0])
+ ready_receiver = ReadyReceiver(ready_queue, opts.broker[0])
+ receivers = [start_receive(q, j, opts, ready_queue, brokers.next(), client_hosts.next())
+ for q in queues for j in xrange(opts.receivers)]
+ ready_receiver.wait(filter(None, receivers)) # Wait for receivers to be ready.
+ senders = [start_send(q, opts,brokers.next(), client_hosts.next())
+ for q in queues for j in xrange(opts.senders)]
+ if opts.report_header and i == 0: print_header(opts.timestamp)
+ send_stats=parse_senders(senders)
+ recv_stats=parse_receivers(receivers)
+ if opts.summarize: print_summary(send_stats, recv_stats)
+ else: print_data(send_stats, recv_stats)
+ delete_queues(queues, opts.broker[0])
if __name__ == "__main__": main()
diff --git a/cpp/src/tests/qpid-ctrl b/cpp/src/tests/qpid-ctrl
index 4246c57898..7b46c190fb 100755
--- a/cpp/src/tests/qpid-ctrl
+++ b/cpp/src/tests/qpid-ctrl
@@ -92,10 +92,7 @@ try:
arguments = {}
for a in args:
name, val = nameval(a)
- if val[0] == '{' or val[0] == '[':
- arguments[name] = eval(val)
- else:
- arguments[name] = val
+ arguments[name] = val
content = {
"_object_id": {"_object_name": object_name},
"_method_name": method_name,
diff --git a/cpp/src/tests/qpid-perftest.cpp b/cpp/src/tests/qpid-perftest.cpp
index dd81354adb..4d7b563c8c 100644
--- a/cpp/src/tests/qpid-perftest.cpp
+++ b/cpp/src/tests/qpid-perftest.cpp
@@ -396,7 +396,7 @@ struct Controller : public Client {
void run() { // Controller
try {
// Wait for subscribers to be ready.
- process(opts.totalSubs, fqn("sub_ready"), boost::bind(expect, _1, "ready"));
+ process(opts.totalSubs, fqn("sub_ready"), bind(expect, _1, "ready"));
LocalQueue pubDone;
LocalQueue subDone;
@@ -423,10 +423,8 @@ struct Controller : public Client {
process(opts.totalSubs, subDone, fqn("sub_done"), boost::ref(subRates));
AbsTime end=now();
+
double time=secs(start, end);
- if (time <= 0.0) {
- throw Exception("ERROR: Test completed in zero seconds. Try again with a larger message count.");
- }
double txrate=opts.transfers/time;
double mbytes=(txrate*opts.size)/(1024*1024);
@@ -510,11 +508,10 @@ struct PublishThread : public Client {
}
SubscriptionManager subs(session);
LocalQueue lq;
- subs.setFlowControl(0, SubscriptionManager::UNLIMITED, false);
- Subscription cs = subs.subscribe(lq, fqn("pub_start"));
+ subs.setFlowControl(1, SubscriptionManager::UNLIMITED, true);
+ subs.subscribe(lq, fqn("pub_start"));
for (size_t j = 0; j < opts.iterations; ++j) {
- cs.grantMessageCredit(1);
expect(lq.pop().getData(), "start");
AbsTime start=now();
for (size_t i=0; i<opts.count; i++) {
@@ -546,9 +543,6 @@ struct PublishThread : public Client {
if (opts.confirm) session.sync();
AbsTime end=now();
double time=secs(start,end);
- if (time <= 0.0) {
- throw Exception("ERROR: Test completed in zero seconds. Try again with a larger message count.");
- }
// Send result to controller.
Message report(lexical_cast<string>(opts.count/time), fqn("pub_done"));
@@ -644,9 +638,7 @@ struct SubscribeThread : public Client {
//
// For now verify order only for a single publisher.
size_t offset = opts.uniqueData ? 5 /*marker is 'data:'*/ : 0;
- size_t n;
- memcpy (&n, reinterpret_cast<const char*>(msg.getData().data() + offset),
- sizeof(n));
+ size_t n = *reinterpret_cast<const size_t*>(msg.getData().data() + offset);
if (opts.pubs == 1) {
if (opts.subs == 1 || opts.mode == FANOUT) verify(n==expect, "==", expect, n);
else verify(n>=expect, ">=", expect, n);
diff --git a/cpp/src/tests/qpid-receive.cpp b/cpp/src/tests/qpid-receive.cpp
index 9c713e872a..012d544a2e 100644
--- a/cpp/src/tests/qpid-receive.cpp
+++ b/cpp/src/tests/qpid-receive.cpp
@@ -53,7 +53,6 @@ struct Options : public qpid::Options
bool forever;
uint messages;
bool ignoreDuplicates;
- bool checkRedelivered;
uint capacity;
uint ackFrequency;
uint tx;
@@ -76,7 +75,6 @@ struct Options : public qpid::Options
forever(false),
messages(0),
ignoreDuplicates(false),
- checkRedelivered(false),
capacity(1000),
ackFrequency(100),
tx(0),
@@ -94,11 +92,10 @@ struct Options : public qpid::Options
("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to")
("address,a", qpid::optValue(address, "ADDRESS"), "address to receive from")
("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection")
- ("timeout", qpid::optValue(timeout, "TIMEOUT"), "timeout in seconds to wait before exiting")
+ ("timeout,t", qpid::optValue(timeout, "TIMEOUT"), "timeout in seconds to wait before exiting")
("forever,f", qpid::optValue(forever), "ignore timeout and wait forever")
("messages,m", qpid::optValue(messages, "N"), "Number of messages to receive; 0 means receive indefinitely")
("ignore-duplicates", qpid::optValue(ignoreDuplicates), "Detect and ignore duplicates (by checking 'sn' header)")
- ("check-redelivered", qpid::optValue(checkRedelivered), "Fails with exception if a duplicate is not marked as redelivered (only relevant when ignore-duplicates is selected)")
("capacity", qpid::optValue(capacity, "N"), "Pre-fetch window (0 implies no pre-fetch)")
("ack-frequency", qpid::optValue(ackFrequency, "N"), "Ack frequency (0 implies none of the messages will get accepted)")
("tx", qpid::optValue(tx, "N"), "batch size for transactions (0 implies transaction are not used)")
@@ -219,8 +216,6 @@ int main(int argc, char ** argv)
std::cout << msg.getContent() << std::endl;//TODO: handle map or list messages
if (opts.messages && count >= opts.messages) done = true;
}
- } else if (opts.checkRedelivered && !msg.getRedelivered()) {
- throw qpid::Exception("duplicate sequence number received, message not marked as redelivered!");
}
if (opts.tx && (count % opts.tx == 0)) {
if (opts.rollbackFrequency && (++txCount % opts.rollbackFrequency == 0)) {
@@ -262,7 +257,7 @@ int main(int argc, char ** argv)
return 0;
}
} catch(const std::exception& error) {
- std::cerr << "qpid-receive: " << error.what() << std::endl;
+ std::cerr << "Failure: " << error.what() << std::endl;
connection.close();
return 1;
}
diff --git a/cpp/src/tests/qpid-send.cpp b/cpp/src/tests/qpid-send.cpp
index b1213a484f..6a7e7838ce 100644
--- a/cpp/src/tests/qpid-send.cpp
+++ b/cpp/src/tests/qpid-send.cpp
@@ -28,7 +28,6 @@
#include <qpid/messaging/FailoverUpdates.h>
#include <qpid/sys/Time.h>
#include <qpid/sys/Monitor.h>
-#include <qpid/sys/SystemInfo.h>
#include "TestOptions.h"
#include "Statistics.h"
@@ -77,11 +76,6 @@ struct Options : public qpid::Options
uint flowControl;
bool sequence;
bool timestamp;
- std::string groupKey;
- std::string groupPrefix;
- uint groupSize;
- bool groupRandSize;
- uint groupInterleave;
Options(const std::string& argv0=std::string())
: qpid::Options("Options"),
@@ -106,23 +100,19 @@ struct Options : public qpid::Options
sendRate(0),
flowControl(0),
sequence(true),
- timestamp(true),
- groupPrefix("GROUP-"),
- groupSize(10),
- groupRandSize(false),
- groupInterleave(1)
+ timestamp(true)
{
addOptions()
("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to")
- ("address,a", qpid::optValue(address, "ADDRESS"), "address to send to")
+ ("address,a", qpid::optValue(address, "ADDRESS"), "address to drain from")
("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection")
("messages,m", qpid::optValue(messages, "N"), "stop after N messages have been sent, 0 means no limit")
("id,i", qpid::optValue(id, "ID"), "use the supplied id instead of generating one")
("reply-to", qpid::optValue(replyto, "REPLY-TO"), "specify reply-to address")
("send-eos", qpid::optValue(sendEos, "N"), "Send N EOS messages to mark end of input")
("durable", qpid::optValue(durable, "yes|no"), "Mark messages as durable.")
- ("ttl", qpid::optValue(ttl, "msecs"), "Time-to-live for messages, in milliseconds")
- ("priority", qpid::optValue(priority, "PRIORITY"), "Priority for messages (higher value implies higher priority)")
+ ("ttl", qpid::optValue(ttl, "msecs"), "Time-to-live for messages, in milliseconds")
+ ("priority", qpid::optValue(priority, "PRIORITY"), "Priority for messages (higher value implies higher priority)")
("property,P", qpid::optValue(properties, "NAME=VALUE"), "specify message property")
("correlation-id", qpid::optValue(correlationid, "ID"), "correlation-id for message")
("user-id", qpid::optValue(userid, "USERID"), "userid for message")
@@ -141,11 +131,6 @@ struct Options : public qpid::Options
("flow-control", qpid::optValue(flowControl,"N"), "Do end to end flow control to limit queue depth to 2*N. 0 means no flow control.")
("sequence", qpid::optValue(sequence, "yes|no"), "Add a sequence number messages property (required for duplicate/lost message detection)")
("timestamp", qpid::optValue(timestamp, "yes|no"), "Add a time stamp messages property (required for latency measurement)")
- ("group-key", qpid::optValue(groupKey, "KEY"), "Generate groups of messages using message header 'KEY' to hold the group identifier")
- ("group-prefix", qpid::optValue(groupPrefix, "STRING"), "Generate group identifers with 'STRING' prefix (if group-key specified)")
- ("group-size", qpid::optValue(groupSize, "N"), "Number of messages per a group (if group-key specified)")
- ("group-randomize-size", qpid::optValue(groupRandSize), "Randomize the number of messages per group to [1...group-size] (if group-key specified)")
- ("group-interleave", qpid::optValue(groupInterleave, "N"), "Simultaineously interleave messages from N different groups (if group-key specified)")
("help", qpid::optValue(help), "print this usage statement");
add(log);
}
@@ -267,68 +252,6 @@ class MapContentGenerator : public ContentGenerator {
const Options& opts;
};
-// tag each generated message with a group identifer
-//
-class GroupGenerator {
-public:
- GroupGenerator(const std::string& key,
- const std::string& prefix,
- const uint size,
- const bool randomize,
- const uint interleave)
- : groupKey(key), groupPrefix(prefix), groupSize(size),
- randomizeSize(randomize), groupSuffix(0)
- {
- if (randomize) srand((unsigned int)qpid::sys::SystemInfo::getProcessId());
-
- for (uint i = 0; i < 1 || i < interleave; ++i) {
- newGroup();
- }
- current = groups.begin();
- }
-
- void setGroupInfo(Message &msg)
- {
- if (current == groups.end())
- current = groups.begin();
- msg.getProperties()[groupKey] = current->id;
- // std::cout << "SENDING GROUPID=[" << current->id << "]" << std::endl;
- if (++(current->count) == current->size) {
- newGroup();
- groups.erase(current++);
- } else
- ++current;
- }
-
- private:
- const std::string& groupKey;
- const std::string& groupPrefix;
- const uint groupSize;
- const bool randomizeSize;
-
- uint groupSuffix;
-
- struct GroupState {
- std::string id;
- const uint size;
- uint count;
- GroupState( const std::string& i, const uint s )
- : id(i), size(s), count(0) {}
- };
- typedef std::list<GroupState> GroupList;
- GroupList groups;
- GroupList::iterator current;
-
- void newGroup() {
- std::ostringstream groupId(groupPrefix, ios_base::out|ios_base::ate);
- groupId << groupSuffix++;
- uint size = (randomizeSize) ? (rand() % groupSize) + 1 : groupSize;
- // std::cout << "New group: GROUPID=[" << groupId.str() << "] size=" << size << std::endl;
- GroupState group( groupId.str(), size );
- groups.push_back( group );
- }
-};
-
int main(int argc, char ** argv)
{
Connection connection;
@@ -373,14 +296,6 @@ int main(int argc, char ** argv)
else
contentGen.reset(new FixedContentGenerator(opts.contentString));
- std::auto_ptr<GroupGenerator> groupGen;
- if (!opts.groupKey.empty())
- groupGen.reset(new GroupGenerator(opts.groupKey,
- opts.groupPrefix,
- opts.groupSize,
- opts.groupRandSize,
- opts.groupInterleave));
-
qpid::sys::AbsTime start = qpid::sys::now();
int64_t interval = 0;
if (opts.sendRate) interval = qpid::sys::TIME_SEC/opts.sendRate;
@@ -397,6 +312,9 @@ int main(int argc, char ** argv)
++sent;
if (opts.sequence)
msg.getProperties()[SN] = sent;
+ if (opts.timestamp)
+ msg.getProperties()[TS] = int64_t(
+ qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now()));
if (opts.flowControl) {
if ((sent % opts.flowControl) == 0) {
msg.setReplyTo(flowControlAddress);
@@ -405,12 +323,6 @@ int main(int argc, char ** argv)
else
msg.setReplyTo(Address()); // Clear the reply address.
}
- if (groupGen.get())
- groupGen->setGroupInfo(msg);
-
- if (opts.timestamp)
- msg.getProperties()[TS] = int64_t(
- qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now()));
sender.send(msg);
reporter.message(msg);
@@ -456,7 +368,7 @@ int main(int argc, char ** argv)
return 0;
}
} catch(const std::exception& error) {
- std::cerr << "qpid-send: " << error.what() << std::endl;
+ std::cout << "Failed: " << error.what() << std::endl;
connection.close();
return 1;
}
diff --git a/cpp/src/tests/qrsh.cpp b/cpp/src/tests/qrsh.cpp
new file mode 100644
index 0000000000..0cb52b6b05
--- /dev/null
+++ b/cpp/src/tests/qrsh.cpp
@@ -0,0 +1,169 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <qpid/client/Connection.h>
+#include <qpid/client/Session.h>
+#include <qpid/client/AsyncSession.h>
+#include <qpid/client/Message.h>
+#include <qpid/client/MessageListener.h>
+#include <qpid/client/SubscriptionManager.h>
+
+#include <stdio.h>
+#include <cstdlib>
+#include <iostream>
+
+#include <sstream>
+
+using namespace qpid::client;
+using namespace qpid::framing;
+
+using namespace std;
+
+namespace qpid {
+namespace tests {
+
+class ResponseListener : public MessageListener
+{
+ public :
+
+ int exitCode;
+
+ ResponseListener ( SubscriptionManager & subscriptions )
+ : exitCode(-1),
+ subscriptions ( subscriptions )
+ {
+ }
+
+ virtual void
+ received ( Message & message )
+ {
+ char first_word[1000];
+ sscanf ( message.getData().c_str(), "%s", first_word );
+
+ if ( ! strcmp ( first_word, "wait_response" ) )
+ {
+ // If we receive a message here, parse out the exit code.
+ sscanf ( message.getData().c_str(), "%*s%d", & exitCode );
+ subscriptions.cancel(message.getDestination());
+ }
+ else
+ if ( ! strcmp ( first_word, "get_response" ) )
+ {
+ // The remainder of the message is the file we requested.
+ fprintf ( stdout,
+ "%s",
+ message.getData().c_str() + strlen("get_response" )
+ );
+ subscriptions.cancel(message.getDestination());
+ }
+ }
+
+
+ private :
+
+ SubscriptionManager & subscriptions;
+};
+
+}} // namespace qpid::tests
+
+using namespace qpid::tests;
+
+/*
+ * argv[1] host
+ * argv[2] port
+ * argv[3] server name
+ * argv[4] command name
+ * argv[5..N] args to the command
+ */
+int
+main ( int argc, char ** argv )
+{
+ const char* host = argv[1];
+ int port = atoi(argv[2]);
+
+
+ Connection connection;
+
+ try
+ {
+ connection.open ( host, port );
+ Session session = connection.newSession ( );
+
+ // Make a queue and bind it to fanout.
+ string myQueue = session.getId().getName();
+
+ session.queueDeclare ( arg::queue=myQueue,
+ arg::exclusive=true,
+ arg::autoDelete=true
+ );
+
+ session.exchangeBind ( arg::exchange="amq.fanout",
+ arg::queue=myQueue,
+ arg::bindingKey="my-key"
+ );
+
+ // Get ready to listen for the wait-response.
+ // or maybe a get-response.
+ // ( Although this may not be one of those types
+ // of command, get ready anyway.
+ SubscriptionManager subscriptions ( session );
+ ResponseListener responseListener ( subscriptions );
+ subscriptions.subscribe ( responseListener, myQueue );
+
+ bool response_command = false;
+ if(! strcmp("exec_wait", argv[4] ))
+ response_command = true;
+ else
+ if(! strcmp("exited", argv[4] ))
+ response_command = true;
+ else
+ if(! strcmp("get", argv[4] ))
+ response_command = true;
+
+ // Send the payload message.
+ // Skip "qrsh host_name port"
+ Message message;
+ stringstream ss;
+ for ( int i = 3; i < argc; ++ i )
+ ss << argv[i] << ' ';
+
+ message.setData ( ss.str() );
+
+ session.messageTransfer(arg::content=message,
+ arg::destination="amq.fanout");
+
+ if ( response_command )
+ subscriptions.run();
+
+ session.close();
+ connection.close();
+ return responseListener.exitCode;
+ }
+ catch ( exception const & e)
+ {
+ cerr << e.what() << endl;
+ }
+
+ return 1;
+}
+
+
+
diff --git a/cpp/src/tests/qrsh_run.cpp b/cpp/src/tests/qrsh_run.cpp
new file mode 100644
index 0000000000..cfdd0cef80
--- /dev/null
+++ b/cpp/src/tests/qrsh_run.cpp
@@ -0,0 +1,321 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+
+using namespace std;
+
+
+
+int
+main ( int argc, char ** argv )
+{
+ int exit_code = -1;
+ int fd[2];
+ int my_pid = getpid();
+ int child_pid;
+
+ pipe(fd);
+
+ char const * root_dir = argv[1]; // This arg is prepended by qrsh_server.
+ char const * child_name = argv[2]; // This arg comes from qrsh.
+ char const * child_path = argv[3]; // This arg comes from qrsh.
+
+ // This is the problem..
+ fprintf ( stderr, "MDEBUG qrsh_run: root_dir: |%s|\n", root_dir );
+ fprintf ( stderr, "MDEBUG qrsh_run: child_name: |%s|\n", child_name );
+ fprintf ( stderr, "MDEBUG qrsh_run: child_path: |%s|\n", child_path );
+
+ /*
+ * A named child is one for whom we will create a directory and
+ * store information. There are some magic names that are not
+ * real symbolic names -- but are instead the names of actions.
+ */
+
+ bool named_child = true;
+
+ if ( ! strcmp ( child_name, "exec" ) )
+ named_child = false;
+ else
+ if ( ! strcmp ( child_name, "exec_wait" ) )
+ named_child = false;
+ else
+ if ( ! strcmp ( child_name, "exited" ) )
+ named_child = false;
+ else
+ named_child = true;
+
+ stringstream child_dir_name;
+
+ if ( named_child )
+ {
+ child_dir_name << root_dir
+ << '/'
+ << child_name;
+
+ /*
+ * Make the child directory before forking, or there is
+ * a race in which the child might be trying to make its
+ * stdout and stderr files while we are tring to make
+ * the directory.
+ */
+ if ( -1 == mkdir ( child_dir_name.str().c_str(), 0777 ) )
+ {
+ fprintf ( stderr,
+ "qrsh_run error: Can't mkdir |%s|\n",
+ child_dir_name.str().c_str()
+ );
+ exit ( 1 );
+ }
+
+ }
+ else
+ /*
+ * If this is an 'exited' command that means we are
+ * waiting for a pre-existing child.
+ */
+ if ( ! strcmp ( child_name, "exited" ) )
+ {
+ int wait_pid = atoi(child_path);
+
+ // Find the child's symbolic name.
+ stringstream pid_to_name_file_name;
+ pid_to_name_file_name << root_dir
+ << '/'
+ << wait_pid;
+ FILE * fp = fopen ( pid_to_name_file_name.str().c_str(), "r" );
+ if (! fp)
+ {
+ fprintf ( stderr,
+ "qrsh_run %d error: Can't open pid2name file |%s|.\n",
+ my_pid,
+ pid_to_name_file_name.str().c_str()
+ );
+ exit(1);
+ }
+ char symbolic_name[1000];
+ strcpy ( symbolic_name, "qrsh_no_name" );
+ fscanf ( fp, "%s", symbolic_name );
+ fclose ( fp );
+
+ // Make the name of the child's exit code file.
+ stringstream exit_code_file_name;
+ exit_code_file_name << root_dir
+ << '/'
+ << symbolic_name
+ << "/exit_code";
+
+ struct stat stat_buf;
+ int file_does_not_exist = stat ( exit_code_file_name.str().c_str(), & stat_buf );
+
+ /*
+ * If the result of stat is zero, the file exists, which means that
+ * the command has exited. The question we are being asked here is
+ * "has it exited yet?"
+ */
+ if ( ! file_does_not_exist )
+ return 1;
+ else
+ if ( errno == ENOENT )
+ return 0;
+ else
+ return 2 ;
+ }
+
+
+ // We are not waiting on a pre-wxiting child: we have a
+ // new child to create.
+
+ child_pid = fork();
+
+ if ( child_pid == 0 )
+ {
+ // This code is executed in the child process.
+
+ // If it's a *named* child, then redirect its stdout and stderr.
+ if ( named_child )
+ {
+ stringstream stdout_path,
+ stderr_path;
+
+ // Redirect the child's stdout. -----------------
+ stdout_path << root_dir
+ << '/'
+ << child_name
+ << '/'
+ << "stdout";
+
+ int redirected_stdout = open ( stdout_path.str().c_str(),
+ O_WRONLY|O_CREAT|O_TRUNC,
+ S_IRWXU|S_IRWXG|S_IRWXO
+ );
+ if ( redirected_stdout < 0 )
+ {
+ perror ( "qrsh_run: error opening redirected_stdout: " );
+ fprintf ( stderr, "stdout path: |%s|\n", stdout_path.str().c_str() );
+ exit ( 1 );
+ }
+ if ( -1 == dup2 ( redirected_stdout, 1 ) )
+ {
+ perror ( "qrsh_run: dup2 (stdout) error: " );
+ exit(1);
+ }
+
+ // Redirect the child's stderr. -----------------
+ stderr_path << root_dir
+ << '/'
+ << child_name
+ << '/'
+ << "stderr";
+
+ int redirected_stderr = open ( stderr_path.str().c_str(),
+ O_WRONLY|O_CREAT|O_TRUNC,
+ S_IRWXU|S_IRWXG|S_IRWXO
+ );
+ if ( redirected_stderr < 0 )
+ {
+ perror ( "qrsh_run: error opening redirected_stderr: " );
+ fprintf ( stderr, "stderr path: |%s|\n", stderr_path.str().c_str() );
+ exit ( 1 );
+ }
+ if(-1 == dup2 ( redirected_stderr, 2 ) )
+ {
+ perror ( "qrsh_run: dup2 (stderr) error: " );
+ exit(1);
+ }
+ }
+
+ fprintf ( stderr, "MDEBUG ------------- qrsh_run argv -------------\n" );
+ for ( int i = 0; i < argc; ++ i )
+ fprintf ( stderr, "MDEBUG argv[%d] : |%s|\n", i, argv[i] );
+
+ execv ( child_path, argv + 2 );
+ perror ( "qrsh_run: execv error: " );
+ fprintf ( stderr, "on path |%s|\n", child_path );
+ exit ( 1 );
+ }
+ else
+ {
+ // This code is executed in the parent process.
+
+ if ( named_child )
+ {
+ // Write the name-to-pid mapping.
+ stringstream pid_file_name;
+ pid_file_name << child_dir_name.str()
+ << "/pid";
+
+ FILE * fp;
+ if ( ! (fp = fopen ( pid_file_name.str().c_str(), "w") ) )
+ {
+ fprintf ( stderr,
+ "qrsh_run %d error: Can't open file |%s|\n",
+ my_pid,
+ pid_file_name.str().c_str()
+ );
+ exit(1);
+ }
+ fprintf ( fp, "%d\n", child_pid );
+ fclose ( fp );
+
+
+ // Write the pid-to-name mapping.
+ stringstream name_to_pid_file_name;
+ name_to_pid_file_name << root_dir
+ << '/'
+ << child_pid;
+ if(! (fp = fopen ( name_to_pid_file_name.str().c_str(), "w")))
+ {
+ fprintf ( stderr,
+ "qrsh_run %d error: Can't open file |%s|\n",
+ my_pid,
+ name_to_pid_file_name.str().c_str()
+ );
+ exit(1);
+ }
+ fprintf ( fp, "%s\n", child_name );
+ fclose(fp);
+ }
+
+ pid_t awaited_pid;
+ while ( 0 == (awaited_pid = waitpid ( child_pid, & exit_code, WNOHANG)) )
+ {
+ fprintf ( stderr,
+ "qrsh_run %d info: parent: waiting for child %d...\n",
+ my_pid,
+ child_pid
+ );
+ sleep(1);
+ }
+
+ if ( -1 == awaited_pid )
+ {
+ fprintf ( stderr, "qrsh_run error awaiting child!\n" );
+ exit ( 1 );
+ }
+
+ /*
+ * Write the exit code.
+ */
+ exit_code >>= 8;
+
+ if ( named_child )
+ {
+ if ( child_pid == awaited_pid )
+ {
+ stringstream exit_code_file_name;
+ exit_code_file_name << child_dir_name.str()
+ << "/exit_code";
+
+ FILE * fp;
+ if ( ! (fp = fopen ( exit_code_file_name.str().c_str(), "w") ) )
+ {
+ fprintf ( stderr,
+ "qrsh_run error: Can't open file |%s|\n",
+ exit_code_file_name.str().c_str()
+ );
+ exit(1);
+ }
+ fprintf ( fp, "%d\n", exit_code );
+ fclose ( fp );
+ }
+ }
+ }
+
+ fprintf ( stderr, "MDEBUG qrsh_run returning exit code %d\n", exit_code );
+ return exit_code;
+}
+
+
+
+
diff --git a/cpp/src/tests/qrsh_server.cpp b/cpp/src/tests/qrsh_server.cpp
new file mode 100644
index 0000000000..782f1e6c7c
--- /dev/null
+++ b/cpp/src/tests/qrsh_server.cpp
@@ -0,0 +1,1068 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <set>
+#include <string>
+#include <sstream>
+#include <unistd.h>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <dirent.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <qpid/client/Connection.h>
+#include <qpid/client/Session.h>
+#include <qpid/client/AsyncSession.h>
+#include <qpid/client/Message.h>
+#include <qpid/client/MessageListener.h>
+#include <qpid/client/SubscriptionManager.h>
+
+
+using namespace qpid::client;
+using namespace qpid::framing;
+using namespace std;
+
+
+namespace qpid {
+namespace tests {
+
+int
+mrand ( int max_desired_val )
+{
+ double zero_to_one = (double) rand() / (double) RAND_MAX;
+ return (int) (zero_to_one * (double) max_desired_val);
+}
+
+
+
+char *
+file2str ( char const * file_name )
+{
+ FILE * fp = fopen ( file_name, "r" );
+ if(! fp)
+ {
+ fprintf ( stderr, "file2str error: can't open file |%s|.\n", file_name );
+ return 0;
+ }
+
+ fseek ( fp, 0, SEEK_END );
+ size_t file_len = (size_t) ftell ( fp );
+ rewind ( fp );
+ char * content = (char *) malloc ( file_len + 1 );
+
+ if ( ! content )
+ {
+ fprintf ( stderr,
+ "file2str error: can't malloc %d bytes.\n",
+ (int)file_len
+ );
+ return 0;
+ }
+
+ size_t items_read = fread ( content, file_len, 1, fp );
+
+ if ( 1 != items_read )
+ {
+ fprintf ( stderr, "file2str error: read failed.\n" );
+ free ( content );
+ return 0;
+ }
+
+ fclose ( fp );
+ content[file_len] = 0;
+
+ return content;
+}
+
+
+
+
+
+class QrshServer : public MessageListener
+{
+ public:
+
+ QrshServer ( SubscriptionManager & subscriptions,
+ char const * name,
+ char const * qrsh_run_path,
+ char const * host,
+ int port
+ );
+
+ virtual void received ( Message & message);
+
+
+ private:
+
+ set<string> all_server_names;
+
+ stringstream data_dir;
+
+ SubscriptionManager & subscriptions;
+
+ // Is this message addressed to me?
+ bool myMessage ( Message const & message );
+
+ /* ----------------------------------------------
+ * Special Commands
+ * These are commands that the qrsh_server executes
+ * directly, rather than through a child process
+ * instance of qrsh_run.
+ */
+ void runCommand ( Message const & message );
+ void execute ( Message const & message );
+ void wait ( Message const & message );
+ void exited ( Message const & message );
+ void get ( Message const & message );
+ void rememberIntroduction ( Message const & message );
+ void getStraw ( Message const & message );
+ void addAlias ( Message const & message );
+
+ void start ( );
+ void sayHello ( );
+ void sayName ( );
+ // end Special Commands ------------------------
+
+
+ void saveCommand ( Message const & message );
+
+ void send ( string const & content );
+
+ void drawStraws ( );
+ void getNames ( );
+ void runSavedCommand ( );
+
+ char ** getArgs ( char const * s );
+ bool isProcessName ( char const * s );
+ int string_countWords ( char const * s );
+ char const * skipWord ( char const * s );
+
+
+ void string_replaceAll ( string & str,
+ string & target,
+ string & replacement
+ );
+
+
+ string name,
+ qrsh_run_path,
+ host;
+
+ vector<string *> aliases;
+
+ int port;
+
+ map < char *, int > abstract_name_map;
+
+ set < string > myFellowBrokers;
+
+ bool saidHello;
+
+ Message savedCommand;
+
+ vector < int > straws;
+ int myStraw;
+
+};
+
+
+
+QrshServer::QrshServer ( SubscriptionManager & subs,
+ char const * name,
+ char const * qrsh_run_path,
+ char const * host,
+ int port
+ )
+ : subscriptions ( subs ),
+ name ( name ),
+ qrsh_run_path ( qrsh_run_path ),
+ host ( host ),
+ port ( port ),
+ saidHello ( false ),
+ myStraw ( 0 )
+{
+ data_dir << "/tmp/qrsh_"
+ << getpid();
+
+ if(mkdir ( data_dir.str().c_str(), 0777 ) )
+ {
+ fprintf ( stderr,
+ "QrshServer::QrshServer error: can't mkdir |%s|\n",
+ data_dir.str().c_str()
+ );
+ exit ( 1 );
+ }
+}
+
+
+
+void
+QrshServer::saveCommand ( Message const & message )
+{
+ savedCommand = message;
+}
+
+
+
+void
+QrshServer::runSavedCommand ( )
+{
+ runCommand ( savedCommand );
+}
+
+
+
+void
+QrshServer::start ( )
+{
+ stringstream announcement_data;
+ announcement_data << "hello_my_name_is "
+ << name;
+
+ send ( announcement_data.str() );
+
+ saidHello = true;
+}
+
+
+
+
+void
+QrshServer::send ( string const & content )
+{
+ try
+ {
+ Message message;
+ message.setData ( content );
+
+ Connection connection;
+ connection.open ( host, port );
+ Session session = connection.newSession ( );
+ session.messageTransfer ( arg::content = message,
+ arg::destination = "amq.fanout"
+ );
+ session.close();
+ connection.close();
+ }
+ catch ( exception const & e )
+ {
+ fprintf ( stderr, "QrshServer::send error: |%s|\n", e.what() );
+ }
+}
+
+
+
+
+void
+QrshServer::sayHello ( )
+{
+ if ( saidHello )
+ return;
+
+ stringstream ss;
+
+ ss << "hello_my_name_is "
+ << name;
+
+ send ( ss.str() );
+ saidHello = true;
+}
+
+
+
+void
+QrshServer::sayName ( )
+{
+ fprintf ( stderr, "My name is: |%s|\n", name.c_str() );
+}
+
+
+
+
+void
+QrshServer::drawStraws ( )
+{
+ myStraw = mrand ( 1000000000 );
+ stringstream ss;
+ ss << "straw "
+ << name
+ << ' '
+ << myStraw;
+ send ( ss.str() );
+}
+
+
+
+void
+QrshServer::getStraw ( Message const & message )
+{
+ int straw;
+
+ char brokerName[1000];
+ sscanf ( message.getData().c_str(), "%*s%s", brokerName );
+
+ if ( ! strcmp ( brokerName, name.c_str() ) )
+ return;
+
+ sscanf ( message.getData().c_str(), "%*s%*s%d", & straw );
+ straws.push_back ( straw );
+
+ bool i_win = true;
+ int ties = 0;
+
+ if ( straws.size() >= myFellowBrokers.size() )
+ {
+ // All votes are in! Let's see if I win!
+ for ( unsigned int i = 0; i < straws.size(); ++ i )
+ {
+ if ( straws[i] == myStraw )
+ ++ ties;
+ else
+ if ( straws[i] > myStraw )
+ {
+ i_win = false;
+ break;
+ }
+ }
+
+ if ( i_win && (ties <= 0) )
+ {
+ myStraw = 0;
+ straws.clear();
+ runSavedCommand ( );
+ }
+ else
+ if ( i_win && (ties > 0) )
+ {
+ fprintf ( stderr, "MDEBUG oh no! drawStraws error: server %s tied with straw %d!\n", name.c_str(), straw );
+ }
+ }
+}
+
+
+
+
+/*
+ * "APB" command (all-points-bullitens (commands that are not addressed
+ * specifically to any server)) are handled directly, here.
+ * Because if I return simply "true", the normal command processing code
+ * will misinterpret the command.
+ */
+bool
+QrshServer::myMessage ( Message const & message )
+{
+ int const maxlen = 100;
+ char head[maxlen];
+ char first_word [ maxlen + 1 ];
+ strncpy ( head, message.getData().c_str(), maxlen );
+ sscanf ( head, "%s", first_word );
+
+ if ( ! strcmp ( name.c_str(), first_word ) )
+ {
+ return true;
+ }
+ else
+ {
+ // Is the given name one of my aliases?
+ char possibleAlias[1000];
+ if(1 == sscanf ( message.getData().c_str(), "%s", possibleAlias ))
+ {
+ for ( unsigned int i = 0; i < aliases.size(); ++ i )
+ {
+
+ if ( ! strcmp ( possibleAlias, aliases[i]->c_str() ))
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ if ( ! strcmp ( first_word, "hello_my_name_is" ) )
+ {
+ rememberIntroduction ( message );
+ sayHello ( );
+ return false;
+ }
+ else
+ if ( ! strcmp ( first_word, "straw" ) )
+ {
+ getStraw ( message );
+ return false;
+ }
+ else
+ if ( ! strcmp ( first_word, "all" ) )
+ {
+ return true;
+ }
+ else
+ if ( ! strcmp ( first_word, "any" ) )
+ {
+ straws.clear();
+ usleep ( 200000 );
+ saveCommand ( message );
+ drawStraws ( );
+ return false;
+ }
+ else
+ return false;
+}
+
+
+
+
+void
+QrshServer::rememberIntroduction ( Message const & message )
+{
+ char brokerName [ 1000 ];
+ sscanf ( message.getData().c_str(), "%*s%s", brokerName );
+
+ if ( strcmp ( brokerName, name.c_str() ) )
+ myFellowBrokers.insert ( string ( brokerName ) );
+}
+
+
+
+
+void
+QrshServer::addAlias ( Message const & message )
+{
+ char alias[1000];
+ sscanf ( message.getData().c_str(), "%*s%*s%s", alias );
+ aliases.push_back ( new string(alias) );
+}
+
+
+
+
+void
+QrshServer::getNames ( )
+{
+ abstract_name_map.clear();
+
+ DIR * dir = opendir ( data_dir.str().c_str() );
+
+ if ( ! dir )
+ {
+ fprintf ( stderr,
+ "QrshServer::getNames error: could not open dir |%s|.\n",
+ data_dir.str().c_str()
+ );
+ return;
+ }
+
+ struct dirent * file;
+ while ( (file = readdir ( dir ) ) )
+ {
+ if ( '.' != file->d_name[0] )
+ {
+ stringstream pid_file_name;
+ pid_file_name << data_dir.str()
+ << '/'
+ << file->d_name
+ << "/pid";
+
+ int pid = 0;
+ FILE * fp;
+ if ( (fp = fopen ( pid_file_name.str().c_str(), "r" ) ) )
+ {
+ fscanf ( fp, "%d", & pid );
+ fclose ( fp );
+ abstract_name_map.insert(pair<char*, int>(strdup(file->d_name), pid));
+ }
+ else
+ {
+ /*
+ * Fail silently. The non-existence of this file
+ * is not necessarily an error.
+ */
+ }
+ }
+ }
+ closedir ( dir );
+}
+
+
+
+void
+QrshServer::string_replaceAll ( string & str,
+ string & target,
+ string & replacement
+ )
+{
+ int target_size = target.size();
+ int found_pos = 0;
+
+ while ( 0 <= (found_pos = str.find ( target ) ) )
+ str.replace ( found_pos, target_size, replacement );
+}
+
+
+
+
+bool
+QrshServer::isProcessName ( char const * str )
+{
+ getNames();
+ map<char *, int>::iterator it;
+ for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+ {
+ if ( ! strcmp ( str, it->first ) )
+ return true;
+ }
+
+ return false;
+}
+
+
+
+
+
+int
+QrshServer::string_countWords ( char const * s1 )
+{
+ int count = 0;
+ char const * s2 = s1 + 1;
+
+ if ( ! isspace(* s1) )
+ {
+ ++ count;
+ }
+
+ for ( ; * s2; ++ s1, ++ s2 )
+ {
+ // count space-to-word transitions.
+ if ( isspace(*s1) && (! isspace(*s2)) )
+ ++ count;
+ }
+
+ return count;
+}
+
+
+
+
+void
+QrshServer::execute ( Message const & message )
+{
+ // First, gather all the symbolic names we know.
+ getNames();
+
+ // Now make a copy of the command, that I can alter.
+ string command ( message.getData() );
+
+
+ // Replace each occurrence of every abstract name with its pid.
+ char pid_str[100];
+ map<char *, int>::iterator it;
+ for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+ {
+ sprintf ( pid_str, "%d", it->second );
+ string target ( it->first ),
+ replacement ( pid_str );
+ string_replaceAll ( command, target, replacement );
+ }
+
+
+ char const * truncated_command = skipWord(skipWord(command.c_str()));
+
+ if ( truncated_command )
+ system ( truncated_command );
+}
+
+
+
+
+
+void
+QrshServer::get ( Message const & request_message )
+{
+ char * file_content;
+
+ /*
+ * Get the contents of the requested file.
+ */
+ char file_or_process_name[1000];
+ sscanf ( request_message.getData().c_str(), "%*s%*s%s", file_or_process_name );
+
+ if ( isProcessName ( file_or_process_name ) )
+ {
+ stringstream desired_file_name;
+ desired_file_name << data_dir.str()
+ << '/'
+ << file_or_process_name
+ << '/';
+ char requested_output_stream[1000];
+ if(1 != sscanf ( request_message.getData().c_str(),
+ "%*s%*s%*s%s",
+ requested_output_stream
+ )
+ )
+ {
+ fprintf ( stderr,
+ "QrshServer::get error: Can't read requested data file name from this message: |%s|\n",
+ request_message.getData().c_str()
+ );
+ return;
+ }
+ desired_file_name << requested_output_stream;
+ file_content = file2str ( desired_file_name.str().c_str() );
+ }
+ else
+ {
+ file_content = file2str ( file_or_process_name );
+ }
+
+ stringstream reply_data ;
+ reply_data << "get_response "
+ << file_content;
+ /*
+ * Send a response-message to the server who is waiting.
+ */
+ send ( reply_data.str() );
+}
+
+
+
+
+
+
+void
+QrshServer::exited ( Message const & message )
+{
+ int exit_code = -1;
+
+ // First, gather all the symbolic names we know.
+ getNames();
+
+ // Now make a copy of the command, that I can alter.
+ string edited_command ( message.getData() );
+
+ // Replace each occurrence of every abstract name with its pid.
+ char pid_str[100];
+ map<char *, int>::iterator it;
+ for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+ {
+ sprintf ( pid_str, "%d", it->second );
+ string target ( it->first ),
+ replacement ( pid_str );
+ string_replaceAll ( edited_command, target, replacement );
+ }
+
+ // Skip the service name. That is not used by the child.
+ char const * truncated_command = skipWord(edited_command.c_str());
+
+ if ( truncated_command )
+ {
+ stringstream ss;
+ ss << qrsh_run_path
+ << ' '
+ << data_dir.str()
+ << ' '
+ << truncated_command;
+
+ int child_pid;
+ if ( ! (child_pid = fork() ) )
+ {
+ // This is the child.
+
+ char ** argv = getArgs ( ss.str().c_str() );
+ execv ( qrsh_run_path.c_str(), argv );
+
+ perror ( "qrsh_server: execv error: " );
+ exit ( 1 );
+ }
+ else
+ {
+ // This is the parent.
+ pid_t awaited_pid;
+ while ( 0 == (awaited_pid = waitpid ( child_pid, & exit_code, WNOHANG)) )
+ {
+ fprintf ( stderr, "qrsh_server info: parent: waiting for child...\n" );
+ sleep(1);
+ }
+
+ if ( -1 == awaited_pid )
+ {
+ fprintf ( stderr, "qrsh_server error awaiting child!\n" );
+ exit ( 1 );
+ }
+
+ exit_code >>= 8;
+
+ stringstream data;
+ data << "wait_response "
+ << exit_code;
+
+ send ( data.str() );
+ }
+ }
+}
+
+
+
+
+void
+QrshServer::wait ( Message const & message )
+{
+ bool pre_existing = false;
+ if ( 3 == string_countWords ( message.getData().c_str() ) )
+ {
+ // The first word is the name of this service.
+ // The second word is "exec_wait".
+ // The third word is the symbolic name of the command to wait for.
+ // The fact that there are exactly three words means that this
+ // must be a command that has already been named and started --
+ // we just need to find its pid and wait on it.
+ pre_existing = true;
+ }
+
+
+ int exit_code = -1;
+
+ // First, gather all the symbolic names we know.
+ getNames();
+
+ // Now make a copy of the command, that I can alter.
+ string edited_command ( message.getData() );
+
+ // Replace each occurrence of every abstract name with its pid.
+ char pid_str[100];
+ map<char *, int>::iterator it;
+ for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+ {
+ sprintf ( pid_str, "%d", it->second );
+ string target ( it->first ),
+ replacement ( pid_str );
+ string_replaceAll ( edited_command, target, replacement );
+ }
+
+ // Skip the service name. That is not used by the child.
+ char const * truncated_command = skipWord(edited_command.c_str());
+
+ if ( truncated_command )
+ {
+ stringstream ss;
+ ss << qrsh_run_path
+ << ' '
+ << data_dir.str()
+ << ' '
+ << truncated_command;
+
+ int child_pid;
+ if ( ! (child_pid = fork() ) )
+ {
+ // This is the child.
+
+ char ** argv = getArgs ( ss.str().c_str() );
+ execv ( qrsh_run_path.c_str(), argv );
+
+ perror ( "qrsh_server: execv error: " );
+ exit ( 1 );
+ }
+ else
+ {
+ // This is the parent.
+ pid_t awaited_pid;
+ while ( 0 == (awaited_pid = waitpid ( child_pid, & exit_code, WNOHANG)) )
+ {
+ fprintf ( stderr, "qrsh_server info: parent: waiting for child...\n" );
+ sleep(1);
+ }
+
+ if ( -1 == awaited_pid )
+ {
+ fprintf ( stderr, "qrsh_server error awaiting child!\n" );
+ exit ( 1 );
+ }
+ }
+
+ exit_code >>= 8;
+
+ stringstream data;
+ data << "wait_response "
+ << exit_code;
+
+ send ( data.str() );
+ }
+}
+
+
+
+
+
+char const *
+QrshServer::skipWord ( char const * s )
+{
+ if(! (s && *s) )
+ return 0;
+
+ // skip past initial white space
+ while ( isspace(*s) )
+ {
+ ++ s;
+ if(! *s)
+ return 0;
+ }
+
+ // skip past first word
+ while ( ! isspace(*s) )
+ {
+ ++ s;
+ if(! *s)
+ return 0;
+ }
+
+ return s;
+}
+
+
+
+
+
+char **
+QrshServer::getArgs ( char const * str )
+{
+ char const * s = str;
+
+ char ** argv = 0;
+ vector<int> start_positions,
+ lengths;
+
+ int pos = 0;
+ int arg_len = 0;
+
+ int n_args = 0;
+ while ( 1 )
+ {
+ // advance over whitespace.
+ while ( isspace ( *s ) )
+ {
+ ++ s; ++ pos;
+ if(! *s)
+ {
+ goto done;
+ }
+ }
+
+ ++ n_args;
+ start_positions.push_back ( pos );
+ arg_len = 0;
+
+ // advance over non-whitespace.
+ while ( ! isspace ( *s ) )
+ {
+ ++ s; ++ pos; ++ arg_len;
+ if(! *s)
+ {
+ lengths.push_back ( arg_len );
+ arg_len = 0;
+ goto done;
+ }
+ }
+
+ lengths.push_back ( arg_len );
+ arg_len = 0;
+ }
+
+ done:
+
+ if ( arg_len > 0 )
+ lengths.push_back ( arg_len );
+
+ // Alloc the array.
+ argv = (char **) malloc ( sizeof(char *) * ( n_args + 1 ) );
+ argv[n_args] = 0; // mull-term the array.
+
+ for ( int i = 0; i < n_args; ++ i )
+ {
+ argv[i] = ( char *) malloc ( lengths[i] + 1 );
+ strncpy ( argv[i],
+ str + start_positions[i],
+ lengths[i]
+ );
+ argv[i][lengths[i]] = 0;
+ }
+
+ return argv;
+}
+
+
+
+void
+QrshServer::runCommand ( Message const & message )
+{
+ char const * s = message.getData().c_str();
+
+ /*
+ * Skip the first word, which is this server's name.
+ */
+ while ( isspace(*s) ) // go to start of first word.
+ ++ s;
+
+ while ( ! isspace(*s) ) // go to end of first word.
+ ++ s;
+
+ while ( isspace(*s) ) // go to start of second word.
+ ++ s;
+
+ char command_name[1000];
+ sscanf ( s, "%s", command_name );
+
+ if ( ! strcmp ( "get", command_name ) )
+ {
+ get ( message );
+ }
+ else
+ if ( ! strcmp ( "exited", command_name ) )
+ {
+ exited ( message );
+ }
+ else
+ if ( ! strcmp ( "exec_wait", command_name ) )
+ {
+ wait ( message );
+ }
+ else
+ if ( ! strcmp ( "exec", command_name ) )
+ {
+ execute ( message );
+ }
+ else
+ if ( ! strcmp ( "start", command_name ) )
+ {
+ start ( );
+ }
+ else
+ if ( ! strcmp ( "alias", command_name ) )
+ {
+ addAlias ( message );
+ }
+ else
+ if ( ! strcmp ( "sayName", command_name ) )
+ {
+ sayName ( );
+ }
+ else
+ {
+ /*
+ * If the command is not any of the "special" commands
+ * above, then it's a "normal" command.
+ * That means we run it with a child process instance of
+ * qrsh_run, which will save all its data in the qrsh dir.
+ */
+ stringstream ss;
+ ss << qrsh_run_path
+ << ' '
+ << data_dir.str()
+ << ' '
+ << s;
+
+ if ( ! fork() )
+ {
+ char ** argv = getArgs ( ss.str().c_str() );
+ execv ( qrsh_run_path.c_str(), argv );
+ perror ( "qrsh_server: execv error: " );
+ }
+ }
+}
+
+
+
+void
+QrshServer::received ( Message & message )
+{
+ if ( myMessage ( message ) )
+ runCommand ( message );
+}
+
+
+
+}} // namespace qpid::tests
+
+using namespace qpid::tests;
+
+/*
+ * fixme mick Mon Aug 3 10:29:26 EDT 2009
+ * argv[1] server name
+ * argv[2] qrsh exe path
+ * argv[3] host
+ * argv[4] port
+ */
+int
+main ( int /*argc*/, char** argv )
+{
+ const char* host = argv[3];
+ int port = atoi(argv[4]);
+ Connection connection;
+ Message msg;
+
+ srand ( getpid() );
+
+ try
+ {
+ connection.open ( host, port );
+ Session session = connection.newSession();
+
+
+ // Declare queues.
+ string myQueue = session.getId().getName();
+ session.queueDeclare ( arg::queue=myQueue,
+ arg::exclusive=true,
+ arg::autoDelete=true);
+
+ session.exchangeBind ( arg::exchange="amq.fanout",
+ arg::queue=myQueue,
+ arg::bindingKey="my-key");
+
+ // Create a server and subscribe it to my queue.
+ SubscriptionManager subscriptions ( session );
+ QrshServer server ( subscriptions,
+ argv[1], // server name
+ argv[2], // qrsh exe path
+ host,
+ port
+ );
+ subscriptions.subscribe ( server, myQueue );
+
+ // Receive messages until the subscription is cancelled
+ // by QrshServer::received()
+ subscriptions.run();
+
+ connection.close();
+ }
+ catch(const exception& error)
+ {
+ cout << error.what() << endl;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+
+
diff --git a/cpp/src/qpid/sys/windows/mingw32_compat.h b/cpp/src/tests/qrsh_utils/10_all
index 51f613cc25..7b486ea672 100644..100755
--- a/cpp/src/qpid/sys/windows/mingw32_compat.h
+++ b/cpp/src/tests/qrsh_utils/10_all
@@ -1,5 +1,3 @@
-#ifndef _sys_windows_mingw32_compat
-#define _sys_windows_mingw32_compat
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -11,7 +9,7 @@
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -19,21 +17,14 @@
* specific language governing permissions and limitations
* under the License.
*
- */
+ */
+
+#! /bin/bash
-#ifdef WIN32
-#ifndef _MSC_VER
+echo "Asking all servers to say their names... "
+qrsh 127.0.0.1 5813 \
+ all sayName
-//
-// The following definitions for extension function GUIDs and signatures are taken from
-// MswSock.h in the Windows32 SDK. These rightfully belong in the mingw32 version of
-// mswsock.h, but are not included presently.
-//
-#define WSAID_ACCEPTEX {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
-typedef BOOL (PASCAL *LPFN_ACCEPTEX)(SOCKET,SOCKET,PVOID,DWORD,DWORD,DWORD,LPDWORD,LPOVERLAPPED);
-#endif
-#endif
-#endif
diff --git a/cpp/src/tests/qrsh_utils/1_remote_run b/cpp/src/tests/qrsh_utils/1_remote_run
new file mode 100755
index 0000000000..5b9b307bba
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/1_remote_run
@@ -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.
+ *
+ */
+
+#! /bin/bash
+
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 command_1 /home/mick/redhat/qrsh/qrsh_run/my_command foo bar baz
diff --git a/cpp/src/tests/qrsh_utils/2_forever b/cpp/src/tests/qrsh_utils/2_forever
new file mode 100755
index 0000000000..5528b0e4d8
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/2_forever
@@ -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.
+ *
+ */
+
+#! /bin/bash
+
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 command_2 /home/mick/redhat/qrsh/qrsh_run/forever foo bar baz
diff --git a/cpp/src/tests/qrsh_utils/3_kill_it b/cpp/src/tests/qrsh_utils/3_kill_it
new file mode 100755
index 0000000000..afc7a03c9d
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/3_kill_it
@@ -0,0 +1,27 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#! /bin/bash
+
+echo "Killing command 2... "
+./qrsh 127.0.0.1 5813 \
+ mrg23 exec kill -9 command_2
+
diff --git a/cpp/src/tests/qrsh_utils/4_wait_for_it b/cpp/src/tests/qrsh_utils/4_wait_for_it
new file mode 100755
index 0000000000..a4dc0da1ce
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/4_wait_for_it
@@ -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.
+ *
+ */
+
+#! /bin/bash
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 exec_wait /home/mick/redhat/qrsh/qrsh_run/my_command foo bar baz
+echo "my_command returned an exit code of $?"
diff --git a/cpp/src/tests/qrsh_utils/5_exited b/cpp/src/tests/qrsh_utils/5_exited
new file mode 100755
index 0000000000..4fec1dcc79
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/5_exited
@@ -0,0 +1,64 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#! /bin/bash
+
+path=/home/mick/redhat/qrsh/qrsh_run
+
+echo "Running command_3 ..."
+./qrsh 127.0.0.1 5813 \
+ mrg23 command_3 $path/my_command foo bar baz
+
+echo "Now I do some other stuff..."
+sleep 1
+echo "And then some more stuff..."
+sleep 1
+echo "and so on..."
+sleep 1
+
+echo "Now I'm waiting for command_3 ..."
+./qrsh 127.0.0.1 5813 \
+ mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/6_get b/cpp/src/tests/qrsh_utils/6_get
new file mode 100755
index 0000000000..4b35ca98e6
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/6_get
@@ -0,0 +1,29 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#! /bin/bash
+
+echo "getting /tmp/foo ..."
+./qrsh 127.0.0.1 5813 \
+ mrg23 get /tmp/foo
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/7_get_output b/cpp/src/tests/qrsh_utils/7_get_output
new file mode 100755
index 0000000000..59911089ec
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/7_get_output
@@ -0,0 +1,44 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#! /bin/bash
+
+echo "Run a command..."
+./qrsh 127.0.0.1 5813 \
+ mrg23 command_4 /home/mick/redhat/qrsh/qrsh_run/my_command foo bar baz
+
+echo "Wait for a while..."
+sleep 20
+
+echo "Get stderr output:"
+echo "------------- begin stderr ---------------"
+./qrsh 127.0.0.1 5813 \
+ mrg23 get command_4 stderr
+echo "------------- end stderr ---------------"
+echo " "
+echo " "
+echo " "
+echo "Get stdout output:"
+echo "------------- begin stdout ---------------"
+./qrsh 127.0.0.1 5813 \
+ mrg23 get command_4 stdout
+echo "------------- end stdout ---------------"
+
diff --git a/cpp/src/tests/qrsh_utils/8_any b/cpp/src/tests/qrsh_utils/8_any
new file mode 100755
index 0000000000..2a922ea0e0
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/8_any
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#! /bin/bash
+
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+ any sayName
+sleep 1
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+ any sayName
+sleep 1
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+ any sayName
+sleep 1
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+ any sayName
+sleep 1
+
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/9_alias b/cpp/src/tests/qrsh_utils/9_alias
new file mode 100755
index 0000000000..a4cfdfdf9a
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/9_alias
@@ -0,0 +1,38 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#! /bin/bash
+
+# Make a group of two of the servers, using "alias",
+# and send the group a command.
+
+qrsh 127.0.0.1 5813 \
+ mrg22 alias group_1
+qrsh 127.0.0.1 5813 \
+ mrg23 alias group_1
+
+echo "Asking group_1 to say their names... "
+qrsh 127.0.0.1 5813 \
+ group_1 sayName
+
+
+
+
diff --git a/cpp/src/qmf/EventNotifierImpl.h b/cpp/src/tests/qrsh_utils/qrsh_example_command.cpp
index d85f9979d2..386e2f73f0 100644
--- a/cpp/src/qmf/EventNotifierImpl.h
+++ b/cpp/src/tests/qrsh_utils/qrsh_example_command.cpp
@@ -1,7 +1,5 @@
-#ifndef __QMF_EVENT_NOTIFIER_IMPL_H
-#define __QMF_EVENT_NOTIFIER_IMPL_H
-
/*
+ *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -9,40 +7,46 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- */
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
-#include "qmf/AgentSession.h"
-#include "qmf/ConsoleSession.h"
-namespace qmf
+main ( int argc, char ** argv )
{
- class EventNotifierImpl {
- private:
- bool readable;
- AgentSession agent;
- ConsoleSession console;
-
- public:
- EventNotifierImpl(AgentSession& agentSession);
- EventNotifierImpl(ConsoleSession& consoleSession);
- virtual ~EventNotifierImpl();
-
- void setReadable(bool readable);
- bool isReadable() const;
-
- protected:
- virtual void update(bool readable) = 0;
- };
+ fprintf ( stderr, "Hello, I am the Example Child!\n");
+ fprintf ( stderr, "my arguments %d are:\n", argc - 1 );
+ fprintf ( stdout, "And hello to stdout, too!\n");
+
+ int i;
+ for ( i = 1; i < argc; ++ i )
+ {
+ fprintf ( stderr, "arg %d: |%s|\n", i, argv[i] );
+ }
+
+ for ( i = 0; i < 15; ++ i )
+ {
+ fprintf ( stderr, "child sleeping...\n" );
+ sleep ( 1 );
+ }
+
+ fprintf ( stderr, "child exiting with code 13.\n" );
+
+ return 13;
}
-#endif
+
+
diff --git a/cpp/src/tests/qrsh_utils/qrsh_forever.cpp b/cpp/src/tests/qrsh_utils/qrsh_forever.cpp
new file mode 100644
index 0000000000..191a9bca11
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/qrsh_forever.cpp
@@ -0,0 +1,50 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+
+#include <stdio.h>
+#include <unistd.h>
+
+
+
+main ( int argc, char ** argv )
+{
+ fprintf ( stderr, "Hello, I am the Forever Example Child!\n");
+ fprintf ( stderr, "my %d arguments are:\n", argc - 1 );
+
+ int i;
+ for ( i = 1; i < argc; ++ i )
+ fprintf ( stderr, "arg %d: |%s|\n", i, argv[i] );
+
+ for ( i = 0; i >= 0; ++ i )
+ {
+ fprintf ( stderr, "child sleeping forever %d ...\n" , i);
+ sleep ( 1 );
+ }
+
+ fprintf ( stderr, "child exiting with code 12.\n" );
+
+ return 12;
+}
+
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/qsh_doc.txt b/cpp/src/tests/qrsh_utils/qsh_doc.txt
new file mode 100644
index 0000000000..ad5990b38b
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/qsh_doc.txt
@@ -0,0 +1,309 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+##############################################
+ qrsh: a Qpid-based remote shell utility
+
+ Last updated: 3 Aug 09 Mick Goulish
+##############################################
+
+
+
+=============================
+Overview
+=============================
+
+ You're writing a multi-box test, and you want to write a
+ shell script in which you start processes on other boxes
+ and kill them (or send arbitrary signals to them).
+
+ But ssh doesn't let you signal them, and bash isn't the
+ greatest language in the world for creating data structures
+ (like you need to associate the PIDs with box names and
+ executable names.)
+
+ Qsh is a utility implemented on Qpid that you can use from
+ within your bash script, or any other scripting language.
+ With it, you can:
+
+ 1. run any executable on any box in your cluster.
+
+ 2. don't worry about PIDs and box-names. You associate
+ your own abstract names with the executable instances,
+ and then use those names in the rest of your script.
+ I.e. "broker_1" "sender_3" etc.
+
+ 3. Launch the executable and wait until it returns, and
+ get its exit code.
+
+ 4. Launch your executable and do other stuff, then come
+ back later and see if it has exited.
+
+ 5. Get whatever it sent to stdout or stderr.
+
+ 6. Get the contents of any other file.
+
+ 7. send a command to all your boxes at once
+
+ 8. send a command to a randomly selected box.
+
+ 9. define groups of boxes, and send a command simultaneously
+ to all boxes in a given group.
+
+
+
+
+=============================
+Using It
+=============================
+
+ 1. You need to run a Qpid broker.
+
+ 2. You start a Qpid client ( which is called a qrsh_server )
+ on all the boxes you care about. And you give them all
+ names like "mrg13", "mrg14" etc. The names can be anything
+ you want, but I've always used one qrsh_server per box,
+ and given it the box name. ( However, you can run two on
+ one box, they won't collide. )
+
+ 3. After you start all servers, send a "start" command to any
+ one of them:
+
+ 4. The qrsh_servers use the fanout exchange to talk to each
+ other.
+
+ 5. In your script, you run an executable called "qrsh". It knows
+ how to talk to the servers, do what you want, and retrieve
+ the data you want.
+
+
+ example start script: (this does 4 servers on the same box)
+ -------------------------------------------------------------
+
+ echo "Starting server mrg22 ..."
+ ./qrsh_server mrg22 ./qrsh_run 127.0.0.1 5813 &
+
+ echo "Starting server mrg23 ..."
+ ./qrsh_server mrg23 ./qrsh_run 127.0.0.1 5813 &
+
+ echo "Starting server mrg24 ..."
+ ./qrsh_server mrg24 ./qrsh_run 127.0.0.1 5813 &
+
+ echo "Starting server mrg25 ..."
+ ./qrsh_server mrg25 ./qrsh_run 127.0.0.1 5813 &
+
+ echo "Issuing start command..."
+ sleep 2
+ ./qrsh 127.0.0.1 5813 mrg22 start
+ sleep 1
+
+ echo "Ready."
+
+ # end of script.
+
+
+
+
+
+
+=============================
+Qrsh Syntax
+=============================
+
+ qrsh host port server_name command_name arg*
+
+
+ "host" and "port" specify the Qpid server to connect to.
+
+ "server_name" can be anything you want. I always use the name
+ of the box that the server is running on.
+
+ "command_name" is the name that you choose to assign to
+ the process you are running. Each process that you decide
+ to name must have a unique name within this script.
+
+ Or it could be a reserved command name, that Qsh
+ interprets in a special way.
+
+ Reserved command names are:
+
+ exec
+ exec_wait
+ exited
+ get
+
+ "exec" means "interpret the rest of the command line as a
+ command to be executed by the designated server.
+
+ "exec_wait" means same as "exec", but wait for the command
+ to terminate, and return its exit code.
+
+ "exited" -- you provide 1 arg, which is an abstract
+ process name. qrsh returns 1 if that process has exited,
+ else 0.
+
+ "get" -- you provide one arg which is a path. qrsh returns
+ (by printing to stdout) the contents of that file.
+
+ "arg*" is zero or more arguments. They are interpreted
+ differently depending on whether you are using one of
+ the above reserved command names, or making up your own
+ abstract name for a command.
+
+
+
+
+=============================
+Examples
+=============================
+
+ 1. Run a process on a remote box.
+
+ qrsh mrg23 command_1 /usr/sbin/whatever foo bar baz
+
+ Returns immediately.
+
+
+
+ 2. Kill a process that you started earlier:
+
+ qrsh mrg23 exec kill -9 command_1
+
+ After the word "exec" put any command line you want.
+ The server you're sending this to will replace all abstract
+ names in the command with process IDs. ( In this example,
+ just the word "command_1" will be replaced. ) Then it will
+ execute the command.
+
+
+
+ 3. Execute a command, and wait for it to finish
+
+ qrsh mrg23 exec_wait command_name args
+
+
+
+ 4. Check on whether a command you issude earlier has exited.
+
+ ./qrsh mrg23 exited command_3
+
+ Returns 1 if it has exited, else 0.
+
+
+
+ 5. Get the contents of a file from the remote system:
+
+ ./qrsh mrg23 get /tmp/foo
+
+ Prints the contents to stdout.
+
+
+
+ 6. Send a command to all servers at once:
+
+ # This example causes them all to print thir names to stderr.
+ ./qrsh all sayName
+
+
+ 7. Define a group of servers and send a command to that group.
+
+ #! /bin/bash
+
+ # Make a group of two of the servers, using "alias",
+ # and send the group a command.
+
+ qrsh 127.0.0.1 5813 \
+ mrg22 alias group_1
+
+ qrsh 127.0.0.1 5813 \
+ mrg23 alias group_1
+
+ echo "Asking group_1 to say their names... "
+ qrsh 127.0.0.1 5813 \
+ group_1 sayName
+
+ # end of script.
+
+
+
+
+ 8. Execute a command and get its stdout and stderr contents.
+
+ #! /bin/bash
+
+ echo "Run a command..."
+ ./qrsh 127.0.0.1 5813 \
+ mrg23 command_4 my_command foo bar baz
+
+ echo "Wait for a while..."
+ sleep 10
+
+ echo "Get stderr output:"
+ echo "------------- begin stderr ---------------"
+ ./qrsh 127.0.0.1 5813 \
+ mrg23 get command_4 stderr
+ echo "------------- end stderr ---------------"
+ echo " "
+
+ echo " "
+ echo "Get stdout output:"
+ echo "------------- begin stdout ---------------"
+ ./qrsh 127.0.0.1 5813 \
+ mrg23 get command_4 stdout
+ echo "------------- end stdout ---------------"
+
+ # end of script.
+
+
+
+
+ 9. Send a command to one of your servers, selected
+ at random.
+
+ #! /bin/bash
+
+ # I do it multiple times here, so I can see
+ # that it really is selecting randomly.
+
+ echo "asking any server to say his name ..."
+ ./qrsh 127.0.0.1 5813 \
+ any sayName
+ sleep 1
+
+ echo "asking any server to say his name ..."
+ ./qrsh 127.0.0.1 5813 \
+ any sayName
+ sleep 1
+
+ echo "asking any server to say his name ..."
+ ./qrsh 127.0.0.1 5813 \
+ any sayName
+ sleep 1
+
+ echo "asking any server to say his name ..."
+ ./qrsh 127.0.0.1 5813 \
+ any sayName
+
+ # end of script.
+
+
+
+
diff --git a/cpp/src/tests/queue_flow_limit_tests.py b/cpp/src/tests/queue_flow_limit_tests.py
deleted file mode 100644
index dec7cfb3af..0000000000
--- a/cpp/src/tests/queue_flow_limit_tests.py
+++ /dev/null
@@ -1,371 +0,0 @@
-#!/usr/bin/env python
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-import sys
-from qpid.testlib import TestBase010
-from qpid import datatypes, messaging
-from qpid.messaging import Message, Empty
-from threading import Thread, Lock
-from logging import getLogger
-from time import sleep, time
-from os import environ, popen
-
-class QueueFlowLimitTests(TestBase010):
-
- def __getattr__(self, name):
- if name == "assertGreater":
- return lambda a, b: self.failUnless(a > b)
- else:
- raise AttributeError
-
- def _create_queue(self, name,
- stop_count=None, resume_count=None,
- stop_size=None, resume_size=None,
- max_size=None, max_count=None):
- """ Create a queue with the given flow settings via the queue.declare
- command.
- """
- args={}
- if (stop_count is not None):
- args["qpid.flow_stop_count"] = stop_count;
- if (resume_count is not None):
- args["qpid.flow_resume_count"] = resume_count;
- if (stop_size is not None):
- args["qpid.flow_stop_size"] = stop_size;
- if (resume_size is not None):
- args["qpid.flow_resume_size"] = resume_size;
- if (max_size is not None):
- args["qpid.max_size"] = max_size;
- if (max_count is not None):
- args["qpid.max_count"] = max_count;
-
-
- self.session.queue_declare(queue=name, arguments=args)
-
- qs = self.qmf.getObjects(_class="queue")
- for i in qs:
- if i.name == name:
- # verify flow settings
- if (stop_count is not None):
- self.assertEqual(i.arguments.get("qpid.flow_stop_count"), stop_count)
- if (resume_count is not None):
- self.assertEqual(i.arguments.get("qpid.flow_resume_count"), resume_count)
- if (stop_size is not None):
- self.assertEqual(i.arguments.get("qpid.flow_stop_size"), stop_size)
- if (resume_size is not None):
- self.assertEqual(i.arguments.get("qpid.flow_resume_size"), resume_size)
- if (max_size is not None):
- self.assertEqual(i.arguments.get("qpid.max_size"), max_size)
- if (max_count is not None):
- self.assertEqual(i.arguments.get("qpid.max_count"), max_count)
- self.failIf(i.flowStopped)
- return i.getObjectId()
- self.fail("Unable to create queue '%s'" % name)
- return None
-
-
- def _delete_queue(self, name):
- """ Delete a named queue
- """
- self.session.queue_delete(queue=name)
-
-
- def _start_qpid_send(self, queue, count, content="X", capacity=100):
- """ Use the qpid-send client to generate traffic to a queue.
- """
- command = "qpid-send" + \
- " -b" + " %s:%s" % (self.broker.host, self.broker.port) \
- + " -a " + str(queue) \
- + " --messages " + str(count) \
- + " --content-string " + str(content) \
- + " --capacity " + str(capacity)
- return popen(command)
-
- def _start_qpid_receive(self, queue, count, timeout=5):
- """ Use the qpid-receive client to consume from a queue.
- Note well: prints one line of text to stdout for each consumed msg.
- """
- command = "qpid-receive" + \
- " -b " + "%s:%s" % (self.broker.host, self.broker.port) \
- + " -a " + str(queue) \
- + " --messages " + str(count) \
- + " --timeout " + str(timeout) \
- + " --print-content yes"
- return popen(command)
-
- def test_qpid_config_cmd(self):
- """ Test the qpid-config command's ability to configure a queue's flow
- control thresholds.
- """
- tool = environ.get("QPID_CONFIG_EXEC")
- if tool:
- command = tool + \
- " --broker-addr=%s:%s " % (self.broker.host, self.broker.port) \
- + "add queue test01 --flow-stop-count=999" \
- + " --flow-resume-count=55 --flow-stop-size=5000000" \
- + " --flow-resume-size=100000"
- cmd = popen(command)
- rc = cmd.close()
- self.assertEqual(rc, None)
-
- # now verify the settings
- self.startQmf();
- qs = self.qmf.getObjects(_class="queue")
- for i in qs:
- if i.name == "test01":
- self.assertEqual(i.arguments.get("qpid.flow_stop_count"), 999)
- self.assertEqual(i.arguments.get("qpid.flow_resume_count"), 55)
- self.assertEqual(i.arguments.get("qpid.flow_stop_size"), 5000000)
- self.assertEqual(i.arguments.get("qpid.flow_resume_size"), 100000)
- self.failIf(i.flowStopped)
- break;
- self.assertEqual(i.name, "test01")
- self._delete_queue("test01")
-
-
- def test_flow_count(self):
- """ Create a queue with count-based flow limit. Spawn several
- producers which will exceed the limit. Verify limit exceeded. Consume
- all messages. Verify flow control released.
- """
- self.startQmf();
- oid = self._create_queue("test-q", stop_count=373, resume_count=229)
- self.assertEqual(self.qmf.getObjects(_objectId=oid)[0].flowStoppedCount, 0)
-
- sndr1 = self._start_qpid_send("test-q", count=1213, content="XXX", capacity=50);
- sndr2 = self._start_qpid_send("test-q", count=797, content="Y", capacity=13);
- sndr3 = self._start_qpid_send("test-q", count=331, content="ZZZZZ", capacity=149);
- totalMsgs = 1213 + 797 + 331
-
- # wait until flow control is active
- deadline = time() + 10
- while (not self.qmf.getObjects(_objectId=oid)[0].flowStopped) and \
- time() < deadline:
- pass
- self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStopped)
- depth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- self.assertGreater(depth, 373)
-
- # now wait until the enqueues stop happening - ensure that
- # not all msgs have been sent (senders are blocked)
- sleep(1)
- newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- while depth != newDepth:
- depth = newDepth;
- sleep(1)
- newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- self.assertGreater(totalMsgs, depth)
-
- # drain the queue
- rcvr = self._start_qpid_receive("test-q",
- count=totalMsgs)
- count = 0;
- x = rcvr.readline() # prints a line for each received msg
- while x:
- count += 1;
- x = rcvr.readline()
-
- sndr1.close();
- sndr2.close();
- sndr3.close();
- rcvr.close();
-
- self.assertEqual(count, totalMsgs)
- self.failIf(self.qmf.getObjects(_objectId=oid)[0].flowStopped)
- self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStoppedCount)
-
- self._delete_queue("test-q")
-
-
- def test_flow_size(self):
- """ Create a queue with size-based flow limit. Spawn several
- producers which will exceed the limit. Verify limit exceeded. Consume
- all messages. Verify flow control released.
- """
- self.startQmf();
- oid = self._create_queue("test-q", stop_size=351133, resume_size=251143)
-
- sndr1 = self._start_qpid_send("test-q", count=1699, content="X"*439, capacity=53);
- sndr2 = self._start_qpid_send("test-q", count=1129, content="Y"*631, capacity=13);
- sndr3 = self._start_qpid_send("test-q", count=881, content="Z"*823, capacity=149);
- totalMsgs = 1699 + 1129 + 881
-
- # wait until flow control is active
- deadline = time() + 10
- while (not self.qmf.getObjects(_objectId=oid)[0].flowStopped) and \
- time() < deadline:
- pass
- self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStopped)
- self.assertGreater(self.qmf.getObjects(_objectId=oid)[0].byteDepth, 351133)
-
- # now wait until the enqueues stop happening - ensure that
- # not all msgs have been sent (senders are blocked)
- depth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- sleep(1)
- newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- while depth != newDepth:
- depth = newDepth;
- sleep(1)
- newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- self.assertGreater(totalMsgs, depth)
-
- # drain the queue
- rcvr = self._start_qpid_receive("test-q",
- count=totalMsgs)
- count = 0;
- x = rcvr.readline() # prints a line for each received msg
- while x:
- count += 1;
- x = rcvr.readline()
-
- sndr1.close();
- sndr2.close();
- sndr3.close();
- rcvr.close();
-
- self.assertEqual(count, totalMsgs)
- self.failIf(self.qmf.getObjects(_objectId=oid)[0].flowStopped)
-
- self._delete_queue("test-q")
-
-
- def verify_limit(self, testq):
- """ run a limit check against the testq object
- """
-
- testq.mgmt = self.qmf.getObjects(_objectId=testq.oid)[0]
-
- # fill up the queue, waiting until flow control is active
- sndr1 = self._start_qpid_send(testq.mgmt.name, count=testq.sendCount, content=testq.content)
- deadline = time() + 10
- while (not testq.mgmt.flowStopped) and time() < deadline:
- testq.mgmt.update()
-
- self.failUnless(testq.verifyStopped())
-
- # now consume enough messages to drop below the flow resume point, and
- # verify flow control is released.
- rcvr = self._start_qpid_receive(testq.mgmt.name, count=testq.consumeCount)
- rcvr.readlines() # prints a line for each received msg
- rcvr.close();
-
- # we should now be below the resume threshold
- self.failUnless(testq.verifyResumed())
-
- self._delete_queue(testq.mgmt.name)
- sndr1.close();
-
-
- def test_default_flow_count(self):
- """ Create a queue with count-based size limit, and verify the computed
- thresholds using the broker's default ratios.
- """
- class TestQ:
- def __init__(self, oid):
- # Use the broker-wide default flow thresholds of 80%/70% (see
- # run_queue_flow_limit_tests) to base the thresholds off the
- # queue's max_count configuration parameter
- # max_count == 1000 -> stop == 800, resume == 700
- self.oid = oid
- self.sendCount = 1000
- self.consumeCount = 301 # (send - resume) + 1 to reenable flow
- self.content = "X"
- def verifyStopped(self):
- self.mgmt.update()
- return self.mgmt.flowStopped and (self.mgmt.msgDepth > 800)
- def verifyResumed(self):
- self.mgmt.update()
- return (not self.mgmt.flowStopped) and (self.mgmt.msgDepth < 700)
-
- self.startQmf();
- oid = self._create_queue("test-X", max_count=1000)
- self.verify_limit(TestQ(oid))
-
-
- def test_default_flow_size(self):
- """ Create a queue with byte-based size limit, and verify the computed
- thresholds using the broker's default ratios.
- """
- class TestQ:
- def __init__(self, oid):
- # Use the broker-wide default flow thresholds of 80%/70% (see
- # run_queue_flow_limit_tests) to base the thresholds off the
- # queue's max_count configuration parameter
- # max_size == 10000 -> stop == 8000 bytes, resume == 7000 bytes
- self.oid = oid
- self.sendCount = 2000
- self.consumeCount = 601 # (send - resume) + 1 to reenable flow
- self.content = "XXXXX" # 5 bytes per message sent.
- def verifyStopped(self):
- self.mgmt.update()
- return self.mgmt.flowStopped and (self.mgmt.byteDepth > 8000)
- def verifyResumed(self):
- self.mgmt.update()
- return (not self.mgmt.flowStopped) and (self.mgmt.byteDepth < 7000)
-
- self.startQmf();
- oid = self._create_queue("test-Y", max_size=10000)
- self.verify_limit(TestQ(oid))
-
-
- def test_blocked_queue_delete(self):
- """ Verify that blocked senders are unblocked when a queue that is flow
- controlled is deleted.
- """
-
- class BlockedSender(Thread):
- def __init__(self, tester, queue, count, capacity=10):
- self.tester = tester
- self.queue = queue
- self.count = count
- self.capacity = capacity
- Thread.__init__(self)
- self.done = False
- self.start()
- def run(self):
- # spawn qpid-send
- p = self.tester._start_qpid_send(self.queue,
- self.count,
- self.capacity)
- p.close() # waits for qpid-send to complete
- self.done = True
-
- self.startQmf();
- oid = self._create_queue("kill-q", stop_size=10, resume_size=2)
- q = self.qmf.getObjects(_objectId=oid)[0]
- self.failIf(q.flowStopped)
-
- sender = BlockedSender(self, "kill-q", count=100)
- # wait for flow control
- deadline = time() + 10
- while (not q.flowStopped) and time() < deadline:
- q.update()
-
- self.failUnless(q.flowStopped)
- self.failIf(sender.done) # sender blocked
-
- self._delete_queue("kill-q")
- sender.join(5)
- self.failIf(sender.isAlive())
- self.failUnless(sender.done)
-
-
-
-
diff --git a/cpp/src/tests/replication_test b/cpp/src/tests/replication_test
index 8c37568875..691fd20b0c 100755
--- a/cpp/src/tests/replication_test
+++ b/cpp/src/tests/replication_test
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
diff --git a/cpp/src/tests/run_acl_tests b/cpp/src/tests/run_acl_tests
index 41f41e20e1..aff13408ed 100755
--- a/cpp/src/tests/run_acl_tests
+++ b/cpp/src/tests/run_acl_tests
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
diff --git a/cpp/src/tests/run_cli_tests b/cpp/src/tests/run_cli_tests
index ec5c71b646..3f1388b9f5 100755
--- a/cpp/src/tests/run_cli_tests
+++ b/cpp/src/tests/run_cli_tests
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
@@ -70,8 +70,7 @@ stop_brokers() {
if test -d ${PYTHON_DIR} ; then
start_brokers
echo "Running CLI tests using brokers on ports $LOCAL_PORT $REMOTE_PORT"
- PYTHON_TESTS=${PYTHON_TESTS:-$*}
- $QPID_PYTHON_TEST -m cli_tests -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dcli-dir=$CLI_DIR $targs $PYTHON_TESTS $@
+ $QPID_PYTHON_TEST -m cli_tests -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dcli-dir=$CLI_DIR $targs $@
RETCODE=$?
stop_brokers
if test x$RETCODE != x0; then
diff --git a/cpp/src/tests/run_federation_sys_tests b/cpp/src/tests/run_federation_sys_tests
deleted file mode 100755
index f5f772d72e..0000000000
--- a/cpp/src/tests/run_federation_sys_tests
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Run the federation system tests.
-
-source ./test_env.sh
-
-MODULENAME=federation_sys
-
-# Test for clustering
-ps -u root | grep 'aisexec\|corosync' > /dev/null
-if (( $? == 0 )); then
- CLUSTERING_ENABLED=1
-else
- echo "WARNING: No clustering detected; tests using it will be ignored."
-fi
-
-# Test for long test
-if [[ "$1" == "LONG_TEST" ]]; then
- USE_LONG_TEST=1
- shift # get rid of this param so it is not treated as a test name
-fi
-
-trap stop_brokers INT TERM QUIT
-
-SKIPTESTS="-i federation_sys.E_* -i federation_sys.F_* -i federation_sys.G_* -i federation_sys.H_*"
-if [ -z ${USE_LONG_TEST} ]; then
- SKIPTESTS="-i federation_sys.A_Long* -i federation_sys.B_Long* ${SKIPTESTS}"
-fi
-echo "WARNING: Tests using persistence will be ignored."
-if [ -z ${CLUSTERING_ENABLED} ]; then
- SKIPTESTS="${SKIPTESTS} -i federation_sys.C_* -i federation_sys.D_*"
-elif [ -z ${USE_LONG_TEST} ]; then
- SKIPTESTS="${SKIPTESTS} -i federation_sys.C_Long* -i federation_sys.D_Long*"
-fi
-
-start_brokers() {
- start_broker() {
- ${QPIDD_EXEC} --daemon --port 0 --auth no --no-data-dir $1 > qpidd.port
- PORT=`cat qpidd.port`
- eval "$2=${PORT}"
- }
- start_broker "" LOCAL_PORT
- start_broker "" REMOTE_PORT
- if [ -n "${CLUSTERING_ENABLED}" ]; then
- start_broker "--load-module ${CLUSTER_LIB} --cluster-name test-cluster-1" CLUSTER_C1_1
- start_broker "--load-module ${CLUSTER_LIB} --cluster-name test-cluster-1" CLUSTER_C1_2
- start_broker "--load-module ${CLUSTER_LIB} --cluster-name test-cluster-2" CLUSTER_C2_1
- start_broker "--load-module ${CLUSTER_LIB} --cluster-name test-cluster-2" CLUSTER_C2_2
- fi
- rm qpidd.port
-}
-
-stop_brokers() {
- ${QPIDD_EXEC} -q --port ${LOCAL_PORT}
- ${QPIDD_EXEC} -q --port ${REMOTE_PORT}
- if [ -n "${CLUSTERING_ENABLED}" ]; then
- ${QPID_CLUSTER_EXEC} --all-stop --force localhost:${CLUSTER_C1_1}
- ${QPID_CLUSTER_EXEC} --all-stop --force localhost:${CLUSTER_C2_1}
- fi
-}
-
-if test -d ${PYTHON_DIR} ; then
- start_brokers
- if [ -z ${CLUSTERING_ENABLED} ]; then
- echo "Running federation tests using brokers on local port ${LOCAL_PORT}, remote port ${REMOTE_PORT} (NOTE: clustering is DISABLED)"
- else
- echo "Running federation tests using brokers on local port ${LOCAL_PORT}, remote port ${REMOTE_PORT}, local cluster nodes ${CLUSTER_C1_1} ${CLUSTER_C1_2}, remote cluster nodes ${CLUSTER_C2_1} ${CLUSTER_C2_2}"
- fi
- if [ -z ${USE_LONG_TEST} ]; then
- echo "NOTE: To run a full set of federation system tests, use \"make check-long\". To test with persistence, run the store version of this script."
- fi
- ${QPID_PYTHON_TEST} -m ${MODULENAME} ${SKIPTESTS} -b localhost:${REMOTE_PORT} -Dlocal-port=${LOCAL_PORT} -Dremote-port=${REMOTE_PORT} -Dlocal-cluster-ports="${CLUSTER_C1_1} ${CLUSTER_C1_2}" -Dremote-cluster-ports="${CLUSTER_C2_1} ${CLUSTER_C2_2}" $@
- RETCODE=$?
- stop_brokers
- if test x${RETCODE} != x0; then
- echo "FAIL federation tests"; exit 1;
- fi
-fi
diff --git a/cpp/src/tests/run_federation_tests b/cpp/src/tests/run_federation_tests
index 14af4807ba..4be27a2e85 100755
--- a/cpp/src/tests/run_federation_tests
+++ b/cpp/src/tests/run_federation_tests
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
@@ -55,7 +55,7 @@ stop_brokers() {
if test -d ${PYTHON_DIR} ; then
start_brokers
echo "Running federation tests using brokers on ports $LOCAL_PORT $REMOTE_PORT $REMOTE_B1 $REMOTE_B2"
- $QPID_PYTHON_TEST -m federation "$SKIPTESTS" -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dextra-brokers="$REMOTE_B1 $REMOTE_B2" $@
+ $QPID_PYTHON_TEST -m federation $SKIPTESTS -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dextra-brokers="$REMOTE_B1 $REMOTE_B2" $@
RETCODE=$?
stop_brokers
if test x$RETCODE != x0; then
diff --git a/cpp/src/tests/run_header_test b/cpp/src/tests/run_header_test
index 34008132cc..07658343e7 100755
--- a/cpp/src/tests/run_header_test
+++ b/cpp/src/tests/run_header_test
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
diff --git a/cpp/src/tests/run_long_federation_sys_tests b/cpp/src/tests/run_long_federation_sys_tests
deleted file mode 100644
index 69dc08d11c..0000000000
--- a/cpp/src/tests/run_long_federation_sys_tests
+++ /dev/null
@@ -1,24 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Run the federation system tests (long version).
-
-./run_federation_sys_tests LONG_TEST $@
diff --git a/cpp/src/tests/run_msg_group_tests b/cpp/src/tests/run_msg_group_tests
deleted file mode 100755
index 8423022521..0000000000
--- a/cpp/src/tests/run_msg_group_tests
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-#script to run a sequence of message group queue tests via make
-
-#setup path to find qpid-config and msg_group_test progs
-source ./test_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`
-
-#trap cleanup INT TERM QUIT
-
-QUEUE_NAME="group-queue"
-GROUP_KEY="My-Group-Id"
-
-BROKER_URL="${QPID_BROKER:-localhost}:${QPID_PORT:-5672}"
-
-run_test() {
- $@
-}
-
-##set -x
-
-declare -i i=0
-declare -a tests
-tests=("qpid-config -a $BROKER_URL add queue $QUEUE_NAME --group-header=${GROUP_KEY} --shared-groups"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 3 --ack-frequency 7 --randomize-group-size --interleave 3"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 7 --ack-frequency 7 --randomize-group-size"
- "qpid-config -a $BROKER_URL add queue ${QUEUE_NAME}-two --group-header=${GROUP_KEY} --shared-groups"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 7 --ack-frequency 3 --randomize-group-size"
- "msg_group_test -b $BROKER_URL -a ${QUEUE_NAME}-two --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 3 --ack-frequency 7 --randomize-group-size --interleave 5"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 59 --group-size 5 --receivers 2 --senders 3 --capacity 1 --ack-frequency 3 --randomize-group-size"
- "qpid-config -a $BROKER_URL del queue ${QUEUE_NAME}-two --force"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 59 --group-size 3 --receivers 2 --senders 3 --capacity 1 --ack-frequency 1 --randomize-group-size"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 211 --group-size 13 --receivers 2 --senders 3 --capacity 47 --ack-frequency 79 --interleave 53"
- "qpid-config -a $BROKER_URL del queue $QUEUE_NAME --force")
-
-while [ -n "${tests[i]}" ]; do
- run_test ${tests[i]}
- RETCODE=$?
- if test x$RETCODE != x0; then
- echo "FAILED message group test. Failed command: \"${tests[i]}\"";
- exit 1;
- fi
- i+=1
-done
diff --git a/cpp/src/tests/run_msg_group_tests_soak b/cpp/src/tests/run_msg_group_tests_soak
deleted file mode 100755
index 5231f74755..0000000000
--- a/cpp/src/tests/run_msg_group_tests_soak
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-#script to run a sequence of long-running message group tests via make
-
-#setup path to find qpid-config and msg_group_test test progs
-source ./test_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`
-
-#trap cleanup INT TERM QUIT
-
-QUEUE_NAME="group-queue"
-GROUP_KEY="My-Group-Id"
-
-BROKER_URL="${QPID_BROKER:-localhost}:${QPID_PORT:-5672}"
-
-run_test() {
- $@
-}
-
-##set -x
-
-declare -i i=0
-declare -a tests
-tests=("qpid-config -a $BROKER_URL add queue $QUEUE_NAME --group-header=${GROUP_KEY} --shared-groups"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 47 --ack-frequency 97"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 79 --ack-frequency 79"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 97 --ack-frequency 47"
- "qpid-config -a $BROKER_URL del queue $QUEUE_NAME --force")
-
-while [ -n "${tests[i]}" ]; do
- run_test ${tests[i]}
- RETCODE=$?
- if test x$RETCODE != x0; then
- echo "FAILED message group test. Failed command: \"${tests[i]}\"";
- exit 1;
- fi
- i+=1
-done
diff --git a/cpp/src/tests/run_queue_flow_limit_tests b/cpp/src/tests/run_queue_flow_limit_tests
deleted file mode 100755
index f921cf5e7e..0000000000
--- a/cpp/src/tests/run_queue_flow_limit_tests
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/sh
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Run tests against Queue producer flow control.
-
-source ./test_env.sh
-test -d $PYTHON_DIR || { echo "Skipping queue flow control tests, no python dir."; exit 0; }
-
-LOG_FILE=queue_flow_limit_test.log
-PORT=""
-
-trap stop_broker INT TERM QUIT
-
-error() {
- echo $*
- exit 1;
-}
-
-start_broker() {
- # Note: if you change the DEFAULT_THRESHOLDS, you will need to update queue_flow_limit_tests.py
- DEFAULT_THRESHOLDS="--default-flow-stop-threshold=80 --default-flow-resume-threshold=70"
- rm -rf $LOG_FILE
- PORT=$($QPIDD_EXEC $DEFAULT_THRESHOLDS --auth=no --no-module-dir --daemon --port=0 -t --log-to-file $LOG_FILE) || error "Could not start broker"
-}
-
-stop_broker() {
- test -n "$PORT" && $QPIDD_EXEC --no-module-dir --quit --port $PORT
-}
-
-start_broker
-echo "Running Queue flow limit tests using broker on port $PORT"
-$QPID_PYTHON_TEST -m queue_flow_limit_tests $SKIPTESTS -b localhost:$PORT $@
-RETCODE=$?
-stop_broker
-if test x$RETCODE != x0; then
- echo "FAIL queue flow limit tests"; exit 1;
-fi
-rm -rf $LOG_FILE
-
diff --git a/cpp/src/tests/run_store_tests.ps1 b/cpp/src/tests/run_store_tests.ps1
index b2f0b1ccd8..76b46737f0 100644
--- a/cpp/src/tests/run_store_tests.ps1
+++ b/cpp/src/tests/run_store_tests.ps1
@@ -111,7 +111,7 @@ Invoke-Expression "$prog --quit --port $env:QPID_PORT" | Write-Output
# Test 2... store.py starts/stops/restarts its own brokers
$tests = "*"
-$env:PYTHONPATH="$PYTHON_DIR;$QMF_LIB;$srcdir"
+$env:PYTHONPATH="$PYTHON_DIR;$srcdir"
$env:QPIDD_EXEC="$prog"
$env:STORE_LIB="$store_dir\store$suffix.dll"
if ($test_store -eq "MSSQL") {
diff --git a/cpp/src/tests/run_test b/cpp/src/tests/run_test
index 6ec1fd892b..4b227621bc 100755
--- a/cpp/src/tests/run_test
+++ b/cpp/src/tests/run_test
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
diff --git a/cpp/src/tests/sasl.mk b/cpp/src/tests/sasl.mk
index 69b24c3f8a..5b8419f604 100644
--- a/cpp/src/tests/sasl.mk
+++ b/cpp/src/tests/sasl.mk
@@ -30,21 +30,9 @@ check_PROGRAMS+=sasl_version
sasl_version_SOURCES=sasl_version.cpp
sasl_version_LDADD=$(lib_client)
-TESTS += run_cluster_authentication_test sasl_fed sasl_fed_ex_dynamic sasl_fed_ex_link sasl_fed_ex_queue sasl_fed_ex_route sasl_fed_ex_route_cluster sasl_fed_ex_link_cluster sasl_fed_ex_queue_cluster sasl_fed_ex_dynamic_cluster sasl_no_dir
+TESTS += run_cluster_authentication_test sasl_fed sasl_fed_ex
LONG_TESTS += run_cluster_authentication_soak
-EXTRA_DIST += run_cluster_authentication_test \
- sasl_fed \
- sasl_fed_ex \
- run_cluster_authentication_soak \
- sasl_fed_ex_dynamic \
- sasl_fed_ex_link \
- sasl_fed_ex_queue \
- sasl_fed_ex_route \
- sasl_fed_ex_dynamic_cluster \
- sasl_fed_ex_link_cluster \
- sasl_fed_ex_queue_cluster \
- sasl_fed_ex_route_cluster \
- sasl_no_dir
+EXTRA_DIST += run_cluster_authentication_test sasl_fed sasl_fed_ex run_cluster_authentication_soak
endif # HAVE_SASL
diff --git a/cpp/src/tests/sasl_fed b/cpp/src/tests/sasl_fed
index 884c44177c..9845a20838 100755
--- a/cpp/src/tests/sasl_fed
+++ b/cpp/src/tests/sasl_fed
@@ -123,7 +123,7 @@ n_messages=100
#--------------------------------------------------
#echo " Sending 100 messages to $broker_1_port "
#--------------------------------------------------
-$builddir/datagen --count $n_messages | $SENDER_EXEC --mechanism DIGEST-MD5 --username zag --password zag --exchange $EXCHANGE_NAME --routing-key $ROUTING_KEY --port $broker_1_port
+$builddir/datagen --count $n_messages | $SENDER_EXEC --username zag --password zag --exchange $EXCHANGE_NAME --routing-key $ROUTING_KEY --port $broker_1_port
sleep 5
diff --git a/cpp/src/tests/sasl_fed_ex b/cpp/src/tests/sasl_fed_ex
index 716a806874..0740650d6c 100755
--- a/cpp/src/tests/sasl_fed_ex
+++ b/cpp/src/tests/sasl_fed_ex
@@ -19,52 +19,22 @@
# under the License.
#
+
#===============================================================================
-# These tests create federated links between two brokers using SASL security.
+# This test creates a federated link between two brokers using SASL security.
# The SASL mechanism used is EXTERNAL, which is satisfied by SSL
# transport-layer security.
#===============================================================================
source ./test_env.sh
-script_name=`basename $0`
-
-if [ $# -lt 1 ] || [ $# -gt 2 ]
-then
- echo
- # These are the four different ways of creating links ( or routes+links )
- # that the qpid-route command provides.
- echo "Usage: ${script_name} dynamic|link|queue|route [cluster]"
- echo
- exit 1
-fi
-
-# Has the user told us to do clustering ? -----------
-clustering_flag=
-if [ $# -eq "2" ] && [ "$2" == "cluster" ]; then
- clustering_flag=true
-fi
-
-qpid_route_method=$1
-
-# Debugging print. --------------------------
-debug=
-function print {
- if [ "$debug" ]; then
- echo "${script_name}: $1"
- fi
-}
-
-print "=========== start sasl_fed_ex $* ============"
-
-
# This minimum value corresponds to sasl version 2.1.22
minimum_sasl_version=131350
sasl_version=`$QPID_TEST_EXEC_DIR/sasl_version`
-# This test is necessary because this sasl version is the first one that permits
+# This test is necessary becasue this sasl version is the first one that permits
# redirection of the sasl config file path.
if [ "$sasl_version" -lt "$minimum_sasl_version" ]; then
echo "sasl_fed: must have sasl version 2.1.22 or greater. ( Integer value: $minimum_sasl_version ) Version is: $sasl_version"
@@ -90,7 +60,6 @@ create_certs() {
delete_certs() {
if [[ -e ${CERT_DIR} ]] ; then
- print "removing cert dir ${CERT_DIR}"
rm -rf ${CERT_DIR}
fi
}
@@ -103,40 +72,22 @@ if [[ !(-x $CERTUTIL) ]] ; then
fi
delete_certs
-create_certs 2> /dev/null
-if [ ! $? ]; then
- error "Could not create test certificate"
- exit 1
-fi
+create_certs || error "Could not create test certificate"
-sasl_config_dir=$builddir/sasl_config
-tmp_root=${builddir}/sasl_fed_ex_temp
-print "results dir is ${tmp_root}"
-rm -rf ${tmp_root}
+sasl_config_file=$builddir/sasl_config
+
+my_random_number=$RANDOM
+tmp_root=/tmp/sasl_fed_$my_random_number
mkdir -p $tmp_root
SRC_SSL_PORT=6667
DST_SSL_PORT=6666
-SRC_SSL_PORT_2=6668
-DST_SSL_PORT_2=6669
-
SRC_TCP_PORT=5801
DST_TCP_PORT=5807
-SRC_TCP_PORT_2=5802
-DST_TCP_PORT_2=5803
-
-CLUSTER_NAME_SUFFIX=`hostname | tr '.' ' ' | awk '{print $1}'`
-CLUSTER_1_NAME=sasl_fed_ex_cluster_1_${CLUSTER_NAME_SUFFIX}
-CLUSTER_2_NAME=sasl_fed_ex_cluster_2_${CLUSTER_NAME_SUFFIX}
-
-print "CLUSTER_1_NAME == ${CLUSTER_1_NAME}"
-print "CLUSTER_2_NAME == ${CLUSTER_2_NAME}"
-
-SSL_LIB=${moduledir}/ssl.so
-CLUSTER_LIB=${moduledir}/cluster.so
+SSL_LIB=../.libs/ssl.so
export QPID_SSL_CERT_NAME=${TEST_HOSTNAME}
@@ -165,112 +116,52 @@ export QPID_SSL_CERT_NAME=${TEST_HOSTNAME}
# 5. DST pulls messages off the temp queue on SRC to itself.
#
-COMMON_BROKER_OPTIONS=" \
- --ssl-sasl-no-dict \
- --sasl-config=$sasl_config_dir \
- --ssl-require-client-authentication \
- --auth yes \
- --ssl-cert-db $CERT_DIR \
- --ssl-cert-password-file $CERT_PW_FILE \
- --ssl-cert-name $TEST_HOSTNAME \
- --no-data-dir \
- --no-module-dir \
- --load-module ${SSL_LIB} \
- --mgmt-enable=yes \
- --log-enable info+ \
- --log-source yes \
- --daemon "
-
-
-function start_brokers {
- if [ $1 ]; then
- # clustered ----------------------------------------
- print "Starting SRC cluster"
-
- print " src broker 1"
- $QPIDD_EXEC \
- --port=${SRC_TCP_PORT} \
- --ssl-port ${SRC_SSL_PORT} \
- ${COMMON_BROKER_OPTIONS} \
- --load-module ${CLUSTER_LIB} \
- --cluster-name ${CLUSTER_1_NAME} \
- --log-to-file $tmp_root/qpidd_src.log 2> /dev/null
-
- broker_ports[0]=${SRC_TCP_PORT}
-
- print " src broker 2"
- $QPIDD_EXEC \
- --port=${SRC_TCP_PORT_2} \
- --ssl-port ${SRC_SSL_PORT_2} \
- ${COMMON_BROKER_OPTIONS} \
- --load-module ${CLUSTER_LIB} \
- --cluster-name ${CLUSTER_1_NAME} \
- --log-to-file $tmp_root/qpidd_src_2.log 2> /dev/null
-
- broker_ports[1]=${SRC_TCP_PORT_2}
-
-
- print "Starting DST cluster"
-
- print " dst broker 1"
- $QPIDD_EXEC \
- --port=${DST_TCP_PORT} \
- --ssl-port ${DST_SSL_PORT} \
- ${COMMON_BROKER_OPTIONS} \
- --load-module ${CLUSTER_LIB} \
- --cluster-name ${CLUSTER_2_NAME} \
- --log-to-file $tmp_root/qpidd_dst.log 2> /dev/null
-
- broker_ports[2]=${DST_TCP_PORT}
-
- print " dst broker 2"
- $QPIDD_EXEC \
- --port=${DST_TCP_PORT_2} \
- --ssl-port ${DST_SSL_PORT_2} \
- ${COMMON_BROKER_OPTIONS} \
- --load-module ${CLUSTER_LIB} \
- --cluster-name ${CLUSTER_2_NAME} \
- --log-to-file $tmp_root/qpidd_dst_2.log 2> /dev/null
-
- broker_ports[3]=${DST_TCP_PORT_2}
-
- else
- # vanilla brokers --------------------------------
- print "Starting SRC broker"
- $QPIDD_EXEC \
- --port=${SRC_TCP_PORT} \
- --ssl-port ${SRC_SSL_PORT} \
- ${COMMON_BROKER_OPTIONS} \
- --log-to-file $tmp_root/qpidd_src.log 2> /dev/null
-
- broker_ports[0]=${SRC_TCP_PORT}
-
- print "Starting DST broker"
- $QPIDD_EXEC \
- --port=${DST_TCP_PORT} \
- --ssl-port ${DST_SSL_PORT} \
- ${COMMON_BROKER_OPTIONS} \
- --log-to-file $tmp_root/qpidd_dst.log 2> /dev/null
-
- broker_ports[1]=${DST_TCP_PORT}
- fi
-}
-
-function halt_brokers {
- n_brokers=${#broker_ports[@]}
- print "Halting ${n_brokers} brokers."
- for i in $(seq 0 $((${n_brokers} - 1)))
- do
- halt_port=${broker_ports[$i]}
- print "Halting broker $i on port ${halt_port}"
- $QPIDD_EXEC --port ${halt_port} --quit
- done
-
-}
-
-start_brokers $clustering_flag
+#echo "-----------------------"
+#echo "Starting SRC broker"
+#echo "-----------------------"
+$QPIDD_EXEC \
+ --port=${SRC_TCP_PORT} \
+ --ssl-port ${SRC_SSL_PORT} \
+ --ssl-sasl-no-dict \
+ --sasl-config=$sasl_config_file \
+ --ssl-require-client-authentication \
+ --auth yes \
+ --ssl-cert-db $CERT_DIR \
+ --ssl-cert-password-file $CERT_PW_FILE \
+ --ssl-cert-name $TEST_HOSTNAME \
+ --no-data-dir \
+ --no-module-dir \
+ --load-module ${SSL_LIB} \
+ --mgmt-enable=yes \
+ --log-enable info+ \
+ --log-source yes \
+ --daemon \
+ --log-to-file $tmp_root/qpidd_src.log 2> /dev/null
+
+
+#echo "-----------------------"
+#echo "Starting DST broker"
+#echo "-----------------------"
+$QPIDD_EXEC \
+ --port=${DST_TCP_PORT} \
+ --ssl-port ${DST_SSL_PORT} \
+ --ssl-cert-db $CERT_DIR \
+ --ssl-cert-password-file $CERT_PW_FILE \
+ --ssl-cert-name $TEST_HOSTNAME \
+ --ssl-sasl-no-dict \
+ --ssl-require-client-authentication \
+ --sasl-config=$sasl_config_file \
+ --no-data-dir \
+ --no-module-dir \
+ --load-module ${SSL_LIB} \
+ --mgmt-enable=yes \
+ --log-enable info+ \
+ --log-source yes \
+ --daemon \
+ $COMMON_BROKER_OPTIONS \
+ --log-to-file $tmp_root/qpidd_dst.log 2> /dev/null
# I am not randomizing these names, because this test creates its own brokers.
@@ -279,83 +170,76 @@ ROUTING_KEY=sasl_fed_queue
EXCHANGE_NAME=sasl_fedex
-print "add exchanges"
+#echo "-----------------------"
+#echo "add exchanges"
+#echo "-----------------------"
$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} add exchange direct $EXCHANGE_NAME
$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} add exchange direct $EXCHANGE_NAME
-print "add queues"
+#echo "-----------------------"
+#echo "add queues"
+#echo "-----------------------"
$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} add queue $QUEUE_NAME
$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} add queue $QUEUE_NAME
-print "create bindings"
+#echo "-----------------------"
+#echo "create bindings"
+#echo "-----------------------"
$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
-#
+#echo "-----------------------"
+#echo "qpid-route route add"
+#echo "-----------------------"
# NOTE: The SRC broker *must* be referred to as $TEST_HOSTNAME, and not as "localhost".
# It must be referred to by the exact string given as the Common Name (CN) in the cert,
# which was created in the function create_certs, above.
+$QPID_ROUTE_EXEC route add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} -t ssl $EXCHANGE_NAME $ROUTING_KEY "" "" EXTERNAL
+#echo "-----------------------"
+#echo "view the route :"
+#echo "-----------------------"
+#$PYTHON_COMMANDS/qpid-route route list localhost:${DST_TCP_PORT}
+# I don't know how to avoid this sleep yet. It has to come after route-creation.
+sleep 5
-#----------------------------------------------------------------
-# Use qpid-route to create the link, or the link+route, depending
-# on which of its several methods was requested.
-#----------------------------------------------------------------
-if [ ${qpid_route_method} == "dynamic" ]; then
- print "dynamic add"
- $QPID_ROUTE_EXEC -t ssl dynamic add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME "" "" EXTERNAL
-elif [ ${qpid_route_method} == "link" ]; then
- print "link add"
- $QPID_ROUTE_EXEC -t ssl link add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} EXTERNAL
-elif [ ${qpid_route_method} == "queue" ]; then
- print "queue add"
- $QPID_ROUTE_EXEC -t ssl queue add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME $ROUTING_KEY EXTERNAL
-elif [ ${qpid_route_method} == "route" ]; then
- print "route add"
- $QPID_ROUTE_EXEC -t ssl route add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME $ROUTING_KEY "" "" EXTERNAL
-else
- echo "unknown method: |${qpid_route_method}|"
- echo " choices are: dynamic|link|queue|route "
- halt_brokers
- exit 1
-fi
+n_messages=100
+./datagen --count ${n_messages} | ./sender --broker localhost --port ${SRC_TCP_PORT} --exchange ${EXCHANGE_NAME} --routing-key ${ROUTING_KEY} --mechanism ANONYMOUS
-# I don't know how to avoid this sleep yet. It has to come after route-creation
-# to avoid false negatives.
-sleep 5
-# This should work the same whether or not we are running a clustered test.
-# In the case of clustered tests, the status is not printed by qpid_route.
-# So in either case, I will look only at the transport field, which should be "ssl".
-print "check the link"
-link_status=$($QPID_ROUTE_EXEC link list localhost:${DST_TCP_PORT} | tail -1 | awk '{print $3}')
+#echo "-----------------------"
+#echo "Examine DST Broker"
+#echo "-----------------------"
+dst_message_count=`qpid-stat -q localhost:${DST_TCP_PORT} | grep sasl_fed_queue | awk '{print $2}'`
-halt_brokers
-sleep 1
+#echo "-----------------------"
+#echo "Asking brokers to quit."
+#echo "-----------------------"
+$QPIDD_EXEC --port ${SRC_TCP_PORT} --quit
+$QPIDD_EXEC --port ${DST_TCP_PORT} --quit
-if [ ! ${link_status} ]; then
- print "link_status is empty"
- print "result: fail"
- exit 2
-fi
-if [ ${link_status} == "ssl" ]; then
- print "result: good"
- # Only remove the tmp_root on success, to permit debugging.
- print "Removing temporary directory $tmp_root"
- rm -rf $tmp_root
+#echo "-----------------------"
+#echo "Removing temporary directory $tmp_root"
+#echo "-----------------------"
+rm -rf $tmp_root
+
+if [ "$dst_message_count" -eq "$n_messages" ]; then
+ #echo "good: |$dst_message_count| == |$n_messages|"
exit 0
+else
+ #echo "not ideal: |$dst_message_count| != |$n_messages|"
+ exit 1
fi
-print "link_status has a bad value: ${link_status}"
-print "result: fail"
-exit 3
+
+
diff --git a/cpp/src/tests/sasl_fed_ex_dynamic b/cpp/src/tests/sasl_fed_ex_dynamic
deleted file mode 100755
index c20b8d69a0..0000000000
--- a/cpp/src/tests/sasl_fed_ex_dynamic
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-
-${srcdir}/sasl_fed_ex dynamic
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_dynamic_cluster b/cpp/src/tests/sasl_fed_ex_dynamic_cluster
deleted file mode 100755
index b0cceccecb..0000000000
--- a/cpp/src/tests/sasl_fed_ex_dynamic_cluster
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-source $srcdir/ais_check
-
-with_ais_group ${srcdir}/sasl_fed_ex dynamic cluster
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_link b/cpp/src/tests/sasl_fed_ex_link
deleted file mode 100755
index 7b232d4874..0000000000
--- a/cpp/src/tests/sasl_fed_ex_link
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-
-${srcdir}/sasl_fed_ex link
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_link_cluster b/cpp/src/tests/sasl_fed_ex_link_cluster
deleted file mode 100755
index 4139300b12..0000000000
--- a/cpp/src/tests/sasl_fed_ex_link_cluster
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-source $srcdir/ais_check
-
-with_ais_group ${srcdir}/sasl_fed_ex link cluster
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_queue b/cpp/src/tests/sasl_fed_ex_queue
deleted file mode 100755
index be0c10cf63..0000000000
--- a/cpp/src/tests/sasl_fed_ex_queue
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-
-${srcdir}/sasl_fed_ex queue
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_queue_cluster b/cpp/src/tests/sasl_fed_ex_queue_cluster
deleted file mode 100755
index f251420e08..0000000000
--- a/cpp/src/tests/sasl_fed_ex_queue_cluster
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-source ${srcdir}/ais_check
-
-with_ais_group ${srcdir}/sasl_fed_ex queue cluster
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_route b/cpp/src/tests/sasl_fed_ex_route
deleted file mode 100755
index dd5c4f3cac..0000000000
--- a/cpp/src/tests/sasl_fed_ex_route
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-
-${srcdir}/sasl_fed_ex route
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_route_cluster b/cpp/src/tests/sasl_fed_ex_route_cluster
deleted file mode 100755
index a5d1542def..0000000000
--- a/cpp/src/tests/sasl_fed_ex_route_cluster
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-source ${srcdir}/ais_check
-
-with_ais_group ${srcdir}/sasl_fed_ex route cluster
-
-
diff --git a/cpp/src/tests/sasl_no_dir b/cpp/src/tests/sasl_no_dir
deleted file mode 100755
index 15a36014bb..0000000000
--- a/cpp/src/tests/sasl_no_dir
+++ /dev/null
@@ -1,218 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-source ./test_env.sh
-
-script_name=`basename $0`
-
-# This minimum value corresponds to sasl version 2.1.22
-minimum_sasl_version=131350
-
-sasl_version=`$QPID_TEST_EXEC_DIR/sasl_version`
-
-# This test is necessary because this sasl version is the first one that permits
-# redirection of the sasl config file path.
-if [ "$sasl_version" -lt "$minimum_sasl_version" ]; then
- echo "sasl_fed: must have sasl version 2.1.22 or greater. ( Integer value: $minimum_sasl_version ) Version is: $sasl_version"
- exit 0
-fi
-
-
-sasl_config_dir=$builddir/sasl_config
-
-
-# Debugging print. --------------------------
-debug=
-function print {
- if [ "$debug" ]; then
- echo "${script_name}: $1"
- fi
-}
-
-
-my_random_number=$RANDOM
-tmp_root=/tmp/sasl_fed_$my_random_number
-mkdir -p $tmp_root
-
-
-LOG_FILE=$tmp_root/qpidd.log
-
-# If you want to see this test fail, just comment out this 'mv' command.
-print "Moving sasl configuration dir."
-mv ${sasl_config_dir} ${sasl_config_dir}-
-
-
-#--------------------------------------------------
-print " Starting broker"
-#--------------------------------------------------
-$QPIDD_EXEC \
- -p 0 \
- --no-data-dir \
- --auth=yes \
- --mgmt-enable=yes \
- --log-enable info+ \
- --log-source yes \
- --log-to-file ${LOG_FILE} \
- --sasl-config=$sasl_config_dir \
- -d 2> /dev/null 1> $tmp_root/broker_port
-
-
-
-# If it works right, the output will look something like this: ( two lines long )
-# Daemon startup failed: SASL: sasl_set_path failed: no such directory: /home/mick/trunk/qpid/cpp/src/tests/sasl_config (qpid/broker/SaslAuthenticator.cpp:112)
-# 2011-10-13 14:07:00 critical qpidd.cpp:83: Unexpected error: Daemon startup failed: SASL: sasl_set_path failed: no such directory: /home/mick/trunk/qpid/cpp/src/tests/sasl_config (qpid/broker/SaslAuthenticator.cpp:112)
-
-result=`cat ${LOG_FILE} | grep "sasl_set_path failed: no such directory" | wc -l `
-
-#--------------------------------------------------
-print "Restore the Sasl config dir to its original place."
-#--------------------------------------------------
-mv ${sasl_config_dir}- ${sasl_config_dir}
-
-if [ "2" -eq ${result} ]; then
- print "result: success"
- rm -rf $tmp_root
- exit 0
-fi
-
-
-# If this test fails, the broker is still alive.
-# Kill it.
-broker_port=`cat $tmp_root/broker_port`
-#--------------------------------------------------
-print "Asking broker to quit."
-#--------------------------------------------------
-$QPIDD_EXEC --port $broker_port --quit
-
-rm -rf $tmp_root
-
-print "result: fail"
-exit 1
-
-#! /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.
-#
-
-source ./test_env.sh
-
-script_name=`basename $0`
-
-# This minimum value corresponds to sasl version 2.1.22
-minimum_sasl_version=131350
-
-sasl_version=`$QPID_TEST_EXEC_DIR/sasl_version`
-
-# This test is necessary because this sasl version is the first one that permits
-# redirection of the sasl config file path.
-if [ "$sasl_version" -lt "$minimum_sasl_version" ]; then
- echo "sasl_fed: must have sasl version 2.1.22 or greater. ( Integer value: $minimum_sasl_version ) Version is: $sasl_version"
- exit 0
-fi
-
-
-sasl_config_dir=$builddir/sasl_config
-
-
-# Debugging print. --------------------------
-debug=
-function print {
- if [ "$debug" ]; then
- echo "${script_name}: $1"
- fi
-}
-
-
-my_random_number=$RANDOM
-tmp_root=/tmp/sasl_fed_$my_random_number
-mkdir -p $tmp_root
-
-
-LOG_FILE=$tmp_root/qpidd.log
-
-# If you want to see this test fail, just comment out this 'mv' command.
-print "Moving sasl configuration dir."
-mv ${sasl_config_dir} ${sasl_config_dir}-
-
-
-#--------------------------------------------------
-print " Starting broker"
-#--------------------------------------------------
-$QPIDD_EXEC \
- -p 0 \
- --no-data-dir \
- --auth=yes \
- --mgmt-enable=yes \
- --log-enable info+ \
- --log-source yes \
- --log-to-file ${LOG_FILE} \
- --sasl-config=$sasl_config_dir \
- -d 2> /dev/null 1> $tmp_root/broker_port
-
-
-
-# If it works right, the output will look something like this: ( two lines long )
-# Daemon startup failed: SASL: sasl_set_path failed: no such directory: /home/mick/trunk/qpid/cpp/src/tests/sasl_config (qpid/broker/SaslAuthenticator.cpp:112)
-# 2011-10-13 14:07:00 critical qpidd.cpp:83: Unexpected error: Daemon startup failed: SASL: sasl_set_path failed: no such directory: /home/mick/trunk/qpid/cpp/src/tests/sasl_config (qpid/broker/SaslAuthenticator.cpp:112)
-
-result=`cat ${LOG_FILE} | grep "sasl_set_path failed: no such directory" | wc -l `
-
-#--------------------------------------------------
-print "Restore the Sasl config dir to its original place."
-#--------------------------------------------------
-mv ${sasl_config_dir}- ${sasl_config_dir}
-
-if [ "2" -eq ${result} ]; then
- print "result: success"
- rm -rf $tmp_root
- exit 0
-fi
-
-
-# If this test fails, the broker is still alive.
-# Kill it.
-broker_port=`cat $tmp_root/broker_port`
-#--------------------------------------------------
-print "Asking broker to quit."
-#--------------------------------------------------
-$QPIDD_EXEC --port $broker_port --quit
-
-rm -rf $tmp_root
-
-print "result: fail"
-exit 1
-
diff --git a/cpp/src/tests/sasl_test_setup.sh b/cpp/src/tests/sasl_test_setup.sh
index 3e69c0f02b..6395ba6ec3 100755
--- a/cpp/src/tests/sasl_test_setup.sh
+++ b/cpp/src/tests/sasl_test_setup.sh
@@ -30,7 +30,6 @@ pwcheck_method: auxprop
auxprop_plugin: sasldb
sasldb_path: $PWD/sasl_config/qpidd.sasldb
sql_select: dummy select
-mech_list: ANONYMOUS PLAIN DIGEST-MD5 EXTERNAL
EOF
# Populate temporary sasl db.
diff --git a/cpp/src/tests/sender.cpp b/cpp/src/tests/sender.cpp
index 063b5e87dc..9850e851da 100644
--- a/cpp/src/tests/sender.cpp
+++ b/cpp/src/tests/sender.cpp
@@ -120,7 +120,7 @@ void Sender::execute(AsyncSession& session, bool isRetry)
string data;
while (getline(std::cin, data)) {
message.setData(data);
- //message.getHeaders().setInt("SN", ++sent);
+ message.getHeaders().setInt("SN", ++sent);
string matchKey;
if (lvqMatchValues && getline(lvqMatchValues, matchKey)) {
message.getHeaders().setString(QueueOptions::strLVQMatchProperty, matchKey);
diff --git a/cpp/src/tests/ssl_test b/cpp/src/tests/ssl_test
index 2a56c0b80e..04584f169d 100755
--- a/cpp/src/tests/ssl_test
+++ b/cpp/src/tests/ssl_test
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
@@ -47,13 +47,9 @@ delete_certs() {
fi
}
-COMMON_OPTS="--daemon --no-data-dir --no-module-dir --config $CONFIG --load-module $SSL_LIB --ssl-cert-db $CERT_DIR --ssl-cert-password-file $CERT_PW_FILE --ssl-cert-name $TEST_HOSTNAME --require-encryption"
+COMMON_OPTS="--daemon --no-data-dir --no-module-dir --auth no --config $CONFIG --load-module $SSL_LIB --ssl-cert-db $CERT_DIR --ssl-cert-password-file $CERT_PW_FILE --ssl-cert-name $TEST_HOSTNAME --require-encryption"
start_broker() { # $1 = extra opts
- ../qpidd --transport ssl --port 0 --ssl-port 0 $COMMON_OPTS --auth no $1;
-}
-
-start_authenticating_broker() {
- ../qpidd --transport ssl --port 0 --ssl-port 0 $COMMON_OPTS --ssl-sasl-no-dict --ssl-require-client-authentication --auth yes;
+ ../qpidd --transport ssl --port 0 --ssl-port 0 $COMMON_OPTS $1;
}
stop_brokers() {
@@ -97,7 +93,7 @@ test "$MSG" = "hello" || { echo "receive failed '$MSG' != 'hello'"; exit 1; }
#### Client Authentication tests
-PORT2=`start_authenticating_broker` || error "Could not start broker"
+PORT2=`start_broker --ssl-require-client-authentication` || error "Could not start broker"
echo "Running SSL client authentication test on port $PORT2"
URL=amqp:ssl:$TEST_HOSTNAME:$PORT2
@@ -125,7 +121,7 @@ pick_port() {
echo $PICK
}
ssl_cluster_broker() { # $1 = port
- ../qpidd $COMMON_OPTS --auth no --load-module $CLUSTER_LIB --cluster-name ssl_test.$HOSTNAME.$$ --cluster-url amqp:ssl:$TEST_HOSTNAME:$1 --port 0 --ssl-port $1 --transport ssl > /dev/null
+ ../qpidd $COMMON_OPTS --load-module $CLUSTER_LIB --cluster-name ssl_test.$HOSTNAME.$$ --cluster-url amqp:ssl:$TEST_HOSTNAME:$1 --port 0 --ssl-port $1 --transport ssl > /dev/null
# Wait for broker to be ready
qpid-ping -Pssl -b $TEST_HOSTNAME -qp $1 || { echo "Cannot connect to broker on $1"; exit 1; }
echo "Running SSL cluster broker on port $1"
diff --git a/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp b/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp
index 024f20b147..a0b665db73 100644
--- a/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp
+++ b/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp
@@ -26,9 +26,7 @@
// include this file with the executable being built. If the default
// behaviors are desired, don't include this file in the build.
-#if defined(_MSC_VER)
#include <crtdbg.h>
-#endif
#include <windows.h>
#include <iostream>
@@ -55,14 +53,12 @@ static redirect_errors_to_stderr block;
redirect_errors_to_stderr::redirect_errors_to_stderr()
{
-#if defined(_MSC_VER)
_CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR);
_CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_FILE);
_CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDERR);
_CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR);
-#endif
// Prevent the system from displaying the critical-error-handler
// and can't-open-file message boxes.
diff --git a/cpp/src/windows/QpiddBroker.cpp b/cpp/src/windows/QpiddBroker.cpp
index 60a31901bd..884cdc366b 100644
--- a/cpp/src/windows/QpiddBroker.cpp
+++ b/cpp/src/windows/QpiddBroker.cpp
@@ -21,12 +21,12 @@
#include "config.h"
#include "qpidd.h"
+#include "SCM.h"
#include "qpid/Exception.h"
#include "qpid/Options.h"
#include "qpid/Plugin.h"
#include "qpid/sys/IntegerTypes.h"
#include "qpid/sys/windows/check.h"
-#include "qpid/sys/windows/SCM.h"
#include "qpid/broker/Broker.h"
#include <iostream>
@@ -147,7 +147,7 @@ NamedSharedMemory<T>::NamedSharedMemory(const std::string& n) :
name(n),
memory(NULL),
data(0)
-{}
+{};
template <typename T>
NamedSharedMemory<T>::~NamedSharedMemory() {
@@ -155,7 +155,7 @@ NamedSharedMemory<T>::~NamedSharedMemory() {
::UnmapViewOfFile(data);
if (memory != NULL)
::CloseHandle(memory);
-}
+};
template <typename T>
T& NamedSharedMemory<T>::create() {
@@ -291,12 +291,12 @@ struct ServiceOptions : public qpid::Options {
depends("")
{
addOptions()
- ("install", qpid::optValue(install), "Install as service.")
- ("start-type", qpid::optValue(startType, "auto|demand|disabled"), "Service start type.\nApplied at install time only.")
+ ("install", qpid::optValue(install), "Install as service")
+ ("start-type", qpid::optValue(startType, "auto|demand|disabled"), "Service start type\nApplied at install time only.")
("arguments", qpid::optValue(startArgs, "COMMAND LINE ARGS"), "Arguments to pass when service auto-starts")
- ("account", qpid::optValue(account, "ACCOUNT"), "Account to run as.\nApplied at install time only.")
- ("password", qpid::optValue(password, "PASSWORD"), "Account password, if needed.\nApplied at install time only.")
- ("depends", qpid::optValue(depends, "(comma delimited list)"), "Names of services that must start before this service.\nApplied at install time only.")
+ ("account", qpid::optValue(account, "(LocalService)"), "Account to run as, default is LocalService\nApplied at install time only.")
+ ("password", qpid::optValue(password, "PASSWORD"), "Account password, if needed\nApplied at install time only.")
+ ("depends", qpid::optValue(depends, "(comma delimited list)"), "Names of services that must start before this service\nApplied at install time only.")
("start", qpid::optValue(start), "Start the service.")
("stop", qpid::optValue(stop), "Stop the service.")
("uninstall", qpid::optValue(uninstall), "Uninstall the service.");
diff --git a/cpp/src/qpid/sys/windows/SCM.cpp b/cpp/src/windows/SCM.cpp
index 4d2c74d4b9..232bb04c17 100644
--- a/cpp/src/qpid/sys/windows/SCM.cpp
+++ b/cpp/src/windows/SCM.cpp
@@ -1,332 +1,332 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/log/Statement.h"
-#include "qpid/sys/windows/check.h"
-#include "SCM.h"
-
-#pragma comment(lib, "advapi32.lib")
-
-namespace {
-
-// Container that will close a SC_HANDLE upon destruction.
-class AutoServiceHandle {
-public:
- AutoServiceHandle(SC_HANDLE h_ = NULL) : h(h_) {}
- ~AutoServiceHandle() { if (h != NULL) ::CloseServiceHandle(h); }
- void release() { h = NULL; }
- void reset(SC_HANDLE newHandle)
- {
- if (h != NULL)
- ::CloseServiceHandle(h);
- h = newHandle;
- }
- operator SC_HANDLE() const { return h; }
-
-private:
- SC_HANDLE h;
-};
-
-}
-
-namespace qpid {
-namespace windows {
-
-SCM::SCM() : scmHandle(NULL)
-{
-}
-
-SCM::~SCM()
-{
- if (NULL != scmHandle)
- ::CloseServiceHandle(scmHandle);
-}
-
-/**
- * Install this executable as a service
- */
-void SCM::install(const string& serviceName,
- const string& serviceDesc,
- const string& args,
- DWORD startType,
- const string& account,
- const string& password,
- const string& depends)
-{
- // Handle dependent service name list; Windows wants a set of nul-separated
- // names ending with a double nul.
- string depends2 = depends;
- if (!depends2.empty()) {
- // CDL to null delimiter w/ trailing double null
- size_t p = 0;
- while ((p = depends2.find_first_of( ',', p)) != string::npos)
- depends2.replace(p, 1, 1, '\0');
- depends2.push_back('\0');
- depends2.push_back('\0');
- }
-
-#if 0
- // I'm nervous about adding a user/password check here. Is this a
- // potential attack vector, letting users check passwords without
- // control? -Steve Huston, Feb 24, 2011
-
- // Validate account, password
- HANDLE hToken = NULL;
- bool logStatus = false;
- if (!account.empty() && !password.empty() &&
- !(logStatus = ::LogonUserA(account.c_str(),
- "",
- password.c_str(),
- LOGON32_LOGON_NETWORK,
- LOGON32_PROVIDER_DEFAULT,
- &hToken ) != 0))
- std::cout << "warning: supplied account & password failed with LogonUser." << std::endl;
- if (logStatus)
- ::CloseHandle(hToken);
-#endif
-
- // Get fully qualified .exe name
- char myPath[MAX_PATH];
- DWORD myPathLength = ::GetModuleFileName(NULL, myPath, MAX_PATH);
- QPID_WINDOWS_CHECK_NOT(myPathLength, 0);
- string imagePath(myPath, myPathLength);
- if (!args.empty())
- imagePath += " " + args;
-
- // Ensure there's a handle to the SCM database.
- openSvcManager();
-
- // Create the service
- SC_HANDLE svcHandle;
- svcHandle = ::CreateService(scmHandle, // SCM database
- serviceName.c_str(), // name of service
- serviceDesc.c_str(), // name to display
- SERVICE_ALL_ACCESS, // desired access
- SERVICE_WIN32_OWN_PROCESS, // service type
- startType, // start type
- SERVICE_ERROR_NORMAL, // error cntrl type
- imagePath.c_str(), // path to service's binary w/ optional arguments
- NULL, // no load ordering group
- NULL, // no tag identifier
- depends2.empty() ? NULL : depends2.c_str(),
- account.empty() ? NULL : account.c_str(), // account name, or NULL for LocalSystem
- password.empty() ? NULL : password.c_str()); // password, or NULL for none
- QPID_WINDOWS_CHECK_NULL(svcHandle);
- ::CloseServiceHandle(svcHandle);
- QPID_LOG(info, "Service installed successfully");
-}
-
-/**
- *
- */
-void SCM::uninstall(const string& serviceName)
-{
- // Ensure there's a handle to the SCM database.
- openSvcManager();
- AutoServiceHandle svc(::OpenService(scmHandle,
- serviceName.c_str(),
- DELETE));
- QPID_WINDOWS_CHECK_NULL((SC_HANDLE)svc);
- QPID_WINDOWS_CHECK_NOT(::DeleteService(svc), 0);
- QPID_LOG(info, "Service deleted successfully.");
-}
-
-/**
- * Attempt to start the service.
- */
-void SCM::start(const string& serviceName)
-{
- // Ensure we have a handle to the SCM database.
- openSvcManager();
-
- // Get a handle to the service.
- AutoServiceHandle svc(::OpenService(scmHandle,
- serviceName.c_str(),
- SERVICE_ALL_ACCESS));
- QPID_WINDOWS_CHECK_NULL(svc);
-
- // Check the status in case the service is not stopped.
- DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
- if (state == SERVICE_STOP_PENDING)
- throw qpid::Exception("Timed out waiting for running service to stop.");
-
- // Attempt to start the service.
- QPID_WINDOWS_CHECK_NOT(::StartService(svc, 0, NULL), 0);
-
- QPID_LOG(info, "Service start pending...");
-
- // Check the status until the service is no longer start pending.
- state = waitForStateChangeFrom(svc, SERVICE_START_PENDING);
- // Determine whether the service is running.
- if (state == SERVICE_RUNNING) {
- QPID_LOG(info, "Service started successfully");
- }
- else {
- throw qpid::Exception(QPID_MSG("Service not yet running; state now " << state));
- }
-}
-
-/**
- *
- */
-void SCM::stop(const string& serviceName)
-{
- // Ensure a handle to the SCM database.
- openSvcManager();
-
- // Get a handle to the service.
- AutoServiceHandle svc(::OpenService(scmHandle,
- serviceName.c_str(),
- SERVICE_STOP | SERVICE_QUERY_STATUS |
- SERVICE_ENUMERATE_DEPENDENTS));
- QPID_WINDOWS_CHECK_NULL(svc);
-
- // Make sure the service is not already stopped; if it's stop-pending,
- // wait for it to finalize.
- DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
- if (state == SERVICE_STOPPED) {
- QPID_LOG(info, "Service is already stopped");
- return;
- }
-
- // If the service is running, dependencies must be stopped first.
- std::auto_ptr<ENUM_SERVICE_STATUS> deps;
- DWORD numDeps = getDependentServices(svc, deps);
- for (DWORD i = 0; i < numDeps; i++)
- stop(deps.get()[i].lpServiceName);
-
- // Dependents stopped; send a stop code to the service.
- SERVICE_STATUS_PROCESS ssp;
- if (!::ControlService(svc, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp))
- throw qpid::Exception(QPID_MSG("Stopping " << serviceName << ": " <<
- qpid::sys::strError(::GetLastError())));
-
- // Wait for the service to stop.
- state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
- if (state == SERVICE_STOPPED)
- QPID_LOG(info, QPID_MSG("Service " << serviceName <<
- " stopped successfully."));
-}
-
-/**
- *
- */
-void SCM::openSvcManager()
-{
- if (NULL != scmHandle)
- return;
-
- scmHandle = ::OpenSCManager(NULL, // local computer
- NULL, // ServicesActive database
- SC_MANAGER_ALL_ACCESS); // Rights
- QPID_WINDOWS_CHECK_NULL(scmHandle);
-}
-
-DWORD SCM::waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState)
-{
- SERVICE_STATUS_PROCESS ssStatus;
- DWORD bytesNeeded;
- DWORD waitTime;
- if (!::QueryServiceStatusEx(svc, // handle to service
- SC_STATUS_PROCESS_INFO, // information level
- (LPBYTE)&ssStatus, // address of structure
- sizeof(ssStatus), // size of structure
- &bytesNeeded)) // size needed if buffer is too small
- throw QPID_WINDOWS_ERROR(::GetLastError());
-
- // Save the tick count and initial checkpoint.
- DWORD startTickCount = ::GetTickCount();
- DWORD oldCheckPoint = ssStatus.dwCheckPoint;
-
- // Wait for the service to change out of the noted state.
- while (ssStatus.dwCurrentState == originalState) {
- // Do not wait longer than the wait hint. A good interval is
- // one-tenth of the wait hint but not less than 1 second
- // and not more than 10 seconds.
- waitTime = ssStatus.dwWaitHint / 10;
- if (waitTime < 1000)
- waitTime = 1000;
- else if (waitTime > 10000)
- waitTime = 10000;
-
- ::Sleep(waitTime);
-
- // Check the status until the service is no longer stop pending.
- if (!::QueryServiceStatusEx(svc,
- SC_STATUS_PROCESS_INFO,
- (LPBYTE) &ssStatus,
- sizeof(ssStatus),
- &bytesNeeded))
- throw QPID_WINDOWS_ERROR(::GetLastError());
-
- if (ssStatus.dwCheckPoint > oldCheckPoint) {
- // Continue to wait and check.
- startTickCount = ::GetTickCount();
- oldCheckPoint = ssStatus.dwCheckPoint;
- } else {
- if ((::GetTickCount() - startTickCount) > ssStatus.dwWaitHint)
- break;
- }
- }
- return ssStatus.dwCurrentState;
-}
-
-/**
- * Get the services that depend on @arg svc. All dependent service info
- * is returned in an array of ENUM_SERVICE_STATUS structures via @arg deps.
- *
- * @retval The number of dependent services.
- */
-DWORD SCM::getDependentServices(SC_HANDLE svc,
- std::auto_ptr<ENUM_SERVICE_STATUS>& deps)
-{
- DWORD bytesNeeded;
- DWORD numEntries;
-
- // Pass a zero-length buffer to get the required buffer size.
- if (::EnumDependentServices(svc,
- SERVICE_ACTIVE,
- 0,
- 0,
- &bytesNeeded,
- &numEntries)) {
- // If the Enum call succeeds, then there are no dependent
- // services, so do nothing.
- return 0;
- }
-
- if (::GetLastError() != ERROR_MORE_DATA)
- throw QPID_WINDOWS_ERROR((::GetLastError()));
-
- // Allocate a buffer for the dependencies.
- deps.reset((LPENUM_SERVICE_STATUS)(new char[bytesNeeded]));
- // Enumerate the dependencies.
- if (!::EnumDependentServices(svc,
- SERVICE_ACTIVE,
- deps.get(),
- bytesNeeded,
- &bytesNeeded,
- &numEntries))
- throw QPID_WINDOWS_ERROR((::GetLastError()));
- return numEntries;
-}
-
-} } // namespace qpid::windows
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/log/Statement.h"
+#include "qpid/sys/windows/check.h"
+#include "SCM.h"
+
+#pragma comment(lib, "advapi32.lib")
+
+namespace {
+
+// Container that will close a SC_HANDLE upon destruction.
+class AutoServiceHandle {
+public:
+ AutoServiceHandle(SC_HANDLE h_ = NULL) : h(h_) {}
+ ~AutoServiceHandle() { if (h != NULL) ::CloseServiceHandle(h); }
+ void release() { h = NULL; }
+ void reset(SC_HANDLE newHandle)
+ {
+ if (h != NULL)
+ ::CloseServiceHandle(h);
+ h = newHandle;
+ }
+ operator SC_HANDLE() const { return h; }
+
+private:
+ SC_HANDLE h;
+};
+
+}
+
+namespace qpid {
+namespace windows {
+
+SCM::SCM() : scmHandle(NULL)
+{
+}
+
+SCM::~SCM()
+{
+ if (NULL != scmHandle)
+ ::CloseServiceHandle(scmHandle);
+}
+
+/**
+ * Install this executable as a service
+ */
+void SCM::install(const string& serviceName,
+ const string& serviceDesc,
+ const string& args,
+ DWORD startType,
+ const string& account,
+ const string& password,
+ const string& depends)
+{
+ // Handle dependent service name list; Windows wants a set of nul-separated
+ // names ending with a double nul.
+ string depends2 = depends;
+ if (!depends2.empty()) {
+ // CDL to null delimiter w/ trailing double null
+ size_t p = 0;
+ while ((p = depends2.find_first_of( ',', p)) != string::npos)
+ depends2.replace(p, 1, 1, '\0');
+ depends2.push_back('\0');
+ depends2.push_back('\0');
+ }
+
+#if 0
+ // I'm nervous about adding a user/password check here. Is this a
+ // potential attack vector, letting users check passwords without
+ // control? -Steve Huston, Feb 24, 2011
+
+ // Validate account, password
+ HANDLE hToken = NULL;
+ bool logStatus = false;
+ if (!account.empty() && !password.empty() &&
+ !(logStatus = ::LogonUserA(account.c_str(),
+ "",
+ password.c_str(),
+ LOGON32_LOGON_NETWORK,
+ LOGON32_PROVIDER_DEFAULT,
+ &hToken ) != 0))
+ std::cout << "warning: supplied account & password failed with LogonUser." << std::endl;
+ if (logStatus)
+ ::CloseHandle(hToken);
+#endif
+
+ // Get fully qualified .exe name
+ char myPath[MAX_PATH];
+ DWORD myPathLength = ::GetModuleFileName(NULL, myPath, MAX_PATH);
+ QPID_WINDOWS_CHECK_NOT(myPathLength, 0);
+ string imagePath(myPath, myPathLength);
+ if (!args.empty())
+ imagePath += " " + args;
+
+ // Ensure there's a handle to the SCM database.
+ openSvcManager();
+
+ // Create the service
+ SC_HANDLE svcHandle;
+ svcHandle = ::CreateService(scmHandle, // SCM database
+ serviceName.c_str(), // name of service
+ serviceDesc.c_str(), // name to display
+ SERVICE_ALL_ACCESS, // desired access
+ SERVICE_WIN32_OWN_PROCESS, // service type
+ startType, // start type
+ SERVICE_ERROR_NORMAL, // error cntrl type
+ imagePath.c_str(), // path to service's binary w/ optional arguments
+ NULL, // no load ordering group
+ NULL, // no tag identifier
+ depends2.empty() ? NULL : depends2.c_str(),
+ account.empty() ? NULL : account.c_str(), // account name, or NULL for LocalSystem
+ password.empty() ? NULL : password.c_str()); // password, or NULL for none
+ QPID_WINDOWS_CHECK_NULL(svcHandle);
+ ::CloseServiceHandle(svcHandle);
+ QPID_LOG(info, "Service installed successfully");
+}
+
+/**
+ *
+ */
+void SCM::uninstall(const string& serviceName)
+{
+ // Ensure there's a handle to the SCM database.
+ openSvcManager();
+ AutoServiceHandle svc(::OpenService(scmHandle,
+ serviceName.c_str(),
+ DELETE));
+ QPID_WINDOWS_CHECK_NULL((SC_HANDLE)svc);
+ QPID_WINDOWS_CHECK_NOT(::DeleteService(svc), 0);
+ QPID_LOG(info, "Service deleted successfully.");
+}
+
+/**
+ * Attempt to start the service.
+ */
+void SCM::start(const string& serviceName)
+{
+ // Ensure we have a handle to the SCM database.
+ openSvcManager();
+
+ // Get a handle to the service.
+ AutoServiceHandle svc(::OpenService(scmHandle,
+ serviceName.c_str(),
+ SERVICE_ALL_ACCESS));
+ QPID_WINDOWS_CHECK_NULL(svc);
+
+ // Check the status in case the service is not stopped.
+ DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
+ if (state == SERVICE_STOP_PENDING)
+ throw qpid::Exception("Timed out waiting for running service to stop.");
+
+ // Attempt to start the service.
+ QPID_WINDOWS_CHECK_NOT(::StartService(svc, 0, NULL), 0);
+
+ QPID_LOG(info, "Service start pending...");
+
+ // Check the status until the service is no longer start pending.
+ state = waitForStateChangeFrom(svc, SERVICE_START_PENDING);
+ // Determine whether the service is running.
+ if (state == SERVICE_RUNNING) {
+ QPID_LOG(info, "Service started successfully");
+ }
+ else {
+ throw qpid::Exception(QPID_MSG("Service not yet running; state now " << state));
+ }
+}
+
+/**
+ *
+ */
+void SCM::stop(const string& serviceName)
+{
+ // Ensure a handle to the SCM database.
+ openSvcManager();
+
+ // Get a handle to the service.
+ AutoServiceHandle svc(::OpenService(scmHandle,
+ serviceName.c_str(),
+ SERVICE_STOP | SERVICE_QUERY_STATUS |
+ SERVICE_ENUMERATE_DEPENDENTS));
+ QPID_WINDOWS_CHECK_NULL(svc);
+
+ // Make sure the service is not already stopped; if it's stop-pending,
+ // wait for it to finalize.
+ DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
+ if (state == SERVICE_STOPPED) {
+ QPID_LOG(info, "Service is already stopped");
+ return;
+ }
+
+ // If the service is running, dependencies must be stopped first.
+ std::auto_ptr<ENUM_SERVICE_STATUS> deps;
+ DWORD numDeps = getDependentServices(svc, deps);
+ for (DWORD i = 0; i < numDeps; i++)
+ stop(deps.get()[i].lpServiceName);
+
+ // Dependents stopped; send a stop code to the service.
+ SERVICE_STATUS_PROCESS ssp;
+ if (!::ControlService(svc, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp))
+ throw qpid::Exception(QPID_MSG("Stopping " << serviceName << ": " <<
+ qpid::sys::strError(::GetLastError())));
+
+ // Wait for the service to stop.
+ state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
+ if (state == SERVICE_STOPPED)
+ QPID_LOG(info, QPID_MSG("Service " << serviceName <<
+ " stopped successfully."));
+}
+
+/**
+ *
+ */
+void SCM::openSvcManager()
+{
+ if (NULL != scmHandle)
+ return;
+
+ scmHandle = ::OpenSCManager(NULL, // local computer
+ NULL, // ServicesActive database
+ SC_MANAGER_ALL_ACCESS); // Rights
+ QPID_WINDOWS_CHECK_NULL(scmHandle);
+}
+
+DWORD SCM::waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState)
+{
+ SERVICE_STATUS_PROCESS ssStatus;
+ DWORD bytesNeeded;
+ DWORD waitTime;
+ if (!::QueryServiceStatusEx(svc, // handle to service
+ SC_STATUS_PROCESS_INFO, // information level
+ (LPBYTE)&ssStatus, // address of structure
+ sizeof(ssStatus), // size of structure
+ &bytesNeeded)) // size needed if buffer is too small
+ throw QPID_WINDOWS_ERROR(::GetLastError());
+
+ // Save the tick count and initial checkpoint.
+ DWORD startTickCount = ::GetTickCount();
+ DWORD oldCheckPoint = ssStatus.dwCheckPoint;
+
+ // Wait for the service to change out of the noted state.
+ while (ssStatus.dwCurrentState == originalState) {
+ // Do not wait longer than the wait hint. A good interval is
+ // one-tenth of the wait hint but not less than 1 second
+ // and not more than 10 seconds.
+ waitTime = ssStatus.dwWaitHint / 10;
+ if (waitTime < 1000)
+ waitTime = 1000;
+ else if (waitTime > 10000)
+ waitTime = 10000;
+
+ ::Sleep(waitTime);
+
+ // Check the status until the service is no longer stop pending.
+ if (!::QueryServiceStatusEx(svc,
+ SC_STATUS_PROCESS_INFO,
+ (LPBYTE) &ssStatus,
+ sizeof(ssStatus),
+ &bytesNeeded))
+ throw QPID_WINDOWS_ERROR(::GetLastError());
+
+ if (ssStatus.dwCheckPoint > oldCheckPoint) {
+ // Continue to wait and check.
+ startTickCount = ::GetTickCount();
+ oldCheckPoint = ssStatus.dwCheckPoint;
+ } else {
+ if ((::GetTickCount() - startTickCount) > ssStatus.dwWaitHint)
+ break;
+ }
+ }
+ return ssStatus.dwCurrentState;
+}
+
+/**
+ * Get the services that depend on @arg svc. All dependent service info
+ * is returned in an array of ENUM_SERVICE_STATUS structures via @arg deps.
+ *
+ * @retval The number of dependent services.
+ */
+DWORD SCM::getDependentServices(SC_HANDLE svc,
+ std::auto_ptr<ENUM_SERVICE_STATUS>& deps)
+{
+ DWORD bytesNeeded;
+ DWORD numEntries;
+
+ // Pass a zero-length buffer to get the required buffer size.
+ if (::EnumDependentServices(svc,
+ SERVICE_ACTIVE,
+ 0,
+ 0,
+ &bytesNeeded,
+ &numEntries)) {
+ // If the Enum call succeeds, then there are no dependent
+ // services, so do nothing.
+ return 0;
+ }
+
+ if (::GetLastError() != ERROR_MORE_DATA)
+ throw QPID_WINDOWS_ERROR((::GetLastError()));
+
+ // Allocate a buffer for the dependencies.
+ deps.reset((LPENUM_SERVICE_STATUS)(new char[bytesNeeded]));
+ // Enumerate the dependencies.
+ if (!::EnumDependentServices(svc,
+ SERVICE_ACTIVE,
+ deps.get(),
+ bytesNeeded,
+ &bytesNeeded,
+ &numEntries))
+ throw QPID_WINDOWS_ERROR((::GetLastError()));
+ return numEntries;
+}
+
+} } // namespace qpid::windows
diff --git a/cpp/src/qpid/sys/windows/SCM.h b/cpp/src/windows/SCM.h
index 8e94ef83c7..bdc73bc210 100644
--- a/cpp/src/qpid/sys/windows/SCM.h
+++ b/cpp/src/windows/SCM.h
@@ -1,111 +1,109 @@
-#ifndef WINDOWS_SCM_H
-#define WINDOWS_SCM_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include <memory>
-#include <string>
-using std::string;
-
-#ifdef UNICODE
-#undef UNICODE
-#endif
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#include <windows.h>
-
-#include "qpid/CommonImportExport.h"
-
-namespace qpid {
-namespace windows {
-
-/**
- * @class SCM
- *
- * Access the Windows Service Control Manager.
- */
-class SCM
-{
-public:
- QPID_COMMON_EXTERN SCM();
- QPID_COMMON_EXTERN ~SCM();
-
- /**
- * Install this executable as a service
- *
- * @param serviceName The name of the service
- * @param serviceDesc Description of the service's purpose
- * @param args The argument list to pass into the service
- * @param startType The start type: SERVICE_DEMAND_START,
- * SERVICE_AUTO_START, SERVICE_DISABLED
- * @param account If not empty, the account name to install this
- * service under
- * @param password If not empty, the account password to install this
- * service with
- * @param depends If not empty, a comma delimited list of services
- * that must start before this one
- */
- QPID_COMMON_EXTERN void install(const string& serviceName,
- const string& serviceDesc,
- const string& args,
- DWORD startType = SERVICE_DEMAND_START,
- const string& account = "NT AUTHORITY\\LocalSystem",
- const string& password = "",
- const string& depends = "");
-
- /**
- * Uninstall this executable as a service
- *
- * @param serviceName the name of the service
- */
- QPID_COMMON_EXTERN void uninstall(const string& serviceName);
-
- /**
- * Start the specified service
- *
- * @param serviceName the name of the service
- */
- QPID_COMMON_EXTERN void start(const string& serviceName);
-
- /**
- * Stop the specified service
- *
- * @param serviceName the name of the service
- */
- QPID_COMMON_EXTERN void stop(const string &serviceName);
-
-private:
- SC_HANDLE scmHandle;
-
- void openSvcManager();
- DWORD waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState);
- DWORD getDependentServices(SC_HANDLE svc,
- std::auto_ptr<ENUM_SERVICE_STATUS>& deps);
-
-};
-
-}} // namespace qpid::windows
-
-#endif /* #ifndef WINDOWS_SCM_H */
+#ifndef WINDOWS_SCM_H
+#define WINDOWS_SCM_H
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <memory>
+#include <string>
+using std::string;
+
+#ifdef UNICODE
+#undef UNICODE
+#endif
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>
+
+namespace qpid {
+namespace windows {
+
+/**
+ * @class SCM
+ *
+ * Access the Windows Service Control Manager.
+ */
+class SCM
+{
+public:
+ SCM();
+ ~SCM();
+
+ /**
+ * Install this executable as a service
+ *
+ * @param serviceName The name of the service
+ * @param serviceDesc Description of the service's purpose
+ * @param args The argument list to pass into the service
+ * @param startType The start type: SERVICE_DEMAND_START,
+ * SERVICE_AUTO_START, SERVICE_DISABLED
+ * @param account If not empty, the account name to install this
+ * service under
+ * @param password If not empty, the account password to install this
+ * service with
+ * @param depends If not empty, a comma delimited list of services
+ * that must start before this one
+ */
+ void install(const string& serviceName,
+ const string& serviceDesc,
+ const string& args,
+ DWORD startType = SERVICE_DEMAND_START,
+ const string& account = "NT AUTHORITY\\LocalSystem",
+ const string& password = "",
+ const string& depends = "");
+
+ /**
+ * Uninstall this executable as a service
+ *
+ * @param serviceName the name of the service
+ */
+ void uninstall(const string& serviceName);
+
+ /**
+ * Start the specified service
+ *
+ * @param serviceName the name of the service
+ */
+ void start(const string& serviceName);
+
+ /**
+ * Stop the specified service
+ *
+ * @param serviceName the name of the service
+ */
+ void stop(const string &serviceName);
+
+private:
+ SC_HANDLE scmHandle;
+
+ void openSvcManager();
+ DWORD waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState);
+ DWORD getDependentServices(SC_HANDLE svc,
+ std::auto_ptr<ENUM_SERVICE_STATUS>& deps);
+
+};
+
+}} // namespace qpid::windows
+
+#endif /* #ifndef WINDOWS_SCM_H */
diff --git a/cpp/src/windows/resources/template-resource.rc b/cpp/src/windows/resources/template-resource.rc
index 8ca0a90890..725d1c9391 100644
--- a/cpp/src/windows/resources/template-resource.rc
+++ b/cpp/src/windows/resources/template-resource.rc
@@ -24,7 +24,7 @@
//
// Generated from the TEXTINCLUDE 2 resource.
//
-#include "windows.h"
+#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
diff --git a/cpp/src/xml.mk b/cpp/src/xml.mk
index baf3803647..0d700fcc03 100644
--- a/cpp/src/xml.mk
+++ b/cpp/src/xml.mk
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-dmoduleexec_LTLIBRARIES += xml.la
+dmodule_LTLIBRARIES += xml.la
xml_la_SOURCES = \
qpid/xml/XmlExchange.cpp \
diff --git a/cpp/xml/cluster.xml b/cpp/xml/cluster.xml
index 899625f5ec..be1c1f868c 100644
--- a/cpp/xml/cluster.xml
+++ b/cpp/xml/cluster.xml
@@ -8,9 +8,9 @@
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
--
+-
- http://www.apache.org/licenses/LICENSE-2.0
--
+-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -78,6 +78,10 @@
<field name="left" type="vbin16"/> <!-- packed member-id array -->
</control>
+ <control name="message-expired" code="0x12">
+ <field name="id" type="uint64"/>
+ </control>
+
<domain name="error-type" type="uint8" label="Types of error">
<enum>
<choice name="none" value="0"/>
@@ -85,7 +89,7 @@
<choice name="connection" value="2"/>
</enum>
</domain>
-
+
<!-- Check for error consistency across the cluster -->
<control name="error-check" code="0x14">
<field name="type" type="error-type"/>
@@ -112,11 +116,6 @@
<field name="message" type="vbin32"/>
</control>
- <!-- Update the cluster time -->
- <control name="clock" code="0x22">
- <field name="time" type="uint64"/>
- </control>
-
</class>
<!-- Controls associated with a specific connection. -->
@@ -150,7 +149,7 @@
<!-- Abort a connection that is sending invalid data. -->
<control name="abort" code="0x4"/>
-
+
<!-- Update controls. Sent to a new broker in joining mode.
A connection is updated as followed:
- send the shadow's management ID in shadow-perpare on the update connection
@@ -184,7 +183,7 @@
<field name="position" type="sequence-no"/>
<field name="tag" type="str8"/>
<field name="id" type="sequence-no"/>
- <field name="acquired" type="bit"/> <!--If not set, message is on update queue. -->
+ <field name="acquired" type="bit"/> <!--If not set, message follows. -->
<field name="accepted" type="bit"/>
<field name="cancelled" type="bit"/>
<field name="completed" type="bit"/>
@@ -193,9 +192,9 @@
<field name="enqueued" type="bit"/>
<field name="credit" type="uint32"/>
</control>
-
+
<!-- Tx transaction state. -->
- <control name="tx-start" code="0x12"/>
+ <control name="tx-start" code="0x12"/>
<control name="tx-accept" code="0x13"> <field name="commands" type="sequence-set"/> </control>
<control name="tx-dequeue" code="0x14"> <field name="queue" type="str8"/> </control>
<control name="tx-enqueue" code="0x15"> <field name="queue" type="str8"/> </control>
@@ -205,37 +204,13 @@
</control>
<control name="tx-end" code="0x17"/>
<control name="accumulated-ack" code="0x18"> <field name="commands" type="sequence-set"/> </control>
-
+
<!-- Consumers in the connection's output task -->
<control name="output-task" code="0x19">
<field name="channel" type="uint16"/>
<field name="name" type="str8"/>
</control>
- <!-- Dtx transaction state. -->
- <control name="dtx-start" code="0x1A">
- <field name="xid" type="str16"/>
- <field name="ended" type="bit"/>
- <field name="suspended" type="bit"/>
- <field name="failed" type="bit"/>
- <field name="expired" type="bit"/>
- </control>
- <control name="dtx-end" code="0x1B"/>
-
- <control name="dtx-ack" code="0x1C"/>
-
- <control name="dtx-buffer-ref" code="0x1D">
- <field name="xid" type="str16"/>
- <field name="index" type="uint32"/>
- <field name="suspended" type="bit"/>
- </control>
-
- <control name="dtx-work-record" code="0x1E">
- <field name="xid" type="str16"/>
- <field name="prepared" type="bit"/>
- <field name="timeout" type="uint32"/>
- </control>
-
<!-- Complete a session state update. -->
<control name="session-state" code="0x1F">
<!-- Target session deduced from channel number. -->
@@ -247,7 +222,6 @@
<field name="received" type="sequence-no"/> <!-- Received up to here (>= expected) -->
<field name="unknown-completed" type="sequence-set"/> <!-- Completed but not known to peer. -->
<field name="received-incomplete" type="sequence-set"/> <!-- Received and incomplete -->
- <field name="dtx-selected" type="bit"/>
</control>
<!-- Complete a shadow connection update. -->
@@ -278,6 +252,10 @@
<!-- Replicate encoded exchanges/queues. -->
<control name="exchange" code="0x31"><field name="encoded" type="str32"/></control>
+ <control name="queue" code="0x32"><field name="encoded" type="str32"/></control>
+
+ <!-- Set expiry-id for subsequent messages. -->
+ <control name="expiry-id" code="0x33"><field name="expiry-id" type="uint64"/></control>
<!-- Add a listener to a queue -->
<control name="add-queue-listener" code="0x34">
@@ -304,26 +282,6 @@
<field name="position" type="uint8"/>
<field name="count" type="uint8"/>
</control>
-
- <!-- Replicate a QueueObserver for a given queue. -->
- <control name="queue-observer-state" code="0x39">
- <field name="queue" type="str8"/>
- <field name="observer-id" type="str8"/>
- <field name="state" type="map"/> <!-- "name"=value -->
- </control>
-
- <!-- Update the cluster time -->
- <control name="clock" code="0x40">
- <field name="time" type="uint64"/>
- </control>
-
- <!-- Update a queue's dequeue rate -->
- <control name="queue-dequeue-since-purge-state" code="0x41">
- <field name="queue" type="str8"/>
- <field name="dequeueSincePurge" type="uint32"/>
- </control>
-
-
</class>
</amqp>