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.

Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +127 -159
  3. data/etc/roots.pem +784 -509
  4. data/include/grpc/grpc_posix.h +8 -0
  5. data/include/grpc/impl/codegen/byte_buffer.h +5 -4
  6. data/include/grpc/impl/codegen/grpc_types.h +2 -0
  7. data/include/grpc/impl/codegen/port_platform.h +2 -1
  8. data/include/grpc/module.modulemap +15 -0
  9. data/src/core/ext/census/grpc_filter.c +3 -0
  10. data/src/core/ext/client_config/channel_connectivity.c +4 -3
  11. data/src/core/ext/client_config/client_channel.c +6 -0
  12. data/src/core/ext/client_config/subchannel.c +2 -0
  13. data/src/core/ext/client_config/subchannel_call_holder.c +2 -5
  14. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +2 -1
  15. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +2 -1
  16. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +171 -104
  17. data/src/core/ext/transport/chttp2/transport/internal.h +5 -3
  18. data/src/core/ext/transport/chttp2/transport/parsing.c +4 -3
  19. data/src/core/ext/transport/chttp2/transport/status_conversion.c +8 -2
  20. data/src/core/ext/transport/chttp2/transport/status_conversion.h +1 -1
  21. data/src/core/lib/channel/channel_stack.c +12 -1
  22. data/src/core/lib/channel/channel_stack.h +5 -0
  23. data/src/core/lib/channel/http_client_filter.c +7 -1
  24. data/src/core/lib/debug/trace.c +6 -2
  25. data/src/core/lib/iomgr/error.c +62 -19
  26. data/src/core/lib/iomgr/error.h +10 -6
  27. data/src/core/lib/iomgr/ev_epoll_linux.c +1872 -0
  28. data/src/core/lib/{surface/surface_trace.h → iomgr/ev_epoll_linux.h} +11 -12
  29. data/src/core/lib/iomgr/ev_posix.c +9 -6
  30. data/src/core/lib/iomgr/ev_posix.h +3 -0
  31. data/src/core/lib/iomgr/network_status_tracker.c +121 -0
  32. data/{include/grpc/grpc_zookeeper.h → src/core/lib/iomgr/network_status_tracker.h} +8 -26
  33. data/src/core/lib/iomgr/socket_utils_common_posix.c +22 -0
  34. data/src/core/lib/iomgr/socket_utils_posix.h +3 -0
  35. data/src/core/lib/iomgr/tcp_posix.c +6 -2
  36. data/src/core/lib/iomgr/tcp_server.h +3 -0
  37. data/src/core/lib/iomgr/tcp_server_posix.c +114 -16
  38. data/src/core/lib/iomgr/tcp_server_windows.c +1 -0
  39. data/src/core/lib/iomgr/tcp_windows.c +5 -0
  40. data/src/core/lib/iomgr/udp_server.c +28 -16
  41. data/src/core/lib/iomgr/wakeup_fd_eventfd.c +4 -2
  42. data/src/core/lib/profiling/basic_timers.c +4 -4
  43. data/src/core/lib/security/credentials/composite/composite_credentials.c +4 -3
  44. data/src/core/lib/security/credentials/credentials.c +1 -1
  45. data/src/core/lib/security/credentials/credentials.h +4 -5
  46. data/src/core/lib/security/credentials/fake/fake_credentials.c +2 -2
  47. data/src/core/lib/security/credentials/iam/iam_credentials.c +1 -1
  48. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +7 -6
  49. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +6 -4
  50. data/src/core/lib/security/credentials/plugin/plugin_credentials.c +4 -3
  51. data/src/core/lib/security/transport/client_auth_filter.c +10 -7
  52. data/src/core/lib/surface/byte_buffer_reader.c +6 -4
  53. data/src/core/lib/surface/call.c +64 -51
  54. data/src/core/lib/surface/call.h +0 -1
  55. data/src/core/lib/surface/channel.c +10 -8
  56. data/src/core/lib/surface/completion_queue.c +26 -12
  57. data/src/core/lib/surface/completion_queue.h +4 -0
  58. data/src/core/lib/surface/init.c +6 -1
  59. data/src/core/lib/surface/version.c +1 -1
  60. data/src/core/lib/transport/transport.c +62 -29
  61. data/src/core/lib/transport/transport.h +8 -5
  62. data/src/core/lib/transport/transport_op_string.c +14 -3
  63. data/src/ruby/ext/grpc/rb_byte_buffer.c +4 -1
  64. data/src/ruby/ext/grpc/rb_call.c +87 -54
  65. data/src/ruby/ext/grpc/rb_call.h +1 -1
  66. data/src/ruby/ext/grpc/rb_call_credentials.c +1 -30
  67. data/src/ruby/ext/grpc/rb_channel.c +25 -50
  68. data/src/ruby/ext/grpc/rb_channel_credentials.c +1 -31
  69. data/src/ruby/ext/grpc/rb_completion_queue.c +15 -134
  70. data/src/ruby/ext/grpc/rb_completion_queue.h +3 -7
  71. data/src/ruby/ext/grpc/rb_grpc.c +2 -4
  72. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  73. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
  74. data/src/ruby/ext/grpc/rb_server.c +81 -133
  75. data/src/ruby/ext/grpc/rb_server_credentials.c +4 -33
  76. data/src/ruby/lib/grpc/generic/active_call.rb +40 -55
  77. data/src/ruby/lib/grpc/generic/bidi_call.rb +21 -23
  78. data/src/ruby/lib/grpc/generic/client_stub.rb +20 -15
  79. data/src/ruby/lib/grpc/generic/rpc_server.rb +15 -37
  80. data/src/ruby/lib/grpc/generic/service.rb +1 -1
  81. data/src/ruby/lib/grpc/version.rb +1 -1
  82. data/src/ruby/pb/test/client.rb +25 -7
  83. data/src/ruby/pb/test/server.rb +7 -5
  84. data/src/ruby/spec/call_spec.rb +1 -2
  85. data/src/ruby/spec/channel_spec.rb +2 -3
  86. data/src/ruby/spec/client_server_spec.rb +74 -59
  87. data/src/ruby/spec/generic/active_call_spec.rb +66 -86
  88. data/src/ruby/spec/generic/client_stub_spec.rb +27 -48
  89. data/src/ruby/spec/generic/rpc_server_spec.rb +4 -34
  90. data/src/ruby/spec/pb/health/checker_spec.rb +0 -2
  91. data/src/ruby/spec/server_spec.rb +20 -24
  92. metadata +9 -8
  93. data/src/ruby/spec/completion_queue_spec.rb +0 -42
