amq-protocol 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -12,3 +12,4 @@ Gemfile.lock
12
12
  .bundle/*
13
13
  bin/*
14
14
  *.bundle
15
+ Makefile
data/Gemfile CHANGED
@@ -4,7 +4,9 @@ source "https://rubygems.org"
4
4
 
5
5
  group :development do
6
6
  # excludes Windows, Rubinius and JRuby
7
- gem "perftools.rb", :platform => :mri_18
7
+ gem "ruby-prof", :platform => :mri
8
+
9
+ gem "rake"
8
10
  end
9
11
 
10
12
  group :test do
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require "bundler"
2
+ Bundler.setup
3
+
4
+ require "rake"
5
+ require "rspec/core/rake_task"
6
+
7
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
8
+ require "amq/protocol/version"
9
+
10
+ task :gem => :build
11
+ task :build do
12
+ system "gem build amq-protocol.gemspec"
13
+ end
14
+
15
+ task :install => :build do
16
+ system "gem install amq-protocol-#{AMQ::Protocol::VERSION}.gem"
17
+ end
18
+
19
+ def extension
20
+ RUBY_PLATFORM =~ /darwin/ ? "bundle" : "so"
21
+ end
22
+
23
+ def compile!
24
+ puts "Compiling native extensions..."
25
+ Dir.chdir(Pathname(__FILE__).dirname + "ext/") do
26
+ `bundle exec ruby extconf.rb`
27
+ `make`
28
+ `cp client.#{extension} ../lib/amq/protocol/native/`
29
+ end
30
+ end
31
+
32
+ RSpec::Core::RakeTask.new("spec") do |spec|
33
+ spec.pattern = "spec/**/*_spec.rb"
34
+ end
35
+
36
+ RSpec::Core::RakeTask.new("clean_spec") do |spec|
37
+ spec.pattern = "spec/**/*_spec.rb"
38
+ end
39
+
40
+ task :compile do
41
+ compile!
42
+ end
43
+
44
+ task :clean do
45
+ puts "Cleaning out native extensions..."
46
+ begin
47
+ Dir.chdir(Pathname(__FILE__).dirname + "lib/amq-protocol/native") do
48
+ `rm client.#{extension}`
49
+ end
50
+ rescue Exception => e
51
+ puts e.message
52
+ end
53
+ end
54
+
55
+ task :default => [:compile, :spec, :clean, :clean_spec]
@@ -0,0 +1,28 @@
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
+ require "benchmark"
8
+
9
+ FRAME_SIZE = 128 * 1024
10
+
11
+ puts
12
+ puts "-" * 80
13
+ puts "Benchmarking on #{RUBY_DESCRIPTION}"
14
+
15
+ n = 250_000
16
+
17
+ # warm up the JIT, etc
18
+ puts "Doing a warmup run..."
19
+ 15_000.times { AMQ::Protocol::Method.encode_body("a" * 256 * 1024, 1, FRAME_SIZE) }
20
+
21
+ t = Benchmark.realtime do
22
+ n.times { AMQ::Protocol::Method.encode_body("a" * 256 * 1024, 1, FRAME_SIZE) }
23
+ end
24
+ r = (n.to_f/t.to_f)
25
+
26
+ puts "AMQ::Protocol::Method.encode_body rate: #{(r / 1000).round(2)} KGHz"
27
+ puts
28
+ puts "-" * 80
@@ -0,0 +1,28 @@
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
+ require "benchmark"
8
+
9
+ FRAME_SIZE = 128 * 1024
10
+
11
+ puts
12
+ puts "-" * 80
13
+ puts "Benchmarking on #{RUBY_DESCRIPTION}"
14
+
15
+ n = 250_000
16
+
17
+ # warm up the JIT, etc
18
+ puts "Doing a warmup run..."
19
+ 15_000.times { AMQ::Protocol::Method.encode_body("ab" * 1024, 1, FRAME_SIZE) }
20
+
21
+ t = Benchmark.realtime do
22
+ n.times { AMQ::Protocol::Method.encode_body("ab" * 1024, 1, FRAME_SIZE) }
23
+ end
24
+ r = (n.to_f/t.to_f)
25
+
26
+ puts "AMQ::Protocol::Method.encode_body rate: #{(r / 1000).round(2)} KGHz"
27
+ puts
28
+ puts "-" * 80
@@ -16,9 +16,9 @@ def genSingleEncode(spec, cValue, unresolved_domain):
16
16
  elif type == 'long':
17
17
  buffer.append("buffer << [%s].pack(PACK_UINT32)" % (cValue,))
18
18
  elif type == 'longlong':
19
- buffer.append("buffer << AMQ::Hacks.pack_uint64_big_endian(%s)" % (cValue,))
19
+ buffer.append("buffer << AMQ::Pack.pack_uint64_big_endian(%s)" % (cValue,))
20
20
  elif type == 'timestamp':
21
- buffer.append("buffer << AMQ::Hacks.pack_uint64_big_endian(%s)" % (cValue,))
21
+ buffer.append("buffer << AMQ::Pack.pack_uint64_big_endian(%s)" % (cValue,))
22
22
  elif type == 'bit':
23
23
  raise "Can't encode bit in genSingleEncode"
24
24
  elif type == 'table':
@@ -58,7 +58,7 @@ def genSingleDecode(spec, field):
58
58
  buffer.append("%s = data[offset, 4].unpack(PACK_UINT32).first" % (cLvalue,))
59
59
  buffer.append("offset += 4")
60
60
  elif type == 'longlong':
