ffi-rzmq 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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