grpc 1.1.2 → 1.2.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Makefile +1257 -404
- data/etc/roots.pem +189 -102
- data/include/grpc/census.h +7 -7
- data/include/grpc/compression.h +4 -4
- data/include/grpc/grpc.h +13 -7
- data/include/grpc/impl/codegen/atm_gcc_atomic.h +26 -9
- data/include/grpc/impl/codegen/grpc_types.h +39 -30
- data/include/grpc/impl/codegen/slice.h +24 -6
- data/include/grpc/impl/codegen/sync.h +8 -0
- data/include/grpc/load_reporting.h +63 -0
- data/include/grpc/slice.h +37 -1
- data/include/grpc/slice_buffer.h +7 -0
- data/include/grpc/support/alloc.h +3 -0
- data/include/grpc/support/useful.h +3 -0
- data/src/core/ext/census/gen/census.pb.h +1 -1
- data/src/core/ext/census/gen/trace_context.pb.c +9 -36
- data/src/core/ext/census/gen/trace_context.pb.h +20 -26
- data/src/core/ext/census/grpc_filter.c +3 -5
- data/src/core/ext/census/trace_context.c +1 -1
- data/src/core/ext/census/trace_context.h +3 -0
- data/src/core/ext/census/trace_label.h +61 -0
- data/src/core/ext/census/trace_propagation.h +63 -0
- data/src/core/ext/census/trace_status.h +45 -0
- data/src/core/ext/census/trace_string.h +50 -0
- data/src/core/ext/census/tracing.c +31 -11
- data/src/core/ext/census/tracing.h +124 -0
- data/src/core/ext/client_channel/client_channel.c +456 -368
- data/src/core/ext/client_channel/client_channel.h +4 -0
- data/src/core/ext/client_channel/client_channel_plugin.c +6 -1
- data/src/core/ext/client_channel/connector.c +3 -3
- data/src/core/ext/client_channel/connector.h +4 -3
- data/src/core/ext/client_channel/http_connect_handshaker.c +62 -72
- data/src/core/ext/client_channel/http_connect_handshaker.h +7 -10
- data/src/core/ext/client_channel/http_proxy.c +125 -0
- data/src/core/ext/client_channel/http_proxy.h +39 -0
- data/src/core/ext/client_channel/lb_policy.c +56 -35
- data/src/core/ext/client_channel/lb_policy.h +46 -39
- data/src/core/ext/client_channel/lb_policy_factory.h +1 -0
- data/src/core/ext/client_channel/parse_address.c +32 -6
- data/src/core/ext/client_channel/proxy_mapper.c +63 -0
- data/src/core/ext/client_channel/proxy_mapper.h +89 -0
- data/src/core/ext/client_channel/proxy_mapper_registry.c +133 -0
- data/src/core/ext/client_channel/proxy_mapper_registry.h +59 -0
- data/src/core/ext/client_channel/resolver.c +16 -9
- data/src/core/ext/client_channel/resolver.h +23 -12
- data/src/core/ext/client_channel/resolver_factory.h +1 -0
- data/src/core/ext/client_channel/resolver_registry.c +15 -11
- data/src/core/ext/client_channel/resolver_registry.h +5 -3
- data/src/core/ext/client_channel/subchannel.c +44 -27
- data/src/core/ext/client_channel/subchannel.h +6 -2
- data/src/core/ext/client_channel/uri_parser.c +26 -14
- data/src/core/ext/client_channel/uri_parser.h +3 -1
- data/src/core/ext/lb_policy/grpclb/grpclb.c +220 -209
- data/src/core/ext/lb_policy/grpclb/grpclb_channel.h +56 -0
- data/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c +107 -0
- data/src/core/ext/lb_policy/grpclb/load_balancer_api.c +3 -6
- data/src/core/ext/lb_policy/pick_first/pick_first.c +71 -116
- data/src/core/ext/lb_policy/round_robin/round_robin.c +52 -67
- data/src/core/ext/load_reporting/load_reporting.c +20 -0
- data/src/core/ext/load_reporting/load_reporting.h +1 -16
- data/src/core/ext/load_reporting/load_reporting_filter.c +28 -54
- data/src/core/ext/resolver/dns/native/dns_resolver.c +31 -45
- data/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +20 -29
- data/src/core/ext/transport/chttp2/client/chttp2_connector.c +11 -8
- data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +11 -2
- data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +143 -46
- data/src/core/ext/transport/chttp2/server/chttp2_server.c +12 -50
- data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +1 -1
- data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +1 -1
- data/src/core/ext/transport/chttp2/transport/bin_decoder.c +7 -7
- data/src/core/ext/transport/chttp2/transport/bin_encoder.c +1 -2
- data/src/core/ext/transport/chttp2/transport/bin_encoder.h +1 -2
- data/src/core/ext/transport/chttp2/transport/chttp2_plugin.c +0 -3
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +606 -374
- data/src/core/ext/transport/chttp2/transport/frame_ping.c +17 -5
- data/src/core/ext/transport/chttp2/transport/frame_ping.h +2 -2
- data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +9 -13
- data/src/core/ext/transport/chttp2/transport/frame_settings.c +12 -11
- data/src/core/ext/transport/chttp2/transport/frame_settings.h +1 -1
- data/src/core/ext/transport/chttp2/transport/frame_window_update.c +5 -6
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +100 -53
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +2 -2
- data/src/core/ext/transport/chttp2/transport/hpack_parser.c +126 -70
- data/src/core/ext/transport/chttp2/transport/hpack_parser.h +13 -7
- data/src/core/ext/transport/chttp2/transport/hpack_table.c +22 -19
- data/src/core/ext/transport/chttp2/transport/hpack_table.h +6 -6
- data/src/core/ext/transport/chttp2/transport/incoming_metadata.c +23 -11
- data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +6 -2
- data/src/core/ext/transport/chttp2/transport/internal.h +169 -42
- data/src/core/ext/transport/chttp2/transport/parsing.c +98 -41
- data/src/core/ext/transport/chttp2/transport/stream_lists.c +29 -14
- data/src/core/ext/transport/chttp2/transport/writing.c +137 -15
- data/src/core/lib/channel/channel_stack.c +14 -44
- data/src/core/lib/channel/channel_stack.h +10 -17
- data/src/core/lib/channel/channel_stack_builder.c +2 -3
- data/src/core/lib/channel/compress_filter.c +54 -46
- data/src/core/lib/channel/connected_channel.c +4 -4
- data/src/core/lib/channel/connected_channel.h +5 -0
- data/src/core/lib/channel/context.h +3 -0
- data/src/core/lib/channel/deadline_filter.c +61 -61
- data/src/core/lib/channel/deadline_filter.h +8 -5
- data/src/core/lib/channel/handshaker.c +47 -7
- data/src/core/lib/channel/handshaker.h +21 -3
- data/src/core/lib/channel/http_client_filter.c +149 -99
- data/src/core/lib/channel/http_server_filter.c +163 -147
- data/src/core/lib/channel/message_size_filter.c +15 -10
- data/src/core/lib/compression/algorithm_metadata.h +4 -4
- data/src/core/lib/compression/compression.c +17 -23
- data/src/core/lib/http/httpcli.c +3 -2
- data/src/core/lib/http/httpcli.h +2 -1
- data/src/core/lib/http/httpcli_security_connector.c +2 -3
- data/src/core/lib/http/parser.c +2 -2
- data/src/core/lib/iomgr/closure.c +6 -3
- data/src/core/lib/iomgr/closure.h +4 -2
- data/src/core/lib/iomgr/combiner.c +35 -5
- data/src/core/lib/iomgr/combiner.h +21 -2
- data/src/core/lib/iomgr/endpoint.c +3 -2
- data/src/core/lib/iomgr/endpoint.h +3 -2
- data/src/core/lib/iomgr/error.c +60 -94
- data/src/core/lib/iomgr/error.h +7 -10
- data/src/core/lib/iomgr/error_internal.h +54 -0
- data/src/core/lib/iomgr/ev_epoll_linux.c +253 -109
- data/src/core/lib/iomgr/ev_poll_posix.c +61 -29
- data/src/core/lib/iomgr/ev_posix.c +7 -8
- data/src/core/lib/iomgr/ev_posix.h +4 -4
- data/src/core/lib/iomgr/exec_ctx.c +11 -6
- data/src/core/lib/iomgr/exec_ctx.h +11 -14
- data/src/core/lib/iomgr/executor.c +2 -2
- data/src/core/lib/iomgr/load_file.c +1 -1
- data/src/core/lib/iomgr/network_status_tracker.c +5 -81
- data/src/core/lib/iomgr/pollset.h +1 -3
- data/src/core/lib/iomgr/pollset_set.h +2 -1
- data/src/core/lib/iomgr/pollset_set_uv.c +2 -1
- data/src/core/lib/iomgr/pollset_set_windows.c +2 -1
- data/src/core/lib/iomgr/pollset_uv.c +25 -11
- data/src/core/lib/iomgr/pollset_windows.c +0 -11
- data/src/core/lib/iomgr/resolve_address_uv.c +50 -2
- data/src/core/lib/iomgr/resource_quota.c +41 -11
- data/src/core/lib/iomgr/resource_quota.h +6 -0
- data/src/core/lib/iomgr/sockaddr_utils.c +33 -17
- data/src/core/lib/iomgr/sockaddr_utils.h +4 -0
- data/src/core/lib/iomgr/tcp_client_posix.c +2 -3
- data/src/core/lib/iomgr/tcp_client_uv.c +1 -3
- data/src/core/lib/iomgr/tcp_client_windows.c +21 -6
- data/src/core/lib/iomgr/tcp_posix.c +4 -5
- data/src/core/lib/iomgr/tcp_server_posix.c +269 -94
- data/src/core/lib/iomgr/tcp_server_windows.c +1 -1
- data/src/core/lib/iomgr/tcp_uv.c +11 -5
- data/src/core/lib/iomgr/tcp_windows.c +20 -7
- data/src/core/lib/iomgr/timer_generic.c +15 -22
- data/src/core/lib/iomgr/timer_generic.h +1 -1
- data/src/core/lib/iomgr/timer_uv.c +10 -6
- data/src/core/lib/iomgr/timer_uv.h +1 -1
- data/src/core/lib/iomgr/udp_server.c +45 -6
- data/src/core/lib/iomgr/udp_server.h +7 -1
- data/src/core/lib/iomgr/unix_sockets_posix.c +11 -1
- data/src/core/lib/json/json.c +1 -2
- data/src/core/lib/profiling/basic_timers.c +17 -3
- data/src/core/lib/security/context/security_context.c +3 -10
- data/src/core/lib/security/credentials/composite/composite_credentials.c +4 -8
- data/src/core/lib/security/credentials/credentials.c +48 -2
- data/src/core/lib/security/credentials/credentials.h +13 -0
- data/src/core/lib/security/credentials/credentials_metadata.c +1 -2
- data/src/core/lib/security/credentials/fake/fake_credentials.c +6 -8
- data/src/core/lib/security/credentials/fake/fake_credentials.h +15 -0
- data/src/core/lib/security/credentials/google_default/google_default_credentials.c +3 -3
- data/src/core/lib/security/credentials/iam/iam_credentials.c +1 -2
- data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -2
- data/src/core/lib/security/credentials/jwt/jwt_verifier.c +5 -8
- data/src/core/lib/security/credentials/jwt/jwt_verifier.h +2 -1
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +3 -5
- data/src/core/lib/security/credentials/plugin/plugin_credentials.c +15 -13
- data/src/core/lib/security/credentials/ssl/ssl_credentials.c +2 -4
- data/src/core/lib/security/transport/client_auth_filter.c +72 -47
- data/src/core/lib/security/transport/lb_targets_info.c +70 -0
- data/src/core/lib/security/transport/lb_targets_info.h +47 -0
- data/src/core/lib/security/transport/secure_endpoint.c +3 -3
- data/src/core/lib/security/transport/security_connector.c +125 -28
- data/src/core/lib/security/transport/security_connector.h +4 -3
- data/src/core/lib/security/transport/security_handshaker.c +13 -9
- data/src/core/lib/security/transport/server_auth_filter.c +31 -40
- data/src/core/lib/security/util/b64.c +1 -1
- data/src/core/lib/slice/slice.c +110 -20
- data/src/core/lib/slice/slice_buffer.c +92 -39
- data/src/core/lib/{transport/mdstr_hash_table.c → slice/slice_hash_table.c} +40 -33
- data/src/core/lib/{transport/mdstr_hash_table.h → slice/slice_hash_table.h} +21 -21
- data/src/core/lib/slice/slice_intern.c +346 -0
- data/src/core/lib/slice/slice_internal.h +15 -0
- data/src/core/lib/slice/slice_string_helpers.c +5 -0
- data/src/core/lib/slice/slice_string_helpers.h +5 -0
- data/src/core/lib/support/alloc.c +26 -1
- data/src/core/lib/support/cmdline.c +2 -4
- data/src/core/lib/support/cpu_posix.c +2 -7
- data/src/core/lib/support/histogram.c +1 -2
- data/src/core/lib/support/log_posix.c +8 -4
- data/src/core/lib/support/spinlock.h +52 -0
- data/src/core/lib/support/subprocess_posix.c +1 -2
- data/src/core/lib/support/sync.c +7 -1
- data/src/core/lib/support/sync_posix.c +9 -0
- data/src/core/lib/support/time_windows.c +7 -1
- data/src/core/lib/surface/call.c +647 -629
- data/src/core/lib/surface/call.h +4 -1
- data/src/core/lib/surface/call_details.c +8 -2
- data/src/core/lib/surface/call_log_batch.c +17 -6
- data/src/core/lib/surface/channel.c +49 -59
- data/src/core/lib/surface/channel.h +5 -6
- data/src/core/lib/surface/completion_queue.c +16 -45
- data/src/core/lib/surface/completion_queue.h +0 -3
- data/src/core/lib/surface/init.c +6 -2
- data/src/core/lib/surface/init_secure.c +1 -1
- data/src/core/lib/surface/lame_client.c +14 -4
- data/src/core/lib/surface/server.c +79 -82
- data/src/core/lib/surface/validate_metadata.c +46 -15
- data/src/core/lib/surface/validate_metadata.h +43 -0
- data/src/core/lib/surface/version.c +2 -2
- data/src/core/lib/transport/bdp_estimator.c +104 -0
- data/src/core/lib/transport/bdp_estimator.h +76 -0
- data/src/core/lib/transport/connectivity_state.c +33 -13
- data/src/core/lib/transport/connectivity_state.h +15 -5
- data/src/core/lib/transport/error_utils.c +124 -0
- data/src/core/lib/transport/error_utils.h +56 -0
- data/src/core/{ext/transport/chttp2 → lib}/transport/http2_errors.h +18 -18
- data/src/core/lib/transport/metadata.c +259 -503
- data/src/core/lib/transport/metadata.h +69 -68
- data/src/core/lib/transport/metadata_batch.c +183 -63
- data/src/core/lib/transport/metadata_batch.h +50 -26
- data/src/core/lib/transport/pid_controller.c +28 -8
- data/src/core/lib/transport/pid_controller.h +15 -2
- data/src/core/lib/transport/service_config.c +21 -18
- data/src/core/lib/transport/service_config.h +5 -5
- data/src/core/lib/transport/static_metadata.c +753 -112
- data/src/core/lib/transport/static_metadata.h +403 -264
- data/src/core/{ext/transport/chttp2 → lib}/transport/status_conversion.c +18 -20
- data/src/core/{ext/transport/chttp2 → lib}/transport/status_conversion.h +9 -10
- data/src/core/lib/transport/timeout_encoding.c +11 -9
- data/src/core/lib/transport/timeout_encoding.h +3 -1
- data/src/core/lib/transport/transport.c +47 -87
- data/src/core/lib/transport/transport.h +20 -25
- data/src/core/lib/transport/transport_op_string.c +7 -19
- data/src/core/lib/tsi/fake_transport_security.c +2 -4
- data/src/core/lib/tsi/ssl_transport_security.c +7 -16
- data/src/core/lib/tsi/transport_security.c +2 -4
- data/src/ruby/ext/grpc/extconf.rb +4 -1
- data/src/ruby/ext/grpc/rb_byte_buffer.c +7 -0
- data/src/ruby/ext/grpc/rb_byte_buffer.h +3 -0
- data/src/ruby/ext/grpc/rb_call.c +47 -46
- data/src/ruby/ext/grpc/rb_channel.c +21 -6
- data/src/ruby/ext/grpc/rb_compression_options.c +9 -6
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +36 -2
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +59 -8
- data/src/ruby/ext/grpc/rb_server.c +6 -4
- data/src/ruby/lib/grpc/generic/client_stub.rb +1 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- metadata +33 -9
|
@@ -43,15 +43,19 @@
|
|
|
43
43
|
#include <grpc/support/sync.h>
|
|
44
44
|
#include <grpc/support/useful.h>
|
|
45
45
|
|
|
46
|
+
#include "src/core/ext/client_channel/http_connect_handshaker.h"
|
|
46
47
|
#include "src/core/ext/client_channel/lb_policy_registry.h"
|
|
48
|
+
#include "src/core/ext/client_channel/proxy_mapper_registry.h"
|
|
47
49
|
#include "src/core/ext/client_channel/resolver_registry.h"
|
|
48
50
|
#include "src/core/ext/client_channel/subchannel.h"
|
|
49
51
|
#include "src/core/lib/channel/channel_args.h"
|
|
50
52
|
#include "src/core/lib/channel/connected_channel.h"
|
|
51
53
|
#include "src/core/lib/channel/deadline_filter.h"
|
|
54
|
+
#include "src/core/lib/iomgr/combiner.h"
|
|
52
55
|
#include "src/core/lib/iomgr/iomgr.h"
|
|
53
56
|
#include "src/core/lib/iomgr/polling_entity.h"
|
|
54
57
|
#include "src/core/lib/profiling/timers.h"
|
|
58
|
+
#include "src/core/lib/slice/slice_internal.h"
|
|
55
59
|
#include "src/core/lib/support/string.h"
|
|
56
60
|
#include "src/core/lib/surface/channel.h"
|
|
57
61
|
#include "src/core/lib/transport/connectivity_state.h"
|
|
@@ -72,24 +76,82 @@ typedef enum {
|
|
|
72
76
|
WAIT_FOR_READY_TRUE
|
|
73
77
|
} wait_for_ready_value;
|
|
74
78
|
|
|
75
|
-
typedef struct
|
|
79
|
+
typedef struct {
|
|
80
|
+
gpr_refcount refs;
|
|
76
81
|
gpr_timespec timeout;
|
|
77
82
|
wait_for_ready_value wait_for_ready;
|
|
78
83
|
} method_parameters;
|
|
79
84
|
|
|
85
|
+
static method_parameters *method_parameters_ref(
|
|
86
|
+
method_parameters *method_params) {
|
|
87
|
+
gpr_ref(&method_params->refs);
|
|
88
|
+
return method_params;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static void method_parameters_unref(method_parameters *method_params) {
|
|
92
|
+
if (gpr_unref(&method_params->refs)) {
|
|
93
|
+
gpr_free(method_params);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
80
97
|
static void *method_parameters_copy(void *value) {
|
|
81
|
-
|
|
82
|
-
memcpy(new_value, value, sizeof(method_parameters));
|
|
83
|
-
return new_value;
|
|
98
|
+
return method_parameters_ref(value);
|
|
84
99
|
}
|
|
85
100
|
|
|
86
|
-
static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *
|
|
87
|
-
|
|
101
|
+
static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *value) {
|
|
102
|
+
method_parameters_unref(value);
|
|
88
103
|
}
|
|
89
104
|
|
|
90
|
-
static const
|
|
105
|
+
static const grpc_slice_hash_table_vtable method_parameters_vtable = {
|
|
91
106
|
method_parameters_free, method_parameters_copy};
|
|
92
107
|
|
|
108
|
+
static bool parse_wait_for_ready(grpc_json *field,
|
|
109
|
+
wait_for_ready_value *wait_for_ready) {
|
|
110
|
+
if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
*wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
|
|
114
|
+
: WAIT_FOR_READY_FALSE;
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static bool parse_timeout(grpc_json *field, gpr_timespec *timeout) {
|
|
119
|
+
if (field->type != GRPC_JSON_STRING) return false;
|
|
120
|
+
size_t len = strlen(field->value);
|
|
121
|
+
if (field->value[len - 1] != 's') return false;
|
|
122
|
+
char *buf = gpr_strdup(field->value);
|
|
123
|
+
buf[len - 1] = '\0'; // Remove trailing 's'.
|
|
124
|
+
char *decimal_point = strchr(buf, '.');
|
|
125
|
+
if (decimal_point != NULL) {
|
|
126
|
+
*decimal_point = '\0';
|
|
127
|
+
timeout->tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
|
|
128
|
+
if (timeout->tv_nsec == -1) {
|
|
129
|
+
gpr_free(buf);
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
// There should always be exactly 3, 6, or 9 fractional digits.
|
|
133
|
+
int multiplier = 1;
|
|
134
|
+
switch (strlen(decimal_point + 1)) {
|
|
135
|
+
case 9:
|
|
136
|
+
break;
|
|
137
|
+
case 6:
|
|
138
|
+
multiplier *= 1000;
|
|
139
|
+
break;
|
|
140
|
+
case 3:
|
|
141
|
+
multiplier *= 1000000;
|
|
142
|
+
break;
|
|
143
|
+
default: // Unsupported number of digits.
|
|
144
|
+
gpr_free(buf);
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
timeout->tv_nsec *= multiplier;
|
|
148
|
+
}
|
|
149
|
+
timeout->tv_sec = gpr_parse_nonnegative_int(buf);
|
|
150
|
+
gpr_free(buf);
|
|
151
|
+
if (timeout->tv_sec == -1) return false;
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
|
|
93
155
|
static void *method_parameters_create_from_json(const grpc_json *json) {
|
|
94
156
|
wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
|
|
95
157
|
gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
|
|
@@ -97,49 +159,14 @@ static void *method_parameters_create_from_json(const grpc_json *json) {
|
|
|
97
159
|
if (field->key == NULL) continue;
|
|
98
160
|
if (strcmp(field->key, "waitForReady") == 0) {
|
|
99
161
|
if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
|
|
100
|
-
if (field
|
|
101
|
-
return NULL;
|
|
102
|
-
}
|
|
103
|
-
wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
|
|
104
|
-
: WAIT_FOR_READY_FALSE;
|
|
162
|
+
if (!parse_wait_for_ready(field, &wait_for_ready)) return NULL;
|
|
105
163
|
} else if (strcmp(field->key, "timeout") == 0) {
|
|
106
164
|
if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
|
|
107
|
-
if (field
|
|
108
|
-
size_t len = strlen(field->value);
|
|
109
|
-
if (field->value[len - 1] != 's') return NULL;
|
|
110
|
-
char *buf = gpr_strdup(field->value);
|
|
111
|
-
buf[len - 1] = '\0'; // Remove trailing 's'.
|
|
112
|
-
char *decimal_point = strchr(buf, '.');
|
|
113
|
-
if (decimal_point != NULL) {
|
|
114
|
-
*decimal_point = '\0';
|
|
115
|
-
timeout.tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
|
|
116
|
-
if (timeout.tv_nsec == -1) {
|
|
117
|
-
gpr_free(buf);
|
|
118
|
-
return NULL;
|
|
119
|
-
}
|
|
120
|
-
// There should always be exactly 3, 6, or 9 fractional digits.
|
|
121
|
-
int multiplier = 1;
|
|
122
|
-
switch (strlen(decimal_point + 1)) {
|
|
123
|
-
case 9:
|
|
124
|
-
break;
|
|
125
|
-
case 6:
|
|
126
|
-
multiplier *= 1000;
|
|
127
|
-
break;
|
|
128
|
-
case 3:
|
|
129
|
-
multiplier *= 1000000;
|
|
130
|
-
break;
|
|
131
|
-
default: // Unsupported number of digits.
|
|
132
|
-
gpr_free(buf);
|
|
133
|
-
return NULL;
|
|
134
|
-
}
|
|
135
|
-
timeout.tv_nsec *= multiplier;
|
|
136
|
-
}
|
|
137
|
-
timeout.tv_sec = gpr_parse_nonnegative_int(buf);
|
|
138
|
-
if (timeout.tv_sec == -1) return NULL;
|
|
139
|
-
gpr_free(buf);
|
|
165
|
+
if (!parse_timeout(field, &timeout)) return NULL;
|
|
140
166
|
}
|
|
141
167
|
}
|
|
142
168
|
method_parameters *value = gpr_malloc(sizeof(method_parameters));
|
|
169
|
+
gpr_ref_init(&value->refs, 1);
|
|
143
170
|
value->timeout = timeout;
|
|
144
171
|
value->wait_for_ready = wait_for_ready;
|
|
145
172
|
return value;
|
|
@@ -157,15 +184,12 @@ typedef struct client_channel_channel_data {
|
|
|
157
184
|
/** client channel factory */
|
|
158
185
|
grpc_client_channel_factory *client_channel_factory;
|
|
159
186
|
|
|
160
|
-
/**
|
|
161
|
-
|
|
187
|
+
/** combiner protecting all variables below in this data structure */
|
|
188
|
+
grpc_combiner *combiner;
|
|
162
189
|
/** currently active load balancer */
|
|
163
|
-
char *lb_policy_name;
|
|
164
190
|
grpc_lb_policy *lb_policy;
|
|
165
|
-
/** service config in JSON form */
|
|
166
|
-
char *service_config_json;
|
|
167
191
|
/** maps method names to method_parameters structs */
|
|
168
|
-
|
|
192
|
+
grpc_slice_hash_table *method_params_table;
|
|
169
193
|
/** incoming resolver result - set by resolver.next() */
|
|
170
194
|
grpc_channel_args *resolver_result;
|
|
171
195
|
/** a list of closures that are all waiting for config to come in */
|
|
@@ -180,6 +204,13 @@ typedef struct client_channel_channel_data {
|
|
|
180
204
|
grpc_channel_stack *owning_stack;
|
|
181
205
|
/** interested parties (owned) */
|
|
182
206
|
grpc_pollset_set *interested_parties;
|
|
207
|
+
|
|
208
|
+
/* the following properties are guarded by a mutex since API's require them
|
|
209
|
+
to be instantaneously available */
|
|
210
|
+
gpr_mu info_mu;
|
|
211
|
+
char *info_lb_policy_name;
|
|
212
|
+
/** service config in JSON form */
|
|
213
|
+
char *info_service_config_json;
|
|
183
214
|
} channel_data;
|
|
184
215
|
|
|
185
216
|
/** We create one watcher for each new lb_policy that is returned from a
|
|
@@ -192,9 +223,9 @@ typedef struct {
|
|
|
192
223
|
grpc_lb_policy *lb_policy;
|
|
193
224
|
} lb_policy_connectivity_watcher;
|
|
194
225
|
|
|
195
|
-
static void
|
|
196
|
-
|
|
197
|
-
|
|
226
|
+
static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
|
|
227
|
+
grpc_lb_policy *lb_policy,
|
|
228
|
+
grpc_connectivity_state current_state);
|
|
198
229
|
|
|
199
230
|
static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
|
|
200
231
|
channel_data *chand,
|
|
@@ -205,7 +236,7 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
|
|
|
205
236
|
state == GRPC_CHANNEL_SHUTDOWN) &&
|
|
206
237
|
chand->lb_policy != NULL) {
|
|
207
238
|
/* cancel picks with wait_for_ready=false */
|
|
208
|
-
|
|
239
|
+
grpc_lb_policy_cancel_picks_locked(
|
|
209
240
|
exec_ctx, chand->lb_policy,
|
|
210
241
|
/* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
|
|
211
242
|
/* check= */ 0, GRPC_ERROR_REF(error));
|
|
@@ -215,59 +246,50 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
|
|
|
215
246
|
}
|
|
216
247
|
|
|
217
248
|
static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
|
|
218
|
-
|
|
219
|
-
|
|
249
|
+
void *arg, grpc_error *error) {
|
|
250
|
+
lb_policy_connectivity_watcher *w = arg;
|
|
220
251
|
grpc_connectivity_state publish_state = w->state;
|
|
221
|
-
/* check if the notification is for
|
|
222
|
-
if (w->lb_policy
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
252
|
+
/* check if the notification is for the latest policy */
|
|
253
|
+
if (w->lb_policy == w->chand->lb_policy) {
|
|
254
|
+
if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
|
|
255
|
+
publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
|
|
256
|
+
grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
|
|
257
|
+
GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
|
|
258
|
+
w->chand->lb_policy = NULL;
|
|
259
|
+
}
|
|
260
|
+
set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
|
|
261
|
+
GRPC_ERROR_REF(error), "lb_changed");
|
|
262
|
+
if (w->state != GRPC_CHANNEL_SHUTDOWN) {
|
|
263
|
+
watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
|
|
264
|
+
}
|
|
234
265
|
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|
238
|
-
grpc_error *error) {
|
|
239
|
-
lb_policy_connectivity_watcher *w = arg;
|
|
240
|
-
|
|
241
|
-
gpr_mu_lock(&w->chand->mu);
|
|
242
|
-
on_lb_policy_state_changed_locked(exec_ctx, w, error);
|
|
243
|
-
gpr_mu_unlock(&w->chand->mu);
|
|
244
266
|
|
|
245
267
|
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
|
|
246
268
|
gpr_free(w);
|
|
247
269
|
}
|
|
248
270
|
|
|
249
|
-
static void
|
|
250
|
-
|
|
251
|
-
|
|
271
|
+
static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
|
|
272
|
+
grpc_lb_policy *lb_policy,
|
|
273
|
+
grpc_connectivity_state current_state) {
|
|
252
274
|
lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
|
|
253
275
|
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
|
|
254
276
|
|
|
255
277
|
w->chand = chand;
|
|
256
|
-
grpc_closure_init(&w->on_changed,
|
|
257
|
-
|
|
278
|
+
grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
|
|
279
|
+
grpc_combiner_scheduler(chand->combiner, false));
|
|
258
280
|
w->state = current_state;
|
|
259
281
|
w->lb_policy = lb_policy;
|
|
260
|
-
|
|
261
|
-
|
|
282
|
+
grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
|
|
283
|
+
&w->on_changed);
|
|
262
284
|
}
|
|
263
285
|
|
|
264
|
-
static void
|
|
265
|
-
|
|
286
|
+
static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
|
|
287
|
+
void *arg, grpc_error *error) {
|
|
266
288
|
channel_data *chand = arg;
|
|
267
289
|
char *lb_policy_name = NULL;
|
|
268
290
|
grpc_lb_policy *lb_policy = NULL;
|
|
269
291
|
grpc_lb_policy *old_lb_policy;
|
|
270
|
-
|
|
292
|
+
grpc_slice_hash_table *method_params_table = NULL;
|
|
271
293
|
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
|
|
272
294
|
bool exit_idle = false;
|
|
273
295
|
grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
|
|
@@ -314,13 +336,14 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|
|
314
336
|
grpc_lb_policy_args lb_policy_args;
|
|
315
337
|
lb_policy_args.args = chand->resolver_result;
|
|
316
338
|
lb_policy_args.client_channel_factory = chand->client_channel_factory;
|
|
339
|
+
lb_policy_args.combiner = chand->combiner;
|
|
317
340
|
lb_policy =
|
|
318
341
|
grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
|
|
319
342
|
if (lb_policy != NULL) {
|
|
320
343
|
GRPC_LB_POLICY_REF(lb_policy, "config_change");
|
|
321
344
|
GRPC_ERROR_UNREF(state_error);
|
|
322
|
-
state =
|
|
323
|
-
|
|
345
|
+
state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
|
|
346
|
+
&state_error);
|
|
324
347
|
}
|
|
325
348
|
// Find service config.
|
|
326
349
|
channel_arg =
|
|
@@ -350,19 +373,20 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|
|
350
373
|
chand->interested_parties);
|
|
351
374
|
}
|
|
352
375
|
|
|
353
|
-
gpr_mu_lock(&chand->
|
|
376
|
+
gpr_mu_lock(&chand->info_mu);
|
|
354
377
|
if (lb_policy_name != NULL) {
|
|
355
|
-
gpr_free(chand->
|
|
356
|
-
chand->
|
|
378
|
+
gpr_free(chand->info_lb_policy_name);
|
|
379
|
+
chand->info_lb_policy_name = lb_policy_name;
|
|
357
380
|
}
|
|
358
381
|
old_lb_policy = chand->lb_policy;
|
|
359
382
|
chand->lb_policy = lb_policy;
|
|
360
383
|
if (service_config_json != NULL) {
|
|
361
|
-
gpr_free(chand->
|
|
362
|
-
chand->
|
|
384
|
+
gpr_free(chand->info_service_config_json);
|
|
385
|
+
chand->info_service_config_json = service_config_json;
|
|
363
386
|
}
|
|
387
|
+
gpr_mu_unlock(&chand->info_mu);
|
|
364
388
|
if (chand->method_params_table != NULL) {
|
|
365
|
-
|
|
389
|
+
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
|
|
366
390
|
}
|
|
367
391
|
chand->method_params_table = method_params_table;
|
|
368
392
|
if (lb_policy != NULL) {
|
|
@@ -383,15 +407,15 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|
|
383
407
|
set_channel_connectivity_state_locked(
|
|
384
408
|
exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
|
|
385
409
|
if (lb_policy != NULL) {
|
|
386
|
-
|
|
410
|
+
watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
|
|
387
411
|
}
|
|
388
412
|
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
413
|
+
grpc_resolver_next_locked(exec_ctx, chand->resolver,
|
|
414
|
+
&chand->resolver_result,
|
|
415
|
+
&chand->on_resolver_result_changed);
|
|
392
416
|
} else {
|
|
393
417
|
if (chand->resolver != NULL) {
|
|
394
|
-
|
|
418
|
+
grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
|
|
395
419
|
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
|
|
396
420
|
chand->resolver = NULL;
|
|
397
421
|
}
|
|
@@ -401,11 +425,10 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|
|
401
425
|
GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
|
|
402
426
|
GPR_ARRAY_SIZE(refs)),
|
|
403
427
|
"resolver_gone");
|
|
404
|
-
gpr_mu_unlock(&chand->mu);
|
|
405
428
|
}
|
|
406
429
|
|
|
407
430
|
if (exit_idle) {
|
|
408
|
-
|
|
431
|
+
grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
|
|
409
432
|
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
|
|
410
433
|
}
|
|
411
434
|
|
|
@@ -423,20 +446,12 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|
|
423
446
|
GRPC_ERROR_UNREF(state_error);
|
|
424
447
|
}
|
|
425
448
|
|
|
426
|
-
static void
|
|
427
|
-
|
|
428
|
-
|
|
449
|
+
static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
|
|
450
|
+
grpc_error *error_ignored) {
|
|
451
|
+
grpc_transport_op *op = arg;
|
|
452
|
+
grpc_channel_element *elem = op->transport_private.args[0];
|
|
429
453
|
channel_data *chand = elem->channel_data;
|
|
430
454
|
|
|
431
|
-
grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
|
|
432
|
-
|
|
433
|
-
GPR_ASSERT(op->set_accept_stream == false);
|
|
434
|
-
if (op->bind_pollset != NULL) {
|
|
435
|
-
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
|
|
436
|
-
op->bind_pollset);
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
gpr_mu_lock(&chand->mu);
|
|
440
455
|
if (op->on_connectivity_state_change != NULL) {
|
|
441
456
|
grpc_connectivity_state_notify_on_state_change(
|
|
442
457
|
exec_ctx, &chand->state_tracker, op->connectivity_state,
|
|
@@ -450,7 +465,7 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|
|
450
465
|
grpc_closure_sched(exec_ctx, op->send_ping,
|
|
451
466
|
GRPC_ERROR_CREATE("Ping with no load balancing"));
|
|
452
467
|
} else {
|
|
453
|
-
|
|
468
|
+
grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
|
|
454
469
|
op->bind_pollset = NULL;
|
|
455
470
|
}
|
|
456
471
|
op->send_ping = NULL;
|
|
@@ -461,7 +476,7 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|
|
461
476
|
set_channel_connectivity_state_locked(
|
|
462
477
|
exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
|
|
463
478
|
GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
|
|
464
|
-
|
|
479
|
+
grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
|
|
465
480
|
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
|
|
466
481
|
chand->resolver = NULL;
|
|
467
482
|
if (!chand->started_resolving) {
|
|
@@ -479,25 +494,48 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|
|
479
494
|
}
|
|
480
495
|
GRPC_ERROR_UNREF(op->disconnect_with_error);
|
|
481
496
|
}
|
|
482
|
-
|
|
497
|
+
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
|
|
498
|
+
|
|
499
|
+
grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|
503
|
+
grpc_channel_element *elem,
|
|
504
|
+
grpc_transport_op *op) {
|
|
505
|
+
channel_data *chand = elem->channel_data;
|
|
506
|
+
|
|
507
|
+
GPR_ASSERT(op->set_accept_stream == false);
|
|
508
|
+
if (op->bind_pollset != NULL) {
|
|
509
|
+
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
|
|
510
|
+
op->bind_pollset);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
op->transport_private.args[0] = elem;
|
|
514
|
+
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
|
|
515
|
+
grpc_closure_sched(
|
|
516
|
+
exec_ctx, grpc_closure_init(
|
|
517
|
+
&op->transport_private.closure, start_transport_op_locked,
|
|
518
|
+
op, grpc_combiner_scheduler(chand->combiner, false)),
|
|
519
|
+
GRPC_ERROR_NONE);
|
|
483
520
|
}
|
|
484
521
|
|
|
485
522
|
static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
|
|
486
523
|
grpc_channel_element *elem,
|
|
487
524
|
const grpc_channel_info *info) {
|
|
488
525
|
channel_data *chand = elem->channel_data;
|
|
489
|
-
gpr_mu_lock(&chand->
|
|
526
|
+
gpr_mu_lock(&chand->info_mu);
|
|
490
527
|
if (info->lb_policy_name != NULL) {
|
|
491
|
-
*info->lb_policy_name = chand->
|
|
528
|
+
*info->lb_policy_name = chand->info_lb_policy_name == NULL
|
|
492
529
|
? NULL
|
|
493
|
-
: gpr_strdup(chand->
|
|
530
|
+
: gpr_strdup(chand->info_lb_policy_name);
|
|
494
531
|
}
|
|
495
532
|
if (info->service_config_json != NULL) {
|
|
496
|
-
*info->service_config_json =
|
|
497
|
-
|
|
498
|
-
|
|
533
|
+
*info->service_config_json =
|
|
534
|
+
chand->info_service_config_json == NULL
|
|
535
|
+
? NULL
|
|
536
|
+
: gpr_strdup(chand->info_service_config_json);
|
|
499
537
|
}
|
|
500
|
-
gpr_mu_unlock(&chand->
|
|
538
|
+
gpr_mu_unlock(&chand->info_mu);
|
|
501
539
|
}
|
|
502
540
|
|
|
503
541
|
/* Constructor for channel_data */
|
|
@@ -505,15 +543,15 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
|
|
|
505
543
|
grpc_channel_element *elem,
|
|
506
544
|
grpc_channel_element_args *args) {
|
|
507
545
|
channel_data *chand = elem->channel_data;
|
|
508
|
-
memset(chand, 0, sizeof(*chand));
|
|
509
546
|
GPR_ASSERT(args->is_last);
|
|
510
547
|
GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
|
|
511
548
|
// Initialize data members.
|
|
512
|
-
|
|
549
|
+
chand->combiner = grpc_combiner_create(NULL);
|
|
550
|
+
gpr_mu_init(&chand->info_mu);
|
|
513
551
|
chand->owning_stack = args->channel_stack;
|
|
514
552
|
grpc_closure_init(&chand->on_resolver_result_changed,
|
|
515
|
-
|
|
516
|
-
|
|
553
|
+
on_resolver_result_changed_locked, chand,
|
|
554
|
+
grpc_combiner_scheduler(chand->combiner, false));
|
|
517
555
|
chand->interested_parties = grpc_pollset_set_create();
|
|
518
556
|
grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
|
|
519
557
|
"client_channel");
|
|
@@ -524,27 +562,44 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
|
|
|
524
562
|
GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
|
|
525
563
|
grpc_client_channel_factory_ref(arg->value.pointer.p);
|
|
526
564
|
chand->client_channel_factory = arg->value.pointer.p;
|
|
527
|
-
//
|
|
565
|
+
// Get server name to resolve, using proxy mapper if needed.
|
|
528
566
|
arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
|
|
529
567
|
GPR_ASSERT(arg != NULL);
|
|
530
568
|
GPR_ASSERT(arg->type == GRPC_ARG_STRING);
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
569
|
+
char *proxy_name = NULL;
|
|
570
|
+
grpc_channel_args *new_args = NULL;
|
|
571
|
+
grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
|
|
572
|
+
&proxy_name, &new_args);
|
|
573
|
+
// Instantiate resolver.
|
|
574
|
+
chand->resolver = grpc_resolver_create(
|
|
575
|
+
exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
|
|
576
|
+
new_args != NULL ? new_args : args->channel_args,
|
|
577
|
+
chand->interested_parties, chand->combiner);
|
|
578
|
+
if (proxy_name != NULL) gpr_free(proxy_name);
|
|
579
|
+
if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
|
|
534
580
|
if (chand->resolver == NULL) {
|
|
535
581
|
return GRPC_ERROR_CREATE("resolver creation failed");
|
|
536
582
|
}
|
|
537
583
|
return GRPC_ERROR_NONE;
|
|
538
584
|
}
|
|
539
585
|
|
|
586
|
+
static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
|
|
587
|
+
grpc_error *error) {
|
|
588
|
+
grpc_resolver *resolver = arg;
|
|
589
|
+
grpc_resolver_shutdown_locked(exec_ctx, resolver);
|
|
590
|
+
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
|
|
591
|
+
}
|
|
592
|
+
|
|
540
593
|
/* Destructor for channel_data */
|
|
541
594
|
static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
|
|
542
595
|
grpc_channel_element *elem) {
|
|
543
596
|
channel_data *chand = elem->channel_data;
|
|
544
|
-
|
|
545
597
|
if (chand->resolver != NULL) {
|
|
546
|
-
|
|
547
|
-
|
|
598
|
+
grpc_closure_sched(
|
|
599
|
+
exec_ctx,
|
|
600
|
+
grpc_closure_create(shutdown_resolver_locked, chand->resolver,
|
|
601
|
+
grpc_combiner_scheduler(chand->combiner, false)),
|
|
602
|
+
GRPC_ERROR_NONE);
|
|
548
603
|
}
|
|
549
604
|
if (chand->client_channel_factory != NULL) {
|
|
550
605
|
grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
|
|
@@ -555,14 +610,15 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
|
|
|
555
610
|
chand->interested_parties);
|
|
556
611
|
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
|
|
557
612
|
}
|
|
558
|
-
gpr_free(chand->
|
|
559
|
-
gpr_free(chand->
|
|
613
|
+
gpr_free(chand->info_lb_policy_name);
|
|
614
|
+
gpr_free(chand->info_service_config_json);
|
|
560
615
|
if (chand->method_params_table != NULL) {
|
|
561
|
-
|
|
616
|
+
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
|
|
562
617
|
}
|
|
563
618
|
grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
|
|
564
|
-
grpc_pollset_set_destroy(chand->interested_parties);
|
|
565
|
-
|
|
619
|
+
grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
|
|
620
|
+
GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
|
|
621
|
+
gpr_mu_destroy(&chand->info_mu);
|
|
566
622
|
}
|
|
567
623
|
|
|
568
624
|
/*************************************************************************
|
|
@@ -593,10 +649,10 @@ typedef struct client_channel_call_data {
|
|
|
593
649
|
// to avoid this without breaking the grpc_deadline_state abstraction.
|
|
594
650
|
grpc_deadline_state deadline_state;
|
|
595
651
|
|
|
596
|
-
|
|
652
|
+
grpc_slice path; // Request path.
|
|
597
653
|
gpr_timespec call_start_time;
|
|
598
654
|
gpr_timespec deadline;
|
|
599
|
-
|
|
655
|
+
method_parameters *method_params;
|
|
600
656
|
grpc_closure read_service_config;
|
|
601
657
|
|
|
602
658
|
grpc_error *cancel_error;
|
|
@@ -605,8 +661,6 @@ typedef struct client_channel_call_data {
|
|
|
605
661
|
grpc_subchannel_call */
|
|
606
662
|
gpr_atm subchannel_call;
|
|
607
663
|
|
|
608
|
-
gpr_mu mu;
|
|
609
|
-
|
|
610
664
|
subchannel_creation_phase creation_phase;
|
|
611
665
|
grpc_connected_subchannel *connected_subchannel;
|
|
612
666
|
grpc_polling_entity *pollent;
|
|
@@ -622,6 +676,12 @@ typedef struct client_channel_call_data {
|
|
|
622
676
|
grpc_linked_mdelem lb_token_mdelem;
|
|
623
677
|
} call_data;
|
|
624
678
|
|
|
679
|
+
grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
|
|
680
|
+
grpc_call_element *call_elem) {
|
|
681
|
+
grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
|
|
682
|
+
return scc == CANCELLED_CALL ? NULL : scc;
|
|
683
|
+
}
|
|
684
|
+
|
|
625
685
|
static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
|
|
626
686
|
GPR_TIMER_BEGIN("add_waiting_locked", 0);
|
|
627
687
|
if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
|
|
@@ -645,52 +705,32 @@ static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
|
|
|
645
705
|
GRPC_ERROR_UNREF(error);
|
|
646
706
|
}
|
|
647
707
|
|
|
648
|
-
typedef struct {
|
|
649
|
-
grpc_transport_stream_op **ops;
|
|
650
|
-
size_t nops;
|
|
651
|
-
grpc_subchannel_call *call;
|
|
652
|
-
} retry_ops_args;
|
|
653
|
-
|
|
654
|
-
static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
|
|
655
|
-
retry_ops_args *a = args;
|
|
656
|
-
size_t i;
|
|
657
|
-
for (i = 0; i < a->nops; i++) {
|
|
658
|
-
grpc_subchannel_call_process_op(exec_ctx, a->call, a->ops[i]);
|
|
659
|
-
}
|
|
660
|
-
GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops");
|
|
661
|
-
gpr_free(a->ops);
|
|
662
|
-
gpr_free(a);
|
|
663
|
-
}
|
|
664
|
-
|
|
665
708
|
static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
|
|
666
709
|
if (calld->waiting_ops_count == 0) {
|
|
667
710
|
return;
|
|
668
711
|
}
|
|
669
712
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
if (a->call == CANCELLED_CALL) {
|
|
675
|
-
gpr_free(a);
|
|
713
|
+
grpc_subchannel_call *call = GET_CALL(calld);
|
|
714
|
+
grpc_transport_stream_op **ops = calld->waiting_ops;
|
|
715
|
+
size_t nops = calld->waiting_ops_count;
|
|
716
|
+
if (call == CANCELLED_CALL) {
|
|
676
717
|
fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
|
|
677
718
|
return;
|
|
678
719
|
}
|
|
679
720
|
calld->waiting_ops = NULL;
|
|
680
721
|
calld->waiting_ops_count = 0;
|
|
681
722
|
calld->waiting_ops_capacity = 0;
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
723
|
+
for (size_t i = 0; i < nops; i++) {
|
|
724
|
+
grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
|
|
725
|
+
}
|
|
726
|
+
gpr_free(ops);
|
|
686
727
|
}
|
|
687
728
|
|
|
688
|
-
static void
|
|
689
|
-
|
|
729
|
+
static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
|
|
730
|
+
grpc_error *error) {
|
|
690
731
|
grpc_call_element *elem = arg;
|
|
691
732
|
call_data *calld = elem->call_data;
|
|
692
733
|
channel_data *chand = elem->channel_data;
|
|
693
|
-
gpr_mu_lock(&calld->mu);
|
|
694
734
|
GPR_ASSERT(calld->creation_phase ==
|
|
695
735
|
GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
|
|
696
736
|
grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
|
|
@@ -726,7 +766,6 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
|
|
|
726
766
|
(gpr_atm)(uintptr_t)subchannel_call);
|
|
727
767
|
retry_waiting_locked(exec_ctx, calld);
|
|
728
768
|
}
|
|
729
|
-
gpr_mu_unlock(&calld->mu);
|
|
730
769
|
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
|
|
731
770
|
}
|
|
732
771
|
|
|
@@ -752,37 +791,35 @@ typedef struct {
|
|
|
752
791
|
/** Return true if subchannel is available immediately (in which case on_ready
|
|
753
792
|
should not be called), or false otherwise (in which case on_ready should be
|
|
754
793
|
called when the subchannel is available). */
|
|
755
|
-
static bool
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
static void
|
|
762
|
-
|
|
794
|
+
static bool pick_subchannel_locked(
|
|
795
|
+
grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|
796
|
+
grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
|
|
797
|
+
grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
|
|
798
|
+
grpc_error *error);
|
|
799
|
+
|
|
800
|
+
static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
|
|
801
|
+
grpc_error *error) {
|
|
763
802
|
continue_picking_args *cpa = arg;
|
|
764
803
|
if (cpa->connected_subchannel == NULL) {
|
|
765
804
|
/* cancelled, do nothing */
|
|
766
805
|
} else if (error != GRPC_ERROR_NONE) {
|
|
767
806
|
grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
|
|
768
807
|
} else {
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
cpa->on_ready, GRPC_ERROR_NONE)) {
|
|
808
|
+
if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
|
|
809
|
+
cpa->initial_metadata_flags,
|
|
810
|
+
cpa->connected_subchannel, cpa->on_ready,
|
|
811
|
+
GRPC_ERROR_NONE)) {
|
|
774
812
|
grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
|
|
775
813
|
}
|
|
776
|
-
gpr_mu_unlock(&calld->mu);
|
|
777
814
|
}
|
|
778
815
|
gpr_free(cpa);
|
|
779
816
|
}
|
|
780
817
|
|
|
781
|
-
static bool
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
818
|
+
static bool pick_subchannel_locked(
|
|
819
|
+
grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|
820
|
+
grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
|
|
821
|
+
grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
|
|
822
|
+
grpc_error *error) {
|
|
786
823
|
GPR_TIMER_BEGIN("pick_subchannel", 0);
|
|
787
824
|
|
|
788
825
|
channel_data *chand = elem->channel_data;
|
|
@@ -792,11 +829,11 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|
|
792
829
|
|
|
793
830
|
GPR_ASSERT(connected_subchannel);
|
|
794
831
|
|
|
795
|
-
gpr_mu_lock(&chand->mu);
|
|
796
832
|
if (initial_metadata == NULL) {
|
|
797
833
|
if (chand->lb_policy != NULL) {
|
|
798
|
-
|
|
799
|
-
|
|
834
|
+
grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
|
|
835
|
+
connected_subchannel,
|
|
836
|
+
GRPC_ERROR_REF(error));
|
|
800
837
|
}
|
|
801
838
|
for (closure = chand->waiting_for_config_closures.head; closure != NULL;
|
|
802
839
|
closure = closure->next_data.next) {
|
|
@@ -808,7 +845,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|
|
808
845
|
GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
|
|
809
846
|
}
|
|
810
847
|
}
|
|
811
|
-
gpr_mu_unlock(&chand->mu);
|
|
812
848
|
GPR_TIMER_END("pick_subchannel", 0);
|
|
813
849
|
GRPC_ERROR_UNREF(error);
|
|
814
850
|
return true;
|
|
@@ -817,7 +853,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|
|
817
853
|
if (chand->lb_policy != NULL) {
|
|
818
854
|
grpc_lb_policy *lb_policy = chand->lb_policy;
|
|
819
855
|
GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
|
|
820
|
-
gpr_mu_unlock(&chand->mu);
|
|
821
856
|
// If the application explicitly set wait_for_ready, use that.
|
|
822
857
|
// Otherwise, if the service config specified a value for this
|
|
823
858
|
// method, use that.
|
|
@@ -825,10 +860,11 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|
|
825
860
|
initial_metadata_flags &
|
|
826
861
|
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
|
|
827
862
|
const bool wait_for_ready_set_from_service_config =
|
|
828
|
-
calld->
|
|
863
|
+
calld->method_params != NULL &&
|
|
864
|
+
calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
|
|
829
865
|
if (!wait_for_ready_set_from_api &&
|
|
830
866
|
wait_for_ready_set_from_service_config) {
|
|
831
|
-
if (calld->
|
|
867
|
+
if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
|
|
832
868
|
initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
|
|
833
869
|
} else {
|
|
834
870
|
initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
|
|
@@ -837,7 +873,7 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|
|
837
873
|
const grpc_lb_policy_pick_args inputs = {
|
|
838
874
|
initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
|
|
839
875
|
gpr_inf_future(GPR_CLOCK_MONOTONIC)};
|
|
840
|
-
const bool result =
|
|
876
|
+
const bool result = grpc_lb_policy_pick_locked(
|
|
841
877
|
exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
|
|
842
878
|
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
|
|
843
879
|
GPR_TIMER_END("pick_subchannel", 0);
|
|
@@ -846,8 +882,9 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|
|
846
882
|
if (chand->resolver != NULL && !chand->started_resolving) {
|
|
847
883
|
chand->started_resolving = true;
|
|
848
884
|
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
|
|
849
|
-
|
|
850
|
-
|
|
885
|
+
grpc_resolver_next_locked(exec_ctx, chand->resolver,
|
|
886
|
+
&chand->resolver_result,
|
|
887
|
+
&chand->on_resolver_result_changed);
|
|
851
888
|
}
|
|
852
889
|
if (chand->resolver != NULL) {
|
|
853
890
|
cpa = gpr_malloc(sizeof(*cpa));
|
|
@@ -856,88 +893,66 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|
|
856
893
|
cpa->connected_subchannel = connected_subchannel;
|
|
857
894
|
cpa->on_ready = on_ready;
|
|
858
895
|
cpa->elem = elem;
|
|
859
|
-
grpc_closure_init(&cpa->closure,
|
|
860
|
-
|
|
896
|
+
grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
|
|
897
|
+
grpc_combiner_scheduler(chand->combiner, true));
|
|
861
898
|
grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
|
|
862
899
|
GRPC_ERROR_NONE);
|
|
863
900
|
} else {
|
|
864
901
|
grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
|
|
865
902
|
}
|
|
866
|
-
gpr_mu_unlock(&chand->mu);
|
|
867
903
|
|
|
868
904
|
GPR_TIMER_END("pick_subchannel", 0);
|
|
869
905
|
return false;
|
|
870
906
|
}
|
|
871
907
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
// the streaming case.
|
|
876
|
-
// TODO(ctiller): Explain this more thoroughly.
|
|
877
|
-
static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
|
|
878
|
-
grpc_call_element *elem,
|
|
879
|
-
grpc_transport_stream_op *op) {
|
|
880
|
-
call_data *calld = elem->call_data;
|
|
908
|
+
static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
|
|
909
|
+
grpc_transport_stream_op *op,
|
|
910
|
+
grpc_call_element *elem) {
|
|
881
911
|
channel_data *chand = elem->channel_data;
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
grpc_subchannel_call *call = GET_CALL(calld);
|
|
886
|
-
GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
|
|
887
|
-
if (call == CANCELLED_CALL) {
|
|
888
|
-
grpc_transport_stream_op_finish_with_failure(
|
|
889
|
-
exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
|
|
890
|
-
GPR_TIMER_END("cc_start_transport_stream_op", 0);
|
|
891
|
-
return;
|
|
892
|
-
}
|
|
893
|
-
if (call != NULL) {
|
|
894
|
-
grpc_subchannel_call_process_op(exec_ctx, call, op);
|
|
895
|
-
GPR_TIMER_END("cc_start_transport_stream_op", 0);
|
|
896
|
-
return;
|
|
897
|
-
}
|
|
898
|
-
/* we failed; lock and figure out what to do */
|
|
899
|
-
gpr_mu_lock(&calld->mu);
|
|
900
|
-
retry:
|
|
912
|
+
call_data *calld = elem->call_data;
|
|
913
|
+
grpc_subchannel_call *call;
|
|
914
|
+
|
|
901
915
|
/* need to recheck that another thread hasn't set the call */
|
|
902
916
|
call = GET_CALL(calld);
|
|
903
917
|
if (call == CANCELLED_CALL) {
|
|
904
|
-
gpr_mu_unlock(&calld->mu);
|
|
905
918
|
grpc_transport_stream_op_finish_with_failure(
|
|
906
919
|
exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
|
|
907
|
-
|
|
920
|
+
/* early out */
|
|
908
921
|
return;
|
|
909
922
|
}
|
|
910
923
|
if (call != NULL) {
|
|
911
|
-
gpr_mu_unlock(&calld->mu);
|
|
912
924
|
grpc_subchannel_call_process_op(exec_ctx, call, op);
|
|
913
|
-
|
|
925
|
+
/* early out */
|
|
914
926
|
return;
|
|
915
927
|
}
|
|
916
928
|
/* if this is a cancellation, then we can raise our cancelled flag */
|
|
917
929
|
if (op->cancel_error != GRPC_ERROR_NONE) {
|
|
918
930
|
if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
|
|
919
931
|
(gpr_atm)(uintptr_t)CANCELLED_CALL)) {
|
|
920
|
-
|
|
932
|
+
/* recurse to retry */
|
|
933
|
+
start_transport_stream_op_locked_inner(exec_ctx, op, elem);
|
|
934
|
+
/* early out */
|
|
935
|
+
return;
|
|
921
936
|
} else {
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
937
|
+
/* Stash a copy of cancel_error in our call data, so that we can use
|
|
938
|
+
it for subsequent operations. This ensures that if the call is
|
|
939
|
+
cancelled before any ops are passed down (e.g., if the deadline
|
|
940
|
+
is in the past when the call starts), we can return the right
|
|
941
|
+
error to the caller when the first op does get passed down. */
|
|
927
942
|
calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
|
|
928
943
|
switch (calld->creation_phase) {
|
|
929
944
|
case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
|
|
930
945
|
fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
|
|
931
946
|
break;
|
|
932
947
|
case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
|
|
933
|
-
|
|
934
|
-
|
|
948
|
+
pick_subchannel_locked(exec_ctx, elem, NULL, 0,
|
|
949
|
+
&calld->connected_subchannel, NULL,
|
|
950
|
+
GRPC_ERROR_REF(op->cancel_error));
|
|
935
951
|
break;
|
|
936
952
|
}
|
|
937
|
-
gpr_mu_unlock(&calld->mu);
|
|
938
953
|
grpc_transport_stream_op_finish_with_failure(
|
|
939
954
|
exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
|
|
940
|
-
|
|
955
|
+
/* early out */
|
|
941
956
|
return;
|
|
942
957
|
}
|
|
943
958
|
}
|
|
@@ -946,16 +961,16 @@ retry:
|
|
|
946
961
|
calld->connected_subchannel == NULL &&
|
|
947
962
|
op->send_initial_metadata != NULL) {
|
|
948
963
|
calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
|
|
949
|
-
grpc_closure_init(&calld->next_step,
|
|
950
|
-
|
|
964
|
+
grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
|
|
965
|
+
grpc_combiner_scheduler(chand->combiner, true));
|
|
951
966
|
GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
|
|
952
967
|
/* If a subchannel is not available immediately, the polling entity from
|
|
953
968
|
call_data should be provided to channel_data's interested_parties, so
|
|
954
969
|
that IO of the lb_policy and resolver could be done under it. */
|
|
955
|
-
if (
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
970
|
+
if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
|
|
971
|
+
op->send_initial_metadata_flags,
|
|
972
|
+
&calld->connected_subchannel, &calld->next_step,
|
|
973
|
+
GRPC_ERROR_NONE)) {
|
|
959
974
|
calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
|
|
960
975
|
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
|
|
961
976
|
} else {
|
|
@@ -978,131 +993,181 @@ retry:
|
|
|
978
993
|
gpr_atm_rel_store(&calld->subchannel_call,
|
|
979
994
|
(gpr_atm)(uintptr_t)subchannel_call);
|
|
980
995
|
retry_waiting_locked(exec_ctx, calld);
|
|
981
|
-
|
|
996
|
+
/* recurse to retry */
|
|
997
|
+
start_transport_stream_op_locked_inner(exec_ctx, op, elem);
|
|
998
|
+
/* early out */
|
|
999
|
+
return;
|
|
982
1000
|
}
|
|
983
1001
|
/* nothing to be done but wait */
|
|
984
1002
|
add_waiting_locked(calld, op);
|
|
985
|
-
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
|
|
1006
|
+
grpc_error *error_ignored) {
|
|
1007
|
+
GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
|
|
1008
|
+
|
|
1009
|
+
grpc_transport_stream_op *op = arg;
|
|
1010
|
+
grpc_call_element *elem = op->handler_private.args[0];
|
|
1011
|
+
call_data *calld = elem->call_data;
|
|
1012
|
+
|
|
1013
|
+
start_transport_stream_op_locked_inner(exec_ctx, op, elem);
|
|
1014
|
+
|
|
1015
|
+
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
|
|
1016
|
+
"start_transport_stream_op");
|
|
1017
|
+
GPR_TIMER_END("start_transport_stream_op_locked", 0);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/* The logic here is fairly complicated, due to (a) the fact that we
|
|
1021
|
+
need to handle the case where we receive the send op before the
|
|
1022
|
+
initial metadata op, and (b) the need for efficiency, especially in
|
|
1023
|
+
the streaming case.
|
|
1024
|
+
|
|
1025
|
+
We use double-checked locking to initially see if initialization has been
|
|
1026
|
+
performed. If it has not, we acquire the combiner and perform initialization.
|
|
1027
|
+
If it has, we proceed on the fast path. */
|
|
1028
|
+
static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
|
|
1029
|
+
grpc_call_element *elem,
|
|
1030
|
+
grpc_transport_stream_op *op) {
|
|
1031
|
+
call_data *calld = elem->call_data;
|
|
1032
|
+
channel_data *chand = elem->channel_data;
|
|
1033
|
+
GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
|
|
1034
|
+
grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
|
|
1035
|
+
/* try to (atomically) get the call */
|
|
1036
|
+
grpc_subchannel_call *call = GET_CALL(calld);
|
|
1037
|
+
GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
|
|
1038
|
+
if (call == CANCELLED_CALL) {
|
|
1039
|
+
grpc_transport_stream_op_finish_with_failure(
|
|
1040
|
+
exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
|
|
1041
|
+
GPR_TIMER_END("cc_start_transport_stream_op", 0);
|
|
1042
|
+
/* early out */
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
if (call != NULL) {
|
|
1046
|
+
grpc_subchannel_call_process_op(exec_ctx, call, op);
|
|
1047
|
+
GPR_TIMER_END("cc_start_transport_stream_op", 0);
|
|
1048
|
+
/* early out */
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
/* we failed; lock and figure out what to do */
|
|
1052
|
+
GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
|
|
1053
|
+
op->handler_private.args[0] = elem;
|
|
1054
|
+
grpc_closure_sched(
|
|
1055
|
+
exec_ctx,
|
|
1056
|
+
grpc_closure_init(&op->handler_private.closure,
|
|
1057
|
+
start_transport_stream_op_locked, op,
|
|
1058
|
+
grpc_combiner_scheduler(chand->combiner, false)),
|
|
1059
|
+
GRPC_ERROR_NONE);
|
|
986
1060
|
GPR_TIMER_END("cc_start_transport_stream_op", 0);
|
|
987
1061
|
}
|
|
988
1062
|
|
|
1063
|
+
// Sets calld->method_params.
|
|
1064
|
+
// If the method params specify a timeout, populates
|
|
1065
|
+
// *per_method_deadline and returns true.
|
|
1066
|
+
static bool set_call_method_params_from_service_config_locked(
|
|
1067
|
+
grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|
1068
|
+
gpr_timespec *per_method_deadline) {
|
|
1069
|
+
channel_data *chand = elem->channel_data;
|
|
1070
|
+
call_data *calld = elem->call_data;
|
|
1071
|
+
if (chand->method_params_table != NULL) {
|
|
1072
|
+
calld->method_params = grpc_method_config_table_get(
|
|
1073
|
+
exec_ctx, chand->method_params_table, calld->path);
|
|
1074
|
+
if (calld->method_params != NULL) {
|
|
1075
|
+
method_parameters_ref(calld->method_params);
|
|
1076
|
+
if (gpr_time_cmp(calld->method_params->timeout,
|
|
1077
|
+
gpr_time_0(GPR_TIMESPAN)) != 0) {
|
|
1078
|
+
*per_method_deadline =
|
|
1079
|
+
gpr_time_add(calld->call_start_time, calld->method_params->timeout);
|
|
1080
|
+
return true;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
return false;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
989
1087
|
// Gets data from the service config. Invoked when the resolver returns
|
|
990
1088
|
// its initial result.
|
|
991
|
-
static void
|
|
992
|
-
|
|
1089
|
+
static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg,
|
|
1090
|
+
grpc_error *error) {
|
|
993
1091
|
grpc_call_element *elem = arg;
|
|
994
|
-
channel_data *chand = elem->channel_data;
|
|
995
1092
|
call_data *calld = elem->call_data;
|
|
996
1093
|
// If this is an error, there's no point in looking at the service config.
|
|
997
1094
|
if (error == GRPC_ERROR_NONE) {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
// If the method config table was present, use it.
|
|
1007
|
-
if (method_params_table != NULL) {
|
|
1008
|
-
const method_parameters *method_params = grpc_method_config_table_get(
|
|
1009
|
-
exec_ctx, method_params_table, calld->path);
|
|
1010
|
-
if (method_params != NULL) {
|
|
1011
|
-
const bool have_method_timeout =
|
|
1012
|
-
gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
|
|
1013
|
-
if (have_method_timeout ||
|
|
1014
|
-
method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
|
|
1015
|
-
gpr_mu_lock(&calld->mu);
|
|
1016
|
-
if (have_method_timeout) {
|
|
1017
|
-
const gpr_timespec per_method_deadline =
|
|
1018
|
-
gpr_time_add(calld->call_start_time, method_params->timeout);
|
|
1019
|
-
if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
|
|
1020
|
-
calld->deadline = per_method_deadline;
|
|
1021
|
-
// Reset deadline timer.
|
|
1022
|
-
grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
|
|
1026
|
-
calld->wait_for_ready_from_service_config =
|
|
1027
|
-
method_params->wait_for_ready;
|
|
1028
|
-
}
|
|
1029
|
-
gpr_mu_unlock(&calld->mu);
|
|
1030
|
-
}
|
|
1095
|
+
gpr_timespec per_method_deadline;
|
|
1096
|
+
if (set_call_method_params_from_service_config_locked(
|
|
1097
|
+
exec_ctx, elem, &per_method_deadline)) {
|
|
1098
|
+
// If the deadline from the service config is shorter than the one
|
|
1099
|
+
// from the client API, reset the deadline timer.
|
|
1100
|
+
if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
|
|
1101
|
+
calld->deadline = per_method_deadline;
|
|
1102
|
+
grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
|
|
1031
1103
|
}
|
|
1032
|
-
grpc_mdstr_hash_table_unref(exec_ctx, method_params_table);
|
|
1033
1104
|
}
|
|
1034
1105
|
}
|
|
1035
1106
|
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
|
|
1036
1107
|
}
|
|
1037
1108
|
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1109
|
+
static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
|
|
1110
|
+
void *arg,
|
|
1111
|
+
grpc_error *error_ignored) {
|
|
1112
|
+
grpc_call_element *elem = arg;
|
|
1042
1113
|
channel_data *chand = elem->channel_data;
|
|
1043
1114
|
call_data *calld = elem->call_data;
|
|
1044
|
-
// Initialize data members.
|
|
1045
|
-
grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
|
|
1046
|
-
calld->path = GRPC_MDSTR_REF(args->path);
|
|
1047
|
-
calld->call_start_time = args->start_time;
|
|
1048
|
-
calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
|
|
1049
|
-
calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
|
|
1050
|
-
calld->cancel_error = GRPC_ERROR_NONE;
|
|
1051
|
-
gpr_atm_rel_store(&calld->subchannel_call, 0);
|
|
1052
|
-
gpr_mu_init(&calld->mu);
|
|
1053
|
-
calld->connected_subchannel = NULL;
|
|
1054
|
-
calld->waiting_ops = NULL;
|
|
1055
|
-
calld->waiting_ops_count = 0;
|
|
1056
|
-
calld->waiting_ops_capacity = 0;
|
|
1057
|
-
calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
|
|
1058
|
-
calld->owning_call = args->call_stack;
|
|
1059
|
-
calld->pollent = NULL;
|
|
1060
1115
|
// If the resolver has already returned results, then we can access
|
|
1061
1116
|
// the service config parameters immediately. Otherwise, we need to
|
|
1062
1117
|
// defer that work until the resolver returns an initial result.
|
|
1063
|
-
// TODO(roth): This code is almost but not quite identical to the code
|
|
1064
|
-
// in read_service_config() above. It would be nice to find a way to
|
|
1065
|
-
// combine them, to avoid having to maintain it twice.
|
|
1066
|
-
gpr_mu_lock(&chand->mu);
|
|
1067
1118
|
if (chand->lb_policy != NULL) {
|
|
1068
1119
|
// We already have a resolver result, so check for service config.
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
method_parameters *method_params = grpc_method_config_table_get(
|
|
1074
|
-
exec_ctx, method_params_table, args->path);
|
|
1075
|
-
if (method_params != NULL) {
|
|
1076
|
-
if (gpr_time_cmp(method_params->timeout,
|
|
1077
|
-
gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
|
|
1078
|
-
gpr_timespec per_method_deadline =
|
|
1079
|
-
gpr_time_add(calld->call_start_time, method_params->timeout);
|
|
1080
|
-
calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
|
|
1081
|
-
}
|
|
1082
|
-
if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
|
|
1083
|
-
calld->wait_for_ready_from_service_config =
|
|
1084
|
-
method_params->wait_for_ready;
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
grpc_mdstr_hash_table_unref(exec_ctx, method_params_table);
|
|
1088
|
-
} else {
|
|
1089
|
-
gpr_mu_unlock(&chand->mu);
|
|
1120
|
+
gpr_timespec per_method_deadline;
|
|
1121
|
+
if (set_call_method_params_from_service_config_locked(
|
|
1122
|
+
exec_ctx, elem, &per_method_deadline)) {
|
|
1123
|
+
calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
|
|
1090
1124
|
}
|
|
1091
1125
|
} else {
|
|
1092
1126
|
// We don't yet have a resolver result, so register a callback to
|
|
1093
1127
|
// get the service config data once the resolver returns.
|
|
1094
1128
|
// Take a reference to the call stack to be owned by the callback.
|
|
1095
1129
|
GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
|
|
1096
|
-
grpc_closure_init(&calld->read_service_config,
|
|
1097
|
-
|
|
1130
|
+
grpc_closure_init(&calld->read_service_config, read_service_config_locked,
|
|
1131
|
+
elem, grpc_combiner_scheduler(chand->combiner, false));
|
|
1098
1132
|
grpc_closure_list_append(&chand->waiting_for_config_closures,
|
|
1099
1133
|
&calld->read_service_config, GRPC_ERROR_NONE);
|
|
1100
|
-
gpr_mu_unlock(&chand->mu);
|
|
1101
1134
|
}
|
|
1102
1135
|
// Start the deadline timer with the current deadline value. If we
|
|
1103
1136
|
// do not yet have service config data, then the timer may be reset
|
|
1104
1137
|
// later.
|
|
1105
1138
|
grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
|
|
1139
|
+
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
|
|
1140
|
+
"initial_read_service_config");
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/* Constructor for call_data */
|
|
1144
|
+
static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
|
|
1145
|
+
grpc_call_element *elem,
|
|
1146
|
+
const grpc_call_element_args *args) {
|
|
1147
|
+
channel_data *chand = elem->channel_data;
|
|
1148
|
+
call_data *calld = elem->call_data;
|
|
1149
|
+
// Initialize data members.
|
|
1150
|
+
grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
|
|
1151
|
+
calld->path = grpc_slice_ref_internal(args->path);
|
|
1152
|
+
calld->call_start_time = args->start_time;
|
|
1153
|
+
calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
|
|
1154
|
+
calld->method_params = NULL;
|
|
1155
|
+
calld->cancel_error = GRPC_ERROR_NONE;
|
|
1156
|
+
gpr_atm_rel_store(&calld->subchannel_call, 0);
|
|
1157
|
+
calld->connected_subchannel = NULL;
|
|
1158
|
+
calld->waiting_ops = NULL;
|
|
1159
|
+
calld->waiting_ops_count = 0;
|
|
1160
|
+
calld->waiting_ops_capacity = 0;
|
|
1161
|
+
calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
|
|
1162
|
+
calld->owning_call = args->call_stack;
|
|
1163
|
+
calld->pollent = NULL;
|
|
1164
|
+
GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config");
|
|
1165
|
+
grpc_closure_sched(
|
|
1166
|
+
exec_ctx,
|
|
1167
|
+
grpc_closure_init(&calld->read_service_config,
|
|
1168
|
+
initial_read_service_config_locked, elem,
|
|
1169
|
+
grpc_combiner_scheduler(chand->combiner, false)),
|
|
1170
|
+
GRPC_ERROR_NONE);
|
|
1106
1171
|
return GRPC_ERROR_NONE;
|
|
1107
1172
|
}
|
|
1108
1173
|
|
|
@@ -1113,14 +1178,16 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
|
|
|
1113
1178
|
void *and_free_memory) {
|
|
1114
1179
|
call_data *calld = elem->call_data;
|
|
1115
1180
|
grpc_deadline_state_destroy(exec_ctx, elem);
|
|
1116
|
-
|
|
1181
|
+
grpc_slice_unref_internal(exec_ctx, calld->path);
|
|
1182
|
+
if (calld->method_params != NULL) {
|
|
1183
|
+
method_parameters_unref(calld->method_params);
|
|
1184
|
+
}
|
|
1117
1185
|
GRPC_ERROR_UNREF(calld->cancel_error);
|
|
1118
1186
|
grpc_subchannel_call *call = GET_CALL(calld);
|
|
1119
1187
|
if (call != NULL && call != CANCELLED_CALL) {
|
|
1120
1188
|
GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
|
|
1121
1189
|
}
|
|
1122
1190
|
GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
|
|
1123
|
-
gpr_mu_destroy(&calld->mu);
|
|
1124
1191
|
GPR_ASSERT(calld->waiting_ops_count == 0);
|
|
1125
1192
|
if (calld->connected_subchannel != NULL) {
|
|
1126
1193
|
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
|
|
@@ -1156,26 +1223,37 @@ const grpc_channel_filter grpc_client_channel_filter = {
|
|
|
1156
1223
|
"client-channel",
|
|
1157
1224
|
};
|
|
1158
1225
|
|
|
1226
|
+
static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
|
|
1227
|
+
grpc_error *error_ignored) {
|
|
1228
|
+
channel_data *chand = arg;
|
|
1229
|
+
if (chand->lb_policy != NULL) {
|
|
1230
|
+
grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
|
|
1231
|
+
} else {
|
|
1232
|
+
chand->exit_idle_when_lb_policy_arrives = true;
|
|
1233
|
+
if (!chand->started_resolving && chand->resolver != NULL) {
|
|
1234
|
+
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
|
|
1235
|
+
chand->started_resolving = true;
|
|
1236
|
+
grpc_resolver_next_locked(exec_ctx, chand->resolver,
|
|
1237
|
+
&chand->resolver_result,
|
|
1238
|
+
&chand->on_resolver_result_changed);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1159
1244
|
grpc_connectivity_state grpc_client_channel_check_connectivity_state(
|
|
1160
1245
|
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
|
|
1161
1246
|
channel_data *chand = elem->channel_data;
|
|
1162
|
-
grpc_connectivity_state out
|
|
1163
|
-
|
|
1164
|
-
out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
|
|
1247
|
+
grpc_connectivity_state out =
|
|
1248
|
+
grpc_connectivity_state_check(&chand->state_tracker);
|
|
1165
1249
|
if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
chand->started_resolving = true;
|
|
1173
|
-
grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
|
|
1174
|
-
&chand->on_resolver_result_changed);
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1250
|
+
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
|
|
1251
|
+
grpc_closure_sched(
|
|
1252
|
+
exec_ctx,
|
|
1253
|
+
grpc_closure_create(try_to_connect_locked, chand,
|
|
1254
|
+
grpc_combiner_scheduler(chand->combiner, false)),
|
|
1255
|
+
GRPC_ERROR_NONE);
|
|
1177
1256
|
}
|
|
1178
|
-
gpr_mu_unlock(&chand->mu);
|
|
1179
1257
|
return out;
|
|
1180
1258
|
}
|
|
1181
1259
|
|
|
@@ -1183,6 +1261,7 @@ typedef struct {
|
|
|
1183
1261
|
channel_data *chand;
|
|
1184
1262
|
grpc_pollset *pollset;
|
|
1185
1263
|
grpc_closure *on_complete;
|
|
1264
|
+
grpc_connectivity_state *state;
|
|
1186
1265
|
grpc_closure my_closure;
|
|
1187
1266
|
} external_connectivity_watcher;
|
|
1188
1267
|
|
|
@@ -1195,7 +1274,16 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
|
|
|
1195
1274
|
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
|
|
1196
1275
|
"external_connectivity_watcher");
|
|
1197
1276
|
gpr_free(w);
|
|
1198
|
-
|
|
1277
|
+
grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
|
|
1281
|
+
grpc_error *error_ignored) {
|
|
1282
|
+
external_connectivity_watcher *w = arg;
|
|
1283
|
+
grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
|
|
1284
|
+
grpc_schedule_on_exec_ctx);
|
|
1285
|
+
grpc_connectivity_state_notify_on_state_change(
|
|
1286
|
+
exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
|
|
1199
1287
|
}
|
|
1200
1288
|
|
|
1201
1289
|
void grpc_client_channel_watch_connectivity_state(
|
|
@@ -1206,13 +1294,13 @@ void grpc_client_channel_watch_connectivity_state(
|
|
|
1206
1294
|
w->chand = chand;
|
|
1207
1295
|
w->pollset = pollset;
|
|
1208
1296
|
w->on_complete = on_complete;
|
|
1297
|
+
w->state = state;
|
|
1209
1298
|
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
|
|
1210
|
-
grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
|
|
1211
|
-
grpc_schedule_on_exec_ctx);
|
|
1212
1299
|
GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
|
|
1213
1300
|
"external_connectivity_watcher");
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1301
|
+
grpc_closure_sched(
|
|
1302
|
+
exec_ctx,
|
|
1303
|
+
grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
|
|
1304
|
+
grpc_combiner_scheduler(chand->combiner, true)),
|
|
1305
|
+
GRPC_ERROR_NONE);
|
|
1218
1306
|
}
|