61
- buffer.append("%s = AMQ::Hacks.unpack_uint64_big_endian(data[offset, 8]).first" % (cLvalue,))
61
+ buffer.append("%s = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first" % (cLvalue,))
62
62
  buffer.append("offset += 8")
63
63
  elif type == 'timestamp':
64
64
  buffer.append("%s = data[offset, 8].unpack(PACK_UINT32_X2).first" % (cLvalue,))
@@ -97,7 +97,7 @@ def genSingleSimpleDecode(spec, field):
97
97
  elif type == 'long':
98
98
  buffer.append("data.unpack(PACK_UINT32).first")
99
99
  elif type == 'longlong':
100
- buffer.append("AMQ::Hacks.unpack_uint64_big_endian(data).first")
100
+ buffer.append("AMQ::Pack.unpack_uint64_big_endian(data).first")
101
101
  elif type == 'timestamp':
102
102
  buffer.append("Time.at(data.unpack(PACK_UINT32_X2).last)")
103
103
  elif type == 'bit':
@@ -5,35 +5,19 @@
5
5
  # IT DIRECTLY ! FOR CHANGES, PLEASE UPDATE FILES
6
6
  # IN THE ./codegen DIRECTORY OF THE AMQ-PROTOCOL REPOSITORY.<% import codegen_helpers as helpers %><% import re, os, codegen %>
7
7
 
8
+ require "amq/pack"
9
+
8
10
  require "amq/protocol/table"
9
11
  require "amq/protocol/frame"
10
- require "amq/hacks"
12
+
13
+ require "amq/protocol/constants"
14
+ require "amq/protocol/exceptions"
11
15
 
12
16
  module AMQ
13
17
  module Protocol
14
18
  PROTOCOL_VERSION = "${spec.major}.${spec.minor}.${spec.revision}".freeze
15
19
  PREAMBLE = "${'AMQP\\x00\\x%02x\\x%02x\\x%02x' % (spec.major, spec.minor, spec.revision)}".freeze
16
20
  DEFAULT_PORT = ${spec.port}
17
- TLS_PORT = 5671
18
- SSL_PORT = 5671
19
-
20
- # caching
21
- EMPTY_STRING = "".freeze
22
-
23
- PACK_INT8 = 'c'.freeze
24
- PACK_CHAR = 'C'.freeze
25
- PACK_UINT16 = 'n'.freeze
26
- PACK_UINT16_X2 = 'n2'.freeze
27
- PACK_UINT32 = 'N'.freeze
28
- PACK_UINT32_X2 = 'N2'.freeze
29
- PACK_INT64 = 'q'.freeze
30
- PACK_UCHAR_UINT32 = 'CN'.freeze
31
- PACK_CHAR_UINT16_UINT32 = 'cnN'.freeze
32
-
33
- PACK_32BIT_FLOAT = 'f'.freeze
34
- PACK_64BIT_FLOAT = 'G'.freeze
35
-
36
-
37
21
 
38
22
  # @return [Array] Collection of subclasses of AMQ::Protocol::Class.
39
23
  def self.classes
@@ -45,63 +29,6 @@ module AMQ
45
29
  Protocol::Method.methods
46
30
  end
47
31
 
48
- class Error < StandardError
49
- DEFAULT_MESSAGE = "AMQP error".freeze
50
-
51
- def self.inherited(subclass)
52
- @_subclasses ||= []
53
- @_subclasses << subclass
54
- end # self.inherited(subclazz)
55
-
56
- def self.subclasses_with_values
57
- @_subclasses.select{ |k| defined?(k::VALUE) }
58
- end # self.subclasses_with_values
59
-
60
- def self.[](code)
61
- if result = subclasses_with_values.detect { |klass| klass::VALUE == code }
62
- result
63
- else
64
- raise "No such exception class for code #{code}" unless result
65
- end # if
66
- end # self.[]
67
-
68
- def initialize(message = self.class::DEFAULT_MESSAGE)
69
- super(message)
70
- end
71
- end
72
-
73
- class FrameTypeError < Protocol::Error
74
- def initialize(types)
75
- super("Must be one of #{types.inspect}")
76
- end
77
- end
78
-
79
- class EmptyResponseError < Protocol::Error
80
- DEFAULT_MESSAGE = "Empty response received from the server."
81
-
82
- def initialize(message = self.class::DEFAULT_MESSAGE)
83
- super(message)
84
- end
85
- end
86
-
87
- class BadResponseError < Protocol::Error
88
- def initialize(argument, expected, actual)
89
- super("Argument #{argument} has to be #{expected.inspect}, was #{data.inspect}")
90
- end
91
- end
92
-
93
- class SoftError < Protocol::Error
94
- def self.inherited(subclass)
95
- Error.inherited(subclass)
96
- end # self.inherited(subclass)
97
- end
98
-
99
- class HardError < Protocol::Error
100
- def self.inherited(subclass)
101
- Error.inherited(subclass)
102
- end # self.inherited(subclass)
103
- end
104
-
105
32
  % for tuple in spec.constants:
106
33
  % if tuple[2] == "soft-error" or tuple[2] == "hard-error":
107
34
  class ${codegen.to_ruby_class_name(tuple[0])} < ${codegen.to_ruby_class_name(tuple[2])}
@@ -111,21 +38,6 @@ module AMQ
111
38
  % endif
112
39
  % endfor
113
40
 
114
- # We don't instantiate the following classes,
115
- # as we don't actually need any per-instance state.
116
- # Also, this is pretty low-level functionality,
117
- # hence it should have a reasonable performance.
118
- # As everyone knows, garbage collector in MRI performs
119
- # really badly, which is another good reason for
120
- # not creating any objects, but only use class as
121
- # a struct. Creating classes is quite expensive though,
122
- # but here the inheritance comes handy and mainly
123
- # as we can't simply make a reference to a function,
124
- # we can't use a hash or an object. I've been also
125
- # considering to have just a bunch of methods, but
126
- # here's the problem, that after we'd require this file,
127
- # all these methods would become global which would
128
- # be a bad, bad thing to do.
129
41
  class Class
