ffi-rzmq 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,16 @@
1
+ script: bundle exec rspec
2
+ language: ruby
3
+ rvm:
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - ruby-head
7
+ - jruby-18mode
8
+ - jruby-19mode
9
+ - jruby-head
10
+ - rbx-18mode
11
+ - rbx-19mode
12
+
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: ruby-head
16
+ - rvm: jruby-head
data/AUTHORS.txt CHANGED
@@ -17,3 +17,9 @@ Stefan Kaes, github: skaes
17
17
  Dmitry Ustalov, github: eveel
18
18
 
19
19
  Patrik Sundberg, github: sundbp
20
+
21
+ Pawel Pacana, github: pawelpacana
22
+
23
+ Brian Ford, github: brixen
24
+
25
+ Nilson Santos F. Jr., github: nilsonfsj
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
+
5
+ gem "jruby-openssl", :platform => :jruby
data/History.txt CHANGED
@@ -1,3 +1,37 @@
1
+ == 0.9.7 / 20121221
2
+ * BROKE THE API.
3
+ ZMQ::Poller#register and ZMQ::Poller#deregister don't take fd argument
4
+ anymore. ZMQ::Poller#readables and ZMQ::Poller#writables return pollables
5
+ instead of just fd when pollable is other than ZMQ socket.
6
+ ZMQ::Poller#register now returns nil instead of false when no pollable
7
+ or events to register to are given, which is consistent with rest of api.
8
+ Thanks to Pawel Pacana for this code contribution.
9
+
10
+ * Added support in ZMQ::Poller for pollables responding to fileno and socket.
11
+ Standard Ruby Sockets and IOs can be now registered in poller to listen for
12
+ events. Thanks to Pawel Pacana for this code contribution.
13
+
14
+ * Fixed a bug in ZMQ::Poller#deregister where it would raise exception
15
+ when trying to deregister already closed ZMQ socket. Issue 59.
16
+
17
+ * Improved specs to use random inproc socket address to avoid race conditions
18
+ between tests under same context.
19
+
20
+ * Added continous integration for all supported platforms on Travis-CI.
21
+ Thanks to Pawel Pacana for this code contribution.
22
+
23
+ * Signed up for codeclimate.com and made some code changes to get a better
24
+ "grade" from it.
25
+
26
+ * Modified the library to *always* load the 'ffi' library upon startup. It
27
+ used to be conditional for Rubinius. Thanks to brixen for the change.
28
+
29
+ * There was a little bit of churn on the zmq "monitor" api. Thanks to
30
+ Nilson Santos F. Jr. for some code to conditionally attach to the
31
+ appropriate api depending on library version.
32
+
33
+
34
+
1
35
  == 0.9.6 / 20120808
2
36
  * Never released 0.9.5 as a gem. It was available via github only.
3
37
 
data/README.rdoc CHANGED
@@ -13,56 +13,18 @@ This single gem supports 0mq 2.x and 3.1.x 0mq APIs. The 0mq project started
13
13
  making backward-incompatible changes to the API with the 3.1.x release.
14
14
  The gem auto-configures itself to expose the API conforming to the loaded
15
15
  C library. 0mq API 3.0 is *not* supported; the 0mq community voted to
16
- abandon it.
16
+ abandon it.
17
17
 
18
18
  The impetus behind this library was to provide support for ZeroMQ in
19
19
  JRuby which has native threads. Unlike MRI, which has a GIL, JRuby and
20
- Rubinius allow for threaded access to Ruby code from outside extensions.
21
- ZeroMQ is heavily threaded, so until the MRI runtime removes its GIL,
20
+ Rubinius allow for threaded access to Ruby code from outside extensions.
21
+ ZeroMQ is heavily threaded, so until the MRI runtime removes its GIL,
22
22
  JRuby and Rubinius will likely be the best environments to run this library.
23
23
 
24
- == Breaking API Changes from 0.8.x to 0.9.0
24
+ Please read the History.txt file for a description of all changes, including
25
+ API changes, since the last release!
25
26
 
