rabbitmq 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 244f595aa2d3971af7abf7ca4cc7ef6c56c210c1
4
- data.tar.gz: 3d416e1b3667a19c547bc11a81ca0cdf6c2530ed
3
+ metadata.gz: 1c1c764cdfb743927b47bbd5165898582458c656
4
+ data.tar.gz: dda4411b342ca6e609562976f6fc981d9eb67577
5
5
  SHA512:
6
- metadata.gz: 9440df7f81db2e10d88d69816da91a1f059db6581c5d7e136b58bee98b5e516e4f8250ad87f7bbb43ff53b790915da1d44566b05998f33036b06b9e8742d9e3a
7
- data.tar.gz: 48489bb898751dd7a433e5a7456216a08650736b6b84b9fcc67acd21eef003da45d4d60f767626458d92569394c8e9c5cc7b446f378a7a1a3c00a3d033ec3b9f
6
+ metadata.gz: 6d3cee85a69364b25a15087b264fb47c906bbd1dd94c76a9fb56ffb06171f093ef9ffa78363dabb0dca23c2def71bf2bbe45c2d4a9e0b029e92074beb6dd4c9e
7
+ data.tar.gz: 5d418e13636abdd2189c7b49072abdf2ca4a9ed053dc7711d2fc60d009067a8a3202ecb77548d3c77df671d84ce49c8d1991d8110e10352ad2813c5dd4b85da3
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Joe McIlvain
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+
2
+ require 'rake/clean'
3
+
4
+ FILES = {}
5
+
6
+ task :default => :build
7
+
8
+ def self.file_task(filename, opts, &block)
9
+ name, dep = opts.is_a?(Hash) ? opts.to_a.first : [opts, nil]
10
+
11
+ FILES[name] = filename
12
+ CLEAN.include filename
13
+ task name => filename
14
+
15
+ if dep
16
+ file filename => FILES[dep], &block
17
+ else
18
+ file filename, &block
19
+ end
20
+ end
21
+
22
+ file_task 'rabbitmq-c.tar.gz', :download_tarball do
23
+ version = "0.6.0"
24
+ release = "https://github.com/alanxz/rabbitmq-c/releases/download/v#{version}/rabbitmq-c-#{version}.tar.gz"
25
+ system "wget #{release}"
26
+ system "mv #{File.basename(release)} #{FILES[:download_tarball]}"
27
+ end
28
+
29
+ file_task 'rabbitmq-c', :download => :download_tarball do
30
+ system "tar -xf #{FILES[:download_tarball]}"
31
+ system "mv rabbitmq-c-* #{FILES[:download]}"
32
+ end
33
+
34
+ file_task 'config.status', :configure => :download do
35
+ system "bash -c 'cd #{FILES[:download]} && ./configure'"
36
+ system "cp #{FILES[:download]}/#{FILES[:configure]} ./"
37
+ end
38
+
39
+ file_task 'librabbitmq.so', :build => :configure do
40
+ system "bash -c 'cd #{FILES[:download]} && make'"
41
+ system "cp #{FILES[:download]}/librabbitmq/.libs/#{FILES[:build]} ."
42
+ end
data/lib/rabbitmq.rb CHANGED
@@ -1,2 +1,8 @@
1
1
 
2
2
  require_relative 'rabbitmq/ffi'
3
+ require_relative 'rabbitmq/ffi/ext'
4
+ require_relative 'rabbitmq/ffi/error'
5
+
6
+ require_relative 'rabbitmq/util'
7
+
8
+ require_relative 'rabbitmq/connection'
@@ -0,0 +1,112 @@
1
+
2
+ module RabbitMQ
3
+ class Connection
4
+ def initialize *args
5
+ @ptr = FFI.amqp_new_connection
6
+ parse_info(*args)
7
+ create_socket!
8
+
9
+ @finalizer = self.class.send :create_finalizer_for, @ptr
10
+ ObjectSpace.define_finalizer self, @finalizer
11
+ end
12
+
13
+ def destroy
14
+ if @finalizer
15
+ @finalizer.call
16
+ ObjectSpace.undefine_finalizer self
17
+ end
18
+ @ptr = @socket = @finalizer = nil
19
+ end
20
+
21
+ class DestroyedError < RuntimeError; end
22
+
23
+ # @private
24
+ def self.create_finalizer_for(ptr)
25
+ Proc.new do
26
+ FFI.amqp_connection_close(ptr, 200)
27
+ FFI.amqp_destroy_connection(ptr)
28
+ end
29
+ end
30
+
31
+ def user; @info[:user]; end
32
+ def password; @info[:password]; end
33
+ def host; @info[:host]; end
34
+ def vhost; @info[:vhost]; end
35
+ def port; @info[:port]; end
36
+ def ssl?; @info[:ssl]; end
37
+
38
+ def max_channels; @max_channels ||= 0; end; attr_writer :max_channels
39
+ def max_frame_size; @max_frame_size ||= 131072; end; attr_writer :max_frame_size
40
+ def heartbeat_interval; 0; end # not fully implemented in librabbitmq
41
+
42
+ def start
43
+ close # Close if already open
44
+ connect_socket!
45
+ login!
46
+ open_channel!
47
+ end
48
+
49
+ def close
50
+ raise DestroyedError unless @ptr
51
+ FFI.amqp_connection_close(@ptr, 200)
52
+ end
53
+
54
+ private def parse_info url=nil
55
+ info = FFI::ConnectionInfo.new
56
+
57
+ if url
58
+ url_ptr = Util.strdup_ptr(url)
59
+ Util.error_check :"parsing connection URL",
60
+ FFI.amqp_parse_url(url_ptr, info)
61
+
62
+ # We must copy ConnectionInfo before the url_ptr is freed.
63
+ @info = info.to_h
64
+ url_ptr.free
65
+ else
66
+ FFI.amqp_default_connection_info(info)
67
+ @info = info.to_h
68
+ end
69
+ end
70
+
71
+ private def create_socket!
72
+ raise DestroyedError unless @ptr
73
+
74
+ @socket = FFI.amqp_tcp_socket_new(@ptr)
75
+ Util.null_check :"creating a socket", @socket
76
+ end
77
+
78
+ private def connect_socket!
79
+ raise DestroyedError unless @ptr
80
+ raise NotImplementedError if ssl?
81
+
82
+ create_socket!
83
+ Util.error_check :"opening a socket",
84
+ FFI.amqp_socket_open(@socket, host, port)
85
+ end
86
+
87
+ private def login!
88
+ raise DestroyedError unless @ptr
89
+
90
+ rpc_check :"logging in",
91
+ FFI.amqp_login(@ptr, vhost, max_channels, max_frame_size,
92
+ heartbeat_interval, :plain, :string, user, :string, password)
93
+
94
+ @server_properties = FFI::Table.new(FFI.amqp_get_server_properties(@ptr)).to_h
95
+ end
96
+
97
+ private def open_channel!(number=1)
98
+ raise DestroyedError unless @ptr
99
+
100
+ FFI.amqp_channel_open(@ptr, number)
101
+ rpc_check :"opening channel", FFI.amqp_get_rpc_reply(@ptr)
102
+ end
103
+
104
+ private def rpc_check action, res
105
+ case res[:reply_type]
106
+ when :library_exception; Util.error_check action, res[:library_error]
107
+ when :server_exception; raise NotImplementedError
108
+ else res
109
+ end
110
+ end
111
+ end
112
+ end
data/lib/rabbitmq/ffi.rb CHANGED
@@ -6,24 +6,10 @@ module RabbitMQ
6
6
  module FFI