130
42
  @classes = Array.new
131
43
 
@@ -195,6 +107,7 @@ module AMQ
195
107
  # 4 bytes of frame payload length
196
108
  # 1 byte of payload trailer FRAME_END byte
197
109
  limit = frame_size - 8
110
+ return [BodyFrame.new(body, channel)] if body.bytesize < limit
198
111
 
199
112
  # Otherwise String#slice on 1.9 will operate with code points,
200
113
  # and we need bytes. MK.
@@ -203,24 +116,14 @@ module AMQ
203
116
  array = Array.new
204
117
  while body
205
118
  payload, body = body[0, limit], body[limit, body.length - limit]
206
- # array << [0x03, payload]
207
119
  array << BodyFrame.new(payload, channel)
208
120
  end
209
121
 
210
122
  array
211
123
  end
212
124
 
213
- # We can return different:
214
- # - instantiate given subclass of Method
215
- # - create an OpenStruct object
216
- # - create a hash
217
- # - yield params into the block rather than just return
218
- # @api plugin
219
125
  def self.instantiate(*args, &block)
220
126
  self.new(*args, &block)
221
- # or OpenStruct.new(args.first)
222
- # or args.first
223
- # or block.call(*args)
224
127
  end
225
128
  end
226
129
 
@@ -250,7 +153,6 @@ module AMQ
250
153
 
251
154
  % endif
252
155
 
253
- ## TODO: not only basic, resp. in fact it's only this class, but not necessarily in the future, rather check if properties are empty #}
254
156
  % if klass.name == "basic" :
255
157
  def self.encode_properties(body_size, properties)
256
158
  pieces, flags = [], 0
@@ -263,7 +165,7 @@ module AMQ
263
165
 
264
166
  # result = [${klass.index}, 0, body_size, flags].pack('n2Qn')
265
167
  result = [${klass.index}, 0].pack(PACK_UINT16_X2)
266
- result += AMQ::Hacks.pack_uint64_big_endian(body_size)
168
+ result += AMQ::Pack.pack_uint64_big_endian(body_size)
267
169
  result += [flags].pack(PACK_UINT16)
268
170
  result + pieces.join(EMPTY_STRING)
269
171
  end
@@ -376,8 +278,7 @@ module AMQ
376
278
  % if klass.name == "connection":
377
279
  channel = 0
378
280
  % endif
379
- buffer = ''
380
- buffer << @packed_indexes
281
+ buffer = @packed_indexes.dup
381
282
  % for line in helpers.genEncodeMethodDefinition(spec, method):
382
283
  ${line}
383
284
  % endfor
@@ -385,9 +286,8 @@ module AMQ
385
286
  frames = [MethodFrame.new(buffer, channel)]
386
287
  % if "user_headers" in method.args():
387
288
  properties, headers = self.split_headers(user_headers)
388
- # TODO: what shall I do with the headers?
389
289
  if properties.nil? or properties.empty?
390
- raise RuntimeError.new("Properties can not be empty!") # TODO: or can they?
290
+ raise RuntimeError.new("Properties can not be empty!")
391
291
  end
392
292
  properties_payload = Basic.encode_properties(payload.bytesize, properties)
393
293
  frames << HeaderFrame.new(properties_payload, channel)
@@ -2,10 +2,10 @@
2
2
 
3
3
  require 'amq/endianness'
4
4
 
5
- # Ruby doesn't support pack to/unpack from
6
- # 64bit string in network byte order.
7
5
  module AMQ
8
- module Hacks
6
+ # Implements pack to/unpack from 64bit string in network byte order
7
+ # compatible with Ruby 1.8+.
8
+ module Pack
9
9
  UINT64 = "Q".freeze
10
10
  INT16 = "c".freeze
11
11
 
@@ -47,7 +47,7 @@ module AMQ
47
47
  end
48
48
  end
49
49
  end
50
- end
51
50
 
52
- # AMQ::Hacks.pack_uint64_big_endian(17)
53
- # AMQ::Hacks.unpack_uint64_big_endian("\x00\x00\x00\x00\x00\x00\x00\x11")
51
+ # Backwards compatibility
52
+ Hacks = Pack
53
+ end
@@ -4,35 +4,19 @@
4
4
  # IT DIRECTLY ! FOR CHANGES, PLEASE UPDATE FILES
5
5
  # IN THE ./codegen DIRECTORY OF THE AMQ-PROTOCOL REPOSITORY.
6
6
 
7
+ require "amq/pack"
8
+
7
9
  require "amq/protocol/table"
8
10
  require "amq/protocol/frame"
9
- require "amq/hacks"
11
+
12
+ require "amq/protocol/constants"
13
+ require "amq/protocol/exceptions"
10
14
 
11
15
  module AMQ
12
16
  module Protocol
13
17
  PROTOCOL_VERSION = "0.9.1".freeze
14
18
  PREAMBLE = "AMQP\x00\x00\x09\x01".freeze
15
19
  DEFAULT_PORT = 5672
