grpc 1.9.0.pre2 → 1.9.0.pre3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b727fc38e0b40853ad0d7066f43e890329d3e71f6ca709299ca8c70e960e2a12
4
- data.tar.gz: 5647639c196148ba184ff497cacaf6e985bab50127cf0f5134edc4b01bbd6c4b
3
+ metadata.gz: 42b494831008d6915361053c5d39fa06f4c274daa76376ed1d73994ba56a8ed1
4
+ data.tar.gz: 59c61af48ea465e644657e57ff7f8f01ed18ab597f84542add663891e88d22a5
5
5
  SHA512:
6
- metadata.gz: c416db0869ce536011ed2f16ad0197297ea6cf5f2d8ea21b3405b5f46115a7097f8ba410af093b2780050f3cef91062422266d1efb6249f8c9d16f38c6063ff1
7
- data.tar.gz: 8665dca460ebf3d8b6ca61b353e317aff12e0038e32416817a0321fe5823e4196f6ee0ea3a32e4b95227b629e7c90cb6e3f0647665168147d3580d7e1e6e6526
6
+ metadata.gz: 3787efa86a57047f1cc1c2c39539c580ee191157eb3ab5d3024abfeb8a7af0ac25100d402f09ef41702b885df95bd684389f4ea14ce59abdc22bce9e48b32524
7
+ data.tar.gz: 135ff4dbbef3ffd794266da6852acac137f1e2e4de06b438dfa7ff547cbf8c5802da3d262b1a9ee496bbc95e3ec738867bf2cae2fe978c67dac2ab19c1810b9b
data/Makefile CHANGED
@@ -418,9 +418,9 @@ E = @echo
418
418
  Q = @
419
419
  endif
420
420
 
421
- CORE_VERSION = 5.0.0-pre2
422
- CPP_VERSION = 1.9.0-pre2
423
- CSHARP_VERSION = 1.9.0-pre2
421
+ CORE_VERSION = 5.0.0-pre3
422
+ CPP_VERSION = 1.9.0-pre3
423
+ CSHARP_VERSION = 1.9.0-pre3
424
424
 
425
425
  CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
426
426
  CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -1233,6 +1233,7 @@ boringssl_tab_test: $(BINDIR)/$(CONFIG)/boringssl_tab_test
1233
1233
  boringssl_v3name_test: $(BINDIR)/$(CONFIG)/boringssl_v3name_test
1234
1234
  badreq_bad_client_test: $(BINDIR)/$(CONFIG)/badreq_bad_client_test
1235
1235
  connection_prefix_bad_client_test: $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test
1236
+ duplicate_header_bad_client_test: $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test
1236
1237
  head_of_line_blocking_bad_client_test: $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test
1237
1238
  headers_bad_client_test: $(BINDIR)/$(CONFIG)/headers_bad_client_test
1238
1239
  initial_settings_frame_bad_client_test: $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
@@ -1485,6 +1486,7 @@ buildtests_c: privatelibs_c \
1485
1486
  $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 \
1486
1487
  $(BINDIR)/$(CONFIG)/badreq_bad_client_test \
1487
1488
  $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \
1489
+ $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test \
1488
1490
  $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test \
1489
1491
  $(BINDIR)/$(CONFIG)/headers_bad_client_test \
1490
1492
  $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \
@@ -2023,6 +2025,8 @@ test_c: buildtests_c
2023
2025
  $(Q) $(BINDIR)/$(CONFIG)/badreq_bad_client_test || ( echo test badreq_bad_client_test failed ; exit 1 )
2024
2026
  $(E) "[RUN] Testing connection_prefix_bad_client_test"
2025
2027
  $(Q) $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test || ( echo test connection_prefix_bad_client_test failed ; exit 1 )
2028
+ $(E) "[RUN] Testing duplicate_header_bad_client_test"
2029
+ $(Q) $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test || ( echo test duplicate_header_bad_client_test failed ; exit 1 )
2026
2030
  $(E) "[RUN] Testing head_of_line_blocking_bad_client_test"
2027
2031
  $(Q) $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test || ( echo test head_of_line_blocking_bad_client_test failed ; exit 1 )
2028
2032
  $(E) "[RUN] Testing headers_bad_client_test"
@@ -18726,6 +18730,26 @@ ifneq ($(NO_DEPS),true)
18726
18730
  endif
18727
18731
 
18728
18732
 