@@ -37,7 +37,6 @@
37
37
  #include "src/core/lib/channel/channel_stack.h"
38
38
  #include "src/core/lib/channel/context.h"
39
39
  #include "src/core/lib/surface/api_trace.h"
40
- #include "src/core/lib/surface/surface_trace.h"
41
40
 
42
41
  #include <grpc/grpc.h>
43
42
  #include <grpc/impl/codegen/compression_types.h>
@@ -81,7 +81,7 @@ struct grpc_channel {
81
81
  CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem))
82
82
 
83
83
  /* the protobuf library will (by default) start warning at 100megs */
84
- #define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024)
84
+ #define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024)
85
85
 
86
86
  static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg,
87
87
  grpc_error *error);
@@ -223,11 +223,12 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
223
223
  "grpc_channel_create_call("
224
224
  "channel=%p, parent_call=%p, propagation_mask=%x, cq=%p, method=%s, "
225
225
  "host=%s, "
226
- "deadline=gpr_timespec { tv_sec: %"PRId64", tv_nsec: %d, clock_type: %d }, "
226
+ "deadline=gpr_timespec { tv_sec: %" PRId64
227
+ ", tv_nsec: %d, clock_type: %d }, "
227
228
  "reserved=%p)",
228
- 10, (channel, parent_call, (unsigned)propagation_mask, cq, method, host,
229
- deadline.tv_sec, deadline.tv_nsec,
230
- (int)deadline.clock_type, reserved));
229
+ 10,
230
+ (channel, parent_call, (unsigned)propagation_mask, cq, method, host,
231
+ deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, reserved));
231
232
  GPR_ASSERT(!reserved);
