ffi-rzmq 0.8.2 → 0.9.0

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 (56) hide show
  1. data/AUTHORS.txt +1 -0
  2. data/History.txt +35 -0
  3. data/README.rdoc +48 -15
  4. data/Rakefile +7 -2
  5. data/examples/README.rdoc +21 -76
  6. data/examples/{local_lat.rb → v2api/local_lat.rb} +27 -12
  7. data/examples/v2api/local_lat_poll.rb +66 -0
  8. data/examples/{local_throughput.rb → v2api/local_throughput.rb} +24 -9
  9. data/examples/v2api/publish_subscribe.rb +82 -0
  10. data/examples/{remote_lat.rb → v2api/remote_lat.rb} +26 -8
  11. data/examples/v2api/remote_throughput.rb +39 -0
  12. data/examples/v2api/reqrep_poll.rb +62 -0
  13. data/examples/v2api/request_response.rb +40 -0
  14. data/examples/v2api/throughput_measurement.rb +138 -0
  15. data/examples/v3api/local_lat.rb +59 -0
  16. data/examples/v3api/local_lat_poll.rb +66 -0
  17. data/examples/v3api/local_throughput.rb +65 -0
  18. data/examples/v3api/publish_subscribe.rb +82 -0
  19. data/examples/v3api/remote_lat.rb +71 -0
  20. data/examples/v3api/remote_throughput.rb +47 -0
  21. data/examples/v3api/reqrep_poll.rb +62 -0
  22. data/examples/v3api/request_response.rb +40 -0
  23. data/examples/v3api/throughput_measurement.rb +166 -0
  24. data/ext/README +5 -0
  25. data/ffi-rzmq.gemspec +4 -4
  26. data/lib/ffi-rzmq.rb +4 -1
  27. data/lib/ffi-rzmq/constants.rb +178 -0
  28. data/lib/ffi-rzmq/context.rb +61 -45
  29. data/lib/ffi-rzmq/device.rb +22 -9
  30. data/lib/ffi-rzmq/exceptions.rb +0 -98
  31. data/lib/ffi-rzmq/libc.rb +19 -0
  32. data/lib/ffi-rzmq/libzmq.rb +188 -0
  33. data/lib/ffi-rzmq/message.rb +33 -40
  34. data/lib/ffi-rzmq/poll.rb +49 -52
  35. data/lib/ffi-rzmq/socket.rb +902 -392
  36. data/lib/ffi-rzmq/util.rb +101 -0
  37. data/spec/context_spec.rb +47 -21
  38. data/spec/device_spec.rb +78 -58
  39. data/spec/message_spec.rb +90 -12
  40. data/spec/multipart_spec.rb +162 -0
  41. data/spec/nonblocking_recv_spec.rb +325 -0
  42. data/spec/pushpull_spec.rb +95 -34
  43. data/spec/reqrep_spec.rb +55 -20
  44. data/spec/socket_spec.rb +353 -204
  45. data/spec/spec_helper.rb +46 -3
  46. data/version.txt +1 -1
  47. metadata +91 -66
  48. data/examples/local_lat_poll.rb +0 -54
  49. data/examples/local_lat_zerocopy.rb +0 -24
  50. data/examples/publish_subscribe.rb +0 -52
  51. data/examples/remote_lat_zerocopy.rb +0 -35
  52. data/examples/remote_throughput.rb +0 -27
  53. data/examples/reqrep_poll.rb +0 -49
  54. data/examples/request_response.rb +0 -23
  55. data/lib/ffi-rzmq/wrapper.rb +0 -121
  56. data/lib/ffi-rzmq/zmq.rb +0 -198
