mdp 0.1
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.
- data/.gitignore +19 -0
- data/CHANGELOG.rdoc +4 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +19 -0
- data/README.rdoc +158 -0
- data/Rakefile +47 -0
- data/ext/majordomo/client.c +302 -0
- data/ext/majordomo/client.h +39 -0
- data/ext/majordomo/extconf.rb +25 -0
- data/ext/majordomo/jruby.h +9 -0
- data/ext/majordomo/majordomo_ext.c +19 -0
- data/ext/majordomo/majordomo_ext.h +26 -0
- data/ext/majordomo/prelude.h +23 -0
- data/ext/majordomo/rubinius.h +19 -0
- data/ext/majordomo/ruby18.h +38 -0
- data/ext/majordomo/ruby19.h +13 -0
- data/ext/majordomo/worker.c +366 -0
- data/ext/majordomo/worker.h +43 -0
- data/lib/majordomo.rb +8 -0
- data/lib/majordomo/version.rb +3 -0
- data/mdp.gemspec +22 -0
- data/test/helper.rb +20 -0
- data/test/test_client.rb +51 -0
- data/test/test_threading.rb +32 -0
- data/test/test_worker.rb +86 -0
- metadata +92 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
#ifndef MAJORDOMO_CLIENT_H
|
2
|
+
#define MAJORDOMO_CLIENT_H
|
3
|
+
|
4
|
+
typedef struct {
|
5
|
+
mdp_client_t *client;
|
6
|
+
VALUE broker;
|
7
|
+
VALUE timeout;
|
8
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
9
|
+
zlist_t *recv_buffer;
|
10
|
+
#endif
|
11
|
+
} rb_majordomo_client_t;
|
12
|
+
|
13
|
+
#define MAJORDOMO_CLIENT_TIMEOUT 2500
|
14
|
+
|
15
|
+
#define GetMajordomoClient(obj) \
|
16
|
+
rb_majordomo_client_t *client = NULL; \
|
17
|
+
Data_Get_Struct(obj, rb_majordomo_client_t, client); \
|
18
|
+
if (!client) rb_raise(rb_eTypeError, "uninitialized Majordomo client!"); \
|
19
|
+
if (!client->client) rb_raise(rb_eRuntimeError, "Majordomo client has already been closed!");
|
20
|
+
|
21
|
+
struct nogvl_md_client_new_args {
|
22
|
+
char *broker;
|
23
|
+
int verbose;
|
24
|
+
};
|
25
|
+
|
26
|
+
struct nogvl_md_client_send_args {
|
27
|
+
mdp_client_t *client;
|
28
|
+
char *service;
|
29
|
+
zmsg_t *request;
|
30
|
+
};
|
31
|
+
|
32
|
+
struct nogvl_md_client_recv_args {
|
33
|
+
rb_majordomo_client_t *client;
|
34
|
+
char *service;
|
35
|
+
};
|
36
|
+
|
37
|
+
void _init_majordomo_client();
|
38
|
+
|
39
|
+
#endif
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
|
5
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
6
|
+
|
7
|
+
def fail(msg)
|
8
|
+
STDERR.puts msg
|
9
|
+
exit(1)
|
10
|
+
end
|
11
|
+
|
12
|
+
dir_config('majordomo')
|
13
|
+
|
14
|
+
fail("libmdp header file 'mdp.h' not found") unless have_header('mdp.h')
|
15
|
+
|
16
|
+
fail("zmq not found") unless have_library('zmq')
|
17
|
+
fail("czmq not found") unless have_library('czmq')
|
18
|
+
fail("libdmp not found") unless have_library('mdp')
|
19
|
+
|
20
|
+
have_func('rb_thread_blocking_region')
|
21
|
+
|
22
|
+
$CFLAGS << ' -Wall -funroll-loops'
|
23
|
+
$CFLAGS << ' -Wextra -O0 -ggdb3' if ENV['DEBUG']
|
24
|
+
|
25
|
+
create_makefile('majordomo_ext')
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#include "majordomo_ext.h"
|
2
|
+
|
3
|
+
VALUE rb_mMajordomo;
|
4
|
+
|
5
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
6
|
+
rb_encoding *binary_encoding;
|
7
|
+
#endif
|
8
|
+
|
9
|
+
void Init_majordomo_ext()
|
10
|
+
{
|
11
|
+
rb_mMajordomo = rb_define_module("Majordomo");
|
12
|
+
|
13
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
14
|
+
binary_encoding = rb_enc_find("binary");
|
15
|
+
#endif
|
16
|
+
|
17
|
+
_init_majordomo_client();
|
18
|
+
_init_majordomo_worker();
|
19
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#ifndef MAJORDOMO_EXT_H
|
2
|
+
#define MAJORDOMO_EXT_H
|
3
|
+
|
4
|
+
#include <mdp.h>
|
5
|
+
#include "ruby.h"
|
6
|
+
|
7
|
+
/* Compiler specific */
|
8
|
+
|
9
|
+
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
10
|
+
#define MAJORDOMO_UNUSED __attribute__ ((unused))
|
11
|
+
#define MAJORDOMO_NOINLINE __attribute__ ((noinline))
|
12
|
+
#else
|
13
|
+
#define MAJORDOMO_UNUSED
|
14
|
+
#define MAJORDOMO_NOINLINE
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#include "prelude.h"
|
18
|
+
|
19
|
+
extern VALUE rb_mMajordomo;
|
20
|
+
extern VALUE rb_cMajordomoClient;
|
21
|
+
extern VALUE rb_cMajordomoWorker;
|
22
|
+
|
23
|
+
#include "client.h"
|
24
|
+
#include "worker.h"
|
25
|
+
|
26
|
+
#endif
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#ifndef MAJORDOMO_PRELUDE_H
|
2
|
+
#define MAJORDOMO_PRELUDE_H
|
3
|
+
#include <stdint.h>
|
4
|
+
|
5
|
+
#ifndef RFLOAT_VALUE
|
6
|
+
#define RFLOAT_VALUE(v) (RFLOAT(v)->value)
|
7
|
+
#endif
|
8
|
+
|
9
|
+
#ifdef RUBINIUS
|
10
|
+
#include "rubinius.h"
|
11
|
+
#else
|
12
|
+
#ifdef JRUBY
|
13
|
+
#include "jruby.h"
|
14
|
+
#else
|
15
|
+
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
16
|
+
#include "ruby19.h"
|
17
|
+
#else
|
18
|
+
#include "ruby18.h"
|
19
|
+
#endif
|
20
|
+
#endif
|
21
|
+
#endif
|
22
|
+
|
23
|
+
#endif
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#ifndef MAJORDOMO_RUBINIUS_H
|
2
|
+
#define MAJORDOMO_RUBINIUS_H
|
3
|
+
|
4
|
+
#define RSTRING_NOT_MODIFIED
|
5
|
+
|
6
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
7
|
+
#include <ruby/encoding.h>
|
8
|
+
extern rb_encoding *binary_encoding;
|
9
|
+
#define MajordomorEncode(str) rb_enc_associate(str, binary_encoding)
|
10
|
+
#else
|
11
|
+
#define MajordomoEncode(str) str
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#define TRAP_BEG
|
15
|
+
#define TRAP_END
|
16
|
+
|
17
|
+
#define FIXNUM_FLAG 0x01
|
18
|
+
|
19
|
+
#endif
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#ifndef MAJORDOMO_RUBY18_H
|
2
|
+
#define MAJORDOMO_RUBY18_H
|
3
|
+
|
4
|
+
#define MajordomoEncode(str) str
|
5
|
+
|
6
|
+
#ifndef RSTRING_PTR
|
7
|
+
#define RSTRING_PTR(str) RSTRING(str)->ptr
|
8
|
+
#endif
|
9
|
+
#ifndef RSTRING_LEN
|
10
|
+
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#include "rubyio.h"
|
14
|
+
#include "rubysig.h"
|
15
|
+
|
16
|
+
/*
|
17
|
+
* partial emulation of the 1.9 rb_thread_blocking_region under 1.8,
|
18
|
+
* this is enough for dealing with blocking I/O functions in the
|
19
|
+
* presence of threads.
|
20
|
+
*/
|
21
|
+
|
22
|
+
#define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
|
23
|
+
typedef void rb_unblock_function_t(void *);
|
24
|
+
typedef VALUE rb_blocking_function_t(void *);
|
25
|
+
static VALUE
|
26
|
+
rb_thread_blocking_region(
|
27
|
+
rb_blocking_function_t *func, void *data1,
|
28
|
+
MAJORDOMO_UNUSED rb_unblock_function_t *ubf,
|
29
|
+
MAJORDOMO_UNUSED void *data2)
|
30
|
+
{
|
31
|
+
VALUE rv;
|
32
|
+
TRAP_BEG;
|
33
|
+
rv = func(data1);
|
34
|
+
TRAP_END;
|
35
|
+
return rv;
|
36
|
+
}
|
37
|
+
|
38
|
+
#endif
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#ifndef MAJORDOMO_RUBY19_H
|
2
|
+
#define MAJORDOMO_RUBY19_H
|
3
|
+
|
4
|
+
#include <ruby/encoding.h>
|
5
|
+
#include <ruby/io.h>
|
6
|
+
|
7
|
+
extern rb_encoding *binary_encoding;
|
8
|
+
#define MajordomoEncode(str) rb_enc_associate(str, binary_encoding)
|
9
|
+
|
10
|
+
#define TRAP_BEG
|
11
|
+
#define TRAP_END
|
12
|
+
|
13
|
+
#endif
|
@@ -0,0 +1,366 @@
|
|
1
|
+
#include "majordomo_ext.h"
|
2
|
+
|
3
|
+
VALUE rb_cMajordomoWorker;
|
4
|
+
|
5
|
+
/*
|
6
|
+
* :nodoc:
|
7
|
+
* GC mark callback
|
8
|
+
*
|
9
|
+
*/
|
10
|
+
static void rb_mark_majordomo_worker(void *ptr)
|
11
|
+
{
|
12
|
+
rb_majordomo_worker_t *worker = (rb_majordomo_worker_t *)ptr;
|
13
|
+
if (worker) {
|
14
|
+
rb_gc_mark(worker->broker);
|
15
|
+
rb_gc_mark(worker->service);
|
16
|
+
rb_gc_mark(worker->heartbeat);
|
17
|
+
rb_gc_mark(worker->reconnect);
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
/*
|
22
|
+
* :nodoc:
|
23
|
+
* Release the GIL when closing a Majordomo worker
|
24
|
+
*
|
25
|
+
*/
|
26
|
+
static VALUE rb_nogvl_mdp_worker_close(void *ptr)
|
27
|
+
{
|
28
|
+
mdp_worker_t *worker = ptr;
|
29
|
+
mdp_worker_destroy(&worker);
|
30
|
+
return Qnil;
|
31
|
+
}
|
32
|
+
|
33
|
+
/*
|
34
|
+
* :nodoc:
|
35
|
+
* GC free callback
|
36
|
+
*
|
37
|
+
*/
|
38
|
+
static void rb_free_majordomo_worker(void *ptr)
|
39
|
+
{
|
40
|
+
rb_majordomo_worker_t *worker = (rb_majordomo_worker_t *)ptr;
|
41
|
+
if (worker) {
|
42
|
+
if (worker->worker) rb_thread_blocking_region(rb_nogvl_mdp_worker_close, (void *)worker->worker, RUBY_UBF_IO, 0);
|
43
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
44
|
+
zlist_destroy(&(worker->recv_buffer));
|
45
|
+
#endif
|
46
|
+
xfree(worker);
|
47
|
+
worker = NULL;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
/*
|
52
|
+
* :nodoc:
|
53
|
+
* Release the GIL when creating a new Majordomo worker
|
54
|
+
*
|
55
|
+
*/
|
56
|
+
static VALUE rb_nogvl_mdp_worker_new(void *ptr)
|
57
|
+
{
|
58
|
+
struct nogvl_md_worker_new_args *args = ptr;
|
59
|
+
return (VALUE)mdp_worker_new(args->broker, args->service, args->verbose);
|
60
|
+
}
|
61
|
+
|
62
|
+
/*
|
63
|
+
* call-seq:
|
64
|
+
* Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
65
|
+
* Majordomo::Worker.new("tcp://0.0.0.0:5555", "service", true) => Majordomo::Worker
|
66
|
+
*
|
67
|
+
* Creates a new Majordomo::Worker instance. A broker URI and service identifier is required and an
|
68
|
+
* optional verbose flag can be passed to the initializer.
|
69
|
+
*
|
70
|
+
* === Examples
|
71
|
+
* wk = Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
72
|
+
* wk.broker => "tcp://0.0.0.0:5555"
|
73
|
+
* wk.heartbeat => 2500
|
74
|
+
* wk.recv => "request"
|
75
|
+
*
|
76
|
+
*/
|
77
|
+
static VALUE rb_majordomo_worker_s_new(int argc, VALUE *argv, VALUE klass)
|
78
|
+
{
|
79
|
+
rb_majordomo_worker_t *worker = NULL;
|
80
|
+
struct nogvl_md_worker_new_args args;
|
81
|
+
VALUE obj, broker, service, verbose;
|
82
|
+
rb_scan_args(argc, argv, "21", &broker, &service, &verbose);
|
83
|
+
if (verbose == Qnil)
|
84
|
+
verbose = Qfalse;
|
85
|
+
Check_Type(broker, T_STRING);
|
86
|
+
Check_Type(service, T_STRING);
|
87
|
+
obj = Data_Make_Struct(klass, rb_majordomo_worker_t, rb_mark_majordomo_worker, rb_free_majordomo_worker, worker);
|
88
|
+
|
89
|
+
args.broker = RSTRING_PTR(broker);
|
90
|
+
args.service = RSTRING_PTR(service);
|
91
|
+
args.verbose = (verbose == Qtrue ? 1 : 0);
|
92
|
+
worker->worker = (mdp_worker_t *)rb_thread_blocking_region(rb_nogvl_mdp_worker_new, (void *)&args, RUBY_UBF_IO, 0);
|
93
|
+
worker->broker = rb_str_new4(broker);
|
94
|
+
worker->service = rb_str_new4(service);
|
95
|
+
worker->heartbeat = INT2NUM(MAJORDOMO_WORKER_HEARTBEAT);
|
96
|
+
worker->reconnect = INT2NUM(MAJORDOMO_WORKER_RECONNECT);
|
97
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
98
|
+
worker->recv_buffer = zlist_new();
|
99
|
+
#endif
|
100
|
+
rb_obj_call_init(obj, 0, NULL);
|
101
|
+
return obj;
|
102
|
+
}
|
103
|
+
|
104
|
+
/*
|
105
|
+
* call-seq:
|
106
|
+
* wk.broker => String
|
107
|
+
*
|
108
|
+
* Returns the URI of the broker this worker is connected to.
|
109
|
+
*
|
110
|
+
* === Examples
|
111
|
+
* wk = Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
112
|
+
* wk.broker => "tcp://0.0.0.0:5555"
|
113
|
+
*
|
114
|
+
*/
|
115
|
+
static VALUE rb_majordomo_worker_broker(VALUE obj){
|
116
|
+
GetMajordomoWorker(obj);
|
117
|
+
return worker->broker;
|
118
|
+
}
|
119
|
+
|
120
|
+
/*
|
121
|
+
* call-seq:
|
122
|
+
* wk.service => String
|
123
|
+
*
|
124
|
+
* Returns the service identifier this worker implements.
|
125
|
+
*
|
126
|
+
* === Examples
|
127
|
+
* wk = Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
128
|
+
* wk.service => "service"
|
129
|
+
*
|
130
|
+
*/
|
131
|
+
static VALUE rb_majordomo_worker_service(VALUE obj){
|
132
|
+
GetMajordomoWorker(obj);
|
133
|
+
return worker->service;
|
134
|
+
}
|
135
|
+
|
136
|
+
/*
|
137
|
+
* call-seq:
|
138
|
+
* wk.heartbeat => Fixnum
|
139
|
+
*
|
140
|
+
* Returns the worker heartbeat delay (in msecs).
|
141
|
+
*
|
142
|
+
* === Examples
|
143
|
+
* wk = Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
144
|
+
* wk.heartbeat => 2500
|
145
|
+
*
|
146
|
+
*/
|
147
|
+
static VALUE rb_majordomo_worker_heartbeat(VALUE obj){
|
148
|
+
GetMajordomoWorker(obj);
|
149
|
+
return worker->heartbeat;
|
150
|
+
}
|
151
|
+
|
152
|
+
/*
|
153
|
+
* call-seq:
|
154
|
+
* wk.reconnect => Fixnum
|
155
|
+
*
|
156
|
+
* Returns the worker reconnect delay (in msecs).
|
157
|
+
*
|
158
|
+
* === Examples
|
159
|
+
* wk = Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
160
|
+
* wk.reconnect => 2500
|
161
|
+
*
|
162
|
+
*/
|
163
|
+
static VALUE rb_majordomo_worker_reconnect(VALUE obj){
|
164
|
+
GetMajordomoWorker(obj);
|
165
|
+
return worker->reconnect;
|
166
|
+
}
|
167
|
+
|
168
|
+
/*
|
169
|
+
* call-seq:
|
170
|
+
* wk.heartbeat = val => nil
|
171
|
+
*
|
172
|
+
* Sets the worker heartbeat delay (in msecs).
|
173
|
+
*
|
174
|
+
* === Examples
|
175
|
+
* wk = Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
176
|
+
* wk.heartbeat = 100 => nil
|
177
|
+
* wk.heartbeat => 100
|
178
|
+
*
|
179
|
+
*/
|
180
|
+
static VALUE rb_majordomo_worker_heartbeat_equals(VALUE obj, VALUE heartbeat){
|
181
|
+
GetMajordomoWorker(obj);
|
182
|
+
Check_Type(heartbeat, T_FIXNUM);
|
183
|
+
mdp_worker_set_heartbeat(worker->worker, FIX2INT(heartbeat));
|
184
|
+
worker->heartbeat = heartbeat;
|
185
|
+
return Qnil;
|
186
|
+
}
|
187
|
+
|
188
|
+
/*
|
189
|
+
* call-seq:
|
190
|
+
* wk.reconnect = 100 => nil
|
191
|
+
*
|
192
|
+
* Sets the worker reconnect delay (in msecs).
|
193
|
+
*
|
194
|
+
* === Examples
|
195
|
+
* wk = Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
196
|
+
* wk.reconnect = 100 => nil
|
197
|
+
* wk.reconnect => 100
|
198
|
+
*
|
199
|
+
*/
|
200
|
+
static VALUE rb_majordomo_worker_reconnect_equals(VALUE obj, VALUE reconnect){
|
201
|
+
GetMajordomoWorker(obj);
|
202
|
+
Check_Type(reconnect, T_FIXNUM);
|
203
|
+
mdp_worker_set_reconnect(worker->worker, FIX2INT(reconnect));
|
204
|
+
worker->reconnect = reconnect;
|
205
|
+
return Qnil;
|
206
|
+
}
|
207
|
+
|
208
|
+
/*
|
209
|
+
* :nodoc:
|
210
|
+
* Release the GIL when receiving a worker message
|
211
|
+
*
|
212
|
+
*/
|
213
|
+
static VALUE rb_nogvl_mdp_worker_recv(void *ptr)
|
214
|
+
{
|
215
|
+
struct nogvl_md_worker_recv_args *args = ptr;
|
216
|
+
rb_majordomo_worker_t *worker = args->worker;
|
217
|
+
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
218
|
+
return (VALUE)mdp_worker_recv(worker->worker, &args->reply);
|
219
|
+
#else
|
220
|
+
uint32_t events;
|
221
|
+
size_t evopt_len = sizeof (uint32_t);
|
222
|
+
int fd;
|
223
|
+
size_t fdopt_len = sizeof (int);
|
224
|
+
if (zlist_size(worker->recv_buffer) != 0)
|
225
|
+
return (VALUE)zlist_pop(worker->recv_buffer);
|
226
|
+
try_readable:
|
227
|
+
mdp_worker_getsockopt (worker->worker, ZMQ_EVENTS, &events, &evopt_len);
|
228
|
+
if ((events & ZMQ_POLLIN) == ZMQ_POLLIN) {
|
229
|
+
do {
|
230
|
+
zlist_append(worker->recv_buffer, mdp_worker_recv(worker->worker, &args->reply));
|
231
|
+
} while (zmq_errno() != EAGAIN && zmq_errno() != EINTR);
|
232
|
+
return (VALUE)zlist_pop(worker->recv_buffer);
|
233
|
+
} else {
|
234
|
+
mdp_worker_getsockopt (worker->worker, ZMQ_FD, &fd, &fdopt_len);
|
235
|
+
rb_thread_wait_fd(fd);
|
236
|
+
goto try_readable;
|
237
|
+
}
|
238
|
+
#endif
|
239
|
+
}
|
240
|
+
|
241
|
+
/*
|
242
|
+
* call-seq:
|
243
|
+
* wk.recv => String or nil
|
244
|
+
*
|
245
|
+
* Receives a client request form the broker. Valid requests are of type String and NilClass
|
246
|
+
*
|
247
|
+
* === Examples
|
248
|
+
* wk = Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
249
|
+
* wk.recv => ["request", "reply"]
|
250
|
+
*
|
251
|
+
*/
|
252
|
+
static VALUE rb_majordomo_worker_recv(VALUE obj){
|
253
|
+
VALUE req, reply;
|
254
|
+
struct nogvl_md_worker_recv_args args;
|
255
|
+
GetMajordomoWorker(obj);
|
256
|
+
args.worker = worker;
|
257
|
+
args.reply = NULL;
|
258
|
+
zmsg_t *request = (zmsg_t *)rb_thread_blocking_region(rb_nogvl_mdp_worker_recv, (void *)&args, RUBY_UBF_IO, 0);
|
259
|
+
if (!request)
|
260
|
+
return Qnil;
|
261
|
+
req = MajordomoEncode(rb_str_new2(zmsg_popstr(request)));
|
262
|
+
zmsg_destroy(&request);
|
263
|
+
reply = rb_str_new(zframe_data(args.reply), zframe_size(args.reply));
|
264
|
+
zframe_destroy(&args.reply);
|
265
|
+
return rb_ary_new3(2, req, reply);
|
266
|
+
}
|
267
|
+
|
268
|
+
/*
|
269
|
+
* :nodoc:
|
270
|
+
* Release the GIL when sending a worker message
|
271
|
+
*
|
272
|
+
*/
|
273
|
+
static VALUE rb_nogvl_mdp_worker_send(void *ptr)
|
274
|
+
{
|
275
|
+
struct nogvl_md_worker_send_args *args = ptr;
|
276
|
+
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
277
|
+
mdp_worker_send(args->worker, &args->progress, args->reply_to);
|
278
|
+
#else
|
279
|
+
uint32_t events;
|
280
|
+
size_t evopt_len = sizeof (uint32_t);
|
281
|
+
int fd;
|
282
|
+
size_t fdopt_len = sizeof (int);
|
283
|
+
if (rb_thread_alone()) {
|
284
|
+
mdp_worker_send(args->worker, &args->progress, args->reply_to);
|
285
|
+
return Qnil;
|
286
|
+
}
|
287
|
+
try_writable:
|
288
|
+
mdp_worker_getsockopt (args->worker, ZMQ_EVENTS, &events, &evopt_len);
|
289
|
+
if ((events & ZMQ_POLLOUT) == ZMQ_POLLOUT) {
|
290
|
+
mdp_worker_send(args->worker, &args->progress, args->reply_to);
|
291
|
+
} else {
|
292
|
+
mdp_worker_getsockopt (args->worker, ZMQ_FD, &fd, &fdopt_len);
|
293
|
+
rb_thread_wait_fd(fd);
|
294
|
+
goto try_writable;
|
295
|
+
}
|
296
|
+
#endif
|
297
|
+
return Qnil;
|
298
|
+
}
|
299
|
+
|
300
|
+
/*
|
301
|
+
* call-seq:
|
302
|
+
* wk.send(message, reply_to) => boolean
|
303
|
+
*
|
304
|
+
* Send a reply to a client request. Returns true if the send was succfessful.
|
305
|
+
*
|
306
|
+
* === Examples
|
307
|
+
* wk = Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
308
|
+
* req, reply_to = wk.recv => ["request", "reply"]
|
309
|
+
* wk.send("reply", reply_to) => true
|
310
|
+
*
|
311
|
+
*/
|
312
|
+
static VALUE rb_majordomo_worker_send(VALUE obj, VALUE message, VALUE reply_to){
|
313
|
+
struct nogvl_md_worker_send_args args;
|
314
|
+
GetMajordomoWorker(obj);
|
315
|
+
args.worker = worker->worker;
|
316
|
+
args.progress = zmsg_new();
|
317
|
+
if (!args.progress)
|
318
|
+
return Qfalse;
|
319
|
+
if (zmsg_pushmem(args.progress, RSTRING_PTR(message), RSTRING_LEN(message)) == -1) {
|
320
|
+
zmsg_destroy(&args.progress);
|
321
|
+
return Qfalse;
|
322
|
+
}
|
323
|
+
args.reply_to = zframe_new(RSTRING_PTR(reply_to), RSTRING_LEN(reply_to));
|
324
|
+
if (!args.reply_to) {
|
325
|
+
zmsg_destroy(&args.progress);
|
326
|
+
return Qfalse;
|
327
|
+
}
|
328
|
+
rb_thread_blocking_region(rb_nogvl_mdp_worker_send, (void *)&args, RUBY_UBF_IO, 0);
|
329
|
+
zframe_destroy(&args.reply_to);
|
330
|
+
return Qtrue;
|
331
|
+
}
|
332
|
+
|
333
|
+
/*
|
334
|
+
* call-seq:
|
335
|
+
* wk.close => nil
|
336
|
+
*
|
337
|
+
* Close the worker connection to the broker.
|
338
|
+
*
|
339
|
+
* === Examples
|
340
|
+
* wk = Majordomo::Worker.new("tcp://0.0.0.0:5555", "service") => Majordomo::Worker
|
341
|
+
* wk.close => nil
|
342
|
+
*
|
343
|
+
*/
|
344
|
+
static VALUE rb_majordomo_worker_close(VALUE obj){
|
345
|
+
VALUE ret;
|
346
|
+
GetMajordomoWorker(obj);
|
347
|
+
ret = rb_thread_blocking_region(rb_nogvl_mdp_worker_close, (void *)worker->worker, RUBY_UBF_IO, 0);
|
348
|
+
worker->worker = NULL;
|
349
|
+
return ret;
|
350
|
+
}
|
351
|
+
|
352
|
+
void _init_majordomo_worker()
|
353
|
+
{
|
354
|
+
rb_cMajordomoWorker = rb_define_class_under(rb_mMajordomo, "Worker", rb_cObject);
|
355
|
+
|
356
|
+
rb_define_singleton_method(rb_cMajordomoWorker, "new", rb_majordomo_worker_s_new, -1);
|
357
|
+
rb_define_method(rb_cMajordomoWorker, "broker", rb_majordomo_worker_broker, 0);
|
358
|
+
rb_define_method(rb_cMajordomoWorker, "service", rb_majordomo_worker_service, 0);
|
359
|
+
rb_define_method(rb_cMajordomoWorker, "heartbeat", rb_majordomo_worker_heartbeat, 0);
|
360
|
+
rb_define_method(rb_cMajordomoWorker, "reconnect", rb_majordomo_worker_reconnect, 0);
|
361
|
+
rb_define_method(rb_cMajordomoWorker, "heartbeat=", rb_majordomo_worker_heartbeat_equals, 1);
|
362
|
+
rb_define_method(rb_cMajordomoWorker, "reconnect=", rb_majordomo_worker_reconnect_equals, 1);
|
363
|
+
rb_define_method(rb_cMajordomoWorker, "recv", rb_majordomo_worker_recv, 0);
|
364
|
+
rb_define_method(rb_cMajordomoWorker, "send", rb_majordomo_worker_send, 2);
|
365
|
+
rb_define_method(rb_cMajordomoWorker, "close", rb_majordomo_worker_close, 0);
|
366
|
+
}
|