16
- TLS_PORT = 5671
17
- SSL_PORT = 5671
18
-
19
- # caching
20
- EMPTY_STRING = "".freeze
21
-
22
- PACK_INT8 = 'c'.freeze
23
- PACK_CHAR = 'C'.freeze
24
- PACK_UINT16 = 'n'.freeze
25
- PACK_UINT16_X2 = 'n2'.freeze
26
- PACK_UINT32 = 'N'.freeze
27
- PACK_UINT32_X2 = 'N2'.freeze
28
- PACK_INT64 = 'q'.freeze
29
- PACK_UCHAR_UINT32 = 'CN'.freeze
30
- PACK_CHAR_UINT16_UINT32 = 'cnN'.freeze
31
-
32
- PACK_32BIT_FLOAT = 'f'.freeze
33
- PACK_64BIT_FLOAT = 'G'.freeze
34
-
35
-
36
20
 
37
21
  # @return [Array] Collection of subclasses of AMQ::Protocol::Class.
38
22
  def self.classes
@@ -44,63 +28,6 @@ module AMQ
44
28
  Protocol::Method.methods
45
29
  end
46
30
 
47
- class Error < StandardError
48
- DEFAULT_MESSAGE = "AMQP error".freeze
49
-
50
- def self.inherited(subclass)
51
- @_subclasses ||= []
52
- @_subclasses << subclass
53
- end # self.inherited(subclazz)
54
-
55
- def self.subclasses_with_values
56
- @_subclasses.select{ |k| defined?(k::VALUE) }
57
- end # self.subclasses_with_values
58
-
59
- def self.[](code)
60
- if result = subclasses_with_values.detect { |klass| klass::VALUE == code }
61
- result
62
- else
63
- raise "No such exception class for code #{code}" unless result
64
- end # if
65
- end # self.[]
66
-
67
- def initialize(message = self.class::DEFAULT_MESSAGE)
68
- super(message)
69
- end
70
- end
71
-
72
- class FrameTypeError < Protocol::Error
73
- def initialize(types)
74
- super("Must be one of #{types.inspect}")
75
- end
76
- end
77
-
78
- class EmptyResponseError < Protocol::Error
79
- DEFAULT_MESSAGE = "Empty response received from the server."
80
-
81
- def initialize(message = self.class::DEFAULT_MESSAGE)
82
- super(message)
83
- end
84
- end
85
-
86
- class BadResponseError < Protocol::Error
87
- def initialize(argument, expected, actual)
88
- super("Argument #{argument} has to be #{expected.inspect}, was #{data.inspect}")
89
- end
90
- end
91
-
92
- class SoftError < Protocol::Error
93
- def self.inherited(subclass)
94
- Error.inherited(subclass)
95
- end # self.inherited(subclass)
96
- end
97
-
98
- class HardError < Protocol::Error
99
- def self.inherited(subclass)
100
- Error.inherited(subclass)
101
- end # self.inherited(subclass)
102
- end
103
-
104
31
  class ContentTooLarge < SoftError
105
32
  VALUE = 311
106
33
  end
@@ -174,21 +101,6 @@ module AMQ
174
101
  end
175
102
 
176
103
 
177
- # We don't instantiate the following classes,
178
- # as we don't actually need any per-instance state.
179
- # Also, this is pretty low-level functionality,
180
- # hence it should have a reasonable performance.
181
- # As everyone knows, garbage collector in MRI performs
182
- # really badly, which is another good reason for
183
- # not creating any objects, but only use class as
184
- # a struct. Creating classes is quite expensive though,
185
- # but here the inheritance comes handy and mainly
186
- # as we can't simply make a reference to a function,
187
- # we can't use a hash or an object. I've been also
188
- # considering to have just a bunch of methods, but
189
- # here's the problem, that after we'd require this file,
190
- # all these methods would become global which would
191
- # be a bad, bad thing to do.
192
104
  class Class
193
105
  @classes = Array.new
194
106
 
@@ -258,6 +170,7 @@ module AMQ
258
170
  # 4 bytes of frame payload length
259
171
  # 1 byte of payload trailer FRAME_END byte
260
172
  limit = frame_size - 8
173
+ return [BodyFrame.new(body, channel)] if body.bytesize < limit
261
174
 
262
175
  # Otherwise String#slice on 1.9 will operate with code points,
263
176
  # and we need bytes. MK.
@@ -266,24 +179,14 @@ module AMQ
266
179
  array = Array.new
267
180
  while body
268
181
  payload, body = body[0, limit], body[limit, body.length - limit]
269
- # array << [0x03, payload]
270
182
  array << BodyFrame.new(payload, channel)
271
183
  end
272
184
 
273
185
  array
274
186
  end
275
187
 
276
- # We can return different:
277
- # - instantiate given subclass of Method
278
- # - create an OpenStruct object
279
- # - create a hash
280
- # - yield params into the block rather than just return
281
- # @api plugin
282
188
  def self.instantiate(*args, &block)
283
189
  self.new(*args, &block)
284
- # or OpenStruct.new(args.first)
285
- # or args.first
286
- # or block.call(*args)
287
190
  end
288
191
  end
289
192
 
@@ -351,8 +254,7 @@ module AMQ
351
254
  # [u'client_properties = nil', u"mechanism = u'PLAIN'", u'response = nil', u"locale = u'en_US'"]
352
255
  def self.encode(client_properties, mechanism, response, locale)
353
256
  channel = 0
354
- buffer = ''
355
- buffer << @packed_indexes
257
+ buffer = @packed_indexes.dup
356
258
  buffer << AMQ::Protocol::Table.encode(client_properties)
357
259
  buffer << mechanism.to_s.bytesize.chr
358
260
  buffer << mechanism.to_s
@@ -408,8 +310,7 @@ module AMQ
408
310
  # [u'response = nil']
409
311
  def self.encode(response)
410
312
  channel = 0
411
- buffer = ''
412
- buffer << @packed_indexes
313
+ buffer = @packed_indexes.dup
413
314
  buffer << [response.to_s.bytesize].pack(PACK_UINT32)