7
7
  extend ::FFI::Library
8
8
 
9
- def self.available?
10
- @available
11
- end
12
-
13
- begin
14
- lib_name = 'librabbitmq'
15
- lib_paths = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
16
- .map { |path| "#{path}/#{lib_name}.#{::FFI::Platform::LIBSUFFIX}" }
17
- ffi_lib lib_paths + [lib_name]
18
- @available = true
19
- rescue LoadError
20
- warn ""
21
- warn "WARNING: #{self} is not available without librabbitmq."
22
- warn ""
23
- @available = false
24
- end
9
+ ffi_lib \
10
+ File.expand_path("../../ext/rabbitmq/librabbitmq.so", File.dirname(__FILE__))
25
11
 
26
- if available?
12
+ begin # TODO: remove begin/end block
27
13
  opts = {
28
14
  blocking: true # only necessary on MRI to deal with the GIL.
29
15
  }
@@ -33,10 +19,87 @@ module RabbitMQ
33
19
  attach_function :amqp_version_number, [], :uint32, **opts
34
20
  attach_function :amqp_version, [], :string, **opts
35
21
 
36
- Boolean = :int
37
- MethodNumber = :uint32
38
- Flags = :uint32
39
- Channel = :uint16
22
+ class Timeval < ::FFI::Struct
23
+ layout :tv_sec, :time_t,
24
+ :tv_usec, :suseconds_t
25
+ end
26
+
27
+ class Boolean
28
+ extend ::FFI::DataConverter
29
+ native_type ::FFI::TypeDefs[:int]
30
+ def self.to_native val, ctx; val ? 1 : 0; end
31
+ def self.from_native val, ctx; val != 0; end
32
+ end
33
+
34
+ MethodNumber = enum ::FFI::TypeDefs[:uint32], [
35
+ :connection_start, 0x000A000A, # 10, 10; 655370
36
+ :connection_start_ok, 0x000A000B, # 10, 11; 655371
37
+ :connection_secure, 0x000A0014, # 10, 20; 655380
38
+ :connection_secure_ok, 0x000A0015, # 10, 21; 655381
39
+ :connection_tune, 0x000A001E, # 10, 30; 655390
40
+ :connection_tune_ok, 0x000A001F, # 10, 31; 655391
41
+ :connection_open, 0x000A0028, # 10, 40; 655400
42
+ :connection_open_ok, 0x000A0029, # 10, 41; 655401
43
+ :connection_close, 0x000A0032, # 10, 50; 655410
44
+ :connection_close_ok, 0x000A0033, # 10, 51; 655411
45
+ :connection_blocked, 0x000A003C, # 10, 60; 655420
46
+ :connection_unblocked, 0x000A003D, # 10, 61; 655421
47
+ :channel_open, 0x0014000A, # 20, 10; 1310730
48
+ :channel_open_ok, 0x0014000B, # 20, 11; 1310731
49
+ :channel_flow, 0x00140014, # 20, 20; 1310740
50
+ :channel_flow_ok, 0x00140015, # 20, 21; 1310741
51
+ :channel_close, 0x00140028, # 20, 40; 1310760
52
+ :channel_close_ok, 0x00140029, # 20, 41; 1310761
53
+ :access_request, 0x001E000A, # 30, 10; 1966090
54
+ :access_request_ok, 0x001E000B, # 30, 11; 1966091
55
+ :exchange_declare, 0x0028000A, # 40, 10; 2621450
56
+ :exchange_declare_ok, 0x0028000B, # 40, 11; 2621451
57
+ :exchange_delete, 0x00280014, # 40, 20; 2621460
58
+ :exchange_delete_ok, 0x00280015, # 40, 21; 2621461
59
+ :exchange_bind, 0x0028001E, # 40, 30; 2621470
60
+ :exchange_bind_ok, 0x0028001F, # 40, 31; 2621471
61
+ :exchange_unbind, 0x00280028, # 40, 40; 2621480
62
+ :exchange_unbind_ok, 0x00280033, # 40, 51; 2621491
63
+ :queue_declare, 0x0032000A, # 50, 10; 3276810
64
+ :queue_declare_ok, 0x0032000B, # 50, 11; 3276811
65
+ :queue_bind, 0x00320014, # 50, 20; 3276820
66
+ :queue_bind_ok, 0x00320015, # 50, 21; 3276821
67
+ :queue_purge, 0x0032001E, # 50, 30; 3276830
68
+ :queue_purge_ok, 0x0032001F, # 50, 31; 3276831
69
+ :queue_delete, 0x00320028, # 50, 40; 3276840
70
+ :queue_delete_ok, 0x00320029, # 50, 41; 3276841
71
+ :queue_unbind, 0x00320032, # 50, 50; 3276850
72
+ :queue_unbind_ok, 0x00320033, # 50, 51; 3276851
73
+ :basic_qos, 0x003C000A, # 60, 10; 3932170
74
+ :basic_qos_ok, 0x003C000B, # 60, 11; 3932171
75
+ :basic_consume, 0x003C0014, # 60, 20; 3932180
76
+ :basic_consume_ok, 0x003C0015, # 60, 21; 3932181
77
+ :basic_cancel, 0x003C001E, # 60, 30; 3932190
78
+ :basic_cancel_ok, 0x003C001F, # 60, 31; 3932191
79
+ :basic_publish, 0x003C0028, # 60, 40; 3932200
80
+ :basic_return, 0x003C0032, # 60, 50; 3932210
81
+ :basic_deliver, 0x003C003C, # 60, 60; 3932220
82
+ :basic_get, 0x003C0046, # 60, 70; 3932230
83
+ :basic_get_ok, 0x003C0047, # 60, 71; 3932231
84
+ :basic_get_empty, 0x003C0048, # 60, 72; 3932232
85
+ :basic_ack, 0x003C0050, # 60, 80; 3932240
86
+ :basic_reject, 0x003C005A, # 60, 90; 3932250
87
+ :basic_recover_async, 0x003C0064, # 60, 100; 3932260
88
+ :basic_recover, 0x003C006E, # 60, 110; 3932270
89
+ :basic_recover_ok, 0x003C006F, # 60, 111; 3932271
90
+ :basic_nack, 0x003C0078, # 60, 120; 3932280
91
+ :tx_select, 0x005A000A, # 90, 10; 5898250
92
+ :tx_select_ok, 0x005A000B, # 90, 11; 5898251
93
+ :tx_commit, 0x005A0014, # 90, 20; 5898260
94
+ :tx_commit_ok, 0x005A0015, # 90, 21; 5898261
95
+ :tx_rollback, 0x005A001E, # 90, 30; 5898270
96
+ :tx_rollback_ok, 0x005A001F, # 90, 31; 5898271
97
+ :confirm_select, 0x0055000A, # 85, 10; 5570570
98
+ :confirm_select_ok, 0x0055000B, # 85, 11; 5570571
99
+ ]
100
+
101
+ Flags = :uint32
102
+ Channel = :uint16
40
103
 
