ffi-rzmq 0.9.3 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -71,7 +71,7 @@ assert(s4.recv_string(body)) if s4.more_parts?
71
71
  puts "s4 received topic [#{topic}], body [#{body}]"
72
72
 
73
73
  s5_string = ''
74
- rc = s5.recv_string(s5_string, ZMQ::DONTWAIT)
74
+ rc = s5.recv_string(s5_string, ZMQ::NonBlocking)
75
75
  eagain = (rc == -1 && ZMQ::Util.errno == ZMQ::EAGAIN)
76
76
  puts(eagain ? "s5 received no messages" : "s5 FAILED")
77
77
 
@@ -38,7 +38,7 @@ until @done do
38
38
  payload = "#{ '3' * 1024 }"
39
39
 
40
40
  puts "sending payload nonblocking"
41
- assert(s1.send_string(payload, ZMQ::DONTWAIT))
41
+ assert(s1.send_string(payload, ZMQ::NonBlocking))
42
42
  @unsent = false
43
43
  end
44
44
 
@@ -46,7 +46,7 @@ until @done do
46
46
  if Time.now - start_time > 1
47
47
  poller.readables.each do |sock|
48
48
  received_msg = ''
49
- assert(sock.recv_string(received_msg, ZMQ::DONTWAIT))
49
+ assert(sock.recv_string(received_msg, ZMQ::NonBlocking))
50
50
 
51
51
  puts "message received [#{received_msg}]"
52
52
  @done = true
@@ -0,0 +1,69 @@
1
+
2
+ require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
3
+
4
+ #if ARGV.length != 3
5
+ # puts "usage: ruby local_throughtput.rb <bind-to> <message-size> <message-count>"
6
+ # Process.exit
7
+ #end
8
+ p ZMQ::Util.version
9
+
10
+ def assert(rc)
11
+ raise "Last API call failed at #{caller(1)}" unless rc >= 0
12
+ end
13
+
14
+ bind_to = ARGV[0]
15
+ message_size = ARGV[1].to_i
16
+ message_count = ARGV[2].to_i
17
+ sleep_time = ARGV[3].to_f
18
+
19
+ begin
20
+ ctx = ZMQ::Context.new
21
+ s = ZMQ::Socket.new(ctx.pointer, ZMQ::SUB)
22
+ rescue ContextError => e
23
+ STDERR.puts "Failed to allocate context or socket!"
24
+ raise
25
+ end
26
+
27
+ #assert(s.setsockopt(ZMQ::LINGER, 100))
28
+ assert(s.setsockopt(ZMQ::SUBSCRIBE, ""))
29
+ assert(s.setsockopt(ZMQ::RCVHWM, 20))
30
+ #assert(s.setsockopt(ZMQ::RCVHWM, 0))
31
+ #assert(s.setsockopt(ZMQ::SNDHWM, 0))
32
+
33
+ assert(s.connect(bind_to))
34
+ sleep 1
35
+
36
+ msg = ZMQ::Message.new
37
+ msg = ''
38
+ assert(s.recv_string(msg))
39
+ raise unless msg.to_i == 0
40
+
41
+ start_time = Time.now
42
+
43
+ i = 1
44
+ while i < message_count
45
+ assert(s.recv_string(msg))
46
+ msg_i = msg.to_i
47
+ puts "missed [#{msg_i - i}] messages"
48
+ i = msg_i
49
+ sleep(sleep_time)
50
+ end
51
+
52
+ end_time = Time.now
53
+
54
+ elapsed = (end_time.to_f - start_time.to_f) * 1000000
55
+ if elapsed == 0
56
+ elapsed = 1
57
+ end
58
+
59
+ throughput = message_count * 1000000 / elapsed
60
+ megabits = throughput * message_size * 8 / 1000000
61
+
62
+ puts "message size: %i [B]" % message_size
63
+ puts "message count: %i" % message_count
64
+ puts "mean throughput: %i [msg/s]" % throughput
65
+ puts "mean throughput: %.3f [Mb/s]" % megabits
66
+
67
+ assert(s.close)
68
+
69
+ ctx.terminate
@@ -43,7 +43,7 @@ until @done do
43
43
 
