ffi-rzmq 1.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +1 -1
  3. data/AUTHORS.txt +5 -1
  4. data/History.txt +45 -0
  5. data/README.rdoc +58 -28
  6. data/Rakefile +15 -0
  7. data/examples/README.rdoc +1 -3
  8. data/examples/{v3api/latency_measurement.rb → latency_measurement.rb} +1 -2
  9. data/examples/{v3api/local_lat.rb → local_lat.rb} +1 -1
  10. data/examples/{v3api/local_lat_poll.rb → local_lat_poll.rb} +4 -4
  11. data/examples/{v3api/local_throughput.rb → local_throughput.rb} +1 -1
  12. data/examples/{v3api/pub.rb → pub.rb} +1 -1
  13. data/examples/{v2api/publish_subscribe.rb → publish_subscribe.rb} +2 -2
  14. data/examples/{v2api/remote_lat.rb → remote_lat.rb} +1 -1
  15. data/examples/{v3api/remote_throughput.rb → remote_throughput.rb} +4 -3
  16. data/examples/repreq_over_curve.rb +60 -0
  17. data/examples/{v2api/reqrep_poll.rb → reqrep_poll.rb} +3 -4
  18. data/examples/{v2api/request_response.rb → request_response.rb} +1 -2
  19. data/examples/{v3api/sub.rb → sub.rb} +1 -2
  20. data/examples/{v3api/throughput_measurement.rb → throughput_measurement.rb} +1 -1
  21. data/examples/{v3api/xreqxrep_poll.rb → xreqxrep_poll.rb} +6 -7
  22. data/ffi-rzmq.gemspec +4 -4
  23. data/lib/ffi-rzmq.rb +2 -3
  24. data/lib/ffi-rzmq/context.rb +25 -53
  25. data/lib/ffi-rzmq/device.rb +8 -4
  26. data/lib/ffi-rzmq/exceptions.rb +3 -0
  27. data/lib/ffi-rzmq/message.rb +24 -30
  28. data/lib/ffi-rzmq/poll.rb +5 -16
  29. data/lib/ffi-rzmq/socket.rb +132 -282
  30. data/lib/ffi-rzmq/util.rb +28 -36
  31. data/lib/ffi-rzmq/version.rb +1 -1
  32. data/spec/context_spec.rb +18 -23
  33. data/spec/device_spec.rb +13 -12
  34. data/spec/message_spec.rb +13 -13
  35. data/spec/multipart_spec.rb +11 -11
  36. data/spec/nonblocking_recv_spec.rb +22 -22
  37. data/spec/poll_spec.rb +49 -49
  38. data/spec/pushpull_spec.rb +12 -11
  39. data/spec/reqrep_spec.rb +11 -11
  40. data/spec/socket_spec.rb +109 -196
  41. data/spec/spec_helper.rb +3 -11
  42. data/spec/util_spec.rb +29 -0
  43. metadata +80 -104
  44. data/examples/v2api/latency_measurement.rb +0 -139
  45. data/examples/v2api/local_lat.rb +0 -58
  46. data/examples/v2api/local_lat_poll.rb +0 -66
  47. data/examples/v2api/local_throughput.rb +0 -58
  48. data/examples/v2api/pub.rb +0 -46
  49. data/examples/v2api/remote_throughput.rb +0 -39
  50. data/examples/v2api/sub.rb +0 -74
  51. data/examples/v2api/throughput_measurement.rb +0 -138
  52. data/examples/v2api/xreqxrep_poll.rb +0 -93
  53. data/examples/v3api/publish_subscribe.rb +0 -82
  54. data/examples/v3api/remote_lat.rb +0 -71
  55. data/examples/v3api/reqrep_poll.rb +0 -62
  56. data/examples/v3api/request_response.rb +0 -40
  57. data/lib/ffi-rzmq/constants.rb +0 -187
  58. data/lib/ffi-rzmq/libc.rb +0 -19
  59. data/lib/ffi-rzmq/libzmq.rb +0 -283