41
104
  class Bytes < ::FFI::Struct
42
105
  layout :len, :size_t,
@@ -58,6 +121,27 @@ module RabbitMQ
58
121
  :entries, :pointer
59
122
  end
60
123
 
124
+ FieldValueKind = enum ::FFI::TypeDefs[:uint8], [
125
+ :boolean, 't'.ord,
126
+ :i8, 'b'.ord,
127
+ :u8, 'B'.ord,
128
+ :i16, 's'.ord,
129
+ :u16, 'u'.ord,
130
+ :i32, 'I'.ord,
131
+ :u32, 'i'.ord,
132
+ :i64, 'l'.ord,
133
+ :u64, 'L'.ord,
134
+ :f32, 'f'.ord,
135
+ :f64, 'd'.ord,
136
+ :decimal, 'D'.ord,
137
+ :utf8, 'S'.ord,
138
+ :array, 'A'.ord,
139
+ :timestamp, 'T'.ord,
140
+ :table, 'F'.ord,
141
+ :void, 'V'.ord,
142
+ :bytes, 'x'.ord,
143
+ ]
144
+
61
145
  class FieldValueValue < ::FFI::Union
62
146
  layout :boolean, Boolean,
63
147
  :i8, :int8,
@@ -77,7 +161,7 @@ module RabbitMQ
77
161
  end
78
162
 
79
163
  class FieldValue < ::FFI::Struct
80
- layout :kind, :uint8,
164
+ layout :kind, FieldValueKind,
81
165
  :value, FieldValueValue
82
166
  end
83
167
 
@@ -86,27 +170,6 @@ module RabbitMQ
86
170
  :value, FieldValue
87
171
  end
88
172
 