18733
+ DUPLICATE_HEADER_BAD_CLIENT_TEST_SRC = \
18734
+ test/core/bad_client/tests/duplicate_header.cc \
18735
+
18736
+ DUPLICATE_HEADER_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DUPLICATE_HEADER_BAD_CLIENT_TEST_SRC))))
18737
+
18738
+
18739
+ $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test: $(DUPLICATE_HEADER_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
18740
+ $(E) "[LD] Linking $@"
18741
+ $(Q) mkdir -p `dirname $@`
18742
+ $(Q) $(LD) $(LDFLAGS) $(DUPLICATE_HEADER_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/duplicate_header_bad_client_test
18743
+
18744
+ $(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/duplicate_header.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
18745
+
18746
+ deps_duplicate_header_bad_client_test: $(DUPLICATE_HEADER_BAD_CLIENT_TEST_OBJS:.o=.dep)
18747
+
18748
+ ifneq ($(NO_DEPS),true)
18749
+ -include $(DUPLICATE_HEADER_BAD_CLIENT_TEST_OBJS:.o=.dep)
18750
+ endif
18751
+
18752
+
18729
18753
  HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC = \
18730
18754
  test/core/bad_client/tests/head_of_line_blocking.cc \
18731
18755
 
@@ -1003,7 +1003,7 @@ static void create_subchannel_call_locked(grpc_call_element* elem,
1003
1003
  grpc_error* error) {
1004
1004
  channel_data* chand = (channel_data*)elem->channel_data;
1005
1005
  call_data* calld = (call_data*)elem->call_data;
1006
- const grpc_core::ConnectedSubchannel::CallArgs call_args = {
1006
+ const grpc_connected_subchannel_call_args call_args = {
1007
1007
  calld->pollent, // pollent
1008
1008
  calld->path, // path
1009
1009
  calld->call_start_time, // start_time
@@ -1012,8 +1012,8 @@ static void create_subchannel_call_locked(grpc_call_element* elem,
1012
1012
  calld->pick.subchannel_call_context, // context
1013
1013
  calld->call_combiner // call_combiner
1014
1014
  };
1015
- grpc_error* new_error = calld->pick.connected_subchannel->CreateCall(
1016
- call_args, &calld->subchannel_call);
1015
+ grpc_error* new_error = grpc_connected_subchannel_create_call(
1016
+ calld->pick.connected_subchannel, &call_args, &calld->subchannel_call);
1017
1017
  if (grpc_client_channel_trace.enabled()) {
1018
1018
  gpr_log(GPR_DEBUG, "chand=%p calld=%p: create subchannel_call=%p: error=%s",
1019
1019
  chand, calld, calld->subchannel_call, grpc_error_string(new_error));
@@ -1463,7 +1463,7 @@ static void cc_destroy_call_elem(grpc_call_element* elem,
1463
1463
  }
1464
1464
  GPR_ASSERT(calld->waiting_for_pick_batches_count == 0);
1465
1465
  if (calld->pick.connected_subchannel != nullptr) {
1466
- calld->pick.connected_subchannel.reset();
1466
+ GRPC_CONNECTED_SUBCHANNEL_UNREF(calld->pick.connected_subchannel, "picked");
1467
1467
  }
1468
1468
  for (size_t i = 0; i < GRPC_CONTEXT_COUNT; ++i) {
1469
1469
  if (calld->pick.subchannel_call_context[i].value != nullptr) {
@@ -55,9 +55,9 @@ typedef struct grpc_lb_policy_pick_state {
55
55
  grpc_linked_mdelem lb_token_mdelem_storage;
56
56
  /// Closure to run when pick is complete, if not completed synchronously.
57
57
  grpc_closure* on_complete;
58
- /// Will be set to the selected subchannel, or nullptr on failure or when
58
+ /// Will be set to the selected subchannel, or NULL on failure or when
59
59
  /// the LB policy decides to drop the call.
60
- grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel> connected_subchannel;
60
+ grpc_connected_subchannel* connected_subchannel;
61
61
  /// Will be populated with context to pass to the subchannel call, if needed.
62
62
  grpc_call_context_element subchannel_call_context[GRPC_CONTEXT_COUNT];
63
63
  /// Upon success, \a *user_data will be set to whatever opaque information
@@ -153,8 +153,7 @@ void grpc_lb_policy_shutdown_locked(grpc_lb_policy* policy,
153
153
  int grpc_lb_policy_pick_locked(grpc_lb_policy* policy,
154
154
  grpc_lb_policy_pick_state* pick);
155
155
 
156
- /** Perform a connected subchannel ping (see \a
157
- grpc_core::ConnectedSubchannel::Ping)
156
+ /** Perform a connected subchannel ping (see \a grpc_connected_subchannel_ping)
158
157
  against one of the connected subchannels managed by \a policy. */
159
158
  void grpc_lb_policy_ping_one_locked(grpc_lb_policy* policy,
160
159
  grpc_closure* on_initiate,
@@ -939,7 +939,7 @@ static void glb_shutdown_locked(grpc_lb_policy* pol,
939
939
  }
940
940
  gpr_free(pp);
941
941
  } else {
942
- pp->pick->connected_subchannel.reset();
942
+ pp->pick->connected_subchannel = nullptr;
943
943
  GRPC_CLOSURE_SCHED(&pp->on_complete, GRPC_ERROR_REF(error));
944
944
  }
945
945
  pp = next;
@@ -976,7 +976,7 @@ static void glb_cancel_pick_locked(grpc_lb_policy* pol,
976
976
  while (pp != nullptr) {
977
977
  pending_pick* next = pp->next;
978
978
  if (pp->pick == pick) {
979
- pick->connected_subchannel.reset();
979
+ pick->connected_subchannel = nullptr;
980
980
  GRPC_CLOSURE_SCHED(&pp->on_complete,
981
981
  GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
982
982
  "Pick Cancelled", &error, 1));
@@ -81,7 +81,7 @@ static void pf_shutdown_locked(grpc_lb_policy* pol,
81
81
  GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
82
82
  }
83
83
  } else {
84
- pick->connected_subchannel.reset();
84
+ pick->connected_subchannel = nullptr;
85
85
  GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_REF(error));
86
86
  }
87
87
  }
@@ -111,7 +111,7 @@ static void pf_cancel_pick_locked(grpc_lb_policy* pol,
111
111
  while (pp != nullptr) {
112
112
  grpc_lb_policy_pick_state* next = pp->next;
113
113
  if (pp == pick) {
114
- pick->connected_subchannel.reset();
114
+ pick->connected_subchannel = nullptr;
115
115
  GRPC_CLOSURE_SCHED(pick->on_complete,
116
116
  GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
117
117
  "Pick Cancelled", &error, 1));
@@ -176,7 +176,8 @@ static int pf_pick_locked(grpc_lb_policy* pol,
176
176
  pick_first_lb_policy* p = (pick_first_lb_policy*)pol;
177
177
  // If we have a selected subchannel already, return synchronously.
178
178
  if (p->selected != nullptr) {
179
- pick->connected_subchannel = p->selected->connected_subchannel;
179
+ pick->connected_subchannel = GRPC_CONNECTED_SUBCHANNEL_REF(
180
+ p->selected->connected_subchannel, "picked");
180
181
  return 1;
181
182
  }
182
183
  // No subchannel selected yet, so handle asynchronously.
@@ -216,7 +217,8 @@ static void pf_ping_one_locked(grpc_lb_policy* pol, grpc_closure* on_initiate,
216
217
  grpc_closure* on_ack) {
217
218
  pick_first_lb_policy* p = (pick_first_lb_policy*)pol;
218
219
  if (p->selected) {
219
- p->selected->connected_subchannel->Ping(on_initiate, on_ack);
220
+ grpc_connected_subchannel_ping(p->selected->connected_subchannel,
221
+ on_initiate, on_ack);
220
222
  } else {
221
223
  GRPC_CLOSURE_SCHED(on_initiate,
222
224
  GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected"));
@@ -295,7 +297,8 @@ static void pf_update_locked(grpc_lb_policy* policy,
295
297
  subchannel_list->num_subchannels);
296
298
  }
297
299
  if (p->selected->connected_subchannel != nullptr) {
298
- sd->connected_subchannel = p->selected->connected_subchannel;
300
+ sd->connected_subchannel = GRPC_CONNECTED_SUBCHANNEL_REF(
301
+ p->selected->connected_subchannel, "pf_update_includes_selected");
299
302
  }
300
303
  p->selected = sd;
301
304
  if (p->subchannel_list != nullptr) {
@@ -407,8 +410,8 @@ static void pf_connectivity_changed_locked(void* arg, grpc_error* error) {
407
410
  // re-resolution is introduced. But we need to investigate whether we
408
411
  // really want to take any action instead of waiting for the selected
409
412
  // subchannel reconnecting.
410
- GPR_ASSERT(sd->curr_connectivity_state != GRPC_CHANNEL_SHUTDOWN);
411
- if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
413
+ if (sd->curr_connectivity_state == GRPC_CHANNEL_SHUTDOWN ||
414
+ sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
412
415
  // If the selected channel goes bad, request a re-resolution.
413
416
  grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_IDLE,
414
417
  GRPC_ERROR_NONE,
@@ -416,19 +419,20 @@ static void pf_connectivity_changed_locked(void* arg, grpc_error* error) {
416
419
  p->started_picking = false;
417
420
  grpc_lb_policy_try_reresolve(&p->base, &grpc_lb_pick_first_trace,
418
421
  GRPC_ERROR_NONE);
419
- // in transient failure. Rely on re-resolution to recover.
420
- p->selected = nullptr;
421
- grpc_lb_subchannel_data_stop_connectivity_watch(sd);
422
- grpc_lb_subchannel_list_unref_for_connectivity_watch(
423
- sd->subchannel_list, "pf_selected_shutdown");
424
- grpc_lb_subchannel_data_unref_subchannel(
425
- sd, "pf_selected_shutdown"); // Unrefs connected subchannel
426
422
  } else {
427
423
  grpc_connectivity_state_set(&p->state_tracker,
428
424
  sd->curr_connectivity_state,
429
425
  GRPC_ERROR_REF(error), "selected_changed");
426
+ }
427
+ if (sd->curr_connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
430
428
  // Renew notification.
431
429
  grpc_lb_subchannel_data_start_connectivity_watch(sd);
430
+ } else {
431
+ p->selected = nullptr;
432
+ grpc_lb_subchannel_data_stop_connectivity_watch(sd);
433
+ grpc_lb_subchannel_list_unref_for_connectivity_watch(
434
+ sd->subchannel_list, "pf_selected_shutdown");
435
+ grpc_lb_subchannel_data_unref_subchannel(sd, "pf_selected_shutdown");
432
436
  }
433
437
  }
434
438
  return;
@@ -446,8 +450,6 @@ static void pf_connectivity_changed_locked(void* arg, grpc_error* error) {
446
450
  case GRPC_CHANNEL_READY: {
447
451
  // Case 2. Promote p->latest_pending_subchannel_list to
448
452
  // p->subchannel_list.
449
- sd->connected_subchannel =
450
- grpc_subchannel_get_connected_subchannel(sd->subchannel);
451
453
  if (sd->subchannel_list == p->latest_pending_subchannel_list) {
452
454
  GPR_ASSERT(p->subchannel_list != nullptr);
453
455
  grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list,
@@ -458,6 +460,9 @@ static void pf_connectivity_changed_locked(void* arg, grpc_error* error) {
458
460
  // Cases 1 and 2.
459
461
  grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_READY,
460
462
  GRPC_ERROR_NONE, "connecting_ready");
463
+ sd->connected_subchannel = GRPC_CONNECTED_SUBCHANNEL_REF(
464
+ grpc_subchannel_get_connected_subchannel(sd->subchannel),
465
+ "connected");
461
466
  p->selected = sd;
462
467
  if (grpc_lb_pick_first_trace.enabled()) {
463
468
  gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", (void*)p,
@@ -469,7 +474,8 @@ static void pf_connectivity_changed_locked(void* arg, grpc_error* error) {
469
474
  grpc_lb_policy_pick_state* pick;
470
475
  while ((pick = p->pending_picks)) {
471
476
  p->pending_picks = pick->next;
472
- pick->connected_subchannel = p->selected->connected_subchannel;
477
+ pick->connected_subchannel = GRPC_CONNECTED_SUBCHANNEL_REF(
478
+ p->selected->connected_subchannel, "picked");
473
479
  if (grpc_lb_pick_first_trace.enabled()) {
474
480
  gpr_log(GPR_INFO,
475
481
  "Servicing pending pick with selected subchannel %p",
@@ -514,8 +520,39 @@ static void pf_connectivity_changed_locked(void* arg, grpc_error* error) {
514
520
  grpc_lb_subchannel_data_start_connectivity_watch(sd);
515
521
  break;
516
522
  }
517
- case GRPC_CHANNEL_SHUTDOWN:
518
- GPR_UNREACHABLE_CODE(break);
523
+ case GRPC_CHANNEL_SHUTDOWN: {
524
+ grpc_lb_subchannel_data_stop_connectivity_watch(sd);
525
+ grpc_lb_subchannel_data_unref_subchannel(sd, "pf_candidate_shutdown");
526
+ // Advance to next subchannel and check its state.
527
+ grpc_lb_subchannel_data* original_sd = sd;
528
+ do {
529
+ sd->subchannel_list->checking_subchannel =
530
+ (sd->subchannel_list->checking_subchannel + 1) %
531
+ sd->subchannel_list->num_subchannels;
532
+ sd = &sd->subchannel_list
533
+ ->subchannels[sd->subchannel_list->checking_subchannel];
534
+ } while (sd->subchannel == nullptr && sd != original_sd);
535
+ if (sd == original_sd) {
536
+ grpc_lb_subchannel_list_unref_for_connectivity_watch(
537
+ sd->subchannel_list, "pf_exhausted_subchannels");
538
+ if (sd->subchannel_list == p->subchannel_list) {
539
+ grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_IDLE,
540
+ GRPC_ERROR_NONE,
541
+ "exhausted_subchannels+reresolve");
542
+ p->started_picking = false;
543
+ grpc_lb_policy_try_reresolve(&p->base, &grpc_lb_pick_first_trace,
544
+ GRPC_ERROR_NONE);
545
+ }
546
+ } else {
547
+ if (sd->subchannel_list == p->subchannel_list) {
548
+ grpc_connectivity_state_set(
549
+ &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
550
+ GRPC_ERROR_REF(error), "subchannel_failed");
551
+ }
552
+ // Reuses the connectivity refs from the previous watch.
553
+ grpc_lb_subchannel_data_start_connectivity_watch(sd);
554
+ }
555
+ }
519
556
  }
520
557
  }
521
558
 
@@ -128,7 +128,7 @@ static void update_last_ready_subchannel_index_locked(round_robin_lb_policy* p,
128
128
  (void*)p, (unsigned long)last_ready_index,
129
129
  (void*)p->subchannel_list->subchannels[last_ready_index].subchannel,
130
130
  (void*)p->subchannel_list->subchannels[last_ready_index]
131
- .connected_subchannel.get());
131
+ .connected_subchannel);
132
132
  }
133
133
  }
134
134
 
@@ -163,7 +163,7 @@ static void rr_shutdown_locked(grpc_lb_policy* pol,
163
163
  GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
164
164
  }
165
165
  } else {
166
- pick->connected_subchannel.reset();
166
+ pick->connected_subchannel = nullptr;
167
167
  GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_REF(error));
168
168
  }
169
169
  }
@@ -193,7 +193,7 @@ static void rr_cancel_pick_locked(grpc_lb_policy* pol,
193
193
  while (pp != nullptr) {
194
194
  grpc_lb_policy_pick_state* next = pp->next;
195
195
  if (pp == pick) {
196
- pick->connected_subchannel.reset();
196
+ pick->connected_subchannel = nullptr;
197
197
  GRPC_CLOSURE_SCHED(pick->on_complete,
198
198
  GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
199
199
  "Pick cancelled", &error, 1));
@@ -217,7 +217,7 @@ static void rr_cancel_picks_locked(grpc_lb_policy* pol,
217
217
  grpc_lb_policy_pick_state* next = pick->next;
218
218
  if ((pick->initial_metadata_flags & initial_metadata_flags_mask) ==
219
219
  initial_metadata_flags_eq) {
220
- pick->connected_subchannel.reset();
220
+ pick->connected_subchannel = nullptr;
221
221
  GRPC_CLOSURE_SCHED(pick->on_complete,
222
222
  GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
223
223
  "Pick cancelled", &error, 1));
@@ -263,7 +263,8 @@ static int rr_pick_locked(grpc_lb_policy* pol,
263
263
  /* readily available, report right away */
264
264
  grpc_lb_subchannel_data* sd =
265
265
  &p->subchannel_list->subchannels[next_ready_index];
266
- pick->connected_subchannel = sd->connected_subchannel;
266
+ pick->connected_subchannel =
267
+ GRPC_CONNECTED_SUBCHANNEL_REF(sd->connected_subchannel, "rr_picked");
267
268
  if (pick->user_data != nullptr) {
268
269
  *pick->user_data = sd->user_data;
269
270
  }
@@ -272,8 +273,8 @@ static int rr_pick_locked(grpc_lb_policy* pol,
272
273
  GPR_DEBUG,
273
274
  "[RR %p] Picked target <-- Subchannel %p (connected %p) (sl %p, "
274
275
  "index %" PRIuPTR ")",
275
- p, sd->subchannel, pick->connected_subchannel.get(),
276
- sd->subchannel_list, next_ready_index);
276
+ p, sd->subchannel, pick->connected_subchannel, sd->subchannel_list,
277
+ next_ready_index);
277
278
  }
278
279
  /* only advance the last picked pointer if the selection was used */
279
280
  update_last_ready_subchannel_index_locked(p, next_ready_index);
@@ -291,14 +292,15 @@ static int rr_pick_locked(grpc_lb_policy* pol,
291
292
 
292
293
  static void update_state_counters_locked(grpc_lb_subchannel_data* sd) {
293
294
  grpc_lb_subchannel_list* subchannel_list = sd->subchannel_list;
294
- GPR_ASSERT(sd->prev_connectivity_state != GRPC_CHANNEL_SHUTDOWN);
295
- GPR_ASSERT(sd->curr_connectivity_state != GRPC_CHANNEL_SHUTDOWN);
296
295
  if (sd->prev_connectivity_state == GRPC_CHANNEL_READY) {
297
296
  GPR_ASSERT(subchannel_list->num_ready > 0);
298
297
  --subchannel_list->num_ready;
299
298
  } else if (sd->prev_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
300
299
  GPR_ASSERT(subchannel_list->num_transient_failures > 0);
301
300
  --subchannel_list->num_transient_failures;
301
+ } else if (sd->prev_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
302
+ GPR_ASSERT(subchannel_list->num_shutdown > 0);
303
+ --subchannel_list->num_shutdown;
302
304
  } else if (sd->prev_connectivity_state == GRPC_CHANNEL_IDLE) {
303
305
  GPR_ASSERT(subchannel_list->num_idle > 0);
304
306
  --subchannel_list->num_idle;
@@ -308,6 +310,8 @@ static void update_state_counters_locked(grpc_lb_subchannel_data* sd) {
308
310
  ++subchannel_list->num_ready;
309
311
  } else if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
310
312
  ++subchannel_list->num_transient_failures;
313
+ } else if (sd->curr_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
314
+ ++subchannel_list->num_shutdown;
311
315
  } else if (sd->curr_connectivity_state == GRPC_CHANNEL_IDLE) {
312
316
  ++subchannel_list->num_idle;
313
317
  }
@@ -407,7 +411,6 @@ static void rr_connectivity_changed_locked(void* arg, grpc_error* error) {
407
411
  // either the current or latest pending subchannel lists.
408
412
  GPR_ASSERT(sd->subchannel_list == p->subchannel_list ||
409
413
  sd->subchannel_list == p->latest_pending_subchannel_list);
410
- GPR_ASSERT(sd->pending_connectivity_state_unsafe != GRPC_CHANNEL_SHUTDOWN);
411
414
  // Now that we're inside the combiner, copy the pending connectivity
412
415
  // state (which was set by the connectivity state watcher) to
413
416
  // curr_connectivity_state, which is what we use inside of the combiner.
@@ -415,17 +418,18 @@ static void rr_connectivity_changed_locked(void* arg, grpc_error* error) {
415
418
  // Update state counters and new overall state.
416
419
  update_state_counters_locked(sd);
417
420
  update_lb_connectivity_status_locked(sd, GRPC_ERROR_REF(error));
418
- // If the sd's new state is TRANSIENT_FAILURE, unref the *connected*
419
- // subchannel, if any.
420
- switch (sd->curr_connectivity_state) {
421
- case GRPC_CHANNEL_TRANSIENT_FAILURE: {
422
- sd->connected_subchannel.reset();
423
- break;
424
- }
425
- case GRPC_CHANNEL_READY: {
421
+ // If the sd's new state is SHUTDOWN, unref the subchannel.
422
+ if (sd->curr_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
423
+ grpc_lb_subchannel_data_stop_connectivity_watch(sd);
424
+ grpc_lb_subchannel_data_unref_subchannel(sd, "rr_connectivity_shutdown");
425
+ grpc_lb_subchannel_list_unref_for_connectivity_watch(
426
+ sd->subchannel_list, "rr_connectivity_shutdown");
427
+ } else { // sd not in SHUTDOWN
428
+ if (sd->curr_connectivity_state == GRPC_CHANNEL_READY) {
426
429
  if (sd->connected_subchannel == nullptr) {
427
- sd->connected_subchannel =
428
- grpc_subchannel_get_connected_subchannel(sd->subchannel);
430
+ sd->connected_subchannel = GRPC_CONNECTED_SUBCHANNEL_REF(
431
+ grpc_subchannel_get_connected_subchannel(sd->subchannel),
432
+ "connected");
429
433
  }
430
434
  if (sd->subchannel_list != p->subchannel_list) {
431
435
  // promote sd->subchannel_list to p->subchannel_list.
@@ -468,7 +472,8 @@ static void rr_connectivity_changed_locked(void* arg, grpc_error* error) {
468
472
  grpc_lb_policy_pick_state* pick;
469
473
  while ((pick = p->pending_picks)) {
470
474
  p->pending_picks = pick->next;
471
- pick->connected_subchannel = selected->connected_subchannel;
475
+ pick->connected_subchannel = GRPC_CONNECTED_SUBCHANNEL_REF(
476
+ selected->connected_subchannel, "rr_picked");
472
477
  if (pick->user_data != nullptr) {
473
478
  *pick->user_data = selected->user_data;
474
479
  }
@@ -481,15 +486,10 @@ static void rr_connectivity_changed_locked(void* arg, grpc_error* error) {
481
486
  }
482
487
  GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
483
488
  }
484
- break;
485
489
  }
486
- case GRPC_CHANNEL_SHUTDOWN:
487
- GPR_UNREACHABLE_CODE(return );
488
- case GRPC_CHANNEL_CONNECTING:
489
- case GRPC_CHANNEL_IDLE:; // fallthrough
490
+ // Renew notification.
491
+ grpc_lb_subchannel_data_start_connectivity_watch(sd);
490
492
  }
491
- // Renew notification.
492
- grpc_lb_subchannel_data_start_connectivity_watch(sd);
493
493
  }
494
494
 
495
495
  static grpc_connectivity_state rr_check_connectivity_locked(
@@ -513,9 +513,10 @@ static void rr_ping_one_locked(grpc_lb_policy* pol, grpc_closure* on_initiate,
513
513
  if (next_ready_index < p->subchannel_list->num_subchannels) {
514
514
  grpc_lb_subchannel_data* selected =
515
515
  &p->subchannel_list->subchannels[next_ready_index];
516
- grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel> target =
517
- selected->connected_subchannel;
518
- target->Ping(on_initiate, on_ack);
516
+ grpc_connected_subchannel* target = GRPC_CONNECTED_SUBCHANNEL_REF(
517
+ selected->connected_subchannel, "rr_ping");
518
+ grpc_connected_subchannel_ping(target, on_initiate, on_ack);
519
+ GRPC_CONNECTED_SUBCHANNEL_UNREF(target, "rr_ping");
519
520
  } else {
520
521
  GRPC_CLOSURE_SCHED(on_initiate, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
521
522
  "Round Robin not connected"));
@@ -42,7 +42,10 @@ void grpc_lb_subchannel_data_unref_subchannel(grpc_lb_subchannel_data* sd,
42
42
  }
43
43
  GRPC_SUBCHANNEL_UNREF(sd->subchannel, reason);
44
44
  sd->subchannel = nullptr;
45
- sd->connected_subchannel.reset();
45
+ if (sd->connected_subchannel != nullptr) {
46
+ GRPC_CONNECTED_SUBCHANNEL_UNREF(sd->connected_subchannel, reason);
47
+ sd->connected_subchannel = nullptr;
48
+ }
46
49
  if (sd->user_data != nullptr) {
47
50
  GPR_ASSERT(sd->user_data_vtable != nullptr);
48
51
  sd->user_data_vtable->destroy(sd->user_data);
@@ -22,7 +22,6 @@
22
22
  #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
23
23
  #include "src/core/ext/filters/client_channel/subchannel.h"
24
24
  #include "src/core/lib/debug/trace.h"
25
- #include "src/core/lib/gpr++/ref_counted_ptr.h"
26
25
  #include "src/core/lib/transport/connectivity_state.h"
27
26
 
28
27
  // TODO(roth): This code is intended to be shared between pick_first and
@@ -44,7 +43,7 @@ typedef struct {
44
43
  grpc_lb_subchannel_list* subchannel_list;
45
44
  /** subchannel itself */
46
45
  grpc_subchannel* subchannel;
47
- grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel> connected_subchannel;
46
+ grpc_connected_subchannel* connected_subchannel;
48
47
  /** Is a connectivity notification pending? */
49
48
  bool connectivity_notification_pending;
50
49
  /** notification that connectivity has changed on subchannel */
@@ -56,6 +56,10 @@
56
56
  #define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120
57
57
  #define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2
58
58
 
59
+ #define GET_CONNECTED_SUBCHANNEL(subchannel, barrier) \
60
+ ((grpc_connected_subchannel*)(gpr_atm_##barrier##_load( \
61
+ &(subchannel)->connected_subchannel)))
62
+
59
63
  namespace {
60
64
  struct state_watcher {
61
65
  grpc_closure closure;
@@ -95,7 +99,7 @@ struct grpc_subchannel {
95
99
  grpc_connect_out_args connecting_result;
96
100
 
97
101
  /** callback for connection finishing */
98
- grpc_closure on_connected;
102
+ grpc_closure connected;
99
103
 
100
104
  /** callback for our alarm */
101
105
  grpc_closure on_alarm;
@@ -104,13 +108,12 @@ struct grpc_subchannel {
104
108
  being setup */
105
109
  grpc_pollset_set* pollset_set;
106
110
 
111
+ /** active connection, or null; of type grpc_connected_subchannel */
112
+ gpr_atm connected_subchannel;
113
+
107
114
  /** mutex protecting remaining elements */
108
115
  gpr_mu mu;
109
116
 
110
- /** active connection, or null; of type grpc_core::ConnectedSubchannel
111
- */
112
- grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel> connected_subchannel;
113
-
114
117
  /** have we seen a disconnection? */
115
118
  bool disconnected;
116
119
  /** are we connecting */
@@ -134,15 +137,16 @@ struct grpc_subchannel {
134
137
  };
135
138
 
136
139
  struct grpc_subchannel_call {
137
- grpc_core::ConnectedSubchannel* connection;
140
+ grpc_connected_subchannel* connection;
138
141
  grpc_closure* schedule_closure_after_destroy;
139
142
  };
140
143
 
141
144
  #define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack*)((call) + 1))
145
+ #define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack*)(con))
142
146
  #define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \
143
147
  (((grpc_subchannel_call*)(callstack)) - 1)
144
148
 
145
- static void on_subchannel_connected(void* subchannel, grpc_error* error);
149
+ static void subchannel_connected(void* subchannel, grpc_error* error);
146
150
 
147
151
  #ifndef NDEBUG
148
152
  #define REF_REASON reason
@@ -160,9 +164,20 @@ static void on_subchannel_connected(void* subchannel, grpc_error* error);
160
164
  */
161
165
 
162
166
  static void connection_destroy(void* arg, grpc_error* error) {
163
- grpc_channel_stack* stk = (grpc_channel_stack*)arg;
164
- grpc_channel_stack_destroy(stk);
165
- gpr_free(stk);
167
+ grpc_connected_subchannel* c = (grpc_connected_subchannel*)arg;
168
+ grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CONNECTION(c));
169
+ gpr_free(c);
170
+ }
171
+
172
+ grpc_connected_subchannel* grpc_connected_subchannel_ref(
173
+ grpc_connected_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
174
+ GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON);
175
+ return c;
176
+ }
177
+
178
+ void grpc_connected_subchannel_unref(
179
+ grpc_connected_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
180
+ GRPC_CHANNEL_STACK_UNREF(CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON);
166
181
  }
167
182
 
168
183
  /*
@@ -229,13 +244,18 @@ grpc_subchannel* grpc_subchannel_ref_from_weak_ref(
229
244
  }
230
245
 
231
246
  static void disconnect(grpc_subchannel* c) {
247
+ grpc_connected_subchannel* con;
232
248
  grpc_subchannel_index_unregister(c->key, c);
233
249
  gpr_mu_lock(&c->mu);
234
250
  GPR_ASSERT(!c->disconnected);
235
251
  c->disconnected = true;
236
252
  grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
237
253
  "Subchannel disconnected"));
238
- c->connected_subchannel.reset();
254
+ con = GET_CONNECTED_SUBCHANNEL(c, no_barrier);
255
+ if (con != nullptr) {
256
+ GRPC_CONNECTED_SUBCHANNEL_UNREF(con, "connection");
257
+ gpr_atm_no_barrier_store(&c->connected_subchannel, (gpr_atm)0xdeadbeef);
258
+ }
239
259
  gpr_mu_unlock(&c->mu);
240
260
  }
241
261
 
@@ -355,7 +375,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
355
375
  if (new_args != nullptr) grpc_channel_args_destroy(new_args);
356
376
  c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
357
377
  &c->root_external_state_watcher;
358
- GRPC_CLOSURE_INIT(&c->on_connected, on_subchannel_connected, c,
378
+ GRPC_CLOSURE_INIT(&c->connected, subchannel_connected, c,
359
379
  grpc_schedule_on_exec_ctx);
360
380
  grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
361
381
  "subchannel");
@@ -379,7 +399,7 @@ static void continue_connect_locked(grpc_subchannel* c) {
379
399
  grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_CONNECTING,
380
400
  GRPC_ERROR_NONE, "state_change");
381
401
  grpc_connector_connect(c->connector, &args, &c->connecting_result,
382
- &c->on_connected);
402
+ &c->connected);
383
403
  }
384
404
 
385
405
  grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel* c,
@@ -439,7 +459,7 @@ static void maybe_start_connecting_locked(grpc_subchannel* c) {
439
459
  return;
440
460
  }
441
461
 
442
- if (c->connected_subchannel != nullptr) {
462
+ if (GET_CONNECTED_SUBCHANNEL(c, no_barrier) != nullptr) {
443
463
  /* Already connected: don't restart */
444
464
  return;
445
465
  }
@@ -461,10 +481,9 @@ static void maybe_start_connecting_locked(grpc_subchannel* c) {
461
481
  const grpc_millis time_til_next =
462
482
  c->next_attempt_deadline - grpc_core::ExecCtx::Get()->Now();
463
483
  if (time_til_next <= 0) {
464
- gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", c);
484
+ gpr_log(GPR_INFO, "Retry immediately");
465
485
  } else {
466
- gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRIdPTR " milliseconds", c,
467
- time_til_next);
486
+ gpr_log(GPR_INFO, "Retry in %" PRIdPTR " milliseconds", time_til_next);
468
487
  }
469
488
  GRPC_CLOSURE_INIT(&c->on_alarm, on_alarm, c, grpc_schedule_on_exec_ctx);
470
489
  grpc_timer_init(&c->alarm, c->next_attempt_deadline, &c->on_alarm);
@@ -508,56 +527,75 @@ void grpc_subchannel_notify_on_state_change(
508
527
  }
509
528
  }
510
529
 
511
- static void on_connected_subchannel_connectivity_changed(void* p,
512
- grpc_error* error) {
513
- state_watcher* connected_subchannel_watcher = (state_watcher*)p;
514
- grpc_subchannel* c = connected_subchannel_watcher->subchannel;
530
+ void grpc_connected_subchannel_process_transport_op(
531
+ grpc_connected_subchannel* con, grpc_transport_op* op) {
532
+ grpc_channel_stack* channel_stack = CHANNEL_STACK_FROM_CONNECTION(con);
533
+ grpc_channel_element* top_elem = grpc_channel_stack_element(channel_stack, 0);
534
+ top_elem->filter->start_transport_op(top_elem, op);
535
+ }
536
+
537
+ static void subchannel_on_child_state_changed(void* p, grpc_error* error) {
538
+ state_watcher* sw = (state_watcher*)p;
539
+ grpc_subchannel* c = sw->subchannel;
515
540
  gpr_mu* mu = &c->mu;
516
541
 
517
542
  gpr_mu_lock(mu);
518
543
 
519
- switch (connected_subchannel_watcher->connectivity_state) {
520
- case GRPC_CHANNEL_TRANSIENT_FAILURE:
521
- case GRPC_CHANNEL_SHUTDOWN: {
522
- if (!c->disconnected && c->connected_subchannel != nullptr) {
523
- if (grpc_trace_stream_refcount.enabled()) {
524
- gpr_log(GPR_INFO,
525
- "Connected subchannel %p of subchannel %p has gone into %s. "
526
- "Attempting to reconnect.",
527
- c->connected_subchannel.get(), c,
528
- grpc_connectivity_state_name(
529
- connected_subchannel_watcher->connectivity_state));
530
- }
531
- c->connected_subchannel.reset();
532
- grpc_connectivity_state_set(&c->state_tracker,
533
- GRPC_CHANNEL_TRANSIENT_FAILURE,
534
- GRPC_ERROR_REF(error), "reflect_child");
535
- c->backoff_begun = false;
536
- c->backoff->Reset();
537
- maybe_start_connecting_locked(c);
538
- } else {
539
- connected_subchannel_watcher->connectivity_state =
540
- GRPC_CHANNEL_SHUTDOWN;
541
- }
542
- break;
543
- }
544
- default: {
545
- grpc_connectivity_state_set(
546
- &c->state_tracker, connected_subchannel_watcher->connectivity_state,
547
- GRPC_ERROR_REF(error), "reflect_child");
548
- GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
549
- c->connected_subchannel->NotifyOnStateChange(
550
- nullptr, &connected_subchannel_watcher->connectivity_state,
551
- &connected_subchannel_watcher->closure);
552
- connected_subchannel_watcher = nullptr;
553
- }
544
+ /* if we failed just leave this closure */
545
+ if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
546
+ /* any errors on a subchannel ==> we're done, create a new one */
547
+ sw->connectivity_state = GRPC_CHANNEL_SHUTDOWN;
548
+ }
549
+ grpc_connectivity_state_set(&c->state_tracker, sw->connectivity_state,
550
+ GRPC_ERROR_REF(error), "reflect_child");
551
+ if (sw->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
552
+ grpc_connected_subchannel_notify_on_state_change(
553
+ GET_CONNECTED_SUBCHANNEL(c, no_barrier), nullptr,
554
+ &sw->connectivity_state, &sw->closure);
555
+ GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
556
+ sw = nullptr;
554
557
  }
558
+
555
559
  gpr_mu_unlock(mu);
556
560
  GRPC_SUBCHANNEL_WEAK_UNREF(c, "state_watcher");
557
- gpr_free(connected_subchannel_watcher);
561
+ gpr_free(sw);
562
+ }
563
+
564
+ static void connected_subchannel_state_op(grpc_connected_subchannel* con,
565
+ grpc_pollset_set* interested_parties,
566
+ grpc_connectivity_state* state,
567
+ grpc_closure* closure) {
568
+ grpc_transport_op* op = grpc_make_transport_op(nullptr);
569
+ grpc_channel_element* elem;
570
+ op->connectivity_state = state;
571
+ op->on_connectivity_state_change = closure;
572
+ op->bind_pollset_set = interested_parties;
573
+ elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
574
+ elem->filter->start_transport_op(elem, op);
575
+ }
576
+
577
+ void grpc_connected_subchannel_notify_on_state_change(
578
+ grpc_connected_subchannel* con, grpc_pollset_set* interested_parties,
579
+ grpc_connectivity_state* state, grpc_closure* closure) {
580
+ connected_subchannel_state_op(con, interested_parties, state, closure);
581
+ }
582
+
583
+ void grpc_connected_subchannel_ping(grpc_connected_subchannel* con,
584
+ grpc_closure* on_initiate,
585
+ grpc_closure* on_ack) {
586
+ grpc_transport_op* op = grpc_make_transport_op(nullptr);
587
+ grpc_channel_element* elem;
588
+ op->send_ping.on_initiate = on_initiate;
589
+ op->send_ping.on_ack = on_ack;
590
+ elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
591
+ elem->filter->start_transport_op(elem, op);
558
592
  }
559
593
 
560
594
  static bool publish_transport_locked(grpc_subchannel* c) {
595
+ grpc_connected_subchannel* con;
596
+ grpc_channel_stack* stk;
597
+ state_watcher* sw_subchannel;
598
+
561
599
  /* construct channel stack */
562
600
  grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
563
601
  grpc_channel_stack_builder_set_channel_arguments(
@@ -569,9 +607,8 @@ static bool publish_transport_locked(grpc_subchannel* c) {
569
607
  grpc_channel_stack_builder_destroy(builder);
570
608
  return false;
571
609
  }
572
- grpc_channel_stack* stk;
573
610
  grpc_error* error = grpc_channel_stack_builder_finish(
574
- builder, 0, 1, connection_destroy, nullptr, (void**)&stk);
611
+ builder, 0, 1, connection_destroy, nullptr, (void**)&con);
575
612
  if (error != GRPC_ERROR_NONE) {
576
613
  grpc_transport_destroy(c->connecting_result.transport);
577
614
  gpr_log(GPR_ERROR, "error initializing subchannel stack: %s",
@@ -579,37 +616,38 @@ static bool publish_transport_locked(grpc_subchannel* c) {
579
616
  GRPC_ERROR_UNREF(error);
580
617
  return false;
581
618
  }
619
+ stk = CHANNEL_STACK_FROM_CONNECTION(con);
582
620
  memset(&c->connecting_result, 0, sizeof(c->connecting_result));
583
621
 
584
622
  /* initialize state watcher */
585
- state_watcher* connected_subchannel_watcher =
586
- (state_watcher*)gpr_zalloc(sizeof(*connected_subchannel_watcher));
587
- connected_subchannel_watcher->subchannel = c;
588
- connected_subchannel_watcher->connectivity_state = GRPC_CHANNEL_READY;
589
- GRPC_CLOSURE_INIT(&connected_subchannel_watcher->closure,
590
- on_connected_subchannel_connectivity_changed,
591
- connected_subchannel_watcher, grpc_schedule_on_exec_ctx);
623
+ sw_subchannel = (state_watcher*)gpr_malloc(sizeof(*sw_subchannel));
624
+ sw_subchannel->subchannel = c;
625
+ sw_subchannel->connectivity_state = GRPC_CHANNEL_READY;
626
+ GRPC_CLOSURE_INIT(&sw_subchannel->closure, subchannel_on_child_state_changed,
627
+ sw_subchannel, grpc_schedule_on_exec_ctx);
592
628
 
593
629
  if (c->disconnected) {
594
- gpr_free(connected_subchannel_watcher);
630
+ gpr_free(sw_subchannel);
595
631
  grpc_channel_stack_destroy(stk);
596
- gpr_free(stk);
632
+ gpr_free(con);
597
633
  return false;
598
634
  }
599
635
 
600
636
  /* publish */
601
- c->connected_subchannel.reset(
602
- grpc_core::New<grpc_core::ConnectedSubchannel>(stk));
603
- gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
604
- c->connected_subchannel.get(), c);
637
+ /* TODO(ctiller): this full barrier seems to clear up a TSAN failure.
638
+ I'd have expected the rel_cas below to be enough, but
639
+ seemingly it's not.
640
+ Re-evaluate if we really need this. */
641
+ gpr_atm_full_barrier();
642
+ GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con));
605
643
 
606
644
  /* setup subchannel watching connected subchannel for changes; subchannel
607
645
  ref for connecting is donated to the state watcher */
608
646
  GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
609
647
  GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
610
- c->connected_subchannel->NotifyOnStateChange(
611
- c->pollset_set, &connected_subchannel_watcher->connectivity_state,
612
- &connected_subchannel_watcher->closure);
648
+ grpc_connected_subchannel_notify_on_state_change(
649
+ con, c->pollset_set, &sw_subchannel->connectivity_state,
650
+ &sw_subchannel->closure);
613
651
 
614
652
  /* signal completion */
615
653
  grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_READY,
@@ -617,11 +655,11 @@ static bool publish_transport_locked(grpc_subchannel* c) {
617
655
  return true;
618
656
  }
619
657
 
620
- static void on_subchannel_connected(void* arg, grpc_error* error) {
658
+ static void subchannel_connected(void* arg, grpc_error* error) {
621
659
  grpc_subchannel* c = (grpc_subchannel*)arg;
622
660
  grpc_channel_args* delete_channel_args = c->connecting_result.channel_args;
623
661
 
624
- GRPC_SUBCHANNEL_WEAK_REF(c, "on_subchannel_connected");
662
+ GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
625
663
  gpr_mu_lock(&c->mu);
626
664
  c->connecting = false;
627
665
  if (c->connecting_result.transport != nullptr &&
@@ -656,10 +694,10 @@ static void subchannel_call_destroy(void* call, grpc_error* error) {
656
694
  grpc_subchannel_call* c = (grpc_subchannel_call*)call;
657
695
  GPR_ASSERT(c->schedule_closure_after_destroy != nullptr);
658
696
  GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0);
659
- grpc_core::ConnectedSubchannel* connection = c->connection;
697
+ grpc_connected_subchannel* connection = c->connection;
660
698
  grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(c), nullptr,
661
699
  c->schedule_closure_after_destroy);
662
- connection->Unref(DEBUG_LOCATION, "subchannel_call");
700
+ GRPC_CONNECTED_SUBCHANNEL_UNREF(connection, "subchannel_call");
663
701
  GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0);
664
702
  }
665
703
 
@@ -690,12 +728,9 @@ void grpc_subchannel_call_process_op(grpc_subchannel_call* call,
690
728
  GPR_TIMER_END("grpc_subchannel_call_process_op", 0);
691
729
  }
692
730
 
693
- grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel>
694
- grpc_subchannel_get_connected_subchannel(grpc_subchannel* c) {
695
- gpr_mu_lock(&c->mu);
696
- auto copy = c->connected_subchannel;
697
- gpr_mu_unlock(&c->mu);
698
- return copy;
731
+ grpc_connected_subchannel* grpc_subchannel_get_connected_subchannel(
732
+ grpc_subchannel* c) {
733
+ return GET_CONNECTED_SUBCHANNEL(c, acq);
699
734
  }
700
735
 
701
736
  const grpc_subchannel_key* grpc_subchannel_get_key(
@@ -703,6 +738,36 @@ const grpc_subchannel_key* grpc_subchannel_get_key(
703
738
  return subchannel->key;
704
739
  }
705
740
 
741
+ grpc_error* grpc_connected_subchannel_create_call(
742
+ grpc_connected_subchannel* con,
743
+ const grpc_connected_subchannel_call_args* args,
744
+ grpc_subchannel_call** call) {
745
+ grpc_channel_stack* chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
746
+ *call = (grpc_subchannel_call*)gpr_arena_alloc(
747
+ args->arena, sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
748
+ grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
749
+ (*call)->connection = GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call");
750
+ const grpc_call_element_args call_args = {
751
+ callstk, /* call_stack */
752
+ nullptr, /* server_transport_data */
753
+ args->context, /* context */
754
+ args->path, /* path */
755
+ args->start_time, /* start_time */
756
+ args->deadline, /* deadline */
757
+ args->arena, /* arena */
758
+ args->call_combiner /* call_combiner */
759
+ };
760
+ grpc_error* error = grpc_call_stack_init(chanstk, 1, subchannel_call_destroy,
761
+ *call, &call_args);
762
+ if (error != GRPC_ERROR_NONE) {
763
+ const char* error_string = grpc_error_string(error);
764
+ gpr_log(GPR_ERROR, "error: %s", error_string);
765
+ return error;
766
+ }
767
+ grpc_call_stack_set_pollset_or_pollset_set(callstk, args->pollent);
768
+ return GRPC_ERROR_NONE;
769
+ }
770
+
706
771
  grpc_call_stack* grpc_subchannel_call_get_call_stack(
707
772
  grpc_subchannel_call* subchannel_call) {
708
773
  return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
@@ -738,64 +803,3 @@ grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) {
738
803
  (char*)GRPC_ARG_SUBCHANNEL_ADDRESS,
739
804
  addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup(""));
740
805
  }
741
-
742
- namespace grpc_core {
743
- ConnectedSubchannel::ConnectedSubchannel(grpc_channel_stack* channel_stack)
744
- : grpc_core::RefCountedWithTracing(&grpc_trace_stream_refcount),
745
- channel_stack_(channel_stack) {}
746
-
747
- ConnectedSubchannel::~ConnectedSubchannel() {
748
- GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");
749
- }
750
-
751
- void ConnectedSubchannel::NotifyOnStateChange(
752
- grpc_pollset_set* interested_parties, grpc_connectivity_state* state,
753
- grpc_closure* closure) {
754
- grpc_transport_op* op = grpc_make_transport_op(nullptr);
755
- grpc_channel_element* elem;
756
- op->connectivity_state = state;
757
- op->on_connectivity_state_change = closure;
758
- op->bind_pollset_set = interested_parties;
759
- elem = grpc_channel_stack_element(channel_stack_, 0);
760
- elem->filter->start_transport_op(elem, op);
761
- }
762
-
763
- void ConnectedSubchannel::Ping(grpc_closure* on_initiate,
764
- grpc_closure* on_ack) {
765
- grpc_transport_op* op = grpc_make_transport_op(nullptr);
766
- grpc_channel_element* elem;
767
- op->send_ping.on_initiate = on_initiate;
768
- op->send_ping.on_ack = on_ack;
769
- elem = grpc_channel_stack_element(channel_stack_, 0);
770
- elem->filter->start_transport_op(elem, op);
771
- }
772
-
773
- grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args,
774
- grpc_subchannel_call** call) {
775
- *call = (grpc_subchannel_call*)gpr_arena_alloc(
776
- args.arena,
777
- sizeof(grpc_subchannel_call) + channel_stack_->call_stack_size);
778
- grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
779
- Ref(DEBUG_LOCATION, "subchannel_call");
780
- (*call)->connection = this;
781
- const grpc_call_element_args call_args = {
782
- callstk, /* call_stack */
783
- nullptr, /* server_transport_data */
784
- args.context, /* context */
785
- args.path, /* path */
786
- args.start_time, /* start_time */
787
- args.deadline, /* deadline */
788
- args.arena, /* arena */
789
- args.call_combiner /* call_combiner */
790
- };
791
- grpc_error* error = grpc_call_stack_init(
792
- channel_stack_, 1, subchannel_call_destroy, *call, &call_args);
793
- if (error != GRPC_ERROR_NONE) {
794
- const char* error_string = grpc_error_string(error);
795
- gpr_log(GPR_ERROR, "error: %s", error_string);
796
- return error;
797
- }
798
- grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent);
799
- return GRPC_ERROR_NONE;
800
- }
801
- } // namespace grpc_core
@@ -34,6 +34,7 @@
34
34
  /** A (sub-)channel that knows how to connect to exactly one target
35
35
  address. Provides a target for load balancing. */
36
36
  typedef struct grpc_subchannel grpc_subchannel;
37
+ typedef struct grpc_connected_subchannel grpc_connected_subchannel;
37
38
  typedef struct grpc_subchannel_call grpc_subchannel_call;
38
39
  typedef struct grpc_subchannel_args grpc_subchannel_args;
39
40
  typedef struct grpc_subchannel_key grpc_subchannel_key;
@@ -49,6 +50,10 @@ typedef struct grpc_subchannel_key grpc_subchannel_key;
49
50
  grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r))
50
51
  #define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) \
51
52
  grpc_subchannel_weak_unref((p), __FILE__, __LINE__, (r))
53
+ #define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) \
54
+ grpc_connected_subchannel_ref((p), __FILE__, __LINE__, (r))
55
+ #define GRPC_CONNECTED_SUBCHANNEL_UNREF(p, r) \
56
+ grpc_connected_subchannel_unref((p), __FILE__, __LINE__, (r))
52
57
  #define GRPC_SUBCHANNEL_CALL_REF(p, r) \
53
58
  grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r))
54
59
  #define GRPC_SUBCHANNEL_CALL_UNREF(p, r) \
@@ -62,39 +67,14 @@ typedef struct grpc_subchannel_key grpc_subchannel_key;
62
67
  #define GRPC_SUBCHANNEL_UNREF(p, r) grpc_subchannel_unref((p))
63
68
  #define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p))
64
69
  #define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) grpc_subchannel_weak_unref((p))
70
+ #define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) grpc_connected_subchannel_ref((p))
71
+ #define GRPC_CONNECTED_SUBCHANNEL_UNREF(p, r) \
72
+ grpc_connected_subchannel_unref((p))
65
73
  #define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p))
66
74
  #define GRPC_SUBCHANNEL_CALL_UNREF(p, r) grpc_subchannel_call_unref((p))
67
75
  #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS
68
76
  #endif
69
77
 
70
- namespace grpc_core {
71
- class ConnectedSubchannel : public grpc_core::RefCountedWithTracing {
72
- public:
73
- struct CallArgs {
74
- grpc_polling_entity* pollent;
75
- grpc_slice path;
76
- gpr_timespec start_time;
77
- grpc_millis deadline;
78
- gpr_arena* arena;
79
- grpc_call_context_element* context;
80
- grpc_call_combiner* call_combiner;
81
- };
82
-
83
- explicit ConnectedSubchannel(grpc_channel_stack* channel_stack);
84
- ~ConnectedSubchannel();
85
-
86
- grpc_channel_stack* channel_stack() { return channel_stack_; }
87
- void NotifyOnStateChange(grpc_pollset_set* interested_parties,
88
- grpc_connectivity_state* state,
89
- grpc_closure* closure);
90
- void Ping(grpc_closure* on_initiate, grpc_closure* on_ack);
91
- grpc_error* CreateCall(const CallArgs& args, grpc_subchannel_call** call);
92
-
93
- private:
94
- grpc_channel_stack* channel_stack_;
95
- };
96
- } // namespace grpc_core
97
-
98
78
  grpc_subchannel* grpc_subchannel_ref(
99
79
  grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
100
80
  grpc_subchannel* grpc_subchannel_ref_from_weak_ref(
@@ -105,11 +85,35 @@ grpc_subchannel* grpc_subchannel_weak_ref(
105
85
  grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
106
86
  void grpc_subchannel_weak_unref(
107
87
  grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
88
+ grpc_connected_subchannel* grpc_connected_subchannel_ref(
89
+ grpc_connected_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
90
+ void grpc_connected_subchannel_unref(
91
+ grpc_connected_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
108
92
  void grpc_subchannel_call_ref(
109
93
  grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
110
94
  void grpc_subchannel_call_unref(
111
95
  grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
112
96
 
97
+ /** construct a subchannel call */
98
+ typedef struct {
99
+ grpc_polling_entity* pollent;
100
+ grpc_slice path;
101
+ gpr_timespec start_time;
102
+ grpc_millis deadline;
103
+ gpr_arena* arena;
104
+ grpc_call_context_element* context;
105
+ grpc_call_combiner* call_combiner;
106
+ } grpc_connected_subchannel_call_args;
107
+
108
+ grpc_error* grpc_connected_subchannel_create_call(
109
+ grpc_connected_subchannel* connected_subchannel,
110
+ const grpc_connected_subchannel_call_args* args,
111
+ grpc_subchannel_call** subchannel_call);
112
+
113
+ /** process a transport level op */
114
+ void grpc_connected_subchannel_process_transport_op(
115
+ grpc_connected_subchannel* subchannel, grpc_transport_op* op);
116
+
113
117
  /** poll the current connectivity state of a channel */
114
118
  grpc_connectivity_state grpc_subchannel_check_connectivity(
115
119
  grpc_subchannel* channel, grpc_error** error);
@@ -119,12 +123,17 @@ grpc_connectivity_state grpc_subchannel_check_connectivity(
119
123
  void grpc_subchannel_notify_on_state_change(
120
124
  grpc_subchannel* channel, grpc_pollset_set* interested_parties,
121
125
  grpc_connectivity_state* state, grpc_closure* notify);
122
-
123
- /** retrieve the grpc_core::ConnectedSubchannel - or nullptr if not connected
124
- * (which may happen before it initially connects or during transient failures)
125
- * */
126
- grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel>
127
- grpc_subchannel_get_connected_subchannel(grpc_subchannel* c);
126
+ void grpc_connected_subchannel_notify_on_state_change(
127
+ grpc_connected_subchannel* channel, grpc_pollset_set* interested_parties,
128
+ grpc_connectivity_state* state, grpc_closure* notify);
129
+ void grpc_connected_subchannel_ping(grpc_connected_subchannel* channel,
130
+ grpc_closure* on_initiate,
131
+ grpc_closure* on_ack);
132
+
133
+ /** retrieve the grpc_connected_subchannel - or NULL if called before
134
+ the subchannel becomes connected */
135
+ grpc_connected_subchannel* grpc_subchannel_get_connected_subchannel(
136
+ grpc_subchannel* subchannel);
128
137
 
129
138
  /** return the subchannel index key for \a subchannel */
130
139
  const grpc_subchannel_key* grpc_subchannel_get_key(
@@ -1081,6 +1081,7 @@ static grpc_stream_compression_algorithm decode_stream_compression(
1081
1081
  static void publish_app_metadata(grpc_call* call, grpc_metadata_batch* b,
1082
1082
  int is_trailing) {
1083
1083
  if (b->list.count == 0) return;
1084
+ if (is_trailing && call->buffered_metadata[1] == nullptr) return;
1084
1085
  GPR_TIMER_BEGIN("publish_app_metadata", 0);
1085
1086
  grpc_metadata_array* dest;
1086
1087
  grpc_metadata* mdusr;
@@ -21,6 +21,6 @@
21
21
 
22
22
  #include <grpc/grpc.h>
23
23
 
24
- const char* grpc_version_string(void) { return "5.0.0-pre2"; }
24
+ const char* grpc_version_string(void) { return "5.0.0-pre3"; }
25
25
 
26
26
  const char* grpc_g_stands_for(void) { return "glossy"; }
@@ -14,5 +14,5 @@
14
14
 
15
15
  # GRPC contains the General RPC module.
16
16
  module GRPC
17
- VERSION = '1.9.0.pre2'
17
+ VERSION = '1.9.0.pre3'
18
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0.pre2
4
+ version: 1.9.0.pre3
5
5
  platform: ruby
6
6
  authors:
7
7
  - gRPC Authors
8
8
  autorequire:
9
9
  bindir: src/ruby/bin
10
10
  cert_chain: []
11
- date: 2018-01-24 00:00:00.000000000 Z
11
+ date: 2018-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf