zyre 0.1.0
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 +7 -0
- checksums.yaml.gz.sig +2 -0
- data.tar.gz.sig +0 -0
- data/History.md +8 -0
- data/LICENSE.txt +20 -0
- data/README.md +104 -0
- data/ext/zyre_ext/event.c +479 -0
- data/ext/zyre_ext/extconf.rb +25 -0
- data/ext/zyre_ext/node.c +850 -0
- data/ext/zyre_ext/poller.c +272 -0
- data/ext/zyre_ext/zyre_ext.c +154 -0
- data/ext/zyre_ext/zyre_ext.h +99 -0
- data/lib/observability/instrumentation/zyre.rb +52 -0
- data/lib/zyre.rb +53 -0
- data/lib/zyre/event.rb +82 -0
- data/lib/zyre/event/enter.rb +19 -0
- data/lib/zyre/event/evasive.rb +17 -0
- data/lib/zyre/event/exit.rb +18 -0
- data/lib/zyre/event/join.rb +18 -0
- data/lib/zyre/event/leave.rb +18 -0
- data/lib/zyre/event/shout.rb +19 -0
- data/lib/zyre/event/silent.rb +18 -0
- data/lib/zyre/event/stop.rb +9 -0
- data/lib/zyre/event/whisper.rb +18 -0
- data/lib/zyre/node.rb +147 -0
- data/lib/zyre/poller.rb +16 -0
- data/lib/zyre/testing.rb +296 -0
- data/spec/observability/instrumentation/zyre_spec.rb +56 -0
- data/spec/spec_helper.rb +62 -0
- data/spec/zyre/event_spec.rb +141 -0
- data/spec/zyre/node_spec.rb +356 -0
- data/spec/zyre/poller_spec.rb +44 -0
- data/spec/zyre/testing_spec.rb +260 -0
- data/spec/zyre_spec.rb +55 -0
- metadata +224 -0
- metadata.gz.sig +3 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rbconfig'
|
4
|
+
require 'mkmf'
|
5
|
+
|
6
|
+
dir_config( 'libzyre' )
|
7
|
+
|
8
|
+
have_library( 'zyre' ) or
|
9
|
+
abort "No zyre library!"
|
10
|
+
have_library( 'czmq' ) or
|
11
|
+
abort "No czmq library!"
|
12
|
+
|
13
|
+
have_header( 'zyre.h' ) or
|
14
|
+
abort "No zyre.h header!"
|
15
|
+
have_header( 'czmq.h' ) or
|
16
|
+
abort "No czmq.h header!"
|
17
|
+
have_header( 'ruby/thread.h' ) or
|
18
|
+
abort "Your Ruby is too old!"
|
19
|
+
|
20
|
+
have_func( 'zyre_set_name', 'zyre.h' )
|
21
|
+
have_func( 'zyre_set_silent_timeout', 'zyre.h' )
|
22
|
+
|
23
|
+
create_header()
|
24
|
+
create_makefile( 'zyre_ext' )
|
25
|
+
|
data/ext/zyre_ext/node.c
ADDED
@@ -0,0 +1,850 @@
|
|
1
|
+
/*
|
2
|
+
* node.c - A node in a Zyre cluster
|
3
|
+
* $Id$
|
4
|
+
*
|
5
|
+
* Authors:
|
6
|
+
* * Michael Granger <ged@FaerieMUD.org>
|
7
|
+
*
|
8
|
+
*/
|
9
|
+
|
10
|
+
#include "zyre_ext.h"
|
11
|
+
|
12
|
+
|
13
|
+
VALUE rzyre_cZyreNode;
|
14
|
+
|
15
|
+
static void rzyre_node_free( void *ptr );
|
16
|
+
|
17
|
+
static const rb_data_type_t rzyre_node_t = {
|
18
|
+
"Zyre::Node",
|
19
|
+
{
|
20
|
+
NULL,
|
21
|
+
rzyre_node_free
|
22
|
+
},
|
23
|
+
0,
|
24
|
+
0,
|
25
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
26
|
+
};
|
27
|
+
|
28
|
+
|
29
|
+
/*
|
30
|
+
* Free function
|
31
|
+
*/
|
32
|
+
static void
|
33
|
+
rzyre_node_free( void *ptr )
|
34
|
+
{
|
35
|
+
if ( ptr ) {
|
36
|
+
zyre_destroy( (zyre_t **)&ptr );
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
|
41
|
+
/*
|
42
|
+
* Alloc function
|
43
|
+
*/
|
44
|
+
static VALUE
|
45
|
+
rzyre_node_alloc( VALUE klass )
|
46
|
+
{
|
47
|
+
return TypedData_Wrap_Struct( klass, &rzyre_node_t, NULL );
|
48
|
+
}
|
49
|
+
|
50
|
+
|
51
|
+
/*
|
52
|
+
* Fetch the data pointer and check it for sanity.
|
53
|
+
*/
|
54
|
+
inline zyre_t *
|
55
|
+
rzyre_get_node( VALUE self )
|
56
|
+
{
|
57
|
+
if ( !IsZyreNode(self) ) {
|
58
|
+
rb_raise( rb_eTypeError, "wrong argument type %s (expected Zyre::Node)",
|
59
|
+
rb_class2name(CLASS_OF( self )) );
|
60
|
+
}
|
61
|
+
|
62
|
+
return DATA_PTR( self );
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
/*
|
67
|
+
* call-seq:
|
68
|
+
* Zyre::Node.new -> node
|
69
|
+
* Zyre::Node.new( name ) -> node
|
70
|
+
*
|
71
|
+
* Create a new (unstarted) Zyre node. If the +name+ is not given, Zyre generates a
|
72
|
+
* randomized node name from the UUID
|
73
|
+
*
|
74
|
+
*/
|
75
|
+
static VALUE
|
76
|
+
rzyre_node_initialize( int argc, VALUE *argv, VALUE self )
|
77
|
+
{
|
78
|
+
zyre_t *ptr;
|
79
|
+
VALUE name;
|
80
|
+
char *name_str = NULL;
|
81
|
+
|
82
|
+
rb_scan_args( argc, argv, "01", &name );
|
83
|
+
|
84
|
+
if ( !NIL_P(name) ) {
|
85
|
+
name_str = StringValueCStr( name );
|
86
|
+
}
|
87
|
+
|
88
|
+
TypedData_Get_Struct( self, zyre_t, &rzyre_node_t, ptr );
|
89
|
+
if ( !ptr ) {
|
90
|
+
RTYPEDDATA_DATA( self ) = ptr = zyre_new( name_str );
|
91
|
+
assert( ptr );
|
92
|
+
}
|
93
|
+
|
94
|
+
return self;
|
95
|
+
}
|
96
|
+
|
97
|
+
|
98
|
+
/*
|
99
|
+
* call-seq:
|
100
|
+
* node.uuid -> str
|
101
|
+
*
|
102
|
+
* Return the node's UUID as a String.
|
103
|
+
*
|
104
|
+
*/
|
105
|
+
static VALUE
|
106
|
+
rzyre_node_uuid( VALUE self )
|
107
|
+
{
|
108
|
+
zyre_t *ptr = rzyre_get_node( self );
|
109
|
+
const char *uuid_str = zyre_uuid( ptr );
|
110
|
+
VALUE uuid = rb_str_new2( uuid_str );
|
111
|
+
|
112
|
+
return rb_str_freeze( uuid );
|
113
|
+
}
|
114
|
+
|
115
|
+
|
116
|
+
/*
|
117
|
+
* call-seq:
|
118
|
+
* node.name -> str
|
119
|
+
*
|
120
|
+
* Return the node name.
|
121
|
+
*
|
122
|
+
*/
|
123
|
+
static VALUE
|
124
|
+
rzyre_node_name( VALUE self )
|
125
|
+
{
|
126
|
+
zyre_t *ptr = rzyre_get_node( self );
|
127
|
+
const char *name_str = zyre_name( ptr );
|
128
|
+
VALUE name = rb_str_new2( name_str );
|
129
|
+
|
130
|
+
return rb_str_freeze( name );
|
131
|
+
}
|
132
|
+
|
133
|
+
|
134
|
+
/*
|
135
|
+
* call-seq:
|
136
|
+
* node.name = str
|
137
|
+
*
|
138
|
+
* Set the public name of this node overriding the default. The name is
|
139
|
+
* provided during discovery and come in each ENTER message.
|
140
|
+
*
|
141
|
+
*/
|
142
|
+
static VALUE
|
143
|
+
rzyre_node_name_eq( VALUE self, VALUE new_name )
|
144
|
+
{
|
145
|
+
zyre_t *ptr = rzyre_get_node( self );
|
146
|
+
const char *name_str = StringValueCStr( new_name );
|
147
|
+
|
148
|
+
zyre_set_name( ptr, name_str );
|
149
|
+
|
150
|
+
return Qtrue;
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
/*
|
155
|
+
* call-seq:
|
156
|
+
* node.port = integer
|
157
|
+
*
|
158
|
+
* Set UDP beacon discovery port. Defaults to 5670. This call overrides
|
159
|
+
* the default so that you can create independent clusters on the same network, for
|
160
|
+
* e.g. development vs. production. Has no effect after #start.
|
161
|
+
*
|
162
|
+
*/
|
163
|
+
static VALUE
|
164
|
+
rzyre_node_port_eq( VALUE self, VALUE new_port )
|
165
|
+
{
|
166
|
+
zyre_t *ptr = rzyre_get_node( self );
|
167
|
+
int port_nbr = FIX2INT( new_port );
|
168
|
+
|
169
|
+
zyre_set_port( ptr, port_nbr );
|
170
|
+
|
171
|
+
return Qtrue;
|
172
|
+
}
|
173
|
+
|
174
|
+
|
175
|
+
/*
|
176
|
+
* call-seq:
|
177
|
+
* node.evasive_timeout = milliseconds
|
178
|
+
*
|
179
|
+
* Set the peer evasiveness timeout in milliseconds. Default is 5000.
|
180
|
+
* This can be tuned in order to deal with expected network conditions
|
181
|
+
* and the response time expected by the application. This is tied to
|
182
|
+
* the beacon interval and rate of messages received.
|
183
|
+
*
|
184
|
+
*/
|
185
|
+
static VALUE
|
186
|
+
rzyre_node_evasive_timeout_eq( VALUE self, VALUE timeout )
|
187
|
+
{
|
188
|
+
zyre_t *ptr = rzyre_get_node( self );
|
189
|
+
int timeout_ms = FIX2INT( timeout );
|
190
|
+
|
191
|
+
zyre_set_evasive_timeout( ptr, timeout_ms );
|
192
|
+
|
193
|
+
return Qtrue;
|
194
|
+
}
|
195
|
+
|
196
|
+
|
197
|
+
/*
|
198
|
+
* call-seq:
|
199
|
+
* node.silent_timeout = milliseconds
|
200
|
+
*
|
201
|
+
* Set the peer silence timeout, in milliseconds. Default is 5000.
|
202
|
+
* This can be tuned in order to deal with expected network conditions
|
203
|
+
* and the response time expected by the application. This is tied to
|
204
|
+
* the beacon interval and rate of messages received.
|
205
|
+
* Silence is triggered one second after the timeout if peer has not
|
206
|
+
* answered ping and has not sent any message.
|
207
|
+
*
|
208
|
+
* NB: this is currently redundant with the evasiveness timeout. Both
|
209
|
+
* affect the same timeout value.
|
210
|
+
*
|
211
|
+
*/
|
212
|
+
#ifdef HAVE_ZYRE_SET_SILENT_TIMEOUT
|
213
|
+
static VALUE
|
214
|
+
rzyre_node_silent_timeout_eq( VALUE self, VALUE timeout )
|
215
|
+
{
|
216
|
+
zyre_t *ptr = rzyre_get_node( self );
|
217
|
+
int timeout_ms = FIX2INT( timeout );
|
218
|
+
|
219
|
+
zyre_set_silent_timeout( ptr, timeout_ms );
|
220
|
+
|
221
|
+
return Qtrue;
|
222
|
+
}
|
223
|
+
#endif // HAVE_ZYRE_SET_SILENT_TIMEOUT
|
224
|
+
|
225
|
+
|
226
|
+
/*
|
227
|
+
* call-seq:
|
228
|
+
* node.expired_timeout = milliseconds
|
229
|
+
*
|
230
|
+
* Set the peer expiration timeout, in milliseconds. Default is 30000.
|
231
|
+
* This can be tuned in order to deal with expected network conditions
|
232
|
+
* and the response time expected by the application. This is tied to
|
233
|
+
* the beacon interval and rate of messages received.
|
234
|
+
*
|
235
|
+
*/
|
236
|
+
static VALUE
|
237
|
+
rzyre_node_expired_timeout_eq( VALUE self, VALUE timeout )
|
238
|
+
{
|
239
|
+
zyre_t *ptr = rzyre_get_node( self );
|
240
|
+
int timeout_ms = FIX2INT( timeout );
|
241
|
+
|
242
|
+
zyre_set_expired_timeout( ptr, timeout_ms );
|
243
|
+
|
244
|
+
return Qtrue;
|
245
|
+
}
|
246
|
+
|
247
|
+
|
248
|
+
/*
|
249
|
+
* call-seq:
|
250
|
+
* node.interval = milliseconds
|
251
|
+
*
|
252
|
+
* Set UDP beacon discovery interval in milliseconds. Default is instant
|
253
|
+
* beacon exploration followed by pinging every 1000 msecs.
|
254
|
+
*
|
255
|
+
*/
|
256
|
+
static VALUE
|
257
|
+
rzyre_node_interval_eq( VALUE self, VALUE interval )
|
258
|
+
{
|
259
|
+
zyre_t *ptr = rzyre_get_node( self );
|
260
|
+
size_t interval_ms = FIX2INT( interval );
|
261
|
+
|
262
|
+
zyre_set_interval( ptr, interval_ms );
|
263
|
+
|
264
|
+
return Qtrue;
|
265
|
+
}
|
266
|
+
|
267
|
+
|
268
|
+
/*
|
269
|
+
* call-seq:
|
270
|
+
* node.interface = string
|
271
|
+
*
|
272
|
+
* Set network interface for UDP beacons. If you do not set this, CZMQ will
|
273
|
+
* choose an interface for you. On boxes with several interfaces you should
|
274
|
+
* specify which one you want to use, or strange things can happen.
|
275
|
+
*
|
276
|
+
*/
|
277
|
+
static VALUE
|
278
|
+
rzyre_node_interface_eq( VALUE self, VALUE interface )
|
279
|
+
{
|
280
|
+
zyre_t *ptr = rzyre_get_node( self );
|
281
|
+
const char *interface_str = StringValueCStr( interface );
|
282
|
+
|
283
|
+
zyre_set_interface( ptr, interface_str );
|
284
|
+
|
285
|
+
return Qtrue;
|
286
|
+
}
|
287
|
+
|
288
|
+
|
289
|
+
/*
|
290
|
+
* call-seq:
|
291
|
+
* node.endpoint = string
|
292
|
+
*
|
293
|
+
* By default, Zyre binds to an ephemeral TCP port and broadcasts the local
|
294
|
+
* host name using UDP beaconing. When you call this method, Zyre will use
|
295
|
+
* gossip discovery instead of UDP beaconing. You MUST set up the gossip
|
296
|
+
* service separately using #gossip_bind and #gossip_connect. Note that the
|
297
|
+
* endpoint MUST be valid for both bind and connect operations. You can use
|
298
|
+
* `inproc://`, `ipc://`, or `tcp://` transports (for `tcp://`, use an IP
|
299
|
+
* address that is meaningful to remote as well as local nodes). Returns
|
300
|
+
* +true+ if the bind was successful.
|
301
|
+
*
|
302
|
+
*/
|
303
|
+
static VALUE
|
304
|
+
rzyre_node_endpoint_eq( VALUE self, VALUE endpoint )
|
305
|
+
{
|
306
|
+
zyre_t *ptr = rzyre_get_node( self );
|
307
|
+
const char *endpoint_str = StringValueCStr( endpoint );
|
308
|
+
int res;
|
309
|
+
|
310
|
+
res = zyre_set_endpoint( ptr, "%s", endpoint_str );
|
311
|
+
|
312
|
+
if ( res == 0 ) return Qtrue;
|
313
|
+
return Qfalse;
|
314
|
+
}
|
315
|
+
|
316
|
+
|
317
|
+
/*
|
318
|
+
* call-seq:
|
319
|
+
* node.endpoint -> str
|
320
|
+
*
|
321
|
+
* Return the endpoint being used by the Node if there is one.
|
322
|
+
*
|
323
|
+
*/
|
324
|
+
static VALUE
|
325
|
+
rzyre_node_endpoint( VALUE self )
|
326
|
+
{
|
327
|
+
zyre_t *ptr = rzyre_get_node( self );
|
328
|
+
zsock_t *sock = zyre_socket( ptr );
|
329
|
+
const char *endpoint_str = zsock_endpoint( sock );
|
330
|
+
|
331
|
+
return rb_str_new2( endpoint_str );
|
332
|
+
}
|
333
|
+
|
334
|
+
|
335
|
+
/*
|
336
|
+
* call-seq:
|
337
|
+
* node.verbose!
|
338
|
+
*
|
339
|
+
* Set verbose mode; this tells the node to log all traffic as well as
|
340
|
+
* all major events.
|
341
|
+
*
|
342
|
+
*/
|
343
|
+
static VALUE
|
344
|
+
rzyre_node_verbose_bang( VALUE self )
|
345
|
+
{
|
346
|
+
zyre_t *ptr = rzyre_get_node( self );
|
347
|
+
|
348
|
+
zyre_set_verbose( ptr );
|
349
|
+
|
350
|
+
return Qtrue;
|
351
|
+
}
|
352
|
+
|
353
|
+
|
354
|
+
/*
|
355
|
+
* call-seq:
|
356
|
+
* node.set_header( name, value )
|
357
|
+
*
|
358
|
+
* Set node header; these are provided to other nodes during discovery
|
359
|
+
* and come in each `ENTER` message.
|
360
|
+
*
|
361
|
+
*/
|
362
|
+
static VALUE
|
363
|
+
rzyre_node_set_header( VALUE self, VALUE name, VALUE value )
|
364
|
+
{
|
365
|
+
zyre_t *ptr = rzyre_get_node( self );
|
366
|
+
const char *name_str = StringValueCStr( name );
|
367
|
+
const char *value_str = StringValueCStr( value );
|
368
|
+
|
369
|
+
rzyre_log_obj( self, "debug", "Setting header `%s` to `%s`", name_str, value_str );
|
370
|
+
zyre_set_header( ptr, name_str, "%s", value_str );
|
371
|
+
|
372
|
+
return Qtrue;
|
373
|
+
}
|
374
|
+
|
375
|
+
|
376
|
+
/*
|
377
|
+
* call-seq:
|
378
|
+
* node.gossip_bind( endpoint )
|
379
|
+
*
|
380
|
+
* Set-up gossip discovery of other nodes. At least one node in the cluster
|
381
|
+
* must bind to a well-known gossip endpoint, so other nodes can connect to
|
382
|
+
* it. Note that gossip endpoints are completely distinct from Zyre node
|
383
|
+
* endpoints, and should not overlap (they can use the same transport).
|
384
|
+
*
|
385
|
+
*/
|
386
|
+
static VALUE
|
387
|
+
rzyre_node_gossip_bind( VALUE self, VALUE endpoint )
|
388
|
+
{
|
389
|
+
zyre_t *ptr = rzyre_get_node( self );
|
390
|
+
const char *endpoint_str = StringValueCStr( endpoint );
|
391
|
+
|
392
|
+
assert( endpoint_str );
|
393
|
+
rzyre_log_obj( self, "debug", "Binding to gossip endpoint %s.", endpoint_str );
|
394
|
+
zyre_gossip_bind( ptr, "%s", endpoint_str );
|
395
|
+
|
396
|
+
return Qtrue;
|
397
|
+
}
|
398
|
+
|
399
|
+
|
400
|
+
/*
|
401
|
+
* call-seq:
|
402
|
+
* node.gossip_connect( endpoint )
|
403
|
+
*
|
404
|
+
* Set-up gossip discovery of other nodes. A node may connect to multiple
|
405
|
+
* other nodes, for redundancy paths. For details of the gossip network
|
406
|
+
* design, see the CZMQ zgossip class.
|
407
|
+
*
|
408
|
+
*/
|
409
|
+
static VALUE
|
410
|
+
rzyre_node_gossip_connect( VALUE self, VALUE endpoint )
|
411
|
+
{
|
412
|
+
zyre_t *ptr = rzyre_get_node( self );
|
413
|
+
const char *endpoint_str = StringValueCStr( endpoint );
|
414
|
+
|
415
|
+
assert( endpoint_str );
|
416
|
+
rzyre_log_obj( self, "debug", "Connecting to gossip endpoint %s.", endpoint_str );
|
417
|
+
zyre_gossip_connect( ptr, "%s", endpoint_str );
|
418
|
+
|
419
|
+
return Qtrue;
|
420
|
+
}
|
421
|
+
|
422
|
+
|
423
|
+
/*
|
424
|
+
* call-seq:
|
425
|
+
* node.start -> bool
|
426
|
+
*
|
427
|
+
* Start node, after setting header values. When you start a node it
|
428
|
+
* begins discovery and connection. Returns +true+ if the node was started
|
429
|
+
* successfully.
|
430
|
+
*
|
431
|
+
*/
|
432
|
+
static VALUE
|
433
|
+
rzyre_node_start( VALUE self )
|
434
|
+
{
|
435
|
+
zyre_t *ptr = rzyre_get_node( self );
|
436
|
+
int res;
|
437
|
+
|
438
|
+
rzyre_log_obj( self, "debug", "Starting." );
|
439
|
+
res = zyre_start( ptr );
|
440
|
+
|
441
|
+
if ( res == 0 ) return Qtrue;
|
442
|
+
return Qfalse;
|
443
|
+
}
|
444
|
+
|
445
|
+
|
446
|
+
/*
|
447
|
+
* call-seq:
|
448
|
+
* node.stop
|
449
|
+
*
|
450
|
+
* Stop node; this signals to other peers that this node will go away.
|
451
|
+
* This is polite; however you can also just destroy the node without
|
452
|
+
* stopping it.
|
453
|
+
*
|
454
|
+
*/
|
455
|
+
static VALUE
|
456
|
+
rzyre_node_stop( VALUE self )
|
457
|
+
{
|
458
|
+
zyre_t *ptr = rzyre_get_node( self );
|
459
|
+
|
460
|
+
assert( ptr );
|
461
|
+
rzyre_log_obj( self, "debug", "Stopping." );
|
462
|
+
zyre_stop( ptr );
|
463
|
+
|
464
|
+
return Qtrue;
|
465
|
+
}
|
466
|
+
|
467
|
+
|
468
|
+
/*
|
469
|
+
* call-seq:
|
470
|
+
* node.join( group_name ) -> int
|
471
|
+
*
|
472
|
+
* Join a named group; after joining a group you can send messages to
|
473
|
+
* the group and all Zyre nodes in that group will receive them.
|
474
|
+
*
|
475
|
+
*/
|
476
|
+
static VALUE
|
477
|
+
rzyre_node_join( VALUE self, VALUE group )
|
478
|
+
{
|
479
|
+
zyre_t *ptr = rzyre_get_node( self );
|
480
|
+
const char *group_str = StringValueCStr( group );
|
481
|
+
int res;
|
482
|
+
|
483
|
+
rzyre_log_obj( self, "debug", "Joining group %s.", group_str );
|
484
|
+
res = zyre_join( ptr, group_str );
|
485
|
+
|
486
|
+
return INT2FIX( res );
|
487
|
+
}
|
488
|
+
|
489
|
+
|
490
|
+
/*
|
491
|
+
* call-seq:
|
492
|
+
* node.leave( group_name ) -> int
|
493
|
+
*
|
494
|
+
* Leave a group.
|
495
|
+
*
|
496
|
+
*/
|
497
|
+
static VALUE
|
498
|
+
rzyre_node_leave( VALUE self, VALUE group )
|
499
|
+
{
|
500
|
+
zyre_t *ptr = rzyre_get_node( self );
|
501
|
+
const char *group_str = StringValueCStr( group );
|
502
|
+
int res;
|
503
|
+
|
504
|
+
rzyre_log_obj( self, "debug", "Leaving group %s.", group_str );
|
505
|
+
res = zyre_leave( ptr, group_str );
|
506
|
+
|
507
|
+
return INT2FIX( res );
|
508
|
+
}
|
509
|
+
|
510
|
+
|
511
|
+
/*
|
512
|
+
* call-seq:
|
513
|
+
* node.recv -> zyre_event
|
514
|
+
*
|
515
|
+
* Receive the next event from the network; the message may be a control
|
516
|
+
* message (ENTER, EXIT, JOIN, LEAVE) or data (WHISPER, SHOUT).
|
517
|
+
* Returns a Zyre::Event.
|
518
|
+
*
|
519
|
+
*/
|
520
|
+
static VALUE
|
521
|
+
rzyre_node_recv( VALUE self )
|
522
|
+
{
|
523
|
+
return rb_funcall( rzyre_cZyreEvent, rb_intern("from_node"), 1, self );
|
524
|
+
}
|
525
|
+
|
526
|
+
|
527
|
+
/*
|
528
|
+
* call-seq:
|
529
|
+
* node.whisper( peer_uuid, message ) -> int
|
530
|
+
*
|
531
|
+
* Send a +message+ to a single +peer+ specified as a UUID string.
|
532
|
+
*
|
533
|
+
*/
|
534
|
+
static VALUE
|
535
|
+
rzyre_node_whisper( VALUE self, VALUE peer_uuid, VALUE msg )
|
536
|
+
{
|
537
|
+
zyre_t *ptr = rzyre_get_node( self );
|
538
|
+
const char *peer_str = StringValueCStr( peer_uuid ),
|
539
|
+
*msg_str = StringValueCStr( msg );
|
540
|
+
int rval;
|
541
|
+
|
542
|
+
assert( peer_str );
|
543
|
+
assert( msg_str );
|
544
|
+
|
545
|
+
rval = zyre_whispers( ptr, peer_str, "%s", msg_str );
|
546
|
+
|
547
|
+
return rval ? Qtrue : Qfalse;
|
548
|
+
}
|
549
|
+
|
550
|
+
|
551
|
+
/*
|
552
|
+
* call-seq:
|
553
|
+
* node.shout( group, message ) -> int
|
554
|
+
*
|
555
|
+
* Send +message+ to a named +group+.
|
556
|
+
*
|
557
|
+
*/
|
558
|
+
static VALUE
|
559
|
+
rzyre_node_shout( VALUE self, VALUE group, VALUE msg )
|
560
|
+
{
|
561
|
+
zyre_t *ptr = rzyre_get_node( self );
|
562
|
+
const char *group_str = StringValueCStr( group ),
|
563
|
+
*msg_str = StringValueCStr( msg );
|
564
|
+
int rval;
|
565
|
+
|
566
|
+
assert( group_str );
|
567
|
+
assert( msg_str );
|
568
|
+
|
569
|
+
rval = zyre_shouts( ptr, group_str, "%s", msg_str );
|
570
|
+
|
571
|
+
return rval ? Qtrue : Qfalse;
|
572
|
+
}
|
573
|
+
|
574
|
+
|
575
|
+
/*
|
576
|
+
* call-seq:
|
577
|
+
* node.peers -> array
|
578
|
+
*
|
579
|
+
* Return an Array of current peer UUIDs.
|
580
|
+
*
|
581
|
+
*/
|
582
|
+
static VALUE
|
583
|
+
rzyre_node_peers( VALUE self )
|
584
|
+
{
|
585
|
+
zyre_t *ptr;
|
586
|
+
zlist_t *peers;
|
587
|
+
VALUE rary = rb_ary_new();
|
588
|
+
char *item = NULL;
|
589
|
+
|
590
|
+
ptr = rzyre_get_node( self );
|
591
|
+
assert( ptr );
|
592
|
+
|
593
|
+
peers = zyre_peers( ptr );
|
594
|
+
assert( peers );
|
595
|
+
|
596
|
+
item = zlist_first( peers );
|
597
|
+
while ( item ) {
|
598
|
+
rb_ary_push( rary, rb_str_new2(item) );
|
599
|
+
item = zlist_next( peers );
|
600
|
+
}
|
601
|
+
|
602
|
+
zlist_destroy( &peers );
|
603
|
+
return rary;
|
604
|
+
}
|
605
|
+
|
606
|
+
|
607
|
+
/*
|
608
|
+
* call-seq:
|
609
|
+
* node.peers_by_group( group ) -> array
|
610
|
+
*
|
611
|
+
* Return an Array of the current peers in the specified +group+.
|
612
|
+
*
|
613
|
+
*/
|
614
|
+
static VALUE
|
615
|
+
rzyre_node_peers_by_group( VALUE self, VALUE group )
|
616
|
+
{
|
617
|
+
zyre_t *ptr;
|
618
|
+
const char *group_str = StringValueCStr( group );
|
619
|
+
zlist_t *peers;
|
620
|
+
VALUE rary = rb_ary_new();
|
621
|
+
char *item = NULL;
|
622
|
+
|
623
|
+
ptr = rzyre_get_node( self );
|
624
|
+
assert( ptr );
|
625
|
+
|
626
|
+
peers = zyre_peers_by_group( ptr, group_str );
|
627
|
+
assert( peers );
|
628
|
+
|
629
|
+
item = zlist_first( peers );
|
630
|
+
while ( item ) {
|
631
|
+
rb_ary_push( rary, rb_str_new2(item) );
|
632
|
+
item = zlist_next( peers );
|
633
|
+
}
|
634
|
+
|
635
|
+
zlist_destroy( &peers );
|
636
|
+
return rary;
|
637
|
+
}
|
638
|
+
|
639
|
+
|
640
|
+
/*
|
641
|
+
* call-seq:
|
642
|
+
* node.own_groups -> array
|
643
|
+
*
|
644
|
+
* Return an Array of the names of the receiving node's current groups.
|
645
|
+
*
|
646
|
+
*/
|
647
|
+
static VALUE
|
648
|
+
rzyre_node_own_groups( VALUE self )
|
649
|
+
{
|
650
|
+
zyre_t *ptr = rzyre_get_node( self );
|
651
|
+
zlist_t *groups = zyre_own_groups( ptr );
|
652
|
+
VALUE rary = rb_ary_new();
|
653
|
+
char *item = NULL;
|
654
|
+
|
655
|
+
assert( groups );
|
656
|
+
|
657
|
+
item = zlist_first( groups );
|
658
|
+
while ( item ) {
|
659
|
+
rb_ary_push( rary, rb_str_new2(item) );
|
660
|
+
item = zlist_next( groups );
|
661
|
+
}
|
662
|
+
|
663
|
+
zlist_destroy( &groups );
|
664
|
+
return rary;
|
665
|
+
}
|
666
|
+
|
667
|
+
|
668
|
+
/*
|
669
|
+
* call-seq:
|
670
|
+
* node.peer_groups -> array
|
671
|
+
*
|
672
|
+
* Return an Array of the names of groups known through connected peers.
|
673
|
+
*
|
674
|
+
*/
|
675
|
+
static VALUE
|
676
|
+
rzyre_node_peer_groups( VALUE self )
|
677
|
+
{
|
678
|
+
zyre_t *ptr = rzyre_get_node( self );
|
679
|
+
zlist_t *groups = zyre_peer_groups( ptr );
|
680
|
+
VALUE rary = rb_ary_new();
|
681
|
+
char *item = NULL;
|
682
|
+
|
683
|
+
assert( groups );
|
684
|
+
|
685
|
+
item = zlist_first( groups );
|
686
|
+
while ( item ) {
|
687
|
+
rb_ary_push( rary, rb_str_new2(item) );
|
688
|
+
item = zlist_next( groups );
|
689
|
+
}
|
690
|
+
|
691
|
+
zlist_destroy( &groups );
|
692
|
+
return rary;
|
693
|
+
}
|
694
|
+
|
695
|
+
|
696
|
+
/*
|
697
|
+
* call-seq:
|
698
|
+
* node.peer_address( peer_uuid ) -> str
|
699
|
+
*
|
700
|
+
* Return the endpoint of a connected +peer+.
|
701
|
+
* Returns nil if peer does not exist.
|
702
|
+
*
|
703
|
+
*/
|
704
|
+
static VALUE
|
705
|
+
rzyre_node_peer_address( VALUE self, VALUE peer_uuid )
|
706
|
+
{
|
707
|
+
zyre_t *ptr = rzyre_get_node( self );
|
708
|
+
const char *peer = StringValueCStr( peer_uuid );
|
709
|
+
char *address = zyre_peer_address( ptr, peer );
|
710
|
+
VALUE rval = Qnil;
|
711
|
+
|
712
|
+
if ( strnlen(address, BUFSIZ) ) {
|
713
|
+
rval = rb_str_new2( address );
|
714
|
+
}
|
715
|
+
|
716
|
+
free( address );
|
717
|
+
return rval;
|
718
|
+
}
|
719
|
+
|
720
|
+
|
721
|
+
/*
|
722
|
+
* call-seq:
|
723
|
+
* node.peer_header_value( peer_id, header_name ) -> str
|
724
|
+
*
|
725
|
+
* Return the value of a header of a conected peer. Returns nil if
|
726
|
+
* peer or key doesn't exist.
|
727
|
+
*
|
728
|
+
*/
|
729
|
+
static VALUE
|
730
|
+
rzyre_node_peer_header_value( VALUE self, VALUE peer_id, VALUE header_name )
|
731
|
+
{
|
732
|
+
zyre_t *ptr = rzyre_get_node( self );
|
733
|
+
const char *peer_id_str = StringValueCStr( peer_id );
|
734
|
+
const char *header_name_str = StringValueCStr( header_name );
|
735
|
+
char *res;
|
736
|
+
VALUE rval = Qnil;
|
737
|
+
|
738
|
+
res = zyre_peer_header_value( ptr, peer_id_str, header_name_str );
|
739
|
+
|
740
|
+
// TODO: Encoding + frozen
|
741
|
+
if ( res ) {
|
742
|
+
rval = rb_str_new2( res );
|
743
|
+
xfree( res );
|
744
|
+
}
|
745
|
+
|
746
|
+
return rval;
|
747
|
+
}
|
748
|
+
|
749
|
+
|
750
|
+
/*
|
751
|
+
* call-seq:
|
752
|
+
* node.print
|
753
|
+
*
|
754
|
+
* Print zyre node information to stdout.
|
755
|
+
*
|
756
|
+
*/
|
757
|
+
static VALUE
|
758
|
+
rzyre_node_print( VALUE self )
|
759
|
+
{
|
760
|
+
zyre_t *ptr = rzyre_get_node( self );
|
761
|
+
|
762
|
+
zyre_print( ptr );
|
763
|
+
|
764
|
+
return Qtrue;
|
765
|
+
}
|
766
|
+
|
767
|
+
|
768
|
+
/*
|
769
|
+
* Node class init
|
770
|
+
*/
|
771
|
+
void
|
772
|
+
rzyre_init_node( void )
|
773
|
+
{
|
774
|
+
|
775
|
+
#ifdef FOR_RDOC
|
776
|
+
rb_cData = rb_define_class( "Data" );
|
777
|
+
rzyre_mZyre = rb_define_module( "Zyre" );
|
778
|
+
#endif
|
779
|
+
|
780
|
+
/*
|
781
|
+
* Document-class: Zyre::Node
|
782
|
+
*
|
783
|
+
* A node in a Zyre cluster.
|
784
|
+
*
|
785
|
+
* Refs:
|
786
|
+
* - https://github.com/zeromq/zyre#readme
|
787
|
+
*/
|
788
|
+
rzyre_cZyreNode = rb_define_class_under( rzyre_mZyre, "Node", rb_cData );
|
789
|
+
|
790
|
+
rb_define_alloc_func( rzyre_cZyreNode, rzyre_node_alloc );
|
791
|
+
|
792
|
+
rb_define_protected_method( rzyre_cZyreNode, "initialize", rzyre_node_initialize, -1 );
|
793
|
+
|
794
|
+
rb_define_method( rzyre_cZyreNode, "uuid", rzyre_node_uuid, 0 );
|
795
|
+
rb_define_method( rzyre_cZyreNode, "name", rzyre_node_name, 0 );
|
796
|
+
|
797
|
+
rb_define_method( rzyre_cZyreNode, "name=", rzyre_node_name_eq, 1 );
|
798
|
+
rb_define_method( rzyre_cZyreNode, "port=", rzyre_node_port_eq, 1 );
|
799
|
+
rb_define_method( rzyre_cZyreNode, "evasive_timeout=", rzyre_node_evasive_timeout_eq, 1 );
|
800
|
+
#ifdef HAVE_ZYRE_SET_SILENT_TIMEOUT
|
801
|
+
rb_define_method( rzyre_cZyreNode, "silent_timeout=", rzyre_node_silent_timeout_eq, 1 );
|
802
|
+
#endif
|
803
|
+
rb_define_method( rzyre_cZyreNode, "expired_timeout=", rzyre_node_expired_timeout_eq, 1 );
|
804
|
+
rb_define_method( rzyre_cZyreNode, "interval=", rzyre_node_interval_eq, 1 );
|
805
|
+
rb_define_method( rzyre_cZyreNode, "interface=", rzyre_node_interface_eq, 1 );
|
806
|
+
rb_define_method( rzyre_cZyreNode, "endpoint=", rzyre_node_endpoint_eq, 1 );
|
807
|
+
rb_define_method( rzyre_cZyreNode, "endpoint", rzyre_node_endpoint, 0 );
|
808
|
+
|
809
|
+
rb_define_method( rzyre_cZyreNode, "set_header", rzyre_node_set_header, 2 );
|
810
|
+
|
811
|
+
rb_define_method( rzyre_cZyreNode, "gossip_bind", rzyre_node_gossip_bind, 1 );
|
812
|
+
rb_define_method( rzyre_cZyreNode, "gossip_connect", rzyre_node_gossip_connect, 1 );
|
813
|
+
|
814
|
+
rb_define_method( rzyre_cZyreNode, "start", rzyre_node_start, 0 );
|
815
|
+
rb_define_method( rzyre_cZyreNode, "stop", rzyre_node_stop, 0 );
|
816
|
+
|
817
|
+
rb_define_method( rzyre_cZyreNode, "join", rzyre_node_join, 1 );
|
818
|
+
rb_define_method( rzyre_cZyreNode, "leave", rzyre_node_leave, 1 );
|
819
|
+
|
820
|
+
rb_define_method( rzyre_cZyreNode, "recv", rzyre_node_recv, 0 );
|
821
|
+
|
822
|
+
rb_define_method( rzyre_cZyreNode, "whisper", rzyre_node_whisper, 2 );
|
823
|
+
rb_define_method( rzyre_cZyreNode, "shout", rzyre_node_shout, 2 );
|
824
|
+
|
825
|
+
rb_define_method( rzyre_cZyreNode, "peers", rzyre_node_peers, 0 );
|
826
|
+
rb_define_method( rzyre_cZyreNode, "peers_by_group", rzyre_node_peers_by_group, 1 );
|
827
|
+
rb_define_method( rzyre_cZyreNode, "own_groups", rzyre_node_own_groups, 0 );
|
828
|
+
rb_define_method( rzyre_cZyreNode, "peer_groups", rzyre_node_peer_groups, 0 );
|
829
|
+
rb_define_method( rzyre_cZyreNode, "peer_address", rzyre_node_peer_address, 1 );
|
830
|
+
rb_define_method( rzyre_cZyreNode, "peer_header_value", rzyre_node_peer_header_value, 2 );
|
831
|
+
|
832
|
+
rb_define_method( rzyre_cZyreNode, "verbose!", rzyre_node_verbose_bang, 0 );
|
833
|
+
rb_define_method( rzyre_cZyreNode, "print", rzyre_node_print, 0 );
|
834
|
+
|
835
|
+
#ifdef ZYRE_BUILD_DRAFT_API
|
836
|
+
|
837
|
+
rb_define_method( rzyre_cZyreNode, "set_beacon_peer_port", rzyre_node_set_beacon_peer_port, -1 );
|
838
|
+
rb_define_method( rzyre_cZyreNode, "set_contest_in_group", rzyre_node_set_contest_in_group, -1 );
|
839
|
+
rb_define_method( rzyre_cZyreNode, "set_advertised_endpoint", rzyre_node_set_advertised_endpoint, -1 );
|
840
|
+
rb_define_method( rzyre_cZyreNode, "set_zcert", rzyre_node_set_zcert, -1 );
|
841
|
+
rb_define_method( rzyre_cZyreNode, "set_zap_domain", rzyre_node_set_zap_domain, -1 );
|
842
|
+
rb_define_method( rzyre_cZyreNode, "gossip_connect_curve", rzyre_node_gossip_connect_curve, -1 );
|
843
|
+
rb_define_method( rzyre_cZyreNode, "gossip_unpublish", rzyre_node_gossip_unpublish, -1 );
|
844
|
+
rb_define_method( rzyre_cZyreNode, "require_peer", rzyre_node_require_peer, -1 );
|
845
|
+
|
846
|
+
#endif // ZYRE_BUILD_DRAFT_API
|
847
|
+
|
848
|
+
rb_require( "zyre/node" );
|
849
|
+
}
|
850
|
+
|