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.
@@ -0,0 +1,272 @@
1
+ /*
2
+ * poller.c - A poller for doing evented IO on one or more Zyre nodes
3
+ * $Id$
4
+ *
5
+ * Authors:
6
+ * * Michael Granger <ged@FaerieMUD.org>
7
+ *
8
+ */
9
+
10
+ #include "zyre_ext.h"
11
+
12
+ VALUE rzyre_cZyrePoller;
13
+
14
+
15
+ static void rzyre_poller_free( void *ptr );
16
+
17
+ static const rb_data_type_t rzyre_poller_t = {
18
+ "Zyre::Poller",
19
+ {
20
+ NULL,
21
+ rzyre_poller_free
22
+ },
23
+ 0,
24
+ 0,
25
+ RUBY_TYPED_FREE_IMMEDIATELY,
26
+ };
27
+
28
+
29
+ /*
30
+ * Free function
31
+ */
32
+ static void
33
+ rzyre_poller_free( void *ptr )
34
+ {
35
+ if ( ptr ) {
36
+ zpoller_destroy( (zpoller_t **)&ptr );
37
+ }
38
+ }
39
+
40
+
41
+ /*
42
+ * Alloc function
43
+ */
44
+ static VALUE
45
+ rzyre_poller_alloc( VALUE klass )
46
+ {
47
+ return TypedData_Wrap_Struct( klass, &rzyre_poller_t, NULL );
48
+ }
49
+
50
+
51
+ /*
52
+ * Fetch the data pointer and check it for sanity.
53
+ */
54
+ static inline zpoller_t *
55
+ rzyre_get_poller( VALUE self )
56
+ {
57
+ zpoller_t *ptr;
58
+
59
+ if ( !IsZyrePoller(self) ) {
60
+ rb_raise( rb_eTypeError, "wrong argument type %s (expected Zyre::Poller)",
61
+ rb_class2name(CLASS_OF( self )) );
62
+ }
63
+
64
+ ptr = DATA_PTR( self );
65
+ assert( ptr );
66
+
67
+ return ptr;
68
+ }
69
+
70
+
71
+ /*
72
+ * call-seq:
73
+ * Zyre::Poller.new( *nodes ) -> poller
74
+ *
75
+ * Create a poller that will wait for input on any of the given +nodes+.
76
+ *
77
+ */
78
+ static VALUE
79
+ rzyre_poller_initialize( VALUE self, VALUE nodes )
80
+ {
81
+ zpoller_t *ptr;
82
+
83
+ TypedData_Get_Struct( self, zpoller_t, &rzyre_poller_t, ptr );
84
+ if ( !ptr ) {
85
+ RTYPEDDATA_DATA( self ) = ptr = zpoller_new( NULL );
86
+ assert( ptr );
87
+
88
+ rb_ivar_set( self, rb_intern("@nodes"), rb_hash_new() );
89
+ }
90
+
91
+ rb_funcall( self, rb_intern("add"), 1, nodes );
92
+
93
+ return self;
94
+ }
95
+
96
+
97
+ /*
98
+ * call-seq:
99
+ * poller.add( *nodes )
100
+ *
101
+ * Add the specified +nodes+ to the list which will be polled by a call to #wait.
102
+ *
103
+ */
104
+ static VALUE
105
+ rzyre_poller_add( VALUE self, VALUE nodes )
106
+ {
107
+ zpoller_t *ptr = rzyre_get_poller( self );
108
+ VALUE nodemap = rb_ivar_get( self, rb_intern("@nodes") );
109
+ long i;
110
+
111
+ // For each node given, record its endpoint in @nodes so we can map it back to
112
+ // the node later and add it to the poller.
113
+ nodes = rb_funcall( nodes, rb_intern("flatten"), 0 );
114
+ for ( i=0; i < RARRAY_LEN(nodes); i++ ) {
115
+ VALUE node = RARRAY_AREF( nodes, i );
116
+ zyre_t *zyre_node = rzyre_get_node( node );
117
+ zsock_t *sock = zyre_socket( zyre_node );
118
+ const char *endpoint_str = zsock_endpoint( sock );
119
+
120
+ assert( endpoint_str );
121
+
122
+ rb_hash_aset( nodemap, rb_str_new2(endpoint_str), node );
123
+ zpoller_add( ptr, sock );
124
+ }
125
+
126
+ return Qtrue;
127
+ }
128
+
129
+
130
+ /*
131
+ * call-seq:
132
+ * poller.nodes -> hash
133
+ *
134
+ * Return a (frozen copy) of the Hash of the nodes the Poller will wait on.
135
+ *
136
+ */
137
+ static VALUE
138
+ rzyre_poller_nodes( VALUE self )
139
+ {
140
+ VALUE rval = rb_obj_dup( rb_ivar_get(self, rb_intern( "@nodes" )) );
141
+
142
+ return rb_hash_freeze( rval );
143
+ }
144
+
145
+
146
+ /*
147
+ * call-seq:
148
+ * poller.remove( *nodes )
149
+ *
150
+ * Add the specified +nodes+ to the list which will be polled by a call to #wait.
151
+ *
152
+ */
153
+ static VALUE
154
+ rzyre_poller_remove( VALUE self, VALUE nodes )
155
+ {
156
+ zpoller_t *ptr = rzyre_get_poller( self );
157
+ VALUE nodemap = rb_ivar_get( self, rb_intern("@nodes") );
158
+ long i;
159
+
160
+ // For each node given, record its endpoint in @nodes so we can map it back to
161
+ // the node later and remove it to the poller.
162
+ nodes = rb_funcall( nodes, rb_intern("flatten"), 0 );
163
+ for ( i=0; i < RARRAY_LEN(nodes); i++ ) {
164
+ VALUE node = RARRAY_AREF( nodes, i );
165
+ zyre_t *zyre_node = rzyre_get_node( node );
166
+ zsock_t *sock = zyre_socket( zyre_node );
167
+ const char *endpoint_str = zsock_endpoint( sock );
168
+
169
+ assert( endpoint_str );
170
+
171
+ rb_hash_aset( nodemap, rb_str_new2(endpoint_str), node );
172
+ zpoller_remove( ptr, sock );
173
+ }
174
+
175
+ return Qtrue;
176
+ }
177
+
178
+
179
+ typedef struct {
180
+ zpoller_t *poller;
181
+ int timeout;
182
+ } wait_call_t;
183
+
184
+ /*
185
+ * Async wait function; called without the GVL.
186
+ */
187
+ static void *
188
+ rzyre_poller_wait_without_gvl( void *wait_call )
189
+ {
190
+ wait_call_t *call = (wait_call_t *)wait_call;
191
+ return zpoller_wait( call->poller, call->timeout );
192
+ }
193
+
194
+
195
+ /*
196
+ * call-seq:
197
+ * poller.wait( timeout=-1 ) -> node or nil
198
+ *
199
+ * Poll the registered nodes for I/O, return first one that has input. The
200
+ * timeout should be zero or greater, or -1 to wait indefinitely. Socket
201
+ * priority is defined by their order in the poll list. If the timeout expired,
202
+ * returns nil. If poll call is interrupted (SIGINT) or the ZMQ context was
203
+ * destroyed, an Interrupt is raised.
204
+ *
205
+ */
206
+ static VALUE
207
+ rzyre_poller_wait( int argc, VALUE *argv, VALUE self )
208
+ {
209
+ zpoller_t *ptr = rzyre_get_poller( self );
210
+ VALUE rval = Qnil;
211
+ zsock_t *sock;
212
+ VALUE timeout_arg;
213
+ VALUE nodemap = rb_ivar_get( self, rb_intern("@nodes") );
214
+ int timeout = -1;
215
+ wait_call_t call;
216
+
217
+ if ( rb_scan_args(argc, argv, "01", &timeout_arg) ) {
218
+ timeout = floor( NUM2DBL(timeout_arg) * 1000 );
219
+ }
220
+
221
+ rzyre_log_obj( self, "debug", "waiting on %d socket/s (timeout: %d)",
222
+ RHASH_SIZE(nodemap), timeout );
223
+
224
+ call.poller = ptr;
225
+ call.timeout = timeout;
226
+ sock = (zsock_t *)rb_thread_call_without_gvl2( rzyre_poller_wait_without_gvl, (void *)&call,
227
+ RUBY_UBF_IO, 0 );
228
+
229
+ if ( sock ) {
230
+ const char *endpoint = zsock_endpoint( sock );
231
+ rval = rb_hash_aref( nodemap, rb_str_new2(endpoint) );
232
+ }
233
+
234
+ return rval;
235
+ }
236
+
237
+
238
+
239
+ /*
240
+ * Initialize the Poller class.
241
+ */
242
+ void
243
+ rzyre_init_poller( void ) {
244
+
245
+ #ifdef FOR_RDOC
246
+ rb_cData = rb_define_class( "Data" );
247
+ rzyre_mZyre = rb_define_module( "Zyre" );
248
+ #endif
249
+
250
+ /*
251
+ * Document-class: Zyre::Poller
252
+ *
253
+ * A poller for evented Zyre IO. Built on zpoller from czmq.
254
+ *
255
+ * Refs:
256
+ * - http://api.zeromq.org/czmq3-0:zpoller
257
+ *
258
+ */
259
+ rzyre_cZyrePoller = rb_define_class_under( rzyre_mZyre, "Poller", rb_cObject );
260
+
261
+ rb_define_alloc_func( rzyre_cZyrePoller, rzyre_poller_alloc );
262
+
263
+ rb_define_protected_method( rzyre_cZyrePoller, "initialize", rzyre_poller_initialize, -2 );
264
+
265
+ rb_define_method( rzyre_cZyrePoller, "add", rzyre_poller_add, -2 );
266
+ rb_define_method( rzyre_cZyrePoller, "nodes", rzyre_poller_nodes, 0 );
267
+ rb_define_method( rzyre_cZyrePoller, "remove", rzyre_poller_remove, 1 );
268
+ rb_define_method( rzyre_cZyrePoller, "wait", rzyre_poller_wait, -1 );
269
+
270
+ rb_require( "zyre/poller" );
271
+ }
272
+
@@ -0,0 +1,154 @@
1
+ /*
2
+ * zyre_ext.c - Ruby binding for Zyre
3
+ * $Id$
4
+ *
5
+ * Authors:
6
+ * * Michael Granger <ged@FaerieMUD.org>
7
+ *
8
+ */
9
+
10
+ #include "zyre_ext.h"
11
+
12
+ VALUE rzyre_mZyre;
13
+
14
+
15
+ /* --------------------------------------------------------------
16
+ * Logging Functions
17
+ * -------------------------------------------------------------- */
18
+
19
+ /*
20
+ * Log a message to the given +context+ object's logger.
21
+ */
22
+ void
23
+ #ifdef HAVE_STDARG_PROTOTYPES
24
+ rzyre_log_obj( VALUE context, const char *level, const char *fmt, ... )
25
+ #else
26
+ rzyre_log_obj( VALUE context, const char *level, const char *fmt, va_dcl )
27
+ #endif
28
+ {
29
+ char buf[BUFSIZ];
30
+ va_list args;
31
+ VALUE logger = Qnil;
32
+ VALUE message = Qnil;
33
+
34
+ va_init_list( args, fmt );
35
+ vsnprintf( buf, BUFSIZ, fmt, args );
36
+ message = rb_str_new2( buf );
37
+
38
+ logger = rb_funcall( context, rb_intern("log"), 0 );
39
+ rb_funcall( logger, rb_intern(level), 1, message );
40
+
41
+ va_end( args );
42
+ }
43
+
44
+
45
+ /*
46
+ * Log a message to the global logger.
47
+ */
48
+ void
49
+ #ifdef HAVE_STDARG_PROTOTYPES
50
+ rzyre_log( const char *level, const char *fmt, ... )
51
+ #else
52
+ rzyre_log( const char *level, const char *fmt, va_dcl )
53
+ #endif
54
+ {
55
+ char buf[BUFSIZ];
56
+ va_list args;
57
+ VALUE logger = Qnil;
58
+ VALUE message = Qnil;
59
+
60
+ va_init_list( args, fmt );
61
+ vsnprintf( buf, BUFSIZ, fmt, args );
62
+ message = rb_str_new2( buf );
63
+
64
+ logger = rb_funcall( rzyre_mZyre, rb_intern("logger"), 0 );
65
+ rb_funcall( logger, rb_intern(level), 1, message );
66
+
67
+ va_end( args );
68
+ }
69
+
70
+
71
+
72
+ /* --------------------------------------------------------------
73
+ * Module methods
74
+ * -------------------------------------------------------------- */
75
+
76
+ /*
77
+ * call-seq:
78
+ * Zyre.zyre_version -> int
79
+ *
80
+ * Return the version of the underlying libzyre.
81
+ *
82
+ */
83
+ static VALUE
84
+ rzyre_s_zyre_version()
85
+ {
86
+ static uint64_t version;
87
+
88
+ version = zyre_version();
89
+
90
+ return INT2NUM( version );
91
+ }
92
+
93
+
94
+ /*
95
+ * call-seq:
96
+ * Zyre.interfaces -> hash
97
+ *
98
+ * Return a Hash of broadcast-capable interfaces on the local host keyed by name. The
99
+ * values contain other information about the interface:
100
+ *
101
+ * {
102
+ * "<interface name>" => {
103
+ * address: "<interface address>",
104
+ * broadcast: "<interface broadcast address>",
105
+ * netmask: "<interface network mask>",
106
+ * }
107
+ * }
108
+ */
109
+ static VALUE
110
+ rzyre_s_interfaces()
111
+ {
112
+ ziflist_t *iflist = ziflist_new();
113
+ const VALUE rval = rb_hash_new();
114
+ const char *iface = ziflist_first( iflist );
115
+
116
+ while ( iface ) {
117
+ const char *address_s = ziflist_address( iflist );
118
+ const char *broadcast_s = ziflist_broadcast( iflist );
119
+ const char *netmask_s = ziflist_netmask( iflist );
120
+ const VALUE info_hash = rb_hash_new();
121
+
122
+ rb_hash_aset( info_hash, ID2SYM(rb_intern("address")), rb_usascii_str_new_cstr(address_s) );
123
+ rb_hash_aset( info_hash, ID2SYM(rb_intern("broadcast")), rb_usascii_str_new_cstr(broadcast_s) );
124
+ rb_hash_aset( info_hash, ID2SYM(rb_intern("netmask")), rb_usascii_str_new_cstr(netmask_s) );
125
+
126
+ rb_hash_aset( rval, rb_usascii_str_new_cstr(iface), info_hash );
127
+
128
+ iface = ziflist_next( iflist );
129
+ }
130
+
131
+ ziflist_destroy( &iflist );
132
+
133
+ return rval;
134
+ }
135
+
136
+
137
+ /*
138
+ * Zyre extension init function
139
+ */
140
+ void
141
+ Init_zyre_ext()
142
+ {
143
+ rzyre_mZyre = rb_define_module( "Zyre" );
144
+
145
+ rb_define_singleton_method( rzyre_mZyre, "zyre_version", rzyre_s_zyre_version, 0 );
146
+ rb_define_singleton_method( rzyre_mZyre, "interfaces", rzyre_s_interfaces, 0 );
147
+
148
+ // :TODO: set up zsys_set_logsender()
149
+
150
+ rzyre_init_node();
151
+ rzyre_init_event();
152
+ rzyre_init_poller();
153
+ }
154
+
@@ -0,0 +1,99 @@
1
+ /*
2
+ * zyre_ext.h - Ruby binding for Zyre
3
+ * $Id$
4
+ *
5
+ * Authors:
6
+ * * Michael Granger <ged@FaerieMUD.org>
7
+ *
8
+ */
9
+
10
+ #ifndef ZYRE_EXT_H_90322ABD
11
+ #define ZYRE_EXT_H_90322ABD
12
+
13
+ #include <ruby.h>
14
+ #include <ruby/intern.h>
15
+ #include <ruby/thread.h>
16
+
17
+ #include "zyre.h"
18
+ #include "czmq.h"
19
+ #include "extconf.h"
20
+
21
+ #ifndef TRUE
22
+ # define TRUE 1
23
+ #endif
24
+
25
+ #ifndef FALSE
26
+ # define FALSE 0
27
+ #endif
28
+
29
+
30
+ // For synthesized events
31
+ struct _zyre_event_t {
32
+ char *type; // Event type as string
33
+ char *peer_uuid; // Sender UUID as string
34
+ char *peer_name; // Sender public name as string
35
+ char *peer_addr; // Sender ipaddress as string, for an ENTER event
36
+ zhash_t *headers; // Headers, for an ENTER event
37
+ char *group; // Group name for a SHOUT event
38
+ zmsg_t *msg; // Message payload for SHOUT or WHISPER
39
+ };
40
+
41
+
42
+ /* --------------------------------------------------------------
43
+ * Declarations
44
+ * -------------------------------------------------------------- */
45
+
46
+ #ifdef HAVE_STDARG_PROTOTYPES
47
+ #include <stdarg.h>
48
+ #define va_init_list(a,b) va_start(a,b)
49
+ void rzyre_log_obj( VALUE, const char *, const char *, ... );
50
+ void rzyre_log( const char *, const char *, ... );
51
+ #else
52
+ #include <varargs.h>
53
+ #define va_init_list(a,b) va_start(a)
54
+ void rzyre_log_obj( VALUE, const char *, const char *, va_dcl );
55
+ void rzyre_log( const char *, const char *, va_dcl );
56
+ #endif
57
+
58
+
59
+ /* --------------------------------------------------------------
60
+ * Structs
61
+ * -------------------------------------------------------------- */
62
+
63
+
64
+
65
+ /* -------------------------------------------------------
66
+ * Globals
67
+ * ------------------------------------------------------- */
68
+
69
+ /*
70
+ * Modules
71
+ */
72
+ extern VALUE rzyre_mZyre;
73
+ extern VALUE rzyre_cZyreNode;
74
+ extern VALUE rzyre_cZyreEvent;
75
+ extern VALUE rzyre_cZyrePoller;
76
+
77
+
78
+ /* --------------------------------------------------------------
79
+ * Type-check macros
80
+ * -------------------------------------------------------------- */
81
+
82
+ #define IsZyreNode( obj ) rb_obj_is_kind_of( (obj), rzyre_cZyreNode )
83
+ #define IsZyreEvent( obj ) rb_obj_is_kind_of( (obj), rzyre_cZyreEvent )
84
+ #define IsZyrePoller( obj ) rb_obj_is_kind_of( (obj), rzyre_cZyrePoller )
85
+
86
+
87
+ /* -------------------------------------------------------
88
+ * Initializer functions
89
+ * ------------------------------------------------------- */
90
+ extern void Init_zyre_ext _(( void ));
91
+
92
+ extern void rzyre_init_node _(( void ));
93
+ extern void rzyre_init_event _(( void ));
94
+ extern void rzyre_init_poller _(( void ));
95
+
96
+ extern zyre_t * rzyre_get_node _(( VALUE ));
97
+
98
+ #endif /* end of include guard: ZYRE_EXT_H_90322ABD */
99
+