grpc 0.15.0-x86-linux → 1.0.0.pre1-x86-linux

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.

Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/etc/roots.pem +784 -509
  3. data/grpc_c.32.ruby +0 -0
  4. data/grpc_c.64.ruby +0 -0
  5. data/src/ruby/ext/grpc/rb_byte_buffer.c +4 -1
  6. data/src/ruby/ext/grpc/rb_call.c +87 -54
  7. data/src/ruby/ext/grpc/rb_call.h +1 -1
  8. data/src/ruby/ext/grpc/rb_call_credentials.c +1 -30
  9. data/src/ruby/ext/grpc/rb_channel.c +25 -50
  10. data/src/ruby/ext/grpc/rb_channel_credentials.c +1 -31
  11. data/src/ruby/ext/grpc/rb_completion_queue.c +15 -134
  12. data/src/ruby/ext/grpc/rb_completion_queue.h +3 -7
  13. data/src/ruby/ext/grpc/rb_grpc.c +2 -4
  14. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  15. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
  16. data/src/ruby/ext/grpc/rb_server.c +81 -133
  17. data/src/ruby/ext/grpc/rb_server_credentials.c +4 -33
  18. data/src/ruby/lib/grpc/2.0/grpc_c.so +0 -0
  19. data/src/ruby/lib/grpc/2.1/grpc_c.so +0 -0
  20. data/src/ruby/lib/grpc/2.2/grpc_c.so +0 -0
  21. data/src/ruby/lib/grpc/2.3/grpc_c.so +0 -0
  22. data/src/ruby/lib/grpc/generic/active_call.rb +40 -55
  23. data/src/ruby/lib/grpc/generic/bidi_call.rb +21 -23
  24. data/src/ruby/lib/grpc/generic/client_stub.rb +20 -15
  25. data/src/ruby/lib/grpc/generic/rpc_server.rb +15 -37
  26. data/src/ruby/lib/grpc/generic/service.rb +1 -1
  27. data/src/ruby/lib/grpc/grpc_c.so +0 -0
  28. data/src/ruby/lib/grpc/version.rb +1 -1
  29. data/src/ruby/pb/test/client.rb +25 -7
  30. data/src/ruby/pb/test/server.rb +7 -5
  31. data/src/ruby/spec/call_spec.rb +1 -2
  32. data/src/ruby/spec/channel_spec.rb +2 -3
  33. data/src/ruby/spec/client_server_spec.rb +74 -59
  34. data/src/ruby/spec/generic/active_call_spec.rb +66 -86
  35. data/src/ruby/spec/generic/client_stub_spec.rb +27 -48
  36. data/src/ruby/spec/generic/rpc_server_spec.rb +4 -34
  37. data/src/ruby/spec/pb/health/checker_spec.rb +0 -2
  38. data/src/ruby/spec/server_spec.rb +20 -24
  39. metadata +4 -6
  40. data/src/ruby/spec/completion_queue_spec.rb +0 -42
Binary file
Binary file
@@ -56,7 +56,10 @@ VALUE grpc_rb_byte_buffer_to_s(grpc_byte_buffer *buffer) {
56
56
  return Qnil;
57
57
  }
58
58
  rb_string = rb_str_buf_new(grpc_byte_buffer_length(buffer));
59
- grpc_byte_buffer_reader_init(&reader, buffer);
59
+ if (!grpc_byte_buffer_reader_init(&reader, buffer)) {
60
+ rb_raise(rb_eRuntimeError, "Error initializing byte buffer reader.");
61
+ return Qnil;
62
+ }
60
63
  while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
61
64
  rb_str_cat(rb_string, (const char *) GPR_SLICE_START_PTR(next),
62
65
  GPR_SLICE_LENGTH(next));
@@ -63,27 +63,18 @@ static VALUE grpc_rb_sBatchResult;
63
63
  * grpc_metadata_array. */
64
64
  static VALUE grpc_rb_cMdAry;
65
65
 
66
- /* id_cq is the name of the hidden ivar that preserves a reference to a
67
- * completion queue */
68
- static ID id_cq;
69
-
70
- /* id_flags is the name of the hidden ivar that preserves the value of
71
- * the flags used to create metadata from a Hash */
72
- static ID id_flags;
73
-
74
66
  /* id_credentials is the name of the hidden ivar that preserves the value
75
67
  * of the credentials added to the call */
