grpc 1.22.0 → 1.23.0
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 +487 -649
- data/include/grpc/grpc_security.h +25 -0
- data/include/grpc/impl/codegen/grpc_types.h +11 -2
- data/include/grpc/impl/codegen/port_platform.h +12 -0
- data/src/core/ext/filters/client_channel/backup_poller.cc +4 -2
- data/src/core/ext/filters/client_channel/client_channel.cc +477 -182
- data/src/core/ext/filters/client_channel/client_channel_channelz.cc +25 -16
- data/src/core/ext/filters/client_channel/client_channel_channelz.h +11 -6
- data/src/core/ext/filters/client_channel/connector.h +10 -2
- data/src/core/ext/filters/client_channel/health/health_check_client.cc +3 -3
- data/src/core/ext/filters/client_channel/http_proxy.cc +9 -10
- data/src/core/ext/filters/client_channel/lb_policy.cc +2 -17
- data/src/core/ext/filters/client_channel/lb_policy.h +36 -8
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +22 -8
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +86 -52
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h +7 -0
- data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +73 -72
- data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +8 -12
- data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +25 -101
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +5 -5
- data/src/core/ext/filters/client_channel/parse_address.cc +29 -26
- data/src/core/ext/filters/client_channel/resolver.h +3 -11
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +5 -3
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +405 -82
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +44 -51
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +0 -1
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +0 -1
- data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +11 -6
- data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +130 -65
- data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +8 -3
- data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +31 -14
- data/src/core/ext/filters/client_channel/resolver_factory.h +4 -0
- data/src/core/ext/filters/client_channel/resolver_registry.cc +11 -0
- data/src/core/ext/filters/client_channel/resolver_registry.h +3 -0
- data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +10 -49
- data/src/core/ext/filters/client_channel/resolving_lb_policy.h +1 -14
- data/src/core/ext/filters/client_channel/retry_throttle.h +2 -3
- data/src/core/ext/filters/client_channel/subchannel.cc +65 -58
- data/src/core/ext/filters/client_channel/subchannel.h +65 -45
- data/src/core/ext/filters/client_channel/subchannel_interface.h +15 -30
- data/src/core/ext/filters/client_idle/client_idle_filter.cc +262 -0
- data/src/core/ext/filters/http/client/http_client_filter.cc +4 -5
- data/src/core/ext/filters/http/client_authority_filter.cc +2 -2
- data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +140 -152
- data/src/core/ext/filters/max_age/max_age_filter.cc +3 -3
- data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +3 -4
- data/src/core/ext/transport/chttp2/server/chttp2_server.cc +7 -6
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +63 -38
- data/src/core/ext/transport/chttp2/transport/context_list.cc +3 -1
- data/src/core/ext/transport/chttp2/transport/frame_data.cc +4 -4
- data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +1 -1
- data/src/core/ext/transport/chttp2/transport/frame_ping.cc +1 -0
- data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +8 -0
- data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +7 -0
- data/src/core/ext/transport/chttp2/transport/frame_settings.cc +1 -0
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +37 -22
- data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +136 -81
- data/src/core/ext/transport/chttp2/transport/hpack_parser.h +8 -0
- data/src/core/ext/transport/chttp2/transport/hpack_table.cc +7 -166
- data/src/core/ext/transport/chttp2/transport/hpack_table.h +41 -15
- data/src/core/ext/transport/chttp2/transport/internal.h +13 -2
- data/src/core/ext/transport/chttp2/transport/parsing.cc +35 -22
- data/src/core/ext/transport/chttp2/transport/stream_map.cc +28 -18
- data/src/core/ext/transport/chttp2/transport/writing.cc +1 -0
- data/src/core/ext/transport/inproc/inproc_transport.cc +1 -1
- data/src/core/lib/channel/channelz.cc +80 -33
- data/src/core/lib/channel/channelz.h +28 -13
- data/src/core/lib/compression/compression.cc +1 -2
- data/src/core/lib/compression/compression_args.cc +13 -6
- data/src/core/lib/compression/compression_args.h +3 -2
- data/src/core/lib/compression/compression_internal.cc +1 -1
- data/src/core/lib/gpr/env_linux.cc +10 -21
- data/src/core/lib/gpr/env_posix.cc +0 -5
- data/src/core/lib/gpr/string.cc +7 -2
- data/src/core/lib/gpr/string.h +1 -0
- data/src/core/lib/gpr/sync_posix.cc +0 -129
- data/src/core/lib/gprpp/debug_location.h +3 -2
- data/src/core/lib/gprpp/fork.cc +14 -21
- data/src/core/lib/gprpp/fork.h +15 -4
- data/src/core/lib/gprpp/host_port.cc +118 -0
- data/src/core/lib/{gpr → gprpp}/host_port.h +27 -11
- data/src/core/lib/gprpp/map.h +25 -0
- data/src/core/lib/gprpp/memory.h +26 -9
- data/src/core/lib/gprpp/ref_counted.h +63 -21
- data/src/core/lib/gprpp/string_view.h +143 -0
- data/src/core/lib/gprpp/thd.h +10 -1
- data/src/core/lib/gprpp/thd_posix.cc +25 -0
- data/src/core/lib/gprpp/thd_windows.cc +9 -1
- data/src/core/lib/http/httpcli_security_connector.cc +3 -1
- data/src/core/lib/iomgr/cfstream_handle.cc +6 -1
- data/src/core/lib/iomgr/cfstream_handle.h +8 -2
- data/src/core/lib/iomgr/combiner.cc +4 -4
- data/src/core/lib/iomgr/error.cc +18 -8
- data/src/core/lib/iomgr/error.h +2 -0
- data/src/core/lib/iomgr/ev_posix.cc +4 -2
- data/src/core/lib/iomgr/executor.cc +4 -1
- data/src/core/lib/iomgr/executor/mpmcqueue.cc +183 -0
- data/src/core/lib/iomgr/executor/mpmcqueue.h +178 -0
- data/src/core/lib/iomgr/executor/threadpool.cc +138 -0
- data/src/core/lib/iomgr/executor/threadpool.h +153 -0
- data/src/core/lib/iomgr/fork_posix.cc +4 -2
- data/src/core/lib/iomgr/iocp_windows.cc +2 -2
- data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +14 -0
- data/src/core/lib/iomgr/iomgr_uv.cc +3 -0
- data/src/core/lib/iomgr/lockfree_event.cc +3 -3
- data/src/core/lib/iomgr/resolve_address_custom.cc +16 -20
- data/src/core/lib/iomgr/resolve_address_posix.cc +8 -10
- data/src/core/lib/iomgr/resolve_address_windows.cc +6 -8
- data/src/core/lib/iomgr/sockaddr_utils.cc +5 -3
- data/src/core/lib/iomgr/socket_utils_common_posix.cc +0 -1
- data/src/core/lib/iomgr/socket_windows.h +1 -1
- data/src/core/lib/iomgr/tcp_client_cfstream.cc +7 -6
- data/src/core/lib/iomgr/tcp_client_custom.cc +1 -0
- data/src/core/lib/iomgr/tcp_custom.cc +4 -0
- data/src/core/lib/iomgr/tcp_posix.cc +8 -2
- data/src/core/lib/iomgr/tcp_server_custom.cc +1 -0
- data/src/core/lib/iomgr/tcp_server_windows.cc +1 -1
- data/src/core/lib/iomgr/tcp_windows.cc +7 -7
- data/src/core/lib/iomgr/timer_custom.cc +1 -0
- data/src/core/lib/iomgr/timer_manager.cc +0 -29
- data/src/core/lib/security/credentials/credentials.cc +84 -0
- data/src/core/lib/security/credentials/credentials.h +58 -2
- data/src/core/lib/security/credentials/jwt/json_token.cc +6 -2
- data/src/core/lib/security/credentials/jwt/json_token.h +1 -1
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +245 -24
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +16 -0
- data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +3 -2
- data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +21 -25
- data/src/core/lib/security/security_connector/local/local_security_connector.cc +3 -2
- data/src/core/lib/security/security_connector/security_connector.cc +1 -1
- data/src/core/lib/security/security_connector/security_connector.h +1 -1
- data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +19 -19
- data/src/core/lib/security/security_connector/ssl_utils.cc +26 -31
- data/src/core/lib/security/security_connector/ssl_utils.h +11 -8
- data/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc +16 -20
- data/src/core/lib/security/security_connector/tls/spiffe_security_connector.h +4 -3
- data/src/core/lib/security/transport/client_auth_filter.cc +1 -2
- data/src/core/lib/security/util/json_util.cc +19 -5
- data/src/core/lib/security/util/json_util.h +3 -1
- data/src/core/lib/slice/slice.cc +69 -50
- data/src/core/lib/slice/slice_buffer.cc +6 -5
- data/src/core/lib/slice/slice_hash_table.h +3 -7
- data/src/core/lib/slice/slice_intern.cc +130 -39
- data/src/core/lib/slice/slice_internal.h +8 -0
- data/src/core/lib/slice/slice_utils.h +120 -0
- data/src/core/lib/slice/slice_weak_hash_table.h +2 -7
- data/src/core/lib/surface/call.cc +8 -3
- data/src/core/lib/surface/channel.cc +31 -8
- data/src/core/lib/surface/completion_queue.cc +17 -7
- data/src/core/lib/surface/init_secure.cc +4 -1
- data/src/core/lib/surface/lame_client.cc +2 -2
- data/src/core/lib/surface/server.cc +34 -35
- data/src/core/lib/surface/server.h +8 -17
- data/src/core/lib/surface/version.cc +1 -1
- data/src/core/lib/transport/byte_stream.cc +3 -5
- data/src/core/lib/transport/byte_stream.h +1 -2
- data/src/core/lib/transport/error_utils.cc +10 -1
- data/src/core/lib/transport/metadata.cc +202 -35
- data/src/core/lib/transport/metadata.h +81 -6
- data/src/core/lib/transport/static_metadata.cc +1257 -465
- data/src/core/lib/transport/static_metadata.h +190 -347
- data/src/core/lib/transport/timeout_encoding.cc +7 -0
- data/src/core/lib/transport/timeout_encoding.h +3 -2
- data/src/core/plugin_registry/grpc_plugin_registry.cc +4 -0
- data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +0 -1
- data/src/core/tsi/ssl/session_cache/ssl_session_cache.h +2 -7
- data/src/core/tsi/ssl_transport_security.cc +35 -43
- data/src/core/tsi/ssl_transport_security.h +2 -1
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -0
- data/src/ruby/lib/grpc/generic/rpc_server.rb +1 -1
- data/src/ruby/lib/grpc/grpc.rb +1 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- metadata +39 -33
- data/src/core/lib/gpr/host_port.cc +0 -98
@@ -328,6 +328,31 @@ GRPCAPI grpc_call_credentials* grpc_google_iam_credentials_create(
|
|
328
328
|
const char* authorization_token, const char* authority_selector,
|
329
329
|
void* reserved);
|
330
330
|
|
331
|
+
/** Options for creating STS Oauth Token Exchange credentials following the IETF
|
332
|
+
draft https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16.
|
333
|
+
Optional fields may be set to NULL or empty string. It is the responsibility
|
334
|
+
of the caller to ensure that the subject and actor tokens are refreshed on
|
335
|
+
disk at the specified paths. This API is used for experimental purposes for
|
336
|
+
now and may change in the future. */
|
337
|
+
typedef struct {
|
338
|
+
const char* token_exchange_service_uri; /* Required. */
|
339
|
+
const char* resource; /* Optional. */
|
340
|
+
const char* audience; /* Optional. */
|
341
|
+
const char* scope; /* Optional. */
|
342
|
+
const char* requested_token_type; /* Optional. */
|
343
|
+
const char* subject_token_path; /* Required. */
|
344
|
+
const char* subject_token_type; /* Required. */
|
345
|
+
const char* actor_token_path; /* Optional. */
|
346
|
+
const char* actor_token_type; /* Optional. */
|
347
|
+
} grpc_sts_credentials_options;
|
348
|
+
|
349
|
+
/** Creates an STS credentials following the STS Token Exchanged specifed in the
|
350
|
+
IETF draft https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16.
|
351
|
+
This API is used for experimental purposes for now and may change in the
|
352
|
+
future. */
|
353
|
+
GRPCAPI grpc_call_credentials* grpc_sts_credentials_create(
|
354
|
+
const grpc_sts_credentials_options* options, void* reserved);
|
355
|
+
|
331
356
|
/** Callback function to be called by the metadata credentials plugin
|
332
357
|
implementation when the metadata is ready.
|
333
358
|
- user_data is the opaque pointer that was passed in the get_metadata method
|
@@ -157,8 +157,9 @@ typedef struct {
|
|
157
157
|
/** Maximum message length that the channel can send. Int valued, bytes.
|
158
158
|
-1 means unlimited. */
|
159
159
|
#define GRPC_ARG_MAX_SEND_MESSAGE_LENGTH "grpc.max_send_message_length"
|
160
|
-
/** Maximum time that a channel may have no outstanding rpcs
|
161
|
-
|
160
|
+
/** Maximum time that a channel may have no outstanding rpcs, after which the
|
161
|
+
* server will close the connection. Int valued, milliseconds. INT_MAX means
|
162
|
+
* unlimited. */
|
162
163
|
#define GRPC_ARG_MAX_CONNECTION_IDLE_MS "grpc.max_connection_idle_ms"
|
163
164
|
/** Maximum time that a channel may exist. Int valued, milliseconds.
|
164
165
|
* INT_MAX means unlimited. */
|
@@ -166,6 +167,14 @@ typedef struct {
|
|
166
167
|
/** Grace period after the channel reaches its max age. Int valued,
|
167
168
|
milliseconds. INT_MAX means unlimited. */
|
168
169
|
#define GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS "grpc.max_connection_age_grace_ms"
|
170
|
+
/** Timeout after the last RPC finishes on the client channel at which the
|
171
|
+
* channel goes back into IDLE state. Int valued, milliseconds. INT_MAX means
|
172
|
+
* unlimited. */
|
173
|
+
/** TODO(qianchengz): Currently the default value is INT_MAX, which means the
|
174
|
+
* client idle filter is disabled by default. After the client idle filter
|
175
|
+
* proves no perfomance issue, we will change the default value to a reasonable
|
176
|
+
* value. */
|
177
|
+
#define GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS "grpc.client_idle_timeout_ms"
|
169
178
|
/** Enable/disable support for per-message compression. Defaults to 1, unless
|
170
179
|
GRPC_ARG_MINIMAL_STACK is enabled, in which case it defaults to 0. */
|
171
180
|
#define GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION "grpc.per_message_compression"
|
@@ -394,6 +394,18 @@
|
|
394
394
|
#endif
|
395
395
|
#endif /* GPR_NO_AUTODETECT_PLATFORM */
|
396
396
|
|
397
|
+
#if defined(GPR_BACKWARDS_COMPATIBILITY_MODE)
|
398
|
+
/*
|
399
|
+
* For backward compatibility mode, reset _FORTIFY_SOURCE to prevent
|
400
|
+
* a library from having non-standard symbols such as __asprintf_chk.
|
401
|
+
* This helps non-glibc systems such as alpine using musl to find symbols.
|
402
|
+
*/
|
403
|
+
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
|
404
|
+
#undef _FORTIFY_SOURCE
|
405
|
+
#define _FORTIFY_SOURCE 0
|
406
|
+
#endif
|
407
|
+
#endif
|
408
|
+
|
397
409
|
/*
|
398
410
|
* There are platforms for which TLS should not be used even though the
|
399
411
|
* compiler makes it seem like it's supported (Android NDK < r12b for example).
|
@@ -24,10 +24,12 @@
|
|
24
24
|
#include <grpc/support/alloc.h>
|
25
25
|
#include <grpc/support/log.h>
|
26
26
|
#include <grpc/support/sync.h>
|
27
|
+
|
27
28
|
#include "src/core/ext/filters/client_channel/client_channel.h"
|
28
29
|
#include "src/core/lib/gpr/string.h"
|
29
30
|
#include "src/core/lib/gprpp/global_config.h"
|
30
31
|
#include "src/core/lib/iomgr/error.h"
|
32
|
+
#include "src/core/lib/iomgr/iomgr.h"
|
31
33
|
#include "src/core/lib/iomgr/pollset.h"
|
32
34
|
#include "src/core/lib/iomgr/timer.h"
|
33
35
|
#include "src/core/lib/surface/channel.h"
|
@@ -153,7 +155,7 @@ static void g_poller_init_locked() {
|
|
153
155
|
|
154
156
|
void grpc_client_channel_start_backup_polling(
|
155
157
|
grpc_pollset_set* interested_parties) {
|
156
|
-
if (g_poll_interval_ms == 0) {
|
158
|
+
if (g_poll_interval_ms == 0 || grpc_iomgr_run_in_background()) {
|
157
159
|
return;
|
158
160
|
}
|
159
161
|
gpr_mu_lock(&g_poller_mu);
|
@@ -171,7 +173,7 @@ void grpc_client_channel_start_backup_polling(
|
|
171
173
|
|
172
174
|
void grpc_client_channel_stop_backup_polling(
|
173
175
|
grpc_pollset_set* interested_parties) {
|
174
|
-
if (g_poll_interval_ms == 0) {
|
176
|
+
if (g_poll_interval_ms == 0 || grpc_iomgr_run_in_background()) {
|
175
177
|
return;
|
176
178
|
}
|
177
179
|
grpc_pollset_set_del_pollset(interested_parties, g_poller->pollset);
|
@@ -147,6 +147,9 @@ class ChannelData {
|
|
147
147
|
return service_config_;
|
148
148
|
}
|
149
149
|
|
150
|
+
RefCountedPtr<ConnectedSubchannel> GetConnectedSubchannelInDataPlane(
|
151
|
+
SubchannelInterface* subchannel) const;
|
152
|
+
|
150
153
|
grpc_connectivity_state CheckConnectivityState(bool try_to_connect);
|
151
154
|
void AddExternalConnectivityWatcher(grpc_polling_entity pollent,
|
152
155
|
grpc_connectivity_state* state,
|
@@ -161,9 +164,9 @@ class ChannelData {
|
|
161
164
|
}
|
162
165
|
|
163
166
|
private:
|
167
|
+
class SubchannelWrapper;
|
164
168
|
class ConnectivityStateAndPickerSetter;
|
165
169
|
class ServiceConfigSetter;
|
166
|
-
class GrpcSubchannel;
|
167
170
|
class ClientChannelControlHelper;
|
168
171
|
|
169
172
|
class ExternalConnectivityWatcher {
|
@@ -210,6 +213,10 @@ class ChannelData {
|
|
210
213
|
ChannelData(grpc_channel_element_args* args, grpc_error** error);
|
211
214
|
~ChannelData();
|
212
215
|
|
216
|
+
void CreateResolvingLoadBalancingPolicyLocked();
|
217
|
+
|
218
|
+
void DestroyResolvingLoadBalancingPolicyLocked();
|
219
|
+
|
213
220
|
static bool ProcessResolverResultLocked(
|
214
221
|
void* arg, const Resolver::Result& result, const char** lb_policy_name,
|
215
222
|
RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config,
|
@@ -235,8 +242,10 @@ class ChannelData {
|
|
235
242
|
const size_t per_rpc_retry_buffer_size_;
|
236
243
|
grpc_channel_stack* owning_stack_;
|
237
244
|
ClientChannelFactory* client_channel_factory_;
|
238
|
-
|
245
|
+
const grpc_channel_args* channel_args_;
|
239
246
|
RefCountedPtr<ServiceConfig> default_service_config_;
|
247
|
+
UniquePtr<char> server_name_;
|
248
|
+
UniquePtr<char> target_uri_;
|
240
249
|
channelz::ChannelNode* channelz_node_;
|
241
250
|
|
242
251
|
//
|
@@ -262,7 +271,14 @@ class ChannelData {
|
|
262
271
|
UniquePtr<char> health_check_service_name_;
|
263
272
|
RefCountedPtr<ServiceConfig> saved_service_config_;
|
264
273
|
bool received_first_resolver_result_ = false;
|
274
|
+
// The number of SubchannelWrapper instances referencing a given Subchannel.
|
265
275
|
Map<Subchannel*, int> subchannel_refcount_map_;
|
276
|
+
// Pending ConnectedSubchannel updates for each SubchannelWrapper.
|
277
|
+
// Updates are queued here in the control plane combiner and then applied
|
278
|
+
// in the data plane combiner when the picker is updated.
|
279
|
+
Map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>,
|
280
|
+
RefCountedPtrLess<SubchannelWrapper>>
|
281
|
+
pending_subchannel_updates_;
|
266
282
|
|
267
283
|
//
|
268
284
|
// Fields accessed from both data plane and control plane combiners.
|
@@ -304,6 +320,54 @@ class CallData {
|
|
304
320
|
private:
|
305
321
|
class QueuedPickCanceller;
|
306
322
|
|
323
|
+
class Metadata : public LoadBalancingPolicy::MetadataInterface {
|
324
|
+
public:
|
325
|
+
Metadata(CallData* calld, grpc_metadata_batch* batch)
|
326
|
+
: calld_(calld), batch_(batch) {}
|
327
|
+
|
328
|
+
void Add(StringView key, StringView value) override {
|
329
|
+
grpc_linked_mdelem* linked_mdelem = static_cast<grpc_linked_mdelem*>(
|
330
|
+
calld_->arena_->Alloc(sizeof(grpc_linked_mdelem)));
|
331
|
+
linked_mdelem->md = grpc_mdelem_from_slices(
|
332
|
+
grpc_core::ExternallyManagedSlice(key.data(), key.size()),
|
333
|
+
grpc_core::ExternallyManagedSlice(value.data(), value.size()));
|
334
|
+
GPR_ASSERT(grpc_metadata_batch_link_tail(batch_, linked_mdelem) ==
|
335
|
+
GRPC_ERROR_NONE);
|
336
|
+
}
|
337
|
+
|
338
|
+
Iterator Begin() const override {
|
339
|
+
static_assert(sizeof(grpc_linked_mdelem*) <= sizeof(Iterator),
|
340
|
+
"iterator size too large");
|
341
|
+
return reinterpret_cast<Iterator>(batch_->list.head);
|
342
|
+
}
|
343
|
+
bool IsEnd(Iterator it) const override {
|
344
|
+
return reinterpret_cast<grpc_linked_mdelem*>(it) == nullptr;
|
345
|
+
}
|
346
|
+
void Next(Iterator* it) const override {
|
347
|
+
*it = reinterpret_cast<Iterator>(
|
348
|
+
reinterpret_cast<grpc_linked_mdelem*>(*it)->next);
|
349
|
+
}
|
350
|
+
StringView Key(Iterator it) const override {
|
351
|
+
return StringView(
|
352
|
+
GRPC_MDKEY(reinterpret_cast<grpc_linked_mdelem*>(it)->md));
|
353
|
+
}
|
354
|
+
StringView Value(Iterator it) const override {
|
355
|
+
return StringView(
|
356
|
+
GRPC_MDVALUE(reinterpret_cast<grpc_linked_mdelem*>(it)->md));
|
357
|
+
}
|
358
|
+
|
359
|
+
void Erase(Iterator* it) override {
|
360
|
+
grpc_linked_mdelem* linked_mdelem =
|
361
|
+
reinterpret_cast<grpc_linked_mdelem*>(*it);
|
362
|
+
*it = reinterpret_cast<Iterator>(linked_mdelem->next);
|
363
|
+
grpc_metadata_batch_remove(batch_, linked_mdelem);
|
364
|
+
}
|
365
|
+
|
366
|
+
private:
|
367
|
+
CallData* calld_;
|
368
|
+
grpc_metadata_batch* batch_;
|
369
|
+
};
|
370
|
+
|
307
371
|
class LbCallState : public LoadBalancingPolicy::CallState {
|
308
372
|
public:
|
309
373
|
explicit LbCallState(CallData* calld) : calld_(calld) {}
|
@@ -644,7 +708,8 @@ class CallData {
|
|
644
708
|
LbCallState lb_call_state_;
|
645
709
|
RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
|
646
710
|
void (*lb_recv_trailing_metadata_ready_)(
|
647
|
-
void* user_data,
|
711
|
+
void* user_data,
|
712
|
+
LoadBalancingPolicy::MetadataInterface* recv_trailing_metadata,
|
648
713
|
LoadBalancingPolicy::CallState* call_state) = nullptr;
|
649
714
|
void* lb_recv_trailing_metadata_ready_user_data_ = nullptr;
|
650
715
|
grpc_closure pick_closure_;
|
@@ -706,6 +771,247 @@ class CallData {
|
|
706
771
|
grpc_metadata_batch send_trailing_metadata_;
|
707
772
|
};
|
708
773
|
|
774
|
+
//
|
775
|
+
// ChannelData::SubchannelWrapper
|
776
|
+
//
|
777
|
+
|
778
|
+
// This class is a wrapper for Subchannel that hides details of the
|
779
|
+
// channel's implementation (such as the health check service name and
|
780
|
+
// connected subchannel) from the LB policy API.
|
781
|
+
//
|
782
|
+
// Note that no synchronization is needed here, because even if the
|
783
|
+
// underlying subchannel is shared between channels, this wrapper will only
|
784
|
+
// be used within one channel, so it will always be synchronized by the
|
785
|
+
// control plane combiner.
|
786
|
+
class ChannelData::SubchannelWrapper : public SubchannelInterface {
|
787
|
+
public:
|
788
|
+
SubchannelWrapper(ChannelData* chand, Subchannel* subchannel,
|
789
|
+
UniquePtr<char> health_check_service_name)
|
790
|
+
: SubchannelInterface(&grpc_client_channel_routing_trace),
|
791
|
+
chand_(chand),
|
792
|
+
subchannel_(subchannel),
|
793
|
+
health_check_service_name_(std::move(health_check_service_name)) {
|
794
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
795
|
+
gpr_log(GPR_INFO,
|
796
|
+
"chand=%p: creating subchannel wrapper %p for subchannel %p",
|
797
|
+
chand, this, subchannel_);
|
798
|
+
}
|
799
|
+
GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "SubchannelWrapper");
|
800
|
+
auto* subchannel_node = subchannel_->channelz_node();
|
801
|
+
if (subchannel_node != nullptr) {
|
802
|
+
intptr_t subchannel_uuid = subchannel_node->uuid();
|
803
|
+
auto it = chand_->subchannel_refcount_map_.find(subchannel_);
|
804
|
+
if (it == chand_->subchannel_refcount_map_.end()) {
|
805
|
+
chand_->channelz_node_->AddChildSubchannel(subchannel_uuid);
|
806
|
+
it = chand_->subchannel_refcount_map_.emplace(subchannel_, 0).first;
|
807
|
+
}
|
808
|
+
++it->second;
|
809
|
+
}
|
810
|
+
}
|
811
|
+
|
812
|
+
~SubchannelWrapper() {
|
813
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
814
|
+
gpr_log(GPR_INFO,
|
815
|
+
"chand=%p: destroying subchannel wrapper %p for subchannel %p",
|
816
|
+
chand_, this, subchannel_);
|
817
|
+
}
|
818
|
+
auto* subchannel_node = subchannel_->channelz_node();
|
819
|
+
if (subchannel_node != nullptr) {
|
820
|
+
intptr_t subchannel_uuid = subchannel_node->uuid();
|
821
|
+
auto it = chand_->subchannel_refcount_map_.find(subchannel_);
|
822
|
+
GPR_ASSERT(it != chand_->subchannel_refcount_map_.end());
|
823
|
+
--it->second;
|
824
|
+
if (it->second == 0) {
|
825
|
+
chand_->channelz_node_->RemoveChildSubchannel(subchannel_uuid);
|
826
|
+
chand_->subchannel_refcount_map_.erase(it);
|
827
|
+
}
|
828
|
+
}
|
829
|
+
GRPC_SUBCHANNEL_UNREF(subchannel_, "unref from LB");
|
830
|
+
GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "SubchannelWrapper");
|
831
|
+
}
|
832
|
+
|
833
|
+
grpc_connectivity_state CheckConnectivityState() override {
|
834
|
+
RefCountedPtr<ConnectedSubchannel> connected_subchannel;
|
835
|
+
grpc_connectivity_state connectivity_state =
|
836
|
+
subchannel_->CheckConnectivityState(health_check_service_name_.get(),
|
837
|
+
&connected_subchannel);
|
838
|
+
MaybeUpdateConnectedSubchannel(std::move(connected_subchannel));
|
839
|
+
return connectivity_state;
|
840
|
+
}
|
841
|
+
|
842
|
+
void WatchConnectivityState(
|
843
|
+
grpc_connectivity_state initial_state,
|
844
|
+
UniquePtr<ConnectivityStateWatcherInterface> watcher) override {
|
845
|
+
auto& watcher_wrapper = watcher_map_[watcher.get()];
|
846
|
+
GPR_ASSERT(watcher_wrapper == nullptr);
|
847
|
+
watcher_wrapper = New<WatcherWrapper>(
|
848
|
+
std::move(watcher), Ref(DEBUG_LOCATION, "WatcherWrapper"));
|
849
|
+
subchannel_->WatchConnectivityState(
|
850
|
+
initial_state,
|
851
|
+
UniquePtr<char>(gpr_strdup(health_check_service_name_.get())),
|
852
|
+
OrphanablePtr<Subchannel::ConnectivityStateWatcherInterface>(
|
853
|
+
watcher_wrapper));
|
854
|
+
}
|
855
|
+
|
856
|
+
void CancelConnectivityStateWatch(
|
857
|
+
ConnectivityStateWatcherInterface* watcher) override {
|
858
|
+
auto it = watcher_map_.find(watcher);
|
859
|
+
GPR_ASSERT(it != watcher_map_.end());
|
860
|
+
subchannel_->CancelConnectivityStateWatch(health_check_service_name_.get(),
|
861
|
+
it->second);
|
862
|
+
watcher_map_.erase(it);
|
863
|
+
}
|
864
|
+
|
865
|
+
void AttemptToConnect() override { subchannel_->AttemptToConnect(); }
|
866
|
+
|
867
|
+
void ResetBackoff() override { subchannel_->ResetBackoff(); }
|
868
|
+
|
869
|
+
const grpc_channel_args* channel_args() override {
|
870
|
+
return subchannel_->channel_args();
|
871
|
+
}
|
872
|
+
|
873
|
+
// Caller must be holding the control-plane combiner.
|
874
|
+
ConnectedSubchannel* connected_subchannel() const {
|
875
|
+
return connected_subchannel_.get();
|
876
|
+
}
|
877
|
+
|
878
|
+
// Caller must be holding the data-plane combiner.
|
879
|
+
ConnectedSubchannel* connected_subchannel_in_data_plane() const {
|
880
|
+
return connected_subchannel_in_data_plane_.get();
|
881
|
+
}
|
882
|
+
void set_connected_subchannel_in_data_plane(
|
883
|
+
RefCountedPtr<ConnectedSubchannel> connected_subchannel) {
|
884
|
+
connected_subchannel_in_data_plane_ = std::move(connected_subchannel);
|
885
|
+
}
|
886
|
+
|
887
|
+
private:
|
888
|
+
// Subchannel and SubchannelInterface have different interfaces for
|
889
|
+
// their respective ConnectivityStateWatcherInterface classes.
|
890
|
+
// The one in Subchannel updates the ConnectedSubchannel along with
|
891
|
+
// the state, whereas the one in SubchannelInterface does not expose
|
892
|
+
// the ConnectedSubchannel.
|
893
|
+
//
|
894
|
+
// This wrapper provides a bridge between the two. It implements
|
895
|
+
// Subchannel::ConnectivityStateWatcherInterface and wraps
|
896
|
+
// the instance of SubchannelInterface::ConnectivityStateWatcherInterface
|
897
|
+
// that was passed in by the LB policy. We pass an instance of this
|
898
|
+
// class to the underlying Subchannel, and when we get updates from
|
899
|
+
// the subchannel, we pass those on to the wrapped watcher to return
|
900
|
+
// the update to the LB policy. This allows us to set the connected
|
901
|
+
// subchannel before passing the result back to the LB policy.
|
902
|
+
class WatcherWrapper : public Subchannel::ConnectivityStateWatcherInterface {
|
903
|
+
public:
|
904
|
+
WatcherWrapper(
|
905
|
+
UniquePtr<SubchannelInterface::ConnectivityStateWatcherInterface>
|
906
|
+
watcher,
|
907
|
+
RefCountedPtr<SubchannelWrapper> parent)
|
908
|
+
: watcher_(std::move(watcher)), parent_(std::move(parent)) {}
|
909
|
+
|
910
|
+
~WatcherWrapper() { parent_.reset(DEBUG_LOCATION, "WatcherWrapper"); }
|
911
|
+
|
912
|
+
void Orphan() override { Unref(); }
|
913
|
+
|
914
|
+
void OnConnectivityStateChange(
|
915
|
+
grpc_connectivity_state new_state,
|
916
|
+
RefCountedPtr<ConnectedSubchannel> connected_subchannel) override {
|
917
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
918
|
+
gpr_log(GPR_INFO,
|
919
|
+
"chand=%p: connectivity change for subchannel wrapper %p "
|
920
|
+
"subchannel %p (connected_subchannel=%p state=%s); "
|
921
|
+
"hopping into combiner",
|
922
|
+
parent_->chand_, parent_.get(), parent_->subchannel_,
|
923
|
+
connected_subchannel.get(),
|
924
|
+
grpc_connectivity_state_name(new_state));
|
925
|
+
}
|
926
|
+
// Will delete itself.
|
927
|
+
New<Updater>(Ref(), new_state, std::move(connected_subchannel));
|
928
|
+
}
|
929
|
+
|
930
|
+
grpc_pollset_set* interested_parties() override {
|
931
|
+
return watcher_->interested_parties();
|
932
|
+
}
|
933
|
+
|
934
|
+
private:
|
935
|
+
class Updater {
|
936
|
+
public:
|
937
|
+
Updater(RefCountedPtr<WatcherWrapper> parent,
|
938
|
+
grpc_connectivity_state new_state,
|
939
|
+
RefCountedPtr<ConnectedSubchannel> connected_subchannel)
|
940
|
+
: parent_(std::move(parent)),
|
941
|
+
state_(new_state),
|
942
|
+
connected_subchannel_(std::move(connected_subchannel)) {
|
943
|
+
GRPC_CLOSURE_INIT(
|
944
|
+
&closure_, ApplyUpdateInControlPlaneCombiner, this,
|
945
|
+
grpc_combiner_scheduler(parent_->parent_->chand_->combiner_));
|
946
|
+
GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE);
|
947
|
+
}
|
948
|
+
|
949
|
+
private:
|
950
|
+
static void ApplyUpdateInControlPlaneCombiner(void* arg,
|
951
|
+
grpc_error* error) {
|
952
|
+
Updater* self = static_cast<Updater*>(arg);
|
953
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
954
|
+
gpr_log(GPR_INFO,
|
955
|
+
"chand=%p: processing connectivity change in combiner "
|
956
|
+
"for subchannel wrapper %p subchannel %p "
|
957
|
+
"(connected_subchannel=%p state=%s)",
|
958
|
+
self->parent_->parent_->chand_, self->parent_->parent_.get(),
|
959
|
+
self->parent_->parent_->subchannel_,
|
960
|
+
self->connected_subchannel_.get(),
|
961
|
+
grpc_connectivity_state_name(self->state_));
|
962
|
+
}
|
963
|
+
self->parent_->parent_->MaybeUpdateConnectedSubchannel(
|
964
|
+
std::move(self->connected_subchannel_));
|
965
|
+
self->parent_->watcher_->OnConnectivityStateChange(self->state_);
|
966
|
+
Delete(self);
|
967
|
+
}
|
968
|
+
|
969
|
+
RefCountedPtr<WatcherWrapper> parent_;
|
970
|
+
grpc_connectivity_state state_;
|
971
|
+
RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
|
972
|
+
grpc_closure closure_;
|
973
|
+
};
|
974
|
+
|
975
|
+
UniquePtr<SubchannelInterface::ConnectivityStateWatcherInterface> watcher_;
|
976
|
+
RefCountedPtr<SubchannelWrapper> parent_;
|
977
|
+
};
|
978
|
+
|
979
|
+
void MaybeUpdateConnectedSubchannel(
|
980
|
+
RefCountedPtr<ConnectedSubchannel> connected_subchannel) {
|
981
|
+
// Update the connected subchannel only if the channel is not shutting
|
982
|
+
// down. This is because once the channel is shutting down, we
|
983
|
+
// ignore picker updates from the LB policy, which means that
|
984
|
+
// ConnectivityStateAndPickerSetter will never process the entries
|
985
|
+
// in chand_->pending_subchannel_updates_. So we don't want to add
|
986
|
+
// entries there that will never be processed, since that would
|
987
|
+
// leave dangling refs to the channel and prevent its destruction.
|
988
|
+
grpc_error* disconnect_error = chand_->disconnect_error();
|
989
|
+
if (disconnect_error != GRPC_ERROR_NONE) return;
|
990
|
+
// Not shutting down, so do the update.
|
991
|
+
if (connected_subchannel_ != connected_subchannel) {
|
992
|
+
connected_subchannel_ = std::move(connected_subchannel);
|
993
|
+
// Record the new connected subchannel so that it can be updated
|
994
|
+
// in the data plane combiner the next time the picker is updated.
|
995
|
+
chand_->pending_subchannel_updates_[Ref(
|
996
|
+
DEBUG_LOCATION, "ConnectedSubchannelUpdate")] = connected_subchannel_;
|
997
|
+
}
|
998
|
+
}
|
999
|
+
|
1000
|
+
ChannelData* chand_;
|
1001
|
+
Subchannel* subchannel_;
|
1002
|
+
UniquePtr<char> health_check_service_name_;
|
1003
|
+
// Maps from the address of the watcher passed to us by the LB policy
|
1004
|
+
// to the address of the WrapperWatcher that we passed to the underlying
|
1005
|
+
// subchannel. This is needed so that when the LB policy calls
|
1006
|
+
// CancelConnectivityStateWatch() with its watcher, we know the
|
1007
|
+
// corresponding WrapperWatcher to cancel on the underlying subchannel.
|
1008
|
+
Map<ConnectivityStateWatcherInterface*, WatcherWrapper*> watcher_map_;
|
1009
|
+
// To be accessed only in the control plane combiner.
|
1010
|
+
RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
|
1011
|
+
// To be accessed only in the data plane combiner.
|
1012
|
+
RefCountedPtr<ConnectedSubchannel> connected_subchannel_in_data_plane_;
|
1013
|
+
};
|
1014
|
+
|
709
1015
|
//
|
710
1016
|
// ChannelData::ConnectivityStateAndPickerSetter
|
711
1017
|
//
|
@@ -720,6 +1026,13 @@ class ChannelData::ConnectivityStateAndPickerSetter {
|
|
720
1026
|
ChannelData* chand, grpc_connectivity_state state, const char* reason,
|
721
1027
|
UniquePtr<LoadBalancingPolicy::SubchannelPicker> picker)
|
722
1028
|
: chand_(chand), picker_(std::move(picker)) {
|
1029
|
+
// Clean the control plane when entering IDLE, while holding control plane
|
1030
|
+
// combiner.
|
1031
|
+
if (picker_ == nullptr) {
|
1032
|
+
chand->health_check_service_name_.reset();
|
1033
|
+
chand->saved_service_config_.reset();
|
1034
|
+
chand->received_first_resolver_result_ = false;
|
1035
|
+
}
|
723
1036
|
// Update connectivity state here, while holding control plane combiner.
|
724
1037
|
grpc_connectivity_state_set(&chand->state_tracker_, state, reason);
|
725
1038
|
if (chand->channelz_node_ != nullptr) {
|
@@ -727,44 +1040,59 @@ class ChannelData::ConnectivityStateAndPickerSetter {
|
|
727
1040
|
chand->channelz_node_->AddTraceEvent(
|
728
1041
|
channelz::ChannelTrace::Severity::Info,
|
729
1042
|
grpc_slice_from_static_string(
|
730
|
-
GetChannelConnectivityStateChangeString(
|
1043
|
+
channelz::ChannelNode::GetChannelConnectivityStateChangeString(
|
1044
|
+
state)));
|
731
1045
|
}
|
1046
|
+
// Grab any pending subchannel updates.
|
1047
|
+
pending_subchannel_updates_ =
|
1048
|
+
std::move(chand_->pending_subchannel_updates_);
|
732
1049
|
// Bounce into the data plane combiner to reset the picker.
|
733
1050
|
GRPC_CHANNEL_STACK_REF(chand->owning_stack_,
|
734
1051
|
"ConnectivityStateAndPickerSetter");
|
735
|
-
GRPC_CLOSURE_INIT(&closure_,
|
1052
|
+
GRPC_CLOSURE_INIT(&closure_, SetPickerInDataPlane, this,
|
736
1053
|
grpc_combiner_scheduler(chand->data_plane_combiner_));
|
737
1054
|
GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE);
|
738
1055
|
}
|
739
1056
|
|
740
1057
|
private:
|
741
|
-
static
|
742
|
-
grpc_connectivity_state state) {
|
743
|
-
switch (state) {
|
744
|
-
case GRPC_CHANNEL_IDLE:
|
745
|
-
return "Channel state change to IDLE";
|
746
|
-
case GRPC_CHANNEL_CONNECTING:
|
747
|
-
return "Channel state change to CONNECTING";
|
748
|
-
case GRPC_CHANNEL_READY:
|
749
|
-
return "Channel state change to READY";
|
750
|
-
case GRPC_CHANNEL_TRANSIENT_FAILURE:
|
751
|
-
return "Channel state change to TRANSIENT_FAILURE";
|
752
|
-
case GRPC_CHANNEL_SHUTDOWN:
|
753
|
-
return "Channel state change to SHUTDOWN";
|
754
|
-
}
|
755
|
-
GPR_UNREACHABLE_CODE(return "UNKNOWN");
|
756
|
-
}
|
757
|
-
|
758
|
-
static void SetPicker(void* arg, grpc_error* ignored) {
|
1058
|
+
static void SetPickerInDataPlane(void* arg, grpc_error* ignored) {
|
759
1059
|
auto* self = static_cast<ConnectivityStateAndPickerSetter*>(arg);
|
760
|
-
//
|
761
|
-
|
1060
|
+
// Handle subchannel updates.
|
1061
|
+
for (auto& p : self->pending_subchannel_updates_) {
|
1062
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
1063
|
+
gpr_log(GPR_INFO,
|
1064
|
+
"chand=%p: updating subchannel wrapper %p data plane "
|
1065
|
+
"connected_subchannel to %p",
|
1066
|
+
self->chand_, p.first.get(), p.second.get());
|
1067
|
+
}
|
1068
|
+
p.first->set_connected_subchannel_in_data_plane(std::move(p.second));
|
1069
|
+
}
|
1070
|
+
// Swap out the picker. We hang on to the old picker so that it can
|
1071
|
+
// be deleted in the control-plane combiner, since that's where we need
|
1072
|
+
// to unref the subchannel wrappers that are reffed by the picker.
|
1073
|
+
self->picker_.swap(self->chand_->picker_);
|
1074
|
+
// Clean the data plane if the updated picker is nullptr.
|
1075
|
+
if (self->chand_->picker_ == nullptr) {
|
1076
|
+
self->chand_->received_service_config_data_ = false;
|
1077
|
+
self->chand_->retry_throttle_data_.reset();
|
1078
|
+
self->chand_->service_config_.reset();
|
1079
|
+
}
|
762
1080
|
// Re-process queued picks.
|
763
1081
|
for (QueuedPick* pick = self->chand_->queued_picks_; pick != nullptr;
|
764
1082
|
pick = pick->next) {
|
765
1083
|
CallData::StartPickLocked(pick->elem, GRPC_ERROR_NONE);
|
766
1084
|
}
|
767
|
-
//
|
1085
|
+
// Pop back into the control plane combiner to delete ourself, so
|
1086
|
+
// that we make sure to unref subchannel wrappers there. This
|
1087
|
+
// includes both the ones reffed by the old picker (now stored in
|
1088
|
+
// self->picker_) and the ones in self->pending_subchannel_updates_.
|
1089
|
+
GRPC_CLOSURE_INIT(&self->closure_, CleanUpInControlPlane, self,
|
1090
|
+
grpc_combiner_scheduler(self->chand_->combiner_));
|
1091
|
+
GRPC_CLOSURE_SCHED(&self->closure_, GRPC_ERROR_NONE);
|
1092
|
+
}
|
1093
|
+
|
1094
|
+
static void CleanUpInControlPlane(void* arg, grpc_error* ignored) {
|
1095
|
+
auto* self = static_cast<ConnectivityStateAndPickerSetter*>(arg);
|
768
1096
|
GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack_,
|
769
1097
|
"ConnectivityStateAndPickerSetter");
|
770
1098
|
Delete(self);
|
@@ -772,6 +1100,9 @@ class ChannelData::ConnectivityStateAndPickerSetter {
|
|
772
1100
|
|
773
1101
|
ChannelData* chand_;
|
774
1102
|
UniquePtr<LoadBalancingPolicy::SubchannelPicker> picker_;
|
1103
|
+
Map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>,
|
1104
|
+
RefCountedPtrLess<SubchannelWrapper>>
|
1105
|
+
pending_subchannel_updates_;
|
775
1106
|
grpc_closure closure_;
|
776
1107
|
};
|
777
1108
|
|
@@ -946,89 +1277,6 @@ void ChannelData::ExternalConnectivityWatcher::WatchConnectivityStateLocked(
|
|
946
1277
|
&self->chand_->state_tracker_, self->state_, &self->my_closure_);
|
947
1278
|
}
|
948
1279
|
|
949
|
-
//
|
950
|
-
// ChannelData::GrpcSubchannel
|
951
|
-
//
|
952
|
-
|
953
|
-
// This class is a wrapper for Subchannel that hides details of the
|
954
|
-
// channel's implementation (such as the health check service name) from
|
955
|
-
// the LB policy API.
|
956
|
-
//
|
957
|
-
// Note that no synchronization is needed here, because even if the
|
958
|
-
// underlying subchannel is shared between channels, this wrapper will only
|
959
|
-
// be used within one channel, so it will always be synchronized by the
|
960
|
-
// control plane combiner.
|
961
|
-
class ChannelData::GrpcSubchannel : public SubchannelInterface {
|
962
|
-
public:
|
963
|
-
GrpcSubchannel(ChannelData* chand, Subchannel* subchannel,
|
964
|
-
UniquePtr<char> health_check_service_name)
|
965
|
-
: chand_(chand),
|
966
|
-
subchannel_(subchannel),
|
967
|
-
health_check_service_name_(std::move(health_check_service_name)) {
|
968
|
-
GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "GrpcSubchannel");
|
969
|
-
auto* subchannel_node = subchannel_->channelz_node();
|
970
|
-
if (subchannel_node != nullptr) {
|
971
|
-
intptr_t subchannel_uuid = subchannel_node->uuid();
|
972
|
-
auto it = chand_->subchannel_refcount_map_.find(subchannel_);
|
973
|
-
if (it == chand_->subchannel_refcount_map_.end()) {
|
974
|
-
chand_->channelz_node_->AddChildSubchannel(subchannel_uuid);
|
975
|
-
it = chand_->subchannel_refcount_map_.emplace(subchannel_, 0).first;
|
976
|
-
}
|
977
|
-
++it->second;
|
978
|
-
}
|
979
|
-
}
|
980
|
-
|
981
|
-
~GrpcSubchannel() {
|
982
|
-
auto* subchannel_node = subchannel_->channelz_node();
|
983
|
-
if (subchannel_node != nullptr) {
|
984
|
-
intptr_t subchannel_uuid = subchannel_node->uuid();
|
985
|
-
auto it = chand_->subchannel_refcount_map_.find(subchannel_);
|
986
|
-
GPR_ASSERT(it != chand_->subchannel_refcount_map_.end());
|
987
|
-
--it->second;
|
988
|
-
if (it->second == 0) {
|
989
|
-
chand_->channelz_node_->RemoveChildSubchannel(subchannel_uuid);
|
990
|
-
chand_->subchannel_refcount_map_.erase(it);
|
991
|
-
}
|
992
|
-
}
|
993
|
-
GRPC_SUBCHANNEL_UNREF(subchannel_, "unref from LB");
|
994
|
-
GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "GrpcSubchannel");
|
995
|
-
}
|
996
|
-
|
997
|
-
grpc_connectivity_state CheckConnectivityState(
|
998
|
-
RefCountedPtr<ConnectedSubchannelInterface>* connected_subchannel)
|
999
|
-
override {
|
1000
|
-
RefCountedPtr<ConnectedSubchannel> tmp;
|
1001
|
-
auto retval = subchannel_->CheckConnectivityState(
|
1002
|
-
health_check_service_name_.get(), &tmp);
|
1003
|
-
*connected_subchannel = std::move(tmp);
|
1004
|
-
return retval;
|
1005
|
-
}
|
1006
|
-
|
1007
|
-
void WatchConnectivityState(
|
1008
|
-
grpc_connectivity_state initial_state,
|
1009
|
-
UniquePtr<ConnectivityStateWatcher> watcher) override {
|
1010
|
-
subchannel_->WatchConnectivityState(
|
1011
|
-
initial_state,
|
1012
|
-
UniquePtr<char>(gpr_strdup(health_check_service_name_.get())),
|
1013
|
-
std::move(watcher));
|
1014
|
-
}
|
1015
|
-
|
1016
|
-
void CancelConnectivityStateWatch(
|
1017
|
-
ConnectivityStateWatcher* watcher) override {
|
1018
|
-
subchannel_->CancelConnectivityStateWatch(health_check_service_name_.get(),
|
1019
|
-
watcher);
|
1020
|
-
}
|
1021
|
-
|
1022
|
-
void AttemptToConnect() override { subchannel_->AttemptToConnect(); }
|
1023
|
-
|
1024
|
-
void ResetBackoff() override { subchannel_->ResetBackoff(); }
|
1025
|
-
|
1026
|
-
private:
|
1027
|
-
ChannelData* chand_;
|
1028
|
-
Subchannel* subchannel_;
|
1029
|
-
UniquePtr<char> health_check_service_name_;
|
1030
|
-
};
|
1031
|
-
|
1032
1280
|
//
|
1033
1281
|
// ChannelData::ClientChannelControlHelper
|
1034
1282
|
//
|
@@ -1066,8 +1314,8 @@ class ChannelData::ClientChannelControlHelper
|
|
1066
1314
|
chand_->client_channel_factory_->CreateSubchannel(new_args);
|
1067
1315
|
grpc_channel_args_destroy(new_args);
|
1068
1316
|
if (subchannel == nullptr) return nullptr;
|
1069
|
-
return MakeRefCounted<
|
1070
|
-
|
1317
|
+
return MakeRefCounted<SubchannelWrapper>(
|
1318
|
+
chand_, subchannel, std::move(health_check_service_name));
|
1071
1319
|
}
|
1072
1320
|
|
1073
1321
|
grpc_channel* CreateChannel(const char* target,
|
@@ -1078,8 +1326,7 @@ class ChannelData::ClientChannelControlHelper
|
|
1078
1326
|
void UpdateState(
|
1079
1327
|
grpc_connectivity_state state,
|
1080
1328
|
UniquePtr<LoadBalancingPolicy::SubchannelPicker> picker) override {
|
1081
|
-
grpc_error* disconnect_error =
|
1082
|
-
chand_->disconnect_error_.Load(MemoryOrder::ACQUIRE);
|
1329
|
+
grpc_error* disconnect_error = chand_->disconnect_error();
|
1083
1330
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
1084
1331
|
const char* extra = disconnect_error == GRPC_ERROR_NONE
|
1085
1332
|
? ""
|
@@ -1226,59 +1473,61 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error)
|
|
1226
1473
|
grpc_channel_args* new_args = nullptr;
|
1227
1474
|
grpc_proxy_mappers_map_name(server_uri, args->channel_args, &proxy_name,
|
1228
1475
|
&new_args);
|
1229
|
-
|
1230
|
-
|
1476
|
+
target_uri_.reset(proxy_name != nullptr ? proxy_name
|
1477
|
+
: gpr_strdup(server_uri));
|
1478
|
+
channel_args_ = new_args != nullptr
|
1479
|
+
? new_args
|
1480
|
+
: grpc_channel_args_copy(args->channel_args);
|
1481
|
+
if (!ResolverRegistry::IsValidTarget(target_uri_.get())) {
|
1482
|
+
*error =
|
1483
|
+
GRPC_ERROR_CREATE_FROM_STATIC_STRING("the target uri is not valid.");
|
1484
|
+
return;
|
1485
|
+
}
|
1486
|
+
*error = GRPC_ERROR_NONE;
|
1487
|
+
}
|
1488
|
+
|
1489
|
+
ChannelData::~ChannelData() {
|
1490
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
1491
|
+
gpr_log(GPR_INFO, "chand=%p: destroying channel", this);
|
1492
|
+
}
|
1493
|
+
DestroyResolvingLoadBalancingPolicyLocked();
|
1494
|
+
grpc_channel_args_destroy(channel_args_);
|
1495
|
+
// Stop backup polling.
|
1496
|
+
grpc_client_channel_stop_backup_polling(interested_parties_);
|
1497
|
+
grpc_pollset_set_destroy(interested_parties_);
|
1498
|
+
GRPC_COMBINER_UNREF(data_plane_combiner_, "client_channel");
|
1499
|
+
GRPC_COMBINER_UNREF(combiner_, "client_channel");
|
1500
|
+
GRPC_ERROR_UNREF(disconnect_error_.Load(MemoryOrder::RELAXED));
|
1501
|
+
grpc_connectivity_state_destroy(&state_tracker_);
|
1502
|
+
gpr_mu_destroy(&info_mu_);
|
1503
|
+
}
|
1504
|
+
|
1505
|
+
void ChannelData::CreateResolvingLoadBalancingPolicyLocked() {
|
1231
1506
|
// Instantiate resolving LB policy.
|
1232
1507
|
LoadBalancingPolicy::Args lb_args;
|
1233
1508
|
lb_args.combiner = combiner_;
|
1234
1509
|
lb_args.channel_control_helper =
|
1235
1510
|
UniquePtr<LoadBalancingPolicy::ChannelControlHelper>(
|
1236
1511
|
New<ClientChannelControlHelper>(this));
|
1237
|
-
lb_args.args =
|
1512
|
+
lb_args.args = channel_args_;
|
1513
|
+
UniquePtr<char> target_uri(gpr_strdup(target_uri_.get()));
|
1238
1514
|
resolving_lb_policy_.reset(New<ResolvingLoadBalancingPolicy>(
|
1239
1515
|
std::move(lb_args), &grpc_client_channel_routing_trace,
|
1240
|
-
std::move(target_uri), ProcessResolverResultLocked, this
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
// unref the channel stack) before we return.
|
1247
|
-
// TODO(roth): This is not a complete solution, because it only
|
1248
|
-
// catches the case where channel stack initialization fails in this
|
1249
|
-
// particular filter. If there is a failure in a different filter, we
|
1250
|
-
// will leave a dangling ref here, which can cause a crash. Fortunately,
|
1251
|
-
// in practice, there are no other filters that can cause failures in
|
1252
|
-
// channel stack initialization, so this works for now.
|
1253
|
-
resolving_lb_policy_.reset();
|
1254
|
-
ExecCtx::Get()->Flush();
|
1255
|
-
} else {
|
1256
|
-
grpc_pollset_set_add_pollset_set(resolving_lb_policy_->interested_parties(),
|
1257
|
-
interested_parties_);
|
1258
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
1259
|
-
gpr_log(GPR_INFO, "chand=%p: created resolving_lb_policy=%p", this,
|
1260
|
-
resolving_lb_policy_.get());
|
1261
|
-
}
|
1516
|
+
std::move(target_uri), ProcessResolverResultLocked, this));
|
1517
|
+
grpc_pollset_set_add_pollset_set(resolving_lb_policy_->interested_parties(),
|
1518
|
+
interested_parties_);
|
1519
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
1520
|
+
gpr_log(GPR_INFO, "chand=%p: created resolving_lb_policy=%p", this,
|
1521
|
+
resolving_lb_policy_.get());
|
1262
1522
|
}
|
1263
1523
|
}
|
1264
1524
|
|
1265
|
-
ChannelData
|
1266
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
1267
|
-
gpr_log(GPR_INFO, "chand=%p: destroying channel", this);
|
1268
|
-
}
|
1525
|
+
void ChannelData::DestroyResolvingLoadBalancingPolicyLocked() {
|
1269
1526
|
if (resolving_lb_policy_ != nullptr) {
|
1270
1527
|
grpc_pollset_set_del_pollset_set(resolving_lb_policy_->interested_parties(),
|
1271
1528
|
interested_parties_);
|
1272
1529
|
resolving_lb_policy_.reset();
|
1273
1530
|
}
|
1274
|
-
// Stop backup polling.
|
1275
|
-
grpc_client_channel_stop_backup_polling(interested_parties_);
|
1276
|
-
grpc_pollset_set_destroy(interested_parties_);
|
1277
|
-
GRPC_COMBINER_UNREF(data_plane_combiner_, "client_channel");
|
1278
|
-
GRPC_COMBINER_UNREF(combiner_, "client_channel");
|
1279
|
-
GRPC_ERROR_UNREF(disconnect_error_.Load(MemoryOrder::RELAXED));
|
1280
|
-
grpc_connectivity_state_destroy(&state_tracker_);
|
1281
|
-
gpr_mu_destroy(&info_mu_);
|
1282
1531
|
}
|
1283
1532
|
|
1284
1533
|
void ChannelData::ProcessLbPolicy(
|
@@ -1451,9 +1700,13 @@ grpc_error* ChannelData::DoPingLocked(grpc_transport_op* op) {
|
|
1451
1700
|
}
|
1452
1701
|
LoadBalancingPolicy::PickResult result =
|
1453
1702
|
picker_->Pick(LoadBalancingPolicy::PickArgs());
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1703
|
+
ConnectedSubchannel* connected_subchannel = nullptr;
|
1704
|
+
if (result.subchannel != nullptr) {
|
1705
|
+
SubchannelWrapper* subchannel =
|
1706
|
+
static_cast<SubchannelWrapper*>(result.subchannel.get());
|
1707
|
+
connected_subchannel = subchannel->connected_subchannel();
|
1708
|
+
}
|
1709
|
+
if (connected_subchannel != nullptr) {
|
1457
1710
|
connected_subchannel->Ping(op->send_ping.on_initiate, op->send_ping.on_ack);
|
1458
1711
|
} else {
|
1459
1712
|
if (result.error == GRPC_ERROR_NONE) {
|
@@ -1494,22 +1747,35 @@ void ChannelData::StartTransportOpLocked(void* arg, grpc_error* ignored) {
|
|
1494
1747
|
chand->resolving_lb_policy_->ResetBackoffLocked();
|
1495
1748
|
}
|
1496
1749
|
}
|
1497
|
-
// Disconnect.
|
1750
|
+
// Disconnect or enter IDLE.
|
1498
1751
|
if (op->disconnect_with_error != GRPC_ERROR_NONE) {
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1752
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
|
1753
|
+
gpr_log(GPR_INFO, "chand=%p: disconnect_with_error: %s", chand,
|
1754
|
+
grpc_error_string(op->disconnect_with_error));
|
1755
|
+
}
|
1756
|
+
chand->DestroyResolvingLoadBalancingPolicyLocked();
|
1757
|
+
intptr_t value;
|
1758
|
+
if (grpc_error_get_int(op->disconnect_with_error,
|
1759
|
+
GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE, &value) &&
|
1760
|
+
static_cast<grpc_connectivity_state>(value) == GRPC_CHANNEL_IDLE) {
|
1761
|
+
if (chand->disconnect_error() == GRPC_ERROR_NONE) {
|
1762
|
+
// Enter IDLE state.
|
1763
|
+
New<ConnectivityStateAndPickerSetter>(chand, GRPC_CHANNEL_IDLE,
|
1764
|
+
"channel entering IDLE", nullptr);
|
1765
|
+
}
|
1766
|
+
GRPC_ERROR_UNREF(op->disconnect_with_error);
|
1767
|
+
} else {
|
1768
|
+
// Disconnect.
|
1769
|
+
GPR_ASSERT(chand->disconnect_error_.Load(MemoryOrder::RELAXED) ==
|
1770
|
+
GRPC_ERROR_NONE);
|
1771
|
+
chand->disconnect_error_.Store(op->disconnect_with_error,
|
1772
|
+
MemoryOrder::RELEASE);
|
1773
|
+
New<ConnectivityStateAndPickerSetter>(
|
1774
|
+
chand, GRPC_CHANNEL_SHUTDOWN, "shutdown from API",
|
1775
|
+
UniquePtr<LoadBalancingPolicy::SubchannelPicker>(
|
1776
|
+
New<LoadBalancingPolicy::TransientFailurePicker>(
|
1777
|
+
GRPC_ERROR_REF(op->disconnect_with_error))));
|
1778
|
+
}
|
1513
1779
|
}
|
1514
1780
|
GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_, "start_transport_op");
|
1515
1781
|
GRPC_CLOSURE_SCHED(op->on_consumed, GRPC_ERROR_NONE);
|
@@ -1570,10 +1836,23 @@ void ChannelData::RemoveQueuedPick(QueuedPick* to_remove,
|
|
1570
1836
|
}
|
1571
1837
|
}
|
1572
1838
|
|
1839
|
+
RefCountedPtr<ConnectedSubchannel>
|
1840
|
+
ChannelData::GetConnectedSubchannelInDataPlane(
|
1841
|
+
SubchannelInterface* subchannel) const {
|
1842
|
+
SubchannelWrapper* subchannel_wrapper =
|
1843
|
+
static_cast<SubchannelWrapper*>(subchannel);
|
1844
|
+
ConnectedSubchannel* connected_subchannel =
|
1845
|
+
subchannel_wrapper->connected_subchannel_in_data_plane();
|
1846
|
+
if (connected_subchannel == nullptr) return nullptr;
|
1847
|
+
return connected_subchannel->Ref();
|
1848
|
+
}
|
1849
|
+
|
1573
1850
|
void ChannelData::TryToConnectLocked(void* arg, grpc_error* error_ignored) {
|
1574
1851
|
auto* chand = static_cast<ChannelData*>(arg);
|
1575
1852
|
if (chand->resolving_lb_policy_ != nullptr) {
|
1576
1853
|
chand->resolving_lb_policy_->ExitIdleLocked();
|
1854
|
+
} else {
|
1855
|
+
chand->CreateResolvingLoadBalancingPolicyLocked();
|
1577
1856
|
}
|
1578
1857
|
GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_, "TryToConnect");
|
1579
1858
|
}
|
@@ -1879,9 +2158,10 @@ void CallData::RecvTrailingMetadataReadyForLoadBalancingPolicy(
|
|
1879
2158
|
void* arg, grpc_error* error) {
|
1880
2159
|
CallData* calld = static_cast<CallData*>(arg);
|
1881
2160
|
// Invoke callback to LB policy.
|
2161
|
+
Metadata trailing_metadata(calld, calld->recv_trailing_metadata_);
|
1882
2162
|
calld->lb_recv_trailing_metadata_ready_(
|
1883
|
-
calld->lb_recv_trailing_metadata_ready_user_data_,
|
1884
|
-
|
2163
|
+
calld->lb_recv_trailing_metadata_ready_user_data_, &trailing_metadata,
|
2164
|
+
&calld->lb_call_state_);
|
1885
2165
|
// Chain to original callback.
|
1886
2166
|
GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready_,
|
1887
2167
|
GRPC_ERROR_REF(error));
|
@@ -2157,9 +2437,8 @@ void CallData::DoRetry(grpc_call_element* elem,
|
|
2157
2437
|
GPR_ASSERT(method_params_ != nullptr);
|
2158
2438
|
const auto* retry_policy = method_params_->retry_policy();
|
2159
2439
|
GPR_ASSERT(retry_policy != nullptr);
|
2160
|
-
// Reset subchannel call
|
2440
|
+
// Reset subchannel call.
|
2161
2441
|
subchannel_call_.reset();
|
2162
|
-
connected_subchannel_.reset();
|
2163
2442
|
// Compute backoff delay.
|
2164
2443
|
grpc_millis next_attempt_time;
|
2165
2444
|
if (server_pushback_ms >= 0) {
|
@@ -3277,13 +3556,14 @@ void CallData::CreateSubchannelCall(grpc_call_element* elem) {
|
|
3277
3556
|
ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
|
3278
3557
|
const size_t parent_data_size =
|
3279
3558
|
enable_retries_ ? sizeof(SubchannelCallRetryState) : 0;
|
3280
|
-
|
3281
|
-
pollent_, path_, call_start_time_,
|
3559
|
+
SubchannelCall::Args call_args = {
|
3560
|
+
std::move(connected_subchannel_), pollent_, path_, call_start_time_,
|
3561
|
+
deadline_, arena_,
|
3282
3562
|
// TODO(roth): When we implement hedging support, we will probably
|
3283
3563
|
// need to use a separate call context for each subchannel call.
|
3284
3564
|
call_context_, call_combiner_, parent_data_size};
|
3285
3565
|
grpc_error* error = GRPC_ERROR_NONE;
|
3286
|
-
subchannel_call_ =
|
3566
|
+
subchannel_call_ = SubchannelCall::Create(std::move(call_args), &error);
|
3287
3567
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
3288
3568
|
gpr_log(GPR_INFO, "chand=%p calld=%p: create subchannel_call=%p: error=%s",
|
3289
3569
|
chand, this, subchannel_call_.get(), grpc_error_string(error));
|
@@ -3463,6 +3743,15 @@ void CallData::StartPickLocked(void* arg, grpc_error* error) {
|
|
3463
3743
|
ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
|
3464
3744
|
GPR_ASSERT(calld->connected_subchannel_ == nullptr);
|
3465
3745
|
GPR_ASSERT(calld->subchannel_call_ == nullptr);
|
3746
|
+
// picker's being null means the channel is currently in IDLE state. The
|
3747
|
+
// incoming call will make the channel exit IDLE and queue itself.
|
3748
|
+
if (chand->picker() == nullptr) {
|
3749
|
+
// We are currently in the data plane.
|
3750
|
+
// Bounce into the control plane to exit IDLE.
|
3751
|
+
chand->CheckConnectivityState(true);
|
3752
|
+
calld->AddCallToQueuedPicksLocked(elem);
|
3753
|
+
return;
|
3754
|
+
}
|
3466
3755
|
// Apply service config to call if needed.
|
3467
3756
|
calld->MaybeApplyServiceConfigToCallLocked(elem);
|
3468
3757
|
// If this is a retry, use the send_initial_metadata payload that
|
@@ -3477,11 +3766,13 @@ void CallData::StartPickLocked(void* arg, grpc_error* error) {
|
|
3477
3766
|
// attempt) to the LB policy instead the one from the parent channel.
|
3478
3767
|
LoadBalancingPolicy::PickArgs pick_args;
|
3479
3768
|
pick_args.call_state = &calld->lb_call_state_;
|
3480
|
-
|
3769
|
+
Metadata initial_metadata(
|
3770
|
+
calld,
|
3481
3771
|
calld->seen_send_initial_metadata_
|
3482
3772
|
? &calld->send_initial_metadata_
|
3483
3773
|
: calld->pending_batches_[0]
|
3484
|
-
.batch->payload->send_initial_metadata.send_initial_metadata;
|
3774
|
+
.batch->payload->send_initial_metadata.send_initial_metadata);
|
3775
|
+
pick_args.initial_metadata = &initial_metadata;
|
3485
3776
|
// Grab initial metadata flags so that we can check later if the call has
|
3486
3777
|
// wait_for_ready enabled.
|
3487
3778
|
const uint32_t send_initial_metadata_flags =
|
@@ -3497,10 +3788,9 @@ void CallData::StartPickLocked(void* arg, grpc_error* error) {
|
|
3497
3788
|
auto result = chand->picker()->Pick(pick_args);
|
3498
3789
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
|
3499
3790
|
gpr_log(GPR_INFO,
|
3500
|
-
"chand=%p calld=%p: LB pick returned %s (
|
3501
|
-
"error=%s)",
|
3791
|
+
"chand=%p calld=%p: LB pick returned %s (subchannel=%p, error=%s)",
|
3502
3792
|
chand, calld, PickResultTypeName(result.type),
|
3503
|
-
result.
|
3793
|
+
result.subchannel.get(), grpc_error_string(result.error));
|
3504
3794
|
}
|
3505
3795
|
switch (result.type) {
|
3506
3796
|
case LoadBalancingPolicy::PickResult::PICK_TRANSIENT_FAILURE: {
|
@@ -3542,11 +3832,16 @@ void CallData::StartPickLocked(void* arg, grpc_error* error) {
|
|
3542
3832
|
break;
|
3543
3833
|
default: // PICK_COMPLETE
|
3544
3834
|
// Handle drops.
|
3545
|
-
if (GPR_UNLIKELY(result.
|
3835
|
+
if (GPR_UNLIKELY(result.subchannel == nullptr)) {
|
3546
3836
|
result.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
3547
3837
|
"Call dropped by load balancing policy");
|
3838
|
+
} else {
|
3839
|
+
// Grab a ref to the connected subchannel while we're still
|
3840
|
+
// holding the data plane combiner.
|
3841
|
+
calld->connected_subchannel_ =
|
3842
|
+
chand->GetConnectedSubchannelInDataPlane(result.subchannel.get());
|
3843
|
+
GPR_ASSERT(calld->connected_subchannel_ != nullptr);
|
3548
3844
|
}
|
3549
|
-
calld->connected_subchannel_ = std::move(result.connected_subchannel);
|
3550
3845
|
calld->lb_recv_trailing_metadata_ready_ =
|
3551
3846
|
result.recv_trailing_metadata_ready;
|
3552
3847
|
calld->lb_recv_trailing_metadata_ready_user_data_ =
|