diff options
Diffstat (limited to 'cpp')
-rwxr-xr-x | cpp/rubygen/cppgen.rb | 13 | ||||
-rw-r--r-- | cpp/rubygen/templates/Session.rb | 333 | ||||
-rw-r--r-- | cpp/src/qpid/client/Channel.cpp | 13 | ||||
-rw-r--r-- | cpp/src/tests/ClientSessionTest.cpp | 33 |
4 files changed, 187 insertions, 205 deletions
diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb index ceda5e039c..2590d48f7b 100755 --- a/cpp/rubygen/cppgen.rb +++ b/cpp/rubygen/cppgen.rb @@ -97,12 +97,13 @@ class AmqpField def cppname() name.lcaps.cppsafe; end def cpptype() domain.cpptype; end def bit?() domain.type_ == "bit"; end + def signature() cpptype.param+" "+cppname; end end class AmqpMethod def cppname() name.lcaps.cppsafe; end def param_names() fields.map { |f| f.cppname }; end - def signature() fields.map { |f| f.cpptype.param+" "+f.cppname }; end + def signature() fields.map { |f| f.signature }; end def body_name() parent.name.caps+name.caps+"Body"; end end @@ -197,7 +198,7 @@ class CppGen < Generator genl yield genl - genl('}'*names.size+" // "+name) + genl('}'*names.size+" // namespace "+name) genl end @@ -236,3 +237,11 @@ class CppGen < Generator end end +# Fully-qualified class name +class FqClass < Struct.new(:fqname,:namespace,:name,:file) + def initialize(fqclass) + names=fqclass.split "::" + super(fqclass, names[0..-2].join('::'), names[-1], names.join("/")) + end +end + diff --git a/cpp/rubygen/templates/Session.rb b/cpp/rubygen/templates/Session.rb index f351710e7d..c61a217682 100644 --- a/cpp/rubygen/templates/Session.rb +++ b/cpp/rubygen/templates/Session.rb @@ -4,209 +4,180 @@ $: << '..' require 'cppgen' -class SessionGen < CppGen - - def initialize(outdir, amqp) - super(outdir, amqp) - @chassis="server" - @classname="Session_#{@amqp.version.bars}" - end - - def return_type(m) - if (m.result) - return "TypedResult<qpid::framing::#{m.result.cpptype.ret}>" - elsif (not m.responses().empty?) - return "Response" - else - return "Completion" - end +class CppGen + def session_methods + excludes = ["channel", "connection", "session", "execution"] + gen_methods=@amqp.methods_on(@chassis).reject { |m| + excludes.include? m.parent.name + } end +end - def declare_method (m) - param_unpackers = m.fields.collect { |f| "args[::qpid::client::#{f.cppname}|#{f.cpptype.default_value}]" } - if (m.content()) - param_names = m.param_names + ["content"] - param_unpackers << "args[content|DefaultContent(\"\")]" - params=m.signature + ["const MethodContent& content"] - else - param_names = m.param_names - params=m.signature - end - - if (params.empty?) - gen "#{return_type(m)} #{m.parent.name.lcaps}#{m.name.caps}();\n\n" - else - genl "template <class ArgumentPack> #{return_type(m)} #{m.parent.name.lcaps}#{m.name.caps}(ArgumentPack const& args)" - genl "{" - indent { - genl "return #{m.parent.name.lcaps}#{m.name.caps}(#{param_unpackers.join(",\n")});" - } - genl "}" - - #generate the 'real' methods signature - gen "#{return_type(m)} #{m.parent.name.lcaps}#{m.name.caps}(" - indent { gen params.join(",\n") } - gen ");\n\n" - - #generate some overloaded methods to handle keyword args - boost_max_arity = 8 - if param_names.length > boost_max_arity - keywords = param_names[1..boost_max_arity].collect { |p| "keyword::#{p}" } - else - keywords = param_names.collect { |p| "keyword::#{p}" } - end - genl "typedef boost::parameter::parameters< #{keywords.join(",")} > #{m.parent.name.caps}#{m.name.caps}Params;\n" - - j = 1 - while j <= params.length && j <= boost_max_arity - dummy_args = Array.new(j) { |i| "P#{i} const& p#{i}"} - dummy_names = Array.new(j) { |i| "p#{i}"} - dummy_types = Array.new(j) { |i| "class P#{i}"} - - genl "template <#{dummy_types.join(',')}> #{return_type(m)} #{m.parent.name.lcaps}#{m.name.caps}_(#{dummy_args.join(',')})" - genl "{" - indent { - genl "return #{m.parent.name.lcaps}#{m.name.caps}(#{m.parent.name.caps}#{m.name.caps}Params()(#{dummy_names.join(',')}));" - } - genl "}" - j = j + 1 - end - end +class ContentField # For extra content parameters + def cppname() "content" end + def signature() "const MethodContent& content" end + def unpack() "p[arg::content|DefaultContent(std::string())]"; end +end - end +class AmqpField + def unpack() "p[arg::#{cppname}|#{cpptype.default_value}]"; end +end - def define_method (m) - if (m.content()) - params=m.signature + ["const MethodContent& content"] - else - params=m.signature - end - if (params.empty?) - gen "#{return_type(m)} #{@classname}::#{m.parent.name.lcaps}#{m.name.caps}(){\n\n" - else - gen "#{return_type(m)} #{@classname}::#{m.parent.name.lcaps}#{m.name.caps}(" - indent { gen params.join(",\n") } - gen "){\n\n" - end - indent (2) { - gen "return #{return_type(m)}(impl->send(#{m.body_name}(" - params = ["version"] + m.param_names - gen params.join(", ") - other_params=[] - if (m.content()) - gen "), content), impl);\n" - else - gen ")), impl);\n" - end - } - gen "}\n\n" +class AmqpMethod + def fields_c() content ? fields+[ContentField.new] : fields end + def param_names_c() fields_c.map { |f| f.cppname} end + def signature_c() fields_c.map { |f| f.signature }; end + def argpack_name() "#{parent.cppname}#{name.caps}Parameters"; end + def argpack_type() + "boost::parameter::parameters<" + + fields_c.map { |f| "arg::keyword_tags::"+f.cppname }.join(',') + + ">" end - - def declare_keywords(classes) - #need to assemble a listof all the field names - keywords = classes.collect { |c| c.methods_on(@chassis).collect { |m| m.param_names } }.flatten().uniq() - keywords.each { |k| genl "BOOST_PARAMETER_KEYWORD(keyword, #{k})" } - genl "BOOST_PARAMETER_KEYWORD(keyword, content)" + def return_type() + return "TypedResult<qpid::framing::#{result.cpptype.ret}>" if (result) + return "Response" if (not responses().empty?) + return "Completion" end + def session_function() "#{parent.name.lcaps}#{name.caps}"; end +end - def declare_class(c) - c.methods_on(@chassis).each { |m| declare_method(m) } - end +class SessionNoKeywordGen < CppGen - def define_class(c) - c.methods_on(@chassis).each { |m| define_method(m) } + def initialize(outdir, amqp) + super(outdir, amqp) + @chassis="server" + @namespace,@classname,@file= + parse_classname "qpid::client::no_keyword::Session_#{@amqp.version.bars}" end def generate() - excludes = ["channel", "connection", "session", "execution"] - - h_file("qpid/client/#{@classname}.h") { - genl "#define BOOST_PARAMETER_MAX_ARITY 8" - - gen <<EOS -#include <sstream> -#include <boost/parameter.hpp> -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/Uuid.h" -#include "qpid/framing/amqp_structs.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/framing/MethodContent.h" -#include "qpid/framing/TransferContent.h" -#include "qpid/client/Completion.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/Response.h" -#include "qpid/client/SessionCore.h" -#include "qpid/client/TypedResult.h" -#include "qpid/shared_ptr.h" - -namespace qpid { -namespace client { - -using std::string; -using framing::Content; -using framing::FieldTable; -using framing::MethodContent; -using framing::SequenceNumberSet; -using framing::Uuid; - + h_file(@file) { + include "qpid/framing/amqp_framing.h" + include "qpid/framing/Uuid.h" + include "qpid/framing/amqp_structs.h" + include "qpid/framing/ProtocolVersion.h" + include "qpid/framing/MethodContent.h" + include "qpid/framing/TransferContent.h" + include "qpid/client/Completion.h" + include "qpid/client/ConnectionImpl.h" + include "qpid/client/Response.h" + include "qpid/client/SessionCore.h" + include "qpid/client/TypedResult.h" + include "qpid/shared_ptr.h" + include "<string>" + namespace("qpid::client") { + genl "using std::string;" + genl "using framing::Content;" + genl "using framing::FieldTable;" + genl "using framing::MethodContent;" + genl "using framing::SequenceNumberSet;" + genl "using framing::Uuid;" + genl + namespace("no_keyword") { + cpp_class(@classname) { + public + gen <<EOS +#{@classname}(); +framing::FrameSet::shared_ptr get() { return impl->get(); } +Uuid getId() const { return impl->getId(); } +void setSynchronous(bool sync) { impl->setSync(sync); } +void suspend(); +void close(); +Execution& execution() { return impl->getExecution(); } + +typedef framing::TransferContent DefaultContent; EOS - declare_keywords(@amqp.classes.select { |c| !excludes.include?(c.name) }) - genl - gen <<EOS -class #{@classname} { - shared_ptr<SessionCore> impl; - framing::ProtocolVersion version; - friend class Connection; - #{@classname}(shared_ptr<SessionCore>); -public: - #{@classname}(); - - framing::FrameSet::shared_ptr get() { return impl->get(); } - Uuid getId() const { return impl->getId(); } - void setSynchronous(bool sync) { impl->setSync(sync); } - void suspend(); - void close(); - Execution& execution() { return impl->getExecution(); } - - typedef framing::TransferContent DefaultContent; -EOS - indent { @amqp.classes.each { |c| declare_class(c) if !excludes.include?(c.name) } } - gen <<EOS -}; /* class #{@classname} */ -} -} + session_methods.each { |m| + genl + args=m.signature_c.join(", ") + genl "#{m.return_type} #{m.session_function}(#{args});" + } + genl + protected + gen <<EOS +shared_ptr<SessionCore> impl; +framing::ProtocolVersion version; +friend class Connection; +#{@classname}(shared_ptr<SessionCore>); EOS -} - - # .cpp file - cpp_file("qpid/client/#{@classname}.cpp") { - gen <<EOS -#include "#{@classname}.h" -#include "qpid/framing/all_method_bodies.h" - -using std::string; -using namespace qpid::framing; - -namespace qpid { -namespace client { - + }}}} + + cpp_file(@file) { + include @classname + include "qpid/framing/all_method_bodies.h" + namespace(@namespace) { + gen <<EOS +using namespace framing; #{@classname}::#{@classname}() {} #{@classname}::#{@classname}(shared_ptr<SessionCore> core) : impl(core) {} - void #{@classname}::suspend() { impl->suspend(); } void #{@classname}::close() { impl->close(); } - EOS + session_methods.each { |m| + genl + sig=m.signature_c.join(", ") + func="#{@classname}::#{m.session_function}" + scope("#{m.return_type} #{func}(#{sig}) {") { + args=(["ProtocolVersion()"]+m.param_names).join(", ") + body="#{m.body_name}(#{args})" + sendargs=body + sendargs << ", content" if m.content + genl "return #{m.return_type}(impl->send(#{sendargs}), impl);" + }}}} + end +end - @amqp.classes.each { |c| define_class(c) if !excludes.include?(c.name) } - - gen <<EOS -}} // namespace qpid::client -EOS - } +class SessionGen < CppGen + def initialize(outdir, amqp) + super(outdir, amqp) + @chassis="server" + session="Session_#{@amqp.version.bars}" + @base="no_keyword::#{session}" + @fqclass=FqClass.new "qpid::client::#{session}" + @classname=@fqclass.name + @fqbase=FqClass.new("qpid::client::#{@base}") + end + + def gen_keyword_decl(m, prefix) + return if m.fields_c.empty? # Inherited function will do. + scope("BOOST_PARAMETER_MEMFUN(#{m.return_type}, #{m.session_function}, 0, #{m.fields_c.size}, #{m.argpack_name}) {") { + scope("return #{prefix}#{m.session_function}(",");") { + gen m.fields_c.map { |f| f.unpack() }.join(",\n") + } + } + genl + end + + def generate() + keyword_methods=session_methods.reject { |m| m.fields_c.empty? } + max_arity = keyword_methods.map{ |m| m.fields_c.size }.max + + h_file(@fqclass.file) { + include @fqbase.file + genl + genl "#define BOOST_PARAMETER_MAX_ARITY #{max_arity}" + include "<boost/parameter.hpp>" + genl + namespace("qpid::client") { + # Generate keyword tag declarations. + namespace("arg") { + keyword_methods.map{ |m| m.param_names_c }.flatten.uniq.each { |k| + genl "BOOST_PARAMETER_KEYWORD(keyword_tags, #{k})" + }} + genl + cpp_class(@classname,"public #{@base}") { + private + genl "#{@classname}(shared_ptr<SessionCore> core) : #{ @base}(core) {}" + keyword_methods.each { |m| typedef m.argpack_type, m.argpack_name } + genl "friend class Connection;" + public + genl "#{@classname}() {}" + keyword_methods.each { |m| gen_keyword_decl(m,@base+"::") } + }}} end end +SessionNoKeywordGen.new(ARGV[0], Amqp).generate() SessionGen.new(ARGV[0], Amqp).generate() diff --git a/cpp/src/qpid/client/Channel.cpp b/cpp/src/qpid/client/Channel.cpp index fbb2e0c6f8..9246ead44e 100644 --- a/cpp/src/qpid/client/Channel.cpp +++ b/cpp/src/qpid/client/Channel.cpp @@ -44,6 +44,7 @@ using namespace qpid::sys; namespace qpid{ namespace client{ +using namespace arg; const std::string empty; @@ -89,12 +90,12 @@ void Channel::setPrefetch(uint32_t _prefetch){ void Channel::declareExchange(Exchange& _exchange, bool synch){ ScopedSync s(session, synch); - session.exchangeDeclare_(exchange=_exchange.getName(), type=_exchange.getType()); + session.exchangeDeclare(exchange=_exchange.getName(), type=_exchange.getType()); } void Channel::deleteExchange(Exchange& _exchange, bool synch){ ScopedSync s(session, synch); - session.exchangeDelete_(exchange=_exchange.getName(), ifUnused=false); + session.exchangeDelete(exchange=_exchange.getName(), ifUnused=false); } void Channel::declareQueue(Queue& _queue, bool synch){ @@ -105,14 +106,14 @@ void Channel::declareQueue(Queue& _queue, bool synch){ } ScopedSync s(session, synch); - session.queueDeclare_(queue=_queue.getName(), passive=false/*passive*/, durable=_queue.isDurable(), + session.queueDeclare(queue=_queue.getName(), passive=false/*passive*/, durable=_queue.isDurable(), exclusive=_queue.isExclusive(), autoDelete=_queue.isAutoDelete()); } void Channel::deleteQueue(Queue& _queue, bool ifunused, bool ifempty, bool synch){ ScopedSync s(session, synch); - session.queueDelete_(queue=_queue.getName(), ifUnused=ifunused, ifEmpty=ifempty); + session.queueDelete(queue=_queue.getName(), ifUnused=ifunused, ifEmpty=ifempty); } void Channel::bind(const Exchange& exchange, const Queue& queue, const std::string& key, const FieldTable& args, bool synch){ @@ -180,7 +181,7 @@ bool Channel::get(Message& msg, const Queue& _queue, AckMode ackMode) { ScopedDivert handler(tag, session.execution().getDemux()); Demux::Queue& incoming = handler.getQueue(); - session.messageSubscribe_(destination=tag, queue=_queue.getName(), confirmMode=(ackMode == NO_ACK ? 0 : 1)); + session.messageSubscribe(destination=tag, queue=_queue.getName(), confirmMode=(ackMode == NO_ACK ? 0 : 1)); session.messageFlow(tag, 1/*BYTES*/, 0xFFFFFFFF); session.messageFlow(tag, 0/*MESSAGES*/, 1); Completion status = session.messageFlush(tag); @@ -203,7 +204,7 @@ void Channel::publish(Message& msg, const Exchange& exchange, msg.getDeliveryProperties().setRoutingKey(routingKey); msg.getDeliveryProperties().setDiscardUnroutable(!mandatory); - session.messageTransfer_(destination=exchange.getName(), content=msg); + session.messageTransfer(destination=exchange.getName(), content=msg); } void Channel::close() diff --git a/cpp/src/tests/ClientSessionTest.cpp b/cpp/src/tests/ClientSessionTest.cpp index 149cbd8e3d..ed3d733c20 100644 --- a/cpp/src/tests/ClientSessionTest.cpp +++ b/cpp/src/tests/ClientSessionTest.cpp @@ -30,6 +30,7 @@ #include <list> using namespace qpid::client; +using namespace qpid::client::arg; using namespace qpid::framing; using namespace qpid; using namespace boost; @@ -98,22 +99,22 @@ public: { // FIXME aconway 2007-10-18: autoDelete queues are destroyed on channel close, not session. // Fix & make all test queues exclusive, autoDelete - session.queueDeclare_(queue=q); // FIXME aconway 2007-10-01: exclusive=true, autoDelete=true); - session.messageSubscribe_(queue=q, destination=dest, acquireMode=1); - session.messageFlow_(destination=dest, unit=0, value=0xFFFFFFFF);//messages - session.messageFlow_(destination=dest, unit=1, value=0xFFFFFFFF);//bytes + session.queueDeclare(queue=q); // FIXME aconway 2007-10-01: exclusive=true, autoDelete=true); + session.messageSubscribe(queue=q, destination=dest, acquireMode=1); + session.messageFlow(destination=dest, unit=0, value=0xFFFFFFFF);//messages + session.messageFlow(destination=dest, unit=1, value=0xFFFFFFFF);//bytes } bool queueExists(const std::string& q) { - TypedResult<QueueQueryResult> result = session.queueQuery_(q); + TypedResult<QueueQueryResult> result = session.queueQuery(q); return result.get().getQueue() == q; } void testQueueQuery() { session = c->newSession(); - session.queueDeclare_(queue="my-queue", alternateExchange="amq.fanout", exclusive=true, autoDelete=true); - TypedResult<QueueQueryResult> result = session.queueQuery_(std::string("my-queue")); + session.queueDeclare(queue="my-queue", alternateExchange="amq.fanout", exclusive=true, autoDelete=true); + TypedResult<QueueQueryResult> result = session.queueQuery(std::string("my-queue")); CPPUNIT_ASSERT_EQUAL(false, result.get().getDurable()); CPPUNIT_ASSERT_EQUAL(true, result.get().getExclusive()); CPPUNIT_ASSERT_EQUAL(std::string("amq.fanout"), @@ -124,7 +125,7 @@ public: { session = c->newSession(); declareSubscribe(); - session.messageTransfer_(content=TransferContent("my-message", "my-queue")); + session.messageTransfer(content=TransferContent("my-message", "my-queue")); //get & test the message: FrameSet::shared_ptr msg = session.get(); CPPUNIT_ASSERT(msg->isA<MessageTransferBody>()); @@ -140,15 +141,15 @@ public: TransferContent msg1("One"); msg1.getDeliveryProperties().setRoutingKey("my-queue"); - session.messageTransfer_(content=msg1); + session.messageTransfer(content=msg1); TransferContent msg2("Two"); msg2.getDeliveryProperties().setRoutingKey("my-queue"); - session.messageTransfer_(content=msg2); + session.messageTransfer(content=msg2); TransferContent msg3("Three"); msg3.getDeliveryProperties().setRoutingKey("my-queue"); - session.messageTransfer_(content=msg3); + session.messageTransfer(content=msg3); DummyListener listener(session, "my-dest", 3); listener.listen(); @@ -175,7 +176,7 @@ public: session = c->newSession(60); session.suspend(); try { - session.exchangeQuery_(name="amq.fanout"); + session.exchangeQuery(name="amq.fanout"); CPPUNIT_FAIL("Expected session suspended exception"); } catch(const CommandInvalidException&) {} } @@ -186,18 +187,18 @@ public: session.suspend(); // Make sure we are still subscribed after resume. c->resume(session); - session.messageTransfer_(content=TransferContent("my-message", "my-queue")); + session.messageTransfer(content=TransferContent("my-message", "my-queue")); FrameSet::shared_ptr msg = session.get(); CPPUNIT_ASSERT_EQUAL(string("my-message"), msg->getContent()); } void testDisconnectResume() { session = c->newSession(60); - session.queueDeclare_(queue="before"); + session.queueDeclare(queue="before"); CPPUNIT_ASSERT(queueExists("before")); // Simulate lost frames. c->discard(); - session.queueDeclare_(queue=string("after")); + session.queueDeclare(queue=string("after")); c->disconnect(); // Simulate disconnect, resume on a new connection. c2->resume(session); CPPUNIT_ASSERT(queueExists("after")); @@ -206,7 +207,7 @@ public: void testAutoDelete() { // Verify that autoDelete queues survive suspend/resume. session = c->newSession(60); - session.queueDeclare_(queue="my-queue", exclusive=true, autoDelete=true); + session.queueDeclare(queue="my-queue", exclusive=true, autoDelete=true); CPPUNIT_ASSERT(queueExists("my-queue")); session.suspend(); c->resume(session); |