414
315
  buffer << response.to_s
415
316
  MethodFrame.new(buffer, channel)
@@ -464,8 +365,7 @@ module AMQ
464
365
  # [u'channel_max = false', u'frame_max = false', u'heartbeat = false']
465
366
  def self.encode(channel_max, frame_max, heartbeat)
466
367
  channel = 0
467
- buffer = ''
468
- buffer << @packed_indexes
368
+ buffer = @packed_indexes.dup
469
369
  buffer << [channel_max].pack(PACK_UINT16)
470
370
  buffer << [frame_max].pack(PACK_UINT32)
471
371
  buffer << [heartbeat].pack(PACK_UINT16)
@@ -491,8 +391,7 @@ module AMQ
491
391
  capabilities = EMPTY_STRING
492
392
  insist = false
493
393
  channel = 0
494
- buffer = ''
495
- buffer << @packed_indexes
394
+ buffer = @packed_indexes.dup
496
395
  buffer << virtual_host.to_s.bytesize.chr
497
396
  buffer << virtual_host.to_s
498
397
  buffer << capabilities.to_s.bytesize.chr
@@ -571,8 +470,7 @@ module AMQ
571
470
  # [u'reply_code = nil', u'reply_text = EMPTY_STRING', u'class_id = nil', u'method_id = nil']
572
471
  def self.encode(reply_code, reply_text, class_id, method_id)
573
472
  channel = 0
574
- buffer = ''
575
- buffer << @packed_indexes
473
+ buffer = @packed_indexes.dup
576
474
  buffer << [reply_code].pack(PACK_UINT16)
577
475
  buffer << reply_text.to_s.bytesize.chr
578
476
  buffer << reply_text.to_s
@@ -606,8 +504,7 @@ module AMQ
606
504
  # []
607
505
  def self.encode()
608
506
  channel = 0
609
- buffer = ''
610
- buffer << @packed_indexes
507
+ buffer = @packed_indexes.dup
611
508
  MethodFrame.new(buffer, channel)
612
509
  end
613
510
 
@@ -635,8 +532,7 @@ module AMQ
635
532
  # @return
636
533
  # [u'out_of_band = EMPTY_STRING']
637
534
  def self.encode(channel, out_of_band)
638
- buffer = ''
639
- buffer << @packed_indexes
535
+ buffer = @packed_indexes.dup
640
536
  buffer << out_of_band.to_s.bytesize.chr
641
537
  buffer << out_of_band.to_s
642
538
  MethodFrame.new(buffer, channel)
@@ -699,8 +595,7 @@ module AMQ
699
595
  # @return
700
596
  # [u'active = nil']
701
597
  def self.encode(channel, active)
702
- buffer = ''
703
- buffer << @packed_indexes
598
+ buffer = @packed_indexes.dup
704
599
  bit_buffer = 0
705
600
  bit_buffer = bit_buffer | (1 << 0) if active
706
601
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -736,8 +631,7 @@ module AMQ
736
631
  # @return
737
632
  # [u'active = nil']
738
633
  def self.encode(channel, active)
739
- buffer = ''
740
- buffer << @packed_indexes
634
+ buffer = @packed_indexes.dup
741
635
  bit_buffer = 0
742
636
  bit_buffer = bit_buffer | (1 << 0) if active
743
637
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -783,8 +677,7 @@ module AMQ
783
677
  # @return
784
678
  # [u'reply_code = nil', u'reply_text = EMPTY_STRING', u'class_id = nil', u'method_id = nil']
785
679
  def self.encode(channel, reply_code, reply_text, class_id, method_id)
786
- buffer = ''
787
- buffer << @packed_indexes
680
+ buffer = @packed_indexes.dup
788
681
  buffer << [reply_code].pack(PACK_UINT16)
789
682
  buffer << reply_text.to_s.bytesize.chr
790
683
  buffer << reply_text.to_s
@@ -817,8 +710,7 @@ module AMQ
817
710
  # @return
818
711
  # []
819
712
  def self.encode(channel)
820
- buffer = ''
821
- buffer << @packed_indexes
713
+ buffer = @packed_indexes.dup
822
714
  MethodFrame.new(buffer, channel)
823
715
  end
824
716
 
@@ -847,8 +739,7 @@ module AMQ
847
739
  # [u'ticket = 0', u'exchange = nil', u"type = u'direct'", u'passive = false', u'durable = false', u'auto_delete = false', u'internal = false', u'nowait = false', u'arguments = {}']
848
740
  def self.encode(channel, exchange, type, passive, durable, auto_delete, internal, nowait, arguments)
849
741
  ticket = 0
850
- buffer = ''
851
- buffer << @packed_indexes
742
+ buffer = @packed_indexes.dup
852
743
  buffer << [ticket].pack(PACK_UINT16)
853
744
  buffer << exchange.to_s.bytesize.chr
854
745
  buffer << exchange.to_s
@@ -904,8 +795,7 @@ module AMQ
904
795
  # [u'ticket = 0', u'exchange = nil', u'if_unused = false', u'nowait = false']
905
796
  def self.encode(channel, exchange, if_unused, nowait)
906
797
  ticket = 0
907
- buffer = ''
908
- buffer << @packed_indexes
798
+ buffer = @packed_indexes.dup
909
799
  buffer << [ticket].pack(PACK_UINT16)
910
800
  buffer << exchange.to_s.bytesize.chr
911
801
  buffer << exchange.to_s
@@ -955,8 +845,7 @@ module AMQ
955
845
  # [u'ticket = 0', u'destination = nil', u'source = nil', u'routing_key = EMPTY_STRING', u'nowait = false', u'arguments = {}']