76
68
  static ID id_credentials;
77
69
 
78
- /* id_input_md is the name of the hidden ivar that preserves the hash used to
79
- * create metadata, so that references to the strings it contains last as long
80
- * as the call the metadata is added to. */
81
- static ID id_input_md;
82
-
83
70
  /* id_metadata is name of the attribute used to access the metadata hash
84
71
  * received by the call and subsequently saved on it. */
85
72
  static ID id_metadata;
86
73
 
74
+ /* id_trailing_metadata is the name of the attribute used to access the trailing
75
+ * metadata hash received by the call and subsequently saved on it. */
76
+ static ID id_trailing_metadata;
77
+
87
78
  /* id_status is name of the attribute used to access the status object
88
79
  * received by the call and subsequently saved on it. */
89
80
  static ID id_status;
@@ -101,14 +92,27 @@ static VALUE sym_message;
101
92
  static VALUE sym_status;
102
93
  static VALUE sym_cancelled;
103
94
 
95
+ typedef struct grpc_rb_call {
96
+ grpc_call *wrapped;
97
+ grpc_completion_queue *queue;
98
+ } grpc_rb_call;
99
+
100
+ static void destroy_call(grpc_rb_call *call) {
101
+ /* Ensure that we only try to destroy the call once */
102
+ if (call->wrapped != NULL) {
103
+ grpc_call_destroy(call->wrapped);
104
+ call->wrapped = NULL;
105
+ grpc_rb_completion_queue_destroy(call->queue);
106
+ call->queue = NULL;
107
+ }
108
+ }
109
+
104
110
  /* Destroys a Call. */
105
111
  static void grpc_rb_call_destroy(void *p) {
106
- grpc_call* call = NULL;
107
112
  if (p == NULL) {
108
113
  return;
109
114
  }
110
- call = (grpc_call *)p;
111
- grpc_call_destroy(call);
115
+ destroy_call((grpc_rb_call*)p);
112
116
  }
113
117
 
114
118
  static size_t md_ary_datasize(const void *p) {
@@ -167,15 +171,15 @@ const char *grpc_call_error_detail_of(grpc_call_error err) {
167
171
  /* Called by clients to cancel an RPC on the server.
168
172
  Can be called multiple times, from any thread. */
169
173
  static VALUE grpc_rb_call_cancel(VALUE self) {
170
- grpc_call *call = NULL;
174
+ grpc_rb_call *call = NULL;
171
175
  grpc_call_error err;
172
176
  if (RTYPEDDATA_DATA(self) == NULL) {
173
177
  //This call has been closed
174
178
  return Qnil;
175
179
  }
176
180
 
177
- TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
178
- err = grpc_call_cancel(call, NULL);
181
+ TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call);
182
+ err = grpc_call_cancel(call->wrapped, NULL);
179
183
  if (err != GRPC_CALL_OK) {
180
184
  rb_raise(grpc_rb_eCallError, "cancel failed: %s (code=%d)",
181
185
  grpc_call_error_detail_of(err), err);
@@ -189,10 +193,10 @@ static VALUE grpc_rb_call_cancel(VALUE self) {
189
193
  processed.
190
194
  */
191
195
  static VALUE grpc_rb_call_close(VALUE self) {
192
- grpc_call *call = NULL;
193
- TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
196
+ grpc_rb_call *call = NULL;
197
+ TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call);
194
198
  if(call != NULL) {
195
- grpc_call_destroy(call);
199
+ destroy_call(call);
196
200
  RTYPEDDATA_DATA(self) = NULL;
197
201
  }
198
202
  return Qnil;
@@ -201,14 +205,14 @@ static VALUE grpc_rb_call_close(VALUE self) {
201
205
  /* Called to obtain the peer that this call is connected to. */
202
206
  static VALUE grpc_rb_call_get_peer(VALUE self) {
203
207
  VALUE res = Qnil;
204
- grpc_call *call = NULL;
208
+ grpc_rb_call *call = NULL;
205
209
  char *peer = NULL;
206
210
  if (RTYPEDDATA_DATA(self) == NULL) {
207
211
  rb_raise(grpc_rb_eCallError, "Cannot get peer value on closed call");
208
212
  return Qnil;
209
213
  }
210
- TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
211
- peer = grpc_call_get_peer(call);
214
+ TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call);
215
+ peer = grpc_call_get_peer(call->wrapped);
212
216
  res = rb_str_new2(peer);
213
217
  gpr_free(peer);
214
218
 
@@ -217,16 +221,16 @@ static VALUE grpc_rb_call_get_peer(VALUE self) {
217
221
 
218
222
  /* Called to obtain the x509 cert of an authenticated peer. */
219
223
  static VALUE grpc_rb_call_get_peer_cert(VALUE self) {
220
- grpc_call *call = NULL;
224
+ grpc_rb_call *call = NULL;
221
225
  VALUE res = Qnil;
222
226
  grpc_auth_context *ctx = NULL;
223
227
  if (RTYPEDDATA_DATA(self) == NULL) {
224
228
  rb_raise(grpc_rb_eCallError, "Cannot get peer cert on closed call");
225
229
  return Qnil;
226
230
  }
227
- TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
231
+ TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call);
228
232
 
229
- ctx = grpc_call_auth_context(call);
233
+ ctx = grpc_call_auth_context(call->wrapped);
230
234
 
231
235
  if (!ctx || !grpc_auth_context_peer_is_authenticated(ctx)) {
232
236
  return Qnil;
@@ -296,6 +300,30 @@ static VALUE grpc_rb_call_set_metadata(VALUE self, VALUE metadata) {
296
300
  return rb_ivar_set(self, id_metadata, metadata);
297
301
  }
298
302
 
303
+ /*
304
+ call-seq:
305
+ trailing_metadata = call.trailing_metadata
306
+
307
+ Gets the trailing metadata object saved on the call */
308
+ static VALUE grpc_rb_call_get_trailing_metadata(VALUE self) {
309
+ return rb_ivar_get(self, id_trailing_metadata);
310
+ }
311
+
312
+ /*
313
+ call-seq:
314
+ call.trailing_metadata = trailing_metadata
315
+
316
+ Saves the trailing metadata hash on the call. */
317
+ static VALUE grpc_rb_call_set_trailing_metadata(VALUE self, VALUE metadata) {
318
+ if (!NIL_P(metadata) && TYPE(metadata) != T_HASH) {
319
+ rb_raise(rb_eTypeError, "bad metadata: got:<%s> want: <Hash>",
320
+ rb_obj_classname(metadata));
321
+ return Qnil;
322
+ }
323
+
324
+ return rb_ivar_set(self, id_trailing_metadata, metadata);
325
+ }
326
+
299
327
  /*
300
328
  call-seq:
301
329
  write_flag = call.write_flag
@@ -326,21 +354,23 @@ static VALUE grpc_rb_call_set_write_flag(VALUE self, VALUE write_flag) {
326
354
 
327
355
  Sets credentials on a call */
328
356
  static VALUE grpc_rb_call_set_credentials(VALUE self, VALUE credentials) {
329
- grpc_call *call = NULL;
357
+ grpc_rb_call *call = NULL;
330
358
  grpc_call_credentials *creds;
331
359
  grpc_call_error err;
332
360
  if (RTYPEDDATA_DATA(self) == NULL) {
333
361
  rb_raise(grpc_rb_eCallError, "Cannot set credentials of closed call");
334
362
  return Qnil;
335
363
  }
336
- TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
364
+ TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call);
337
365
  creds = grpc_rb_get_wrapped_call_credentials(credentials);
338
- err = grpc_call_set_credentials(call, creds);
366
+ err = grpc_call_set_credentials(call->wrapped, creds);
339
367
  if (err != GRPC_CALL_OK) {
340
368
  rb_raise(grpc_rb_eCallError,
341
369
  "grpc_call_set_credentials failed with %s (code=%d)",
342
370
  grpc_call_error_detail_of(err), err);
343
371
  }
372
+ /* We need the credentials to be alive for as long as the call is alive,
373
+ but we don't care about destruction order. */
344
374
  rb_ivar_set(self, id_credentials, credentials);
345
375
  return Qnil;
346
376
  }
@@ -733,7 +763,6 @@ static VALUE grpc_run_batch_stack_build_result(run_batch_stack *st) {
733
763
  }
734
764
 
735
765
  /* call-seq:
736
- cq = CompletionQueue.new
737
766
  ops = {
738
767
  GRPC::Core::CallOps::SEND_INITIAL_METADATA => <op_value>,
739
768
  GRPC::Core::CallOps::SEND_MESSAGE => <op_value>,
@@ -741,7 +770,7 @@ static VALUE grpc_run_batch_stack_build_result(run_batch_stack *st) {
741
770
  }
742
771
  tag = Object.new
743
772
  timeout = 10
744
- call.start_batch(cq, tag, timeout, ops)
773
+ call.start_batch(tag, timeout, ops)
745
774
 
746
775
  Start a batch of operations defined in the array ops; when complete, post a
747
776
  completion of type 'tag' to the completion queue bound to the call.
@@ -750,20 +779,20 @@ static VALUE grpc_run_batch_stack_build_result(run_batch_stack *st) {
750
779
  The order of ops specified in the batch has no significance.
751
780
  Only one operation of each type can be active at once in any given
752
781
  batch */
753
- static VALUE grpc_rb_call_run_batch(VALUE self, VALUE cqueue, VALUE tag,
754
- VALUE timeout, VALUE ops_hash) {
782
+ static VALUE grpc_rb_call_run_batch(VALUE self, VALUE ops_hash) {
755
783
  run_batch_stack st;
756
- grpc_call *call = NULL;
784
+ grpc_rb_call *call = NULL;
757
785
  grpc_event ev;
758
786
  grpc_call_error err;
759
787
  VALUE result = Qnil;
760
788
  VALUE rb_write_flag = rb_ivar_get(self, id_write_flag);
761
789
  unsigned write_flag = 0;
790
+ void *tag = (void*)&st;
762
791
  if (RTYPEDDATA_DATA(self) == NULL) {
763
792
  rb_raise(grpc_rb_eCallError, "Cannot run batch on closed call");
764
793
  return Qnil;
765
794
  }
766
- TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
795
+ TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call);
767
796
 
768
797
  /* Validate the ops args, adding them to a ruby array */
769
798
  if (TYPE(ops_hash) != T_HASH) {
@@ -778,7 +807,7 @@ static VALUE grpc_rb_call_run_batch(VALUE self, VALUE cqueue, VALUE tag,
778
807
 
779
808
  /* call grpc_call_start_batch, then wait for it to complete using
780
809
  * pluck_event */
781
- err = grpc_call_start_batch(call, st.ops, st.op_num, ROBJECT(tag), NULL);
810
+ err = grpc_call_start_batch(call->wrapped, st.ops, st.op_num, tag, NULL);
782
811
  if (err != GRPC_CALL_OK) {
783
812
  grpc_run_batch_stack_cleanup(&st);
784
813
  rb_raise(grpc_rb_eCallError,
@@ -786,13 +815,11 @@ static VALUE grpc_rb_call_run_batch(VALUE self, VALUE cqueue, VALUE tag,
786
815
  grpc_call_error_detail_of(err), err);
787
816
  return Qnil;
788
817
  }
789
- ev = grpc_rb_completion_queue_pluck_event(cqueue, tag, timeout);
790
- if (ev.type == GRPC_QUEUE_TIMEOUT) {
791
- grpc_run_batch_stack_cleanup(&st);
792
- rb_raise(grpc_rb_eOutOfTime, "grpc_call_start_batch timed out");
793
- return Qnil;
818
+ ev = rb_completion_queue_pluck(call->queue, tag,
819
+ gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
820
+ if (!ev.success) {
821
+ rb_raise(grpc_rb_eCallError, "call#run_batch failed somehow");
794
822
  }
795
-
796
823
  /* Build and return the BatchResult struct result,
797
824
  if there is an error, it's reflected in the status */
798
825
  result = grpc_run_batch_stack_build_result(&st);
@@ -900,7 +927,7 @@ void Init_grpc_call() {
900
927
  1);
901
928
 
902
929
  /* Add ruby analogues of the Call methods. */
903
- rb_define_method(grpc_rb_cCall, "run_batch", grpc_rb_call_run_batch, 4);
930
+ rb_define_method(grpc_rb_cCall, "run_batch", grpc_rb_call_run_batch, 1);
904
931
  rb_define_method(grpc_rb_cCall, "cancel", grpc_rb_call_cancel, 0);
905
932
  rb_define_method(grpc_rb_cCall, "close", grpc_rb_call_close, 0);
906
933
  rb_define_method(grpc_rb_cCall, "peer", grpc_rb_call_get_peer, 0);
@@ -909,6 +936,10 @@ void Init_grpc_call() {
909
936
  rb_define_method(grpc_rb_cCall, "status=", grpc_rb_call_set_status, 1);
910
937
  rb_define_method(grpc_rb_cCall, "metadata", grpc_rb_call_get_metadata, 0);
911
938
  rb_define_method(grpc_rb_cCall, "metadata=", grpc_rb_call_set_metadata, 1);
939
+ rb_define_method(grpc_rb_cCall, "trailing_metadata",
940
+ grpc_rb_call_get_trailing_metadata, 0);
941
+ rb_define_method(grpc_rb_cCall, "trailing_metadata=",
942
+ grpc_rb_call_set_trailing_metadata, 1);
912
943
  rb_define_method(grpc_rb_cCall, "write_flag", grpc_rb_call_get_write_flag, 0);
913
944
  rb_define_method(grpc_rb_cCall, "write_flag=", grpc_rb_call_set_write_flag,
914
945
  1);
@@ -917,13 +948,11 @@ void Init_grpc_call() {
917
948
 
918
949
  /* Ids used to support call attributes */
919
950
  id_metadata = rb_intern("metadata");
951
+ id_trailing_metadata = rb_intern("trailing_metadata");
920
952
  id_status = rb_intern("status");
921
953
  id_write_flag = rb_intern("write_flag");
922
954
 
923
955
  /* Ids used by the c wrapping internals. */
924
- id_cq = rb_intern("__cq");
925
- id_flags = rb_intern("__flags");
926
- id_input_md = rb_intern("__input_md");
927
956
  id_credentials = rb_intern("__credentials");
928
957
 
929
958
  /* Ids used in constructing the batch result. */
@@ -947,15 +976,19 @@ void Init_grpc_call() {
947
976
 
948
977
  /* Gets the call from the ruby object */
949
978
  grpc_call *grpc_rb_get_wrapped_call(VALUE v) {
950
- grpc_call *c = NULL;
951
- TypedData_Get_Struct(v, grpc_call, &grpc_call_data_type, c);
952
- return c;
979
+ grpc_rb_call *call = NULL;
980
+ TypedData_Get_Struct(v, grpc_rb_call, &grpc_call_data_type, call);
981
+ return call->wrapped;
953
982
  }
954
983
 
955
984
  /* Obtains the wrapped object for a given call */
956
- VALUE grpc_rb_wrap_call(grpc_call *c) {
957
- if (c == NULL) {
985
+ VALUE grpc_rb_wrap_call(grpc_call *c, grpc_completion_queue *q) {
986
+ grpc_rb_call *wrapper;
987
+ if (c == NULL || q == NULL) {
958
988
  return Qnil;
959
989
  }
960
- return TypedData_Wrap_Struct(grpc_rb_cCall, &grpc_call_data_type, c);
990
+ wrapper = ALLOC(grpc_rb_call);
991
+ wrapper->wrapped = c;
992
+ wrapper->queue = q;
993
+ return TypedData_Wrap_Struct(grpc_rb_cCall, &grpc_call_data_type, wrapper);
961
994
  }
@@ -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* c);
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
- grpc_rb_call_credentials_init_copy, 1);
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 cqueue,
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
- cq = grpc_rb_get_wrapped_completion_queue(cqueue);
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
- ROBJECT(tag));
230
-
231
- return Qnil;
232
- }
233
-
234
- /* Clones Channel instances.
231
+ tag);
235
232
 
236
- Gives Channel a consistent implementation of Ruby's object copy/dup
237
- protocol. */
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 (copy == orig) {
243
- return copy;
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 cqueue,
265
- VALUE parent, VALUE mask,
266
- VALUE method, VALUE host,
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 = grpc_rb_get_wrapped_completion_queue(cqueue);
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
- grpc_rb_channel_init_copy, 1);
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, 6);
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)));