@@ -1,66 +0,0 @@
1
-
2
- require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
3
-
4
- if ARGV.length < 3
5
- puts "usage: ruby local_lat.rb <connect-to> <message-size> <roundtrip-count>"
6
- exit
7
- end
8
-
9
- link = ARGV[0]
10
- message_size = ARGV[1].to_i
11
- roundtrip_count = ARGV[2].to_i
12
-
13
- def assert(rc)
14
- raise "Last API call failed at #{caller(1)}" unless rc >= 0
15
- end
16
-
17
- begin
18
- ctx = ZMQ::Context.new
19
- s1 = ctx.socket(ZMQ::REQ)
20
- s2 = ctx.socket(ZMQ::REP)
21
- rescue ContextError => e
22
- STDERR.puts "Failed to allocate context or socket!"
23
- raise
24
- end
25
-
26
- assert(s1.setsockopt(ZMQ::LINGER, 100))
27
- assert(s2.setsockopt(ZMQ::LINGER, 100))
28
-
29
- assert(s1.connect(link))
30
- assert(s2.bind(link))
31
-
32
- poller = ZMQ::Poller.new
33
- poller.register_readable(s2)
34
- poller.register_readable(s1)
35
-
36
-
37
- start_time = Time.now
38
-
39
- # kick it off
40
- message = ZMQ::Message.new("a" * message_size)
41
- assert(s1.sendmsg(message, ZMQ::NonBlocking))
42
-
43
- i = roundtrip_count
44
-
45
- until i.zero?
46
- i -= 1
47
-
48
- assert(poller.poll_nonblock)
49
-
50
- poller.readables.each do |socket|
51
- received_message = ''
52
- assert(socket.recv_string(received_message, ZMQ::NonBlocking))
53
- assert(socket.sendmsg(ZMQ::Message.new(received_message), ZMQ::NonBlocking))
54
- end
55
- end
56
-
57
- elapsed_usecs = (Time.now.to_f - start_time.to_f) * 1_000_000
58
- latency = elapsed_usecs / roundtrip_count / 2
59
-
60
- puts "mean latency: %.3f [us]" % latency
61
- puts "received all messages in %.3f seconds" % (elapsed_usecs / 1_000_000)
62
-
63
- assert(s1.close)
64
- assert(s2.close)
65
-
66
- ctx.terminate
@@ -1,58 +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
-
9
- def assert(rc)
10
- raise "Last API call failed at #{caller(1)}" unless rc >= 0
11
- end
12
-
13
- bind_to = ARGV[0]
14
- message_size = ARGV[1].to_i
15
- message_count = ARGV[2].to_i
16
-
17
- begin
18
- ctx = ZMQ::Context.new
19
- s = ZMQ::Socket.new(ctx.pointer, ZMQ::SUB)
20
- rescue ContextError => e
21
- STDERR.puts "Failed to allocate context or socket!"
22
- raise
23
- end
24
-
25
- assert(s.setsockopt(ZMQ::LINGER, 100))
26
- assert(s.setsockopt(ZMQ::SUBSCRIBE, ""))
27
-
28
- assert(s.bind(bind_to))
29
-
30
- msg = ZMQ::Message.new
31
- assert(s.recvmsg(msg))
32
-
33
- start_time = Time.now
34
-
35
- i = 1
36
- while i < message_count
37
- assert(s.recvmsg(msg))
38
- i += 1
39
- end
40
-
41
- end_time = Time.now
42
-
43
- elapsed = (end_time.to_f - start_time.to_f) * 1000000
44
- if elapsed == 0
45
- elapsed = 1
46
- end
47
-
48
- throughput = message_count * 1000000 / elapsed
49
- megabits = throughput * message_size * 8 / 1000000
50
-
51
- puts "message size: %i [B]" % message_size
52
- puts "message count: %i" % message_count
53
- puts "mean throughput: %i [msg/s]" % throughput
54
- puts "mean throughput: %.3f [Mb/s]" % megabits
55
-
56
- assert(s.close)
57
-
58
- ctx.terminate
@@ -1,46 +0,0 @@
1
-
2
- require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
3
-
4
- if ARGV.length != 3
5
- puts "usage: ruby remote_throughput.rb <connect-to> <message-size> <message-count>"
6
- Process.exit
7
- end
8
-
9
- connect_to = ARGV[0]
10
- message_size = ARGV[1].to_i
11
- message_count = ARGV[2].to_i
12
-
13
- def assert(rc)
14
- raise "Last API call failed at #{caller(1)}" unless rc >= 0
15
- end
16
-
17
- begin
18
- ctx = ZMQ::Context.new
19
- s = ZMQ::Socket.new(ctx.pointer, ZMQ::PUB)
20
- rescue ContextError => e
21
- STDERR.puts "Could not allocate a context or socket!"
22
- raise
23
- end
24
-
25
- #assert(s.setsockopt(ZMQ::LINGER, 1_000))
26
- #assert(s.setsockopt(ZMQ::RCVHWM, 0))
27
- assert(s.setsockopt(ZMQ::HWM, 10))
28
- assert(s.bind(connect_to))
29
-
30
- # the sleep gives the downstream SUB socket a chance to register its
31
- # subscription filters with this PUB socket
32
- puts "Hit any key to start publishing"
33
- STDIN.gets
34
-
35
- i = 0
36
- while i < message_count
37
- msg = ZMQ::Message.new(i.to_s)
38
- assert(s.sendmsg(msg))
39
- puts i
40
- i += 1
41
- end
42
-
43
- sleep 10
44
- assert(s.close)
45
-
46
- ctx.terminate
@@ -1,39 +0,0 @@
1
-
2
- require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
3
-
4
- if ARGV.length != 3
5
- puts "usage: ruby remote_throughput.rb <connect-to> <message-size> <message-count>"
6
- Process.exit
7
- end
8
-
9
- connect_to = ARGV[0]
10
- message_size = ARGV[1].to_i
11
- message_count = ARGV[2].to_i
12
-
13
- def assert(rc)
14
- raise "Last API call failed at #{caller(1)}" unless rc >= 0
15
- end
16
-
17
- begin
18
- ctx = ZMQ::Context.new
19
- s = ZMQ::Socket.new(ctx.pointer, ZMQ::PUB)
20
- rescue ContextError => e
21
- STDERR.puts "Could not allocate a context or socket!"
22
- raise
23
- end
24
-
25
- assert(s.setsockopt(ZMQ::LINGER, 1_000))
26
- assert(s.connect(connect_to))
27
-
28
- contents = "#{'0'*message_size}"
29
-
30
- i = 0
31
- while i < message_count
32
- msg = ZMQ::Message.new(contents)
33
- assert(s.sendmsg(msg))
34
- i += 1
35
- end
36
-
37
- assert(s.close)
38
-
39
- ctx.terminate
@@ -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