956
846
  def self.encode(channel, destination, source, routing_key, nowait, arguments)
957
847
  ticket = 0
958
- buffer = ''
959
- buffer << @packed_indexes
848
+ buffer = @packed_indexes.dup
960
849
  buffer << [ticket].pack(PACK_UINT16)
961
850
  buffer << destination.to_s.bytesize.chr
962
851
  buffer << destination.to_s
@@ -1010,8 +899,7 @@ module AMQ
1010
899
  # [u'ticket = 0', u'destination = nil', u'source = nil', u'routing_key = EMPTY_STRING', u'nowait = false', u'arguments = {}']
1011
900
  def self.encode(channel, destination, source, routing_key, nowait, arguments)
1012
901
  ticket = 0
1013
- buffer = ''
1014
- buffer << @packed_indexes
902
+ buffer = @packed_indexes.dup
1015
903
  buffer << [ticket].pack(PACK_UINT16)
1016
904
  buffer << destination.to_s.bytesize.chr
1017
905
  buffer << destination.to_s
@@ -1073,8 +961,7 @@ module AMQ
1073
961
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'passive = false', u'durable = false', u'exclusive = false', u'auto_delete = false', u'nowait = false', u'arguments = {}']
1074
962
  def self.encode(channel, queue, passive, durable, exclusive, auto_delete, nowait, arguments)
1075
963
  ticket = 0
1076
- buffer = ''
1077
- buffer << @packed_indexes
964
+ buffer = @packed_indexes.dup
1078
965
  buffer << [ticket].pack(PACK_UINT16)
1079
966
  buffer << queue.to_s.bytesize.chr
1080
967
  buffer << queue.to_s
@@ -1140,8 +1027,7 @@ module AMQ
1140
1027
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'exchange = nil', u'routing_key = EMPTY_STRING', u'nowait = false', u'arguments = {}']
1141
1028
  def self.encode(channel, queue, exchange, routing_key, nowait, arguments)
1142
1029
  ticket = 0
1143
- buffer = ''
1144
- buffer << @packed_indexes
1030
+ buffer = @packed_indexes.dup
1145
1031
  buffer << [ticket].pack(PACK_UINT16)
1146
1032
  buffer << queue.to_s.bytesize.chr
1147
1033
  buffer << queue.to_s
@@ -1195,8 +1081,7 @@ module AMQ
1195
1081
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'nowait = false']
1196
1082
  def self.encode(channel, queue, nowait)
1197
1083
  ticket = 0
1198
- buffer = ''
1199
- buffer << @packed_indexes
1084
+ buffer = @packed_indexes.dup
1200
1085
  buffer << [ticket].pack(PACK_UINT16)
1201
1086
  buffer << queue.to_s.bytesize.chr
1202
1087
  buffer << queue.to_s
@@ -1249,8 +1134,7 @@ module AMQ
1249
1134
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'if_unused = false', u'if_empty = false', u'nowait = false']
1250
1135
  def self.encode(channel, queue, if_unused, if_empty, nowait)
1251
1136
  ticket = 0
1252
- buffer = ''
1253
- buffer << @packed_indexes
1137
+ buffer = @packed_indexes.dup
1254
1138
  buffer << [ticket].pack(PACK_UINT16)
1255
1139
  buffer << queue.to_s.bytesize.chr
1256
1140
  buffer << queue.to_s
@@ -1305,8 +1189,7 @@ module AMQ
1305
1189
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'exchange = nil', u'routing_key = EMPTY_STRING', u'arguments = {}']
1306
1190
  def self.encode(channel, queue, exchange, routing_key, arguments)
1307
1191
  ticket = 0
1308
- buffer = ''
1309
- buffer << @packed_indexes
1192
+ buffer = @packed_indexes.dup
1310
1193
  buffer << [ticket].pack(PACK_UINT16)
1311
1194
  buffer << queue.to_s.bytesize.chr
1312
1195
  buffer << queue.to_s
@@ -1437,7 +1320,7 @@ module AMQ
1437
1320
  # 1 << 6
1438
1321
  def self.encode_timestamp(value)
1439
1322
  buffer = ''
1440
- buffer << AMQ::Hacks.pack_uint64_big_endian(value)
1323
+ buffer << AMQ::Pack.pack_uint64_big_endian(value)
1441
1324
  [9, 0x0040, buffer]
1442
1325
  end
1443
1326
 
@@ -1486,7 +1369,7 @@ module AMQ
1486
1369
 
1487
1370
  # result = [60, 0, body_size, flags].pack('n2Qn')
1488
1371
  result = [60, 0].pack(PACK_UINT16_X2)
1489
- result += AMQ::Hacks.pack_uint64_big_endian(body_size)
1372
+ result += AMQ::Pack.pack_uint64_big_endian(body_size)
1490
1373
  result += [flags].pack(PACK_UINT16)
1491
1374
  result + pieces.join(EMPTY_STRING)
1492
1375
  end
@@ -1592,8 +1475,7 @@ module AMQ
1592
1475
  # @return
1593
1476
  # [u'prefetch_size = false', u'prefetch_count = false', u'global = false']
1594
1477
  def self.encode(channel, prefetch_size, prefetch_count, global)
1595
- buffer = ''
1596
- buffer << @packed_indexes
1478
+ buffer = @packed_indexes.dup
1597
1479
  buffer << [prefetch_size].pack(PACK_UINT32)
1598
1480
  buffer << [prefetch_count].pack(PACK_UINT16)
1599
1481
  bit_buffer = 0