44
44
  5.times do |i|
45
45
  payload = "#{ i.to_s * 40 }"
46
- assert(s1.send_string(payload, ZMQ::DONTWAIT))
46
+ assert(s1.send_string(payload, ZMQ::NonBlocking))
47
47
  end
48
48
  @unsent = false
49
49
  end
@@ -54,12 +54,12 @@ until @done do
54
54
 
55
55
  if sock.identity =~ /xrep/
56
56
  routing_info = ''
57
- assert(sock.recv_string(routing_info, ZMQ::DONTWAIT))
57
+ assert(sock.recv_string(routing_info, ZMQ::NonBlocking))
58
58
  puts "routing_info received [#{routing_info}] on socket.identity [#{sock.identity}]"
59
59
  else
60
60
  routing_info = nil
61
61
  received_msg = ''
62
- assert(sock.recv_string(received_msg, ZMQ::DONTWAIT))
62
+ assert(sock.recv_string(received_msg, ZMQ::NonBlocking))
63
63
 
64
64
  # skip to the next iteration if received_msg is nil; that means we got an EAGAIN
65
65
  next unless received_msg
@@ -68,13 +68,13 @@ until @done do
68
68
 
69
69
  while sock.more_parts? do
70
70
  received_msg = ''
71
- assert(sock.recv_string(received_msg, ZMQ::DONTWAIT))
71
+ assert(sock.recv_string(received_msg, ZMQ::NonBlocking))
72
72
 
73
73
  puts "message received [#{received_msg}]"
74
74
  end
75
75
 
76
76
  puts "kick back a reply"
77
- assert(sock.send_string(routing_info, ZMQ::SNDMORE | ZMQ::DONTWAIT)) if routing_info
77
+ assert(sock.send_string(routing_info, ZMQ::SNDMORE | ZMQ::NonBlocking)) if routing_info
78
78
  time = Time.now.strftime "%Y-%m-%dT%H:%M:%S.#{Time.now.usec}"
79
79
  reply = "reply " + sock.identity.upcase + " #{time}"
80
80
  puts "sent reply [#{reply}], #{time}"
data/ffi-rzmq.gemspec CHANGED
@@ -6,12 +6,12 @@ Gem::Specification.new do |s|
6
6
  s.name = "ffi-rzmq"
7
7
  s.version = ZMQ::VERSION
8
8
  s.authors = ["Chuck Remes"]
9
- s.email = ["cremes@mac.com"]
9
+ s.email = ["git@chuckremes.com"]
10
10
  s.homepage = "http://github.com/chuckremes/ffi-rzmq"
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:
14
+ and run by any ruby runtime that supports FFI. That's all of them -
15
15
  MRI 1.9.x, Rubinius and JRuby.}
16
16
 
17
17
  s.rubyforge_project = "ffi-rzmq"
@@ -1,7 +1,7 @@
1
1
  module ZMQ
2
2
  # Set up all of the constants that are *common* to all API
3
3
  # versions
4
-
4
+
5
5
  # Socket types
6
6
  PAIR = 0
7
7
  PUB = 1
@@ -41,6 +41,8 @@ module ZMQ
41
41
  RECONNECT_IVL = 18
42
42
  BACKLOG = 19
43
43
  RECONNECT_IVL_MAX = 21
44
+ RCVTIMEO = 27
45
+ SNDTIMEO = 28
44
46
 
45
47
  # Send/recv options
46
48
  SNDMORE = 2
@@ -58,13 +60,14 @@ module ZMQ
58
60
  ENOMEM = Errno::ENOMEM::Errno
59
61
  ENODEV = Errno::ENODEV::Errno
