grpc 0.15.0 → 1.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Makefile +127 -159
- data/etc/roots.pem +784 -509
- data/include/grpc/grpc_posix.h +8 -0
- data/include/grpc/impl/codegen/byte_buffer.h +5 -4
- data/include/grpc/impl/codegen/grpc_types.h +2 -0
- data/include/grpc/impl/codegen/port_platform.h +2 -1
- data/include/grpc/module.modulemap +15 -0
- data/src/core/ext/census/grpc_filter.c +3 -0
- data/src/core/ext/client_config/channel_connectivity.c +4 -3
- data/src/core/ext/client_config/client_channel.c +6 -0
- data/src/core/ext/client_config/subchannel.c +2 -0
- data/src/core/ext/client_config/subchannel_call_holder.c +2 -5
- data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +2 -1
- data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +2 -1
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +171 -104
- data/src/core/ext/transport/chttp2/transport/internal.h +5 -3
- data/src/core/ext/transport/chttp2/transport/parsing.c +4 -3
- data/src/core/ext/transport/chttp2/transport/status_conversion.c +8 -2
- data/src/core/ext/transport/chttp2/transport/status_conversion.h +1 -1
- data/src/core/lib/channel/channel_stack.c +12 -1
- data/src/core/lib/channel/channel_stack.h +5 -0
- data/src/core/lib/channel/http_client_filter.c +7 -1
- data/src/core/lib/debug/trace.c +6 -2
- data/src/core/lib/iomgr/error.c +62 -19
- data/src/core/lib/iomgr/error.h +10 -6
- data/src/core/lib/iomgr/ev_epoll_linux.c +1872 -0
- data/src/core/lib/{surface/surface_trace.h → iomgr/ev_epoll_linux.h} +11 -12
- data/src/core/lib/iomgr/ev_posix.c +9 -6
- data/src/core/lib/iomgr/ev_posix.h +3 -0
- data/src/core/lib/iomgr/network_status_tracker.c +121 -0
- data/{include/grpc/grpc_zookeeper.h → src/core/lib/iomgr/network_status_tracker.h} +8 -26
- data/src/core/lib/iomgr/socket_utils_common_posix.c +22 -0
- data/src/core/lib/iomgr/socket_utils_posix.h +3 -0
- data/src/core/lib/iomgr/tcp_posix.c +6 -2
- data/src/core/lib/iomgr/tcp_server.h +3 -0
- data/src/core/lib/iomgr/tcp_server_posix.c +114 -16
- data/src/core/lib/iomgr/tcp_server_windows.c +1 -0
- data/src/core/lib/iomgr/tcp_windows.c +5 -0
- data/src/core/lib/iomgr/udp_server.c +28 -16
- data/src/core/lib/iomgr/wakeup_fd_eventfd.c +4 -2
- data/src/core/lib/profiling/basic_timers.c +4 -4
- data/src/core/lib/security/credentials/composite/composite_credentials.c +4 -3
- data/src/core/lib/security/credentials/credentials.c +1 -1
- data/src/core/lib/security/credentials/credentials.h +4 -5
- data/src/core/lib/security/credentials/fake/fake_credentials.c +2 -2
- data/src/core/lib/security/credentials/iam/iam_credentials.c +1 -1
- data/src/core/lib/security/credentials/jwt/jwt_credentials.c +7 -6
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +6 -4
- data/src/core/lib/security/credentials/plugin/plugin_credentials.c +4 -3
- data/src/core/lib/security/transport/client_auth_filter.c +10 -7
- data/src/core/lib/surface/byte_buffer_reader.c +6 -4
- data/src/core/lib/surface/call.c +64 -51
- data/src/core/lib/surface/call.h +0 -1
- data/src/core/lib/surface/channel.c +10 -8
- data/src/core/lib/surface/completion_queue.c +26 -12
- data/src/core/lib/surface/completion_queue.h +4 -0
- data/src/core/lib/surface/init.c +6 -1
- data/src/core/lib/surface/version.c +1 -1
- data/src/core/lib/transport/transport.c +62 -29
- data/src/core/lib/transport/transport.h +8 -5
- data/src/core/lib/transport/transport_op_string.c +14 -3
- data/src/ruby/ext/grpc/rb_byte_buffer.c +4 -1
- data/src/ruby/ext/grpc/rb_call.c +87 -54
- data/src/ruby/ext/grpc/rb_call.h +1 -1
- data/src/ruby/ext/grpc/rb_call_credentials.c +1 -30
- data/src/ruby/ext/grpc/rb_channel.c +25 -50
- data/src/ruby/ext/grpc/rb_channel_credentials.c +1 -31
- data/src/ruby/ext/grpc/rb_completion_queue.c +15 -134
- data/src/ruby/ext/grpc/rb_completion_queue.h +3 -7
- data/src/ruby/ext/grpc/rb_grpc.c +2 -4
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
- data/src/ruby/ext/grpc/rb_server.c +81 -133
- data/src/ruby/ext/grpc/rb_server_credentials.c +4 -33
- data/src/ruby/lib/grpc/generic/active_call.rb +40 -55
- data/src/ruby/lib/grpc/generic/bidi_call.rb +21 -23
- data/src/ruby/lib/grpc/generic/client_stub.rb +20 -15
- data/src/ruby/lib/grpc/generic/rpc_server.rb +15 -37
- data/src/ruby/lib/grpc/generic/service.rb +1 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/src/ruby/pb/test/client.rb +25 -7
- data/src/ruby/pb/test/server.rb +7 -5
- data/src/ruby/spec/call_spec.rb +1 -2
- data/src/ruby/spec/channel_spec.rb +2 -3
- data/src/ruby/spec/client_server_spec.rb +74 -59
- data/src/ruby/spec/generic/active_call_spec.rb +66 -86
- data/src/ruby/spec/generic/client_stub_spec.rb +27 -48
- data/src/ruby/spec/generic/rpc_server_spec.rb +4 -34
- data/src/ruby/spec/pb/health/checker_spec.rb +0 -2
- data/src/ruby/spec/server_spec.rb +20 -24
- metadata +9 -8
- data/src/ruby/spec/completion_queue_spec.rb +0 -42
data/src/ruby/ext/grpc/rb_call.h
CHANGED
@@ -42,7 +42,7 @@
|
|
42
42
|
grpc_call* grpc_rb_get_wrapped_call(VALUE v);
|
43
43
|
|
44
44
|
/* Gets the VALUE corresponding to given grpc_call. */
|
45
|
-
VALUE grpc_rb_wrap_call(grpc_call*
|
45
|
+
VALUE grpc_rb_wrap_call(grpc_call *c, grpc_completion_queue *q);
|
46
46
|
|
47
47
|
/* Provides the details of an call error */
|
48
48
|
const char* grpc_call_error_detail_of(grpc_call_error err);
|
@@ -211,35 +211,6 @@ VALUE grpc_rb_wrap_call_credentials(grpc_call_credentials *c, VALUE mark) {
|
|
211
211
|
return rb_wrapper;
|
212
212
|
}
|
213
213
|
|
214
|
-
/* Clones CallCredentials instances.
|
215
|
-
Gives CallCredentials a consistent implementation of Ruby's object copy/dup
|
216
|
-
protocol. */
|
217
|
-
static VALUE grpc_rb_call_credentials_init_copy(VALUE copy, VALUE orig) {
|
218
|
-
grpc_rb_call_credentials *orig_cred = NULL;
|
219
|
-
grpc_rb_call_credentials *copy_cred = NULL;
|
220
|
-
|
221
|
-
if (copy == orig) {
|
222
|
-
return copy;
|
223
|
-
}
|
224
|
-
|
225
|
-
/* Raise an error if orig is not a credentials object or a subclass. */
|
226
|
-
if (TYPE(orig) != T_DATA ||
|
227
|
-
RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_call_credentials_free) {
|
228
|
-
rb_raise(rb_eTypeError, "not a %s",
|
229
|
-
rb_obj_classname(grpc_rb_cCallCredentials));
|
230
|
-
}
|
231
|
-
|
232
|
-
TypedData_Get_Struct(orig, grpc_rb_call_credentials,
|
233
|
-
&grpc_rb_call_credentials_data_type, orig_cred);
|
234
|
-
TypedData_Get_Struct(copy, grpc_rb_call_credentials,
|
235
|
-
&grpc_rb_call_credentials_data_type, copy_cred);
|
236
|
-
|
237
|
-
/* use ruby's MEMCPY to make a byte-for-byte copy of the credentials
|
238
|
-
* wrapper object. */
|
239
|
-
MEMCPY(copy_cred, orig_cred, grpc_rb_call_credentials, 1);
|
240
|
-
return copy;
|
241
|
-
}
|
242
|
-
|
243
214
|
/* The attribute used on the mark object to hold the callback */
|
244
215
|
static ID id_callback;
|
245
216
|
|
@@ -308,7 +279,7 @@ void Init_grpc_call_credentials() {
|
|
308
279
|
rb_define_method(grpc_rb_cCallCredentials, "initialize",
|
309
280
|
grpc_rb_call_credentials_init, 1);
|
310
281
|
rb_define_method(grpc_rb_cCallCredentials, "initialize_copy",
|
311
|
-
|
282
|
+
grpc_rb_cannot_init_copy, 1);
|
312
283
|
rb_define_method(grpc_rb_cCallCredentials, "compose",
|
313
284
|
grpc_rb_call_credentials_compose, -1);
|
314
285
|
|
@@ -39,6 +39,8 @@
|
|
39
39
|
#include <grpc/grpc.h>
|
40
40
|
#include <grpc/grpc_security.h>
|
41
41
|
#include <grpc/support/alloc.h>
|
42
|
+
#include <grpc/support/log.h>
|
43
|
+
#include <grpc/support/time.h>
|
42
44
|
#include "rb_grpc.h"
|
43
45
|
#include "rb_call.h"
|
44
46
|
#include "rb_channel_args.h"
|
@@ -55,11 +57,6 @@ static ID id_channel;
|
|
55
57
|
* GCed before the channel */
|
56
58
|
static ID id_target;
|
57
59
|
|
58
|
-
/* id_cqueue is the name of the hidden ivar that preserves a reference to the
|
59
|
-
* completion queue used to create the call, preserved so that it does not get
|
60
|
-
* GCed before the channel */
|
61
|
-
static ID id_cqueue;
|
62
|
-
|
63
60
|
/* id_insecure_channel is used to indicate that a channel is insecure */
|
64
61
|
static VALUE id_insecure_channel;
|
65
62
|
|
@@ -75,6 +72,7 @@ typedef struct grpc_rb_channel {
|
|
75
72
|
|
76
73
|
/* The actual channel */
|
77
74
|
grpc_channel *wrapped;
|
75
|
+
grpc_completion_queue *queue;
|
78
76
|
} grpc_rb_channel;
|
79
77
|
|
80
78
|
/* Destroys Channel instances. */
|
@@ -87,6 +85,7 @@ static void grpc_rb_channel_free(void *p) {
|
|
87
85
|
|
88
86
|
if (ch->wrapped != NULL) {
|
89
87
|
grpc_channel_destroy(ch->wrapped);
|
88
|
+
grpc_rb_completion_queue_destroy(ch->queue);
|
90
89
|
}
|
91
90
|
|
92
91
|
xfree(p);
|
@@ -169,6 +168,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
|
|
169
168
|
}
|
170
169
|
rb_ivar_set(self, id_target, target);
|
171
170
|
wrapper->wrapped = ch;
|
171
|
+
wrapper->queue = grpc_completion_queue_create(NULL);
|
172
172
|
return self;
|
173
173
|
}
|
174
174
|
|
@@ -207,16 +207,18 @@ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv,
|
|
207
207
|
the completion queue with success=0 */
|
208
208
|
static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self,
|
209
209
|
VALUE last_state,
|
210
|
-
VALUE
|
211
|
-
VALUE deadline,
|
212
|
-
VALUE tag) {
|
210
|
+
VALUE deadline) {
|
213
211
|
grpc_rb_channel *wrapper = NULL;
|
214
212
|
grpc_channel *ch = NULL;
|
215
213
|
grpc_completion_queue *cq = NULL;
|
216
214
|
|
217
|
-
|
215
|
+
void *tag = wrapper;
|
216
|
+
|
217
|
+
grpc_event event;
|
218
|
+
|
218
219
|
TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
|
219
220
|
ch = wrapper->wrapped;
|
221
|
+
cq = wrapper->queue;
|
220
222
|
if (ch == NULL) {
|
221
223
|
rb_raise(rb_eRuntimeError, "closed!");
|
222
224
|
return Qnil;
|
@@ -226,45 +228,23 @@ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self,
|
|
226
228
|
(grpc_connectivity_state)NUM2LONG(last_state),
|
227
229
|
grpc_rb_time_timeval(deadline, /* absolute time */ 0),
|
228
230
|
cq,
|
229
|
-
|
230
|
-
|
231
|
-
return Qnil;
|
232
|
-
}
|
233
|
-
|
234
|
-
/* Clones Channel instances.
|
231
|
+
tag);
|
235
232
|
|
236
|
-
|
237
|
-
|
238
|
-
static VALUE grpc_rb_channel_init_copy(VALUE copy, VALUE orig) {
|
239
|
-
grpc_rb_channel *orig_ch = NULL;
|
240
|
-
grpc_rb_channel *copy_ch = NULL;
|
233
|
+
event = rb_completion_queue_pluck(cq, tag,
|
234
|
+
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
|
241
235
|
|
242
|
-
if (
|
243
|
-
return
|
244
|
-
}
|
245
|
-
|
246
|
-
/* Raise an error if orig is not a channel object or a subclass. */
|
247
|
-
if (TYPE(orig) != T_DATA ||
|
248
|
-
RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_channel_free) {
|
249
|
-
rb_raise(rb_eTypeError, "not a %s", rb_obj_classname(grpc_rb_cChannel));
|
250
|
-
return Qnil;
|
236
|
+
if (event.success) {
|
237
|
+
return Qtrue;
|
238
|
+
} else {
|
239
|
+
return Qfalse;
|
251
240
|
}
|
252
|
-
|
253
|
-
TypedData_Get_Struct(orig, grpc_rb_channel, &grpc_channel_data_type, orig_ch);
|
254
|
-
TypedData_Get_Struct(copy, grpc_rb_channel, &grpc_channel_data_type, copy_ch);
|
255
|
-
|
256
|
-
/* use ruby's MEMCPY to make a byte-for-byte copy of the channel wrapper
|
257
|
-
* object. */
|
258
|
-
MEMCPY(copy_ch, orig_ch, grpc_rb_channel, 1);
|
259
|
-
return copy;
|
260
241
|
}
|
261
242
|
|
262
243
|
/* Create a call given a grpc_channel, in order to call method. The request
|
263
244
|
is not sent until grpc_call_invoke is called. */
|
264
|
-
static VALUE grpc_rb_channel_create_call(VALUE self, VALUE
|
265
|
-
VALUE
|
266
|
-
VALUE
|
267
|
-
VALUE deadline) {
|
245
|
+
static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent,
|
246
|
+
VALUE mask, VALUE method,
|
247
|
+
VALUE host, VALUE deadline) {
|
268
248
|
VALUE res = Qnil;
|
269
249
|
grpc_rb_channel *wrapper = NULL;
|
270
250
|
grpc_call *call = NULL;
|
@@ -284,7 +264,7 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE cqueue,
|
|
284
264
|
parent_call = grpc_rb_get_wrapped_call(parent);
|
285
265
|
}
|
286
266
|
|
287
|
-
cq =
|
267
|
+
cq = grpc_completion_queue_create(NULL);
|
288
268
|
TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
|
289
269
|
ch = wrapper->wrapped;
|
290
270
|
if (ch == NULL) {
|
@@ -301,15 +281,11 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE cqueue,
|
|
301
281
|
method_chars);
|
302
282
|
return Qnil;
|
303
283
|
}
|
304
|
-
res = grpc_rb_wrap_call(call);
|
284
|
+
res = grpc_rb_wrap_call(call, cq);
|
305
285
|
|
306
286
|
/* Make this channel an instance attribute of the call so that it is not GCed
|
307
287
|
* before the call. */
|
308
288
|
rb_ivar_set(res, id_channel, self);
|
309
|
-
|
310
|
-
/* Make the completion queue an instance attribute of the call so that it is
|
311
|
-
* not GCed before the call. */
|
312
|
-
rb_ivar_set(res, id_cqueue, cqueue);
|
313
289
|
return res;
|
314
290
|
}
|
315
291
|
|
@@ -387,7 +363,7 @@ void Init_grpc_channel() {
|
|
387
363
|
/* Provides a ruby constructor and support for dup/clone. */
|
388
364
|
rb_define_method(grpc_rb_cChannel, "initialize", grpc_rb_channel_init, -1);
|
389
365
|
rb_define_method(grpc_rb_cChannel, "initialize_copy",
|
390
|
-
|
366
|
+
grpc_rb_cannot_init_copy, 1);
|
391
367
|
|
392
368
|
/* Add ruby analogues of the Channel methods. */
|
393
369
|
rb_define_method(grpc_rb_cChannel, "connectivity_state",
|
@@ -396,13 +372,12 @@ void Init_grpc_channel() {
|
|
396
372
|
rb_define_method(grpc_rb_cChannel, "watch_connectivity_state",
|
397
373
|
grpc_rb_channel_watch_connectivity_state, 4);
|
398
374
|
rb_define_method(grpc_rb_cChannel, "create_call",
|
399
|
-
grpc_rb_channel_create_call,
|
375
|
+
grpc_rb_channel_create_call, 5);
|
400
376
|
rb_define_method(grpc_rb_cChannel, "target", grpc_rb_channel_get_target, 0);
|
401
377
|
rb_define_method(grpc_rb_cChannel, "destroy", grpc_rb_channel_destroy, 0);
|
402
378
|
rb_define_alias(grpc_rb_cChannel, "close", "destroy");
|
403
379
|
|
404
380
|
id_channel = rb_intern("__channel");
|
405
|
-
id_cqueue = rb_intern("__cqueue");
|
406
381
|
id_target = rb_intern("__target");
|
407
382
|
rb_define_const(grpc_rb_cChannel, "SSL_TARGET",
|
408
383
|
ID2SYM(rb_intern(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)));
|
@@ -126,36 +126,6 @@ VALUE grpc_rb_wrap_channel_credentials(grpc_channel_credentials *c, VALUE mark)
|
|
126
126
|
return rb_wrapper;
|
127
127
|
}
|
128
128
|
|
129
|
-
/* Clones ChannelCredentials instances.
|
130
|
-
Gives ChannelCredentials a consistent implementation of Ruby's object copy/dup
|
131
|
-
protocol. */
|
132
|
-
static VALUE grpc_rb_channel_credentials_init_copy(VALUE copy, VALUE orig) {
|
133
|
-
grpc_rb_channel_credentials *orig_cred = NULL;
|
134
|
-
grpc_rb_channel_credentials *copy_cred = NULL;
|
135
|
-
|
136
|
-
if (copy == orig) {
|
137
|
-
return copy;
|
138
|
-
}
|
139
|
-
|
140
|
-
/* Raise an error if orig is not a credentials object or a subclass. */
|
141
|
-
if (TYPE(orig) != T_DATA ||
|
142
|
-
RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_channel_credentials_free) {
|
143
|
-
rb_raise(rb_eTypeError, "not a %s",
|
144
|
-
rb_obj_classname(grpc_rb_cChannelCredentials));
|
145
|
-
}
|
146
|
-
|
147
|
-
TypedData_Get_Struct(orig, grpc_rb_channel_credentials,
|
148
|
-
&grpc_rb_channel_credentials_data_type, orig_cred);
|
149
|
-
TypedData_Get_Struct(copy, grpc_rb_channel_credentials,
|
150
|
-
&grpc_rb_channel_credentials_data_type, copy_cred);
|
151
|
-
|
152
|
-
/* use ruby's MEMCPY to make a byte-for-byte copy of the credentials
|
153
|
-
* wrapper object. */
|
154
|
-
MEMCPY(copy_cred, orig_cred, grpc_rb_channel_credentials, 1);
|
155
|
-
return copy;
|
156
|
-
}
|
157
|
-
|
158
|
-
|
159
129
|
/* The attribute used on the mark object to hold the pem_root_certs. */
|
160
130
|
static ID id_pem_root_certs;
|
161
131
|
|
@@ -271,7 +241,7 @@ void Init_grpc_channel_credentials() {
|
|
271
241
|
rb_define_method(grpc_rb_cChannelCredentials, "initialize",
|
272
242
|
grpc_rb_channel_credentials_init, -1);
|
273
243
|
rb_define_method(grpc_rb_cChannelCredentials, "initialize_copy",
|
274
|
-
|
244
|
+
grpc_rb_cannot_init_copy, 1);
|
275
245
|
rb_define_method(grpc_rb_cChannelCredentials, "compose",
|
276
246
|
grpc_rb_channel_credentials_compose, -1);
|
277
247
|
rb_define_module_function(grpc_rb_cChannelCredentials,
|
@@ -40,12 +40,9 @@
|
|
40
40
|
|
41
41
|
#include <grpc/grpc.h>
|
42
42
|
#include <grpc/support/time.h>
|
43
|
+
#include <grpc/support/log.h>
|
43
44
|
#include "rb_grpc.h"
|
44
45
|
|
45
|
-
/* grpc_rb_cCompletionQueue is the ruby class that proxies
|
46
|
-
* grpc_completion_queue. */
|
47
|
-
static VALUE grpc_rb_cCompletionQueue = Qnil;
|
48
|
-
|
49
46
|
/* Used to allow grpc_completion_queue_next call to release the GIL */
|
50
47
|
typedef struct next_call_stack {
|
51
48
|
grpc_completion_queue *cq;
|
@@ -55,23 +52,6 @@ typedef struct next_call_stack {
|
|
55
52
|
volatile int interrupted;
|
56
53
|
} next_call_stack;
|
57
54
|
|
58
|
-
/* Calls grpc_completion_queue_next without holding the ruby GIL */
|
59
|
-
static void *grpc_rb_completion_queue_next_no_gil(void *param) {
|
60
|
-
next_call_stack *const next_call = (next_call_stack*)param;
|
61
|
-
gpr_timespec increment = gpr_time_from_millis(20, GPR_TIMESPAN);
|
62
|
-
gpr_timespec deadline;
|
63
|
-
do {
|
64
|
-
deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), increment);
|
65
|
-
next_call->event = grpc_completion_queue_next(next_call->cq,
|
66
|
-
deadline, NULL);
|
67
|
-
if (next_call->event.type != GRPC_QUEUE_TIMEOUT ||
|
68
|
-
gpr_time_cmp(deadline, next_call->timeout) > 0) {
|
69
|
-
break;
|
70
|
-
}
|
71
|
-
} while (!next_call->interrupted);
|
72
|
-
return NULL;
|
73
|
-
}
|
74
|
-
|
75
55
|
/* Calls grpc_completion_queue_pluck without holding the ruby GIL */
|
76
56
|
static void *grpc_rb_completion_queue_pluck_no_gil(void *param) {
|
77
57
|
next_call_stack *const next_call = (next_call_stack*)param;
|
@@ -90,107 +70,32 @@ static void *grpc_rb_completion_queue_pluck_no_gil(void *param) {
|
|
90
70
|
return NULL;
|
91
71
|
}
|
92
72
|
|
93
|
-
/* Shuts down and drains the completion queue if necessary.
|
94
|
-
*
|
95
|
-
* This is done when the ruby completion queue object is about to be GCed.
|
96
|
-
*/
|
97
|
-
static void grpc_rb_completion_queue_shutdown_drain(grpc_completion_queue *cq) {
|
98
|
-
next_call_stack next_call;
|
99
|
-
grpc_completion_type type;
|
100
|
-
int drained = 0;
|
101
|
-
MEMZERO(&next_call, next_call_stack, 1);
|
102
|
-
|
103
|
-
grpc_completion_queue_shutdown(cq);
|
104
|
-
next_call.cq = cq;
|
105
|
-
next_call.event.type = GRPC_QUEUE_TIMEOUT;
|
106
|
-
/* TODO: the timeout should be a module level constant that defaults
|
107
|
-
* to gpr_inf_future(GPR_CLOCK_REALTIME).
|
108
|
-
*
|
109
|
-
* - at the moment this does not work, it stalls. Using a small timeout like
|
110
|
-
* this one works, and leads to fast test run times; a longer timeout was
|
111
|
-
* causing unnecessary delays in the test runs.
|
112
|
-
*
|
113
|
-
* - investigate further, this is probably another example of C-level cleanup
|
114
|
-
* not working consistently in all cases.
|
115
|
-
*/
|
116
|
-
next_call.timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
|
117
|
-
gpr_time_from_micros(5e3, GPR_TIMESPAN));
|
118
|
-
do {
|
119
|
-
rb_thread_call_without_gvl(grpc_rb_completion_queue_next_no_gil,
|
120
|
-
(void *)&next_call, NULL, NULL);
|
121
|
-
type = next_call.event.type;
|
122
|
-
if (type == GRPC_QUEUE_TIMEOUT) break;
|
123
|
-
if (type != GRPC_QUEUE_SHUTDOWN) {
|
124
|
-
++drained;
|
125
|
-
rb_warning("completion queue shutdown: %d undrained events", drained);
|
126
|
-
}
|
127
|
-
} while (type != GRPC_QUEUE_SHUTDOWN);
|
128
|
-
}
|
129
|
-
|
130
73
|
/* Helper function to free a completion queue. */
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
cq
|
137
|
-
grpc_rb_completion_queue_shutdown_drain(cq);
|
74
|
+
void grpc_rb_completion_queue_destroy(grpc_completion_queue *cq) {
|
75
|
+
/* Every function that adds an event to a queue also synchronously plucks
|
76
|
+
that event from the queue, and holds a reference to the Ruby object that
|
77
|
+
holds the queue, so we only get to this point if all of those functions
|
78
|
+
have completed, and the queue is empty */
|
79
|
+
grpc_completion_queue_shutdown(cq);
|
138
80
|
grpc_completion_queue_destroy(cq);
|
139
81
|
}
|
140
82
|
|
141
|
-
static rb_data_type_t grpc_rb_completion_queue_data_type = {
|
142
|
-
"grpc_completion_queue",
|
143
|
-
{GRPC_RB_GC_NOT_MARKED, grpc_rb_completion_queue_destroy,
|
144
|
-
GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
|
145
|
-
NULL, NULL,
|
146
|
-
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
147
|
-
/* cannot immediately free because grpc_rb_completion_queue_shutdown_drain
|
148
|
-
* calls rb_thread_call_without_gvl. */
|
149
|
-
0,
|
150
|
-
#endif
|
151
|
-
};
|
152
|
-
|
153
|
-
/* Releases the c-level resources associated with a completion queue */
|
154
|
-
static VALUE grpc_rb_completion_queue_close(VALUE self) {
|
155
|
-
grpc_completion_queue* cq = grpc_rb_get_wrapped_completion_queue(self);
|
156
|
-
grpc_rb_completion_queue_destroy(cq);
|
157
|
-
RTYPEDDATA_DATA(self) = NULL;
|
158
|
-
return Qnil;
|
159
|
-
}
|
160
|
-
|
161
|
-
/* Allocates a completion queue. */
|
162
|
-
static VALUE grpc_rb_completion_queue_alloc(VALUE cls) {
|
163
|
-
grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
|
164
|
-
if (cq == NULL) {
|
165
|
-
rb_raise(rb_eArgError, "could not create a completion queue: not sure why");
|
166
|
-
}
|
167
|
-
return TypedData_Wrap_Struct(cls, &grpc_rb_completion_queue_data_type, cq);
|
168
|
-
}
|
169
|
-
|
170
83
|
static void unblock_func(void *param) {
|
171
84
|
next_call_stack *const next_call = (next_call_stack*)param;
|
172
85
|
next_call->interrupted = 1;
|
173
86
|
}
|
174
87
|
|
175
|
-
/*
|
176
|
-
|
177
|
-
grpc_event
|
178
|
-
|
88
|
+
/* Does the same thing as grpc_completion_queue_pluck, while properly releasing
|
89
|
+
the GVL and handling interrupts */
|
90
|
+
grpc_event rb_completion_queue_pluck(grpc_completion_queue *queue, void *tag,
|
91
|
+
gpr_timespec deadline, void *reserved) {
|
179
92
|
next_call_stack next_call;
|
180
93
|
MEMZERO(&next_call, next_call_stack, 1);
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
next_call.timeout = gpr_inf_future(GPR_CLOCK_REALTIME);
|
185
|
-
} else {
|
186
|
-
next_call.timeout = grpc_rb_time_timeval(timeout, /* absolute time*/ 0);
|
187
|
-
}
|
188
|
-
if (TYPE(tag) == T_NIL) {
|
189
|
-
next_call.tag = NULL;
|
190
|
-
} else {
|
191
|
-
next_call.tag = ROBJECT(tag);
|
192
|
-
}
|
94
|
+
next_call.cq = queue;
|
95
|
+
next_call.timeout = deadline;
|
96
|
+
next_call.tag = tag;
|
193
97
|
next_call.event.type = GRPC_QUEUE_TIMEOUT;
|
98
|
+
(void)reserved;
|
194
99
|
/* Loop until we finish a pluck without an interruption. The internal
|
195
100
|
pluck function runs either until it is interrupted or it gets an
|
196
101
|
event, or time runs out.
|
@@ -210,27 +115,3 @@ grpc_event grpc_rb_completion_queue_pluck_event(VALUE self, VALUE tag,
|
|
210
115
|
next_call.event.type == GRPC_QUEUE_TIMEOUT);
|
211
116
|
return next_call.event;
|
212
117
|
}
|
213
|
-
|
214
|
-
void Init_grpc_completion_queue() {
|
215
|
-
grpc_rb_cCompletionQueue =
|
216
|
-
rb_define_class_under(grpc_rb_mGrpcCore, "CompletionQueue", rb_cObject);
|
217
|
-
|
218
|
-
/* constructor: uses an alloc func without an initializer. Using a simple
|
219
|
-
alloc func works here as the grpc header does not specify any args for
|
220
|
-
this func, so no separate initialization step is necessary. */
|
221
|
-
rb_define_alloc_func(grpc_rb_cCompletionQueue,
|
222
|
-
grpc_rb_completion_queue_alloc);
|
223
|
-
|
224
|
-
/* close: Provides a way to close the underlying file descriptor without
|
225
|
-
waiting for ruby garbage collection. */
|
226
|
-
rb_define_method(grpc_rb_cCompletionQueue, "close",
|
227
|
-
grpc_rb_completion_queue_close, 0);
|
228
|
-
}
|
229
|
-
|
230
|
-
/* Gets the wrapped completion queue from the ruby wrapper */
|
231
|
-
grpc_completion_queue *grpc_rb_get_wrapped_completion_queue(VALUE v) {
|
232
|
-
grpc_completion_queue *cq = NULL;
|
233
|
-
TypedData_Get_Struct(v, grpc_completion_queue,
|
234
|
-
&grpc_rb_completion_queue_data_type, cq);
|
235
|
-
return cq;
|
236
|
-
}
|