From 25392fe3101ff446bb008dc2c1f96451f3a06d39 Mon Sep 17 00:00:00 2001 From: Alan Conway Date: Mon, 27 Aug 2007 12:56:29 +0000 Subject: * rubygen/amqpgen.rb: Performance and API improvements. Added nodes for all amqp.xml elements except doc, assert and rule. (They can easily be added.) In particular AmqpDomain is a proper node, providing a place to do type mapping. Every node has reader methods for AMQP attributes/elements: - attr() for each AMQP attribute "attr" returns the string value. - foos() returns AmqpElements for all the "foo" children. - foo(name) returns AmqpElements for the named "foo" child domain() returns an AmqpDomain rather than the string name. Method names that would clash with Object methods get a trailing "_" So: class_/classes, method_/methods_, type_/types Notes: - no amqp_ prefixes. - AmqpElement does not inherit REXML::Element, AmqpElement#xml() to get the REXML element. Performance: all templates run in 2.8 seconds on my laptop, compared to almost two minutes previously. Main change was to replace xpath searches with simple descent of the Amqp model and cache values selectively based on profiling. * rubygen/cppgen.rb: - Updated for amqpgen changes. - Introduced CppType to manage C++ type information - Moved all type mapping to CppType/AmqpDomain Some templates still do their own type calculations, these should be centralized in CppType so they can be re-used. * rubygen/templates/*: Updated for new API * src/qpid/framing/amqp_types_full.h: Added Uuid.h * xml/cluster.xml: change "type" attribute to "domain" git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@570096 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/cpp/rubygen/templates/InvocationVisitor.rb | 18 +++---- .../rubygen/templates/MethodBodyConstVisitor.rb | 4 +- qpid/cpp/rubygen/templates/MethodHolder.rb | 12 ++--- qpid/cpp/rubygen/templates/Operations.rb | 23 ++++----- qpid/cpp/rubygen/templates/Proxy.rb | 14 ++--- qpid/cpp/rubygen/templates/Session.rb | 12 ++--- qpid/cpp/rubygen/templates/all_method_bodies.rb | 2 +- qpid/cpp/rubygen/templates/frame_body_lists.rb | 2 +- qpid/cpp/rubygen/templates/structs.rb | 60 +++++++++------------- 9 files changed, 66 insertions(+), 81 deletions(-) (limited to 'qpid/cpp/rubygen/templates') diff --git a/qpid/cpp/rubygen/templates/InvocationVisitor.rb b/qpid/cpp/rubygen/templates/InvocationVisitor.rb index 7017872176..befbdd53c7 100644 --- a/qpid/cpp/rubygen/templates/InvocationVisitor.rb +++ b/qpid/cpp/rubygen/templates/InvocationVisitor.rb @@ -12,7 +12,7 @@ class InvocationVisitor < CppGen end def invocation_args(m) - if (m.amqp_parent.name == "message" && (m.name == "transfer" || m.name == "append")) + if (m.parent.name == "message" && (m.name == "transfer" || m.name == "append")) "body" else m.param_names.collect {|p| "body.get" + p.caps + "()" }.join(",\n") @@ -32,17 +32,17 @@ class InvocationVisitor < CppGen gen <(invocable); + ptr = dynamic_cast(invocable); } else { - ptr = ops->get#{m.amqp_parent.cppname}Handler(); + ptr = ops->get#{m.parent.cppname}Handler(); } if (ptr) { EOS - if (m.has_result?) - indent(2) { genl "encode<#{m.result_struct.cppname.caps}>(ptr->#{m.cppname}(#{invocation_args(m)}), result);" } + if (m.result) + indent(2) { genl "encode<#{m.result.struct.cpptype.name}>(ptr->#{m.cppname}(#{invocation_args(m)}), result);" } else indent(2) { genl "ptr->#{m.cppname}(#{invocation_args(m)});" } end @@ -79,14 +79,14 @@ EOS genl "void clear();" genl "virtual ~InvocationVisitor() {}" } - @amqp.amqp_methods.each { |m| genl "void visit(const #{m.body_name}&);" } + @amqp.methods_.each { |m| genl "void visit(const #{m.body_name}&);" } } } } cpp_file("#{@filename}") { include "InvocationVisitor.h" - @amqp.amqp_methods.each { |m| include m.body_name } + @amqp.methods_.each { |m| include m.body_name } namespace(@namespace) { genl "void InvocationVisitor::clear() {" indent { @@ -95,7 +95,7 @@ EOS } genl "}" genl - @amqp.amqp_methods.each { |m| m.is_server_method? ? define_visit(m) : null_visit(m) } + @amqp.methods_.each { |m| m.on_server? ? define_visit(m) : null_visit(m) } } } end diff --git a/qpid/cpp/rubygen/templates/MethodBodyConstVisitor.rb b/qpid/cpp/rubygen/templates/MethodBodyConstVisitor.rb index 6fd7fe8ead..18f74a2e41 100755 --- a/qpid/cpp/rubygen/templates/MethodBodyConstVisitor.rb +++ b/qpid/cpp/rubygen/templates/MethodBodyConstVisitor.rb @@ -14,11 +14,11 @@ class MethodBodyConstVisitorGen < CppGen def generate() h_file("#{@filename}") { namespace(@namespace) { - @amqp.amqp_methods.each { |m| genl "class #{m.body_name};" } + @amqp.methods_.each { |m| genl "class #{m.body_name};" } cpp_class("MethodBodyConstVisitor") { genl "public:" genl "virtual ~MethodBodyConstVisitor() {}" - @amqp.amqp_methods.each { |m| genl "virtual void visit(const #{m.body_name}&) = 0;" } + @amqp.methods_.each { |m| genl "virtual void visit(const #{m.body_name}&) = 0;" } }}} end end diff --git a/qpid/cpp/rubygen/templates/MethodHolder.rb b/qpid/cpp/rubygen/templates/MethodHolder.rb index 39a570c982..95c60f5727 100755 --- a/qpid/cpp/rubygen/templates/MethodHolder.rb +++ b/qpid/cpp/rubygen/templates/MethodHolder.rb @@ -14,7 +14,7 @@ class MethodHolderGen < CppGen def gen_max_size() # Generate program to generate MaxSize.h cpp_file("generate_#{@classname}MaxSize_h") { - @amqp.amqp_methods.each { |m| include "qpid/framing/#{m.body_name}" } + @amqp.methods_.each { |m| include "qpid/framing/#{m.body_name}" } genl include "" include "" @@ -24,7 +24,7 @@ class MethodHolderGen < CppGen genl scope("int main(int, char** argv) {") { genl "size_t maxSize=0;" - @amqp.amqp_methods.each { |m| + @amqp.methods_.each { |m| genl "maxSize=max(maxSize, sizeof(#{m.body_name}));" } gen <()); break;" } genl "default: throw Exception(QPID_MSG(\"Invalid method id \" << m << \" for class #{c.name} \"));" @@ -64,7 +64,7 @@ EOS # CopyVisitor struct("#{@classname}::CopyVisitor", "public MethodBodyConstVisitor") { genl "MethodHolder& holder;" genl "CopyVisitor(MethodHolder& h) : holder(h) {}" - @amqp.amqp_methods.each { |m| + @amqp.methods_.each { |m| genl "void visit(const #{m.body_name}& x) { holder.blob=x; }" } } diff --git a/qpid/cpp/rubygen/templates/Operations.rb b/qpid/cpp/rubygen/templates/Operations.rb index 79b82a9d59..9f242f5910 100755 --- a/qpid/cpp/rubygen/templates/Operations.rb +++ b/qpid/cpp/rubygen/templates/Operations.rb @@ -3,6 +3,9 @@ # $: << '..' require 'cppgen' +require 'fileutils' +require 'etc' +require 'pathname' class OperationsGen < CppGen @@ -13,12 +16,8 @@ class OperationsGen < CppGen end def handler_method (m) - if (m.has_result?) - return_type = "#{m.amqp_parent.name.caps}#{m.cppname.caps}Result" - else - return_type = "void" - end - if (m.amqp_parent.name == "message" && (m.name == "transfer" || m.name == "append")) + return_type = m.result ? m.result.cpptype.ret : "void" + if (m.parent.name == "message" && (m.name == "transfer" || m.name == "append")) gen "\nvirtual #{return_type} #{m.cppname}(const framing::AMQMethodBody& context) = 0;\n" else gen "\nvirtual #{return_type} #{m.cppname}(" @@ -30,7 +29,7 @@ class OperationsGen < CppGen def handler_classname(c) c.name.caps+"Handler"; end def handler_class(c) - if (!c.amqp_methods_on(@chassis).empty?) + if (!c.methods_on(@chassis).empty?) handlerclass=handler_classname c gen < #include "qpid/framing/ProtocolVersion.h" @@ -88,13 +87,13 @@ class #{@classname} { // Inner classes EOS - indent { @amqp.amqp_classes.each { |c| handler_class(c) } } + indent { @amqp.classes.each { |c| handler_class(c) } } gen <setSync(sync); } void close(); EOS - indent { @amqp.amqp_classes.each { |c| declare_class(c) if !excludes.include?(c.name) } } + indent { @amqp.classes.each { |c| declare_class(c) if !excludes.include?(c.name) } } gen <"LongString", "shortstr"=>"ShortString", "timestamp"=>"LongLong", - "uuid"=>"ShortString",#FIXME "table"=>"FieldTable", "content"=>"Content", - "long-struct"=>"LongString" + "long-struct"=>"LongString", + "uuid" => "ShortString" # FIXME aconway 2007-08-27: } SizeMap={ "octet"=>"1", @@ -34,7 +34,7 @@ class StructGen < CppGen ValueTypes=["octet", "short", "long", "longlong", "timestamp"] def printable_form(f) - if (f.cpptype == "u_int8_t") + if (f.cpptype.name == "u_int8_t") return "(int) " + f.cppname else return f.cppname @@ -42,53 +42,39 @@ class StructGen < CppGen end def generate_encode(f, combined) - if (f.field_type == "bit") + if (f.domain.type_ == "bit") genl "uint8_t #{f.cppname}_bits = #{f.cppname};" count = 0 combined.each { |c| genl "#{f.cppname}_bits |= #{c.cppname} << #{count += 1};" } genl "buffer.putOctet(#{f.cppname}_bits);" else - encoded = EncodingMap[f.field_type] - if (encoded) - genl "buffer.put#{encoded}(#{f.cppname});" - else - genl "#{f.cppname}.encode(buffer);" - end + genl f.domain.cpptype.encode(f.cppname,"buffer") end end def generate_decode(f, combined) - if (f.field_type == "bit") + if (f.domain.type_ == "bit") genl "uint8_t #{f.cppname}_bits = buffer.getOctet();" genl "#{f.cppname} = 1 & #{f.cppname}_bits;" count = 0 combined.each { |c| genl "#{c.cppname} = (1 << #{count += 1}) & #{f.cppname}_bits;" } else - encoded = EncodingMap[f.field_type] - if (encoded) - if (ValueTypes.include?(f.field_type)) - genl "#{f.cppname} = buffer.get#{encoded}();" - else - genl "buffer.get#{encoded}(#{f.cppname});" - end - else - genl "#{f.cppname}.decode(buffer);" - end + genl f.domain.cpptype.decode(f.cppname,"buffer") end end def generate_size(f, combined) - if (f.field_type == "bit") + if (f.domain.type_ == "bit") names = ([f] + combined).collect {|g| g.cppname} genl "+ 1 //#{names.join(", ")}" else - size = SizeMap[f.field_type] + size = SizeMap[f.domain.type_] if (size) genl "+ #{size} //#{f.cppname}" - elsif (f.cpp_member_type == "SequenceNumberSet") + elsif (f.cpptype.name == "SequenceNumberSet") genl "+ #{f.cppname}.encodedSize()" else - encoded = EncodingMap[f.field_type] + encoded = EncodingMap[f.domain.type_] gen "+ 4 " if encoded == "LongString" gen "+ 1 " if encoded == "ShortString" genl "+ #{f.cppname}.size()" @@ -137,7 +123,7 @@ EOS if (s.kind_of? AmqpMethod) indent {gen "ProtocolVersion, "} end - indent { gen s.fields.collect { |f| "#{f.cpptype} _#{f.cppname}" }.join(",\n") } + indent { gen s.fields.collect { |f| "#{f.cpptype.param} _#{f.cppname}" }.join(",\n") } gen ")" genl ": " if s.fields.size > 0 indent { gen s.fields.collect { |f| " #{f.cppname}(_#{f.cppname})" }.join(",\n") } @@ -149,8 +135,8 @@ EOS end def define_accessors(f) - genl "void set#{f.name.caps}(#{f.cpptype} _#{f.cppname}) { #{f.cppname} = _#{f.cppname}; }" - genl "#{f.cpptype} get#{f.name.caps}() const { return #{f.cppname}; }" + genl "void set#{f.name.caps}(#{f.cpptype.param} _#{f.cppname}) { #{f.cppname} = _#{f.cppname}; }" + genl "#{f.cpptype.ret} get#{f.name.caps}() const { return #{f.cppname}; }" end def define_struct(s) @@ -171,7 +157,7 @@ EOS end #need to include any nested struct definitions - s.fields.select {|f| f.defined_as_struct }.map {|f| include f.name.caps} + s.fields.each { |f| include f.cpptype.name if f.domain.struct } gen <