grpc 1.32.0 → 1.33.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Makefile +175 -376
- data/include/grpc/grpc.h +0 -5
- data/include/grpc/grpc_security.h +16 -0
- data/include/grpc/impl/codegen/grpc_types.h +0 -5
- data/src/core/ext/filters/client_channel/client_channel.cc +204 -170
- data/src/core/ext/filters/client_channel/config_selector.cc +0 -4
- data/src/core/ext/filters/client_channel/config_selector.h +34 -5
- data/src/core/ext/filters/client_channel/lb_policy.h +1 -1
- data/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc +48 -35
- data/src/core/ext/filters/client_channel/lb_policy/address_filtering.h +7 -5
- data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc +3 -2
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +106 -106
- data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +2 -2
- data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +3 -3
- data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +3 -3
- data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +9 -32
- data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +3 -3
- data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +198 -126
- data/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc +439 -249
- data/src/core/ext/filters/client_channel/lb_policy/xds/eds_drop.cc +571 -0
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +727 -0
- data/src/core/ext/filters/client_channel/lb_policy_registry.cc +8 -1
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +1 -1
- data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +553 -358
- data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.h +28 -0
- data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +8 -39
- data/src/core/ext/filters/client_channel/resolver_result_parsing.h +4 -2
- data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +44 -43
- data/src/core/ext/filters/client_channel/resolving_lb_policy.h +5 -9
- data/src/core/ext/filters/client_channel/server_address.cc +80 -0
- data/src/core/ext/filters/client_channel/server_address.h +25 -36
- data/src/core/ext/filters/client_channel/service_config.cc +16 -13
- data/src/core/ext/filters/client_channel/service_config.h +7 -4
- data/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +2 -2
- data/src/core/ext/filters/client_channel/service_config_parser.cc +8 -6
- data/src/core/ext/filters/client_channel/service_config_parser.h +8 -5
- data/src/core/ext/filters/client_channel/subchannel_interface.h +44 -0
- data/src/core/ext/filters/message_size/message_size_filter.cc +2 -1
- data/src/core/ext/filters/message_size/message_size_filter.h +2 -1
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +17 -10
- data/src/core/ext/transport/chttp2/transport/flow_control.cc +10 -2
- data/src/core/ext/transport/chttp2/transport/flow_control.h +10 -0
- data/src/core/ext/transport/chttp2/transport/internal.h +5 -0
- data/src/core/ext/transport/chttp2/transport/parsing.cc +16 -2
- data/src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c +29 -9
- data/src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h +66 -0
- data/src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c +123 -45
- data/src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h +310 -53
- data/src/core/ext/upb-generated/envoy/config/core/v3/address.upb.c +17 -5
- data/src/core/ext/upb-generated/envoy/config/core/v3/address.upb.h +45 -0
- data/src/core/ext/upb-generated/envoy/config/core/v3/base.upb.c +1 -0
- data/src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.c +16 -9
- data/src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.h +38 -15
- data/src/core/ext/upb-generated/envoy/config/core/v3/extension.upb.c +53 -0
- data/src/core/ext/upb-generated/envoy/config/core/v3/extension.upb.h +133 -0
- data/src/core/ext/upb-generated/envoy/config/core/v3/grpc_service.upb.c +54 -8
- data/src/core/ext/upb-generated/envoy/config/core/v3/grpc_service.upb.h +123 -5
- data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c +40 -16
- data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h +114 -5
- data/src/core/ext/upb-generated/envoy/config/core/v3/substitution_format_string.upb.c +36 -0
- data/src/core/ext/upb-generated/envoy/config/core/v3/substitution_format_string.upb.h +85 -0
- data/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c +36 -16
- data/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h +86 -20
- data/src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c +23 -6
- data/src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h +54 -5
- data/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c +10 -6
- data/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h +28 -11
- data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c +184 -57
- data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h +504 -69
- data/src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c +6 -5
- data/src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h +11 -7
- data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c +78 -26
- data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h +236 -25
- data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c +8 -9
- data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h +19 -33
- data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c +7 -3
- data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.h +16 -0
- data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/tls.upb.c +65 -23
- data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/tls.upb.h +229 -47
- data/src/core/ext/upb-generated/envoy/service/discovery/v3/discovery.upb.c +20 -10
- data/src/core/ext/upb-generated/envoy/service/discovery/v3/discovery.upb.h +67 -4
- data/src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c +3 -2
- data/src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h +6 -0
- data/src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c +242 -0
- data/src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.h +753 -0
- data/src/core/ext/upb-generated/udpa/annotations/security.upb.c +31 -0
- data/src/core/ext/upb-generated/udpa/annotations/security.upb.h +57 -0
- data/src/core/ext/upb-generated/udpa/core/v1/authority.upb.c +28 -0
- data/src/core/ext/upb-generated/udpa/core/v1/authority.upb.h +53 -0
- data/src/core/ext/upb-generated/udpa/core/v1/collection_entry.upb.c +52 -0
- data/src/core/ext/upb-generated/udpa/core/v1/collection_entry.upb.h +129 -0
- data/src/core/ext/upb-generated/udpa/core/v1/context_params.upb.c +42 -0
- data/src/core/ext/upb-generated/udpa/core/v1/context_params.upb.h +77 -0
- data/src/core/ext/upb-generated/udpa/core/v1/resource.upb.c +36 -0
- data/src/core/ext/upb-generated/udpa/core/v1/resource.upb.h +85 -0
- data/src/core/ext/upb-generated/udpa/core/v1/resource_locator.upb.c +54 -0
- data/src/core/ext/upb-generated/udpa/core/v1/resource_locator.upb.h +160 -0
- data/src/core/ext/upb-generated/udpa/core/v1/resource_name.upb.c +36 -0
- data/src/core/ext/upb-generated/udpa/core/v1/resource_name.upb.h +84 -0
- data/src/core/ext/xds/certificate_provider_factory.h +59 -0
- data/src/core/ext/xds/certificate_provider_registry.cc +103 -0
- data/src/core/ext/xds/certificate_provider_registry.h +57 -0
- data/src/core/ext/xds/certificate_provider_store.h +50 -0
- data/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.cc +377 -0
- data/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.h +102 -0
- data/src/core/ext/xds/xds_api.cc +301 -93
- data/src/core/ext/xds/xds_api.h +129 -92
- data/src/core/ext/xds/xds_channel_args.h +6 -3
- data/src/core/ext/xds/xds_client.cc +498 -410
- data/src/core/ext/xds/xds_client.h +105 -51
- data/src/core/ext/xds/xds_client_stats.cc +18 -12
- data/src/core/ext/xds/xds_client_stats.h +33 -5
- data/src/core/lib/channel/channel_args.h +0 -1
- data/src/core/lib/channel/channelz.cc +10 -45
- data/src/core/lib/channel/channelz.h +11 -19
- data/src/core/lib/channel/channelz_registry.cc +12 -11
- data/src/core/lib/channel/channelz_registry.h +3 -0
- data/src/core/lib/gpr/time_precise.cc +2 -0
- data/src/core/lib/gpr/time_precise.h +6 -2
- data/src/core/lib/gprpp/dual_ref_counted.h +336 -0
- data/src/core/lib/gprpp/ref_counted.h +51 -22
- data/src/core/lib/gprpp/ref_counted_ptr.h +153 -0
- data/src/core/lib/iomgr/endpoint_cfstream.cc +9 -5
- data/src/core/lib/iomgr/exec_ctx.h +10 -8
- data/src/core/lib/json/json_util.cc +58 -0
- data/src/core/lib/json/json_util.h +37 -0
- data/src/core/lib/security/certificate_provider.h +60 -0
- data/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc +321 -0
- data/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h +214 -0
- data/src/core/lib/security/credentials/xds/xds_credentials.cc +45 -0
- data/src/core/lib/security/credentials/xds/xds_credentials.h +51 -0
- data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +6 -10
- data/src/core/lib/security/security_connector/ssl_utils.h +5 -0
- data/src/core/lib/surface/channel.cc +9 -31
- data/src/core/lib/surface/channel.h +6 -1
- data/src/core/lib/surface/init.cc +26 -9
- data/src/core/lib/surface/version.cc +2 -2
- data/src/core/lib/transport/bdp_estimator.h +2 -1
- data/src/core/lib/transport/connectivity_state.h +2 -2
- data/src/core/lib/transport/metadata.cc +11 -1
- data/src/core/plugin_registry/grpc_plugin_registry.cc +35 -20
- data/src/core/tsi/ssl_transport_security.cc +2 -2
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -2
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -3
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/third_party/boringssl-with-bazel/err_data.c +465 -463
- data/third_party/boringssl-with-bazel/src/crypto/asn1/asn1_lib.c +0 -6
- data/third_party/boringssl-with-bazel/src/crypto/dsa/dsa.c +9 -43
- data/third_party/boringssl-with-bazel/src/crypto/dsa/dsa_asn1.c +55 -4
- data/third_party/boringssl-with-bazel/src/crypto/dsa/internal.h +34 -0
- data/third_party/boringssl-with-bazel/src/crypto/evp/evp.c +4 -0
- data/third_party/boringssl-with-bazel/src/crypto/evp/p_dsa_asn1.c +6 -2
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/digest/digest.c +2 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/internal.h +4 -0
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa.c +30 -10
- data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa_impl.c +10 -15
- data/third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c +98 -11
- data/third_party/boringssl-with-bazel/src/crypto/hpke/internal.h +51 -6
- data/third_party/boringssl-with-bazel/src/crypto/trust_token/internal.h +44 -2
- data/third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c +221 -49
- data/third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c +64 -20
- data/third_party/boringssl-with-bazel/src/crypto/x509/a_strex.c +3 -3
- data/third_party/boringssl-with-bazel/src/crypto/x509/algorithm.c +0 -8
- data/third_party/boringssl-with-bazel/src/crypto/x509/t_crl.c +3 -3
- data/third_party/boringssl-with-bazel/src/crypto/x509/t_x509.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_cmp.c +7 -2
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_ext.c +21 -18
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_obj.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c +24 -3
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_trs.c +3 -3
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_txt.c +67 -67
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_v3.c +3 -3
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509_vfy.c +29 -35
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509cset.c +13 -2
- data/third_party/boringssl-with-bazel/src/crypto/x509/x509name.c +9 -8
- data/third_party/boringssl-with-bazel/src/crypto/x509/x_all.c +10 -10
- data/third_party/boringssl-with-bazel/src/crypto/x509/x_crl.c +2 -2
- data/third_party/boringssl-with-bazel/src/crypto/x509/x_name.c +28 -40
- data/third_party/boringssl-with-bazel/src/crypto/x509/x_x509.c +3 -1
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/ext_dat.h +1 -4
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_conf.c +7 -3
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_genn.c +2 -2
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_info.c +1 -1
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_purp.c +55 -8
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_skey.c +1 -1
- data/third_party/boringssl-with-bazel/src/include/openssl/asn1.h +0 -1
- data/third_party/boringssl-with-bazel/src/include/openssl/base.h +1 -1
- data/third_party/boringssl-with-bazel/src/include/openssl/cipher.h +6 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/crypto.h +1 -1
- data/third_party/boringssl-with-bazel/src/include/openssl/dh.h +12 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/digest.h +9 -0
- data/third_party/boringssl-with-bazel/src/include/openssl/evp.h +4 -1
- data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +9 -2
- data/third_party/boringssl-with-bazel/src/include/openssl/trust_token.h +26 -6
- data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +188 -78
- data/third_party/boringssl-with-bazel/src/include/openssl/x509v3.h +52 -43
- data/third_party/boringssl-with-bazel/src/ssl/handshake.cc +18 -18
- data/third_party/boringssl-with-bazel/src/ssl/handshake_client.cc +2 -3
- data/third_party/boringssl-with-bazel/src/ssl/handshake_server.cc +1 -1
- data/third_party/boringssl-with-bazel/src/ssl/internal.h +9 -9
- data/third_party/boringssl-with-bazel/src/ssl/ssl_cipher.cc +8 -9
- data/third_party/boringssl-with-bazel/src/ssl/tls13_both.cc +1 -2
- data/third_party/boringssl-with-bazel/src/ssl/tls13_client.cc +4 -8
- data/third_party/boringssl-with-bazel/src/ssl/tls13_server.cc +2 -2
- metadata +72 -42
- data/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc +0 -537
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc +0 -1141
- data/src/core/ext/upb-generated/gogoproto/gogo.upb.c +0 -17
- data/src/core/ext/upb-generated/gogoproto/gogo.upb.h +0 -29
- data/src/core/ext/xds/xds_channel.h +0 -46
- data/src/core/ext/xds/xds_channel_secure.cc +0 -103
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_pku.c +0 -110
- data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_sxnet.c +0 -274
@@ -23,7 +23,9 @@
|
|
23
23
|
#include <string.h>
|
24
24
|
|
25
25
|
#include "absl/container/inlined_vector.h"
|
26
|
+
#include "absl/strings/str_cat.h"
|
26
27
|
#include "absl/strings/str_format.h"
|
28
|
+
#include "absl/strings/str_join.h"
|
27
29
|
|
28
30
|
#include "src/core/lib/gpr/string.h"
|
29
31
|
|
@@ -126,6 +128,7 @@ grpc_error* ParseLoadBalancingConfigHelper(
|
|
126
128
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("type should be array");
|
127
129
|
}
|
128
130
|
// Find the first LB policy that this client supports.
|
131
|
+
std::vector<absl::string_view> policies_tried;
|
129
132
|
for (const Json& lb_config : lb_config_array.array_value()) {
|
130
133
|
if (lb_config.type() != Json::Type::OBJECT) {
|
131
134
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
@@ -149,8 +152,12 @@ grpc_error* ParseLoadBalancingConfigHelper(
|
|
149
152
|
*result = it;
|
150
153
|
return GRPC_ERROR_NONE;
|
151
154
|
}
|
155
|
+
policies_tried.push_back(it->first);
|
152
156
|
}
|
153
|
-
return
|
157
|
+
return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
|
158
|
+
absl::StrCat("No known policies in list: ",
|
159
|
+
absl::StrJoin(policies_tried, " "))
|
160
|
+
.c_str());
|
154
161
|
}
|
155
162
|
|
156
163
|
} // namespace
|
@@ -352,7 +352,7 @@ void AresDnsResolver::OnResolvedLocked(grpc_error* error) {
|
|
352
352
|
GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s",
|
353
353
|
this, service_config_string.c_str());
|
354
354
|
result.service_config = ServiceConfig::Create(
|
355
|
-
service_config_string, &result.service_config_error);
|
355
|
+
channel_args_, service_config_string, &result.service_config_error);
|
356
356
|
}
|
357
357
|
}
|
358
358
|
absl::InlinedVector<grpc_arg, 1> new_args;
|
@@ -18,18 +18,25 @@
|
|
18
18
|
|
19
19
|
#include <grpc/support/port_platform.h>
|
20
20
|
|
21
|
+
#include "absl/strings/match.h"
|
21
22
|
#include "absl/strings/str_join.h"
|
23
|
+
#include "absl/strings/str_split.h"
|
24
|
+
#include "re2/re2.h"
|
22
25
|
|
23
26
|
#include "src/core/ext/filters/client_channel/config_selector.h"
|
24
27
|
#include "src/core/ext/filters/client_channel/resolver_registry.h"
|
25
28
|
#include "src/core/ext/xds/xds_client.h"
|
26
29
|
#include "src/core/lib/channel/channel_args.h"
|
30
|
+
#include "src/core/lib/iomgr/closure.h"
|
31
|
+
#include "src/core/lib/iomgr/exec_ctx.h"
|
27
32
|
#include "src/core/lib/transport/timeout_encoding.h"
|
28
33
|
|
29
34
|
namespace grpc_core {
|
30
35
|
|
31
36
|
TraceFlag grpc_xds_resolver_trace(false, "xds_resolver");
|
32
37
|
|
38
|
+
const char* kXdsClusterAttribute = "xds_cluster_name";
|
39
|
+
|
33
40
|
namespace {
|
34
41
|
|
35
42
|
//
|
@@ -42,8 +49,7 @@ class XdsResolver : public Resolver {
|
|
42
49
|
: Resolver(std::move(args.work_serializer),
|
43
50
|
std::move(args.result_handler)),
|
44
51
|
args_(grpc_channel_args_copy(args.args)),
|
45
|
-
interested_parties_(args.pollset_set)
|
46
|
-
config_selector_(MakeRefCounted<XdsConfigSelector>()) {
|
52
|
+
interested_parties_(args.pollset_set) {
|
47
53
|
char* path = args.uri->path;
|
48
54
|
if (path[0] == '/') ++path;
|
49
55
|
server_name_ = path;
|
@@ -62,124 +68,443 @@ class XdsResolver : public Resolver {
|
|
62
68
|
|
63
69
|
void StartLocked() override;
|
64
70
|
|
65
|
-
void ShutdownLocked() override
|
66
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
|
67
|
-
gpr_log(GPR_INFO, "[xds_resolver %p] shutting down", this);
|
68
|
-
}
|
69
|
-
xds_client_.reset();
|
70
|
-
}
|
71
|
+
void ShutdownLocked() override;
|
71
72
|
|
72
73
|
private:
|
74
|
+
class Notifier {
|
75
|
+
public:
|
76
|
+
Notifier(RefCountedPtr<XdsResolver> resolver, XdsApi::LdsUpdate update);
|
77
|
+
Notifier(RefCountedPtr<XdsResolver> resolver, XdsApi::RdsUpdate update);
|
78
|
+
Notifier(RefCountedPtr<XdsResolver> resolver, grpc_error* error);
|
79
|
+
explicit Notifier(RefCountedPtr<XdsResolver> resolver);
|
80
|
+
|
81
|
+
private:
|
82
|
+
enum Type { kLdsUpdate, kRdsUpdate, kError, kDoesNotExist };
|
83
|
+
|
84
|
+
static void RunInExecCtx(void* arg, grpc_error* error);
|
85
|
+
void RunInWorkSerializer(grpc_error* error);
|
86
|
+
|
87
|
+
RefCountedPtr<XdsResolver> resolver_;
|
88
|
+
grpc_closure closure_;
|
89
|
+
XdsApi::LdsUpdate update_;
|
90
|
+
Type type_;
|
91
|
+
};
|
92
|
+
|
73
93
|
class ListenerWatcher : public XdsClient::ListenerWatcherInterface {
|
74
94
|
public:
|
75
95
|
explicit ListenerWatcher(RefCountedPtr<XdsResolver> resolver)
|
76
96
|
: resolver_(std::move(resolver)) {}
|
77
|
-
void OnListenerChanged(
|
78
|
-
|
79
|
-
|
97
|
+
void OnListenerChanged(XdsApi::LdsUpdate listener) override {
|
98
|
+
new Notifier(resolver_, std::move(listener));
|
99
|
+
}
|
100
|
+
void OnError(grpc_error* error) override { new Notifier(resolver_, error); }
|
101
|
+
void OnResourceDoesNotExist() override { new Notifier(resolver_); }
|
80
102
|
|
81
103
|
private:
|
82
104
|
RefCountedPtr<XdsResolver> resolver_;
|
83
105
|
};
|
84
106
|
|
85
|
-
class
|
107
|
+
class RouteConfigWatcher : public XdsClient::RouteConfigWatcherInterface {
|
86
108
|
public:
|
87
|
-
|
88
|
-
|
109
|
+
explicit RouteConfigWatcher(RefCountedPtr<XdsResolver> resolver)
|
110
|
+
: resolver_(std::move(resolver)) {}
|
111
|
+
void OnRouteConfigChanged(XdsApi::RdsUpdate route_config) override {
|
112
|
+
new Notifier(resolver_, std::move(route_config));
|
89
113
|
}
|
114
|
+
void OnError(grpc_error* error) override { new Notifier(resolver_, error); }
|
115
|
+
void OnResourceDoesNotExist() override { new Notifier(resolver_); }
|
116
|
+
|
117
|
+
private:
|
118
|
+
RefCountedPtr<XdsResolver> resolver_;
|
119
|
+
};
|
120
|
+
|
121
|
+
class ClusterState
|
122
|
+
: public RefCounted<ClusterState, PolymorphicRefCount, false> {
|
123
|
+
public:
|
124
|
+
using ClusterStateMap =
|
125
|
+
std::map<std::string, std::unique_ptr<ClusterState>>;
|
126
|
+
|
127
|
+
ClusterState(const std::string& cluster_name,
|
128
|
+
ClusterStateMap* cluster_state_map)
|
129
|
+
: it_(cluster_state_map
|
130
|
+
->emplace(cluster_name, std::unique_ptr<ClusterState>(this))
|
131
|
+
.first) {}
|
132
|
+
const std::string& cluster() const { return it_->first; }
|
133
|
+
|
134
|
+
private:
|
135
|
+
ClusterStateMap::iterator it_;
|
90
136
|
};
|
91
137
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
138
|
+
class XdsConfigSelector : public ConfigSelector {
|
139
|
+
public:
|
140
|
+
XdsConfigSelector(RefCountedPtr<XdsResolver> resolver,
|
141
|
+
const std::vector<XdsApi::Route>& routes);
|
142
|
+
~XdsConfigSelector();
|
143
|
+
|
144
|
+
const char* name() const override { return "XdsConfigSelector"; }
|
145
|
+
|
146
|
+
bool Equals(const ConfigSelector* other) const override {
|
147
|
+
const auto* other_xds = static_cast<const XdsConfigSelector*>(other);
|
148
|
+
// Don't need to compare resolver_, since that will always be the same.
|
149
|
+
return route_table_ == other_xds->route_table_ &&
|
150
|
+
clusters_ == other_xds->clusters_;
|
151
|
+
}
|
152
|
+
|
153
|
+
CallConfig GetCallConfig(GetCallConfigArgs args) override;
|
154
|
+
|
155
|
+
private:
|
156
|
+
struct Route {
|
157
|
+
XdsApi::Route route;
|
158
|
+
absl::InlinedVector<std::pair<uint32_t, absl::string_view>, 2>
|
159
|
+
weighted_cluster_state;
|
160
|
+
bool operator==(const Route& other) const {
|
161
|
+
return route == other.route &&
|
162
|
+
weighted_cluster_state == other.weighted_cluster_state;
|
163
|
+
}
|
164
|
+
};
|
165
|
+
using RouteTable = std::vector<Route>;
|
166
|
+
|
167
|
+
void MaybeAddCluster(const std::string& name);
|
168
|
+
|
169
|
+
RefCountedPtr<XdsResolver> resolver_;
|
170
|
+
RouteTable route_table_;
|
171
|
+
std::map<absl::string_view, RefCountedPtr<ClusterState>> clusters_;
|
172
|
+
};
|
96
173
|
|
97
|
-
|
98
|
-
|
99
|
-
void
|
174
|
+
void OnListenerUpdate(XdsApi::LdsUpdate listener);
|
175
|
+
void OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update);
|
176
|
+
void OnError(grpc_error* error);
|
177
|
+
void OnResourceDoesNotExist();
|
100
178
|
|
101
|
-
|
102
|
-
|
103
|
-
|
179
|
+
grpc_error* CreateServiceConfig(RefCountedPtr<ServiceConfig>* service_config);
|
180
|
+
void GenerateResult();
|
181
|
+
void MaybeRemoveUnusedClusters();
|
104
182
|
|
105
183
|
std::string server_name_;
|
106
184
|
const grpc_channel_args* args_;
|
107
185
|
grpc_pollset_set* interested_parties_;
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
struct ClusterNamesInfo {
|
115
|
-
uint64_t next_index = 0;
|
116
|
-
std::map<std::string /*cluster names + weights*/,
|
117
|
-
uint64_t /*policy index number*/>
|
118
|
-
cluster_weights_map;
|
119
|
-
};
|
120
|
-
using WeightedClusterIndexMap =
|
121
|
-
std::map<std::string /*cluster names*/, ClusterNamesInfo>;
|
122
|
-
|
123
|
-
// Cache of action names for WeightedCluster targets in the current
|
124
|
-
// service config.
|
125
|
-
WeightedClusterIndexMap weighted_cluster_index_map_;
|
186
|
+
RefCountedPtr<XdsClient> xds_client_;
|
187
|
+
XdsClient::ListenerWatcherInterface* listener_watcher_ = nullptr;
|
188
|
+
std::string route_config_name_;
|
189
|
+
XdsClient::RouteConfigWatcherInterface* route_config_watcher_ = nullptr;
|
190
|
+
ClusterState::ClusterStateMap cluster_state_map_;
|
191
|
+
std::vector<XdsApi::Route> current_update_;
|
126
192
|
};
|
127
193
|
|
128
194
|
//
|
129
|
-
// XdsResolver::
|
195
|
+
// XdsResolver::Notifier
|
130
196
|
//
|
131
197
|
|
132
|
-
|
133
|
-
|
134
|
-
|
198
|
+
XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver,
|
199
|
+
XdsApi::LdsUpdate update)
|
200
|
+
: resolver_(std::move(resolver)),
|
201
|
+
update_(std::move(update)),
|
202
|
+
type_(kLdsUpdate) {
|
203
|
+
GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
|
204
|
+
ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
|
205
|
+
}
|
206
|
+
|
207
|
+
XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver,
|
208
|
+
XdsApi::RdsUpdate update)
|
209
|
+
: resolver_(std::move(resolver)), type_(kRdsUpdate) {
|
210
|
+
update_.rds_update = std::move(update);
|
211
|
+
GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
|
212
|
+
ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
|
213
|
+
}
|
214
|
+
|
215
|
+
XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver,
|
216
|
+
grpc_error* error)
|
217
|
+
: resolver_(std::move(resolver)), type_(kError) {
|
218
|
+
GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
|
219
|
+
ExecCtx::Run(DEBUG_LOCATION, &closure_, error);
|
220
|
+
}
|
221
|
+
|
222
|
+
XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver)
|
223
|
+
: resolver_(std::move(resolver)), type_(kDoesNotExist) {
|
224
|
+
GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
|
225
|
+
ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
|
226
|
+
}
|
227
|
+
|
228
|
+
void XdsResolver::Notifier::RunInExecCtx(void* arg, grpc_error* error) {
|
229
|
+
Notifier* self = static_cast<Notifier*>(arg);
|
230
|
+
GRPC_ERROR_REF(error);
|
231
|
+
self->resolver_->work_serializer()->Run(
|
232
|
+
[self, error]() { self->RunInWorkSerializer(error); }, DEBUG_LOCATION);
|
233
|
+
}
|
234
|
+
|
235
|
+
void XdsResolver::Notifier::RunInWorkSerializer(grpc_error* error) {
|
236
|
+
if (resolver_->xds_client_ == nullptr) {
|
237
|
+
GRPC_ERROR_UNREF(error);
|
238
|
+
delete this;
|
239
|
+
return;
|
240
|
+
}
|
241
|
+
switch (type_) {
|
242
|
+
case kLdsUpdate:
|
243
|
+
resolver_->OnListenerUpdate(std::move(update_));
|
244
|
+
break;
|
245
|
+
case kRdsUpdate:
|
246
|
+
resolver_->OnRouteConfigUpdate(std::move(*update_.rds_update));
|
247
|
+
break;
|
248
|
+
case kError:
|
249
|
+
resolver_->OnError(error);
|
250
|
+
break;
|
251
|
+
case kDoesNotExist:
|
252
|
+
resolver_->OnResourceDoesNotExist();
|
253
|
+
break;
|
254
|
+
};
|
255
|
+
delete this;
|
256
|
+
}
|
257
|
+
|
258
|
+
//
|
259
|
+
// XdsResolver::XdsConfigSelector
|
260
|
+
//
|
261
|
+
|
262
|
+
XdsResolver::XdsConfigSelector::XdsConfigSelector(
|
263
|
+
RefCountedPtr<XdsResolver> resolver,
|
264
|
+
const std::vector<XdsApi::Route>& routes)
|
265
|
+
: resolver_(std::move(resolver)) {
|
135
266
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
|
136
|
-
gpr_log(GPR_INFO, "[xds_resolver %p]
|
137
|
-
resolver_.get());
|
267
|
+
gpr_log(GPR_INFO, "[xds_resolver %p] creating XdsConfigSelector %p",
|
268
|
+
resolver_.get(), this);
|
138
269
|
}
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
270
|
+
// 1. Construct the route table
|
271
|
+
// 2 Update resolver's cluster state map
|
272
|
+
// 3. Construct cluster list to hold on to entries in the cluster state
|
273
|
+
// map.
|
274
|
+
// Reserve the necessary entries up-front to avoid reallocation as we add
|
275
|
+
// elements. This is necessary because the string_view in the entry's
|
276
|
+
// weighted_cluster_state field points to the memory in the route field, so
|
277
|
+
// moving the entry in a reallocation will cause the string_view to point to
|
278
|
+
// invalid data.
|
279
|
+
route_table_.reserve(routes.size());
|
280
|
+
for (auto& route : routes) {
|
281
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
|
282
|
+
gpr_log(GPR_INFO, "[xds_resolver %p] XdsConfigSelector %p: route: %s",
|
283
|
+
resolver_.get(), this, route.ToString().c_str());
|
284
|
+
}
|
285
|
+
route_table_.emplace_back();
|
286
|
+
auto& route_entry = route_table_.back();
|
287
|
+
route_entry.route = route;
|
288
|
+
if (route.weighted_clusters.empty()) {
|
289
|
+
MaybeAddCluster(route.cluster_name);
|
290
|
+
} else {
|
291
|
+
uint32_t end = 0;
|
292
|
+
for (const auto& weighted_cluster : route_entry.route.weighted_clusters) {
|
293
|
+
MaybeAddCluster(weighted_cluster.name);
|
294
|
+
end += weighted_cluster.weight;
|
295
|
+
route_entry.weighted_cluster_state.emplace_back(end,
|
296
|
+
weighted_cluster.name);
|
297
|
+
}
|
298
|
+
}
|
145
299
|
}
|
300
|
+
}
|
301
|
+
|
302
|
+
XdsResolver::XdsConfigSelector::~XdsConfigSelector() {
|
146
303
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
|
147
|
-
gpr_log(GPR_INFO, "[xds_resolver %p]
|
148
|
-
resolver_.get(),
|
304
|
+
gpr_log(GPR_INFO, "[xds_resolver %p] destroying XdsConfigSelector %p",
|
305
|
+
resolver_.get(), this);
|
149
306
|
}
|
150
|
-
|
151
|
-
|
152
|
-
resolver_->config_selector_->MakeChannelArg(),
|
153
|
-
};
|
154
|
-
result.args = grpc_channel_args_copy_and_add(resolver_->args_, new_args,
|
155
|
-
GPR_ARRAY_SIZE(new_args));
|
156
|
-
resolver_->result_handler()->ReturnResult(std::move(result));
|
307
|
+
clusters_.clear();
|
308
|
+
resolver_->MaybeRemoveUnusedClusters();
|
157
309
|
}
|
158
310
|
|
159
|
-
void XdsResolver::
|
160
|
-
if (
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
311
|
+
void XdsResolver::XdsConfigSelector::MaybeAddCluster(const std::string& name) {
|
312
|
+
if (clusters_.find(name) == clusters_.end()) {
|
313
|
+
auto it = resolver_->cluster_state_map_.find(name);
|
314
|
+
if (it == resolver_->cluster_state_map_.end()) {
|
315
|
+
auto new_cluster_state =
|
316
|
+
MakeRefCounted<ClusterState>(name, &resolver_->cluster_state_map_);
|
317
|
+
clusters_[new_cluster_state->cluster()] = std::move(new_cluster_state);
|
318
|
+
} else {
|
319
|
+
clusters_[it->second->cluster()] = it->second->Ref();
|
320
|
+
}
|
321
|
+
}
|
169
322
|
}
|
170
323
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
324
|
+
bool PathMatch(const absl::string_view& path,
|
325
|
+
const XdsApi::Route::Matchers::PathMatcher& path_matcher) {
|
326
|
+
switch (path_matcher.type) {
|
327
|
+
case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::PREFIX:
|
328
|
+
return absl::StartsWith(path, path_matcher.string_matcher);
|
329
|
+
case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::PATH:
|
330
|
+
return path == path_matcher.string_matcher;
|
331
|
+
case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::REGEX:
|
332
|
+
return RE2::FullMatch(path.data(), *path_matcher.regex_matcher);
|
333
|
+
default:
|
334
|
+
return false;
|
335
|
+
}
|
336
|
+
}
|
337
|
+
|
338
|
+
absl::optional<absl::string_view> GetMetadataValue(
|
339
|
+
const std::string& target_key, grpc_metadata_batch* initial_metadata,
|
340
|
+
std::string* concatenated_value) {
|
341
|
+
// Find all values for the specified key.
|
342
|
+
GPR_DEBUG_ASSERT(initial_metadata != nullptr);
|
343
|
+
absl::InlinedVector<absl::string_view, 1> values;
|
344
|
+
for (grpc_linked_mdelem* md = initial_metadata->list.head; md != nullptr;
|
345
|
+
md = md->next) {
|
346
|
+
absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md->md));
|
347
|
+
absl::string_view value = StringViewFromSlice(GRPC_MDVALUE(md->md));
|
348
|
+
if (target_key == key) values.push_back(value);
|
349
|
+
}
|
350
|
+
// If none found, no match.
|
351
|
+
if (values.empty()) return absl::nullopt;
|
352
|
+
// If exactly one found, return it as-is.
|
353
|
+
if (values.size() == 1) return values.front();
|
354
|
+
// If more than one found, concatenate the values, using
|
355
|
+
// *concatenated_values as a temporary holding place for the
|
356
|
+
// concatenated string.
|
357
|
+
*concatenated_value = absl::StrJoin(values, ",");
|
358
|
+
return *concatenated_value;
|
359
|
+
}
|
360
|
+
|
361
|
+
bool HeaderMatchHelper(
|
362
|
+
const XdsApi::Route::Matchers::HeaderMatcher& header_matcher,
|
363
|
+
grpc_metadata_batch* initial_metadata) {
|
364
|
+
std::string concatenated_value;
|
365
|
+
absl::optional<absl::string_view> value;
|
366
|
+
// Note: If we ever allow binary headers here, we still need to
|
367
|
+
// special-case ignore "grpc-tags-bin" and "grpc-trace-bin", since
|
368
|
+
// they are not visible to the LB policy in grpc-go.
|
369
|
+
if (absl::EndsWith(header_matcher.name, "-bin") ||
|
370
|
+
header_matcher.name == "grpc-previous-rpc-attempts") {
|
371
|
+
value = absl::nullopt;
|
372
|
+
} else if (header_matcher.name == "content-type") {
|
373
|
+
value = "application/grpc";
|
374
|
+
} else {
|
375
|
+
value = GetMetadataValue(header_matcher.name, initial_metadata,
|
376
|
+
&concatenated_value);
|
377
|
+
}
|
378
|
+
if (!value.has_value()) {
|
379
|
+
if (header_matcher.type ==
|
380
|
+
XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::PRESENT) {
|
381
|
+
return !header_matcher.present_match;
|
382
|
+
} else {
|
383
|
+
// For all other header matcher types, we need the header value to
|
384
|
+
// exist to consider matches.
|
385
|
+
return false;
|
386
|
+
}
|
387
|
+
}
|
388
|
+
switch (header_matcher.type) {
|
389
|
+
case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::EXACT:
|
390
|
+
return value.value() == header_matcher.string_matcher;
|
391
|
+
case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::REGEX:
|
392
|
+
return RE2::FullMatch(value.value().data(), *header_matcher.regex_match);
|
393
|
+
case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::RANGE:
|
394
|
+
int64_t int_value;
|
395
|
+
if (!absl::SimpleAtoi(value.value(), &int_value)) {
|
396
|
+
return false;
|
397
|
+
}
|
398
|
+
return int_value >= header_matcher.range_start &&
|
399
|
+
int_value < header_matcher.range_end;
|
400
|
+
case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::PREFIX:
|
401
|
+
return absl::StartsWith(value.value(), header_matcher.string_matcher);
|
402
|
+
case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::SUFFIX:
|
403
|
+
return absl::EndsWith(value.value(), header_matcher.string_matcher);
|
404
|
+
default:
|
405
|
+
return false;
|
406
|
+
}
|
407
|
+
}
|
408
|
+
|
409
|
+
bool HeadersMatch(
|
410
|
+
const std::vector<XdsApi::Route::Matchers::HeaderMatcher>& header_matchers,
|
411
|
+
grpc_metadata_batch* initial_metadata) {
|
412
|
+
for (const auto& header_matcher : header_matchers) {
|
413
|
+
bool match = HeaderMatchHelper(header_matcher, initial_metadata);
|
414
|
+
if (header_matcher.invert_match) match = !match;
|
415
|
+
if (!match) return false;
|
416
|
+
}
|
417
|
+
return true;
|
418
|
+
}
|
419
|
+
|
420
|
+
bool UnderFraction(const uint32_t fraction_per_million) {
|
421
|
+
// Generate a random number in [0, 1000000).
|
422
|
+
const uint32_t random_number = rand() % 1000000;
|
423
|
+
return random_number < fraction_per_million;
|
424
|
+
}
|
425
|
+
|
426
|
+
ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
|
427
|
+
GetCallConfigArgs args) {
|
428
|
+
for (const auto& entry : route_table_) {
|
429
|
+
// Path matching.
|
430
|
+
if (!PathMatch(StringViewFromSlice(*args.path),
|
431
|
+
entry.route.matchers.path_matcher)) {
|
432
|
+
continue;
|
433
|
+
}
|
434
|
+
// Header Matching.
|
435
|
+
if (!HeadersMatch(entry.route.matchers.header_matchers,
|
436
|
+
args.initial_metadata)) {
|
437
|
+
continue;
|
438
|
+
}
|
439
|
+
// Match fraction check
|
440
|
+
if (entry.route.matchers.fraction_per_million.has_value() &&
|
441
|
+
!UnderFraction(entry.route.matchers.fraction_per_million.value())) {
|
442
|
+
continue;
|
443
|
+
}
|
444
|
+
// Found a route match
|
445
|
+
absl::string_view cluster_name;
|
446
|
+
if (entry.route.weighted_clusters.empty()) {
|
447
|
+
cluster_name = entry.route.cluster_name;
|
448
|
+
} else {
|
449
|
+
const uint32_t key =
|
450
|
+
rand() %
|
451
|
+
entry.weighted_cluster_state[entry.weighted_cluster_state.size() - 1]
|
452
|
+
.first;
|
453
|
+
// Find the index in weighted clusters corresponding to key.
|
454
|
+
size_t mid = 0;
|
455
|
+
size_t start_index = 0;
|
456
|
+
size_t end_index = entry.weighted_cluster_state.size() - 1;
|
457
|
+
size_t index = 0;
|
458
|
+
while (end_index > start_index) {
|
459
|
+
mid = (start_index + end_index) / 2;
|
460
|
+
if (entry.weighted_cluster_state[mid].first > key) {
|
461
|
+
end_index = mid;
|
462
|
+
} else if (entry.weighted_cluster_state[mid].first < key) {
|
463
|
+
start_index = mid + 1;
|
464
|
+
} else {
|
465
|
+
index = mid + 1;
|
466
|
+
break;
|
467
|
+
}
|
468
|
+
}
|
469
|
+
if (index == 0) index = start_index;
|
470
|
+
GPR_ASSERT(entry.weighted_cluster_state[index].first > key);
|
471
|
+
cluster_name = entry.weighted_cluster_state[index].second;
|
472
|
+
}
|
473
|
+
auto it = clusters_.find(cluster_name);
|
474
|
+
GPR_ASSERT(it != clusters_.end());
|
475
|
+
XdsResolver* resolver =
|
476
|
+
static_cast<XdsResolver*>(resolver_->Ref().release());
|
477
|
+
ClusterState* cluster_state = it->second->Ref().release();
|
478
|
+
CallConfig call_config;
|
479
|
+
call_config.call_attributes[kXdsClusterAttribute] = it->first;
|
480
|
+
call_config.on_call_committed = [resolver, cluster_state]() {
|
481
|
+
cluster_state->Unref();
|
482
|
+
ExecCtx::Run(
|
483
|
+
// TODO(roth): This hop into the ExecCtx is being done to avoid
|
484
|
+
// entering the WorkSerializer while holding the client channel data
|
485
|
+
// plane mutex, since that can lead to deadlocks. However, we should
|
486
|
+
// not have to solve this problem in each individual ConfigSelector
|
487
|
+
// implementation. When we have time, we should fix the client channel
|
488
|
+
// code to avoid this by not invoking the
|
489
|
+
// CallConfig::on_call_committed callback until after it has released
|
490
|
+
// the data plane mutex.
|
491
|
+
DEBUG_LOCATION,
|
492
|
+
GRPC_CLOSURE_CREATE(
|
493
|
+
[](void* arg, grpc_error* /*error*/) {
|
494
|
+
auto* resolver = static_cast<XdsResolver*>(arg);
|
495
|
+
resolver->work_serializer()->Run(
|
496
|
+
[resolver]() {
|
497
|
+
resolver->MaybeRemoveUnusedClusters();
|
498
|
+
resolver->Unref();
|
499
|
+
},
|
500
|
+
DEBUG_LOCATION);
|
501
|
+
},
|
502
|
+
resolver, nullptr),
|
503
|
+
GRPC_ERROR_NONE);
|
504
|
+
};
|
505
|
+
return call_config;
|
506
|
+
}
|
507
|
+
return CallConfig();
|
183
508
|
}
|
184
509
|
|
185
510
|
//
|
@@ -188,320 +513,190 @@ void XdsResolver::ListenerWatcher::OnResourceDoesNotExist() {
|
|
188
513
|
|
189
514
|
void XdsResolver::StartLocked() {
|
190
515
|
grpc_error* error = GRPC_ERROR_NONE;
|
191
|
-
xds_client_ =
|
192
|
-
work_serializer(), interested_parties_, server_name_,
|
193
|
-
absl::make_unique<ListenerWatcher>(Ref()), *args_, &error);
|
516
|
+
xds_client_ = XdsClient::GetOrCreate(&error);
|
194
517
|
if (error != GRPC_ERROR_NONE) {
|
195
518
|
gpr_log(GPR_ERROR,
|
196
519
|
"Failed to create xds client -- channel will remain in "
|
197
520
|
"TRANSIENT_FAILURE: %s",
|
198
521
|
grpc_error_string(error));
|
199
522
|
result_handler()->ReturnError(error);
|
523
|
+
return;
|
524
|
+
}
|
525
|
+
grpc_pollset_set_add_pollset_set(xds_client_->interested_parties(),
|
526
|
+
interested_parties_);
|
527
|
+
channelz::ChannelNode* parent_channelz_node =
|
528
|
+
grpc_channel_args_find_pointer<channelz::ChannelNode>(
|
529
|
+
args_, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
|
530
|
+
if (parent_channelz_node != nullptr) {
|
531
|
+
xds_client_->AddChannelzLinkage(parent_channelz_node);
|
200
532
|
}
|
533
|
+
auto watcher = absl::make_unique<ListenerWatcher>(Ref());
|
534
|
+
listener_watcher_ = watcher.get();
|
535
|
+
xds_client_->WatchListenerData(server_name_, std::move(watcher));
|
201
536
|
}
|
202
537
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
538
|
+
void XdsResolver::ShutdownLocked() {
|
539
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
|
540
|
+
gpr_log(GPR_INFO, "[xds_resolver %p] shutting down", this);
|
541
|
+
}
|
542
|
+
if (xds_client_ != nullptr) {
|
543
|
+
if (listener_watcher_ != nullptr) {
|
544
|
+
xds_client_->CancelListenerDataWatch(server_name_, listener_watcher_,
|
545
|
+
/*delay_unsubscription=*/false);
|
546
|
+
}
|
547
|
+
if (route_config_watcher_ != nullptr) {
|
548
|
+
xds_client_->CancelRouteConfigDataWatch(
|
549
|
+
server_name_, route_config_watcher_, /*delay_unsubscription=*/false);
|
550
|
+
}
|
551
|
+
channelz::ChannelNode* parent_channelz_node =
|
552
|
+
grpc_channel_args_find_pointer<channelz::ChannelNode>(
|
553
|
+
args_, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
|
554
|
+
if (parent_channelz_node != nullptr) {
|
555
|
+
xds_client_->RemoveChannelzLinkage(parent_channelz_node);
|
556
|
+
}
|
557
|
+
grpc_pollset_set_del_pollset_set(xds_client_->interested_parties(),
|
558
|
+
interested_parties_);
|
559
|
+
xds_client_.reset();
|
560
|
+
}
|
213
561
|
}
|
214
562
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::REGEX:
|
226
|
-
header_matcher = absl::StrFormat(" \"regex_match\": \"%s\"",
|
227
|
-
header.regex_match->pattern());
|
228
|
-
break;
|
229
|
-
case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::RANGE:
|
230
|
-
header_matcher = absl::StrFormat(
|
231
|
-
" \"range_match\":{\n"
|
232
|
-
" \"start\":%d,\n"
|
233
|
-
" \"end\":%d\n"
|
234
|
-
" }",
|
235
|
-
header.range_start, header.range_end);
|
236
|
-
break;
|
237
|
-
case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::PRESENT:
|
238
|
-
header_matcher =
|
239
|
-
absl::StrFormat(" \"present_match\": %s",
|
240
|
-
header.present_match ? "true" : "false");
|
241
|
-
break;
|
242
|
-
case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::PREFIX:
|
243
|
-
header_matcher = absl::StrFormat(
|
244
|
-
" \"prefix_match\": \"%s\"", header.string_matcher);
|
245
|
-
break;
|
246
|
-
case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::SUFFIX:
|
247
|
-
header_matcher = absl::StrFormat(
|
248
|
-
" \"suffix_match\": \"%s\"", header.string_matcher);
|
249
|
-
break;
|
250
|
-
default:
|
251
|
-
break;
|
563
|
+
void XdsResolver::OnListenerUpdate(XdsApi::LdsUpdate listener) {
|
564
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
|
565
|
+
gpr_log(GPR_INFO, "[xds_resolver %p] received updated listener data", this);
|
566
|
+
}
|
567
|
+
if (listener.route_config_name != route_config_name_) {
|
568
|
+
if (route_config_watcher_ != nullptr) {
|
569
|
+
xds_client_->CancelRouteConfigDataWatch(
|
570
|
+
route_config_name_, route_config_watcher_,
|
571
|
+
/*delay_unsubscription=*/!listener.route_config_name.empty());
|
572
|
+
route_config_watcher_ = nullptr;
|
252
573
|
}
|
253
|
-
std::
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
header_parts.push_back(header_matcher);
|
259
|
-
if (header.invert_match) {
|
260
|
-
header_parts.push_back(
|
261
|
-
absl::StrFormat(",\n"
|
262
|
-
" \"invert_match\": true"));
|
574
|
+
route_config_name_ = std::move(listener.route_config_name);
|
575
|
+
if (!route_config_name_.empty()) {
|
576
|
+
auto watcher = absl::make_unique<RouteConfigWatcher>(Ref());
|
577
|
+
route_config_watcher_ = watcher.get();
|
578
|
+
xds_client_->WatchRouteConfigData(route_config_name_, std::move(watcher));
|
263
579
|
}
|
264
|
-
header_parts.push_back(
|
265
|
-
absl::StrFormat("\n"
|
266
|
-
" }"));
|
267
|
-
headers.push_back(absl::StrJoin(header_parts, ""));
|
268
580
|
}
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
headers_service_config.push_back(absl::StrJoin(headers, ","));
|
273
|
-
headers_service_config.push_back(" ],\n");
|
581
|
+
if (route_config_name_.empty()) {
|
582
|
+
GPR_ASSERT(listener.rds_update.has_value());
|
583
|
+
OnRouteConfigUpdate(std::move(*listener.rds_update));
|
274
584
|
}
|
275
|
-
std::string path_match_str;
|
276
|
-
switch (route.matchers.path_matcher.type) {
|
277
|
-
case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::PREFIX:
|
278
|
-
path_match_str = absl::StrFormat(
|
279
|
-
"\"prefix\": \"%s\",\n", route.matchers.path_matcher.string_matcher);
|
280
|
-
break;
|
281
|
-
case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::PATH:
|
282
|
-
path_match_str = absl::StrFormat(
|
283
|
-
"\"path\": \"%s\",\n", route.matchers.path_matcher.string_matcher);
|
284
|
-
break;
|
285
|
-
case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::REGEX:
|
286
|
-
path_match_str =
|
287
|
-
absl::StrFormat("\"regex\": \"%s\",\n",
|
288
|
-
route.matchers.path_matcher.regex_matcher->pattern());
|
289
|
-
break;
|
290
|
-
}
|
291
|
-
return absl::StrFormat(
|
292
|
-
" { \n"
|
293
|
-
" %s"
|
294
|
-
" %s"
|
295
|
-
" %s"
|
296
|
-
" \"action\": \"%s\"\n"
|
297
|
-
" }",
|
298
|
-
path_match_str, absl::StrJoin(headers_service_config, ""),
|
299
|
-
route.matchers.fraction_per_million.has_value()
|
300
|
-
? absl::StrFormat("\"match_fraction\":%d,\n",
|
301
|
-
route.matchers.fraction_per_million.value())
|
302
|
-
: "",
|
303
|
-
action_name);
|
304
585
|
}
|
305
586
|
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
const std::vector<XdsApi::Route::ClusterWeight>& clusters) {
|
310
|
-
std::vector<std::string> config_parts;
|
311
|
-
config_parts.push_back(
|
312
|
-
absl::StrFormat(" \"weighted:%s\":{\n"
|
313
|
-
" \"childPolicy\":[ {\n"
|
314
|
-
" \"weighted_target_experimental\":{\n"
|
315
|
-
" \"targets\":{\n",
|
316
|
-
name));
|
317
|
-
std::vector<std::string> weighted_targets;
|
318
|
-
weighted_targets.reserve(clusters.size());
|
319
|
-
for (const auto& cluster_weight : clusters) {
|
320
|
-
weighted_targets.push_back(absl::StrFormat(
|
321
|
-
" \"%s\":{\n"
|
322
|
-
" \"weight\":%d,\n"
|
323
|
-
" \"childPolicy\":[ {\n"
|
324
|
-
" \"cds_experimental\":{\n"
|
325
|
-
" \"cluster\": \"%s\"\n"
|
326
|
-
" }\n"
|
327
|
-
" } ]\n"
|
328
|
-
" }",
|
329
|
-
cluster_weight.name, cluster_weight.weight, cluster_weight.name));
|
587
|
+
void XdsResolver::OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update) {
|
588
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
|
589
|
+
gpr_log(GPR_INFO, "[xds_resolver %p] received updated route config", this);
|
330
590
|
}
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
struct WeightedClustersKeys {
|
341
|
-
std::string cluster_names_key;
|
342
|
-
std::string cluster_weights_key;
|
343
|
-
};
|
344
|
-
|
345
|
-
// Returns the cluster names and weights key or the cluster names only key.
|
346
|
-
WeightedClustersKeys GetWeightedClustersKey(
|
347
|
-
const std::vector<XdsApi::Route::ClusterWeight>& weighted_clusters) {
|
348
|
-
std::set<std::string> cluster_names;
|
349
|
-
std::set<std::string> cluster_weights;
|
350
|
-
for (const auto& cluster_weight : weighted_clusters) {
|
351
|
-
cluster_names.emplace(absl::StrFormat("%s", cluster_weight.name));
|
352
|
-
cluster_weights.emplace(
|
353
|
-
absl::StrFormat("%s_%d", cluster_weight.name, cluster_weight.weight));
|
591
|
+
// Find the relevant VirtualHost from the RouteConfiguration.
|
592
|
+
XdsApi::RdsUpdate::VirtualHost* vhost =
|
593
|
+
rds_update.FindVirtualHostForDomain(server_name_);
|
594
|
+
if (vhost == nullptr) {
|
595
|
+
OnError(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
|
596
|
+
absl::StrCat("could not find VirtualHost for ", server_name_,
|
597
|
+
" in RouteConfiguration")
|
598
|
+
.c_str()));
|
599
|
+
return;
|
354
600
|
}
|
355
|
-
|
356
|
-
|
601
|
+
// Save the list of routes in the resolver.
|
602
|
+
current_update_ = std::move(vhost->routes);
|
603
|
+
// Send a new result to the channel.
|
604
|
+
GenerateResult();
|
357
605
|
}
|
358
606
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
cluster_names_map_it->second.cluster_weights_map;
|
367
|
-
auto cluster_weights_map_it =
|
368
|
-
cluster_weights_map.find(keys.cluster_weights_key);
|
369
|
-
GPR_ASSERT(cluster_weights_map_it != cluster_weights_map.end());
|
370
|
-
return absl::StrFormat("%s_%d", keys.cluster_names_key,
|
371
|
-
cluster_weights_map_it->second);
|
607
|
+
void XdsResolver::OnError(grpc_error* error) {
|
608
|
+
gpr_log(GPR_ERROR, "[xds_resolver %p] received error from XdsClient: %s",
|
609
|
+
this, grpc_error_string(error));
|
610
|
+
Result result;
|
611
|
+
result.args = grpc_channel_args_copy(args_);
|
612
|
+
result.service_config_error = error;
|
613
|
+
result_handler()->ReturnResult(std::move(result));
|
372
614
|
}
|
373
615
|
|
374
|
-
void XdsResolver::
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
if (action_it == actions_to_process.end()) {
|
387
|
-
actions_to_process[std::move(keys.cluster_weights_key)] =
|
388
|
-
std::move(keys.cluster_names_key);
|
389
|
-
}
|
390
|
-
}
|
391
|
-
}
|
392
|
-
// First pass of all unique WeightedCluster actions: if the exact same
|
393
|
-
// weighted target policy (same clusters and weights) appears in the old map,
|
394
|
-
// then that old action name is taken again and should be moved to the new
|
395
|
-
// map; any other action names from the old set of actions are candidates for
|
396
|
-
// reuse.
|
397
|
-
XdsResolver::WeightedClusterIndexMap new_weighted_cluster_index_map;
|
398
|
-
for (auto action_it = actions_to_process.begin();
|
399
|
-
action_it != actions_to_process.end();) {
|
400
|
-
const std::string& cluster_names_key = action_it->second;
|
401
|
-
const std::string& cluster_weights_key = action_it->first;
|
402
|
-
auto old_cluster_names_map_it =
|
403
|
-
weighted_cluster_index_map_.find(cluster_names_key);
|
404
|
-
if (old_cluster_names_map_it != weighted_cluster_index_map_.end()) {
|
405
|
-
// Add cluster_names_key to the new map and copy next_index.
|
406
|
-
auto& new_cluster_names_info =
|
407
|
-
new_weighted_cluster_index_map[cluster_names_key];
|
408
|
-
new_cluster_names_info.next_index =
|
409
|
-
old_cluster_names_map_it->second.next_index;
|
410
|
-
// Lookup cluster_weights_key in old map.
|
411
|
-
auto& old_cluster_weights_map =
|
412
|
-
old_cluster_names_map_it->second.cluster_weights_map;
|
413
|
-
auto old_cluster_weights_map_it =
|
414
|
-
old_cluster_weights_map.find(cluster_weights_key);
|
415
|
-
if (old_cluster_weights_map_it != old_cluster_weights_map.end()) {
|
416
|
-
// same policy found, move from old map to new map.
|
417
|
-
new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
|
418
|
-
old_cluster_weights_map_it->second;
|
419
|
-
old_cluster_weights_map.erase(old_cluster_weights_map_it);
|
420
|
-
// This action has been added to new map, so no need to process it
|
421
|
-
// again.
|
422
|
-
action_it = actions_to_process.erase(action_it);
|
423
|
-
continue;
|
424
|
-
}
|
425
|
-
}
|
426
|
-
++action_it;
|
427
|
-
}
|
428
|
-
// Second pass of all remaining unique WeightedCluster actions: if clusters
|
429
|
-
// for a new action are the same as an old unused action, reuse the name. If
|
430
|
-
// clusters differ, use a brand new name.
|
431
|
-
for (const auto& action : actions_to_process) {
|
432
|
-
const std::string& cluster_names_key = action.second;
|
433
|
-
const std::string& cluster_weights_key = action.first;
|
434
|
-
auto& new_cluster_names_info =
|
435
|
-
new_weighted_cluster_index_map[cluster_names_key];
|
436
|
-
auto& old_cluster_weights_map =
|
437
|
-
weighted_cluster_index_map_[cluster_names_key].cluster_weights_map;
|
438
|
-
auto old_cluster_weights_it = old_cluster_weights_map.begin();
|
439
|
-
if (old_cluster_weights_it != old_cluster_weights_map.end()) {
|
440
|
-
// There is something to reuse: this action uses the same set
|
441
|
-
// of clusters as a previous action and that action name is not
|
442
|
-
// already taken.
|
443
|
-
new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
|
444
|
-
old_cluster_weights_it->second;
|
445
|
-
// Remove the name from being able to reuse again.
|
446
|
-
old_cluster_weights_map.erase(old_cluster_weights_it);
|
447
|
-
} else {
|
448
|
-
// There is nothing to reuse, take the next index to use and
|
449
|
-
// increment.
|
450
|
-
new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
|
451
|
-
new_cluster_names_info.next_index++;
|
452
|
-
}
|
453
|
-
}
|
454
|
-
weighted_cluster_index_map_ = std::move(new_weighted_cluster_index_map);
|
616
|
+
void XdsResolver::OnResourceDoesNotExist() {
|
617
|
+
gpr_log(GPR_ERROR,
|
618
|
+
"[xds_resolver %p] LDS/RDS resource does not exist -- clearing "
|
619
|
+
"update and returning empty service config",
|
620
|
+
this);
|
621
|
+
current_update_.clear();
|
622
|
+
Result result;
|
623
|
+
result.service_config =
|
624
|
+
ServiceConfig::Create(args_, "{}", &result.service_config_error);
|
625
|
+
GPR_ASSERT(result.service_config != nullptr);
|
626
|
+
result.args = grpc_channel_args_copy(args_);
|
627
|
+
result_handler()->ReturnResult(std::move(result));
|
455
628
|
}
|
456
629
|
|
457
630
|
grpc_error* XdsResolver::CreateServiceConfig(
|
458
|
-
const std::vector<XdsApi::Route>& routes,
|
459
631
|
RefCountedPtr<ServiceConfig>* service_config) {
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
actions_vector.push_back(
|
472
|
-
route.weighted_clusters.empty()
|
473
|
-
? CreateServiceConfigActionCluster(action_name)
|
474
|
-
: CreateServiceConfigActionWeightedCluster(
|
475
|
-
action_name, route.weighted_clusters));
|
476
|
-
}
|
477
|
-
route_table.push_back(CreateServiceConfigRoute(
|
478
|
-
absl::StrFormat("%s:%s",
|
479
|
-
route.weighted_clusters.empty() ? "cds" : "weighted",
|
480
|
-
action_name),
|
481
|
-
route));
|
632
|
+
std::vector<std::string> clusters;
|
633
|
+
for (const auto& cluster : cluster_state_map_) {
|
634
|
+
clusters.push_back(
|
635
|
+
absl::StrFormat(" \"%s\":{\n"
|
636
|
+
" \"childPolicy\":[ {\n"
|
637
|
+
" \"cds_experimental\":{\n"
|
638
|
+
" \"cluster\": \"%s\"\n"
|
639
|
+
" }\n"
|
640
|
+
" } ]\n"
|
641
|
+
" }",
|
642
|
+
cluster.first, cluster.first));
|
482
643
|
}
|
483
644
|
std::vector<std::string> config_parts;
|
484
645
|
config_parts.push_back(
|
485
646
|
"{\n"
|
486
647
|
" \"loadBalancingConfig\":[\n"
|
487
|
-
" { \"
|
488
|
-
" \"
|
489
|
-
config_parts.push_back(absl::StrJoin(
|
490
|
-
config_parts.push_back(
|
491
|
-
" },\n"
|
492
|
-
" \"routes\":[\n");
|
493
|
-
config_parts.push_back(absl::StrJoin(route_table, ",\n"));
|
648
|
+
" { \"xds_cluster_manager_experimental\":{\n"
|
649
|
+
" \"children\":{\n");
|
650
|
+
config_parts.push_back(absl::StrJoin(clusters, ",\n"));
|
494
651
|
config_parts.push_back(
|
495
|
-
"
|
652
|
+
" }\n"
|
496
653
|
" } }\n"
|
497
654
|
" ]\n"
|
498
655
|
"}");
|
499
656
|
std::string json = absl::StrJoin(config_parts, "");
|
500
657
|
grpc_error* error = GRPC_ERROR_NONE;
|
501
|
-
*service_config = ServiceConfig::Create(json.c_str(), &error);
|
658
|
+
*service_config = ServiceConfig::Create(args_, json.c_str(), &error);
|
502
659
|
return error;
|
503
660
|
}
|
504
661
|
|
662
|
+
void XdsResolver::GenerateResult() {
|
663
|
+
if (current_update_.empty()) return;
|
664
|
+
// First create XdsConfigSelector, which may add new entries to the cluster
|
665
|
+
// state map, and then CreateServiceConfig for LB policies.
|
666
|
+
auto config_selector =
|
667
|
+
MakeRefCounted<XdsConfigSelector>(Ref(), current_update_);
|
668
|
+
Result result;
|
669
|
+
grpc_error* error = CreateServiceConfig(&result.service_config);
|
670
|
+
if (error != GRPC_ERROR_NONE) {
|
671
|
+
OnError(error);
|
672
|
+
return;
|
673
|
+
}
|
674
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
|
675
|
+
gpr_log(GPR_INFO, "[xds_resolver %p] generated service config: %s", this,
|
676
|
+
result.service_config->json_string().c_str());
|
677
|
+
}
|
678
|
+
grpc_arg new_arg = config_selector->MakeChannelArg();
|
679
|
+
result.args = grpc_channel_args_copy_and_add(args_, &new_arg, 1);
|
680
|
+
result_handler()->ReturnResult(std::move(result));
|
681
|
+
}
|
682
|
+
|
683
|
+
void XdsResolver::MaybeRemoveUnusedClusters() {
|
684
|
+
bool update_needed = false;
|
685
|
+
for (auto it = cluster_state_map_.begin(); it != cluster_state_map_.end();) {
|
686
|
+
RefCountedPtr<ClusterState> cluster_state = it->second->RefIfNonZero();
|
687
|
+
if (cluster_state != nullptr) {
|
688
|
+
++it;
|
689
|
+
} else {
|
690
|
+
update_needed = true;
|
691
|
+
it = cluster_state_map_.erase(it);
|
692
|
+
}
|
693
|
+
}
|
694
|
+
if (update_needed && xds_client_ != nullptr) {
|
695
|
+
// Send a new result to the channel.
|
696
|
+
GenerateResult();
|
697
|
+
}
|
698
|
+
}
|
699
|
+
|
505
700
|
//
|
506
701
|
// Factory
|
507
702
|
//
|