60
62
  EFAULT = Errno::EFAULT::Errno
63
+ EINTR = Errno::EINTR::Errno
61
64
 
62
65
  # ZMQ errors
63
66
  HAUSNUMERO = 156384712
64
- EMTHREAD = (HAUSNUMERO + 50)
65
67
  EFSM = (HAUSNUMERO + 51)
66
68
  ENOCOMPATPROTO = (HAUSNUMERO + 52)
67
69
  ETERM = (HAUSNUMERO + 53)
70
+ EMTHREAD = (HAUSNUMERO + 54)
68
71
 
69
72
  # Rescue unknown constants and use the ZeroMQ defined values
70
73
  # Usually only happens on Windows though some don't resolve on
@@ -78,7 +81,20 @@ module ZMQ
78
81
  ECONNREFUSED = Errno::ECONNREFUSED::Errno rescue (HAUSNUMERO + 7)
79
82
  EINPROGRESS = Errno::EINPROGRESS::Errno rescue (HAUSNUMERO + 8)
80
83
  ENOTSOCK = Errno::ENOTSOCK::Errno rescue (HAUSNUMERO + 9)
81
- EINTR = Errno::EINTR::Errno rescue (HAUSNUMERO + 10)
84
+ EMSGSIZE = Errno::EMSGSIZE::Errno rescue (HAUSNUMERO + 10)
85
+ EAFNOSUPPORT = Errno::EAFNOSUPPORT::Errno rescue (HAUSNUMERO + 11)
86
+ ENETUNREACH = Errno::ENETUNREACH::Errno rescue (HAUSNUMERO + 12)
87
+ ECONNABORTED = Errno::ECONNABORTED::Errno rescue (HAUSNUMERO + 13)
88
+ ECONNRESET = Errno::ECONNRESET::Errno rescue (HAUSNUMERO + 14)
89
+ ENOTCONN = Errno::ENOTCONN::Errno rescue (HAUSNUMERO + 15)
90
+ ETIMEDOUT = Errno::ETIMEDOUT::Errno rescue (HAUSNUMERO + 16)
91
+ EHOSTUNREACH = Errno::EHOSTUNREACH::Errno rescue (HAUSNUMERO + 17)
92
+ ENETRESET = Errno::ENETRESET::Errno rescue (HAUSNUMERO + 18)
93
+
94
+ # Device Types
95
+ STREAMER = 1
96
+ FORWARDER = 2
97
+ QUEUE = 3
82
98
  end # module ZMQ
83
99
 
84
100
 
@@ -93,11 +109,6 @@ if ZMQ::LibZMQ.version2?
93
109
  SocketTypeNameMap[ROUTER] = 'ROUTER'
94
110
  SocketTypeNameMap[DEALER] = 'DEALER'
95
111
 
96
- # Device Types
97
- STREAMER = 1
98
- FORWARDER = 2
99
- QUEUE = 3
100
-
101
112
  # Socket options
102
113
  HWM = 1
103
114
  IDENTITY = 5
@@ -107,6 +118,7 @@ if ZMQ::LibZMQ.version2?
107
118
 
108
119
  # Send/recv options
109
120
  NOBLOCK = 1
121
+ NonBlocking = NOBLOCK
110
122
  end
111
123
  end # version2?
112
124
 
@@ -124,22 +136,48 @@ if ZMQ::LibZMQ.version3?
124
136
  SocketTypeNameMap[XPUB] = 'XPUB'
125
137
  SocketTypeNameMap[XSUB] = 'XSUB'
126
138
 
139
+ # Context options
140
+ IO_THREADS = 1
141
+ MAX_SOCKETS = 2
142
+ IO_THREADS_DFLT = 1
143
+ MAX_SOCKETS_DFLT = 1024
144
+
127
145
  # Socket options
128
- IDENTITY = 5
129
- MAXMSGSIZE = 22
130
- SNDHWM = 23
131
- RCVHWM = 24
146
+ IDENTITY = 5
147
+ MAXMSGSIZE = 22
148
+ SNDHWM = 23
149
+ RCVHWM = 24
132
150
  MULTICAST_HOPS = 25
133
- RCVTIMEO = 27
134
- SNDTIMEO = 28
151
+ IPV4ONLY = 31
152
+ LAST_ENDPOINT = 32
153
+ ROUTER_BEHAVIOR = 33
154
+ TCP_KEEPALIVE = 34
155
+ TCP_KEEPALIVE_CNT = 35
156
+ TCP_KEEPALIVE_IDLE = 36
157
+ TCP_KEEPALIVE_INTVL = 37
158
+ TCP_ACCEPT_FILTER = 38
159
+
160
+ # Message options
161
+ MORE = 1
135
162
 
136
163
  # Send/recv options
137
- DONTWAIT = 1
138
- SNDLABEL = 4
139
-
164
+ DONTWAIT = 1
165
+ SNDLABEL = 4
166
+ NonBlocking = DONTWAIT
167
+
168
+ # Socket events and monitoring
169
+ EVENT_CONNECTED = 1
170
+ EVENT_CONNECT_DELAYED = 2
171
+ EVENT_CONNECT_RETRIED = 4
172
+ EVENT_LISTENING = 8
173
+ EVENT_BIND_FAILED = 16
174
+ EVENT_ACCEPTED = 32
175
+ EVENT_ACCEPT_FAILED = 64
176
+ EVENT_CLOSED = 128
177
+ EVENT_CLOSE_FAILED = 256
178
+ EVENT_DISCONNECTED = 512
140
179
 
141
180
  # Socket & other errors
142
181
  EMFILE = Errno::EMFILE::Errno
143
-
144
182
  end
145
183
  end # version3?
@@ -3,9 +3,9 @@ module ZMQ
3
3
 
4
4
 
5
5
  # Recommended to use the default for +io_threads+
6
- # since most programs will not saturate I/O.
6
+ # since most programs will not saturate I/O.
7
7
  #
8
- # The rule of thumb is to make +io_threads+ equal to the number
8
+ # The rule of thumb is to make +io_threads+ equal to the number
9
9
  # gigabits per second that the application will produce.
10
10
  #
11
11
  # The +io_threads+ number specifies the size of the thread pool
@@ -41,23 +41,50 @@ module ZMQ
41
41
  #
42
42
  #
43
43
  class Context
44
- include ZMQ::Util
45
44
 
46
- attr_reader :context, :pointer
45
+ attr_reader :context, :io_threads, :max_sockets
46
+ alias :pointer :context
47
47
 
48
- def self.create io_threads = 1
49
- new(io_threads) rescue nil
50
- end
51
-
52
48
  # Use the factory method Context#create to make contexts.
53
49
  #
54
- def initialize io_threads = 1
55
- @sockets = []
56
- @context = LibZMQ.zmq_init io_threads
57
- @pointer = @context
58
- error_check 'zmq_init', (@context.nil? || @context.null?) ? -1 : 0
50
+ if LibZMQ.version2?
51
+ def self.create io_threads = 1
52
+ new(io_threads) rescue nil
53
+ end
54
+
55
+ def initialize io_threads = 1
56
+ @io_threads = io_threads
57
+ @context = LibZMQ.zmq_init io_threads
58
+ ZMQ::Util.error_check 'zmq_init', (@context.nil? || @context.null?) ? -1 : 0
59
+
60
+ define_finalizer
61
+ end
62
+ elsif LibZMQ.version3?
63
+
64
+ def self.create(opts = {})
65
+ new(opts) rescue nil
66
+ end
59
67
 
60
- define_finalizer
68
+ def initialize(opts = {})
69
+ if opts.respond_to?(:empty?)
70
+ @io_threads = opts[:io_threads] || IO_THREADS_DFLT
71
+ @max_sockets = opts[:max_sockets] || MAX_SOCKETS_DFLT
72
+ else
73
+ @io_threads = opts || 1
74
+ @max_sockets = MAX_SOCKETS_DFLT
75
+ end
76
+
77
+ @context = LibZMQ.zmq_ctx_new
78
+ ZMQ::Util.error_check 'zmq_ctx_new', (@context.nil? || @context.null?) ? -1 : 0
79
+
80
+ rc = LibZMQ.zmq_ctx_set(@context, ZMQ::IO_THREADS, @io_threads)
81
+ ZMQ::Util.error_check 'zmq_ctx_set', rc
82
+
83
+ rc = LibZMQ.zmq_ctx_set(@context, ZMQ::MAX_SOCKETS, @max_sockets)
84
+ ZMQ::Util.error_check 'zmq_ctx_set', rc
85
+
86
+ define_finalizer
87
+ end
61
88
  end
62
89
 
63
90
  # Call to release the context and any remaining data associated
@@ -67,15 +94,27 @@ module ZMQ
67
94
  #
68
95
  # Returns 0 for success, -1 for failure.
69
96
  #
70
- def terminate
71
- unless @context.nil? || @context.null?
72
- remove_finalizer
73
- rc = LibZMQ.zmq_term @context
74
- @context = nil
75
- @sockets = nil
76
- rc
77
- else
78
- 0
97
+ if LibZMQ.version2?
98
+ def terminate
99
+ unless @context.nil? || @context.null?
100
+ remove_finalizer
101
+ rc = LibZMQ.zmq_term @context
102
+ @context = nil
103
+ rc
104
+ else
105
+ 0
106
+ end
107
+ end
108
+ elsif LibZMQ.version3?
109
+ def terminate
110
+ unless @context.nil? || @context.null?
111
+ remove_finalizer
112
+ rc = LibZMQ.zmq_ctx_destroy(@context)
113
+ @context = nil
114
+ rc
115
+ else
116
+ 0
117
+ end
79
118
  end
80
119
  end
81
120
 
@@ -102,7 +141,7 @@ module ZMQ
102
141
  rescue ContextError => e
103
142
  sock = nil
104
143
  end
105
-
144
+
106
145
  sock
107
146
  end
108
147
 
@@ -1,28 +1,28 @@
1
1
  module ZMQ
2
- if LibZMQ.version2?
3
- class Device
4
- attr_reader :device
5
-
6
- def self.create(device_type, frontend, backend)
2
+
3
+ class Device
4
+ attr_reader :device
5
+
6
+ def self.create(device_type, frontend, backend)
7
+ dev = nil
8
+ begin
9
+ dev = new(device_type, frontend, backend)
10
+ rescue ArgumentError
7
11
  dev = nil
8
- begin
9
- dev = new device_type, frontend, backend
10
- rescue ArgumentError
11
- dev = nil
12
- end
13
-
14
- dev
15
12
  end
16
13
 
17
- def initialize(device_type,frontend,backend)
18
- [["frontend", frontend],["backend", backend]].each do |name,socket|
19
- unless socket.is_a?(ZMQ::Socket)
20
- raise ArgumentError, "Expected a ZMQ::Socket, not a #{socket.class} as the #{name}"
21
- end
22
- end
14
+ dev
15
+ end
23
16
 
24
- LibZMQ.zmq_device(device_type, frontend.socket, backend.socket)
17
+ def initialize(device_type, frontend, backend)
18
+ [["frontend", frontend], ["backend", backend]].each do |name, socket|
19
+ unless socket.is_a?(ZMQ::Socket)
20
+ raise ArgumentError, "Expected a ZMQ::Socket, not a #{socket.class} as the #{name}"
21
+ end
25
22
  end
23
+
24
+ LibZMQ.zmq_device(device_type, frontend.socket, backend.socket)
26
25
  end
27
26
  end
27
+
28
28
  end