89
- FieldValueKindEnum = enum [
90
- :boolean, 't'.ord,
91
- :i8, 'b'.ord,
92
- :u8, 'B'.ord,
93
- :i16, 's'.ord,
94
- :u16, 'u'.ord,
95
- :i32, 'I'.ord,
96
- :u32, 'i'.ord,
97
- :i64, 'l'.ord,
98
- :u64, 'L'.ord,
99
- :f32, 'f'.ord,
100
- :f64, 'd'.ord,
101
- :decimal, 'D'.ord,
102
- :utf8, 'S'.ord,
103
- :array, 'A'.ord,
104
- :timestamp, 'T'.ord,
105
- :table, 'F'.ord,
106
- :void, 'V'.ord,
107
- :bytes, 'x'.ord,
108
- ]
109
-
110
173
  class PoolBlocklist < ::FFI::Struct
111
174
  layout :num_blocks, :int,
112
175
  :blocklist, :pointer
@@ -153,7 +216,7 @@ module RabbitMQ
153
216
  :payload, FramePayload
154
217
  end
155
218
 
156
- ResponseTypeEnum = enum [
219
+ ResponseType = enum [
157
220
  :none, 0,
158
221
  :normal,
159
222
  :library_exception,
@@ -161,18 +224,18 @@ module RabbitMQ
161
224
  ]
162
225
 
163
226
  class RpcReply < ::FFI::Struct
164
- layout :reply_type, ResponseTypeEnum,
227
+ layout :reply_type, ResponseType,
165
228
  :reply, Method,
166
229
  :library_error, :int
167
230
  end
168
231
 
169
- SaslMethodEnum = enum [
232
+ SaslMethod = enum [
170
233
  :plain, 0,
171
234
  ]
172
235
 
173
236
  ConnectionState = :pointer
174
237
 
175
- StatusEnum = enum [
238
+ Status = enum [
176
239
  :ok, 0x0,
177
240
  :no_memory, -0x0001,
178
241
  :bad_amqp_data, -0x0002,
@@ -190,6 +253,8 @@ module RabbitMQ
190
253
  :timer_failure, -0x000E,
191
254
  :heartbeat_timeout, -0x000F,
192
255
  :unexpected_state, -0x0010,
256
+ :unexpected_socket_closed, -0x0011,
257
+ :unexpected_socket_inuse, -0x0012,
193
258
  :tcp_error, -0x0100,
194
259
  :tcp_socketlib_init_error, -0x0101,
195
260
  :ssl_error, -0x0200,
@@ -198,7 +263,7 @@ module RabbitMQ
198
263
  :ssl_connection_failed, -0x0203,
199
264
  ]
200
265
 
201
- DeliveryModeEnum = enum [
266
+ DeliveryMode = enum [
202
267
  :nonpersistent, 1,
203
268
  :persistent, 2,
204
269
  ]
@@ -208,10 +273,10 @@ module RabbitMQ
208
273
 
209
274
  attach_function :amqp_method_name, [MethodNumber], :string, **opts
210
275
  attach_function :amqp_method_has_content, [MethodNumber], Boolean, **opts
211
- attach_function :amqp_decode_method, [MethodNumber, :pointer, Bytes, :pointer], :int, **opts
212
- attach_function :amqp_decode_properties, [:uint16, :pointer, Bytes, :pointer], :int, **opts
213
- attach_function :amqp_encode_method, [MethodNumber, :pointer, Bytes], :int, **opts
214
- attach_function :amqp_encode_properties, [:uint16, :pointer, Bytes], :int, **opts
276
+ attach_function :amqp_decode_method, [MethodNumber, Pool.ptr, Bytes, :pointer], Status, **opts
277
+ attach_function :amqp_decode_properties, [:uint16, Pool.ptr, Bytes, :pointer], Status, **opts
278
+ attach_function :amqp_encode_method, [MethodNumber, :pointer, Bytes], Status, **opts
279
+ attach_function :amqp_encode_properties, [:uint16, :pointer, Bytes], Status, **opts
215
280
 
216
281
  class ConnectionStart < ::FFI::Struct
217
282
  layout :version_major, :uint8,
@@ -622,31 +687,31 @@ module RabbitMQ
622
687
  :cluster_id, Bytes
623
688
  end
624
689
 
625
- attach_function :amqp_channel_open, [ConnectionState, Channel], :pointer, **opts
626
- attach_function :amqp_channel_flow, [ConnectionState, Channel, Boolean], :pointer, **opts
627
- attach_function :amqp_exchange_declare, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, Table], :pointer, **opts
628
- attach_function :amqp_exchange_delete, [ConnectionState, Channel, Bytes, Boolean], :pointer, **opts
629
- attach_function :amqp_exchange_bind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], :pointer, **opts
630
- attach_function :amqp_exchange_unbind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], :pointer, **opts
631
- attach_function :amqp_queue_declare, [ConnectionState, Channel, Bytes, Boolean, Boolean, Boolean, Boolean, Table], :pointer, **opts
632
- attach_function :amqp_queue_bind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], :pointer, **opts
633
- attach_function :amqp_queue_purge, [ConnectionState, Channel, Bytes], :pointer, **opts
634
- attach_function :amqp_queue_delete, [ConnectionState, Channel, Bytes, Boolean, Boolean], :pointer, **opts
635
- attach_function :amqp_queue_unbind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], :pointer, **opts
636
- attach_function :amqp_basic_qos, [ConnectionState, Channel, :uint32, :uint16, Boolean], :pointer, **opts
637
- attach_function :amqp_basic_consume, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, Boolean, Table], :pointer, **opts
638
- attach_function :amqp_basic_cancel, [ConnectionState, Channel, Bytes], :pointer, **opts
639
- attach_function :amqp_basic_recover, [ConnectionState, Channel, Boolean], :pointer, **opts
640
- attach_function :amqp_tx_select, [ConnectionState, Channel], :pointer, **opts
641
- attach_function :amqp_tx_commit, [ConnectionState, Channel], :pointer, **opts
642
- attach_function :amqp_tx_rollback, [ConnectionState, Channel], :pointer, **opts
643
- attach_function :amqp_confirm_select, [ConnectionState, Channel], :pointer, **opts
644
-
645
- attach_function :init_amqp_pool, [:pointer, :size_t], :void, **opts
646
- attach_function :recycle_amqp_pool, [:pointer], :void, **opts
647
- attach_function :empty_amqp_pool, [:pointer], :void, **opts
648
- attach_function :amqp_pool_alloc, [:pointer, :size_t], :pointer, **opts
649
- attach_function :amqp_pool_alloc_bytes, [:pointer, :size_t, :pointer], :void, **opts
690
+ attach_function :amqp_channel_open, [ConnectionState, Channel], ChannelOpenOk.ptr, **opts
691
+ attach_function :amqp_channel_flow, [ConnectionState, Channel, Boolean], ChannelFlowOk.ptr, **opts
692
+ attach_function :amqp_exchange_declare, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, Table], ExchangeDeclareOk.ptr, **opts
693
+ attach_function :amqp_exchange_delete, [ConnectionState, Channel, Bytes, Boolean], ExchangeDeleteOk.ptr, **opts
694
+ attach_function :amqp_exchange_bind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], ExchangeBindOk.ptr, **opts
695
+ attach_function :amqp_exchange_unbind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], ExchangeUnbindOk.ptr, **opts
696
+ attach_function :amqp_queue_declare, [ConnectionState, Channel, Bytes, Boolean, Boolean, Boolean, Boolean, Table], QueueDeclareOk.ptr, **opts
697
+ attach_function :amqp_queue_bind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], QueueBindOk.ptr, **opts
698
+ attach_function :amqp_queue_purge, [ConnectionState, Channel, Bytes], QueuePurgeOk.ptr, **opts
699
+ attach_function :amqp_queue_delete, [ConnectionState, Channel, Bytes, Boolean, Boolean], QueueDeleteOk.ptr, **opts
700
+ attach_function :amqp_queue_unbind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], QueueUnbindOk.ptr, **opts
701
+ attach_function :amqp_basic_qos, [ConnectionState, Channel, :uint32, :uint16, Boolean], BasicQosOk.ptr, **opts
702
+ attach_function :amqp_basic_consume, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, Boolean, Table], BasicConsumeOk.ptr, **opts
703
+ attach_function :amqp_basic_cancel, [ConnectionState, Channel, Bytes], BasicCancelOk.ptr, **opts
704
+ attach_function :amqp_basic_recover, [ConnectionState, Channel, Boolean], BasicRecoverOk.ptr, **opts
705
+ attach_function :amqp_tx_select, [ConnectionState, Channel], TxSelect.ptr, **opts
706
+ attach_function :amqp_tx_commit, [ConnectionState, Channel], TxCommit.ptr, **opts
707
+ attach_function :amqp_tx_rollback, [ConnectionState, Channel], TxRollback.ptr, **opts
708
+ attach_function :amqp_confirm_select, [ConnectionState, Channel], ConfirmSelect.ptr, **opts
709
+
710
+ attach_function :init_amqp_pool, [Pool.ptr, :size_t], :void, **opts
711
+ attach_function :recycle_amqp_pool, [Pool.ptr], :void, **opts
712
+ attach_function :empty_amqp_pool, [Pool.ptr], :void, **opts
713
+ attach_function :amqp_pool_alloc, [Pool.ptr, :size_t], :pointer, **opts
714
+ attach_function :amqp_pool_alloc_bytes, [Pool.ptr, :size_t, Bytes.ptr], :void, **opts
650
715
 