@@ -1641,8 +1523,7 @@ module AMQ
1641
1523
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'consumer_tag = EMPTY_STRING', u'no_local = false', u'no_ack = false', u'exclusive = false', u'nowait = false', u'arguments = {}']
1642
1524
  def self.encode(channel, queue, consumer_tag, no_local, no_ack, exclusive, nowait, arguments)
1643
1525
  ticket = 0
1644
- buffer = ''
1645
- buffer << @packed_indexes
1526
+ buffer = @packed_indexes.dup
1646
1527
  buffer << [ticket].pack(PACK_UINT16)
1647
1528
  buffer << queue.to_s.bytesize.chr
1648
1529
  buffer << queue.to_s
@@ -1720,8 +1601,7 @@ module AMQ
1720
1601
  # @return
1721
1602
  # [u'consumer_tag = nil', u'nowait = false']
1722
1603
  def self.encode(channel, consumer_tag, nowait)
1723
- buffer = ''
1724
- buffer << @packed_indexes
1604
+ buffer = @packed_indexes.dup
1725
1605
  buffer << consumer_tag.to_s.bytesize.chr
1726
1606
  buffer << consumer_tag.to_s
1727
1607
  bit_buffer = 0
@@ -1775,8 +1655,7 @@ module AMQ
1775
1655
  # [u'ticket = 0', u'exchange = EMPTY_STRING', u'routing_key = EMPTY_STRING', u'mandatory = false', u'immediate = false', 'user_headers = nil', 'payload = ""', 'frame_size = nil']
1776
1656
  def self.encode(channel, payload, user_headers, exchange, routing_key, mandatory, immediate, frame_size)
1777
1657
  ticket = 0
1778
- buffer = ''
1779
- buffer << @packed_indexes
1658
+ buffer = @packed_indexes.dup
1780
1659
  buffer << [ticket].pack(PACK_UINT16)
1781
1660
  buffer << exchange.to_s.bytesize.chr
1782
1661
  buffer << exchange.to_s
@@ -1788,9 +1667,8 @@ module AMQ
1788
1667
  buffer << [bit_buffer].pack(PACK_CHAR)
1789
1668
  frames = [MethodFrame.new(buffer, channel)]
1790
1669
  properties, headers = self.split_headers(user_headers)
1791
- # TODO: what shall I do with the headers?
1792
1670
  if properties.nil? or properties.empty?
1793
- raise RuntimeError.new("Properties can not be empty!") # TODO: or can they?
1671
+ raise RuntimeError.new("Properties can not be empty!")
1794
1672
  end
1795
1673
  properties_payload = Basic.encode_properties(payload.bytesize, properties)
1796
1674
  frames << HeaderFrame.new(properties_payload, channel)
@@ -1854,7 +1732,7 @@ module AMQ
1854
1732
  offset += 1
1855
1733
  consumer_tag = data[offset, length]
1856
1734
  offset += length
1857
- delivery_tag = AMQ::Hacks.unpack_uint64_big_endian(data[offset, 8]).first
1735
+ delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
1858
1736
  offset += 8
1859
1737
  bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
1860
1738
  offset += 1
@@ -1901,8 +1779,7 @@ module AMQ
1901
1779
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'no_ack = false']
1902
1780
  def self.encode(channel, queue, no_ack)
1903
1781
  ticket = 0
1904
- buffer = ''
1905
- buffer << @packed_indexes
1782
+ buffer = @packed_indexes.dup
1906
1783
  buffer << [ticket].pack(PACK_UINT16)
1907
1784
  buffer << queue.to_s.bytesize.chr
1908
1785
  buffer << queue.to_s
@@ -1923,7 +1800,7 @@ module AMQ
1923
1800
  # @return
1924
1801
  def self.decode(data)
1925
1802
  offset = 0
1926
- delivery_tag = AMQ::Hacks.unpack_uint64_big_endian(data[offset, 8]).first
1803
+ delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
1927
1804
  offset += 8
1928
1805
  bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
1929
1806
  offset += 1
@@ -1994,7 +1871,7 @@ module AMQ
1994
1871
  # @return
1995
1872
  def self.decode(data)
1996
1873
  offset = 0
1997
- delivery_tag = AMQ::Hacks.unpack_uint64_big_endian(data[offset, 8]).first
1874
+ delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
1998
1875
  offset += 8
1999
1876
  bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
2000
1877
  offset += 1
@@ -2015,9 +1892,8 @@ module AMQ
2015
1892
  # @return
2016
1893
  # [u'delivery_tag = false', u'multiple = false']
2017
1894
  def self.encode(channel, delivery_tag, multiple)
2018
- buffer = ''
2019
- buffer << @packed_indexes
2020
- buffer << AMQ::Hacks.pack_uint64_big_endian(delivery_tag)
1895
+ buffer = @packed_indexes.dup
1896
+ buffer << AMQ::Pack.pack_uint64_big_endian(delivery_tag)
2021
1897
  bit_buffer = 0
2022
1898
  bit_buffer = bit_buffer | (1 << 0) if multiple
2023
1899
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -2040,9 +1916,8 @@ module AMQ
2040
1916
  # @return
2041
1917
  # [u'delivery_tag = nil', u'requeue = true']
2042
1918
  def self.encode(channel, delivery_tag, requeue)
2043
- buffer = ''
2044
- buffer << @packed_indexes
2045
- buffer << AMQ::Hacks.pack_uint64_big_endian(delivery_tag)
1919
+ buffer = @packed_indexes.dup
1920
+ buffer << AMQ::Pack.pack_uint64_big_endian(delivery_tag)
2046
1921
  bit_buffer = 0
2047
1922
  bit_buffer = bit_buffer | (1 << 0) if requeue
