ffi-rzmq 1.0.3 → 2.0.1

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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +1 -1
  3. data/AUTHORS.txt +5 -1
  4. data/History.txt +24 -0
  5. data/README.rdoc +2 -4
  6. data/examples/README.rdoc +1 -3
  7. data/examples/{v3api/latency_measurement.rb → latency_measurement.rb} +1 -2
  8. data/examples/{v3api/local_lat.rb → local_lat.rb} +1 -1
  9. data/examples/{v3api/local_lat_poll.rb → local_lat_poll.rb} +4 -4
  10. data/examples/{v3api/local_throughput.rb → local_throughput.rb} +1 -1
  11. data/examples/{v3api/pub.rb → pub.rb} +1 -1
  12. data/examples/{v2api/publish_subscribe.rb → publish_subscribe.rb} +2 -2
  13. data/examples/{v2api/remote_lat.rb → remote_lat.rb} +1 -1
  14. data/examples/{v3api/remote_throughput.rb → remote_throughput.rb} +4 -3
  15. data/examples/repreq_over_curve.rb +60 -0
  16. data/examples/{v2api/reqrep_poll.rb → reqrep_poll.rb} +3 -4
  17. data/examples/{v2api/request_response.rb → request_response.rb} +1 -2
  18. data/examples/{v3api/sub.rb → sub.rb} +1 -2
  19. data/examples/{v3api/throughput_measurement.rb → throughput_measurement.rb} +1 -1
  20. data/examples/{v3api/xreqxrep_poll.rb → xreqxrep_poll.rb} +6 -7
  21. data/ffi-rzmq.gemspec +4 -4
  22. data/lib/ffi-rzmq/context.rb +25 -53
  23. data/lib/ffi-rzmq/device.rb +8 -4
  24. data/lib/ffi-rzmq/exceptions.rb +3 -0
  25. data/lib/ffi-rzmq/message.rb +24 -30
  26. data/lib/ffi-rzmq/poll.rb +5 -16
  27. data/lib/ffi-rzmq/socket.rb +132 -282
  28. data/lib/ffi-rzmq/util.rb +28 -36
  29. data/lib/ffi-rzmq/version.rb +1 -1
  30. data/lib/ffi-rzmq.rb +2 -3
  31. data/spec/context_spec.rb +3 -8
  32. data/spec/device_spec.rb +10 -9
  33. data/spec/nonblocking_recv_spec.rb +7 -7
  34. data/spec/pushpull_spec.rb +8 -7
  35. data/spec/reqrep_spec.rb +6 -6
  36. data/spec/socket_spec.rb +43 -130
  37. data/spec/spec_helper.rb +3 -11
  38. data/spec/util_spec.rb +28 -0
  39. metadata +80 -104
  40. data/examples/v2api/latency_measurement.rb +0 -139
  41. data/examples/v2api/local_lat.rb +0 -58
  42. data/examples/v2api/local_lat_poll.rb +0 -66
  43. data/examples/v2api/local_throughput.rb +0 -58
  44. data/examples/v2api/pub.rb +0 -46
  45. data/examples/v2api/remote_throughput.rb +0 -39
  46. data/examples/v2api/sub.rb +0 -74
  47. data/examples/v2api/throughput_measurement.rb +0 -138
  48. data/examples/v2api/xreqxrep_poll.rb +0 -93
  49. data/examples/v3api/publish_subscribe.rb +0 -82
  50. data/examples/v3api/remote_lat.rb +0 -71
  51. data/examples/v3api/reqrep_poll.rb +0 -62
  52. data/examples/v3api/request_response.rb +0 -40
  53. data/lib/ffi-rzmq/constants.rb +0 -187
  54. data/lib/ffi-rzmq/libc.rb +0 -19
  55. data/lib/ffi-rzmq/libzmq.rb +0 -283