@@ -1,49 +0,0 @@
1
- require 'rubygems'
2
- require 'ffi-rzmq'
3
-
4
-
5
- link = "tcp://127.0.0.1:5554"
6
-
7
- ctx = ZMQ::Context.new 1
8
- s1 = ctx.socket ZMQ::REQ
9
- s2 = ctx.socket ZMQ::REP
10
-
11
- s1.connect link
12
- s2.bind link
13
-
14
- poller = ZMQ::Poller.new
15
- poller.register_readable s2
16
- poller.register_writable s1
17
-
18
- start_time = Time.now
19
- @unsent = true
20
-
21
- until @done do
22
- begin
23
- poller.poll_nonblock
24
- rescue ZMQ::PollError => e
25
- puts "efault? [#{e.efault?}]"
26
- raise
27
- end
28
-
29
- # send the message after 5 seconds
30
- if Time.now - start_time > 5 && @unsent
31
- payload = "#{ '3' * 1024 }"
32
-
33
- puts "sending payload nonblocking"
34
- s1.send_string payload, ZMQ::NOBLOCK
35
- @unsent = false
36
- end
37
-
38
- # check for messages after 1 second
39
- if Time.now - start_time > 1
40
- poller.readables.each do |sock|
41
- received_msg = sock.recv_string ZMQ::NOBLOCK
42
-
43
- puts "message received [#{received_msg}]"
44
- @done = true
45
- end
46
- end
47
- end
48
-
49
- puts "executed in [#{Time.now - start_time}] seconds"
@@ -1,23 +0,0 @@
1
- require 'rubygems'
2
- require 'ffi-rzmq'
3
-
4
-
5
- link = "tcp://127.0.0.1:5555"
6
-
7
- ctx = ZMQ::Context.new 1
8
- s1 = ctx.socket ZMQ::REQ
9
- s2 = ctx.socket ZMQ::REP
10
-
11
- s2.bind link
12
- s1.connect link
13
-
14
- payload = "#{ '3' * 2048 }"
15
- sent_msg = ZMQ::Message.new payload
16
- received_msg = ZMQ::Message.new
17
-
18
- s1.send sent_msg
19
- s2.recv received_msg
20
-
21
- result = payload == received_msg.copy_out_string ? "Request received" : "Received wrong payload"
22
-
23
- p result
@@ -1,121 +0,0 @@
1
- require 'ffi' unless RBX # external gem
2
-
3
- module LibC
4
- extend FFI::Library
5
- # figures out the correct libc for each platform including Windows
6
- library = ffi_lib(FFI::Library::LIBC).first
7
-
8
- # Size_t not working properly on Windows
9
- find_type(:size_t) rescue typedef(:ulong, :size_t)
10
-
11
- # memory allocators
12
- attach_function :malloc, [:size_t], :pointer
13
- attach_function :free, [:pointer], :void
14
-
15
- # get a pointer to the free function; used for ZMQ::Message deallocation
16
- Free = library.find_symbol('free')
17
-
18
- # memory movers
19
- attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
20
- end # module LibC
21
-
22
- module LibZMQ
23
- extend FFI::Library
24
- ZMQ_LIB_PATHS = %w{/usr/local/lib /opt/local/lib /usr/local/homebrew/lib}.map{|path| "#{path}/libzmq.#{FFI::Platform::LIBSUFFIX}"}
25
- ffi_lib(%w{libzmq} + ZMQ_LIB_PATHS)
26
-
27
- # Size_t not working properly on Windows
28
- find_type(:size_t) rescue typedef(:ulong, :size_t)
29
-
30
- # Misc
31
- attach_function :zmq_version, [:pointer, :pointer, :pointer], :void
32
-
33
- # Context and misc api
34
- attach_function :zmq_init, [:int], :pointer
35
- attach_function :zmq_socket, [:pointer, :int], :pointer
36
- attach_function :zmq_term, [:pointer], :int
37
- attach_function :zmq_errno, [], :int
38
- attach_function :zmq_strerror, [:int], :pointer
39
-
40
- # Message api
41
- attach_function :zmq_msg_init, [:pointer], :int
42
- attach_function :zmq_msg_init_size, [:pointer, :size_t], :int
43
- attach_function :zmq_msg_init_data, [:pointer, :pointer, :size_t, :pointer, :pointer], :int
44
- attach_function :zmq_msg_close, [:pointer], :int
45
- attach_function :zmq_msg_data, [:pointer], :pointer
46
- attach_function :zmq_msg_size, [:pointer], :size_t
47
- attach_function :zmq_msg_copy, [:pointer, :pointer], :int
48
- attach_function :zmq_msg_move, [:pointer, :pointer], :int
49
-
50
-
51
- # Used for casting pointers back to the struct
52
- class Msg < FFI::Struct
53
- layout :content, :pointer,
54
- :flags, :uint8,
55
- :vsm_size, :uint8,
56
- :vsm_data, [:uint8, 30]
57
- end # class Msg
58
-
59
-
60
- # Socket api
61
- # @blocking = true is a hint to FFI that the following (and only the following)
62
- # function may block, therefore it should release the GIL before calling it.
63
- # This can aid in situations where the function call will/may block and another
64
- # thread within the lib may try to call back into the ruby runtime. Failure to
65
- # release the GIL will result in a hang; the hint *may* allow things to run
66
- # smoothly for Ruby runtimes hampered by a GIL.
67
- #
68
- # This is really only honored by the MRI implementation.
69
- attach_function :zmq_setsockopt, [:pointer, :int, :pointer, :int], :int
70
- attach_function :zmq_getsockopt, [:pointer, :int, :pointer, :pointer], :int
71
- attach_function :zmq_bind, [:pointer, :string], :int
72
- attach_function :zmq_connect, [:pointer, :string], :int
73
- @blocking = true
74
- attach_function :zmq_send, [:pointer, :pointer, :int], :int
75
- @blocking = true
76
- attach_function :zmq_recv, [:pointer, :pointer, :int], :int
77
- attach_function :zmq_close, [:pointer], :int
78
-
79
- @blocking = true
80
- attach_function :zmq_device, [:int, :pointer, :pointer], :int
81
-
82
- # Poll api
83
- @blocking = true
84
- attach_function :zmq_poll, [:pointer, :int, :long], :int
85
-
86
- module PollItemLayout
87
- def self.included(base)
88
- base.class_eval do
89
- layout :socket, :pointer,
90
- :fd, :int,
91
- :events, :short,
92
- :revents, :short
93
- end
94
- end
95
- end # module PollItemLayout
96
-
97
- class PollItem < FFI::Struct
98
- include PollItemLayout
99
-
100
- def socket() self[:socket]; end
101
-
102
- def readable?
103
- (self[:revents] & ZMQ::POLLIN) > 0
104
- end
105
-
106
- def writable?
107
- (self[:revents] & ZMQ::POLLOUT) > 0
108
- end
109
-
110
- def both_accessible?
111
- readable? && writable?
112
- end
113
-
114
- def inspect
115
- "socket [#{socket}], fd [#{self[:fd]}], events [#{self[:events]}], revents [#{self[:revents]}]"
116
- end
117
-
118
- def to_s; inspect; end
119
- end # class PollItem
120
-
121
- end # module LibZMQ
@@ -1,198 +0,0 @@
1
- module ZMQ
2
-
3
- # Socket types
4
- PAIR = 0
5
- PUB = 1
6
- SUB = 2
7
- REQ = 3
8
- REP = 4
9
- DEALER = XREQ = 5
10
- ROUTER = XREP = 6
11
- PULL = UPSTREAM = 7
12
- PUSH = DOWNSTREAM = 8
13
-
14
- SocketTypeNameMap = {
15
- PAIR => "PAIR",
16
- PUB => "PUB",
17
- SUB => "SUB",
18
- REQ => "REQ",
19
- REP => "REP",
20
- ROUTER => "ROUTER",
21
- DEALER => "DEALER",
22
- PULL => "PULL",
23
- PUSH => "PUSH"
24
- }
25
-
26
- # Socket options
27
- HWM = 1
28
- SWAP = 3
29
- AFFINITY = 4
30
- IDENTITY = 5
31
- SUBSCRIBE = 6
32
- UNSUBSCRIBE = 7
33
- RATE = 8
34
- RECOVERY_IVL = 9
35
- MCAST_LOOP = 10
36
- SNDBUF = 11
37
- RCVBUF = 12
38
- RCVMORE = 13
39
- FD = 14
40
- EVENTS = 15
41
- TYPE = 16
42
- LINGER = 17
43
- RECONNECT_IVL = 18
44
- BACKLOG = 19
45
- RECOVERY_IVL_MSEC = 20
46
-
47
- # Send/recv options
48
- NOBLOCK = 1
49
- SNDMORE = 2
50
-
51
- # I/O multiplexing
52
-
53
- POLL = 1
54
- POLLIN = 1
55
- POLLOUT = 2
56
- POLLERR = 4
57
-
58
- # Socket errors
59
- EAGAIN = Errno::EAGAIN::Errno
60
- EINVAL = Errno::EINVAL::Errno
61
- ENOMEM = Errno::ENOMEM::Errno
62
- ENODEV = Errno::ENODEV::Errno
63
- EFAULT = Errno::EFAULT::Errno
64
-
65
- # Device Types
66
- STREAMER = 1
67
- FORWARDER = 2
68
- QUEUE = 3
69
-
70
- # ZMQ errors
71
- HAUSNUMERO = 156384712
72
- EMTHREAD = (HAUSNUMERO + 50)
73
- EFSM = (HAUSNUMERO + 51)
74
- ENOCOMPATPROTO = (HAUSNUMERO + 52)
75
- ETERM = (HAUSNUMERO + 53)
76
-
77
- # Rescue unknown constants and use the ZeroMQ defined values
78
- # Usually only happens on Windows though some don't resolve on
79
- # OSX too (ENOTSUP)
80
- ENOTSUP = Errno::ENOTSUP::Errno rescue (HAUSNUMERO + 1)
81
- EPROTONOSUPPORT = Errno::EPROTONOSUPPORT::Errno rescue (HAUSNUMERO + 2)
82
- ENOBUFS = Errno::ENOBUFS::Errno rescue (HAUSNUMERO + 3)
83
- ENETDOWN = Errno::ENETDOWN::Errno rescue (HAUSNUMERO + 4)
84
- EADDRINUSE = Errno::EADDRINUSE::Errno rescue (HAUSNUMERO + 5)
85
- EADDRNOTAVAIL = Errno::EADDRNOTAVAIL::Errno rescue (HAUSNUMERO + 6)
86
- ECONNREFUSED = Errno::ECONNREFUSED::Errno rescue (HAUSNUMERO + 7)
87
- EINPROGRESS = Errno::EINPROGRESS::Errno rescue (HAUSNUMERO + 8)
88
-
89
-
90
-
91
- # These methods don't belong to any specific context. They get included
92
- # in the #Context, #Socket and #Poller classes.
93
- #
94
- module Util
95
-
96
- # Returns the +errno+ as set by the libzmq library.
97
- #
98
- def errno
99
- LibZMQ.zmq_errno
100
- end
101
-
102
- # Returns a string corresponding to the currently set #errno. These
103
- # error strings are defined by libzmq.
104
- #
105
- def error_string
106
- LibZMQ.zmq_strerror(errno).read_string
107
- end
108
-
109
- # Returns an array of the form [major, minor, patch] to represent the
110
- # version of libzmq.
111
- #
112
- # Class method! Invoke as: ZMQ::Util.version
113
- #
114
- def self.version
115
- major = FFI::MemoryPointer.new :int
116
- minor = FFI::MemoryPointer.new :int
117
- patch = FFI::MemoryPointer.new :int
118
- LibZMQ.zmq_version major, minor, patch
119
- [major.read_int, minor.read_int, patch.read_int]
120
- end
121
-
122
- # Compares the 0mq library API version to a minimal version tuple. Returns
123
- # true if it meets the minimum requirement, false otherwise.
124
- #
125
- # Takes a +tuple+ with 3 elements corresponding to the major, minor and patch
126
- # version levels.
127
- #
128
- # e.g. Util.minimum_api?([2, 1, 0])
129
- #
130
- def self.minimum_api? tuple
131
- api_version = Util.version
132
-
133
- # call #to_i to convert nil entries to 0 so the comparison is valid
134
- result = tuple[0].to_i <= api_version[0] &&
135
- tuple[1].to_i <= api_version[1] &&
136
- tuple[2].to_i <= api_version[2]
137
- end
138
-
139
-
140
- private
141
-
142
- # :doc:
143
- # Called by most library methods to verify there were no errors during
144
- # operation. If any are found, raise the appropriate #ZeroMQError.
145
- #
146
- # When no error is found, this method returns +true+ which is behavior
147
- # used internally by #send and #recv.
148
- #
149
- def error_check source, result_code
150
- unless result_code.zero?
151
- raise_error source, result_code
152
- end
153
-
154
- # used by Socket::send/recv, ignored by others
155
- true
156
- end
157
-
158
- # :doc:
159
- # Only called on sockets in non-blocking mode.
160
- #
161
- # Checks the #errno and +result_code+ values for a failed non-blocking
162
- # send/recv. True only when #errno is EGAIN and +result_code+ is non-zero.
163
- #
164
- def error_check_nonblock result_code
165
- if result_code.zero?
166
- true
167
- else
168
- # need to check result_code again because !eagain? could be true
169
- # and we need the result_code test to fail again to give the right result
170
- # !eagain? is true, result_code is -1 => return false
171
- # !eagain? is false, result_code is -1 => return false
172
- !eagain? && result_code.zero?
173
- end
174
- end
175
-
176
- def raise_error source, result_code
177
- case source
178
- when ZMQ_SEND_STR, ZMQ_RECV_STR, ZMQ_SOCKET_STR, ZMQ_SETSOCKOPT_STR, ZMQ_GETSOCKOPT_STR, ZMQ_BIND_STR, ZMQ_CONNECT_STR, ZMQ_CLOSE_STR
179
- raise SocketError.new source, result_code, errno, error_string
180
- when ZMQ_INIT_STR, ZMQ_TERM_STR
181
- raise ContextError.new source, result_code, errno, error_string
182
- when ZMQ_POLL_STR
183
- raise PollError.new source, result_code, errno, error_string
184
- when ZMQ_MSG_INIT_STR, ZMQ_MSG_INIT_DATA_STR, ZMQ_MSG_COPY_STR, ZMQ_MSG_MOVE_STR
185
- raise MessageError.new source, result_code, errno, error_string
186
- else
187
- raise ZeroMQError.new source, result_code, -1,
188
- "Source [#{source}] does not match any zmq_* strings, rc [#{result_code}], errno [#{errno}], error_string [#{error_string}]"
189
- end
190
- end
191
-
192
- def eagain?
193
- EAGAIN == errno
194
- end
195
-
196
- end # module Util
197
-
198
- end # module ZMQ