rbczmq 1.7.4 → 1.7.5
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.
- checksums.yaml +5 -13
- data/.travis.yml +4 -1
- data/CHANGELOG.rdoc +13 -0
- data/Gemfile +8 -1
- data/Gemfile.lock +211 -2
- data/README.rdoc +7 -4
- data/ext/rbczmq/beacon.c +6 -3
- data/ext/rbczmq/context.c +117 -8
- data/ext/rbczmq/context.h +5 -0
- data/ext/rbczmq/message.c +6 -4
- data/ext/rbczmq/poller.c +12 -5
- data/ext/rbczmq/rbczmq_ext.c +2 -0
- data/ext/rbczmq/rbczmq_ext.h +1 -0
- data/ext/rbczmq/socket.c +135 -59
- data/ext/rbczmq/socket.h +2 -0
- data/ext/zeromq/CMakeLists.txt +3 -1
- data/ext/zeromq/NEWS +28 -3
- data/ext/zeromq/doc/zmq.txt +3 -3
- data/ext/zeromq/doc/zmq_getsockopt.txt +3 -3
- data/ext/zeromq/doc/zmq_msg_get.txt +2 -1
- data/ext/zeromq/doc/zmq_msg_more.txt +1 -1
- data/ext/zeromq/doc/zmq_setsockopt.txt +18 -19
- data/ext/zeromq/doc/zmq_socket.txt +4 -0
- data/ext/zeromq/include/zmq.h +14 -18
- data/ext/zeromq/src/clock.cpp +57 -2
- data/ext/zeromq/src/ctx.cpp +11 -5
- data/ext/zeromq/src/devpoll.cpp +5 -0
- data/ext/zeromq/src/devpoll.hpp +2 -0
- data/ext/zeromq/src/epoll.cpp +5 -0
- data/ext/zeromq/src/epoll.hpp +2 -0
- data/ext/zeromq/src/i_engine.hpp +2 -2
- data/ext/zeromq/src/kqueue.cpp +5 -0
- data/ext/zeromq/src/kqueue.hpp +2 -0
- data/ext/zeromq/src/pgm_receiver.cpp +2 -2
- data/ext/zeromq/src/pgm_receiver.hpp +2 -2
- data/ext/zeromq/src/pgm_sender.cpp +2 -2
- data/ext/zeromq/src/pgm_sender.hpp +2 -2
- data/ext/zeromq/src/poll.cpp +5 -0
- data/ext/zeromq/src/poll.hpp +2 -0
- data/ext/zeromq/src/router.cpp +2 -0
- data/ext/zeromq/src/select.cpp +5 -0
- data/ext/zeromq/src/select.hpp +2 -0
- data/ext/zeromq/src/session_base.cpp +2 -2
- data/ext/zeromq/src/signaler.cpp +73 -99
- data/ext/zeromq/src/signaler.hpp +2 -2
- data/ext/zeromq/src/socket_base.cpp +42 -40
- data/ext/zeromq/src/stream_engine.cpp +60 -58
- data/ext/zeromq/src/stream_engine.hpp +7 -8
- data/ext/zeromq/src/zmq_utils.cpp +6 -5
- data/ext/zeromq/tests/Makefile.am +6 -5
- data/ext/zeromq/tests/test_conflate.cpp +2 -5
- data/ext/zeromq/tests/test_ctx_destroy.cpp +1 -1
- data/ext/zeromq/tests/test_ctx_options.cpp +1 -1
- data/ext/zeromq/tests/test_immediate.cpp +1 -2
- data/ext/zeromq/tests/test_inproc_connect.cpp +1 -1
- data/ext/zeromq/tests/test_iov.cpp +1 -1
- data/ext/zeromq/tests/test_many_sockets.cpp +90 -0
- data/ext/zeromq/tests/test_monitor.cpp +3 -3
- data/ext/zeromq/tests/test_req_relaxed.cpp +1 -1
- data/ext/zeromq/tests/test_router_raw_empty.cpp +65 -0
- data/ext/zeromq/tests/test_spec_req.cpp +1 -1
- data/ext/zeromq/tests/test_stream.cpp +6 -7
- data/ext/zeromq/tests/test_sub_forward.cpp +1 -1
- data/ext/zeromq/tests/test_term_endpoint.cpp +2 -2
- data/ext/zeromq/tests/testutil.hpp +18 -1
- data/ext/zeromq/tools/Makefile.am +1 -1
- data/lib/zmq/socket.rb +1 -0
- data/lib/zmq/socket/stream.rb +44 -0
- data/lib/zmq/version.rb +1 -1
- data/test/socket/test_dealer_socket.rb +1 -1
- data/test/socket/test_pair_socket.rb +1 -1
- data/test/socket/test_pair_sockets.rb +1 -1
- data/test/socket/test_pub_socket.rb +1 -1
- data/test/socket/test_pub_sub_sockets.rb +1 -1
- data/test/socket/test_pull_socket.rb +1 -1
- data/test/socket/test_push_pull_sockets.rb +1 -1
- data/test/socket/test_push_socket.rb +1 -1
- data/test/socket/test_rep_socket.rb +1 -1
- data/test/socket/test_req_rep_sockets.rb +1 -1
- data/test/socket/test_req_socket.rb +1 -1
- data/test/socket/test_router_socket.rb +1 -1
- data/test/socket/test_routing.rb +1 -1
- data/test/socket/test_stream_socket.rb +74 -0
- data/test/socket/test_sub_socket.rb +1 -1
- data/test/test_beacon.rb +4 -2
- data/test/test_context.rb +2 -2
- data/test/test_frame.rb +2 -2
- data/test/test_handler.rb +2 -2
- data/test/test_logger.rb +1 -1
- data/test/test_loop.rb +2 -2
- data/test/test_message.rb +1 -1
- data/test/test_monitoring.rb +15 -3
- data/test/test_poller.rb +2 -2
- data/test/test_pollitem.rb +2 -2
- data/test/test_socket.rb +53 -6
- data/test/test_threading.rb +2 -2
- data/test/test_timer.rb +2 -2
- data/test/test_zmq.rb +2 -2
- metadata +109 -104
data/ext/rbczmq/context.h
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
#ifndef RBCZMQ_CONTEXT_H
|
2
2
|
#define RBCZMQ_CONTEXT_H
|
3
3
|
|
4
|
+
#include "socket.h"
|
5
|
+
|
4
6
|
#define ZMQ_CONTEXT_DESTROYED 0x01
|
5
7
|
|
6
8
|
typedef struct {
|
@@ -8,6 +10,7 @@ typedef struct {
|
|
8
10
|
int flags;
|
9
11
|
pid_t pid; /* this is the pid for the process that created the context. Only this process can use the context. */
|
10
12
|
VALUE pidValue; /* this is the key used to ensure one context per process */
|
13
|
+
zlist_t* sockets; /* list of socket wrapper objects owned by this context. */
|
11
14
|
} zmq_ctx_wrapper;
|
12
15
|
|
13
16
|
#define ZmqAssertContext(obj) ZmqAssertType(obj, rb_cZmqContext, "ZMQ::Context")
|
@@ -32,4 +35,6 @@ VALUE rb_czmq_socket_alloc(VALUE context, zctx_t *ctx, void *s);
|
|
32
35
|
|
33
36
|
void _init_rb_czmq_context();
|
34
37
|
|
38
|
+
void rb_czmq_context_destroy_socket(zmq_sock_wrapper* socket);
|
39
|
+
|
35
40
|
#endif
|
data/ext/rbczmq/message.c
CHANGED
@@ -377,7 +377,7 @@ static VALUE rb_czmq_message_pushstr(VALUE obj, VALUE str)
|
|
377
377
|
ZmqGetMessage(obj);
|
378
378
|
ZmqAssertMessageOwned(message);
|
379
379
|
Check_Type(str, T_STRING);
|
380
|
-
rc = zmsg_pushmem(message->message,
|
380
|
+
rc = zmsg_pushmem(message->message, RSTRING_PTR(str), RSTRING_LEN(str));
|
381
381
|
ZmqAssert(rc);
|
382
382
|
|
383
383
|
/* keep zlist of frame ruby objects in sync with message's frame list */
|
@@ -410,7 +410,7 @@ static VALUE rb_czmq_message_addstr(VALUE obj, VALUE str)
|
|
410
410
|
ZmqGetMessage(obj);
|
411
411
|
ZmqAssertMessageOwned(message);
|
412
412
|
Check_Type(str, T_STRING);
|
413
|
-
rc = zmsg_addmem(message->message,
|
413
|
+
rc = zmsg_addmem(message->message, RSTRING_PTR(str), RSTRING_LEN(str));
|
414
414
|
ZmqAssert(rc);
|
415
415
|
|
416
416
|
/* keep zlist of frame ruby objects in sync with message's frame list */
|
@@ -603,7 +603,9 @@ static VALUE rb_czmq_message_encode(VALUE obj)
|
|
603
603
|
ZmqGetMessage(obj);
|
604
604
|
ZmqReturnNilUnlessOwned(message);
|
605
605
|
buff_size = zmsg_encode(message->message, &buff);
|
606
|
-
|
606
|
+
VALUE result = rb_str_new((char *)buff, buff_size);
|
607
|
+
free(buff);
|
608
|
+
return result;
|
607
609
|
}
|
608
610
|
|
609
611
|
/*
|
@@ -623,7 +625,7 @@ static VALUE rb_czmq_message_s_decode(ZMQ_UNUSED VALUE obj, VALUE buffer)
|
|
623
625
|
{
|
624
626
|
zmsg_t * m = NULL;
|
625
627
|
Check_Type(buffer, T_STRING);
|
626
|
-
m = zmsg_decode((byte *)
|
628
|
+
m = zmsg_decode((byte *)RSTRING_PTR(buffer), RSTRING_LEN(buffer));
|
627
629
|
if (m == NULL) return Qnil;
|
628
630
|
return rb_czmq_alloc_message(m);
|
629
631
|
}
|
data/ext/rbczmq/poller.c
CHANGED
@@ -154,15 +154,22 @@ VALUE rb_czmq_poller_poll(int argc, VALUE *argv, VALUE obj)
|
|
154
154
|
args.nitems = poller->poll_size;
|
155
155
|
args.timeout = (long)timeout;
|
156
156
|
|
157
|
+
rb_ary_clear(poller->readables);
|
158
|
+
rb_ary_clear(poller->writables);
|
159
|
+
|
157
160
|
rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_poll, (void *)&args, RUBY_UBF_IO, 0);
|
161
|
+
|
158
162
|
/* only call ZmqAssert if return code is less than zero since zmq_poll returns the number of pollers on success */
|
159
163
|
if (rc < 0) {
|
160
|
-
|
164
|
+
if (zmq_errno() == EINTR || zmq_errno() == EAGAIN) {
|
165
|
+
// these are recoverable errors, so return flow to ruby so that retry / interrupt handling can be
|
166
|
+
// done in ruby code. Ruby will see a -1 result. If it was an INT (or other) signal, ruby's signal
|
167
|
+
// handler will raise the Interrupt exception.
|
168
|
+
} else {
|
169
|
+
ZmqAssert(rc);
|
170
|
+
}
|
161
171
|
}
|
162
|
-
if (rc
|
163
|
-
rb_ary_clear(poller->readables);
|
164
|
-
rb_ary_clear(poller->writables);
|
165
|
-
} else {
|
172
|
+
if (rc > 0) {
|
166
173
|
rb_czmq_poller_rebuild_selectables(poller);
|
167
174
|
}
|
168
175
|
return INT2NUM(rc);
|
data/ext/rbczmq/rbczmq_ext.c
CHANGED
@@ -16,6 +16,7 @@ VALUE rb_cZmqReqSocket;
|
|
16
16
|
VALUE rb_cZmqPairSocket;
|
17
17
|
VALUE rb_cZmqXPubSocket;
|
18
18
|
VALUE rb_cZmqXSubSocket;
|
19
|
+
VALUE rb_cZmqStreamSocket;
|
19
20
|
|
20
21
|
VALUE rb_cZmqFrame;
|
21
22
|
VALUE rb_cZmqMessage;
|
@@ -249,6 +250,7 @@ void Init_rbczmq_ext()
|
|
249
250
|
rb_define_const(rb_mZmq, "PULL", INT2NUM(ZMQ_PULL));
|
250
251
|
rb_define_const(rb_mZmq, "XSUB", INT2NUM(ZMQ_XSUB));
|
251
252
|
rb_define_const(rb_mZmq, "XPUB", INT2NUM(ZMQ_XPUB));
|
253
|
+
rb_define_const(rb_mZmq, "STREAM", INT2NUM(ZMQ_STREAM));
|
252
254
|
|
253
255
|
rb_define_const(rb_mZmq, "EFSM", INT2NUM(EFSM));
|
254
256
|
rb_define_const(rb_mZmq, "ENOCOMPATPROTO", INT2NUM(ENOCOMPATPROTO));
|
data/ext/rbczmq/rbczmq_ext.h
CHANGED
data/ext/rbczmq/socket.c
CHANGED
@@ -11,36 +11,6 @@ VALUE intern_on_closed;
|
|
11
11
|
VALUE intern_on_close_failed;
|
12
12
|
VALUE intern_on_disconnected;
|
13
13
|
|
14
|
-
/*
|
15
|
-
* :nodoc:
|
16
|
-
* Destroy the socket while the GIL is released - may block depending on socket linger value.
|
17
|
-
*
|
18
|
-
*/
|
19
|
-
static VALUE rb_czmq_nogvl_zsocket_destroy(void *ptr)
|
20
|
-
{
|
21
|
-
zmq_sock_wrapper *sock = ptr;
|
22
|
-
errno = 0;
|
23
|
-
sock->flags |= ZMQ_SOCKET_DESTROYED;
|
24
|
-
zsocket_destroy(sock->ctx, sock->socket);
|
25
|
-
return Qnil;
|
26
|
-
}
|
27
|
-
|
28
|
-
/*
|
29
|
-
* :nodoc:
|
30
|
-
* Free all resources for a socket - invoked by the lower level ZMQ::Socket#destroy as well as the GC callback (some
|
31
|
-
* regressions here still though).
|
32
|
-
*
|
33
|
-
*/
|
34
|
-
void rb_czmq_free_sock(zmq_sock_wrapper *sock)
|
35
|
-
{
|
36
|
-
if (sock->ctx) {
|
37
|
-
rb_thread_blocking_region(rb_czmq_nogvl_zsocket_destroy, sock, RUBY_UBF_IO, 0);
|
38
|
-
if (zmq_errno() == ENOTSOCK) ZmqRaiseSysError();
|
39
|
-
sock->socket = NULL;
|
40
|
-
sock->flags |= ZMQ_SOCKET_DESTROYED;
|
41
|
-
}
|
42
|
-
}
|
43
|
-
|
44
14
|
/*
|
45
15
|
* :nodoc:
|
46
16
|
* GC mark callback
|
@@ -50,8 +20,9 @@ void rb_czmq_mark_sock(void *ptr)
|
|
50
20
|
{
|
51
21
|
zmq_sock_wrapper *sock = (zmq_sock_wrapper *)ptr;
|
52
22
|
if (sock && sock->ctx){
|
53
|
-
if (sock->verbose)
|
54
|
-
zclock_log ("I: %s socket %p, context %p: GC mark", zsocket_type_str(sock->socket), sock, sock->ctx);
|
23
|
+
if (sock->verbose) {
|
24
|
+
zclock_log ("I: %s socket %p, context %p: GC mark", sock->flags & ZMQ_SOCKET_DESTROYED ? "(closed)" : zsocket_type_str(sock->socket), sock, sock->ctx);
|
25
|
+
}
|
55
26
|
rb_gc_mark(sock->endpoints);
|
56
27
|
rb_gc_mark(sock->thread);
|
57
28
|
rb_gc_mark(sock->context);
|
@@ -69,14 +40,27 @@ void rb_czmq_mark_sock(void *ptr)
|
|
69
40
|
void rb_czmq_free_sock_gc(void *ptr)
|
70
41
|
{
|
71
42
|
zmq_sock_wrapper *sock = (zmq_sock_wrapper *)ptr;
|
72
|
-
if (sock
|
73
|
-
if (sock->verbose)
|
74
|
-
zclock_log ("I: %s socket %p, context %p: GC free", zsocket_type_str(sock->socket), sock, sock->ctx);
|
43
|
+
if (sock) {
|
44
|
+
if (sock->verbose) {
|
45
|
+
zclock_log ("I: %s socket %p, context %p: GC free", sock->flags & ZMQ_SOCKET_DESTROYED ? "(closed)" : zsocket_type_str(sock->socket), sock, sock ? sock->ctx : NULL);
|
46
|
+
}
|
75
47
|
/*
|
76
48
|
XXX: cyclic dependency
|
77
49
|
#4 0x0000000100712524 in zsocket_set_linger (linger=1, socket=<value temporarily unavailable, due to optimizations>) at zsocket.c:288
|
78
50
|
if (sock->socket != NULL && !(sock->flags & ZMQ_SOCKET_DESTROYED)) rb_czmq_free_sock(sock);
|
51
|
+
|
52
|
+
SOLVED:
|
53
|
+
|
54
|
+
The above occurs when a socket is not explicitly destroyed and the socket happens to be garbage
|
55
|
+
collected *after* the context has been destroyed. When the context is destroyed, all sockets
|
56
|
+
in the context are closed internally by czmq. However, the rbczmq ZMQ::Socket object still
|
57
|
+
thinks it is alive and will destroy again.
|
58
|
+
|
59
|
+
The new socket destroy method 'rb_czmq_context_destroy_socket' is idempotent and can safely
|
60
|
+
be called after either context or socket has been destroyed.
|
79
61
|
*/
|
62
|
+
|
63
|
+
rb_czmq_context_destroy_socket(sock);
|
80
64
|
xfree(sock);
|
81
65
|
}
|
82
66
|
}
|
@@ -100,8 +84,8 @@ static VALUE rb_czmq_socket_close(VALUE obj)
|
|
100
84
|
ZmqSockGuardCrossThread(sock);
|
101
85
|
/* This is useless for production / real use cases as we can't query the state again OR assume
|
102
86
|
anything about the underlying connection. Merely doing the right thing. */
|
103
|
-
sock->state =
|
104
|
-
|
87
|
+
sock->state = ZMQ_SOCKET_DISCONNECTED;
|
88
|
+
rb_czmq_context_destroy_socket(sock);
|
105
89
|
return Qnil;
|
106
90
|
}
|
107
91
|
|
@@ -184,7 +168,7 @@ VALUE rb_czmq_nogvl_socket_bind(void *ptr)
|
|
184
168
|
struct nogvl_conn_args *args = ptr;
|
185
169
|
errno = 0;
|
186
170
|
zmq_sock_wrapper *socket = args->socket;
|
187
|
-
rc = zsocket_bind(socket->socket, args->endpoint);
|
171
|
+
rc = zsocket_bind(socket->socket, "%s", args->endpoint);
|
188
172
|
return (VALUE)rc;
|
189
173
|
}
|
190
174
|
|
@@ -199,7 +183,7 @@ VALUE rb_czmq_nogvl_socket_connect(void *ptr)
|
|
199
183
|
struct nogvl_conn_args *args = ptr;
|
200
184
|
errno = 0;
|
201
185
|
zmq_sock_wrapper *socket = args->socket;
|
202
|
-
rc = zsocket_connect(socket->socket, args->endpoint);
|
186
|
+
rc = zsocket_connect(socket->socket, "%s", args->endpoint);
|
203
187
|
return (VALUE)rc;
|
204
188
|
}
|
205
189
|
|
@@ -232,10 +216,14 @@ static VALUE rb_czmq_socket_bind(VALUE obj, VALUE endpoint)
|
|
232
216
|
if (rc < 0) {
|
233
217
|
ZmqAssert(rc);
|
234
218
|
}
|
219
|
+
/* get the endpoint name with any ephemeral ports filled in. */
|
220
|
+
char* endpoint_string = zsocket_last_endpoint(sock->socket);
|
221
|
+
ZmqAssert(endpoint_string != NULL);
|
235
222
|
if (sock->verbose)
|
236
|
-
zclock_log ("I: %s socket %p: bound \"%s\"", zsocket_type_str(sock->socket), obj,
|
223
|
+
zclock_log ("I: %s socket %p: bound \"%s\"", zsocket_type_str(sock->socket), obj, endpoint_string);
|
237
224
|
sock->state = ZMQ_SOCKET_BOUND;
|
238
|
-
rb_ary_push(sock->endpoints,
|
225
|
+
rb_ary_push(sock->endpoints, rb_str_new_cstr(endpoint_string));
|
226
|
+
free(endpoint_string);
|
239
227
|
return INT2NUM(rc);
|
240
228
|
}
|
241
229
|
|
@@ -266,10 +254,14 @@ static VALUE rb_czmq_socket_connect(VALUE obj, VALUE endpoint)
|
|
266
254
|
args.endpoint = StringValueCStr(endpoint);
|
267
255
|
rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_socket_connect, (void *)&args, RUBY_UBF_IO, 0);
|
268
256
|
ZmqAssert(rc);
|
257
|
+
/* get the endpoint name with any ephemeral ports filled in. */
|
258
|
+
char* endpoint_string = zsocket_last_endpoint(sock->socket);
|
259
|
+
ZmqAssert(endpoint_string != NULL);
|
269
260
|
if (sock->verbose)
|
270
|
-
zclock_log ("I: %s socket %p: connected \"%s\"", zsocket_type_str(sock->socket), obj,
|
261
|
+
zclock_log ("I: %s socket %p: connected \"%s\"", zsocket_type_str(sock->socket), obj, endpoint_string);
|
271
262
|
sock->state = ZMQ_SOCKET_CONNECTED;
|
272
|
-
rb_ary_push(sock->endpoints,
|
263
|
+
rb_ary_push(sock->endpoints, rb_str_new_cstr(endpoint_string));
|
264
|
+
free(endpoint_string);
|
273
265
|
return Qtrue;
|
274
266
|
}
|
275
267
|
|
@@ -284,7 +276,7 @@ VALUE rb_czmq_nogvl_socket_disconnect(void *ptr)
|
|
284
276
|
struct nogvl_conn_args *args = ptr;
|
285
277
|
errno = 0;
|
286
278
|
zmq_sock_wrapper *socket = args->socket;
|
287
|
-
rc = zsocket_disconnect(socket->socket, args->endpoint);
|
279
|
+
rc = zsocket_disconnect(socket->socket, "%s", args->endpoint);
|
288
280
|
return (VALUE)rc;
|
289
281
|
}
|
290
282
|
|
@@ -318,11 +310,69 @@ static VALUE rb_czmq_socket_disconnect(VALUE obj, VALUE endpoint)
|
|
318
310
|
ZmqAssert(rc);
|
319
311
|
if (sock->verbose)
|
320
312
|
zclock_log ("I: %s socket %p: disconnected \"%s\"", zsocket_type_str(sock->socket), obj, StringValueCStr(endpoint));
|
321
|
-
sock->state = ZMQ_SOCKET_DISCONNECTED;
|
322
313
|
rb_ary_delete(sock->endpoints, endpoint);
|
314
|
+
long endpoint_count = RARRAY_LEN(sock->endpoints);
|
315
|
+
if (endpoint_count == 0) {
|
316
|
+
sock->state = ZMQ_SOCKET_DISCONNECTED;
|
317
|
+
}
|
318
|
+
return Qtrue;
|
319
|
+
}
|
320
|
+
|
321
|
+
/*
|
322
|
+
* :nodoc:
|
323
|
+
* Unbinds from an endpoint while the GIL is released.
|
324
|
+
*
|
325
|
+
*/
|
326
|
+
VALUE rb_czmq_nogvl_socket_unbind(void *ptr)
|
327
|
+
{
|
328
|
+
int rc;
|
329
|
+
struct nogvl_conn_args *args = ptr;
|
330
|
+
errno = 0;
|
331
|
+
zmq_sock_wrapper *socket = args->socket;
|
332
|
+
rc = zsocket_unbind(socket->socket, "%s", args->endpoint);
|
333
|
+
return (VALUE)rc;
|
334
|
+
}
|
335
|
+
|
336
|
+
|
337
|
+
/*
|
338
|
+
* call-seq:
|
339
|
+
* sock.disconnect("tcp://localhost:3456") => boolean
|
340
|
+
*
|
341
|
+
* Attempts to disconnect from a given endpoint.
|
342
|
+
*
|
343
|
+
* === Examples
|
344
|
+
* ctx = ZMQ::Context.new
|
345
|
+
* rep = ctx.socket(:REP)
|
346
|
+
* port = rep.bind("tcp://localhost:*") => 5432
|
347
|
+
* req = ctx.socket(:REQ)
|
348
|
+
* req.connect("tcp://localhost:#{port}") => true
|
349
|
+
* rep.unbind("tcp://localhost:#{port}") => true
|
350
|
+
*
|
351
|
+
*/
|
352
|
+
|
353
|
+
static VALUE rb_czmq_socket_unbind(VALUE obj, VALUE endpoint)
|
354
|
+
{
|
355
|
+
struct nogvl_conn_args args;
|
356
|
+
int rc;
|
357
|
+
zmq_sock_wrapper *sock = NULL;
|
358
|
+
GetZmqSocket(obj);
|
359
|
+
ZmqSockGuardCrossThread(sock);
|
360
|
+
Check_Type(endpoint, T_STRING);
|
361
|
+
args.socket = sock;
|
362
|
+
args.endpoint = StringValueCStr(endpoint);
|
363
|
+
rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_socket_unbind, (void *)&args, RUBY_UBF_IO, 0);
|
364
|
+
ZmqAssert(rc);
|
365
|
+
if (sock->verbose)
|
366
|
+
zclock_log ("I: %s socket %p: unbound \"%s\"", zsocket_type_str(sock->socket), obj, StringValueCStr(endpoint));
|
367
|
+
rb_ary_delete(sock->endpoints, endpoint);
|
368
|
+
long endpoint_count = RARRAY_LEN(sock->endpoints);
|
369
|
+
if (endpoint_count == 0) {
|
370
|
+
sock->state = ZMQ_SOCKET_DISCONNECTED;
|
371
|
+
}
|
323
372
|
return Qtrue;
|
324
373
|
}
|
325
374
|
|
375
|
+
|
326
376
|
/*
|
327
377
|
* call-seq:
|
328
378
|
* sock.verbose = true => nil
|
@@ -537,7 +587,6 @@ static VALUE rb_czmq_socket_recv(VALUE obj)
|
|
537
587
|
|
538
588
|
static VALUE rb_czmq_socket_recv_nonblock(VALUE obj)
|
539
589
|
{
|
540
|
-
char *str = NULL;
|
541
590
|
struct nogvl_recv_args args;
|
542
591
|
errno = 0;
|
543
592
|
VALUE result = Qnil;
|
@@ -554,12 +603,14 @@ static VALUE rb_czmq_socket_recv_nonblock(VALUE obj)
|
|
554
603
|
return Qnil;
|
555
604
|
}
|
556
605
|
ZmqAssertSysError();
|
557
|
-
if (sock->verbose)
|
558
|
-
zclock_log ("I: %s socket %p: recv \"%s\"", zsocket_type_str(sock->socket), sock->socket, str);
|
559
606
|
|
560
607
|
result = rb_str_new(zmq_msg_data(&args.message), zmq_msg_size(&args.message));
|
561
608
|
zmq_msg_close(&args.message);
|
562
609
|
|
610
|
+
if (sock->verbose) {
|
611
|
+
zclock_log ("I: %s socket %p: recv \"%s\"", zsocket_type_str(sock->socket), sock->socket, StringValueCStr(result));
|
612
|
+
}
|
613
|
+
|
563
614
|
result = ZmqEncode(result);
|
564
615
|
return result;
|
565
616
|
}
|
@@ -1664,6 +1715,28 @@ static VALUE rb_czmq_socket_set_opt_sndtimeo(VALUE obj, VALUE value)
|
|
1664
1715
|
ZmqSetSockOpt(obj, zsocket_set_sndtimeo, "SNDTIMEO", value);
|
1665
1716
|
}
|
1666
1717
|
|
1718
|
+
|
1719
|
+
/*
|
1720
|
+
* call-seq:
|
1721
|
+
* port = sock.bind('tcp://0.0.0.0:*') => 41415
|
1722
|
+
* sock.last_endpoint => "tcp://0.0.0.0:41415"
|
1723
|
+
*
|
1724
|
+
* Gets the last endpoint that this socket connected or bound to.
|
1725
|
+
*
|
1726
|
+
*/
|
1727
|
+
|
1728
|
+
static VALUE rb_czmq_socket_opt_last_endpoint(VALUE obj)
|
1729
|
+
{
|
1730
|
+
zmq_sock_wrapper *sock = NULL;
|
1731
|
+
GetZmqSocket(obj);
|
1732
|
+
char* endpoint_string = zsocket_last_endpoint(sock->socket);
|
1733
|
+
VALUE result = rb_str_new_cstr(endpoint_string);
|
1734
|
+
if (endpoint_string != NULL) {
|
1735
|
+
free(endpoint_string);
|
1736
|
+
}
|
1737
|
+
return result;
|
1738
|
+
}
|
1739
|
+
|
1667
1740
|
/*
|
1668
1741
|
* :nodoc:
|
1669
1742
|
* Receives a monitoring event message while the GIL is released.
|
@@ -1725,7 +1798,7 @@ static VALUE rb_czmq_socket_monitor_thread(void *arg)
|
|
1725
1798
|
// copy endpoint into ruby string.
|
1726
1799
|
VALUE endpoint_str = rb_str_new(zmq_msg_data(&args.msg_endpoint), zmq_msg_size(&args.msg_endpoint));
|
1727
1800
|
VALUE method = Qnil;
|
1728
|
-
|
1801
|
+
|
1729
1802
|
switch (event.event) {
|
1730
1803
|
case ZMQ_EVENT_CONNECTED: method = intern_on_connected; break;
|
1731
1804
|
case ZMQ_EVENT_CONNECT_DELAYED: method = intern_on_connect_delayed; break;
|
@@ -1738,7 +1811,7 @@ static VALUE rb_czmq_socket_monitor_thread(void *arg)
|
|
1738
1811
|
case ZMQ_EVENT_CLOSED: method = intern_on_closed; break;
|
1739
1812
|
case ZMQ_EVENT_DISCONNECTED: method = intern_on_disconnected; break;
|
1740
1813
|
}
|
1741
|
-
|
1814
|
+
|
1742
1815
|
if (method != Qnil) {
|
1743
1816
|
rb_funcall(sock->monitor_handler, method, 2, endpoint_str, INT2FIX(event.value));
|
1744
1817
|
}
|
@@ -1809,16 +1882,17 @@ void _init_rb_czmq_socket()
|
|
1809
1882
|
{
|
1810
1883
|
rb_cZmqSocket = rb_define_class_under(rb_mZmq, "Socket", rb_cObject);
|
1811
1884
|
rb_cZmqPubSocket = rb_define_class_under(rb_cZmqSocket, "Pub", rb_cZmqSocket);
|
1812
|
-
rb_cZmqSubSocket = rb_define_class_under(rb_cZmqSocket, "Sub", rb_cZmqSocket)
|
1813
|
-
rb_cZmqPushSocket = rb_define_class_under(rb_cZmqSocket, "Push", rb_cZmqSocket)
|
1814
|
-
rb_cZmqPullSocket = rb_define_class_under(rb_cZmqSocket, "Pull", rb_cZmqSocket)
|
1815
|
-
rb_cZmqRouterSocket = rb_define_class_under(rb_cZmqSocket, "Router", rb_cZmqSocket)
|
1816
|
-
rb_cZmqDealerSocket = rb_define_class_under(rb_cZmqSocket, "Dealer", rb_cZmqSocket)
|
1817
|
-
rb_cZmqRepSocket = rb_define_class_under(rb_cZmqSocket, "Rep", rb_cZmqSocket)
|
1818
|
-
rb_cZmqReqSocket = rb_define_class_under(rb_cZmqSocket, "Req", rb_cZmqSocket)
|
1819
|
-
rb_cZmqPairSocket = rb_define_class_under(rb_cZmqSocket, "Pair", rb_cZmqSocket)
|
1885
|
+
rb_cZmqSubSocket = rb_define_class_under(rb_cZmqSocket, "Sub", rb_cZmqSocket);
|
1886
|
+
rb_cZmqPushSocket = rb_define_class_under(rb_cZmqSocket, "Push", rb_cZmqSocket);
|
1887
|
+
rb_cZmqPullSocket = rb_define_class_under(rb_cZmqSocket, "Pull", rb_cZmqSocket);
|
1888
|
+
rb_cZmqRouterSocket = rb_define_class_under(rb_cZmqSocket, "Router", rb_cZmqSocket);
|
1889
|
+
rb_cZmqDealerSocket = rb_define_class_under(rb_cZmqSocket, "Dealer", rb_cZmqSocket);
|
1890
|
+
rb_cZmqRepSocket = rb_define_class_under(rb_cZmqSocket, "Rep", rb_cZmqSocket);
|
1891
|
+
rb_cZmqReqSocket = rb_define_class_under(rb_cZmqSocket, "Req", rb_cZmqSocket);
|
1892
|
+
rb_cZmqPairSocket = rb_define_class_under(rb_cZmqSocket, "Pair", rb_cZmqSocket);
|
1820
1893
|
rb_cZmqXPubSocket = rb_define_class_under(rb_cZmqSocket, "XPub", rb_cZmqSocket);
|
1821
|
-
rb_cZmqXSubSocket = rb_define_class_under(rb_cZmqSocket, "XSub", rb_cZmqSocket)
|
1894
|
+
rb_cZmqXSubSocket = rb_define_class_under(rb_cZmqSocket, "XSub", rb_cZmqSocket);
|
1895
|
+
rb_cZmqStreamSocket = rb_define_class_under(rb_cZmqSocket, "Stream", rb_cZmqSocket);
|
1822
1896
|
|
1823
1897
|
intern_on_connected = rb_intern("on_connected");
|
1824
1898
|
intern_on_connect_delayed = rb_intern("on_connect_delayed");
|
@@ -1842,6 +1916,7 @@ void _init_rb_czmq_socket()
|
|
1842
1916
|
rb_define_method(rb_cZmqSocket, "real_bind", rb_czmq_socket_bind, 1);
|
1843
1917
|
rb_define_method(rb_cZmqSocket, "real_connect", rb_czmq_socket_connect, 1);
|
1844
1918
|
rb_define_method(rb_cZmqSocket, "disconnect", rb_czmq_socket_disconnect, 1);
|
1919
|
+
rb_define_method(rb_cZmqSocket, "unbind", rb_czmq_socket_unbind, 1);
|
1845
1920
|
rb_define_method(rb_cZmqSocket, "fd", rb_czmq_socket_fd, 0);
|
1846
1921
|
rb_define_alias(rb_cZmqSocket, "to_i", "fd");
|
1847
1922
|
rb_define_method(rb_cZmqSocket, "verbose=", rb_czmq_socket_set_verbose, 1);
|
@@ -1898,4 +1973,5 @@ void _init_rb_czmq_socket()
|
|
1898
1973
|
rb_define_method(rb_cZmqSocket, "sndtimeo", rb_czmq_socket_opt_sndtimeo, 0);
|
1899
1974
|
rb_define_method(rb_cZmqSocket, "sndtimeo=", rb_czmq_socket_set_opt_sndtimeo, 1);
|
1900
1975
|
rb_define_method(rb_cZmqSocket, "monitor", rb_czmq_socket_monitor, -1);
|
1976
|
+
rb_define_method(rb_cZmqSocket, "last_endpoint", rb_czmq_socket_opt_last_endpoint, 0);
|
1901
1977
|
}
|
data/ext/rbczmq/socket.h
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
typedef struct {
|
14
14
|
zctx_t *ctx;
|
15
15
|
void *socket;
|
16
|
+
void *ctx_wrapper; // zmq_ctx_wrapper - can't be defined yet, circular header includes.
|
16
17
|
int flags;
|
17
18
|
bool verbose;
|
18
19
|
int state;
|
@@ -153,5 +154,6 @@ extern VALUE intern_on_close_failed;
|
|
153
154
|
extern VALUE intern_on_disconnected;
|
154
155
|
|
155
156
|
void _init_rb_czmq_socket();
|
157
|
+
VALUE rb_czmq_nogvl_zsocket_destroy(void *ptr);
|
156
158
|
|
157
159
|
#endif
|