651
716
  attach_function :amqp_cstring_bytes, [:string], Bytes, **opts
652
717
  attach_function :amqp_bytes_malloc_dup, [Bytes], Bytes, **opts
@@ -654,51 +719,55 @@ module RabbitMQ
654
719
  attach_function :amqp_bytes_free, [Bytes], :void, **opts
655
720
 
656
721
  attach_function :amqp_new_connection, [], ConnectionState, **opts
657
- attach_function :amqp_get_sockfd, [ConnectionState], :int, **opts
658
- attach_function :amqp_set_sockfd, [ConnectionState, :int], :void, **opts
659
- attach_function :amqp_tune_connection, [ConnectionState, :int, :int, :int], :int, **opts
660
- attach_function :amqp_get_channel_max, [ConnectionState], :int, **opts
661
- attach_function :amqp_destroy_connection, [ConnectionState], :int, **opts
662
-
663
- attach_function :amqp_handle_input, [ConnectionState, Bytes, :pointer], :int, **opts
664
- attach_function :amqp_release_buffers_ok, [ConnectionState], Boolean, **opts
665
- attach_function :amqp_release_buffers, [ConnectionState], :void, **opts
666
- attach_function :amqp_maybe_release_buffers, [ConnectionState], :void, **opts
667
- attach_function :amqp_maybe_release_buffers_on_channel, [ConnectionState, Channel], :void, **opts
668
- attach_function :amqp_send_frame, [ConnectionState, :pointer], :int, **opts
722
+ attach_function :amqp_get_sockfd, [ConnectionState], :int, **opts
723
+ attach_function :amqp_set_sockfd, [ConnectionState, :int], :void, **opts
724
+ attach_function :amqp_tune_connection, [ConnectionState, :int, :int, :int], Status, **opts
725
+ attach_function :amqp_get_channel_max, [ConnectionState], :int, **opts
726
+ attach_function :amqp_get_frame_max, [ConnectionState], :int, **opts
727
+ attach_function :amqp_get_heartbeat, [ConnectionState], :int, **opts
728
+ attach_function :amqp_destroy_connection, [ConnectionState], Status, **opts
729
+
730
+ attach_function :amqp_handle_input, [ConnectionState, Bytes, Frame.ptr], Status, **opts
731
+ attach_function :amqp_release_buffers_ok, [ConnectionState], Boolean, **opts
732
+ attach_function :amqp_release_buffers, [ConnectionState], :void, **opts
733
+ attach_function :amqp_maybe_release_buffers, [ConnectionState], :void, **opts
734
+ attach_function :amqp_maybe_release_buffers_on_channel, [ConnectionState, Channel], :void, **opts
735
+ attach_function :amqp_send_frame, [ConnectionState, Frame.ptr], Status, **opts
669
736
 
670
737
  attach_function :amqp_table_entry_cmp, [:pointer, :pointer], :int, **opts
671
- attach_function :amqp_open_socket, [:string, :int], :int, **opts
672
-
673
- attach_function :amqp_send_header, [ConnectionState], :int, **opts
674
- attach_function :amqp_frames_enqueued, [ConnectionState], Boolean, **opts
675
- attach_function :amqp_simple_wait_frame, [ConnectionState, :pointer], :int, **opts
676
- attach_function :amqp_simple_wait_frame_noblock, [ConnectionState, :pointer, :pointer], :int, **opts
677
- attach_function :amqp_simple_wait_method, [ConnectionState, Channel, MethodNumber, :pointer], :int, **opts
678
- attach_function :amqp_send_method, [ConnectionState, Channel, MethodNumber, :pointer], :int, **opts
679
-
680
- attach_function :amqp_simple_rpc, [ConnectionState, Channel, MethodNumber, :pointer, :pointer], RpcReply, **opts
681
- attach_function :amqp_simple_rpc_decoded, [ConnectionState, Channel, MethodNumber, MethodNumber, :pointer], :pointer, **opts
682
- attach_function :amqp_get_rpc_reply, [ConnectionState], RpcReply, **opts
683
- attach_function :amqp_login, [ConnectionState, :string, :int, :int, :int, SaslMethodEnum], RpcReply, **opts
684
- attach_function :amqp_login_with_properties, [ConnectionState, :string, :int, :int, :int, :pointer, SaslMethodEnum], RpcReply, **opts
685
- attach_function :amqp_channel_close, [ConnectionState, Channel, :int], RpcReply, **opts
686
- attach_function :amqp_connection_close, [ConnectionState, :int], RpcReply, **opts
687
-
688
- attach_function :amqp_basic_publish, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, :pointer, Bytes], :int, **opts
689
- attach_function :amqp_basic_ack, [ConnectionState, Channel, :uint64, Boolean], :int, **opts
690
- attach_function :amqp_basic_get, [ConnectionState, Channel, Bytes, Boolean], :int, **opts
691
- attach_function :amqp_basic_reject, [ConnectionState, Channel, :uint64, Boolean], :int, **opts
692
- attach_function :amqp_basic_nack, [ConnectionState, Channel, :uint64, Boolean, Boolean], :int, **opts
738
+
739
+ attach_function :amqp_open_socket, [:string, :int], Status, **opts
740
+
741
+ attach_function :amqp_send_header, [ConnectionState], Status, **opts
742
+ attach_function :amqp_frames_enqueued, [ConnectionState], Boolean, **opts
743
+ attach_function :amqp_simple_wait_frame, [ConnectionState, Frame.ptr], Status, **opts
744
+ attach_function :amqp_simple_wait_frame_noblock, [ConnectionState, Frame.ptr, Timeval.ptr], Status, **opts
745
+ attach_function :amqp_simple_wait_method, [ConnectionState, Channel, MethodNumber, Method.ptr], Status, **opts
746
+ attach_function :amqp_send_method, [ConnectionState, Channel, MethodNumber, Method.ptr], Status, **opts
747
+
748
+ attach_function :amqp_simple_rpc, [ConnectionState, Channel, MethodNumber, :pointer, :pointer], RpcReply.by_value, **opts
749
+ attach_function :amqp_simple_rpc_decoded, [ConnectionState, Channel, MethodNumber, MethodNumber, :pointer], :pointer, **opts
750
+ attach_function :amqp_get_rpc_reply, [ConnectionState], RpcReply.by_value, **opts
751
+ attach_function :amqp_login, [ConnectionState, :string, :int, :int, :int, SaslMethod, :varargs], RpcReply.by_value, **opts
752
+ attach_function :amqp_login_with_properties, [ConnectionState, :string, :int, :int, :int, Table.ptr, SaslMethod, :varargs], RpcReply.by_value, **opts
753
+ attach_function :amqp_channel_close, [ConnectionState, Channel, :int], RpcReply.by_value, **opts
754
+ attach_function :amqp_connection_close, [ConnectionState, :int], RpcReply.by_value, **opts
755
+
756
+ attach_function :amqp_basic_publish, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, BasicProperties.ptr, Bytes], RpcReply.by_value, **opts
757
+
758
+ attach_function :amqp_basic_get, [ConnectionState, Channel, Bytes, Boolean], Status, **opts
759
+ attach_function :amqp_basic_ack, [ConnectionState, Channel, :uint64, Boolean], Status, **opts
760
+ attach_function :amqp_basic_reject, [ConnectionState, Channel, :uint64, Boolean], Status, **opts
761
+ attach_function :amqp_basic_nack, [ConnectionState, Channel, :uint64, Boolean, Boolean], Status, **opts
693
762
 