232
233
  return grpc_channel_create_call_internal(
233
234
  channel, parent_call, propagation_mask, cq, NULL,
@@ -282,11 +283,12 @@ grpc_call *grpc_channel_create_registered_call(
282
283
  "grpc_channel_create_registered_call("
283
284
  "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, "
284
285
  "registered_call_handle=%p, "
285
- "deadline=gpr_timespec { tv_sec: %"PRId64", tv_nsec: %d, clock_type: %d }, "
286
+ "deadline=gpr_timespec { tv_sec: %" PRId64
287
+ ", tv_nsec: %d, clock_type: %d }, "
286
288
  "reserved=%p)",
287
289
  9, (channel, parent_call, (unsigned)propagation_mask, completion_queue,
288
- registered_call_handle, deadline.tv_sec,
289
- deadline.tv_nsec, (int)deadline.clock_type, reserved));
290
+ registered_call_handle, deadline.tv_sec, deadline.tv_nsec,
291
+ (int)deadline.clock_type, reserved));
290
292
  GPR_ASSERT(!reserved);
291
293
  return grpc_channel_create_call_internal(
292
294
  channel, parent_call, propagation_mask, completion_queue, NULL,
@@ -48,7 +48,6 @@
48
48
  #include "src/core/lib/surface/api_trace.h"
49
49
  #include "src/core/lib/surface/call.h"
50
50
  #include "src/core/lib/surface/event_string.h"
51
- #include "src/core/lib/surface/surface_trace.h"
52
51
 
53
52
  int grpc_trace_operation_failures;
54
53
 
@@ -93,6 +92,17 @@ struct grpc_completion_queue {
93
92
  static gpr_mu g_freelist_mu;
94
93
  static grpc_completion_queue *g_freelist;
95
94
 
95
+ int grpc_cq_pluck_trace;
96
+ int grpc_cq_event_timeout_trace;
97
+
98
+ #define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \
99
+ if (grpc_api_trace && \
100
+ (grpc_cq_pluck_trace || (event)->type != GRPC_QUEUE_TIMEOUT)) { \
101
+ char *_ev = grpc_event_string(event); \
102
+ gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \
103
+ gpr_free(_ev); \
104
+ }
105
+
96
106
  static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
97
107
  grpc_error *error);
98
108
 
@@ -240,7 +250,7 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
240
250
  "grpc_cq_end_op(exec_ctx=%p, cc=%p, tag=%p, error=%s, done=%p, "
241
251
  "done_arg=%p, storage=%p)",
242
252
  7, (exec_ctx, cc, tag, errmsg, done, done_arg, storage));
243
- if (grpc_trace_operation_failures) {
253
+ if (grpc_trace_operation_failures && error != GRPC_ERROR_NONE) {
244
254
  gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg);
245
255
  }
246
256
  grpc_error_free_string(errmsg);
@@ -316,10 +326,11 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
316
326
  GRPC_API_TRACE(
317
327
  "grpc_completion_queue_next("
318
328
  "cc=%p, "
319
- "deadline=gpr_timespec { tv_sec: %"PRId64", tv_nsec: %d, clock_type: %d }, "
329
+ "deadline=gpr_timespec { tv_sec: %" PRId64
330
+ ", tv_nsec: %d, clock_type: %d }, "
320
331
  "reserved=%p)",
321
- 5, (cc, deadline.tv_sec, deadline.tv_nsec,
322
- (int)deadline.clock_type, reserved));
332
+ 5, (cc, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type,
333
+ reserved));
323
334
  GPR_ASSERT(!reserved);
324
335
 
325
336
  deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
@@ -425,13 +436,16 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
425
436
 
426
437
  GPR_TIMER_BEGIN("grpc_completion_queue_pluck", 0);
427
438
 