26
- There has been a major change in API from the 0.8.x series to 0.9.0.
27
- Previously the Socket#send and Socket#recv methods could raise exceptions
28
- when there was an error. They also returned true or false depending on
29
- the success or failure of the operation. The exceptions were also used
30
- for managing flow control when doing non-blocking send/recv.
31
-
32
- Mixing and matching return codes and exceptions is a terrible idea in
33
- practice. Using them for flow control is an even worse sin. So all of
34
- the exception code from Socket has been removed.
35
-
36
- The Poller and Message class have also had their exceptions removed for
37
- returning errors on instance methods.
38
-
39
- Unfortunately, it isn't possible to indicate that a call to #new has failed
40
- by returning nil. A call to #new that fails needs to raise an exception to
41
- indicate failure. (This isn't strictly true; this behavior can be changed
42
- but it is not a standard Ruby idiom and is therefore a surprising, and
43
- poor, thing to do.) Classes that formerly raised exceptions during allocation
44
- now offer a factory method #create that will either return a successfully
45
- constructed object or nil. Code should check for nil returns before using
46
- the object.
47
-
48
- This is a *breaking* change. I'm sorry but the old API's inconsistency was
49
- causing too many problems. It now more closely mimics the 0mq C API. IF YOU
50
- PREFER THE ORIGINAL API WHICH WAS CLOSER TO IDIOMATIC RUBY, IT SHOULD BE
51
- EASY TO WRAP THESE CLASSES UP TO PROVIDE A MORE IDIOMATIC API. I SUGGEST
52
- YOU CREATE A PATCH *OR* CREATE A SEPARATE GEM TO WRAP THIS ONE. Sorry for
53
- shouting but I wanted to make sure this stood out.
54
-
55
- All example code has been updated to use the new Ruby API.
56
-
57
- == Breaking API Change from 0.9.3 to 0.9.5
58
-
59
- The 0mq library functions zmq_send() and zmq_recv() were changed to
60
- zmq_sendmsg() and zmq_recvmsg() with the 0mq 3.x API change. I have changed
61
- the binding to always use #sendmsg and #recvmsg. This breaks existing code.
62
- This should be the last breaking change heading into the 1.0 release of these
63
- bindings.
64
-
65
- == PERFORMANCE
27
+ == PERFORMANCE:
66
28
 
67
29
  Check out the latest performance results:
68
30
 
@@ -72,7 +34,7 @@ Check out the latest performance results:
72
34
 
73
35
  This gem needs more tests. This gem has been battle tested by myself
74
36
  and others for over a year, so I am fairly confident that it is solid.
75
- However, it is inevitable that there will be bugs, so please open
37
+ However, it is inevitable that there will be bugs, so please open
76
38
  issues for them here or fork this project, fix them, and send me a pull
77
39
  request.
78
40
 
@@ -83,76 +45,82 @@ stability.
83
45
 
84
46
  All features are implemented.
85
47
 
