amq-protocol 2.4.0 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +12 -5
  3. data/lib/amq/protocol/client.rb +30 -37
  4. data/lib/amq/protocol/frame.rb +2 -0
  5. data/lib/amq/protocol/version.rb +1 -1
  6. metadata +3 -52
  7. data/.github/ISSUE_TEMPLATE.md +0 -18
  8. data/.github/workflows/ci.yml +0 -31
  9. data/.gitignore +0 -18
  10. data/.gitmodules +0 -3
  11. data/.rspec +0 -1
  12. data/.travis.yml +0 -17
  13. data/Gemfile +0 -27
  14. data/Rakefile +0 -55
  15. data/amq-protocol.gemspec +0 -27
  16. data/benchmarks/frame_encoding.rb +0 -75
  17. data/benchmarks/int_allocator.rb +0 -34
  18. data/benchmarks/method_encoding.rb +0 -198
  19. data/benchmarks/pack_unpack.rb +0 -158
  20. data/benchmarks/pure/body_framing_with_256k_payload.rb +0 -28
  21. data/benchmarks/pure/body_framing_with_2k_payload.rb +0 -28
  22. data/benchmarks/run_all.rb +0 -64
  23. data/benchmarks/table_encoding.rb +0 -110
  24. data/codegen/__init__.py +0 -0
  25. data/codegen/amqp_0.9.1_changes.json +0 -1
  26. data/codegen/codegen.py +0 -151
  27. data/codegen/codegen_helpers.py +0 -162
  28. data/codegen/protocol.rb.pytemplate +0 -320
  29. data/generate.rb +0 -24
  30. data/profiling/README.md +0 -9
  31. data/profiling/stackprof/body_framing_with_2k_payload.rb +0 -33
  32. data/spec/amq/bit_set_spec.rb +0 -249
  33. data/spec/amq/endianness_spec.rb +0 -23
  34. data/spec/amq/int_allocator_spec.rb +0 -136
  35. data/spec/amq/pack_spec.rb +0 -58
  36. data/spec/amq/protocol/basic_spec.rb +0 -325
  37. data/spec/amq/protocol/blank_body_encoding_spec.rb +0 -9
  38. data/spec/amq/protocol/channel_spec.rb +0 -127
  39. data/spec/amq/protocol/confirm_spec.rb +0 -41
  40. data/spec/amq/protocol/connection_spec.rb +0 -146
  41. data/spec/amq/protocol/constants_spec.rb +0 -10
  42. data/spec/amq/protocol/exceptions_spec.rb +0 -70
  43. data/spec/amq/protocol/exchange_spec.rb +0 -106
  44. data/spec/amq/protocol/float_32bit_spec.rb +0 -27
  45. data/spec/amq/protocol/frame_spec.rb +0 -156
  46. data/spec/amq/protocol/method_spec.rb +0 -43
  47. data/spec/amq/protocol/queue_spec.rb +0 -126
  48. data/spec/amq/protocol/table_spec.rb +0 -291
  49. data/spec/amq/protocol/tx_spec.rb +0 -55
  50. data/spec/amq/protocol/value_decoder_spec.rb +0 -183
  51. data/spec/amq/protocol/value_encoder_spec.rb +0 -161
  52. data/spec/amq/protocol_spec.rb +0 -812
  53. data/spec/amq/settings_spec.rb +0 -58
  54. data/spec/amq/uri_parsing_spec.rb +0 -287
  55. data/spec/spec_helper.rb +0 -29
data/codegen/codegen.py DELETED
@@ -1,151 +0,0 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
-
4
- # Documentation for Mako templates:
5
- # http://www.makotemplates.org/docs/syntax.html
6
-
7
- import os, sys, re
8
-
9
- sys.path.append(os.path.join("codegen", "rabbitmq-codegen"))
10
-
11
- from amqp_codegen import *
12
- try:
13
- from mako.template import Template
14
- except ImportError:
15
- print("Mako isn't installed. Please install mako via pip or similar.")
16
- sys.exit(1)
17
-
18
- # main class
19
- class AmqpSpecObject(AmqpSpec):
20
- IGNORED_CLASSES = ["access"]
21
- IGNORED_FIELDS = {
22
- 'ticket': 0,
23
- 'capabilities': '',
24
- 'insist' : 0,
25
- 'out_of_band': '',
26
- 'known_hosts': '',
27
- }
28
-
29
- def __init__(self, path):
30
- AmqpSpec.__init__(self, path)
31
-
32
- def extend_field(field):
33
- field.ruby_name = re.sub("[- ]", "_", field.name)
34
- field.type = self.resolveDomain(field.domain)
35
- field.ignored = bool(field.name in self.__class__.IGNORED_FIELDS) # I. e. deprecated
36
-
37
- for klass in self.classes:
38
- klass.ignored = bool(klass.name in self.__class__.IGNORED_CLASSES)
39
-
40
- for field in klass.fields:
41
- extend_field(field)
42
-
43
- for method in klass.methods:
44
- for field in method.arguments:
45
- extend_field(field)
46
-
47
- self.classes = filter(lambda klass: not klass.ignored, self.classes)
48
-
49
- original_init = AmqpEntity.__init__
50
- def new_init(self, arg):
51
- original_init(self, arg)
52
- constant_name = ""
53
- for chunk in self.name.split("-"):
54
- constant_name += chunk.capitalize()
55
- self.constant_name = constant_name
56
- AmqpEntity.__init__ = new_init
57
-
58
- # method.accepted_by("server")
59
- # method.accepted_by("client", "server")
60
- accepted_by_update = json.loads(open("codegen/amqp_0.9.1_changes.json").read())
61
-
62
- def accepted_by(self, *receivers):
63
- def get_accepted_by(self):
64
- try:
65
- return accepted_by_update[self.klass.name][self.name]
66
- except KeyError:
67
- return ["server", "client"]
68
-
69
- actual_receivers = get_accepted_by(self)
70
- return all(map(lambda receiver: receiver in actual_receivers, receivers))
71
-
72
- AmqpMethod.accepted_by = accepted_by
73
-
74
- def convert_value_to_ruby(value):
75
- values = {None: "nil", False: "false", True: "true", "": "EMPTY_STRING"}
76
-
77
- try:
78
- return values[value]
79
- except:
80
- return value.__repr__()
81
-
82
- def convert_to_ruby(field):
83
- name = re.sub("-", "_", field.name) # TODO: use ruby_name
84
- if name == "ticket":
85
- return "%s = %s" % (name, field.defaultvalue) # we want to keep it as an int, not as a boolean
86
- else:
87
- return "%s = %s" % (name, convert_value_to_ruby(field.defaultvalue))
88
-
89
- def not_ignored_args(self):
90
- if self.hasContent:
91
- return ["payload", "user_headers"] + map(lambda argument: argument.ruby_name, filter(lambda argument: not argument.ignored, self.arguments)) + ["frame_size"]
92
- else:
93
- return map(lambda argument: argument.ruby_name, filter(lambda argument: not argument.ignored, self.arguments))
94
-
95
- AmqpMethod.not_ignored_args = not_ignored_args
96
-
97
- def ignored_args(self):
98
- return filter(lambda argument: argument.ignored, self.arguments)
99
-
100
- AmqpMethod.ignored_args = ignored_args
101
-
102
- # helpers
103
- def to_ruby_name(name):
104
- return re.sub("[- ]", "_", name)
105
-
106
- def to_ruby_class_name(name):
107
- parts = re.split("[- ]", name)
108
- ruby_class_name = ""
109
- for part in parts:
110
- ruby_class_name = ruby_class_name + part[0].upper() + part[1:].lower()
111
- return ruby_class_name
112
-
113
- def params(self):
114
- buffer = []
115
- for f in self.arguments:
116
- buffer.append(convert_to_ruby(f))
117
- if self.hasContent:
118
- buffer.append("user_headers = nil")
119
- buffer.append("payload = \"\"")
120
- buffer.append("frame_size = nil")
121
- return buffer
122
-
123
- AmqpMethod.params = params
124
-
125
- def args(self):
126
- return map(lambda item: item.split(" ")[0], self.params())
127
-
128
- AmqpMethod.args = args
129
-
130
- def binary(self):
131
- method_id = self.klass.index << 16 | self.index
132
- return "0x%08X # %i, %i, %i" % (method_id, self.klass.index, self.index, method_id)
133
-
134
- AmqpMethod.binary = binary
135
-
136
- # helpers
137
- def render(path, **context):
138
- file = open(path)
139
- template = Template(file.read())
140
- return template.render(**context)
141
-
142
- def generateMain(type):
143
- def main(json_spec_path):
144
- spec = AmqpSpecObject(json_spec_path)
145
- spec.type = type
146
- print(render("codegen/protocol.rb.pytemplate", spec = spec))
147
-
148
- return main
149
-
150
- if __name__ == "__main__":
151
- do_main_dict({"client": generateMain("client")})
@@ -1,162 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- from __future__ import print_function
4
-
5
- def genSingleEncode(spec, cValue, unresolved_domain):
6
- buffer = []
7
- type = spec.resolveDomain(unresolved_domain)
8
- if type == 'shortstr':
9
- buffer.append("buffer << %s.to_s.bytesize.chr" % (cValue,))
10
- buffer.append("buffer << %s.to_s" % (cValue,))
11
- elif type == 'longstr':
12
- buffer.append("buffer << [%s.to_s.bytesize].pack(PACK_UINT32)" % (cValue,))
13
- buffer.append("buffer << %s.to_s" % (cValue,))
14
- elif type == 'octet':
15
- buffer.append("buffer << [%s].pack(PACK_CHAR)" % (cValue,))
16
- elif type == 'short':
17
- buffer.append("buffer << [%s].pack(PACK_UINT16)" % (cValue,))
18
- elif type == 'long':
19
- buffer.append("buffer << [%s].pack(PACK_UINT32)" % (cValue,))
20
- elif type == 'longlong':
21
- buffer.append("buffer << AMQ::Pack.pack_uint64_big_endian(%s)" % (cValue,))
22
- elif type == 'timestamp':
23
- buffer.append("buffer << AMQ::Pack.pack_uint64_big_endian(%s)" % (cValue,))
24
- elif type == 'bit':
25
- raise "Can't encode bit in genSingleEncode"
26
- elif type == 'table':
27
- buffer.append("buffer << AMQ::Protocol::Table.encode(%s)" % (cValue,))
28
- else:
29
- raise "Illegal domain in genSingleEncode: {0}".format(type)
30
-
31
- return buffer
32
-
33
- def genSingleDecode(spec, field):
34
- cLvalue = field.ruby_name
35
- unresolved_domain = field.domain
36
-
37
- if cLvalue == "known_hosts":
38
- import sys
39
- print(field, field.ignored, file = sys.stderr)
40
-
41
- type = spec.resolveDomain(unresolved_domain)
42
- buffer = []
43
- if type == 'shortstr':
44
- buffer.append("length = data[offset, 1].unpack(PACK_CHAR).first")
45
- buffer.append("offset += 1")
46
- buffer.append("%s = data[offset, length]" % (cLvalue,))
47
- buffer.append("offset += length")
48
- elif type == 'longstr':
49
- buffer.append("length = data[offset, 4].unpack(PACK_UINT32).first")
50
- buffer.append("offset += 4")
51
- buffer.append("%s = data[offset, length]" % (cLvalue,))
52
- buffer.append("offset += length")
53
- elif type == 'octet':
54
- buffer.append("%s = data[offset, 1].unpack(PACK_CHAR).first" % (cLvalue,))
55
- buffer.append("offset += 1")
56
- elif type == 'short':
57
- buffer.append("%s = data[offset, 2].unpack(PACK_UINT16).first" % (cLvalue,))
58
- buffer.append("offset += 2")
59
- elif type == 'long':
60
- buffer.append("%s = data[offset, 4].unpack(PACK_UINT32).first" % (cLvalue,))
61
- buffer.append("offset += 4")
62
- elif type == 'longlong':
63
- buffer.append("%s = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first" % (cLvalue,))
64
- buffer.append("offset += 8")
65
- elif type == 'timestamp':
66
- buffer.append("%s = data[offset, 8].unpack(PACK_UINT64_BE).first" % (cLvalue,))
67
- buffer.append("offset += 8")
68
- elif type == 'bit':
69
- raise "Can't decode bit in genSingleDecode"
70
- elif type == 'table':
71
- buffer.append("table_length = Table.length(data[offset, 4])")
72
- buffer.append("%s = Table.decode(data[offset, table_length + 4])" % (cLvalue,))
73
- buffer.append("offset += table_length + 4")
74
- else:
75
- raise StandardError("Illegal domain '{0}' in genSingleDecode".format(type))
76
-
77
- return buffer
78
-
79
-
80
-
81
- def genSingleSimpleDecode(spec, field):
82
- cLvalue = field.ruby_name
83
- unresolved_domain = field.domain
84
-
85
- if cLvalue == "known_hosts":
86
- import sys
87
- print >> sys.stderr, field, field.ignored
88
-
89
- type = spec.resolveDomain(unresolved_domain)
90
- buffer = []
91
- if type == 'shortstr':
92
- buffer.append("data.to_s")
93
- elif type == 'longstr':
94
- buffer.append("data.to_s")
95
- elif type == 'octet':
96
- buffer.append("data.unpack(PACK_INT8).first")
97
- elif type == 'short':
98
- buffer.append("data.unpack(PACK_UINT16).first")
99
- elif type == 'long':
100
- buffer.append("data.unpack(PACK_UINT32).first")
101
- elif type == 'longlong':
102
- buffer.append("AMQ::Pack.unpack_uint64_big_endian(data).first")
103
- elif type == 'timestamp':
104
- buffer.append("Time.at(data.unpack(PACK_UINT64_BE).last)")
105
- elif type == 'bit':
106
- raise "Can't decode bit in genSingleDecode"
107
- elif type == 'table':
108
- buffer.append("Table.decode(data)")
109
- else:
110
- raise StandardError("Illegal domain '" + type + "' in genSingleSimpleDecode")
111
-
112
- return buffer
113
-
114
-
115
- def genEncodeMethodDefinition(spec, m):
116
- def finishBits():
117
- if bit_index is not None:
118
- buffer.append("buffer << [bit_buffer].pack(PACK_CHAR)")
119
-
120
- bit_index = None
121
- buffer = []
122
-
123
- for f in m.arguments:
124
- if spec.resolveDomain(f.domain) == 'bit':
125
- if bit_index is None:
126
- bit_index = 0
127
- buffer.append("bit_buffer = 0")
128
- if bit_index >= 8:
129
- finishBits()
130
- buffer.append("bit_buffer = 0")
131
- bit_index = 0
132
- buffer.append("bit_buffer = bit_buffer | (1 << %d) if %s" % (bit_index, f.ruby_name))
133
- bit_index = bit_index + 1
134
- else:
135
- finishBits()
136
- bit_index = None
137
- buffer += genSingleEncode(spec, f.ruby_name, f.domain)
138
-
139
- finishBits()
140
- return buffer
141
-
142
- def genDecodeMethodDefinition(spec, m):
143
- buffer = []
144
- bitindex = None
145
- for f in m.arguments:
146
- if spec.resolveDomain(f.domain) == 'bit':
147
- if bitindex is None:
148
- bitindex = 0
149
- if bitindex >= 8:
150
- bitindex = 0
151
- if bitindex == 0:
152
- buffer.append("bit_buffer = data[offset, 1].unpack(PACK_CHAR).first")
153
- buffer.append("offset += 1")
154
- buffer.append("%s = (bit_buffer & (1 << %d)) != 0" % (f.ruby_name, bitindex))
155
- #### TODO: ADD bitindex TO THE buffer
156
- else:
157
- buffer.append("%s = (bit_buffer & (1 << %d)) != 0" % (f.ruby_name, bitindex))
158
- bitindex = bitindex + 1
159
- else:
160
- bitindex = None
161
- buffer += genSingleDecode(spec, f)
162
- return buffer
@@ -1,320 +0,0 @@
1
- # encoding: utf-8
2
- # encoding: binary
3
- # frozen_string_literal: true
4
-
5
- # THIS IS AN AUTOGENERATED FILE, DO NOT MODIFY
6
- # IT DIRECTLY ! FOR CHANGES, PLEASE UPDATE FILES
7
- # IN THE ./codegen DIRECTORY OF THE AMQ-PROTOCOL REPOSITORY.<% import codegen_helpers as helpers %><% import re, os, codegen %>
8
-
9
- require "amq/pack"
10
-
11
- require "amq/protocol/table"
12
- require "amq/protocol/frame"
13
-
14
- require "amq/protocol/constants"
15
- require "amq/protocol/exceptions"
16
-
17
- module AMQ
18
- module Protocol
19
- PROTOCOL_VERSION = "${spec.major}.${spec.minor}.${spec.revision}".freeze
20
- PREAMBLE = "${'AMQP\\x00\\x%02x\\x%02x\\x%02x' % (spec.major, spec.minor, spec.revision)}".freeze
21
- DEFAULT_PORT = ${spec.port}
22
-
23
- # @return [Array] Collection of subclasses of AMQ::Protocol::Class.
24
- def self.classes
25
- Protocol::Class.classes
26
- end
27
-
28
- # @return [Array] Collection of subclasses of AMQ::Protocol::Method.
29
- def self.methods
30
- Protocol::Method.methods
31
- end
32
-
33
- % for tuple in spec.constants:
34
- % if tuple[2] == "soft-error" or tuple[2] == "hard-error":
35
- class ${codegen.to_ruby_class_name(tuple[0])} < ${codegen.to_ruby_class_name(tuple[2])}
36
- VALUE = ${tuple[1]}
37
- end
38
-
39
- % endif
40
- % endfor
41
-
42
- class Class
43
- @classes = Array.new
44
-
45
- def self.method_id
46
- @method_id
47
- end
48
-
49
- def self.name
50
- @name
51
- end
52
-
53
- def self.inherited(base)
54
- if self == Protocol::Class
55
- @classes << base
56
- end
57
- end
58
-
59
- def self.classes
60
- @classes
61
- end
62
- end
63
-
64
- class Method
65
- @methods = Array.new
66
- def self.method_id
67
- @method_id
68
- end
69
-
70
- def self.name
71
- @name
72
- end
73
-
74
- def self.index
75
- @index
76
- end
77
-
78
- def self.inherited(base)
79
- if self == Protocol::Method
80
- @methods << base
81
- end
82
- end
83
-
84
- def self.methods
85
- @methods
86
- end
87
-
88
- def self.split_headers(user_headers)
89
- properties, headers = {}, {}
90
- user_headers.each do |key, value|
91
- # key MUST be a symbol since symbols are not garbage-collected
92
- if Basic::PROPERTIES.include?(key)
93
- properties[key] = value
94
- else
95
- headers[key] = value
96
- end
97
- end
98
-
99
- return [properties, headers]
100
- end
101
-
102
- def self.encode_body(body, channel, frame_size)
103
- return [] if body.empty?
104
-
105
- # 8 = 1 + 2 + 4 + 1
106
- # 1 byte of frame type
107
- # 2 bytes of channel number
108
- # 4 bytes of frame payload length
109
- # 1 byte of payload trailer FRAME_END byte
110
- limit = frame_size - 8
111
- return [BodyFrame.new(body, channel)] if body.bytesize < limit
112
-
113
- # Otherwise String#slice on 1.9 will operate with code points,
114
- # and we need bytes. MK.
115
- body.force_encoding("ASCII-8BIT") if RUBY_VERSION.to_f >= 1.9
116
-
117
- array = Array.new
118
- while body && !body.empty?
119
- payload, body = body[0, limit], body[limit, body.length - limit]
120
- array << BodyFrame.new(payload, channel)
121
- end
122
-
123
- array
124
- end
125
-
126
- def self.instantiate(*args, &block)
127
- self.new(*args, &block)
128
- end
129
- end
130
-
131
- % for klass in spec.classes :
132
- class ${klass.constant_name} < Protocol::Class
133
- @name = "${klass.name}"
134
- @method_id = ${klass.index}
135
-
136
- % if klass.fields: ## only the Basic class has fields (refered as properties in the JSON)
137
- PROPERTIES = [
138
- % for field in klass.fields:
139
- :${field.ruby_name}, # ${spec.resolveDomain(field.domain)}
140
- % endfor
141
- ]
142
-
143
- % for f in klass.fields:
144
- # <% i = klass.fields.index(f) %>1 << ${15 - i}
145
- def self.encode_${f.ruby_name}(value)
146
- buffer = +''
147
- % for line in helpers.genSingleEncode(spec, "value", f.domain):
148
- ${line}
149
- % endfor
150
- [${i}, ${"0x%04x" % ( 1 << (15-i),)}, buffer]
151
- end
152
-
153
- % endfor
154
-
155
- % endif
156
-
157
- % if klass.name == "basic" :
158
- def self.encode_properties(body_size, properties)
159
- pieces, flags = [], 0
160
-
161
- properties.reject {|key, value| value.nil?}.each do |key, value|
162
- i, f, result = self.__send__(:"encode_#{key}", value)
163
- flags |= f
164
- pieces[i] = result
165
- end
166
-
167
- # result = [${klass.index}, 0, body_size, flags].pack('n2Qn')
168
- result = [${klass.index}, 0].pack(PACK_UINT16_X2)
169
- result += AMQ::Pack.pack_uint64_big_endian(body_size)
170
- result += [flags].pack(PACK_UINT16)
171
- pieces_joined = pieces.join(EMPTY_STRING)
172
- result.force_encoding(pieces_joined.encoding) + pieces_joined
173
- end
174
-
175
- # THIS DECODES ONLY FLAGS
176
- DECODE_PROPERTIES = {
177
- % for f in klass.fields:
178
- ${"0x%04x" % ( 1 << (15 - klass.fields.index(f)),)} => :${f.ruby_name},
179
- % endfor
180
- }
181
-
182
- DECODE_PROPERTIES_TYPE = {
183
- % for f in klass.fields:
184
- ${"0x%04x" % ( 1 << (15 - klass.fields.index(f)),)} => :${spec.resolveDomain(f.domain)},
185
- % endfor
186
- }
187
-
188
- # Hash doesn't give any guarantees on keys order, we will do it in a
189
- # straightforward way
190
- DECODE_PROPERTIES_KEYS = [
191
- % for f in klass.fields:
192
- ${"0x%04x" % ( 1 << (15 - klass.fields.index(f)),)},
193
- % endfor
194
- ]
195
-
196
- def self.decode_properties(data)
197
- offset, data_length, properties = 0, data.bytesize, {}
198
-
199
- compressed_index = data[offset, 2].unpack(PACK_UINT16)[0]
200
- offset += 2
201
- while data_length > offset
202
- DECODE_PROPERTIES_KEYS.each do |key|
203
- next unless compressed_index >= key
204
- compressed_index -= key
205
- name = DECODE_PROPERTIES[key] || raise(RuntimeError.new("No property found for index #{index.inspect}!"))
206
- case DECODE_PROPERTIES_TYPE[key]
207
- when :shortstr
208
- size = data[offset, 1].unpack(PACK_CHAR)[0]
209
- offset += 1
210
- result = data[offset, size]
211
- when :octet
212
- size = 1
213
- result = data[offset, size].unpack(PACK_CHAR).first
214
- when :timestamp
215
- size = 8
216
- result = Time.at(data[offset, size].unpack(PACK_UINT64_BE).last)
217
- when :table
218
- size = 4 + data[offset, 4].unpack(PACK_UINT32)[0]
219
- result = Table.decode(data[offset, size])
220
- end
221
- properties[name] = result
222
- offset += size
223
- end
224
- end
225
-
226
- properties
227
- end
228
- % endif
229
-
230
- % for method in klass.methods:
231
- class ${method.constant_name} < Protocol::Method
232
- @name = "${klass.name}.${method.name}"
233
- @method_id = ${method.index}
234
- @index = ${method.binary()}
235
- @packed_indexes = [${klass.index}, ${method.index}].pack(PACK_UINT16_X2).freeze
236
-
237
- % if (spec.type == "client" and method.accepted_by("client")) or (spec.type == "server" and method.accepted_by("server") or spec.type == "all"):
238
- # @return
239
- def self.decode(data)
240
- offset = offset = 0 # self-assigning offset to eliminate "assigned but unused variable" warning even if offset is not used in this method
241
- % for line in helpers.genDecodeMethodDefinition(spec, method):
242
- ${line}
243
- % endfor
244
- % if (method.klass.name == "connection" or method.klass.name == "channel") and method.name == "close":
245
- self.new(${', '.join([f.ruby_name for f in method.arguments])})
246
- % else:
247
- self.new(${', '.join([f.ruby_name for f in method.arguments])})
248
- % endif
249
- end
250
-
251
- % if len(method.arguments) > 0:
252
- attr_reader ${', '.join([":" + f.ruby_name for f in method.arguments])}
253
- % endif
254
- def initialize(${', '.join([f.ruby_name for f in method.arguments])})
255
- % for f in method.arguments:
256
- @${f.ruby_name} = ${f.ruby_name}
257
- % endfor
258
- end
259
- % endif
260
-
261
- def self.has_content?
262
- % if method.hasContent:
263
- true
264
- % else:
265
- false
266
- % endif
267
- end
268
-
269
- % if (spec.type == "client" and method.accepted_by("server")) or (spec.type == "server" and method.accepted_by("client")) or spec.type == "all":
270
- # @return
271
- # ${method.params()}
272
- % if klass.name == "connection":
273
- def self.encode(${(", ").join(method.not_ignored_args())})
274
- % else:
275
- def self.encode(${(", ").join(["channel"] + method.not_ignored_args())})
276
- % endif
277
- % for argument in method.ignored_args():
278
- ${codegen.convert_to_ruby(argument)}
279
- % endfor
280
- % if klass.name == "connection":
281
- channel = 0
282
- % endif
283
- buffer = @packed_indexes.dup
284
- % for line in helpers.genEncodeMethodDefinition(spec, method):
285
- ${line}
286
- % endfor
287
- % if "payload" in method.args() or "user_headers" in method.args():
288
- frames = [MethodFrame.new(buffer, channel)]
289
- % if "user_headers" in method.args():
290
- properties, _headers = self.split_headers(user_headers)
291
- if properties.nil? or properties.empty?
292
- raise RuntimeError.new("Properties can not be empty!")
293
- end
294
- properties_payload = Basic.encode_properties(payload.bytesize, properties)
295
- frames << HeaderFrame.new(properties_payload, channel)
296
- % endif
297
- % if "payload" in method.args():
298
- frames += self.encode_body(payload, channel, frame_size)
299
- frames
300
- % endif
301
- % else:
302
- MethodFrame.new(buffer, channel)
303
- % endif
304
- end
305
- % endif
306
-
307
- end
308
-
309
- % endfor
310
- end
311
-
312
- % endfor
313
-
314
- METHODS = begin
315
- Method.methods.inject(Hash.new) do |hash, klass|
316
- hash.merge!(klass.index => klass)
317
- end
318
- end
319
- end
320
- end
data/generate.rb DELETED
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- # rabbitmq-codegen is Python 3 compatible and so is
5
- # the code in this repo but Mako still fails with 3.6 as of May 2017 :( MK.
6
- python = ENV.fetch("PYTHON", "python2")
7
-
8
- def sh(*args)
9
- system(*args)
10
- end
11
-
12
- extensions = []
13
-
14
- spec = "codegen/rabbitmq-codegen/amqp-rabbitmq-0.9.1.json"
15
- unless File.exist?(spec)
16
- sh "git submodule update --init"
17
- end
18
-
19
- path = "lib/amq/protocol/client.rb"
20
- puts "Running '#{python} ./codegen/codegen.py client #{spec} #{extensions.join(' ')} #{path}'"
21
- sh "#{python} ./codegen/codegen.py client #{spec} #{extensions.join(' ')} #{path}"
22
- if File.file?(path)
23
- sh "ruby -c #{path}"
24
- end
data/profiling/README.md DELETED
@@ -1,9 +0,0 @@
1
- # Profiling Scripts
2
-
3
- This directory contains profiling scripts. Currently they use [stackprof](https://github.com/tmm1/stackprof) which
4
- requires Ruby 2.1+ (preview2 or later).
5
-
6
- ## Running the Profiler
7
-
8
- ruby profiling/stackprof/body_framing_with_2k_payload.rb
9
- stackprof profiling/dumps/body_framing_with_2k_payload.dump --text
@@ -1,33 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib"))
5
-
6
- require "amq/protocol/client"
7
-
8
- FRAME_SIZE = 128 * 1024
9
-
10
- puts
11
- puts "-" * 80
12
- puts "Profiling on #{RUBY_DESCRIPTION}"
13
-
14
- n = 250_000
15
-
16
- # warm up the JIT, etc
17
- puts "Doing a warmup run..."
18
- 15_000.times { AMQ::Protocol::Method.encode_body("ab" * 1024, 1, FRAME_SIZE) }
19
-
20
- require 'stackprof'
21
-
22
- # preallocate
23
- ary = Array.new(n) { "ab" * 1024 }
24
-
25
- puts "Doing main run..."
26
- result = StackProf.run(mode: :wall) do
27
- n.times { |i| AMQ::Protocol::Method.encode_body(ary[i], 1, FRAME_SIZE) }
28
- end
29
-
30
- File.open('./profiling/dumps/body_framing_with_2k_payload.dump', "w+") do |f|
31
- f.write Marshal.dump(result)
32
- end
33
-