2048
1923
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -2065,8 +1940,7 @@ module AMQ
2065
1940
  # @return
2066
1941
  # [u'requeue = false']
2067
1942
  def self.encode(channel, requeue)
2068
- buffer = ''
2069
- buffer << @packed_indexes
1943
+ buffer = @packed_indexes.dup
2070
1944
  bit_buffer = 0
2071
1945
  bit_buffer = bit_buffer | (1 << 0) if requeue
2072
1946
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -2089,8 +1963,7 @@ module AMQ
2089
1963
  # @return
2090
1964
  # [u'requeue = false']
2091
1965
  def self.encode(channel, requeue)
2092
- buffer = ''
2093
- buffer << @packed_indexes
1966
+ buffer = @packed_indexes.dup
2094
1967
  bit_buffer = 0
2095
1968
  bit_buffer = bit_buffer | (1 << 0) if requeue
2096
1969
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -2130,7 +2003,7 @@ module AMQ
2130
2003
  # @return
2131
2004
  def self.decode(data)
2132
2005
  offset = 0
2133
- delivery_tag = AMQ::Hacks.unpack_uint64_big_endian(data[offset, 8]).first
2006
+ delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
2134
2007
  offset += 8
2135
2008
  bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
2136
2009
  offset += 1
@@ -2153,9 +2026,8 @@ module AMQ
2153
2026
  # @return
2154
2027
  # [u'delivery_tag = false', u'multiple = false', u'requeue = true']
2155
2028
  def self.encode(channel, delivery_tag, multiple, requeue)
2156
- buffer = ''
2157
- buffer << @packed_indexes
2158
- buffer << AMQ::Hacks.pack_uint64_big_endian(delivery_tag)
2029
+ buffer = @packed_indexes.dup
2030
+ buffer << AMQ::Pack.pack_uint64_big_endian(delivery_tag)
2159
2031
  bit_buffer = 0
2160
2032
  bit_buffer = bit_buffer | (1 << 0) if multiple
2161
2033
  bit_buffer = bit_buffer | (1 << 1) if requeue
@@ -2200,8 +2072,7 @@ module AMQ
2200
2072
  # @return
2201
2073
  # [u'consumer_tag = EMPTY_STRING', u'credit = nil', u'drain = nil']
2202
2074
  def self.encode(channel, consumer_tag, credit, drain)
2203
- buffer = ''
2204
- buffer << @packed_indexes
2075
+ buffer = @packed_indexes.dup
2205
2076
  buffer << consumer_tag.to_s.bytesize.chr
2206
2077
  buffer << consumer_tag.to_s
2207
2078
  buffer << [credit].pack(PACK_UINT32)
@@ -2239,8 +2110,7 @@ module AMQ
2239
2110
  # @return
2240
2111
  # [u'available = nil']
2241
2112
  def self.encode(channel, available)
2242
- buffer = ''
2243
- buffer << @packed_indexes
2113
+ buffer = @packed_indexes.dup
2244
2114
  buffer << [available].pack(PACK_UINT32)
2245
2115
  MethodFrame.new(buffer, channel)
2246
2116
  end
@@ -2278,8 +2148,7 @@ module AMQ
2278
2148
  # @return
2279
2149
  # [u'consumer_tag = EMPTY_STRING', u'credit_drained = nil']
2280
2150
  def self.encode(channel, consumer_tag, credit_drained)
2281
- buffer = ''
2282
- buffer << @packed_indexes
2151
+ buffer = @packed_indexes.dup
2283
2152
  buffer << consumer_tag.to_s.bytesize.chr
2284
2153
  buffer << consumer_tag.to_s
2285
2154
  buffer << [credit_drained].pack(PACK_UINT32)
@@ -2310,8 +2179,7 @@ module AMQ
2310
2179
  # @return
2311
2180
  # []
2312
2181
  def self.encode(channel)
2313
- buffer = ''
2314
- buffer << @packed_indexes
2182
+ buffer = @packed_indexes.dup
2315
2183
  MethodFrame.new(buffer, channel)
2316
2184
  end
2317
2185
 
@@ -2353,8 +2221,7 @@ module AMQ
2353
2221
  # @return
2354
2222
  # []
2355
2223
  def self.encode(channel)
2356
- buffer = ''
2357
- buffer << @packed_indexes
2224
+ buffer = @packed_indexes.dup
2358
2225
  MethodFrame.new(buffer, channel)
2359
2226
  end
2360
2227
 
@@ -2396,8 +2263,7 @@ module AMQ
2396
2263
  # @return
2397
2264
  # []
2398
2265
  def self.encode(channel)
2399
- buffer = ''
2400
- buffer << @packed_indexes
2266
+ buffer = @packed_indexes.dup
2401
2267
  MethodFrame.new(buffer, channel)
2402
2268
  end
2403
2269
 
@@ -2460,8 +2326,7 @@ module AMQ
2460
2326
  # @return
2461
2327
  # [u'nowait = false']
2462
2328
  def self.encode(channel, nowait)
2463
- buffer = ''
2464
- buffer << @packed_indexes
2329
+ buffer = @packed_indexes.dup
2465
2330
  bit_buffer = 0
2466
2331
  bit_buffer = bit_buffer | (1 << 0) if nowait
2467
2332
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -2492,8 +2357,7 @@ module AMQ
2492
2357
  # @return
2493
2358
  # []
2494
2359
  def self.encode(channel)
2495
- buffer = ''
2496
- buffer << @packed_indexes
2360
+ buffer = @packed_indexes.dup
2497
2361
  MethodFrame.new(buffer, channel)
2498
2362
  end
2499
2363