694
763
  attach_function :amqp_data_in_buffer, [ConnectionState], Boolean, **opts
695
764
 
696
765
  attach_function :amqp_error_string, [:int], :string, **opts
697
766
  attach_function :amqp_error_string2, [:int], :string, **opts
698
767
 
699
- attach_function :amqp_decode_table, [Bytes, :pointer, :pointer, :pointer], :int, **opts
700
- attach_function :amqp_encode_table, [Bytes, :pointer, :pointer], :int, **opts
701
- attach_function :amqp_table_clone, [:pointer, :pointer, :pointer], :int, **opts
768
+ attach_function :amqp_decode_table, [Bytes, Pool.ptr, Table.ptr, :pointer], Status, **opts
769
+ attach_function :amqp_encode_table, [Bytes, Table.ptr, :pointer], Status, **opts
770
+ attach_function :amqp_table_clone, [Table.ptr, Table.ptr, Pool.ptr], Status, **opts
702
771
 
703
772
  class Message < ::FFI::Struct
704
773
  layout :properties, BasicProperties,
@@ -706,8 +775,8 @@ module RabbitMQ
706
775
  :pool, Pool
707
776
  end
708
777
 
709
- attach_function :amqp_read_message, [ConnectionState, Channel, :pointer, :int], RpcReply, **opts
710
- attach_function :amqp_destroy_message, [:pointer], :void, **opts
778
+ attach_function :amqp_read_message, [ConnectionState, Channel, Message.ptr, :int], RpcReply.by_value, **opts
779
+ attach_function :amqp_destroy_message, [Message.ptr], :void, **opts
711
780
 
712
781
  class Envelope < ::FFI::Struct
713
782
  layout :channel, Channel,
@@ -719,8 +788,8 @@ module RabbitMQ
719
788
  :message, Message
720
789
  end
721
790
 
722
- attach_function :amqp_consume_message, [ConnectionState, :pointer, :pointer, :int], RpcReply, **opts
723
- attach_function :amqp_destroy_envelope, [:pointer], :void, **opts
791
+ attach_function :amqp_consume_message, [ConnectionState, Envelope.ptr, Timeval.ptr, :int], RpcReply.by_value, **opts
792
+ attach_function :amqp_destroy_envelope, [Envelope.ptr], :void, **opts
724
793
 
725
794
  class ConnectionInfo < ::FFI::Struct
726
795
  layout :user, :string,
@@ -731,13 +800,23 @@ module RabbitMQ
731
800
  :ssl, Boolean
732
801
  end
733
802
 
734
- attach_function :amqp_default_connection_info, [:pointer], :void, **opts
735
- attach_function :amqp_parse_url, [:string, :pointer], :int, **opts
736
- attach_function :amqp_socket_open, [:pointer, :string, :int], :int, **opts
737
- attach_function :amqp_socket_open_noblock, [:pointer, :string, :int, :pointer], :int, **opts
738
- attach_function :amqp_socket_get_sockfd, [:pointer], :int, **opts
739
- attach_function :amqp_get_socket, [ConnectionState], :pointer, **opts
740
- attach_function :amqp_get_server_properties, [ConnectionState], Table, **opts
803
+ attach_function :amqp_default_connection_info, [ConnectionInfo.ptr], :void, **opts
804
+ attach_function :amqp_parse_url, [:pointer, ConnectionInfo.ptr], Status, **opts
805
+ attach_function :amqp_socket_open, [:pointer, :string, :int], Status, **opts
806
+ attach_function :amqp_socket_open_noblock, [:pointer, :string, :int, Timeval.ptr], Status, **opts
807
+ attach_function :amqp_socket_get_sockfd, [:pointer], :int, **opts
808
+ attach_function :amqp_get_socket, [ConnectionState], :pointer, **opts
809
+ attach_function :amqp_get_server_properties, [ConnectionState], Table, **opts
810
+
811
+ attach_function :amqp_tcp_socket_new, [ConnectionState], :pointer, **opts
812
+ attach_function :amqp_tcp_socket_set_sockfd, [:pointer, :int], :void, **opts
813
+
814
+ attach_function :amqp_ssl_socket_new, [ConnectionState], :pointer, **opts
815
+ attach_function :amqp_ssl_socket_set_cacert, [:pointer, :string], Status, **opts
816
+ attach_function :amqp_ssl_socket_set_key, [:pointer, :string, :string], Status, **opts
817
+ attach_function :amqp_ssl_socket_set_key_buffer, [:pointer, :string, :pointer, :size_t], Status, **opts
818
+ attach_function :amqp_ssl_socket_set_verify, [:pointer, Boolean], :void, **opts
819
+ attach_function :amqp_set_initialize_ssl_library, [Boolean], :void, **opts
741
820
  end
