grpc 1.14.2 → 1.15.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Makefile +307 -12
- data/etc/roots.pem +40 -163
- data/include/grpc/grpc.h +49 -0
- data/include/grpc/grpc_security.h +0 -6
- data/include/grpc/grpc_security_constants.h +6 -0
- data/include/grpc/impl/codegen/grpc_types.h +17 -2
- data/include/grpc/impl/codegen/port_platform.h +41 -4
- data/include/grpc/support/sync.h +0 -16
- data/src/{cpp → core}/ext/filters/census/grpc_context.cc +0 -0
- data/src/core/ext/filters/client_channel/client_channel.cc +40 -11
- data/src/core/ext/filters/client_channel/client_channel_channelz.cc +11 -9
- data/src/core/ext/filters/client_channel/client_channel_channelz.h +4 -2
- data/src/core/ext/filters/client_channel/lb_policy.h +14 -11
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +67 -90
- data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +108 -91
- data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +79 -25
- data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +40 -0
- data/src/core/ext/filters/client_channel/resolver.h +8 -0
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +11 -3
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +13 -10
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +18 -4
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +13 -5
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +537 -0
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +6 -5
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +11 -0
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +29 -0
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +29 -0
- data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +9 -0
- data/src/core/ext/filters/client_channel/subchannel.cc +21 -8
- data/src/core/ext/filters/client_channel/subchannel.h +7 -0
- data/src/core/ext/filters/http/client_authority_filter.cc +1 -1
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +24 -0
- data/src/core/ext/transport/chttp2/transport/flow_control.cc +10 -7
- data/src/core/lib/channel/channel_stack.h +1 -1
- data/src/core/lib/channel/channel_trace.cc +1 -1
- data/src/core/lib/channel/channel_trace.h +1 -1
- data/src/core/lib/channel/channelz.cc +37 -27
- data/src/core/lib/channel/channelz.h +13 -4
- data/src/core/lib/channel/channelz_registry.cc +89 -4
- data/src/core/lib/channel/channelz_registry.h +56 -39
- data/src/core/lib/gpr/arena.cc +33 -40
- data/src/core/lib/gprpp/fork.cc +41 -33
- data/src/core/lib/gprpp/fork.h +13 -4
- data/src/core/lib/gprpp/mutex_lock.h +42 -0
- data/src/core/lib/gprpp/orphanable.h +4 -2
- data/src/core/lib/gprpp/ref_counted.h +4 -2
- data/src/core/lib/gprpp/ref_counted_ptr.h +65 -13
- data/src/core/lib/iomgr/call_combiner.h +4 -1
- data/src/core/lib/iomgr/ev_epoll1_linux.cc +77 -17
- data/src/core/lib/iomgr/ev_epollex_linux.cc +8 -26
- data/src/core/lib/iomgr/ev_epollsig_linux.cc +10 -28
- data/src/core/lib/iomgr/ev_poll_posix.cc +144 -35
- data/src/core/lib/iomgr/ev_posix.cc +58 -9
- data/src/core/lib/iomgr/ev_posix.h +22 -8
- data/src/core/lib/iomgr/exec_ctx.cc +6 -0
- data/src/core/lib/iomgr/exec_ctx.h +2 -0
- data/src/core/lib/iomgr/executor.cc +148 -72
- data/src/core/lib/iomgr/executor.h +39 -6
- data/src/core/lib/iomgr/fork_posix.cc +12 -1
- data/src/core/lib/iomgr/iocp_windows.cc +9 -4
- data/src/core/lib/iomgr/lockfree_event.cc +5 -1
- data/src/core/lib/iomgr/port.h +15 -2
- data/src/core/lib/iomgr/resolve_address_posix.cc +3 -2
- data/src/core/lib/iomgr/resolve_address_windows.cc +3 -2
- data/src/core/lib/iomgr/resource_quota.cc +78 -0
- data/src/core/lib/iomgr/resource_quota.h +16 -0
- data/src/core/lib/iomgr/socket_mutator.cc +1 -1
- data/src/core/lib/iomgr/socket_mutator.h +1 -1
- data/src/core/lib/iomgr/socket_windows.cc +33 -0
- data/src/core/lib/iomgr/socket_windows.h +6 -0
- data/src/core/lib/iomgr/tcp_windows.cc +2 -2
- data/src/core/lib/iomgr/tcp_windows.h +2 -0
- data/src/core/lib/iomgr/timer.h +3 -2
- data/src/core/lib/json/json.cc +2 -1
- data/src/core/lib/security/credentials/jwt/json_token.h +2 -0
- data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +2 -0
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -1
- data/src/core/lib/security/security_connector/load_system_roots.h +29 -0
- data/src/core/lib/security/security_connector/load_system_roots_fallback.cc +32 -0
- data/src/core/lib/security/security_connector/load_system_roots_linux.cc +165 -0
- data/src/core/lib/security/security_connector/load_system_roots_linux.h +44 -0
- data/src/core/lib/security/security_connector/security_connector.cc +23 -4
- data/src/core/lib/security/transport/client_auth_filter.cc +0 -4
- data/src/core/lib/security/transport/server_auth_filter.cc +0 -2
- data/src/core/lib/surface/call.cc +7 -3
- data/src/core/lib/surface/channel.cc +18 -2
- data/src/core/lib/surface/completion_queue.cc +152 -15
- data/src/core/lib/surface/completion_queue.h +20 -1
- data/src/core/lib/surface/completion_queue_factory.cc +13 -4
- data/src/core/lib/surface/init.cc +2 -2
- data/src/core/lib/surface/init.h +0 -1
- data/src/core/lib/surface/version.cc +2 -2
- data/src/core/lib/transport/service_config.cc +2 -2
- data/src/core/lib/transport/service_config.h +3 -3
- data/src/core/lib/transport/transport.h +2 -0
- data/src/core/tsi/alts/crypt/aes_gcm.cc +2 -0
- data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +8 -0
- data/src/core/tsi/grpc_shadow_boringssl.h +3006 -0
- data/src/core/tsi/ssl/session_cache/ssl_session.h +2 -0
- data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +5 -5
- data/src/core/tsi/ssl/session_cache/ssl_session_cache.h +2 -0
- data/src/core/tsi/ssl_transport_security.cc +5 -3
- data/src/core/tsi/ssl_types.h +2 -0
- data/src/ruby/ext/grpc/extconf.rb +1 -26
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +12 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +18 -0
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/src/ruby/spec/generic/client_stub_spec.rb +3 -3
- data/third_party/address_sorting/address_sorting.c +7 -2
- data/third_party/address_sorting/address_sorting_windows.c +43 -3
- data/third_party/address_sorting/include/address_sorting/address_sorting.h +3 -0
- metadata +40 -31
@@ -27,6 +27,7 @@
|
|
27
27
|
#include "src/core/ext/filters/client_channel/subchannel.h"
|
28
28
|
#include "src/core/ext/filters/client_channel/subchannel_index.h"
|
29
29
|
#include "src/core/lib/channel/channel_args.h"
|
30
|
+
#include "src/core/lib/gprpp/mutex_lock.h"
|
30
31
|
#include "src/core/lib/iomgr/combiner.h"
|
31
32
|
#include "src/core/lib/iomgr/sockaddr_utils.h"
|
32
33
|
#include "src/core/lib/transport/connectivity_state.h"
|
@@ -46,7 +47,7 @@ class PickFirst : public LoadBalancingPolicy {
|
|
46
47
|
explicit PickFirst(const Args& args);
|
47
48
|
|
48
49
|
void UpdateLocked(const grpc_channel_args& args) override;
|
49
|
-
bool PickLocked(PickState* pick) override;
|
50
|
+
bool PickLocked(PickState* pick, grpc_error** error) override;
|
50
51
|
void CancelPickLocked(PickState* pick, grpc_error* error) override;
|
51
52
|
void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
|
52
53
|
uint32_t initial_metadata_flags_eq,
|
@@ -56,10 +57,10 @@ class PickFirst : public LoadBalancingPolicy {
|
|
56
57
|
grpc_connectivity_state CheckConnectivityLocked(
|
57
58
|
grpc_error** connectivity_error) override;
|
58
59
|
void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override;
|
59
|
-
void PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) override;
|
60
60
|
void ExitIdleLocked() override;
|
61
|
+
void ResetBackoffLocked() override;
|
61
62
|
void FillChildRefsForChannelz(ChildRefsList* child_subchannels,
|
62
|
-
ChildRefsList*
|
63
|
+
ChildRefsList* ignored) override;
|
63
64
|
|
64
65
|
private:
|
65
66
|
~PickFirst();
|
@@ -80,6 +81,11 @@ class PickFirst : public LoadBalancingPolicy {
|
|
80
81
|
|
81
82
|
void ProcessConnectivityChangeLocked(
|
82
83
|
grpc_connectivity_state connectivity_state, grpc_error* error) override;
|
84
|
+
|
85
|
+
// Processes the connectivity change to READY for an unselected subchannel.
|
86
|
+
void ProcessUnselectedReadyLocked();
|
87
|
+
|
88
|
+
void CheckConnectivityStateAndStartWatchingLocked();
|
83
89
|
};
|
84
90
|
|
85
91
|
class PickFirstSubchannelList
|
@@ -173,15 +179,16 @@ void PickFirst::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
|
|
173
179
|
PickState* pick;
|
174
180
|
while ((pick = pending_picks_) != nullptr) {
|
175
181
|
pending_picks_ = pick->next;
|
176
|
-
|
182
|
+
grpc_error* error = GRPC_ERROR_NONE;
|
183
|
+
if (new_policy->PickLocked(pick, &error)) {
|
177
184
|
// Synchronous return, schedule closure.
|
178
|
-
GRPC_CLOSURE_SCHED(pick->on_complete,
|
185
|
+
GRPC_CLOSURE_SCHED(pick->on_complete, error);
|
179
186
|
}
|
180
187
|
}
|
181
188
|
}
|
182
189
|
|
183
190
|
void PickFirst::ShutdownLocked() {
|
184
|
-
AutoChildRefsUpdater(this);
|
191
|
+
AutoChildRefsUpdater guard(this);
|
185
192
|
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown");
|
186
193
|
if (grpc_lb_pick_first_trace.enabled()) {
|
187
194
|
gpr_log(GPR_INFO, "Pick First %p Shutting down", this);
|
@@ -246,7 +253,8 @@ void PickFirst::StartPickingLocked() {
|
|
246
253
|
if (subchannel_list_ != nullptr) {
|
247
254
|
for (size_t i = 0; i < subchannel_list_->num_subchannels(); ++i) {
|
248
255
|
if (subchannel_list_->subchannel(i)->subchannel() != nullptr) {
|
249
|
-
subchannel_list_->subchannel(i)
|
256
|
+
subchannel_list_->subchannel(i)
|
257
|
+
->CheckConnectivityStateAndStartWatchingLocked();
|
250
258
|
break;
|
251
259
|
}
|
252
260
|
}
|
@@ -259,18 +267,30 @@ void PickFirst::ExitIdleLocked() {
|
|
259
267
|
}
|
260
268
|
}
|
261
269
|
|
262
|
-
|
270
|
+
void PickFirst::ResetBackoffLocked() {
|
271
|
+
subchannel_list_->ResetBackoffLocked();
|
272
|
+
if (latest_pending_subchannel_list_ != nullptr) {
|
273
|
+
latest_pending_subchannel_list_->ResetBackoffLocked();
|
274
|
+
}
|
275
|
+
}
|
276
|
+
|
277
|
+
bool PickFirst::PickLocked(PickState* pick, grpc_error** error) {
|
263
278
|
// If we have a selected subchannel already, return synchronously.
|
264
279
|
if (selected_ != nullptr) {
|
265
280
|
pick->connected_subchannel = selected_->connected_subchannel()->Ref();
|
266
281
|
return true;
|
267
282
|
}
|
268
283
|
// No subchannel selected yet, so handle asynchronously.
|
269
|
-
if (
|
270
|
-
|
284
|
+
if (pick->on_complete == nullptr) {
|
285
|
+
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
286
|
+
"No pick result available but synchronous result required.");
|
287
|
+
return true;
|
271
288
|
}
|
272
289
|
pick->next = pending_picks_;
|
273
290
|
pending_picks_ = pick;
|
291
|
+
if (!started_picking_) {
|
292
|
+
StartPickingLocked();
|
293
|
+
}
|
274
294
|
return false;
|
275
295
|
}
|
276
296
|
|
@@ -293,20 +313,9 @@ void PickFirst::NotifyOnStateChangeLocked(grpc_connectivity_state* current,
|
|
293
313
|
notify);
|
294
314
|
}
|
295
315
|
|
296
|
-
void PickFirst::PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) {
|
297
|
-
if (selected_ != nullptr) {
|
298
|
-
selected_->connected_subchannel()->Ping(on_initiate, on_ack);
|
299
|
-
} else {
|
300
|
-
GRPC_CLOSURE_SCHED(on_initiate,
|
301
|
-
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected"));
|
302
|
-
GRPC_CLOSURE_SCHED(on_ack,
|
303
|
-
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected"));
|
304
|
-
}
|
305
|
-
}
|
306
|
-
|
307
316
|
void PickFirst::FillChildRefsForChannelz(
|
308
317
|
ChildRefsList* child_subchannels_to_fill, ChildRefsList* ignored) {
|
309
|
-
|
318
|
+
MutexLock lock(&child_refs_mu_);
|
310
319
|
for (size_t i = 0; i < child_subchannels_.size(); ++i) {
|
311
320
|
// TODO(ncteisen): implement a de dup loop that is not O(n^2). Might
|
312
321
|
// have to implement lightweight set. For now, we don't care about
|
@@ -327,33 +336,13 @@ void PickFirst::FillChildRefsForChannelz(
|
|
327
336
|
void PickFirst::UpdateChildRefsLocked() {
|
328
337
|
ChildRefsList cs;
|
329
338
|
if (subchannel_list_ != nullptr) {
|
330
|
-
|
331
|
-
if (subchannel_list_->subchannel(i)->subchannel() != nullptr) {
|
332
|
-
grpc_core::channelz::SubchannelNode* subchannel_node =
|
333
|
-
grpc_subchannel_get_channelz_node(
|
334
|
-
subchannel_list_->subchannel(i)->subchannel());
|
335
|
-
if (subchannel_node != nullptr) {
|
336
|
-
cs.push_back(subchannel_node->subchannel_uuid());
|
337
|
-
}
|
338
|
-
}
|
339
|
-
}
|
339
|
+
subchannel_list_->PopulateChildRefsList(&cs);
|
340
340
|
}
|
341
341
|
if (latest_pending_subchannel_list_ != nullptr) {
|
342
|
-
|
343
|
-
++i) {
|
344
|
-
if (latest_pending_subchannel_list_->subchannel(i)->subchannel() !=
|
345
|
-
nullptr) {
|
346
|
-
grpc_core::channelz::SubchannelNode* subchannel_node =
|
347
|
-
grpc_subchannel_get_channelz_node(
|
348
|
-
latest_pending_subchannel_list_->subchannel(i)->subchannel());
|
349
|
-
if (subchannel_node != nullptr) {
|
350
|
-
cs.push_back(subchannel_node->subchannel_uuid());
|
351
|
-
}
|
352
|
-
}
|
353
|
-
}
|
342
|
+
latest_pending_subchannel_list_->PopulateChildRefsList(&cs);
|
354
343
|
}
|
355
344
|
// atomically update the data that channelz will actually be looking at.
|
356
|
-
|
345
|
+
MutexLock lock(&child_refs_mu_);
|
357
346
|
child_subchannels_ = std::move(cs);
|
358
347
|
}
|
359
348
|
|
@@ -404,7 +393,8 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) {
|
|
404
393
|
// If we've started picking, start trying to connect to the first
|
405
394
|
// subchannel in the new list.
|
406
395
|
if (started_picking_) {
|
407
|
-
subchannel_list_->subchannel(0)
|
396
|
+
subchannel_list_->subchannel(0)
|
397
|
+
->CheckConnectivityStateAndStartWatchingLocked();
|
408
398
|
}
|
409
399
|
} else {
|
410
400
|
// We do have a selected subchannel.
|
@@ -458,7 +448,7 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) {
|
|
458
448
|
// subchannel in the new list.
|
459
449
|
if (started_picking_) {
|
460
450
|
latest_pending_subchannel_list_->subchannel(0)
|
461
|
-
->
|
451
|
+
->CheckConnectivityStateAndStartWatchingLocked();
|
462
452
|
}
|
463
453
|
}
|
464
454
|
}
|
@@ -471,6 +461,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
|
|
471
461
|
// latest pending subchannel lists.
|
472
462
|
GPR_ASSERT(subchannel_list() == p->subchannel_list_.get() ||
|
473
463
|
subchannel_list() == p->latest_pending_subchannel_list_.get());
|
464
|
+
GPR_ASSERT(connectivity_state != GRPC_CHANNEL_SHUTDOWN);
|
474
465
|
// Handle updates for the currently selected subchannel.
|
475
466
|
if (p->selected_ == this) {
|
476
467
|
if (grpc_lb_pick_first_trace.enabled()) {
|
@@ -500,14 +491,12 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
|
|
500
491
|
"update"),
|
501
492
|
"selected_not_ready+switch_to_update");
|
502
493
|
} else {
|
503
|
-
// TODO(juanlishen): we re-resolve when the selected subchannel goes to
|
504
|
-
// TRANSIENT_FAILURE because we used to shut down in this case before
|
505
|
-
// re-resolution is introduced. But we need to investigate whether we
|
506
|
-
// really want to take any action instead of waiting for the selected
|
507
|
-
// subchannel reconnecting.
|
508
|
-
GPR_ASSERT(connectivity_state != GRPC_CHANNEL_SHUTDOWN);
|
509
494
|
if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
|
510
|
-
// If the selected
|
495
|
+
// If the selected subchannel goes bad, request a re-resolution. We also
|
496
|
+
// set the channel state to IDLE and reset started_picking_. The reason
|
497
|
+
// is that if the new state is TRANSIENT_FAILURE due to a GOAWAY
|
498
|
+
// reception we don't want to connect to the re-resolved backends until
|
499
|
+
// we leave the IDLE state.
|
511
500
|
grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_IDLE,
|
512
501
|
GRPC_ERROR_NONE,
|
513
502
|
"selected_changed+reresolve");
|
@@ -538,41 +527,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
|
|
538
527
|
// select in place of the current one.
|
539
528
|
switch (connectivity_state) {
|
540
529
|
case GRPC_CHANNEL_READY: {
|
541
|
-
|
542
|
-
// p->subchannel_list_.
|
543
|
-
if (subchannel_list() == p->latest_pending_subchannel_list_.get()) {
|
544
|
-
if (grpc_lb_pick_first_trace.enabled()) {
|
545
|
-
gpr_log(GPR_INFO,
|
546
|
-
"Pick First %p promoting pending subchannel list %p to "
|
547
|
-
"replace %p",
|
548
|
-
p, p->latest_pending_subchannel_list_.get(),
|
549
|
-
p->subchannel_list_.get());
|
550
|
-
}
|
551
|
-
p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
|
552
|
-
}
|
553
|
-
// Cases 1 and 2.
|
554
|
-
grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_READY,
|
555
|
-
GRPC_ERROR_NONE, "connecting_ready");
|
556
|
-
p->selected_ = this;
|
557
|
-
if (grpc_lb_pick_first_trace.enabled()) {
|
558
|
-
gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", p,
|
559
|
-
subchannel());
|
560
|
-
}
|
561
|
-
// Drop all other subchannels, since we are now connected.
|
562
|
-
p->DestroyUnselectedSubchannelsLocked();
|
563
|
-
// Update any calls that were waiting for a pick.
|
564
|
-
PickState* pick;
|
565
|
-
while ((pick = p->pending_picks_)) {
|
566
|
-
p->pending_picks_ = pick->next;
|
567
|
-
pick->connected_subchannel =
|
568
|
-
p->selected_->connected_subchannel()->Ref();
|
569
|
-
if (grpc_lb_pick_first_trace.enabled()) {
|
570
|
-
gpr_log(GPR_INFO,
|
571
|
-
"Servicing pending pick with selected subchannel %p",
|
572
|
-
p->selected_->subchannel());
|
573
|
-
}
|
574
|
-
GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
|
575
|
-
}
|
530
|
+
ProcessUnselectedReadyLocked();
|
576
531
|
// Renew notification.
|
577
532
|
RenewConnectivityWatchLocked();
|
578
533
|
break;
|
@@ -588,11 +543,12 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
|
|
588
543
|
// Case 1: Only set state to TRANSIENT_FAILURE if we've tried
|
589
544
|
// all subchannels.
|
590
545
|
if (sd->Index() == 0 && subchannel_list() == p->subchannel_list_.get()) {
|
546
|
+
p->TryReresolutionLocked(&grpc_lb_pick_first_trace, GRPC_ERROR_NONE);
|
591
547
|
grpc_connectivity_state_set(
|
592
548
|
&p->state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
|
593
|
-
GRPC_ERROR_REF(error), "
|
549
|
+
GRPC_ERROR_REF(error), "exhausted_subchannels");
|
594
550
|
}
|
595
|
-
sd->
|
551
|
+
sd->CheckConnectivityStateAndStartWatchingLocked();
|
596
552
|
break;
|
597
553
|
}
|
598
554
|
case GRPC_CHANNEL_CONNECTING:
|
@@ -613,6 +569,67 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
|
|
613
569
|
GRPC_ERROR_UNREF(error);
|
614
570
|
}
|
615
571
|
|
572
|
+
void PickFirst::PickFirstSubchannelData::ProcessUnselectedReadyLocked() {
|
573
|
+
PickFirst* p = static_cast<PickFirst*>(subchannel_list()->policy());
|
574
|
+
// If we get here, there are two possible cases:
|
575
|
+
// 1. We do not currently have a selected subchannel, and the update is
|
576
|
+
// for a subchannel in p->subchannel_list_ that we're trying to
|
577
|
+
// connect to. The goal here is to find a subchannel that we can
|
578
|
+
// select.
|
579
|
+
// 2. We do currently have a selected subchannel, and the update is
|
580
|
+
// for a subchannel in p->latest_pending_subchannel_list_. The
|
581
|
+
// goal here is to find a subchannel from the update that we can
|
582
|
+
// select in place of the current one.
|
583
|
+
GPR_ASSERT(subchannel_list() == p->subchannel_list_.get() ||
|
584
|
+
subchannel_list() == p->latest_pending_subchannel_list_.get());
|
585
|
+
// Case 2. Promote p->latest_pending_subchannel_list_ to p->subchannel_list_.
|
586
|
+
if (subchannel_list() == p->latest_pending_subchannel_list_.get()) {
|
587
|
+
if (grpc_lb_pick_first_trace.enabled()) {
|
588
|
+
gpr_log(GPR_INFO,
|
589
|
+
"Pick First %p promoting pending subchannel list %p to "
|
590
|
+
"replace %p",
|
591
|
+
p, p->latest_pending_subchannel_list_.get(),
|
592
|
+
p->subchannel_list_.get());
|
593
|
+
}
|
594
|
+
p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
|
595
|
+
}
|
596
|
+
// Cases 1 and 2.
|
597
|
+
grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_READY,
|
598
|
+
GRPC_ERROR_NONE, "subchannel_ready");
|
599
|
+
p->selected_ = this;
|
600
|
+
if (grpc_lb_pick_first_trace.enabled()) {
|
601
|
+
gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", p, subchannel());
|
602
|
+
}
|
603
|
+
// Drop all other subchannels, since we are now connected.
|
604
|
+
p->DestroyUnselectedSubchannelsLocked();
|
605
|
+
// Update any calls that were waiting for a pick.
|
606
|
+
PickState* pick;
|
607
|
+
while ((pick = p->pending_picks_)) {
|
608
|
+
p->pending_picks_ = pick->next;
|
609
|
+
pick->connected_subchannel = p->selected_->connected_subchannel()->Ref();
|
610
|
+
if (grpc_lb_pick_first_trace.enabled()) {
|
611
|
+
gpr_log(GPR_INFO, "Servicing pending pick with selected subchannel %p",
|
612
|
+
p->selected_->subchannel());
|
613
|
+
}
|
614
|
+
GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
|
615
|
+
}
|
616
|
+
}
|
617
|
+
|
618
|
+
void PickFirst::PickFirstSubchannelData::
|
619
|
+
CheckConnectivityStateAndStartWatchingLocked() {
|
620
|
+
PickFirst* p = static_cast<PickFirst*>(subchannel_list()->policy());
|
621
|
+
grpc_error* error = GRPC_ERROR_NONE;
|
622
|
+
if (p->selected_ != this &&
|
623
|
+
CheckConnectivityStateLocked(&error) == GRPC_CHANNEL_READY) {
|
624
|
+
// We must process the READY subchannel before we start watching it.
|
625
|
+
// Otherwise, we won't know it's READY because we will be waiting for its
|
626
|
+
// connectivity state to change from READY.
|
627
|
+
ProcessUnselectedReadyLocked();
|
628
|
+
}
|
629
|
+
GRPC_ERROR_UNREF(error);
|
630
|
+
StartConnectivityWatchLocked();
|
631
|
+
}
|
632
|
+
|
616
633
|
//
|
617
634
|
// factory
|
618
635
|
//
|
@@ -36,6 +36,7 @@
|
|
36
36
|
#include "src/core/ext/filters/client_channel/subchannel_index.h"
|
37
37
|
#include "src/core/lib/channel/channel_args.h"
|
38
38
|
#include "src/core/lib/debug/trace.h"
|
39
|
+
#include "src/core/lib/gprpp/mutex_lock.h"
|
39
40
|
#include "src/core/lib/gprpp/ref_counted_ptr.h"
|
40
41
|
#include "src/core/lib/iomgr/combiner.h"
|
41
42
|
#include "src/core/lib/iomgr/sockaddr_utils.h"
|
@@ -57,7 +58,7 @@ class RoundRobin : public LoadBalancingPolicy {
|
|
57
58
|
explicit RoundRobin(const Args& args);
|
58
59
|
|
59
60
|
void UpdateLocked(const grpc_channel_args& args) override;
|
60
|
-
bool PickLocked(PickState* pick) override;
|
61
|
+
bool PickLocked(PickState* pick, grpc_error** error) override;
|
61
62
|
void CancelPickLocked(PickState* pick, grpc_error* error) override;
|
62
63
|
void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
|
63
64
|
uint32_t initial_metadata_flags_eq,
|
@@ -67,11 +68,10 @@ class RoundRobin : public LoadBalancingPolicy {
|
|
67
68
|
grpc_connectivity_state CheckConnectivityLocked(
|
68
69
|
grpc_error** connectivity_error) override;
|
69
70
|
void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override;
|
70
|
-
void PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) override;
|
71
71
|
void ExitIdleLocked() override;
|
72
|
-
|
72
|
+
void ResetBackoffLocked() override;
|
73
73
|
void FillChildRefsForChannelz(ChildRefsList* child_subchannels,
|
74
|
-
ChildRefsList*
|
74
|
+
ChildRefsList* ignored) override;
|
75
75
|
|
76
76
|
private:
|
77
77
|
~RoundRobin();
|
@@ -139,7 +139,8 @@ class RoundRobin : public LoadBalancingPolicy {
|
|
139
139
|
grpc_client_channel_factory* client_channel_factory,
|
140
140
|
const grpc_channel_args& args)
|
141
141
|
: SubchannelList(policy, tracer, addresses, combiner,
|
142
|
-
client_channel_factory, args)
|
142
|
+
client_channel_factory, args),
|
143
|
+
last_ready_index_(num_subchannels() - 1) {
|
143
144
|
// Need to maintain a ref to the LB policy as long as we maintain
|
144
145
|
// any references to subchannels, since the subchannels'
|
145
146
|
// pollset_sets will include the LB policy's pollset_set.
|
@@ -180,7 +181,19 @@ class RoundRobin : public LoadBalancingPolicy {
|
|
180
181
|
size_t num_connecting_ = 0;
|
181
182
|
size_t num_transient_failure_ = 0;
|
182
183
|
grpc_error* last_transient_failure_error_ = GRPC_ERROR_NONE;
|
183
|
-
size_t last_ready_index_
|
184
|
+
size_t last_ready_index_; // Index into list of last pick.
|
185
|
+
};
|
186
|
+
|
187
|
+
// Helper class to ensure that any function that modifies the child refs
|
188
|
+
// data structures will update the channelz snapshot data structures before
|
189
|
+
// returning.
|
190
|
+
class AutoChildRefsUpdater {
|
191
|
+
public:
|
192
|
+
explicit AutoChildRefsUpdater(RoundRobin* rr) : rr_(rr) {}
|
193
|
+
~AutoChildRefsUpdater() { rr_->UpdateChildRefsLocked(); }
|
194
|
+
|
195
|
+
private:
|
196
|
+
RoundRobin* rr_;
|
184
197
|
};
|
185
198
|
|
186
199
|
void ShutdownLocked() override;
|
@@ -188,6 +201,7 @@ class RoundRobin : public LoadBalancingPolicy {
|
|
188
201
|
void StartPickingLocked();
|
189
202
|
bool DoPickLocked(PickState* pick);
|
190
203
|
void DrainPendingPicksLocked();
|
204
|
+
void UpdateChildRefsLocked();
|
191
205
|
|
192
206
|
/** list of subchannels */
|
193
207
|
OrphanablePtr<RoundRobinSubchannelList> subchannel_list_;
|
@@ -205,10 +219,16 @@ class RoundRobin : public LoadBalancingPolicy {
|
|
205
219
|
PickState* pending_picks_ = nullptr;
|
206
220
|
/** our connectivity state tracker */
|
207
221
|
grpc_connectivity_state_tracker state_tracker_;
|
222
|
+
/// Lock and data used to capture snapshots of this channel's child
|
223
|
+
/// channels and subchannels. This data is consumed by channelz.
|
224
|
+
gpr_mu child_refs_mu_;
|
225
|
+
ChildRefsList child_subchannels_;
|
226
|
+
ChildRefsList child_channels_;
|
208
227
|
};
|
209
228
|
|
210
229
|
RoundRobin::RoundRobin(const Args& args) : LoadBalancingPolicy(args) {
|
211
230
|
GPR_ASSERT(args.client_channel_factory != nullptr);
|
231
|
+
gpr_mu_init(&child_refs_mu_);
|
212
232
|
grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
|
213
233
|
"round_robin");
|
214
234
|
UpdateLocked(*args.args);
|
@@ -223,6 +243,7 @@ RoundRobin::~RoundRobin() {
|
|
223
243
|
if (grpc_lb_round_robin_trace.enabled()) {
|
224
244
|
gpr_log(GPR_INFO, "[RR %p] Destroying Round Robin policy", this);
|
225
245
|
}
|
246
|
+
gpr_mu_destroy(&child_refs_mu_);
|
226
247
|
GPR_ASSERT(subchannel_list_ == nullptr);
|
227
248
|
GPR_ASSERT(latest_pending_subchannel_list_ == nullptr);
|
228
249
|
GPR_ASSERT(pending_picks_ == nullptr);
|
@@ -234,14 +255,16 @@ void RoundRobin::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
|
|
234
255
|
PickState* pick;
|
235
256
|
while ((pick = pending_picks_) != nullptr) {
|
236
257
|
pending_picks_ = pick->next;
|
237
|
-
|
258
|
+
grpc_error* error = GRPC_ERROR_NONE;
|
259
|
+
if (new_policy->PickLocked(pick, &error)) {
|
238
260
|
// Synchronous return, schedule closure.
|
239
|
-
GRPC_CLOSURE_SCHED(pick->on_complete,
|
261
|
+
GRPC_CLOSURE_SCHED(pick->on_complete, error);
|
240
262
|
}
|
241
263
|
}
|
242
264
|
}
|
243
265
|
|
244
266
|
void RoundRobin::ShutdownLocked() {
|
267
|
+
AutoChildRefsUpdater guard(this);
|
245
268
|
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown");
|
246
269
|
if (grpc_lb_round_robin_trace.enabled()) {
|
247
270
|
gpr_log(GPR_INFO, "[RR %p] Shutting down", this);
|
@@ -313,6 +336,13 @@ void RoundRobin::ExitIdleLocked() {
|
|
313
336
|
}
|
314
337
|
}
|
315
338
|
|
339
|
+
void RoundRobin::ResetBackoffLocked() {
|
340
|
+
subchannel_list_->ResetBackoffLocked();
|
341
|
+
if (latest_pending_subchannel_list_ != nullptr) {
|
342
|
+
latest_pending_subchannel_list_->ResetBackoffLocked();
|
343
|
+
}
|
344
|
+
}
|
345
|
+
|
316
346
|
bool RoundRobin::DoPickLocked(PickState* pick) {
|
317
347
|
const size_t next_ready_index =
|
318
348
|
subchannel_list_->GetNextReadySubchannelIndexLocked();
|
@@ -348,7 +378,7 @@ void RoundRobin::DrainPendingPicksLocked() {
|
|
348
378
|
}
|
349
379
|
}
|
350
380
|
|
351
|
-
bool RoundRobin::PickLocked(PickState* pick) {
|
381
|
+
bool RoundRobin::PickLocked(PickState* pick, grpc_error** error) {
|
352
382
|
if (grpc_lb_round_robin_trace.enabled()) {
|
353
383
|
gpr_log(GPR_INFO, "[RR %p] Trying to pick (shutdown: %d)", this, shutdown_);
|
354
384
|
}
|
@@ -356,6 +386,11 @@ bool RoundRobin::PickLocked(PickState* pick) {
|
|
356
386
|
if (subchannel_list_ != nullptr) {
|
357
387
|
if (DoPickLocked(pick)) return true;
|
358
388
|
}
|
389
|
+
if (pick->on_complete == nullptr) {
|
390
|
+
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
391
|
+
"No pick result available but synchronous result required.");
|
392
|
+
return true;
|
393
|
+
}
|
359
394
|
/* no pick currently available. Save for later in list of pending picks */
|
360
395
|
pick->next = pending_picks_;
|
361
396
|
pending_picks_ = pick;
|
@@ -365,6 +400,39 @@ bool RoundRobin::PickLocked(PickState* pick) {
|
|
365
400
|
return false;
|
366
401
|
}
|
367
402
|
|
403
|
+
void RoundRobin::FillChildRefsForChannelz(
|
404
|
+
ChildRefsList* child_subchannels_to_fill, ChildRefsList* ignored) {
|
405
|
+
MutexLock lock(&child_refs_mu_);
|
406
|
+
for (size_t i = 0; i < child_subchannels_.size(); ++i) {
|
407
|
+
// TODO(ncteisen): implement a de dup loop that is not O(n^2). Might
|
408
|
+
// have to implement lightweight set. For now, we don't care about
|
409
|
+
// performance when channelz requests are made.
|
410
|
+
bool found = false;
|
411
|
+
for (size_t j = 0; j < child_subchannels_to_fill->size(); ++j) {
|
412
|
+
if ((*child_subchannels_to_fill)[j] == child_subchannels_[i]) {
|
413
|
+
found = true;
|
414
|
+
break;
|
415
|
+
}
|
416
|
+
}
|
417
|
+
if (!found) {
|
418
|
+
child_subchannels_to_fill->push_back(child_subchannels_[i]);
|
419
|
+
}
|
420
|
+
}
|
421
|
+
}
|
422
|
+
|
423
|
+
void RoundRobin::UpdateChildRefsLocked() {
|
424
|
+
ChildRefsList cs;
|
425
|
+
if (subchannel_list_ != nullptr) {
|
426
|
+
subchannel_list_->PopulateChildRefsList(&cs);
|
427
|
+
}
|
428
|
+
if (latest_pending_subchannel_list_ != nullptr) {
|
429
|
+
latest_pending_subchannel_list_->PopulateChildRefsList(&cs);
|
430
|
+
}
|
431
|
+
// atomically update the data that channelz will actually be looking at.
|
432
|
+
MutexLock lock(&child_refs_mu_);
|
433
|
+
child_subchannels_ = std::move(cs);
|
434
|
+
}
|
435
|
+
|
368
436
|
void RoundRobin::RoundRobinSubchannelList::StartWatchingLocked() {
|
369
437
|
if (num_subchannels() == 0) return;
|
370
438
|
// Check current state of each subchannel synchronously, since any
|
@@ -455,6 +523,7 @@ void RoundRobin::RoundRobinSubchannelList::
|
|
455
523
|
void RoundRobin::RoundRobinSubchannelList::
|
456
524
|
UpdateRoundRobinStateFromSubchannelStateCountsLocked() {
|
457
525
|
RoundRobin* p = static_cast<RoundRobin*>(policy());
|
526
|
+
AutoChildRefsUpdater guard(p);
|
458
527
|
if (num_ready_ > 0) {
|
459
528
|
if (p->subchannel_list_.get() != this) {
|
460
529
|
// Promote this list to p->subchannel_list_.
|
@@ -593,24 +662,9 @@ void RoundRobin::NotifyOnStateChangeLocked(grpc_connectivity_state* current,
|
|
593
662
|
notify);
|
594
663
|
}
|
595
664
|
|
596
|
-
void RoundRobin::PingOneLocked(grpc_closure* on_initiate,
|
597
|
-
grpc_closure* on_ack) {
|
598
|
-
const size_t next_ready_index =
|
599
|
-
subchannel_list_->GetNextReadySubchannelIndexLocked();
|
600
|
-
if (next_ready_index < subchannel_list_->num_subchannels()) {
|
601
|
-
RoundRobinSubchannelData* selected =
|
602
|
-
subchannel_list_->subchannel(next_ready_index);
|
603
|
-
selected->connected_subchannel()->Ping(on_initiate, on_ack);
|
604
|
-
} else {
|
605
|
-
GRPC_CLOSURE_SCHED(on_initiate, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
606
|
-
"Round Robin not connected"));
|
607
|
-
GRPC_CLOSURE_SCHED(on_ack, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
608
|
-
"Round Robin not connected"));
|
609
|
-
}
|
610
|
-
}
|
611
|
-
|
612
665
|
void RoundRobin::UpdateLocked(const grpc_channel_args& args) {
|
613
666
|
const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
|
667
|
+
AutoChildRefsUpdater guard(this);
|
614
668
|
if (GPR_UNLIKELY(arg == nullptr || arg->type != GRPC_ARG_POINTER)) {
|
615
669
|
gpr_log(GPR_ERROR, "[RR %p] update provided no addresses; ignoring", this);
|
616
670
|
// If we don't have a current subchannel list, go into TRANSIENT_FAILURE.
|