428
- GRPC_API_TRACE(
429
- "grpc_completion_queue_pluck("
430
- "cc=%p, tag=%p, "
431
- "deadline=gpr_timespec { tv_sec: %"PRId64", tv_nsec: %d, clock_type: %d }, "
432
- "reserved=%p)",
433
- 6, (cc, tag, deadline.tv_sec, deadline.tv_nsec,
434
- (int)deadline.clock_type, reserved));
439
+ if (grpc_cq_pluck_trace) {
440
+ GRPC_API_TRACE(
441
+ "grpc_completion_queue_pluck("
442
+ "cc=%p, tag=%p, "
443
+ "deadline=gpr_timespec { tv_sec: %" PRId64
444
+ ", tv_nsec: %d, clock_type: %d }, "
445
+ "reserved=%p)",
446
+ 6, (cc, tag, deadline.tv_sec, deadline.tv_nsec,
447
+ (int)deadline.clock_type, reserved));
448
+ }
435
449
  GPR_ASSERT(!reserved);
436
450
 
437
451
  deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
@@ -39,6 +39,10 @@
39
39
  #include <grpc/grpc.h>
40
40
  #include "src/core/lib/iomgr/pollset.h"
41
41
 
42
+ /* These trace flags default to 1. The corresponding lines are only traced
43
+ if grpc_api_trace is also truthy */
44
+ extern int grpc_cq_pluck_trace;
45
+ extern int grpc_cq_event_timeout_trace;
42
46
  extern int grpc_trace_operation_failures;
43
47
 
44
48
  typedef struct grpc_cq_completion {
@@ -57,7 +57,6 @@
57
57
  #include "src/core/lib/surface/init.h"
58
58
  #include "src/core/lib/surface/lame_client.h"
59
59
  #include "src/core/lib/surface/server.h"
60
- #include "src/core/lib/surface/surface_trace.h"
61
60
  #include "src/core/lib/transport/connectivity_state.h"
62
61
  #include "src/core/lib/transport/transport_impl.h"
63
62
 
@@ -165,6 +164,12 @@ void grpc_init(void) {
165
164
  &grpc_trace_channel_stack_builder);
166
165
  grpc_register_tracer("http1", &grpc_http1_trace);
167
166
  grpc_register_tracer("compression", &grpc_compression_trace);
167
+ grpc_register_tracer("queue_pluck", &grpc_cq_pluck_trace);
168
+ // Default pluck trace to 1
169
+ grpc_cq_pluck_trace = 1;
170
+ grpc_register_tracer("queue_timeout", &grpc_cq_event_timeout_trace);
171
+ // Default timeout trace to 1
172
+ grpc_cq_event_timeout_trace = 1;
168
173
  grpc_register_tracer("op_failure", &grpc_trace_operation_failures);
169
174
  grpc_security_pre_init();
170
175
  grpc_iomgr_init();
@@ -36,4 +36,4 @@
36
36
 
37
37
  #include <grpc/grpc.h>
38
38
 
39
- const char *grpc_version_string(void) { return "0.15.0"; }
39
+ const char *grpc_version_string(void) { return "1.0.0-pre1"; }
@@ -36,6 +36,7 @@
36
36
  #include <grpc/support/atm.h>
37
37
  #include <grpc/support/log.h>
38
38
  #include <grpc/support/sync.h>
39
+ #include "src/core/lib/support/string.h"
39
40
  #include "src/core/lib/transport/transport_impl.h"
40
41
 
41
42
  #ifdef GRPC_STREAM_REFCOUNT_DEBUG
@@ -162,55 +163,87 @@ void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx,
162
163
  grpc_exec_ctx_sched(exec_ctx, op->on_complete, error, NULL);
163
164
  }
164
165
 
165
- void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
166
- grpc_status_code status) {
167
- GPR_ASSERT(status != GRPC_STATUS_OK);
168
- if (op->cancel_with_status == GRPC_STATUS_OK) {
169
- op->cancel_with_status = status;
170
- }
171
- if (op->close_with_status != GRPC_STATUS_OK) {
172
- op->close_with_status = GRPC_STATUS_OK;
173
- if (op->optional_close_message != NULL) {
174
- gpr_slice_unref(*op->optional_close_message);
175
- op->optional_close_message = NULL;
176
- }
177
- }
178
- }
179
-
180
166
  typedef struct {
181
- gpr_slice message;
167
+ grpc_error *error;
182
168
  grpc_closure *then_call;
183
169
  grpc_closure closure;
184
170
  } close_message_data;
185
171
 
186
172
  static void free_message(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) {
187
173
  close_message_data *cmd = p;
188
- gpr_slice_unref(cmd->message);
174
+ GRPC_ERROR_UNREF(cmd->error);
189
175
  if (cmd->then_call != NULL) {
190
- cmd->then_call->cb(exec_ctx, cmd->then_call->cb_arg, GRPC_ERROR_REF(error));
176
+ cmd->then_call->cb(exec_ctx, cmd->then_call->cb_arg, error);
191
177
  }
192
178
  gpr_free(cmd);
193
179
  }
194
180
 
181
+ static void add_error(grpc_transport_stream_op *op, grpc_error **which,
182
+ grpc_error *error) {
183
+ close_message_data *cmd;
184
+ cmd = gpr_malloc(sizeof(*cmd));
185
+ cmd->error = error;
186
+ cmd->then_call = op->on_complete;
187
+ grpc_closure_init(&cmd->closure, free_message, cmd);
188
+ op->on_complete = &cmd->closure;
189
+ *which = error;
190
+ }
191
+
192
+ void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
193
+ grpc_status_code status) {
194
+ GPR_ASSERT(status != GRPC_STATUS_OK);
195
+ if (op->cancel_error == GRPC_ERROR_NONE) {
196
+ op->cancel_error = grpc_error_set_int(GRPC_ERROR_CANCELLED,
197
+ GRPC_ERROR_INT_GRPC_STATUS, status);
198
+ op->close_error = GRPC_ERROR_NONE;
199
+ }
200
+ }
201
+
202
+ void grpc_transport_stream_op_add_cancellation_with_message(
203
+ grpc_transport_stream_op *op, grpc_status_code status,
204
+ gpr_slice *optional_message) {
205
+ GPR_ASSERT(status != GRPC_STATUS_OK);
206
+ if (op->cancel_error != GRPC_ERROR_NONE) {
207
+ if (optional_message) {
208
+ gpr_slice_unref(*optional_message);
209
+ }
210
+ return;
211
+ }
212
+ grpc_error *error;
213
+ if (optional_message != NULL) {
214
+ char *msg = gpr_dump_slice(*optional_message, GPR_DUMP_ASCII);
215
+ error = grpc_error_set_str(GRPC_ERROR_CREATE(msg),
216
+ GRPC_ERROR_STR_GRPC_MESSAGE, msg);
217
+ gpr_free(msg);
218
+ gpr_slice_unref(*optional_message);
219
+ } else {
220
+ error = GRPC_ERROR_CREATE("Call cancelled");
221
+ }
222
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status);
223
+ add_error(op, &op->close_error, error);
224
+ }
225
+
195
226
  void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op,
196
227
  grpc_status_code status,
197
228
  gpr_slice *optional_message) {
198
- close_message_data *cmd;
199
229
  GPR_ASSERT(status != GRPC_STATUS_OK);
200
- if (op->cancel_with_status != GRPC_STATUS_OK ||
201
- op->close_with_status != GRPC_STATUS_OK) {
230
+ if (op->cancel_error != GRPC_ERROR_NONE ||
231
+ op->close_error != GRPC_ERROR_NONE) {
202
232
  if (optional_message) {
203
233
  gpr_slice_unref(*optional_message);
204
234
  }
205
235
  return;
206
236
  }
207
- if (optional_message) {
208
- cmd = gpr_malloc(sizeof(*cmd));
209
- cmd->message = *optional_message;
210
- cmd->then_call = op->on_complete;
211
- grpc_closure_init(&cmd->closure, free_message, cmd);
212
- op->on_complete = &cmd->closure;
213
- op->optional_close_message = &cmd->message;
237
+ grpc_error *error;
238
+ if (optional_message != NULL) {
239
+ char *msg = gpr_dump_slice(*optional_message, GPR_DUMP_ASCII);
240
+ error = grpc_error_set_str(GRPC_ERROR_CREATE(msg),
241
+ GRPC_ERROR_STR_GRPC_MESSAGE, msg);
242
+ gpr_free(msg);
243
+ gpr_slice_unref(*optional_message);
244
+ } else {
245
+ error = GRPC_ERROR_CREATE("Call force closed");
214
246
  }
215
- op->close_with_status = status;
247
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status);
248
+ add_error(op, &op->close_error, error);
216
249
  }
@@ -135,13 +135,12 @@ typedef struct grpc_transport_stream_op {
135
135
  /** Collect any stats into provided buffer, zero internal stat counters */
136
136
  grpc_transport_stream_stats *collect_stats;
137
137
 
138
- /** If != GRPC_STATUS_OK, cancel this stream */
139
- grpc_status_code cancel_with_status;
138
+ /** If != GRPC_ERROR_NONE, cancel this stream */
139
+ grpc_error *cancel_error;
140
140
 
141
- /** If != GRPC_STATUS_OK, send grpc-status, grpc-message, and close this
141
+ /** If != GRPC_ERROR, send grpc-status, grpc-message, and close this
142
142
  stream for both reading and writing */
143
- grpc_status_code close_with_status;
144
- gpr_slice *optional_close_message;
143
+ grpc_error *close_error;
145
144
 
146
145
  /* Indexes correspond to grpc_context_index enum values */
147
146
  grpc_call_context_element *context;
@@ -222,6 +221,10 @@ void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx,
222
221
  void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
223
222
  grpc_status_code status);
224
223
 
224
+ void grpc_transport_stream_op_add_cancellation_with_message(
225
+ grpc_transport_stream_op *op, grpc_status_code status,
226
+ gpr_slice *optional_message);
227
+
225
228
  void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op,
226
229
  grpc_status_code status,
227
230
  gpr_slice *optional_message);
@@ -63,7 +63,7 @@ static void put_metadata_list(gpr_strvec *b, grpc_metadata_batch md) {
63
63
  }
64
64
  if (gpr_time_cmp(md.deadline, gpr_inf_future(md.deadline.clock_type)) != 0) {
65
65
  char *tmp;
66
- gpr_asprintf(&tmp, " deadline=%"PRId64".%09d", md.deadline.tv_sec,
66
+ gpr_asprintf(&tmp, " deadline=%" PRId64 ".%09d", md.deadline.tv_sec,
67
67
  md.deadline.tv_nsec);
68
68
  gpr_strvec_add(b, tmp);
69
69
  }
@@ -119,10 +119,21 @@ char *grpc_transport_stream_op_string(grpc_transport_stream_op *op) {
119
119
  gpr_strvec_add(&b, gpr_strdup("RECV_TRAILING_METADATA"));
120
120
  }
121
121
 
122
- if (op->cancel_with_status != GRPC_STATUS_OK) {
122
+ if (op->cancel_error != GRPC_ERROR_NONE) {
123
123
  if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
124
124
  first = 0;
125
- gpr_asprintf(&tmp, "CANCEL:%d", op->cancel_with_status);
125
+ const char *msg = grpc_error_string(op->cancel_error);
126
+ gpr_asprintf(&tmp, "CANCEL:%s", msg);
127
+ grpc_error_free_string(msg);
128
+ gpr_strvec_add(&b, tmp);
129
+ }
130
+
131
+ if (op->close_error != GRPC_ERROR_NONE) {
132
+ if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
133
+ first = 0;
134
+ const char *msg = grpc_error_string(op->close_error);
135
+ gpr_asprintf(&tmp, "CLOSE:%s", msg);
136
+ grpc_error_free_string(msg);
126
137
  gpr_strvec_add(&b, tmp);
127
138
  }
128
139
 
@@ -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
  }