742
821
  end
743
822
  end
@@ -0,0 +1,42 @@
1
+
2
+ module RabbitMQ
3
+ module FFI
4
+
5
+ class Error < RuntimeError
6
+ def initialize message=nil
7
+ @message = message
8
+ end
9
+
10
+ def message
11
+ if @message && status_message; "#{status_message} - #{@message}"
12
+ elsif @message; @message
13
+ elsif status_message; status_message
14
+ else; ""
15
+ end
16
+ end
17
+
18
+ def status_message
19
+ nil
20
+ end
21
+
22
+ @lookup_table = {}
23
+ class << self
24
+ attr_reader :lookup_table
25
+ end
26
+
27
+ def self.lookup status
28
+ lookup_table.fetch(status)
29
+ end
30
+
31
+ FFI::Status.symbols.each do |status|
32
+ message = RabbitMQ::FFI.amqp_error_string2(status)
33
+ const_name = status.to_s.gsub(/((?:\A\w)|(?:_\w))/) { |x| x[-1].upcase }
34
+
35
+ kls = Class.new(Error) { define_method(:status_message) { message } }
36
+ lookup_table[status] = kls
37
+ const_set const_name, kls
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,63 @@
1
+
2
+ module RabbitMQ
3
+ module FFI
4
+
5
+ class ConnectionInfo
6
+ def to_h
7
+ members.map { |k| [k, self[k]] }.to_h
8
+ end
9
+ end
10
+
11
+ class Bytes
12
+ def to_s
13
+ ::FFI::Pointer.new(self[:bytes]).read_bytes(self[:len])
14
+ end
15
+
16
+ def self.from_s(str)
17
+ size = str.bytesize
18
+ ptr = Util.mem_ptr(size, release: false)
19
+ ptr.write_string(str)
20
+
21
+ bytes = new
22
+ bytes[:len] = str.bytesize
23
+ bytes[:bytes] = Util.mem_ptr(str.bytesize, release: false)
24
+ bytes
25
+ end
26
+ end
27
+
28
+ class FieldValue
29
+ private def value_member(kind)
30
+ case kind
31
+ when :utf8; :bytes
32
+ when :timestamp; :u64
33
+ else kind
34
+ end
35
+ end
36
+
37
+ def to_value
38
+ kind = self[:kind]
39
+ value = self[:value][value_member(kind)]
40
+ case kind
41
+ when :bytes; value.to_s
42
+ when :utf8; value.to_s.force_encoding(Encoding::UTF_8)
43
+ when :timestamp; Time.at(value / 1000.0)
44
+ when :table; value.to_h
45
+ when :array; value.to_array_not_yet_implemented!
46
+ when :decimal; value.to_value_not_yet_implemented!
47
+ else value
48
+ end
49
+ end
50
+ end
51
+
52
+ class Table
53
+ def to_h
54
+ entry_ptr = self[:entries]
55
+ entries = self[:num_entries].times.map { |i|
56
+ entry = FFI::TableEntry.new(entry_ptr + i * FFI::TableEntry.size)
57
+ [entry[:key].to_s, entry[:value].to_value]
58
+ }.to_h
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,36 @@
1
+
2
+ class RabbitMQ::FFI::Error < RuntimeError; end
3
+
4
+ module RabbitMQ::Util
5
+ class << self
6
+
7
+ def error_check action, status
8
+ return if status == :ok
9
+ raise RabbitMQ::FFI::Error.lookup(status), "while #{action}"
10
+ end
11
+
12
+ def null_check action, obj
13
+ return unless obj.nil?
14
+ raise RabbitMQ::FFI::Error, "while #{action} - got unexpected null"
15
+ end
16
+
17
+ def mem_ptr size, count: 1, clear: true, release: true
18
+ ptr = ::FFI::MemoryPointer.new(size, count, clear)
19
+ ptr.autorelease = false unless release
20
+ ptr
21
+ end
22
+
23
+ def arg_ptr type, **kwargs
24
+ type = ::FFI::TypeDefs[type] if type.is_a?(Symbol)
25
+ mem_ptr(type.size, clear: false, **kwargs)
26
+ end
27
+
28
+ def strdup_ptr str, **kwargs
29
+ str = str + "\x00"
30
+ ptr = mem_ptr(str.bytesize, **kwargs)
31
+ ptr.write_string(str)
32
+ ptr
33
+ end
34
+
35
+ end
36
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabbitmq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe McIlvain
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-29 00:00:00.000000000 Z
11
+ date: 2015-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -111,12 +111,19 @@ dependencies:
111
111
  description: A Ruby RabbitMQ client library based on FFI bindings for librabbitmq.
112
112
  email: joe.eli.mac@gmail.com
113
113
  executables: []
114
- extensions: []
114
+ extensions:
115
+ - ext/rabbitmq/Rakefile
115
116
  extra_rdoc_files: []
116
117
  files:
118
+ - LICENSE
117
119
  - README.md
120
+ - ext/rabbitmq/Rakefile
118
121
  - lib/rabbitmq.rb
122
+ - lib/rabbitmq/connection.rb
119
123
  - lib/rabbitmq/ffi.rb
124
+ - lib/rabbitmq/ffi/error.rb
125
+ - lib/rabbitmq/ffi/ext.rb
126
+ - lib/rabbitmq/util.rb
120
127
  homepage: https://github.com/jemc/rabbitmq/
121
128
  licenses:
122
129
  - MIT