48
+ == BUILD STATUS:
49
+
50
+ {<img src="https://secure.travis-ci.org/chuckremes/ffi-rzmq.png?branch=master" alt="Build Status" />}[http://travis-ci.org/chuckremes/ffi-rzmq]
51
+
52
+ {<img src="https://codeclimate.com/badge.png" />}[https://codeclimate.com/github/chuckremes/ffi-rzmq]
53
+
86
54
  == SYNOPSIS:
87
55
 
88
56
  0mq API v2 client code:
89
-
57
+
90
58
  require 'rubygems'
91
59
  require 'ffi-rzmq'
92
-
60
+
93
61
  if ARGV.length < 3
94
62
  puts "usage: local_lat <connect-to> <message-size> <roundtrip-count>"
95
63
  exit
96
64
  end
97
-
65
+
98
66
  bind_to = ARGV[0]
99
67
  message_size = ARGV[1].to_i
100
68
  roundtrip_count = ARGV[2].to_i
101
-
69
+
102
70
  ctx = ZMQ::Context.new
103
71
  s = ctx.socket ZMQ::REP
104
72
  rc = s.setsockopt(ZMQ::HWM, 100)
105
73
  rc = s.bind(bind_to)
106
-
74
+
107
75
  msg = ""
108
76
  roundtrip_count.times do
109
77
  rc = s.recv_string msg
110
78
  raise "Message size doesn't match, expected [#{message_size}] but received [#{msg.size}]" if message_size != msg.size
111
79
  rc = s.send_string msg, 0
112
80
  end
113
-
81
+
114
82
 
115
83
  0mq API v2 server code:
116
84
 
117
85
  require 'rubygems'
118
86
  require 'ffi-rzmq'
119
-
87
+
120
88
  if ARGV.length < 3
121
89
  puts "usage: remote_lat <connect-to> <message-size> <roundtrip-count>"
122
90
  exit
123
91
  end
124
-
92
+
125
93
  connect_to = ARGV[0]
126
94
  message_size = ARGV[1].to_i
127
95
  roundtrip_count = ARGV[2].to_i
128
-
96
+
129
97
  ctx = ZMQ::Context.new
130
98
  s = ctx.socket ZMQ::REQ
131
99
  rc = s.connect(connect_to)
132
-
100
+
133
101
  msg = "#{ '3' * message_size }"
134
-
102
+
135
103
  start_time = Time.now
136
-
104
+
137
105
  msg = ""
138
106
  roundtrip_count.times do
139
107
  rc = s.send_string msg, 0
140
108
  rc = s.recv_string msg
141
109
  raise "Message size doesn't match, expected [#{message_size}] but received [#{msg.size}]" if message_size != msg.size
142
110
  end
143
-
111
+
144
112
  == Better Examples
145
113
 
146
114
  I highly recommend visiting the Learn Ruby 0mq project for a bunch of good code examples.
147
115
 
148
116
  http://github.com/andrewvc/learn-ruby-zeromq
149
-
117
+
150
118
 
151
119
 
152
120
  == REQUIREMENTS:
153
121
 
154
- * 0mq 2.1.x, 3.1.x or later; 2.0.x and 3.0.x are no longer supported
155
-
122
+ * 0mq 2.2.x, 3.2.x or later; 2.0.x, 3.0.x and 3.1.x are no longer supported
123
+
156
124
  The ZeroMQ library must be installed on your system in a well-known location
157
125
  like /usr/local/lib. This is the default for new ZeroMQ installs.
158
126
 
@@ -162,7 +130,7 @@ Future releases may include the library as a C extension built at
162
130
  time of installation.
163
131
 
164
132
  * ffi (>= 1.0.0)
165
-
133
+
166
134
  This is a requirement for MRI only. Both Rubinius and JRuby have FFI support built
167
135
  in as a standard component. Do *not* run this gem under MRI with an old 'ffi' gem.
168
136
  It will crash randomly and you will be sad.
@@ -182,18 +150,18 @@ To build from git master:
182
150
  % cd ffi-rzmq
183
151
  % gem build ffi-rzmq.gemspec
184
152
  % gem install ffi-rzmq-*.gem
185
-
153
+
186
154
 
187
155
  NOTE for Windows users!
188
156
  In order for this gem to find the libzmq.dll, it *must* be on the Windows PATH. Google
189
157
  for "modify windows path" for instructions on how to do that if you are unfamiliar with
190
- that activity.
158
+ that activity. That DLL also requires that you copy libstdc++-6.dll and libgcc_s_sjlj-1.dll from DevKit MinGW into the same folder that you copied libzmq.dll.
191
159
 
192
160
  == LICENSE:
193
161
 
194
162
  (The MIT License)
195
163
 
196
- Copyright (c) 2011 Chuck Remes
164
+ Copyright (c) 2013 Chuck Remes
197
165
 
198
166
  Permission is hereby granted, free of charge, to any person obtaining
199
167
  a copy of this software and associated documentation files (the
data/ffi-rzmq.gemspec CHANGED
@@ -11,8 +11,8 @@ Gem::Specification.new do |s|
11
11
  s.summary = %q{This gem wraps the ZeroMQ (0mq) networking library using Ruby FFI (foreign function interface).}
12
12
  s.description = %q{This gem wraps the ZeroMQ networking library using the ruby FFI (foreign
13
13
  function interface). It's a pure ruby wrapper so this gem can be loaded
14
- and run by any ruby runtime that supports FFI. That's all of them -
15
- MRI 1.9.x, Rubinius and JRuby.}
14
+ and run by any ruby runtime that supports FFI. That's all of the major ones -
15
+ MRI, Rubinius and JRuby.}
16
16
 
17
17
  s.rubyforge_project = "ffi-rzmq"
18
18
 
data/lib/ffi-rzmq.rb CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  module ZMQ
3
2
 
4
3
  # :stopdoc:
@@ -64,12 +63,10 @@ end # module ZMQ
64
63
  # some code is conditionalized based upon what ruby engine we are
65
64
  # executing
66
65
 
67
- RBX = defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/ ? true : false
68
-
69
- require 'ffi' unless RBX
66
+ require 'ffi'
70
67
 
71
68
  # the order of files is important
72
69
  #%w(wrapper zmq exceptions context message socket poll_items poll device).each do |file|
73
- %w(libc libzmq constants util exceptions context message socket poll_items poll device).each do |file|
70
+ %w(libc libzmq constants util exceptions context message socket poll_items poll_item poll device).each do |file|
74
71
  require ZMQ.libpath(['ffi-rzmq', file])
75
72
  end
@@ -215,10 +215,17 @@ module ZMQ
215
215
  attach_function :zmq_msg_get, [:pointer, :int], :int
216
216
  @blocking = true
217
217
  attach_function :zmq_msg_set, [:pointer, :int, :int], :int
218
-
218
+
219
219
  # Monitoring API
220
- @blocking = true
221
- attach_function :zmq_ctx_set_monitor, [:pointer, :pointer], :int
220
+ # zmq_ctx_set_monitor is no longer supported as of version >= 3.2.1
221
+ # replaced by zmq_socket_monitor
222
+ if LibZMQ.version[:minor] > 2 || (LibZMQ.version[:minor] == 2 && LibZMQ.version[:patch] >= 1)
223
+ @blocking = true
224
+ attach_function :zmq_socket_monitor, [:pointer, :pointer, :int], :int
225
+ else
226
+ @blocking = true
227
+ attach_function :zmq_ctx_set_monitor, [:pointer, :pointer], :int
228
+ end
222
229
 
223
230
  # Socket API
224
231
  @blocking = true
@@ -233,7 +240,7 @@ module ZMQ
233
240
  attach_function :zmq_sendmsg, [:pointer, :pointer, :int], :int
234
241
  @blocking = true
235
242
  attach_function :zmq_send, [:pointer, :pointer, :size_t, :int], :int
236
-
243
+
237
244
  module EventDataLayout
238
245
  def self.included(base)
239
246
  base.class_eval do
@@ -259,7 +266,7 @@ module ZMQ
259
266
 
260
267
  def to_s; inspect; end
261
268
  end # class EventData
262
-
269
+
263
270
  end
264
271
  end
265
272
 
data/lib/ffi-rzmq/poll.rb CHANGED
@@ -1,14 +1,14 @@
1
+ require 'forwardable'
1
2
 
2
3
  module ZMQ
3
-
4
4
  class Poller
5
+ extend Forwardable
5
6
 
7
+ def_delegators :@poll_items, :size, :inspect
6
8
  attr_reader :readables, :writables
7
9
 
8
10
  def initialize
9
- @items = ZMQ::PollItems.new
10
- @raw_to_socket = {}
11
- @sockets = []
11
+ @poll_items = ZMQ::PollItems.new
12
12
  @readables = []
13
13
  @writables = []
14
14
  end
@@ -28,8 +28,8 @@ module ZMQ
28
28
  # frequency.
29
29
  #
30
30
  # Returns 0 when there are no registered sockets that are readable
31
- # or writable.
32
- #
31
+ # or writable.
32
+ #
33
33
  # Return 1 (or greater) to indicate the number of readable or writable
34
34
  # sockets. These sockets should be processed using the #readables and
35
35
  # #writables accessors.
@@ -38,14 +38,11 @@ module ZMQ
38
38
  # error number.
39
39
  #
40
40
  def poll timeout = :blocking
41
- unless @items.empty?
41
+ unless @poll_items.empty?
42
42
  timeout = adjust timeout
43
- items_triggered = LibZMQ.zmq_poll @items.address, @items.size, timeout
44
-
45
- if Util.resultcode_ok?(items_triggered)
46
- update_selectables
47
- end
48
-
43
+ items_triggered = LibZMQ.zmq_poll @poll_items.address, @poll_items.size, timeout
44
+
45
+ update_selectables if Util.resultcode_ok?(items_triggered)
49
46
  items_triggered
50
47
  else
51
48
  0
@@ -62,131 +59,85 @@ module ZMQ
62
59
  poll 0
63
60
  end
64
61
 
65
- # Register the +sock+ for +events+. This method is idempotent meaning
62
+ # Register the +pollable+ for +events+. This method is idempotent meaning
66
63
  # it can be called multiple times with the same data and the socket
67
64
  # will only get registered at most once. Calling multiple times with
68
65
  # different values for +events+ will OR the event information together.
69
66
  #
70
- def register sock, events = ZMQ::POLLIN | ZMQ::POLLOUT, fd = 0
71
- return false if (sock.nil? && fd.zero?) || events.zero?
67
+ def register pollable, events = ZMQ::POLLIN | ZMQ::POLLOUT
68
+ return if pollable.nil? || events.zero?
72
69
 
73
- item = @items.get(@sockets.index(sock))
74
-
75
- unless item
76
- @sockets << sock
77
- item = LibZMQ::PollItem.new
78
-
79
- if sock.kind_of?(ZMQ::Socket) || sock.kind_of?(Socket)
80
- item[:socket] = sock.socket
81
- item[:fd] = 0
82
- else
83
- item[:socket] = FFI::MemoryPointer.new(0)
84
- item[:fd] = fd
85
- end
86
-
87
- @raw_to_socket[item.socket.address] = sock
88
- @items << item
70
+ unless item = @poll_items[pollable]
71
+ item = PollItem.from_pollable(pollable)
72
+ @poll_items << item
89
73
  end
90
74
 
91
- item[:events] |= events
75
+ item.events |= events
92
76
  end
93
77
 
94
- # Deregister the +sock+ for +events+. When there are no events left,
95
- # this also deletes the socket from the poll items.
78
+ # Deregister the +pollable+ for +events+. When there are no events left
79
+ # or socket has been closed this also deletes the socket from the poll items.
96
80
  #
97
- def deregister sock, events, fd = 0
98
- return unless sock || !fd.zero?
99
-
100
- item = @items.get(@sockets.index(sock))
81
+ def deregister pollable, events
82
+ return unless pollable
101
83
 
102
- if item && (item[:events] & events) > 0
103
- # change the value in place
104
- item[:events] ^= events
105
-
106
- delete sock if item[:events].zero?
84
+ item = @poll_items[pollable]
85
+ if item && (item.events & events) > 0
86
+ item.events ^= events
87
+ delete(pollable) if item.events.zero? || item.closed?
107
88
  true
108
89
  else
109
90
  false
110
91
  end
111
92
  end
112
93
 
113
- # A helper method to register a +sock+ as readable events only.
94
+ # A helper method to register a +pollable+ as readable events only.
114
95
  #
115
- def register_readable sock
116
- register sock, ZMQ::POLLIN, 0
96
+ def register_readable pollable
97
+ register pollable, ZMQ::POLLIN
117
98
  end
118
99
 
119
- # A helper method to register a +sock+ for writable events only.
100
+ # A helper method to register a +pollable+ for writable events only.
120
101
  #
121
- def register_writable sock
122
- register sock, ZMQ::POLLOUT, 0
102
+ def register_writable pollable
103
+ register pollable, ZMQ::POLLOUT
123
104
  end
124
105
 
125
- # A helper method to deregister a +sock+ for readable events.
106
+ # A helper method to deregister a +pollable+ for readable events.
126
107
  #
127
- def deregister_readable sock
128
- deregister sock, ZMQ::POLLIN, 0
108
+ def deregister_readable pollable
109
+ deregister pollable, ZMQ::POLLIN
129
110
  end
130
111
 
131
- # A helper method to deregister a +sock+ for writable events.
112
+ # A helper method to deregister a +pollable+ for writable events.
132
113
  #
133
- def deregister_writable sock
134
- deregister sock, ZMQ::POLLOUT, 0
114
+ def deregister_writable pollable
115
+ deregister pollable, ZMQ::POLLOUT
135
116
  end
136
117
 
137
- # Deletes the +sock+ for all subscribed events. Called internally
118
+ # Deletes the +pollable+ for all subscribed events. Called internally
138
119
  # when a socket has been deregistered and has no more events
139
120
  # registered anywhere.
140
121
  #
141
122
  # Can also be called directly to remove the socket from the polling
142
123
  # array.
143
124
  #
144
- def delete sock
145
- unless (size = @sockets.size).zero?
146
- @sockets.delete_if { |socket| socket.socket.address == sock.socket.address }
147
- socket_deleted = size != @sockets.size
148
-
149
- item_deleted = @items.delete sock
150
-
151
- raw_deleted = @raw_to_socket.delete(sock.socket.address)
152
-
153
- socket_deleted && item_deleted && raw_deleted
154
-
155
- else
156
- false
157
- end
125
+ def delete pollable
126
+ return false if @poll_items.empty?
127
+ @poll_items.delete(pollable)
158
128
  end
159
129
 
160
- def size(); @items.size; end
161
-
162
- def inspect
163
- @items.inspect
164
- end
165
-
166
- def to_s(); inspect; end
167
-
130
+ def to_s inspect; end
168
131
 
169
132
  private
170
133
 
171
- def items_hash hash
172
- @items.each do |poll_item|
173
- hash[@raw_to_socket[poll_item.socket.address]] = poll_item
174
- end
175
- end
176
-
177
134
  def update_selectables
178
135
  @readables.clear
179
136
  @writables.clear
180
137
 
181
- @items.each do |poll_item|
182
- #FIXME: spec for sockets *and* file descriptors
183
- if poll_item.readable?
184
- @readables << (poll_item.socket.address.zero? ? poll_item.fd : @raw_to_socket[poll_item.socket.address])
185
- end
186
-
187
- if poll_item.writable?
188
- @writables << (poll_item.socket.address.zero? ? poll_item.fd : @raw_to_socket[poll_item.socket.address])
189
- end
138
+ @poll_items.each do |poll_item|
139
+ @readables << poll_item.pollable if poll_item.readable?
140
+ @writables << poll_item.pollable if poll_item.writable?
190
141
  end
191
142
  end
192
143
 
@@ -198,6 +149,7 @@ module ZMQ
198
149
  # Users will pass in values measured as
199
150
  # milliseconds, so we need to convert that value to
200
151
  # microseconds for the library.
152
+ #
201
153
  if LibZMQ.version2?
202
154
  def adjust timeout
203
155
  if :blocking == timeout || -1 == timeout
@@ -216,6 +168,6 @@ module ZMQ
216
168
  end
217
169
  end
218
170
  end
219
- end
220
171
 
221
- end # module ZMQ
172
+ end
173
+ end