@@ -1,74 +0,0 @@
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::IDENTITY, rand(999_999).to_s))
29
- assert(s.setsockopt(ZMQ::SUBSCRIBE, ""))
30
- assert(s.setsockopt(ZMQ::HWM, 1))
31
- #assert(s.setsockopt(ZMQ::RCVHWM, 0))
32
- #assert(s.setsockopt(ZMQ::SNDHWM, 0))
33
-
34
- assert(s.connect(bind_to))
35
- sleep 1
36
-
37
- msg = ZMQ::Message.new
38
- msg = ''
39
- assert(s.recv_string(msg))
40
- raise unless msg.to_i == 0
41
-
42
- start_time = Time.now
43
-
44
- i = 1
45
- while i < message_count - 1
46
- assert(s.recv_string(msg))
47
- msg_i = msg.to_i
48
- missed = (msg_i - i) - 1
49
- puts "missed [#{missed}] messages" if missed > 0
50
- i = msg_i
51
-
52
- start = Time.now
53
- while (Time.now - start) < sleep_time
54
- end
55
- end
56
-
57
- end_time = Time.now
58
-
59
- elapsed = (end_time.to_f - start_time.to_f) * 1000000
60
- if elapsed == 0
61
- elapsed = 1
62
- end
63
-
64
- throughput = message_count * 1000000 / elapsed
65
- megabits = throughput * message_size * 8 / 1000000
66
-
67
- puts "message size: %i [B]" % message_size
68
- puts "message count: %i" % message_count
69
- puts "mean throughput: %i [msg/s]" % throughput
70
- puts "mean throughput: %.3f [Mb/s]" % megabits
71
-
72
- assert(s.close)
73
-
74
- ctx.terminate
@@ -1,138 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
2
-
3
-
4
- # Within a single process, we start up five threads. Main thread has a PUB (publisher)
5
- # socket and the secondary threads have SUB (subscription) sockets. We measure the
6
- # *throughput* between these sockets. A high-water mark (HWM) is *not* set, so the
7
- # publisher queue is free to grow to the size of memory without dropping packets.
8
- #
9
- # This example also illustrates how a single context can be shared amongst several
10
- # threads. Sharing a single context also allows a user to specify the "inproc"
11
- # transport in addition to "tcp" and "ipc".
12
- #
13
- # % ruby throughput_measurement.rb tcp://127.0.0.1:5555 1024 1_000_000
14
- #
15
- # % ruby throughput_measurement.rb inproc://lm_sock 1024 1_000_000
16
- #
17
-
18
- if ARGV.length < 3
19
- puts "usage: ruby throughput_measurement.rb <connect-to> <message-size> <roundtrip-count>"
20
- exit
21
- end
22
-
23
- link = ARGV[0]
24
- message_size = ARGV[1].to_i
25
- count = ARGV[2].to_i
26
-
27
- def assert(rc)
28
- raise "Last API call failed at #{caller(1)}" unless rc >= 0
29
- end
30
-
31
- begin
32
- master_context = ZMQ::Context.new
33
- rescue ContextError => e
34
- STDERR.puts "Failed to allocate context or socket!"
35
- raise
36
- end
37
-
38
-
39
- class Receiver
40
- def initialize context, link, size, count
41
- @context = context
42
- @link = link
43
- @size = size
44
- @count = count
45
-
46
- begin
47
- @socket = @context.socket(ZMQ::SUB)
48
- rescue ContextError => e
49
- STDERR.puts "Failed to allocate SUB socket!"
50
- raise
51
- end
52
-
53
- assert(@socket.setsockopt(ZMQ::LINGER, 100))
54
- assert(@socket.setsockopt(ZMQ::SUBSCRIBE, ""))
55
-
56
- assert(@socket.connect(@link))
57
- end
58
-
59
- def run
60
- msg = ZMQ::Message.new
61
- assert(@socket.recvmsg(msg))
62
-
63
- elapsed = elapsed_microseconds do
64
- (@count -1).times do
65
- assert(@socket.recvmsg(msg))
66
- end
67
- end
68
-
69
- throughput = @count * 1000000 / elapsed
70
- megabits = throughput * @size * 8 / 1000000
71
-
72
- puts "message size: %i [B]" % @size
73
- puts "message count: %i" % @count
74
- puts "mean throughput: %i [msg/s]" % throughput
75
- puts "mean throughput: %.3f [Mb/s]" % megabits
76
-
77
- assert(@socket.close)
78
- end
79
-
80
- def elapsed_microseconds(&blk)
81
- start = Time.now
82
- yield
83
- ((Time.now - start) * 1_000_000)
84
- end
85
- end
86
-
87
- class Transmitter
88
- def initialize context, link, size, count
89
- @context = context
90
- @link = link
91
- @size = size
92
- @count = count
93
-
94
- begin
95
- @socket = @context.socket(ZMQ::PUB)
96
- rescue ContextError => e
97
- STDERR.puts "Failed to allocate PUB socket!"
98
- raise
99
- end
100
-
101
- assert(@socket.setsockopt(ZMQ::LINGER, 100))
102
-
103
- assert(@socket.bind(@link))
104
- end
105
-
106
- def run
107
- sleep 1
108
- contents = "#{'0' * @size}"
109
-
110
- i = 0
111
- while i < @count
112
- msg = ZMQ::Message.new(contents)
113
- assert(@socket.sendmsg(msg))
114
- i += 1
115
- end
116
-
117
- assert(@socket.close)
118
- end
119
- end
120
-
121
- threads = []
122
-
123
- threads << Thread.new do
124
- transmitter = Transmitter.new(master_context, link, message_size, count)
125
- transmitter.run
126
- end
127
-
128
- 1.times do
129
- threads << Thread.new do
130
- receiver = Receiver.new(master_context, link, message_size, count)
131
- receiver.run
132
- end
133
- end
134
-
135
-
136
- threads.each {|t| t.join}
137
-
138
- master_context.terminate
@@ -1,93 +0,0 @@
1
-
2
- require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
3
-
4
-
5
- def assert(rc)
6
- raise "Last API call failed at #{caller(1)}" unless rc >= 0
7
- end
8
-
9
- link = "tcp://127.0.0.1:5555"
10
-
11
-
12
- begin
13
- ctx = ZMQ::Context.new
14
- s1 = ctx.socket(ZMQ::XREQ)
15
- s2 = ctx.socket(ZMQ::XREP)
16
- rescue ContextError => e
17
- STDERR.puts "Failed to allocate context or socket"
18
- raise
19
- end
20
-
21
- s1.identity = 'socket1.xreq'
22
- s2.identity = 'socket2.xrep'
23
-
24
- assert(s1.setsockopt(ZMQ::LINGER, 100))
25
- assert(s2.setsockopt(ZMQ::LINGER, 100))
26
-
27
- assert(s1.bind(link))
28
- assert(s2.connect(link))
29
-
30
- poller = ZMQ::Poller.new
31
- poller.register_readable(s2)
32
- poller.register_writable(s1)
33
-
34
- start_time = Time.now
35
- @unsent = true
36
-
37
- until @done do
38
- assert(poller.poll_nonblock)
39
-
40
- # send the message after 5 seconds
41
- if Time.now - start_time > 5 && @unsent
42
- puts "sending payload nonblocking"
43
-
44
- 5.times do |i|
45
- payload = "#{ i.to_s * 40 }"
46
- assert(s1.send_string(payload, ZMQ::NonBlocking))
47
- end
48
- @unsent = false
49
- end
50
-
51
- # check for messages after 1 second
52
- if Time.now - start_time > 1
53
- poller.readables.each do |sock|
54
-
55
- if sock.identity =~ /xrep/
56
- routing_info = ''
57
- assert(sock.recv_string(routing_info, ZMQ::NonBlocking))
58
- puts "routing_info received [#{routing_info}] on socket.identity [#{sock.identity}]"
59
- else
60
- routing_info = nil
61
- received_msg = ''
62
- assert(sock.recv_string(received_msg, ZMQ::NonBlocking))
63
-
64
- # skip to the next iteration if received_msg is nil; that means we got an EAGAIN
65
- next unless received_msg
66
- puts "message received [#{received_msg}] on socket.identity [#{sock.identity}]"
67
- end
68
-
69
- while sock.more_parts? do
70
- received_msg = ''
71
- assert(sock.recv_string(received_msg, ZMQ::NonBlocking))
72
-
73
- puts "message received [#{received_msg}]"
74
- end
75
-
76
- puts "kick back a reply"
77
- assert(sock.send_string(routing_info, ZMQ::SNDMORE | ZMQ::NonBlocking)) if routing_info
78
- time = Time.now.strftime "%Y-%m-%dT%H:%M:%S.#{Time.now.usec}"
79
- reply = "reply " + sock.identity.upcase + " #{time}"
80
- puts "sent reply [#{reply}], #{time}"
81
- assert(sock.send_string(reply))
82
- @done = true
83
- poller.register_readable(s1)
84
- end
85
- end
86
- end
87
-
88
- puts "executed in [#{Time.now - start_time}] seconds"
89
-
90
- assert(s1.close)
91
- assert(s2.close)
92
-
93
- ctx.terminate
@@ -1,82 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
2
-
3
-
4
- def assert(rc)
5
- raise "Last API call failed at #{caller(1)}" unless rc >= 0
6
- end
7
-
8
- link = "tcp://127.0.0.1:5555"
9
-
10
- begin
11
- ctx = ZMQ::Context.new
12
- s1 = ctx.socket(ZMQ::PUB)
13
- s2 = ctx.socket(ZMQ::SUB)
14
- s3 = ctx.socket(ZMQ::SUB)
15
- s4 = ctx.socket(ZMQ::SUB)
16
- s5 = ctx.socket(ZMQ::SUB)
17
- rescue ContextError => e
18
- STDERR.puts "Failed to allocate context or socket!"
19
- raise
20
- end
21
-
22
- assert(s1.setsockopt(ZMQ::LINGER, 100))
23
- assert(s2.setsockopt(ZMQ::SUBSCRIBE, '')) # receive all
24
- assert(s3.setsockopt(ZMQ::SUBSCRIBE, 'animals')) # receive any starting with this string
25
- assert(s4.setsockopt(ZMQ::SUBSCRIBE, 'animals.dog'))
26
- assert(s5.setsockopt(ZMQ::SUBSCRIBE, 'animals.cat'))
27
-
28
- assert(s1.bind(link))
29
- assert(s2.connect(link))
30
- assert(s3.connect(link))
31
- assert(s4.connect(link))
32
- assert(s5.connect(link))
33
-
34
- sleep 1
35
-
36
- topic = "animals.dog"
37
- payload = "Animal crackers!"
38
-
39
- s1.identity = "publisher-A"
40
- puts "sending"
41
- # use the new multi-part messaging support to
42
- # automatically separate the topic from the body
43
- assert(s1.send_string(topic, ZMQ::SNDMORE))
44
- assert(s1.send_string(payload, ZMQ::SNDMORE))
45
- assert(s1.send_string(s1.identity))
46
-
47
- topic = ''
48
- assert(s2.recv_string(topic))
49
-
50
- body = ''
51
- assert(s2.recv_string(body)) if s2.more_parts?
52
-
53
- identity = ''
54
- assert(s2.recv_string(identity)) if s2.more_parts?
55
- puts "s2 received topic [#{topic}], body [#{body}], identity [#{identity}]"
56
-
57
-
58
-
59
- topic = ''
60
- assert(s3.recv_string(topic))
61
-
62
- body = ''
63
- assert(s3.recv_string(body)) if s3.more_parts?
64
- puts "s3 received topic [#{topic}], body [#{body}]"
65
-
66
- topic = ''
67
- assert(s4.recv_string(topic))
68
-
69
- body = ''
70
- assert(s4.recv_string(body)) if s4.more_parts?
71
- puts "s4 received topic [#{topic}], body [#{body}]"
72
-
73
- s5_string = ''
74
- rc = s5.recv_string(s5_string, ZMQ::NonBlocking)
75
- eagain = (rc == -1 && ZMQ::Util.errno == ZMQ::EAGAIN)
76
- puts(eagain ? "s5 received no messages" : "s5 FAILED")
77
-
78
- [s1, s2, s3, s4, s5].each do |socket|
79
- assert(socket.close)
80
- end
81
-
82
- ctx.terminate
@@ -1,71 +0,0 @@
1
- #
2
- # Copyright (c) 2007-2010 iMatix Corporation
3
- #
4
- # This file is part of 0MQ.
5
- #
6
- # 0MQ is free software; you can redistribute it and/or modify it under
7
- # the terms of the Lesser GNU General Public License as published by
8
- # the Free Software Foundation; either version 3 of the License, or
9
- # (at your option) any later version.
10
- #
11
- # 0MQ is distributed in the hope that it will be useful,
12
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- # Lesser GNU General Public License for more details.
15
- #
16
- # You should have received a copy of the Lesser GNU General Public License
17
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
-
19
-
20
- require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
21
-
22
- if ARGV.length < 3
23
- puts "usage: ruby remote_lat.rb <connect-to> <message-size> <roundtrip-count>"
24
- exit
25
- end
26
-
27
- def assert(rc)
28
- raise "Last API call failed at #{caller(1)}" unless rc >= 0
29
- end
30
-
31
- connect_to = ARGV[0]
32
- message_size = ARGV[1].to_i
33
- roundtrip_count = ARGV[2].to_i
34
-
35
- begin
36
- ctx = ZMQ::Context.new
37
- s = ctx.socket(ZMQ::REQ)
38
- rescue ContextError => e
39
- STDERR.puts "Failed to allocate context or socket!"
40
- raise
41
- end
42
-
43
- assert(s.setsockopt(ZMQ::LINGER, 100))
44
- assert(s.connect(connect_to))
45
-
46
- msg = "#{ '3' * message_size }"
47
-
48
- start_time = Time.now
49
-
50
- roundtrip_count.times do
51
- assert(s.send_string(msg, 0))
52
-
53
- msg = ''
54
- assert(s.recv_string(msg, 0))
55
-
56
- raise "Message size doesn't match, expected [#{message_size}] but received [#{msg.size}]" if message_size != msg.size
57
- end
58
-
59
- end_time = Time.now
60
- elapsed_secs = (end_time.to_f - start_time.to_f)
61
- elapsed_usecs = elapsed_secs * 1000000
62
- latency = elapsed_usecs / roundtrip_count / 2
63
-
64
- puts "message size: %i [B]" % message_size
65
- puts "roundtrip count: %i" % roundtrip_count
66
- puts "throughput (msgs/s): %i" % (roundtrip_count / elapsed_secs)
67
- puts "mean latency: %.3f [us]" % latency
68
-
69
- assert(s.close)
70
-
71
- ctx.terminate
@@ -1,62 +0,0 @@
1
-
2
- require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
3
-
4
-
5
- def assert(rc)
6
- raise "Last API call failed at #{caller(1)}" unless rc >= 0
7
- end
8
-
9
- link = "tcp://127.0.0.1:5554"
10
-
11
- begin
12
- ctx = ZMQ::Context.new
13
- s1 = ctx.socket(ZMQ::REQ)
14
- s2 = ctx.socket(ZMQ::REP)
15
- rescue ContextError => e
16
- STDERR.puts "Failed to allocate context or socket!"
17
- raise
18
- end
19
-
20
- assert(s1.setsockopt(ZMQ::LINGER, 100))
21
- assert(s2.setsockopt(ZMQ::LINGER, 100))
22
-
23
- assert(s1.connect(link))
24
- assert(s2.bind(link))
25
-
26
- poller = ZMQ::Poller.new
27
- poller.register_readable(s2)
28
- poller.register_writable(s1)
29
-
30
- start_time = Time.now
31
- @unsent = true
32
-
33
- until @done do
34
- assert(poller.poll_nonblock)
35
-
36
- # send the message after 5 seconds
37
- if Time.now - start_time > 5 && @unsent
38
- payload = "#{ '3' * 1024 }"
39
-
40
- puts "sending payload nonblocking"
41
- assert(s1.send_string(payload, ZMQ::NonBlocking))
42
- @unsent = false
43
- end
44
-
45
- # check for messages after 1 second
46
- if Time.now - start_time > 1
47
- poller.readables.each do |sock|
48
- received_msg = ''
49
- assert(sock.recv_string(received_msg, ZMQ::NonBlocking))
50
-
51
- puts "message received [#{received_msg}]"
52
- @done = true
53
- end
54
- end
55
- end
56
-
57
- puts "executed in [#{Time.now - start_time}] seconds"
58
-
59
- assert(s1.close)
60
- assert(s2.close)
61
-
62
- ctx.terminate
@@ -1,40 +0,0 @@
1
-
2
- require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
3
-
4
-
5
- def assert(rc)
6
- raise "Last API call failed at #{caller(1)}" unless rc >= 0
7
- end
8
-
9
- link = "tcp://127.0.0.1:5555"
10
-
11
- begin
12
- ctx = ZMQ::Context.new
13
- s1 = ctx.socket(ZMQ::REQ)
14
- s2 = ctx.socket(ZMQ::REP)
15
- rescue ContextError => e
16
- STDERR.puts "Failed to allocate context or socket"
17
- raise
18
- end
19
-
20
- assert(s1.setsockopt(ZMQ::LINGER, 100))
21
- assert(s2.setsockopt(ZMQ::LINGER, 100))
22
-
23
- assert(s2.bind(link))
24
- assert(s1.connect(link))
25
-
26
- payload = "#{ '3' * 2048 }"
27
- sent_msg = ZMQ::Message.new(payload)
28
- received_msg = ZMQ::Message.new
29
-
30
- assert(s1.sendmsg(sent_msg))
31
- assert(s2.recvmsg(received_msg))
32
-
33
- result = payload == received_msg.copy_out_string ? "Request received" : "Received wrong payload"
34
-
35
- p result
36
-
37
- assert(s1.close)
38
- assert(s2.close)
39
-
40
- ctx.terminate