rbczmq 1.6.4 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/CHANGELOG.rdoc +7 -0
- data/Gemfile.lock +1 -1
- data/ext/rbczmq/beacon.c +1 -1
- data/ext/rbczmq/beacon.h +1 -1
- data/ext/rbczmq/frame.c +63 -50
- data/ext/rbczmq/frame.h +41 -9
- data/ext/rbczmq/message.c +186 -56
- data/ext/rbczmq/message.h +18 -2
- data/ext/rbczmq/pollitem.c +1 -1
- data/ext/rbczmq/rbczmq_ext.c +0 -4
- data/ext/rbczmq/rbczmq_ext.h +0 -2
- data/ext/rbczmq/socket.c +11 -5
- data/lib/zmq.rb +2 -1
- data/lib/zmq/logger.rb +58 -0
- data/lib/zmq/version.rb +2 -2
- data/test/test_frame.rb +2 -3
- data/test/test_logger.rb +41 -0
- data/test/test_message.rb +98 -5
- metadata +8 -10
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NTIyYzk0ZmFkOTc4Y2YwMmRlYzc3ZGE0NmQyZTBhOGRlODQyMDcxMA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NTI4NzQyMDhkNGRjNGE5NDgxMDE3ZDg5MjU2YTViZWZiMWNjYzQxZA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZmQ5NzExNWFhM2ZiODBlZmY4ZDZkMmM5YjBjMDQxODNkZDFlNTUxZmZlMjIz
|
10
|
+
N2JkZGU0Mjg4NzJlZTM2ZTEzYjI5ZDdkMGExNDU5MGMzMDE1ZjM2OTUxOTk4
|
11
|
+
ZDAyYjcwNTcyOGUzYjNhOTFkYzYyZTM5NTBkNjgyNDgyN2Q0ZDg=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NDJmOGNmNmMwNGM3YjY5NmUwYTZmOTYzNzAyNGU5YzFmMTc0NGRhYTUzYjIw
|
14
|
+
YzI0YjJiODBlMjliMGQyYThjNjFhMWE1MWExZTJhNjAzNTMyNjQzZTM2YWZk
|
15
|
+
M2NiYzc5Mzc0NGE0NjlkMmQ1YzBmYTMyYjdiZjkxNmFkMGE5ZTI=
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
= Changelog
|
2
2
|
|
3
|
+
== 1.7.0 (July 21, 2013)
|
4
|
+
|
5
|
+
* ZMQ::Frame - Implemented an interal wrapper around the underlying czmq frame objects to better manage memory and object ownership. (Matt Connolly)
|
6
|
+
* ZMQ::Frame#gone? and ZMQ::Message#gone? - new methods, return true when the frame/message has been sent and is no longer available for accessing. Methods may return nil for read operations or raise ZMQ::Error if the frame/message would be changed by that method. (Matt Connolly)
|
7
|
+
* ZMQ::Message - iterators (#first, #next, #last and #to_a) return consistent frame objects (not duplicates as in previous versions) that can be used with #remove. (Matt Connolly)
|
8
|
+
* Sending a message or frame marks it as "gone". The underlying data objects will be released by ZeroMQ as the frames/messages are sent over the socket. (Matt Connolly)
|
9
|
+
|
3
10
|
== 1.6.4 (July 10, 2013)
|
4
11
|
* Depend on a checkout task for vendored submodule init (Matt Connolly)
|
5
12
|
|
data/Gemfile.lock
CHANGED
data/ext/rbczmq/beacon.c
CHANGED
@@ -315,4 +315,4 @@ void _init_rb_czmq_beacon()
|
|
315
315
|
rb_define_method(rb_cZmqBeacon, "subscribe", rb_czmq_beacon_subscribe, 1);
|
316
316
|
rb_define_method(rb_cZmqBeacon, "unsubscribe", rb_czmq_beacon_unsubscribe, 0);
|
317
317
|
rb_define_method(rb_cZmqBeacon, "pipe", rb_czmq_beacon_pipe, 0);
|
318
|
-
}
|
318
|
+
}
|
data/ext/rbczmq/beacon.h
CHANGED
data/ext/rbczmq/frame.c
CHANGED
@@ -1,18 +1,6 @@
|
|
1
1
|
#include "rbczmq_ext.h"
|
2
2
|
static VALUE intern_data;
|
3
3
|
|
4
|
-
/*
|
5
|
-
* :nodoc:
|
6
|
-
* Callback invoked by zframe_destroy in libczmq. We track all frames coerced to native objects in a symbol table
|
7
|
-
* to guard against a mismatch between allocated frames and the Ruby object space as zframe_destroy is invoked
|
8
|
-
* throughout libczmq (zmsg.c) where the Ruby GC can't easily track it. Ruby MRI Object finalizers are a real
|
9
|
-
* pita to deal with.
|
10
|
-
*
|
11
|
-
*/
|
12
|
-
void rb_czmq_frame_freed(zframe_t *frame)
|
13
|
-
{
|
14
|
-
st_delete(frames_map, (st_data_t*)&frame, 0);
|
15
|
-
}
|
16
4
|
|
17
5
|
/*
|
18
6
|
* :nodoc:
|
@@ -22,8 +10,11 @@ void rb_czmq_frame_freed(zframe_t *frame)
|
|
22
10
|
VALUE rb_czmq_alloc_frame(zframe_t *frame)
|
23
11
|
{
|
24
12
|
VALUE frame_obj;
|
25
|
-
|
26
|
-
frame_obj =
|
13
|
+
zmq_frame_wrapper* f;
|
14
|
+
frame_obj = Data_Make_Struct(rb_cZmqFrame, zmq_frame_wrapper, 0, rb_czmq_free_frame_gc, f);
|
15
|
+
f->frame = frame;
|
16
|
+
f->flags = ZMQ_FRAME_OWNED;
|
17
|
+
f->message = NULL;
|
27
18
|
rb_obj_call_init(frame_obj, 0, NULL);
|
28
19
|
return frame_obj;
|
29
20
|
}
|
@@ -35,13 +26,11 @@ VALUE rb_czmq_alloc_frame(zframe_t *frame)
|
|
35
26
|
* libczmq.
|
36
27
|
*
|
37
28
|
*/
|
38
|
-
void rb_czmq_free_frame(
|
29
|
+
void rb_czmq_free_frame(zmq_frame_wrapper *frame)
|
39
30
|
{
|
40
|
-
if (frame) {
|
41
|
-
|
42
|
-
|
43
|
-
zframe_destroy(&frame);
|
44
|
-
}
|
31
|
+
if (frame && frame->frame && (frame->flags & ZMQ_FRAME_OWNED) != 0) {
|
32
|
+
zframe_destroy(&frame->frame);
|
33
|
+
frame->flags &= ~ZMQ_FRAME_OWNED;
|
45
34
|
}
|
46
35
|
}
|
47
36
|
|
@@ -52,7 +41,7 @@ void rb_czmq_free_frame(zframe_t *frame)
|
|
52
41
|
*/
|
53
42
|
void rb_czmq_free_frame_gc(void *ptr)
|
54
43
|
{
|
55
|
-
|
44
|
+
zmq_frame_wrapper *frame = (zmq_frame_wrapper *)ptr;
|
56
45
|
rb_czmq_free_frame(frame);
|
57
46
|
}
|
58
47
|
|
@@ -85,10 +74,7 @@ static VALUE rb_czmq_frame_s_new(int argc, VALUE *argv, VALUE frame)
|
|
85
74
|
ZmqAssertSysError();
|
86
75
|
rb_memerror();
|
87
76
|
}
|
88
|
-
|
89
|
-
frame = Data_Wrap_Struct(rb_cZmqFrame, 0, rb_czmq_free_frame_gc, fr);
|
90
|
-
rb_obj_call_init(frame, 0, NULL);
|
91
|
-
return frame;
|
77
|
+
return rb_czmq_alloc_frame(fr);
|
92
78
|
}
|
93
79
|
|
94
80
|
/*
|
@@ -108,6 +94,7 @@ static VALUE rb_czmq_frame_s_new(int argc, VALUE *argv, VALUE frame)
|
|
108
94
|
static VALUE rb_czmq_frame_destroy(VALUE obj)
|
109
95
|
{
|
110
96
|
ZmqGetFrame(obj);
|
97
|
+
ZmqAssertFrameOwned(frame);
|
111
98
|
rb_czmq_free_frame(frame);
|
112
99
|
return Qnil;
|
113
100
|
}
|
@@ -128,7 +115,8 @@ static VALUE rb_czmq_frame_size(VALUE obj)
|
|
128
115
|
{
|
129
116
|
size_t size;
|
130
117
|
ZmqGetFrame(obj);
|
131
|
-
|
118
|
+
ZmqReturnNilUnlessFrameOwned(frame);
|
119
|
+
size = zframe_size(frame->frame);
|
132
120
|
return LONG2FIX(size);
|
133
121
|
}
|
134
122
|
|
@@ -148,8 +136,9 @@ static VALUE rb_czmq_frame_data(VALUE obj)
|
|
148
136
|
{
|
149
137
|
size_t size;
|
150
138
|
ZmqGetFrame(obj);
|
151
|
-
|
152
|
-
|
139
|
+
ZmqReturnNilUnlessFrameOwned(frame);
|
140
|
+
size = zframe_size(frame->frame);
|
141
|
+
return ZmqEncode(rb_str_new((char *)zframe_data(frame->frame), (long)size));
|
153
142
|
}
|
154
143
|
|
155
144
|
/*
|
@@ -184,7 +173,8 @@ static VALUE rb_czmq_frame_to_s(VALUE obj)
|
|
184
173
|
static VALUE rb_czmq_frame_strhex(VALUE obj)
|
185
174
|
{
|
186
175
|
ZmqGetFrame(obj);
|
187
|
-
|
176
|
+
ZmqReturnNilUnlessFrameOwned(frame);
|
177
|
+
return rb_str_new2(zframe_strhex(frame->frame));
|
188
178
|
}
|
189
179
|
|
190
180
|
/*
|
@@ -201,19 +191,15 @@ static VALUE rb_czmq_frame_strhex(VALUE obj)
|
|
201
191
|
|
202
192
|
static VALUE rb_czmq_frame_dup(VALUE obj)
|
203
193
|
{
|
204
|
-
VALUE dup;
|
205
194
|
zframe_t *dup_fr = NULL;
|
206
|
-
errno = 0;
|
207
195
|
ZmqGetFrame(obj);
|
208
|
-
|
196
|
+
ZmqAssertFrameOwned(frame);
|
197
|
+
dup_fr = zframe_dup(frame->frame);
|
209
198
|
if (dup_fr == NULL) {
|
210
199
|
ZmqAssertSysError();
|
211
200
|
rb_memerror();
|
212
201
|
}
|
213
|
-
|
214
|
-
dup = Data_Wrap_Struct(rb_cZmqFrame, 0, rb_czmq_free_frame_gc, dup_fr);
|
215
|
-
rb_obj_call_init(dup, 0, NULL);
|
216
|
-
return dup;
|
202
|
+
return rb_czmq_alloc_frame(dup_fr);
|
217
203
|
}
|
218
204
|
|
219
205
|
/*
|
@@ -231,8 +217,9 @@ static VALUE rb_czmq_frame_dup(VALUE obj)
|
|
231
217
|
static VALUE rb_czmq_frame_data_equals_p(VALUE obj, VALUE data)
|
232
218
|
{
|
233
219
|
ZmqGetFrame(obj);
|
220
|
+
ZmqAssertFrameOwned(frame);
|
234
221
|
Check_Type(data, T_STRING);
|
235
|
-
return (zframe_streq(frame, RSTRING_PTR(data)) == true) ? Qtrue : Qfalse;
|
222
|
+
return (zframe_streq(frame->frame, RSTRING_PTR(data)) == true) ? Qtrue : Qfalse;
|
236
223
|
}
|
237
224
|
|
238
225
|
/*
|
@@ -250,7 +237,8 @@ static VALUE rb_czmq_frame_data_equals_p(VALUE obj, VALUE data)
|
|
250
237
|
static VALUE rb_czmq_frame_more_p(VALUE obj)
|
251
238
|
{
|
252
239
|
ZmqGetFrame(obj);
|
253
|
-
|
240
|
+
ZmqReturnNilUnlessFrameOwned(frame);
|
241
|
+
return (zframe_more(frame->frame) == ZFRAME_MORE) ? Qtrue : Qfalse;
|
254
242
|
}
|
255
243
|
|
256
244
|
/*
|
@@ -268,13 +256,14 @@ static VALUE rb_czmq_frame_more_p(VALUE obj)
|
|
268
256
|
|
269
257
|
static VALUE rb_czmq_frame_eql_p(VALUE obj, VALUE other_frame)
|
270
258
|
{
|
271
|
-
|
259
|
+
zmq_frame_wrapper *other = NULL;
|
272
260
|
ZmqGetFrame(obj);
|
261
|
+
ZmqAssertFrameOwned(frame);
|
273
262
|
ZmqAssertFrame(other_frame);
|
274
|
-
Data_Get_Struct(other_frame,
|
275
|
-
if (!other) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!"); \
|
276
|
-
|
277
|
-
return (zframe_eq(frame, other)) ? Qtrue : Qfalse;
|
263
|
+
Data_Get_Struct(other_frame, zmq_frame_wrapper, other);
|
264
|
+
if (!other || !other->frame) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!"); \
|
265
|
+
ZmqAssertFrameOwned(other);
|
266
|
+
return (zframe_eq(frame->frame, other->frame)) ? Qtrue : Qfalse;
|
278
267
|
}
|
279
268
|
|
280
269
|
/*
|
@@ -313,14 +302,15 @@ static VALUE rb_czmq_frame_equals(VALUE obj, VALUE other_frame)
|
|
313
302
|
static VALUE rb_czmq_frame_cmp(VALUE obj, VALUE other_frame)
|
314
303
|
{
|
315
304
|
long diff;
|
316
|
-
|
305
|
+
zmq_frame_wrapper *other = NULL;
|
317
306
|
if (obj == other_frame) return INT2NUM(0);
|
318
307
|
ZmqGetFrame(obj);
|
308
|
+
ZmqAssertFrameOwned(frame);
|
319
309
|
ZmqAssertFrame(other_frame);
|
320
|
-
Data_Get_Struct(other_frame,
|
321
|
-
if (!other) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!");
|
322
|
-
|
323
|
-
diff = (zframe_size(frame) - zframe_size(other));
|
310
|
+
Data_Get_Struct(other_frame, zmq_frame_wrapper, other);
|
311
|
+
if (!other || !other->frame) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!");
|
312
|
+
ZmqAssertFrameOwned(frame);
|
313
|
+
diff = (zframe_size(frame->frame) - zframe_size(other->frame));
|
324
314
|
if (diff == 0) return INT2NUM(0);
|
325
315
|
if (diff > 0) return INT2NUM(1);
|
326
316
|
return INT2NUM(-1);
|
@@ -343,6 +333,7 @@ static VALUE rb_czmq_frame_print(int argc, VALUE *argv, VALUE obj)
|
|
343
333
|
VALUE prefix;
|
344
334
|
const char *print_prefix = NULL;
|
345
335
|
ZmqGetFrame(obj);
|
336
|
+
ZmqAssertFrameOwned(frame);
|
346
337
|
rb_scan_args(argc, argv, "01", &prefix);
|
347
338
|
if (NIL_P(prefix)) {
|
348
339
|
print_prefix = "";
|
@@ -350,7 +341,7 @@ static VALUE rb_czmq_frame_print(int argc, VALUE *argv, VALUE obj)
|
|
350
341
|
Check_Type(prefix, T_STRING);
|
351
342
|
print_prefix = RSTRING_PTR(prefix);
|
352
343
|
}
|
353
|
-
zframe_print(frame, (char *)print_prefix);
|
344
|
+
zframe_print(frame->frame, (char *)print_prefix);
|
354
345
|
return Qnil;
|
355
346
|
}
|
356
347
|
|
@@ -371,12 +362,33 @@ static VALUE rb_czmq_frame_reset(VALUE obj, VALUE data)
|
|
371
362
|
{
|
372
363
|
errno = 0;
|
373
364
|
ZmqGetFrame(obj);
|
365
|
+
ZmqAssertFrameOwned(frame);
|
374
366
|
Check_Type(data, T_STRING);
|
375
|
-
zframe_reset(frame, (char *)RSTRING_PTR(data), (size_t)RSTRING_LEN(data));
|
367
|
+
zframe_reset(frame->frame, (char *)RSTRING_PTR(data), (size_t)RSTRING_LEN(data));
|
376
368
|
ZmqAssertSysError();
|
377
369
|
return Qnil;
|
378
370
|
}
|
379
371
|
|
372
|
+
/*
|
373
|
+
* call-seq:
|
374
|
+
* frame.gone? #=> false
|
375
|
+
* frame.destroy # or send
|
376
|
+
* frame.gone? #=> true
|
377
|
+
*
|
378
|
+
* Return boolean indicating if the ZMQ::Frame is gone (sent or destroyed). If the message is
|
379
|
+
* gone, accessor methods will return nil and methods requiring data or methods that mutate
|
380
|
+
* the message will raise an exception.
|
381
|
+
*/
|
382
|
+
|
383
|
+
static VALUE rb_czmq_frame_gone(VALUE obj)
|
384
|
+
{
|
385
|
+
ZmqGetFrame(obj);
|
386
|
+
return (frame->flags & ZMQ_FRAME_OWNED) ||
|
387
|
+
(frame->message != NULL && (frame->message->flags & ZMQ_MESSAGE_OWNED))
|
388
|
+
? Qfalse : Qtrue;
|
389
|
+
}
|
390
|
+
|
391
|
+
|
380
392
|
void _init_rb_czmq_frame()
|
381
393
|
{
|
382
394
|
intern_data = rb_intern("data");
|
@@ -403,4 +415,5 @@ void _init_rb_czmq_frame()
|
|
403
415
|
rb_define_method(rb_cZmqFrame, "print", rb_czmq_frame_print, -1);
|
404
416
|
rb_define_alias(rb_cZmqFrame, "dump", "print");
|
405
417
|
rb_define_method(rb_cZmqFrame, "reset", rb_czmq_frame_reset, 1);
|
418
|
+
rb_define_method(rb_cZmqFrame, "gone?", rb_czmq_frame_gone, 0);
|
406
419
|
}
|
data/ext/rbczmq/frame.h
CHANGED
@@ -1,21 +1,53 @@
|
|
1
1
|
#ifndef RBCZMQ_FRAME_H
|
2
2
|
#define RBCZMQ_FRAME_H
|
3
3
|
|
4
|
+
#include "message.h"
|
5
|
+
|
6
|
+
/* This flag indicates that the wrapped zframe_t is owned by ruby
|
7
|
+
and can be freed when the ZMQ::Frame object is garbage collected */
|
8
|
+
#define ZMQ_FRAME_OWNED 0x01
|
9
|
+
|
10
|
+
typedef struct {
|
11
|
+
/* The czmq frame object. This is only valid if the frame is owned
|
12
|
+
by ruby, or the frame has been added to a message and the message
|
13
|
+
is owned by ruby. */
|
14
|
+
zframe_t *frame;
|
15
|
+
|
16
|
+
/* The ruby ZMQ::Message object this frame is attached to, or NULL */
|
17
|
+
zmq_message_wrapper* message;
|
18
|
+
|
19
|
+
int flags;
|
20
|
+
} zmq_frame_wrapper;
|
21
|
+
|
4
22
|
#define ZmqAssertFrame(obj) ZmqAssertType(obj, rb_cZmqFrame, "ZMQ::Frame")
|
5
23
|
#define ZmqGetFrame(obj) \
|
6
|
-
|
24
|
+
zmq_frame_wrapper *frame = NULL; \
|
7
25
|
ZmqAssertFrame(obj); \
|
8
|
-
Data_Get_Struct(obj,
|
9
|
-
if (!frame) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!");
|
10
|
-
|
26
|
+
Data_Get_Struct(obj, zmq_frame_wrapper, frame); \
|
27
|
+
if (!frame) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!");
|
28
|
+
|
29
|
+
#define ZmqAssertFrameOwned(wrapper) if (!(\
|
30
|
+
(wrapper->flags & ZMQ_FRAME_OWNED) != 0 || \
|
31
|
+
(wrapper->message != NULL && (wrapper->message->flags & ZMQ_MESSAGE_OWNED) != 0 ) \
|
32
|
+
)) { \
|
33
|
+
rb_raise(rb_eZmqError, "Cannot access frame that belongs to another message or is gone."); \
|
34
|
+
}
|
35
|
+
|
36
|
+
#define ZmqAssertFrameOwnedNoMessage(wrapper) if (!(\
|
37
|
+
(wrapper->flags & ZMQ_FRAME_OWNED) != 0 \
|
38
|
+
)) { \
|
39
|
+
rb_raise(rb_eZmqError, "Cannot access frame that belongs to another message or is gone."); \
|
40
|
+
}
|
11
41
|
|
12
|
-
#define
|
13
|
-
|
14
|
-
|
42
|
+
#define ZmqReturnNilUnlessFrameOwned(wrapper) if (!(\
|
43
|
+
(wrapper->flags & ZMQ_FRAME_OWNED) != 0 || \
|
44
|
+
(wrapper->message != NULL && (wrapper->message->flags & ZMQ_MESSAGE_OWNED) != 0 ) \
|
45
|
+
)) { \
|
46
|
+
return Qnil; \
|
47
|
+
}
|
15
48
|
|
16
|
-
void rb_czmq_free_frame(
|
49
|
+
void rb_czmq_free_frame(zmq_frame_wrapper *frame);
|
17
50
|
void rb_czmq_free_frame_gc(void *ptr);
|
18
|
-
void rb_czmq_frame_freed(zframe_t *frame);
|
19
51
|
|
20
52
|
VALUE rb_czmq_alloc_frame(zframe_t *frame);
|
21
53
|
|
data/ext/rbczmq/message.c
CHANGED
@@ -8,9 +8,12 @@
|
|
8
8
|
void rb_czmq_free_message(zmq_message_wrapper *message)
|
9
9
|
{
|
10
10
|
errno = 0;
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
if (message != NULL && message->message != NULL && message->flags & ZMQ_MESSAGE_OWNED) {
|
12
|
+
zmsg_destroy(&message->message);
|
13
|
+
message->message = NULL;
|
14
|
+
message->flags &= ~ZMQ_MESSAGE_OWNED;
|
15
|
+
zlist_destroy(&message->frames);
|
16
|
+
}
|
14
17
|
}
|
15
18
|
|
16
19
|
/*
|
@@ -22,11 +25,24 @@ static void rb_czmq_free_message_gc(void *ptr)
|
|
22
25
|
{
|
23
26
|
zmq_message_wrapper *msg = (zmq_message_wrapper *)ptr;
|
24
27
|
if (msg) {
|
25
|
-
|
28
|
+
rb_czmq_free_message(msg);
|
26
29
|
xfree(msg);
|
27
30
|
}
|
28
31
|
}
|
29
32
|
|
33
|
+
/*
|
34
|
+
* :nodoc:
|
35
|
+
* mark the owned ZMQ::Frame objects so that they are not collected.
|
36
|
+
*/
|
37
|
+
void rb_czmq_mark_message(zmq_message_wrapper *message)
|
38
|
+
{
|
39
|
+
VALUE frame = (VALUE)zlist_first(message->frames);
|
40
|
+
while (frame) {
|
41
|
+
rb_gc_mark(frame);
|
42
|
+
frame = (VALUE)zlist_next(message->frames);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
30
46
|
/*
|
31
47
|
* :nodoc:
|
32
48
|
* Coerce a zmsg instance to a native Ruby object.
|
@@ -40,7 +56,22 @@ VALUE rb_czmq_alloc_message(zmsg_t *message)
|
|
40
56
|
message_obj = Data_Make_Struct(rb_cZmqMessage, zmq_message_wrapper, 0, rb_czmq_free_message_gc, m);
|
41
57
|
m->message = message;
|
42
58
|
ZmqAssertObjOnAlloc(m->message, m);
|
43
|
-
m->flags =
|
59
|
+
m->flags = ZMQ_MESSAGE_OWNED;
|
60
|
+
m->frames = zlist_new();
|
61
|
+
|
62
|
+
/* create ZMQ::Frame objects for all frames in the message and
|
63
|
+
link the ruby objects to this message. */
|
64
|
+
zframe_t* zframe = zmsg_first(message);
|
65
|
+
while (zframe) {
|
66
|
+
VALUE frame_object = rb_czmq_alloc_frame(zframe);
|
67
|
+
ZmqGetFrame(frame_object);
|
68
|
+
frame->flags &= ~ZMQ_FRAME_OWNED;
|
69
|
+
frame->message = m;
|
70
|
+
zlist_append(m->frames, (void*)frame_object);
|
71
|
+
|
72
|
+
zframe = zmsg_next(message);
|
73
|
+
}
|
74
|
+
|
44
75
|
rb_obj_call_init(message_obj, 0, NULL);
|
45
76
|
return message_obj;
|
46
77
|
}
|
@@ -58,14 +89,11 @@ VALUE rb_czmq_alloc_message(zmsg_t *message)
|
|
58
89
|
|
59
90
|
static VALUE rb_czmq_message_new(VALUE message)
|
60
91
|
{
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
msg->flags = 0;
|
67
|
-
rb_obj_call_init(message, 0, NULL);
|
68
|
-
return message;
|
92
|
+
zmsg_t* msg = zmsg_new();
|
93
|
+
if (msg == NULL) {
|
94
|
+
rb_raise(rb_eZmqError, "Failed to allocate message object (zmsg_new).");
|
95
|
+
}
|
96
|
+
return rb_czmq_alloc_message(msg);
|
69
97
|
}
|
70
98
|
|
71
99
|
/*
|
@@ -85,6 +113,7 @@ static VALUE rb_czmq_message_new(VALUE message)
|
|
85
113
|
static VALUE rb_czmq_message_size(VALUE obj)
|
86
114
|
{
|
87
115
|
ZmqGetMessage(obj);
|
116
|
+
ZmqReturnNilUnlessOwned(message);
|
88
117
|
return INT2NUM(zmsg_size(message->message));
|
89
118
|
}
|
90
119
|
|
@@ -105,6 +134,7 @@ static VALUE rb_czmq_message_size(VALUE obj)
|
|
105
134
|
static VALUE rb_czmq_message_content_size(VALUE obj)
|
106
135
|
{
|
107
136
|
ZmqGetMessage(obj);
|
137
|
+
ZmqReturnNilUnlessOwned(message);
|
108
138
|
return INT2NUM(zmsg_content_size(message->message));
|
109
139
|
}
|
110
140
|
|
@@ -127,10 +157,15 @@ static VALUE rb_czmq_message_push(VALUE obj, VALUE frame_obj)
|
|
127
157
|
int rc = 0;
|
128
158
|
errno = 0;
|
129
159
|
ZmqGetMessage(obj);
|
160
|
+
ZmqAssertMessageOwned(message);
|
130
161
|
ZmqGetFrame(frame_obj);
|
131
|
-
|
162
|
+
ZmqAssertFrameOwnedNoMessage(frame);
|
163
|
+
|
164
|
+
rc = zmsg_push(message->message, frame->frame);
|
132
165
|
ZmqAssert(rc);
|
133
|
-
|
166
|
+
frame->message = message;
|
167
|
+
frame->flags &= ~ZMQ_FRAME_OWNED;
|
168
|
+
zlist_push(message->frames, (void*)frame_obj);
|
134
169
|
return Qtrue;
|
135
170
|
}
|
136
171
|
|
@@ -153,10 +188,15 @@ static VALUE rb_czmq_message_add(VALUE obj, VALUE frame_obj)
|
|
153
188
|
int rc = 0;
|
154
189
|
errno = 0;
|
155
190
|
ZmqGetMessage(obj);
|
191
|
+
ZmqAssertMessageOwned(message);
|
156
192
|
ZmqGetFrame(frame_obj);
|
157
|
-
|
193
|
+
ZmqAssertFrameOwnedNoMessage(frame);
|
194
|
+
|
195
|
+
rc = zmsg_add(message->message, frame->frame);
|
158
196
|
ZmqAssert(rc);
|
159
|
-
|
197
|
+
frame->message = message;
|
198
|
+
frame->flags &= ~ZMQ_FRAME_OWNED;
|
199
|
+
zlist_append(message->frames, (void*)frame_obj);
|
160
200
|
return Qtrue;
|
161
201
|
}
|
162
202
|
|
@@ -179,9 +219,11 @@ static VALUE rb_czmq_message_pop(VALUE obj)
|
|
179
219
|
{
|
180
220
|
zframe_t *frame = NULL;
|
181
221
|
ZmqGetMessage(obj);
|
182
|
-
|
222
|
+
ZmqAssertMessageOwned(message);
|
223
|
+
frame = zmsg_pop(message->message); /* we now own the frame */
|
183
224
|
if (frame == NULL) return Qnil;
|
184
|
-
|
225
|
+
VALUE frame_obj = (VALUE)zlist_pop(message->frames);
|
226
|
+
return frame_obj ? frame_obj : Qnil;
|
185
227
|
}
|
186
228
|
|
187
229
|
/*
|
@@ -200,6 +242,7 @@ static VALUE rb_czmq_message_pop(VALUE obj)
|
|
200
242
|
static VALUE rb_czmq_message_print(VALUE obj)
|
201
243
|
{
|
202
244
|
ZmqGetMessage(obj);
|
245
|
+
ZmqReturnNilUnlessOwned(message);
|
203
246
|
zmsg_dump(message->message);
|
204
247
|
return Qnil;
|
205
248
|
}
|
@@ -220,11 +263,10 @@ static VALUE rb_czmq_message_print(VALUE obj)
|
|
220
263
|
|
221
264
|
static VALUE rb_czmq_message_first(VALUE obj)
|
222
265
|
{
|
223
|
-
zframe_t *frame = NULL;
|
224
266
|
ZmqGetMessage(obj);
|
225
|
-
|
226
|
-
|
227
|
-
return
|
267
|
+
ZmqReturnNilUnlessOwned(message);
|
268
|
+
VALUE frame_obj = (VALUE)zlist_first(message->frames);
|
269
|
+
return frame_obj ? frame_obj : Qnil;
|
228
270
|
}
|
229
271
|
|
230
272
|
/*
|
@@ -244,11 +286,10 @@ static VALUE rb_czmq_message_first(VALUE obj)
|
|
244
286
|
|
245
287
|
static VALUE rb_czmq_message_next(VALUE obj)
|
246
288
|
{
|
247
|
-
zframe_t *frame = NULL;
|
248
289
|
ZmqGetMessage(obj);
|
249
|
-
|
250
|
-
|
251
|
-
return
|
290
|
+
ZmqReturnNilUnlessOwned(message);
|
291
|
+
VALUE frame_obj = (VALUE)zlist_next(message->frames);
|
292
|
+
return frame_obj ? frame_obj : Qnil;
|
252
293
|
}
|
253
294
|
|
254
295
|
/*
|
@@ -267,11 +308,10 @@ static VALUE rb_czmq_message_next(VALUE obj)
|
|
267
308
|
|
268
309
|
static VALUE rb_czmq_message_last(VALUE obj)
|
269
310
|
{
|
270
|
-
zframe_t *frame = NULL;
|
271
311
|
ZmqGetMessage(obj);
|
272
|
-
|
273
|
-
|
274
|
-
return
|
312
|
+
ZmqReturnNilUnlessOwned(message);
|
313
|
+
VALUE frame_obj = (VALUE)zlist_last(message->frames);
|
314
|
+
return frame_obj ? frame_obj : Qnil;
|
275
315
|
}
|
276
316
|
|
277
317
|
/*
|
@@ -293,10 +333,18 @@ static VALUE rb_czmq_message_last(VALUE obj)
|
|
293
333
|
static VALUE rb_czmq_message_remove(VALUE obj, VALUE frame_obj)
|
294
334
|
{
|
295
335
|
ZmqGetMessage(obj);
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
336
|
+
ZmqAssertMessageOwned(message);
|
337
|
+
ZmqGetFrame(frame_obj);
|
338
|
+
|
339
|
+
/* remove from message and our list of frame objects */
|
340
|
+
zmsg_remove(message->message, frame->frame);
|
341
|
+
zlist_remove(message->frames, (void*)frame_obj);
|
342
|
+
|
343
|
+
/* removing from message does not destroy the frame,
|
344
|
+
therefore, we take ownership of the frame at this point */
|
345
|
+
frame->message = NULL;
|
346
|
+
frame->flags |= ZMQ_FRAME_OWNED;
|
347
|
+
|
300
348
|
return Qnil;
|
301
349
|
}
|
302
350
|
|
@@ -317,9 +365,19 @@ static VALUE rb_czmq_message_pushstr(VALUE obj, VALUE str)
|
|
317
365
|
int rc = 0;
|
318
366
|
errno = 0;
|
319
367
|
ZmqGetMessage(obj);
|
368
|
+
ZmqAssertMessageOwned(message);
|
320
369
|
Check_Type(str, T_STRING);
|
321
370
|
rc = zmsg_pushmem(message->message, StringValueCStr(str), RSTRING_LEN(str));
|
322
371
|
ZmqAssert(rc);
|
372
|
+
|
373
|
+
/* keep zlist of frame ruby objects in sync with message's frame list */
|
374
|
+
zframe_t* zframe = zmsg_first(message->message);
|
375
|
+
VALUE frame_object = rb_czmq_alloc_frame(zframe);
|
376
|
+
ZmqGetFrame(frame_object);
|
377
|
+
frame->flags &= ~ZMQ_FRAME_OWNED;
|
378
|
+
frame->message = message;
|
379
|
+
zlist_push(message->frames, (void*)frame_object);
|
380
|
+
|
323
381
|
return Qtrue;
|
324
382
|
}
|
325
383
|
|
@@ -340,9 +398,19 @@ static VALUE rb_czmq_message_addstr(VALUE obj, VALUE str)
|
|
340
398
|
int rc = 0;
|
341
399
|
errno = 0;
|
342
400
|
ZmqGetMessage(obj);
|
401
|
+
ZmqAssertMessageOwned(message);
|
343
402
|
Check_Type(str, T_STRING);
|
344
403
|
rc = zmsg_addmem(message->message, StringValueCStr(str), RSTRING_LEN(str));
|
345
404
|
ZmqAssert(rc);
|
405
|
+
|
406
|
+
/* keep zlist of frame ruby objects in sync with message's frame list */
|
407
|
+
zframe_t* zframe = zmsg_last(message->message);
|
408
|
+
VALUE frame_object = rb_czmq_alloc_frame(zframe);
|
409
|
+
ZmqGetFrame(frame_object);
|
410
|
+
frame->flags &= ~ZMQ_FRAME_OWNED;
|
411
|
+
frame->message = message;
|
412
|
+
zlist_append(message->frames, (void*)frame_object);
|
413
|
+
|
346
414
|
return Qtrue;
|
347
415
|
}
|
348
416
|
|
@@ -363,8 +431,13 @@ static VALUE rb_czmq_message_popstr(VALUE obj)
|
|
363
431
|
{
|
364
432
|
char *str = NULL;
|
365
433
|
ZmqGetMessage(obj);
|
434
|
+
ZmqAssertMessageOwned(message);
|
366
435
|
str = zmsg_popstr(message->message);
|
367
436
|
if (str == NULL) return Qnil;
|
437
|
+
|
438
|
+
/* destroys the frame, keep frame objects list in sync: */
|
439
|
+
zlist_pop(message->frames);
|
440
|
+
|
368
441
|
return rb_str_new2(str);
|
369
442
|
}
|
370
443
|
|
@@ -386,9 +459,30 @@ static VALUE rb_czmq_message_wrap(VALUE obj, VALUE frame_obj)
|
|
386
459
|
{
|
387
460
|
errno = 0;
|
388
461
|
ZmqGetMessage(obj);
|
389
|
-
|
390
|
-
|
391
|
-
|
462
|
+
ZmqAssertMessageOwned(message);
|
463
|
+
|
464
|
+
{
|
465
|
+
ZmqGetFrame(frame_obj);
|
466
|
+
ZmqAssertFrameOwned(frame);
|
467
|
+
zmsg_wrap(message->message, frame->frame);
|
468
|
+
frame->flags &= ~ZMQ_FRAME_OWNED;
|
469
|
+
frame->message = message;
|
470
|
+
}
|
471
|
+
|
472
|
+
/* keep frame objects list in sync. Two frames have been added. frame_obj from above
|
473
|
+
and a new one for the empty frame. */
|
474
|
+
{
|
475
|
+
zmsg_first(message->message);
|
476
|
+
zframe_t* empty_frame = zmsg_next(message->message);
|
477
|
+
|
478
|
+
VALUE empty_frame_object = rb_czmq_alloc_frame(empty_frame);
|
479
|
+
ZmqGetFrame(empty_frame_object);
|
480
|
+
frame->flags &= ~ZMQ_FRAME_OWNED;
|
481
|
+
frame->message = message;
|
482
|
+
|
483
|
+
zlist_push(message->frames, (void*)empty_frame_object);
|
484
|
+
zlist_push(message->frames, (void*)frame_obj);
|
485
|
+
}
|
392
486
|
return Qnil;
|
393
487
|
}
|
394
488
|
|
@@ -410,11 +504,29 @@ static VALUE rb_czmq_message_wrap(VALUE obj, VALUE frame_obj)
|
|
410
504
|
|
411
505
|
static VALUE rb_czmq_message_unwrap(VALUE obj)
|
412
506
|
{
|
413
|
-
zframe_t *frame = NULL;
|
414
507
|
ZmqGetMessage(obj);
|
415
|
-
|
416
|
-
|
417
|
-
|
508
|
+
ZmqAssertMessageOwned(message);
|
509
|
+
|
510
|
+
/* reimplemented the zmsg_unwrap function for simpler logic: */
|
511
|
+
zframe_t *zframe = zmsg_pop(message->message);
|
512
|
+
VALUE frame_obj = 0;
|
513
|
+
if (zframe != NULL) {
|
514
|
+
frame_obj = (VALUE)zlist_pop(message->frames);
|
515
|
+
}
|
516
|
+
|
517
|
+
zframe_t *empty = zmsg_first(message->message);
|
518
|
+
if (zframe_size(empty) == 0) {
|
519
|
+
empty = zmsg_pop(message->message);
|
520
|
+
zframe_destroy (&empty);
|
521
|
+
zlist_pop(message->frames);
|
522
|
+
}
|
523
|
+
|
524
|
+
{
|
525
|
+
ZmqGetFrame(frame_obj);
|
526
|
+
frame->message = NULL;
|
527
|
+
frame->flags |= ZMQ_FRAME_OWNED;
|
528
|
+
}
|
529
|
+
return frame_obj ? frame_obj : Qnil;
|
418
530
|
}
|
419
531
|
|
420
532
|
/*
|
@@ -431,16 +543,11 @@ static VALUE rb_czmq_message_unwrap(VALUE obj)
|
|
431
543
|
|
432
544
|
static VALUE rb_czmq_message_dup(VALUE obj)
|
433
545
|
{
|
434
|
-
VALUE dup;
|
435
|
-
zmq_message_wrapper *dup_msg = NULL;
|
436
|
-
errno = 0;
|
437
546
|
ZmqGetMessage(obj);
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
dup_msg
|
442
|
-
rb_obj_call_init(dup, 0, NULL);
|
443
|
-
return dup;
|
547
|
+
ZmqAssertMessageOwned(message);
|
548
|
+
|
549
|
+
zmsg_t* dup_msg = zmsg_dup(message->message);
|
550
|
+
return rb_czmq_alloc_message(dup_msg);
|
444
551
|
}
|
445
552
|
|
446
553
|
/*
|
@@ -460,6 +567,7 @@ static VALUE rb_czmq_message_dup(VALUE obj)
|
|
460
567
|
static VALUE rb_czmq_message_destroy(VALUE obj)
|
461
568
|
{
|
462
569
|
ZmqGetMessage(obj);
|
570
|
+
ZmqAssertMessageOwned(message);
|
463
571
|
rb_czmq_free_message(message);
|
464
572
|
return Qnil;
|
465
573
|
}
|
@@ -483,6 +591,7 @@ static VALUE rb_czmq_message_encode(VALUE obj)
|
|
483
591
|
byte *buff;
|
484
592
|
size_t buff_size;
|
485
593
|
ZmqGetMessage(obj);
|
594
|
+
ZmqReturnNilUnlessOwned(message);
|
486
595
|
buff_size = zmsg_encode(message->message, &buff);
|
487
596
|
return rb_str_new((char *)buff, buff_size);
|
488
597
|
}
|
@@ -531,8 +640,10 @@ static VALUE rb_czmq_message_eql_p(VALUE obj, VALUE other_message)
|
|
531
640
|
size_t other_buff_size;
|
532
641
|
ZmqGetMessage(obj);
|
533
642
|
ZmqAssertMessage(other_message);
|
643
|
+
ZmqAssertMessageOwned(message);
|
534
644
|
Data_Get_Struct(other_message, zmq_message_wrapper, other);
|
535
645
|
if (!other) rb_raise(rb_eTypeError, "uninitialized ZMQ message!");
|
646
|
+
ZmqAssertMessageOwned(other);
|
536
647
|
|
537
648
|
if (zmsg_size(message->message) != zmsg_size(other->message)) return Qfalse;
|
538
649
|
if (zmsg_content_size(message->message) != zmsg_content_size(other->message)) return Qfalse;
|
@@ -580,15 +691,33 @@ static VALUE rb_czmq_message_to_a(VALUE obj)
|
|
580
691
|
{
|
581
692
|
VALUE ary;
|
582
693
|
ZmqGetMessage(obj);
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
694
|
+
ZmqAssertMessageOwned(message);
|
695
|
+
ary = rb_ary_new2(zlist_size(message->frames));
|
696
|
+
VALUE frame_obj = (VALUE)zlist_first(message->frames);
|
697
|
+
while (frame_obj) {
|
698
|
+
rb_ary_push(ary, frame_obj);
|
699
|
+
frame_obj = (VALUE)zlist_next(message->frames);
|
588
700
|
}
|
589
701
|
return ary;
|
590
702
|
}
|
591
703
|
|
704
|
+
/*
|
705
|
+
* call-seq:
|
706
|
+
* msg.gone? #=> false
|
707
|
+
* msg.destroy # or send
|
708
|
+
* msg.gone? #=> true
|
709
|
+
*
|
710
|
+
* Return boolean indicating if the ZMQ::Message is gone (sent or destroyed). If the message is
|
711
|
+
* gone, accessor methods will return nil and methods requiring data or methods that mutate
|
712
|
+
* the message will raise an exception.
|
713
|
+
*/
|
714
|
+
|
715
|
+
static VALUE rb_czmq_message_gone(VALUE obj)
|
716
|
+
{
|
717
|
+
ZmqGetMessage(obj);
|
718
|
+
return (message->flags & ZMQ_MESSAGE_OWNED) ? Qfalse : Qtrue;
|
719
|
+
}
|
720
|
+
|
592
721
|
void _init_rb_czmq_message()
|
593
722
|
{
|
594
723
|
rb_cZmqMessage = rb_define_class_under(rb_mZmq, "Message", rb_cObject);
|
@@ -617,4 +746,5 @@ void _init_rb_czmq_message()
|
|
617
746
|
rb_define_method(rb_cZmqMessage, "eql?", rb_czmq_message_equals, 1);
|
618
747
|
rb_define_method(rb_cZmqMessage, "==", rb_czmq_message_equals, 1);
|
619
748
|
rb_define_method(rb_cZmqMessage, "to_a", rb_czmq_message_to_a, 0);
|
749
|
+
rb_define_method(rb_cZmqMessage, "gone?", rb_czmq_message_gone, 0);
|
620
750
|
}
|
data/ext/rbczmq/message.h
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
#ifndef RBCZMQ_MESSAGE_H
|
2
2
|
#define RBCZMQ_MESSAGE_H
|
3
3
|
|
4
|
-
|
4
|
+
/* This flag indicates that the wrapped zmsg_t is owned by ruby
|
5
|
+
and can be freed when the ZMQ::Message object is garbage collected */
|
6
|
+
#define ZMQ_MESSAGE_OWNED 0x01
|
5
7
|
|
6
8
|
typedef struct {
|
7
9
|
zmsg_t *message;
|
8
10
|
int flags;
|
11
|
+
/* a zlist of frame wrapper objects for the frames in this message */
|
12
|
+
zlist_t *frames;
|
9
13
|
} zmq_message_wrapper;
|
10
14
|
|
11
15
|
#define ZmqAssertMessage(obj) ZmqAssertType(obj, rb_cZmqMessage, "ZMQ::Message")
|
@@ -13,11 +17,23 @@ typedef struct {
|
|
13
17
|
zmq_message_wrapper *message = NULL; \
|
14
18
|
ZmqAssertMessage(obj); \
|
15
19
|
Data_Get_Struct(obj, zmq_message_wrapper, message); \
|
16
|
-
if (!message) rb_raise(rb_eTypeError, "uninitialized ZMQ message!");
|
20
|
+
if (!message) rb_raise(rb_eTypeError, "uninitialized ZMQ message!");
|
21
|
+
|
22
|
+
/*
|
17
23
|
if (message->flags & ZMQ_MESSAGE_DESTROYED) rb_raise(rb_eZmqError, "ZMQ::Message instance %p has been destroyed by the ZMQ framework", (void *)obj);
|
24
|
+
*/
|
25
|
+
|
26
|
+
#define ZmqReturnNilUnlessOwned(wrapper) if (wrapper && (wrapper->flags & ZMQ_MESSAGE_OWNED) == 0) { \
|
27
|
+
return Qnil; \
|
28
|
+
}
|
29
|
+
|
30
|
+
#define ZmqAssertMessageOwned(wrapper) if (wrapper && (wrapper->flags & ZMQ_MESSAGE_OWNED) == 0) { \
|
31
|
+
rb_raise(rb_eTypeError, "Cannot modify a message that is gone."); \
|
32
|
+
}
|
18
33
|
|
19
34
|
VALUE rb_czmq_alloc_message(zmsg_t *message);
|
20
35
|
void rb_czmq_free_message(zmq_message_wrapper *message);
|
36
|
+
void rb_czmq_mark_message(zmq_message_wrapper *message);
|
21
37
|
|
22
38
|
void _init_rb_czmq_message();
|
23
39
|
|
data/ext/rbczmq/pollitem.c
CHANGED
@@ -250,4 +250,4 @@ void _init_rb_czmq_pollitem()
|
|
250
250
|
rb_define_method(rb_cZmqPollitem, "handler", rb_czmq_pollitem_handler, 0);
|
251
251
|
rb_define_method(rb_cZmqPollitem, "handler=", rb_czmq_pollitem_handler_equals, 1);
|
252
252
|
rb_define_method(rb_cZmqPollitem, "verbose=", rb_czmq_pollitem_set_verbose, 1);
|
253
|
-
}
|
253
|
+
}
|
data/ext/rbczmq/rbczmq_ext.c
CHANGED
@@ -25,8 +25,6 @@ VALUE rb_cZmqPoller;
|
|
25
25
|
VALUE rb_cZmqPollitem;
|
26
26
|
VALUE rb_cZmqBeacon;
|
27
27
|
|
28
|
-
st_table *frames_map = NULL;
|
29
|
-
|
30
28
|
VALUE intern_call;
|
31
29
|
VALUE intern_readable;
|
32
30
|
VALUE intern_writable;
|
@@ -216,8 +214,6 @@ static VALUE rb_czmq_m_proxy(int argc, VALUE *argv, ZMQ_UNUSED VALUE klass)
|
|
216
214
|
|
217
215
|
void Init_rbczmq_ext()
|
218
216
|
{
|
219
|
-
frames_map = st_init_numtable();
|
220
|
-
|
221
217
|
intern_call = rb_intern("call");
|
222
218
|
intern_readable = rb_intern("on_readable");
|
223
219
|
intern_writable = rb_intern("on_writable");
|
data/ext/rbczmq/rbczmq_ext.h
CHANGED
data/ext/rbczmq/socket.c
CHANGED
@@ -229,7 +229,7 @@ static VALUE rb_czmq_socket_bind(VALUE obj, VALUE endpoint)
|
|
229
229
|
args.endpoint = StringValueCStr(endpoint);
|
230
230
|
rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_socket_bind, (void *)&args, RUBY_UBF_IO, 0);
|
231
231
|
/* ZmqAssert will return false on any non-zero return code. Bind returns the port number */
|
232
|
-
if (rc < 0) {
|
232
|
+
if (rc < 0) {
|
233
233
|
ZmqAssert(rc);
|
234
234
|
}
|
235
235
|
if (sock->verbose)
|
@@ -562,6 +562,7 @@ static VALUE rb_czmq_socket_send_frame(int argc, VALUE *argv, VALUE obj)
|
|
562
562
|
ZmqSockGuardCrossThread(sock);
|
563
563
|
rb_scan_args(argc, argv, "11", &frame_obj, &flags);
|
564
564
|
ZmqGetFrame(frame_obj);
|
565
|
+
ZmqAssertFrameOwnedNoMessage(frame);
|
565
566
|
|
566
567
|
if (NIL_P(flags)) {
|
567
568
|
flgs = 0;
|
@@ -573,13 +574,17 @@ static VALUE rb_czmq_socket_send_frame(int argc, VALUE *argv, VALUE obj)
|
|
573
574
|
|
574
575
|
if (sock->verbose) {
|
575
576
|
cur_time = rb_czmq_formatted_current_time();
|
576
|
-
print_frame = (flgs & ZFRAME_REUSE) ? frame : zframe_dup(frame);
|
577
|
+
print_frame = (flgs & ZFRAME_REUSE) ? frame->frame : zframe_dup(frame->frame);
|
577
578
|
}
|
578
579
|
args.socket = sock;
|
579
|
-
args.frame = frame;
|
580
|
+
args.frame = frame->frame;
|
580
581
|
args.flags = flgs;
|
581
582
|
rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_send_frame, (void *)&args, RUBY_UBF_IO, 0);
|
582
583
|
ZmqAssert(rc);
|
584
|
+
if ((flgs & ZFRAME_REUSE) == 0) {
|
585
|
+
/* frame has been destroyed, clear the owns flag */
|
586
|
+
frame->flags &= ~ZMQ_FRAME_OWNED;
|
587
|
+
}
|
583
588
|
if (sock->verbose) ZmqDumpFrame("send_frame", print_frame);
|
584
589
|
return Qtrue;
|
585
590
|
}
|
@@ -623,11 +628,12 @@ static VALUE rb_czmq_socket_send_message(VALUE obj, VALUE message_obj)
|
|
623
628
|
ZmqAssertSocketNotPending(sock, "can only send on a bound or connected socket!");
|
624
629
|
ZmqSockGuardCrossThread(sock);
|
625
630
|
ZmqGetMessage(message_obj);
|
631
|
+
ZmqAssertMessageOwned(message);
|
626
632
|
if (sock->verbose) print_message = zmsg_dup(message->message);
|
627
633
|
args.socket = sock;
|
628
634
|
args.message = message->message;
|
629
635
|
rb_thread_blocking_region(rb_czmq_nogvl_send_message, (void *)&args, RUBY_UBF_IO, 0);
|
630
|
-
message->flags
|
636
|
+
message->flags &= ~ZMQ_MESSAGE_OWNED;
|
631
637
|
if (sock->verbose) ZmqDumpMessage("send_message", print_message);
|
632
638
|
return Qnil;
|
633
639
|
}
|
@@ -1652,7 +1658,7 @@ static VALUE rb_czmq_socket_monitor_thread(void *arg)
|
|
1652
1658
|
|
1653
1659
|
args.monitored_socket_wrapper = sock;
|
1654
1660
|
args.socket = s;
|
1655
|
-
|
1661
|
+
|
1656
1662
|
while (1) {
|
1657
1663
|
zmq_msg_init (&args.msg);
|
1658
1664
|
rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_monitor_recv, (void *)&args, RUBY_UBF_IO, 0);
|
data/lib/zmq.rb
CHANGED
data/lib/zmq/logger.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module ZMQ
|
6
|
+
|
7
|
+
# A logging class that sends its output to a ZMQ socket. This allows log messages to be sent
|
8
|
+
# asynchronously to another process and across a network if required. The receiving socket
|
9
|
+
# will receive messages, each with text of one log message.
|
10
|
+
#
|
11
|
+
# Example usage:
|
12
|
+
#
|
13
|
+
# socket = context.socket(ZMQ::PUSH)
|
14
|
+
# socket.connect("tcp://logserver:5555")
|
15
|
+
# logger = ZMQ::Logger.new(socket)
|
16
|
+
# logger.debug("Hello logger")
|
17
|
+
#
|
18
|
+
class Logger < ::Logger
|
19
|
+
|
20
|
+
class InvalidSocketError < ZMQ::Error ; end
|
21
|
+
|
22
|
+
# only these socket classes are allowed to be used for sending
|
23
|
+
VALID_SOCKET_CLASSES = [
|
24
|
+
Socket::Pub,
|
25
|
+
Socket::Push,
|
26
|
+
Socket::Pair
|
27
|
+
]
|
28
|
+
|
29
|
+
# Initialise a new logger object. The logger sends log messages to a socket.
|
30
|
+
# The caller is responsible for connecting the socket before using the logger to
|
31
|
+
# send log output to the socket.
|
32
|
+
#
|
33
|
+
# Supported socket types are a Socket::Pub, Socket::Push, and Socket::Pair
|
34
|
+
def initialize(socket)
|
35
|
+
raise InvalidSocketError unless VALID_SOCKET_CLASSES.any? { |klass| socket.is_a?(klass) }
|
36
|
+
super(nil)
|
37
|
+
@logdev = LogDevice.new(socket)
|
38
|
+
end
|
39
|
+
|
40
|
+
# implements an interface similar to ::Logger::LogDevice. This is the recipient of the
|
41
|
+
# formatted log messages
|
42
|
+
class LogDevice
|
43
|
+
# :nodoc:
|
44
|
+
def initialize(socket)
|
45
|
+
@socket = socket
|
46
|
+
end
|
47
|
+
|
48
|
+
# write the formatted log message to the socket.
|
49
|
+
def write(message)
|
50
|
+
@socket.send(message)
|
51
|
+
end
|
52
|
+
|
53
|
+
def close
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
data/lib/zmq/version.rb
CHANGED
data/test/test_frame.rb
CHANGED
data/test/test_logger.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
4
|
+
|
5
|
+
class TestZmqLogger < ZmqTestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@ctx = ZMQ::Context.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
@ctx.destroy
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_invalid_socket
|
16
|
+
socket = @ctx.socket(ZMQ::REQ)
|
17
|
+
assert_raises ZMQ::Logger::InvalidSocketError do
|
18
|
+
ZMQ::Logger.new(socket)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_valid_socket
|
23
|
+
socket = @ctx.socket(ZMQ::PUSH)
|
24
|
+
assert_nothing_raised do
|
25
|
+
ZMQ::Logger.new(socket)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_send_message
|
30
|
+
reader = @ctx.socket(ZMQ::PULL)
|
31
|
+
port = reader.bind("tcp://*:*")
|
32
|
+
assert port > 0
|
33
|
+
writer = @ctx.socket(ZMQ::PUSH)
|
34
|
+
writer.connect("tcp://localhost:#{port}")
|
35
|
+
logger = ZMQ::Logger.new(writer)
|
36
|
+
assert logger.debug("hellö world")
|
37
|
+
message = reader.recv.force_encoding Encoding::UTF_8
|
38
|
+
assert_not_nil message =~ /hellö world/
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/test/test_message.rb
CHANGED
@@ -11,10 +11,11 @@ class TestZmqMessage < ZmqTestCase
|
|
11
11
|
|
12
12
|
def test_destroyed
|
13
13
|
msg = ZMQ::Message("one", "two")
|
14
|
+
assert_not_nil msg.encode
|
15
|
+
assert !msg.gone?
|
14
16
|
msg.destroy
|
15
|
-
|
16
|
-
|
17
|
-
end
|
17
|
+
assert msg.gone?
|
18
|
+
assert_nil msg.encode
|
18
19
|
end
|
19
20
|
|
20
21
|
def test_message_sugar
|
@@ -182,7 +183,7 @@ class TestZmqMessage < ZmqTestCase
|
|
182
183
|
end
|
183
184
|
|
184
185
|
def test_equals
|
185
|
-
msg =
|
186
|
+
msg = ZMQ::Message.new
|
186
187
|
msg.pushstr "body"
|
187
188
|
msg.pushstr "header"
|
188
189
|
|
@@ -198,4 +199,96 @@ class TestZmqMessage < ZmqTestCase
|
|
198
199
|
assert !msg.eql?(other)
|
199
200
|
assert other.eql?(other)
|
200
201
|
end
|
201
|
-
|
202
|
+
|
203
|
+
def test_message_with_frames
|
204
|
+
msg = ZMQ::Message.new
|
205
|
+
frame = ZMQ::Frame.new("hello")
|
206
|
+
assert_equal "hello", frame.data
|
207
|
+
msg.add frame
|
208
|
+
# frame is owned by message, but message is still owned by ruby,
|
209
|
+
# so the frame data should still be accessible:
|
210
|
+
assert_equal "hello", frame.data
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_messge_add_frame_twice
|
214
|
+
msg = ZMQ::Message.new
|
215
|
+
frame = ZMQ::Frame.new("hello")
|
216
|
+
msg.add frame
|
217
|
+
assert_raises ZMQ::Error do
|
218
|
+
msg.add frame
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_message_is_gone_after_send
|
223
|
+
ctx = ZMQ::Context.new
|
224
|
+
endpoint = "inproc://test.test_message_is_gone_after_send"
|
225
|
+
push = ctx.bind(:PUSH, endpoint)
|
226
|
+
pull = ctx.connect(:PULL, endpoint)
|
227
|
+
msg = ZMQ::Message.new
|
228
|
+
frame = ZMQ::Frame.new("hello")
|
229
|
+
msg.add frame
|
230
|
+
push.send_message(msg)
|
231
|
+
assert msg.gone?
|
232
|
+
assert frame.gone?
|
233
|
+
ensure
|
234
|
+
ctx.destroy
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_message_has_frames_on_receive
|
238
|
+
ctx = ZMQ::Context.new
|
239
|
+
endpoint = "inproc://test.test_message_is_gone_after_send"
|
240
|
+
push = ctx.bind(:PUSH, endpoint)
|
241
|
+
pull = ctx.connect(:PULL, endpoint)
|
242
|
+
msg = ZMQ::Message.new
|
243
|
+
msg.add ZMQ::Frame.new("hello")
|
244
|
+
msg.add ZMQ::Frame.new("world")
|
245
|
+
push.send_message(msg)
|
246
|
+
received = pull.recv_message
|
247
|
+
assert_not_nil received
|
248
|
+
assert_equal 2, received.size
|
249
|
+
assert_equal "hello", received.first.data
|
250
|
+
assert_equal "world", received.next.data
|
251
|
+
ensure
|
252
|
+
ctx.destroy
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_message_remove_frame
|
256
|
+
msg = ZMQ::Message.new
|
257
|
+
frame = ZMQ::Frame.new("hello")
|
258
|
+
msg.add frame
|
259
|
+
assert_equal 1, msg.size
|
260
|
+
# same object is returned
|
261
|
+
assert_equal frame.object_id, msg.first.object_id
|
262
|
+
msg.remove frame
|
263
|
+
assert_equal 0, msg.size
|
264
|
+
end
|
265
|
+
|
266
|
+
def test_message_array_same_frame_objects
|
267
|
+
msg = ZMQ::Message.new
|
268
|
+
frame = ZMQ::Frame.new("hello")
|
269
|
+
msg.add frame
|
270
|
+
ary = msg.to_a
|
271
|
+
assert_equal 1, ary.count
|
272
|
+
assert_equal frame, ary.first
|
273
|
+
assert_equal frame.object_id, ary.first.object_id
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_message_unwrap_dup
|
277
|
+
ctx = ZMQ::Context.new
|
278
|
+
router = ctx.socket(ZMQ::ROUTER)
|
279
|
+
port = router.bind("tcp://127.0.0.1:*")
|
280
|
+
req = ctx.connect(ZMQ::REQ, "tcp://127.0.0.1:#{port}")
|
281
|
+
msg = ZMQ::Message.new
|
282
|
+
msg.addstr "hello world"
|
283
|
+
req.send_message msg
|
284
|
+
msg2 = router.recv_message
|
285
|
+
identity = msg2.unwrap
|
286
|
+
assert_equal "hello world", msg2.first.data
|
287
|
+
msg3 = ZMQ::Message.new
|
288
|
+
msg3.addstr "reply"
|
289
|
+
msg3.wrap identity.dup
|
290
|
+
assert_equal 3, msg3.size
|
291
|
+
ensure
|
292
|
+
ctx.destroy
|
293
|
+
end
|
294
|
+
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbczmq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.7.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Lourens Naudé
|
@@ -11,12 +10,11 @@ authors:
|
|
11
10
|
autorequire:
|
12
11
|
bindir: bin
|
13
12
|
cert_chain: []
|
14
|
-
date: 2013-07-
|
13
|
+
date: 2013-07-21 00:00:00.000000000 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: rake-compiler
|
18
17
|
requirement: !ruby/object:Gem::Requirement
|
19
|
-
none: false
|
20
18
|
requirements:
|
21
19
|
- - ~>
|
22
20
|
- !ruby/object:Gem::Version
|
@@ -24,7 +22,6 @@ dependencies:
|
|
24
22
|
type: :development
|
25
23
|
prerelease: false
|
26
24
|
version_requirements: !ruby/object:Gem::Requirement
|
27
|
-
none: false
|
28
25
|
requirements:
|
29
26
|
- - ~>
|
30
27
|
- !ruby/object:Gem::Version
|
@@ -86,6 +83,7 @@ files:
|
|
86
83
|
- lib/zmq/default_handler.rb
|
87
84
|
- lib/zmq/frame.rb
|
88
85
|
- lib/zmq/handler.rb
|
86
|
+
- lib/zmq/logger.rb
|
89
87
|
- lib/zmq/loop.rb
|
90
88
|
- lib/zmq/message.rb
|
91
89
|
- lib/zmq/monitor.rb
|
@@ -136,6 +134,7 @@ files:
|
|
136
134
|
- test/test_context.rb
|
137
135
|
- test/test_frame.rb
|
138
136
|
- test/test_handler.rb
|
137
|
+
- test/test_logger.rb
|
139
138
|
- test/test_loop.rb
|
140
139
|
- test/test_message.rb
|
141
140
|
- test/test_monitoring.rb
|
@@ -529,28 +528,27 @@ files:
|
|
529
528
|
- ext/zeromq/version.sh
|
530
529
|
homepage: http://github.com/methodmissing/rbczmq
|
531
530
|
licenses: []
|
531
|
+
metadata: {}
|
532
532
|
post_install_message:
|
533
533
|
rdoc_options:
|
534
534
|
- --charset=UTF-8
|
535
535
|
require_paths:
|
536
536
|
- lib
|
537
537
|
required_ruby_version: !ruby/object:Gem::Requirement
|
538
|
-
none: false
|
539
538
|
requirements:
|
540
539
|
- - ! '>='
|
541
540
|
- !ruby/object:Gem::Version
|
542
541
|
version: '0'
|
543
542
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
544
|
-
none: false
|
545
543
|
requirements:
|
546
544
|
- - ! '>='
|
547
545
|
- !ruby/object:Gem::Version
|
548
546
|
version: '0'
|
549
547
|
requirements: []
|
550
548
|
rubyforge_project:
|
551
|
-
rubygems_version:
|
549
|
+
rubygems_version: 2.0.3
|
552
550
|
signing_key:
|
553
|
-
specification_version:
|
551
|
+
specification_version: 4
|
554
552
|
summary: Ruby extension for ZeroMQ (ZMQ) using CZMQ - High-level C Binding for ØMQ
|
555
553
|
(http://czmq.zeromq.org)
|
556
554
|
test_files:
|
@@ -573,6 +571,7 @@ test_files:
|
|
573
571
|
- test/test_context.rb
|
574
572
|
- test/test_frame.rb
|
575
573
|
- test/test_handler.rb
|
574
|
+
- test/test_logger.rb
|
576
575
|
- test/test_loop.rb
|
577
576
|
- test/test_message.rb
|
578
577
|
- test/test_monitoring.rb
|
@@ -582,4 +581,3 @@ test_files:
|
|
582
581
|
- test/test_threading.rb
|
583
582
|
- test/test_timer.rb
|
584
583
|
- test/test_zmq.rb
|
585
|
-
has_rdoc: true
|