From 477a1aec5a222e04555113b2e0b38ddfdc463933 Mon Sep 17 00:00:00 2001 From: Dan Rosart Date: Tue, 26 Jun 2018 23:56:43 -0700 Subject: Don't segfault when product name from BIOS is empty Somehow some Dell servers we're trying to run a gRPC client on have an empty product name in the BIOS. When gRPC tries to creadte default credentials, it checks whether it's running on GCE by strcmp()ing the contents of /sys/class/dmi/id/product_name to some magic strings. When it reads that file, it gets only a newline; in trim() it skips over the newline in both directions, and since end < start it returns nullptr. This causes a segfault in the strcmp() call. Since a machine without a product name clearly isn't GCE, change it to return false instead. --- test/core/security/check_gcp_environment_linux_test.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'test/core') diff --git a/test/core/security/check_gcp_environment_linux_test.cc b/test/core/security/check_gcp_environment_linux_test.cc index 3acd5b6ae4..b01471abd3 100644 --- a/test/core/security/check_gcp_environment_linux_test.cc +++ b/test/core/security/check_gcp_environment_linux_test.cc @@ -69,6 +69,7 @@ static void test_gcp_environment_check_failure() { GPR_ASSERT(!check_bios_data_linux_test("Amazon")); GPR_ASSERT(!check_bios_data_linux_test("Google-Chrome\t\t")); GPR_ASSERT(!check_bios_data_linux_test("Amazon")); + GPR_ASSERT(!check_bios_data_linux_test("\n")); } int main(int argc, char** argv) { -- cgit v1.2.3 From 018498a06be9188bda95b5753e2aa93db2b5a28f Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 29 Jun 2018 14:48:05 -0700 Subject: Implements subchannel refs for pick_first --- grpc.def | 1 + include/grpc/support/string_util.h | 4 ++ .../ext/filters/client_channel/client_channel.cc | 10 +++ .../ext/filters/client_channel/client_channel.h | 6 ++ .../client_channel/client_channel_channelz.cc | 31 ++++++++++ .../client_channel/client_channel_channelz.h | 8 +++ src/core/ext/filters/client_channel/lb_policy.cc | 17 +++++- src/core/ext/filters/client_channel/lb_policy.h | 17 ++++++ .../lb_policy/pick_first/pick_first.cc | 51 ++++++++++++++++ src/core/ext/filters/client_channel/subchannel.cc | 12 ++++ src/core/ext/filters/client_channel/subchannel.h | 2 + src/core/lib/channel/channel_trace.cc | 44 ++------------ src/core/lib/channel/channelz.cc | 71 +++++----------------- src/core/lib/channel/channelz.h | 2 + src/core/lib/gpr/string.cc | 34 +++++++++++ src/core/lib/iomgr/error.cc | 3 +- src/core/lib/json/json.cc | 10 +++ src/core/lib/json/json.h | 4 ++ src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 + src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 + test/core/end2end/tests/simple_request.cc | 32 +++++----- test/core/surface/public_headers_must_be_c89.c | 1 + 22 files changed, 254 insertions(+), 111 deletions(-) (limited to 'test/core') diff --git a/grpc.def b/grpc.def index 06db74cad5..7d33e08575 100644 --- a/grpc.def +++ b/grpc.def @@ -199,6 +199,7 @@ EXPORTS gpr_format_message gpr_strdup gpr_asprintf + gpr_format_timespec gpr_mu_init gpr_mu_destroy gpr_mu_lock diff --git a/include/grpc/support/string_util.h b/include/grpc/support/string_util.h index 2c7460fa15..3b5b0008b2 100644 --- a/include/grpc/support/string_util.h +++ b/include/grpc/support/string_util.h @@ -21,6 +21,8 @@ #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -42,6 +44,8 @@ GPRAPI char* gpr_strdup(const char* src); GPRAPI int gpr_asprintf(char** strp, const char* format, ...) GPR_PRINT_FORMAT_CHECK(2, 3); +GPRAPI char* gpr_format_timespec(gpr_timespec); + #ifdef __cplusplus } #endif diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 520431e63b..8c3e9f2b30 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -3159,6 +3159,16 @@ static void try_to_connect_locked(void* arg, grpc_error* error_ignored) { GRPC_CHANNEL_STACK_UNREF(chand->owning_stack, "try_to_connect"); } +void grpc_client_channel_populate_child_refs( + grpc_channel_element* elem, grpc_core::ChildRefsList* child_subchannels, + grpc_core::ChildRefsList* child_channels) { + channel_data* chand = static_cast(elem->channel_data); + if (chand->lb_policy) { + chand->lb_policy->FillChildRefsForChannelz(child_subchannels, + child_channels); + } +} + grpc_connectivity_state grpc_client_channel_check_connectivity_state( grpc_channel_element* elem, int try_to_connect) { channel_data* chand = static_cast(elem->channel_data); diff --git a/src/core/ext/filters/client_channel/client_channel.h b/src/core/ext/filters/client_channel/client_channel.h index a21e5623a7..0f95f6670a 100644 --- a/src/core/ext/filters/client_channel/client_channel.h +++ b/src/core/ext/filters/client_channel/client_channel.h @@ -21,9 +21,11 @@ #include +#include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/client_channel_factory.h" #include "src/core/ext/filters/client_channel/resolver.h" #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/json/json.h" extern grpc_core::TraceFlag grpc_client_channel_trace; @@ -39,6 +41,10 @@ extern grpc_core::TraceFlag grpc_client_channel_trace; extern const grpc_channel_filter grpc_client_channel_filter; +void grpc_client_channel_populate_child_refs( + grpc_channel_element* elem, grpc_core::ChildRefsList* child_subchannels, + grpc_core::ChildRefsList* child_channels); + grpc_connectivity_state grpc_client_channel_check_connectivity_state( grpc_channel_element* elem, int try_to_connect); diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 08ceb2dd05..235b8f3207 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -63,6 +63,37 @@ void ClientChannelNode::PopulateConnectivityState(grpc_json* json) { false); } +void ClientChannelNode::PopulateChildRefs(grpc_json* json) { + ChildRefsList child_subchannels; + ChildRefsList child_channels; + grpc_json* json_iterator = nullptr; + grpc_client_channel_populate_child_refs(client_channel_, &child_subchannels, + &child_channels); + if (child_subchannels.size() > 0) { + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "subchannelRef", nullptr, GRPC_JSON_ARRAY, false); + for (size_t i = 0; i < child_subchannels.size(); ++i) { + json_iterator = + grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, + GRPC_JSON_OBJECT, false); + grpc_json_add_number_string_child(json_iterator, nullptr, "subchannelId", + child_subchannels[i]); + } + } + if (child_channels.size() > 0) { + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "channelRef", nullptr, GRPC_JSON_ARRAY, false); + json_iterator = nullptr; + for (size_t i = 0; i < child_subchannels.size(); ++i) { + json_iterator = + grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, + GRPC_JSON_OBJECT, false); + grpc_json_add_number_string_child(json_iterator, nullptr, "channelId", + child_subchannels[i]); + } + } +} + grpc_arg ClientChannelNode::CreateChannelArg() { return grpc_channel_arg_pointer_create( const_cast(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC), diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index cf3ef7b6f2..e5be52e778 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -22,9 +22,14 @@ #include #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channelz.h" +#include "src/core/lib/gprpp/inlined_vector.h" namespace grpc_core { + +typedef InlinedVector ChildRefsList; + namespace channelz { // Subtype of ChannelNode that overrides and provides client_channel specific @@ -38,6 +43,9 @@ class ClientChannelNode : public ChannelNode { // channel connectivity. void PopulateConnectivityState(grpc_json* json) override; + // Override this functionality since client_channels have subchannels + void PopulateChildRefs(grpc_json* json) override; + // Helper to create a channel arg to ensure this type of ChannelNode is // created. static grpc_arg CreateChannelArg(); diff --git a/src/core/ext/filters/client_channel/lb_policy.cc b/src/core/ext/filters/client_channel/lb_policy.cc index e065f45639..a0d7758f23 100644 --- a/src/core/ext/filters/client_channel/lb_policy.cc +++ b/src/core/ext/filters/client_channel/lb_policy.cc @@ -31,13 +31,28 @@ LoadBalancingPolicy::LoadBalancingPolicy(const Args& args) combiner_(GRPC_COMBINER_REF(args.combiner, "lb_policy")), client_channel_factory_(args.client_channel_factory), interested_parties_(grpc_pollset_set_create()), - request_reresolution_(nullptr) {} + request_reresolution_(nullptr) { + gpr_mu_init(&child_refs_mu_); +} LoadBalancingPolicy::~LoadBalancingPolicy() { grpc_pollset_set_destroy(interested_parties_); + gpr_mu_destroy(&child_refs_mu_); GRPC_COMBINER_UNREF(combiner_, "lb_policy"); } +void LoadBalancingPolicy::FillChildRefsForChannelz( + ChildRefsList* child_subchannels, ChildRefsList* child_channels) { + mu_guard guard(&child_refs_mu_); + // TODO, de dup these. + for (size_t i = 0; i < child_subchannels_.size(); ++i) { + child_subchannels->push_back(child_subchannels_[i]); + } + for (size_t i = 0; i < child_channels_.size(); ++i) { + child_channels->push_back(child_channels_[i]); + } +} + void LoadBalancingPolicy::TryReresolutionLocked( grpc_core::TraceFlag* grpc_lb_trace, grpc_error* error) { if (request_reresolution_ != nullptr) { diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h index dab4466b21..0c5fd2ad9c 100644 --- a/src/core/ext/filters/client_channel/lb_policy.h +++ b/src/core/ext/filters/client_channel/lb_policy.h @@ -21,6 +21,7 @@ #include +#include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/client_channel_factory.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/gprpp/abstract.h" @@ -28,6 +29,7 @@ #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/json/json.h" #include "src/core/lib/transport/connectivity_state.h" extern grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount; @@ -157,6 +159,13 @@ class LoadBalancingPolicy request_reresolution_ = request_reresolution; } + /// populates child_subchannels and child_channels with the uuids of this + /// LB policies referenced children. This is not invoked from the + /// client_channel's combiner. It has its own synchronization. This is + /// not abstract, since the behavior is the same for all LB policies. + void FillChildRefsForChannelz(ChildRefsList* child_subchannels, + ChildRefsList* child_channels); + grpc_pollset_set* interested_parties() const { return interested_parties_; } GRPC_ABSTRACT_BASE_CLASS @@ -171,6 +180,9 @@ class LoadBalancingPolicy grpc_client_channel_factory* client_channel_factory() const { return client_channel_factory_; } + gpr_mu* child_refs_mu() { return &child_refs_mu_; } + ChildRefsList* child_subchannels() { return &child_subchannels_; } + ChildRefsList* child_channels() { return &child_channels_; } /// Shuts down the policy. Any pending picks that have not been /// handed off to a new policy via HandOffPendingPicksLocked() will be @@ -190,6 +202,11 @@ class LoadBalancingPolicy /// Combiner under which LB policy actions take place. grpc_combiner* combiner_; + /// Lock and data used to capture snapshots of this channels child + /// channels and subchannels. This data is consumed by channelz. + gpr_mu child_refs_mu_; + ChildRefsList child_subchannels_; + ChildRefsList child_channels_; /// Client channel factory, used to create channels and subchannels. grpc_client_channel_factory* client_channel_factory_; /// Owned pointer to interested parties in load balancing decisions. diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index ff2140e628..e43d1c2ab4 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -37,6 +37,15 @@ TraceFlag grpc_lb_pick_first_trace(false, "pick_first"); namespace { +class LockGuard { + public: + LockGuard(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } + ~LockGuard() { gpr_mu_unlock(mu_); } + + private: + gpr_mu* mu_; +}; + // // pick_first LB policy // @@ -103,10 +112,20 @@ class PickFirst : public LoadBalancingPolicy { } }; + class UpdateGuard { + public: + UpdateGuard(PickFirst* pf) : pf_(pf) {} + ~UpdateGuard() { pf_->UpdateChildRefsLocked(); } + + private: + PickFirst* pf_; + }; + void ShutdownLocked() override; void StartPickingLocked(); void DestroyUnselectedSubchannelsLocked(); + void UpdateChildRefsLocked(); // All our subchannels. OrphanablePtr subchannel_list_; @@ -158,6 +177,7 @@ void PickFirst::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) { } void PickFirst::ShutdownLocked() { + UpdateGuard(this); grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown"); if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Pick First %p Shutting down", this); @@ -280,7 +300,37 @@ void PickFirst::PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) { } } +void PickFirst::UpdateChildRefsLocked() { + mu_guard guard(child_refs_mu()); + // reset both lists + child_subchannels()->clear(); + // this will stay empty, because pick_first channels have no children + // channels. + child_channels()->clear(); + // populate the subchannels with boths subchannels lists, they will be + // deduped when the actual channelz query comes in. + if (subchannel_list_ != nullptr) { + for (size_t i = 0; i < subchannel_list_->num_subchannels(); ++i) { + if (subchannel_list_->subchannel(i)->subchannel() != nullptr) { + child_subchannels()->push_back(grpc_subchannel_get_uuid( + subchannel_list_->subchannel(i)->subchannel())); + } + } + } + if (latest_pending_subchannel_list_ != nullptr) { + for (size_t i = 0; i < latest_pending_subchannel_list_->num_subchannels(); + ++i) { + if (latest_pending_subchannel_list_->subchannel(i)->subchannel() != + nullptr) { + child_subchannels()->push_back(grpc_subchannel_get_uuid( + latest_pending_subchannel_list_->subchannel(i)->subchannel())); + } + } + } +} + void PickFirst::UpdateLocked(const grpc_channel_args& args) { + UpdateGuard guard(this); const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES); if (arg == nullptr || arg->type != GRPC_ARG_POINTER) { if (subchannel_list_ == nullptr) { @@ -388,6 +438,7 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) { void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( grpc_connectivity_state connectivity_state, grpc_error* error) { PickFirst* p = static_cast(subchannel_list()->policy()); + UpdateGuard guard(p); // The notification must be for a subchannel in either the current or // latest pending subchannel lists. GPR_ASSERT(subchannel_list() == p->subchannel_list_.get() || diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 8ab3fe40f5..6c4f1869ea 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -134,6 +134,11 @@ struct grpc_subchannel { bool backoff_begun; /** our alarm */ grpc_timer alarm; + + /* the global uuid for this subchannel */ + // TODO(ncteisen): move this into SubchannelNode while implementing + // GetSubchannel. + intptr_t subchannel_uuid; }; struct grpc_subchannel_call { @@ -374,9 +379,16 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, c->backoff.Init(backoff_options); gpr_mu_init(&c->mu); + // This is just a placeholder for now + c->subchannel_uuid = 42; + return grpc_subchannel_index_register(key, c); } +intptr_t grpc_subchannel_get_uuid(grpc_subchannel* s) { + return s->subchannel_uuid; +} + static void continue_connect_locked(grpc_subchannel* c) { grpc_connect_in_args args; args.interested_parties = c->pollset_set; diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index e23aec12df..590e80f507 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -115,6 +115,8 @@ grpc_subchannel_call* grpc_subchannel_call_ref( void grpc_subchannel_call_unref( grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); +intptr_t grpc_subchannel_get_uuid(grpc_subchannel* subchannel); + /** Returns a pointer to the parent data associated with \a subchannel_call. The data will be of the size specified in \a parent_data_size field of the args passed to \a grpc_connected_subchannel_create_call(). */ diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index 0f655d8716..c17885a713 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -131,38 +131,6 @@ void ChannelTrace::AddTraceEventReferencingSubchannel( namespace { -// returns an allocated string that represents tm according to RFC-3339, and, -// more specifically, follows: -// https://developers.google.com/protocol-buffers/docs/proto3#json -// -// "Uses RFC 3339, where generated output will always be Z-normalized and uses -// 0, 3, 6 or 9 fractional digits." -char* fmt_time(gpr_timespec tm) { - char time_buffer[35]; - char ns_buffer[11]; // '.' + 9 digits of precision - struct tm* tm_info = localtime((const time_t*)&tm.tv_sec); - strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%H:%M:%S", tm_info); - snprintf(ns_buffer, 11, ".%09d", tm.tv_nsec); - // This loop trims off trailing zeros by inserting a null character that the - // right point. We iterate in chunks of three because we want 0, 3, 6, or 9 - // fractional digits. - for (int i = 7; i >= 1; i -= 3) { - if (ns_buffer[i] == '0' && ns_buffer[i + 1] == '0' && - ns_buffer[i + 2] == '0') { - ns_buffer[i] = '\0'; - // Edge case in which all fractional digits were 0. - if (i == 1) { - ns_buffer[0] = '\0'; - } - } else { - break; - } - } - char* full_time_str; - gpr_asprintf(&full_time_str, "%s%sZ", time_buffer, ns_buffer); - return full_time_str; -} - const char* severity_string(ChannelTrace::Severity severity) { switch (severity) { case ChannelTrace::Severity::Info: @@ -186,9 +154,9 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { json_iterator = grpc_json_create_child(json_iterator, json, "severity", severity_string(severity_), GRPC_JSON_STRING, false); - json_iterator = - grpc_json_create_child(json_iterator, json, "timestamp", - fmt_time(timestamp_), GRPC_JSON_STRING, true); + json_iterator = grpc_json_create_child(json_iterator, json, "timestamp", + gpr_format_timespec(timestamp_), + GRPC_JSON_STRING, true); if (referenced_channel_ != nullptr) { char* uuid_str; gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->channel_uuid()); @@ -216,9 +184,9 @@ grpc_json* ChannelTrace::RenderJSON() const { json_iterator = grpc_json_create_child(json_iterator, json, "numEventsLogged", num_events_logged_str, GRPC_JSON_STRING, true); - json_iterator = - grpc_json_create_child(json_iterator, json, "creationTimestamp", - fmt_time(time_created_), GRPC_JSON_STRING, true); + json_iterator = grpc_json_create_child( + json_iterator, json, "creationTimestamp", + gpr_format_timespec(time_created_), GRPC_JSON_STRING, true); grpc_json* events = grpc_json_create_child(json_iterator, json, "events", nullptr, GRPC_JSON_ARRAY, false); json_iterator = nullptr; diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 2074cb0cc5..ffc7ff884c 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -41,53 +41,6 @@ namespace grpc_core { namespace channelz { -namespace { - -// TODO(ncteisen): move this function to a common helper location. -// -// returns an allocated string that represents tm according to RFC-3339, and, -// more specifically, follows: -// https://developers.google.com/protocol-buffers/docs/proto3#json -// -// "Uses RFC 3339, where generated output will always be Z-normalized and uses -// 0, 3, 6 or 9 fractional digits." -char* fmt_time(gpr_timespec tm) { - char time_buffer[35]; - char ns_buffer[11]; // '.' + 9 digits of precision - struct tm* tm_info = localtime((const time_t*)&tm.tv_sec); - strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%H:%M:%S", tm_info); - snprintf(ns_buffer, 11, ".%09d", tm.tv_nsec); - // This loop trims off trailing zeros by inserting a null character that the - // right point. We iterate in chunks of three because we want 0, 3, 6, or 9 - // fractional digits. - for (int i = 7; i >= 1; i -= 3) { - if (ns_buffer[i] == '0' && ns_buffer[i + 1] == '0' && - ns_buffer[i + 2] == '0') { - ns_buffer[i] = '\0'; - // Edge case in which all fractional digits were 0. - if (i == 1) { - ns_buffer[0] = '\0'; - } - } else { - break; - } - } - char* full_time_str; - gpr_asprintf(&full_time_str, "%s%sZ", time_buffer, ns_buffer); - return full_time_str; -} - -// TODO(ncteisen); move this to json library -grpc_json* add_num_str(grpc_json* parent, grpc_json* it, const char* name, - int64_t num) { - char* num_str; - gpr_asprintf(&num_str, "%" PRId64, num); - return grpc_json_create_child(it, parent, name, num_str, GRPC_JSON_STRING, - true); -} - -} // namespace - ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes) : channel_(channel), target_(nullptr), channel_uuid_(-1) { trace_.Init(channel_tracer_max_nodes); @@ -110,6 +63,8 @@ void ChannelNode::RecordCallStarted() { void ChannelNode::PopulateConnectivityState(grpc_json* json) {} +void ChannelNode::PopulateChildRefs(grpc_json* json) {} + char* ChannelNode::RenderJSON() { // We need to track these three json objects to build our object grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); @@ -120,7 +75,8 @@ char* ChannelNode::RenderJSON() { GRPC_JSON_OBJECT, false); json = json_iterator; json_iterator = nullptr; - json_iterator = add_num_str(json, json_iterator, "channelId", channel_uuid_); + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "channelId", channel_uuid_); // reset json iterators to top level object json = top_level_json; json_iterator = nullptr; @@ -148,17 +104,22 @@ char* ChannelNode::RenderJSON() { json_iterator = nullptr; // We use -1 as sentinel values since proto default value for integers is // zero, and the confuses the parser into thinking the value weren't present - json_iterator = - add_num_str(json, json_iterator, "callsStarted", calls_started_); - json_iterator = - add_num_str(json, json_iterator, "callsSucceeded", calls_succeeded_); - json_iterator = - add_num_str(json, json_iterator, "callsFailed", calls_failed_); + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "callsStarted", calls_started_); + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "callsSucceeded", calls_succeeded_); + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "callsFailed", calls_failed_); gpr_timespec ts = grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME); json_iterator = grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp", - fmt_time(ts), GRPC_JSON_STRING, true); + gpr_format_timespec(ts), GRPC_JSON_STRING, true); + + json = top_level_json; + json_iterator = nullptr; + PopulateChildRefs(json); + // render and return the over json object char* json_str = grpc_json_dump_to_string(top_level_json, 0); grpc_json_destroy(top_level_json); diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 9bd01ece50..e84c187f11 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -62,6 +62,8 @@ class ChannelNode : public RefCounted { // instead of lib/ virtual void PopulateConnectivityState(grpc_json* json); + virtual void PopulateChildRefs(grpc_json* json); + ChannelTrace* trace() { return trace_.get(); } void MarkChannelDestroyed() { diff --git a/src/core/lib/gpr/string.cc b/src/core/lib/gpr/string.cc index ef2a6900b4..9bcb6714a3 100644 --- a/src/core/lib/gpr/string.cc +++ b/src/core/lib/gpr/string.cc @@ -23,8 +23,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -54,6 +56,38 @@ typedef struct { char* data; } dump_out; +// Returns an allocated string that represents tm according to RFC-3339, and, +// more specifically, follows: +// https://developers.google.com/protocol-buffers/docs/proto3#json +// +// "Uses RFC 3339, where generated output will always be Z-normalized and uses +// 0, 3, 6 or 9 fractional digits." +char* gpr_format_timespec(gpr_timespec tm) { + char time_buffer[35]; + char ns_buffer[11]; // '.' + 9 digits of precision + struct tm* tm_info = localtime((const time_t*)&tm.tv_sec); + strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%H:%M:%S", tm_info); + snprintf(ns_buffer, 11, ".%09d", tm.tv_nsec); + // This loop trims off trailing zeros by inserting a null character that the + // right point. We iterate in chunks of three because we want 0, 3, 6, or 9 + // fractional digits. + for (int i = 7; i >= 1; i -= 3) { + if (ns_buffer[i] == '0' && ns_buffer[i + 1] == '0' && + ns_buffer[i + 2] == '0') { + ns_buffer[i] = '\0'; + // Edge case in which all fractional digits were 0. + if (i == 1) { + ns_buffer[0] = '\0'; + } + } else { + break; + } + } + char* full_time_str; + gpr_asprintf(&full_time_str, "%s%sZ", time_buffer, ns_buffer); + return full_time_str; +} + static dump_out dump_out_create(void) { dump_out r = {0, 0, nullptr}; return r; diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc index 90ed34da11..8e7205f558 100644 --- a/src/core/lib/iomgr/error.cc +++ b/src/core/lib/iomgr/error.cc @@ -670,7 +670,8 @@ static void collect_times_kvs(grpc_error* err, kv_pairs* kvs) { uint8_t slot = err->times[which]; if (slot != UINT8_MAX) { append_kv(kvs, key_time(static_cast(which)), - fmt_time(*reinterpret_cast(err->arena + slot))); + gpr_format_timespec( + *reinterpret_cast(err->arena + slot))); } } } diff --git a/src/core/lib/json/json.cc b/src/core/lib/json/json.cc index 816241bbf0..6d359573f8 100644 --- a/src/core/lib/json/json.cc +++ b/src/core/lib/json/json.cc @@ -18,10 +18,12 @@ #include +#include #include #include #include +#include #include "src/core/lib/json/json.h" @@ -84,3 +86,11 @@ grpc_json* grpc_json_create_child(grpc_json* sibling, grpc_json* parent, child->key = key; return child; } + +grpc_json* grpc_json_add_number_string_child(grpc_json* parent, grpc_json* it, + const char* name, int64_t num) { + char* num_str; + gpr_asprintf(&num_str, "%" PRId64, num); + return grpc_json_create_child(it, parent, name, num_str, GRPC_JSON_STRING, + true); +} diff --git a/src/core/lib/json/json.h b/src/core/lib/json/json.h index f93b43048b..8742774b5f 100644 --- a/src/core/lib/json/json.h +++ b/src/core/lib/json/json.h @@ -91,4 +91,8 @@ grpc_json* grpc_json_create_child(grpc_json* sibling, grpc_json* parent, const char* key, const char* value, grpc_json_type type, bool owns_value); +/* TODO */ +grpc_json* grpc_json_add_number_string_child(grpc_json* parent, grpc_json* it, + const char* name, int64_t num); + #endif /* GRPC_CORE_LIB_JSON_JSON_H */ diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 4e235121e2..1086b7dfcb 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -222,6 +222,7 @@ gpr_cpu_current_cpu_type gpr_cpu_current_cpu_import; gpr_format_message_type gpr_format_message_import; gpr_strdup_type gpr_strdup_import; gpr_asprintf_type gpr_asprintf_import; +gpr_format_timespec_type gpr_format_timespec_import; gpr_mu_init_type gpr_mu_init_import; gpr_mu_destroy_type gpr_mu_destroy_import; gpr_mu_lock_type gpr_mu_lock_import; @@ -470,6 +471,7 @@ void grpc_rb_load_imports(HMODULE library) { gpr_format_message_import = (gpr_format_message_type) GetProcAddress(library, "gpr_format_message"); gpr_strdup_import = (gpr_strdup_type) GetProcAddress(library, "gpr_strdup"); gpr_asprintf_import = (gpr_asprintf_type) GetProcAddress(library, "gpr_asprintf"); + gpr_format_timespec_import = (gpr_format_timespec_type) GetProcAddress(library, "gpr_format_timespec"); gpr_mu_init_import = (gpr_mu_init_type) GetProcAddress(library, "gpr_mu_init"); gpr_mu_destroy_import = (gpr_mu_destroy_type) GetProcAddress(library, "gpr_mu_destroy"); gpr_mu_lock_import = (gpr_mu_lock_type) GetProcAddress(library, "gpr_mu_lock"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index f01c9c8248..b4107641a4 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -641,6 +641,9 @@ extern gpr_strdup_type gpr_strdup_import; typedef int(*gpr_asprintf_type)(char** strp, const char* format, ...) GPR_PRINT_FORMAT_CHECK(2, 3); extern gpr_asprintf_type gpr_asprintf_import; #define gpr_asprintf gpr_asprintf_import +typedef char*(*gpr_format_timespec_type)(gpr_timespec); +extern gpr_format_timespec_type gpr_format_timespec_import; +#define gpr_format_timespec gpr_format_timespec_import typedef void(*gpr_mu_init_type)(gpr_mu* mu); extern gpr_mu_init_type gpr_mu_init_import; #define gpr_mu_init gpr_mu_init_import diff --git a/test/core/end2end/tests/simple_request.cc b/test/core/end2end/tests/simple_request.cc index 941d9ae319..7ec11d8ac3 100644 --- a/test/core/end2end/tests/simple_request.cc +++ b/test/core/end2end/tests/simple_request.cc @@ -256,24 +256,24 @@ static void test_invoke_simple_request(grpc_end2end_test_config config) { config.tear_down_data(&f); } -static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { - int i; - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_10_simple_requests", nullptr, nullptr); - for (i = 0; i < 10; i++) { - simple_request_body(config, f); - gpr_log(GPR_INFO, "Running test: Passed simple request %d", i); - } - end_test(&f); - config.tear_down_data(&f); -} +// static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { +// int i; +// grpc_end2end_test_fixture f = +// begin_test(config, "test_invoke_10_simple_requests", nullptr, nullptr); +// for (i = 0; i < 10; i++) { +// simple_request_body(config, f); +// gpr_log(GPR_INFO, "Running test: Passed simple request %d", i); +// } +// end_test(&f); +// config.tear_down_data(&f); +// } void simple_request(grpc_end2end_test_config config) { - int i; - for (i = 0; i < 10; i++) { - test_invoke_simple_request(config); - } - test_invoke_10_simple_requests(config); + // int i; + // for (i = 0; i < 10; i++) { + test_invoke_simple_request(config); + // } + // test_invoke_10_simple_requests(config); } void simple_request_pre_init(void) {} diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 9a79b468dd..95deb1f17a 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -257,6 +257,7 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) gpr_cpu_current_cpu); printf("%lx", (unsigned long) gpr_strdup); printf("%lx", (unsigned long) gpr_asprintf); + printf("%lx", (unsigned long) gpr_format_timespec); printf("%lx", (unsigned long) gpr_mu_init); printf("%lx", (unsigned long) gpr_mu_destroy); printf("%lx", (unsigned long) gpr_mu_lock); -- cgit v1.2.3 From 2d2854a1ce398c2a5c4693c68fe689055dda0cdd Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 13 Jul 2018 10:35:46 -0700 Subject: Add copy and move ctor to InlinedVector --- src/core/lib/gprpp/inlined_vector.h | 73 +++++++++++++++++++++++- test/core/gprpp/inlined_vector_test.cc | 101 +++++++++++++++++++++++++++------ 2 files changed, 153 insertions(+), 21 deletions(-) (limited to 'test/core') diff --git a/src/core/lib/gprpp/inlined_vector.h b/src/core/lib/gprpp/inlined_vector.h index 0d2586e507..276d5a078d 100644 --- a/src/core/lib/gprpp/inlined_vector.h +++ b/src/core/lib/gprpp/inlined_vector.h @@ -50,9 +50,76 @@ class InlinedVector { InlinedVector() { init_data(); } ~InlinedVector() { destroy_elements(); } - // For now, we do not support copying. - InlinedVector(const InlinedVector&) = delete; - InlinedVector& operator=(const InlinedVector&) = delete; + // copy constructors + InlinedVector(const InlinedVector& v) { + init_data(); + // if v is allocated, then we copy it's buffer + if (v.dynamic_ != nullptr) { + reserve(v.capacity_); + memcpy(dynamic_, v.dynamic_, v.capacity_ * sizeof(T)); + } else { + memcpy(inline_, v.inline_, v.capacity_ * sizeof(T)); + dynamic_ = nullptr; + } + // copy over metadata + size_ = v.size_; + capacity_ = v.capacity_; + } + InlinedVector& operator=(const InlinedVector& v) { + if (this != &v) { + clear(); + // if v is allocated, then we copy it's buffer + if (v.dynamic_ != nullptr) { + reserve(v.capacity_); + memcpy(dynamic_, v.dynamic_, v.capacity_ * sizeof(T)); + } else { + memcpy(inline_, v.inline_, v.capacity_ * sizeof(T)); + dynamic_ = nullptr; + } + // copy over metadata + size_ = v.size_; + capacity_ = v.capacity_; + } + return *this; + } + + // move constructors + InlinedVector(InlinedVector&& v) { + // if v is allocated, then we steal it's buffer + if (v.dynamic_ != nullptr) { + dynamic_ = v.dynamic_; + } else { + memcpy(inline_, v.inline_, v.capacity_ * sizeof(T)); + dynamic_ = nullptr; + } + // copy over metadata + size_ = v.size_; + capacity_ = v.capacity_; + // null out the original + v.dynamic_ = nullptr; + v.size_ = 0; + v.capacity_ = 0; + } + InlinedVector& operator=(InlinedVector&& v) { + if (this != &v) { + clear(); + // if v is allocated, then we steal it's buffer + if (v.dynamic_ != nullptr) { + dynamic_ = v.dynamic_; + } else { + memcpy(inline_, v.inline_, v.capacity_ * sizeof(T)); + dynamic_ = nullptr; + } + // copy over metadata + size_ = v.size_; + capacity_ = v.capacity_; + // null out the original + v.dynamic_ = nullptr; + v.size_ = 0; + v.capacity_ = 0; + } + return *this; + } T* data() { return dynamic_ != nullptr ? dynamic_ : reinterpret_cast(inline_); diff --git a/test/core/gprpp/inlined_vector_test.cc b/test/core/gprpp/inlined_vector_test.cc index 41f4338f8a..ba2f4d9e6f 100644 --- a/test/core/gprpp/inlined_vector_test.cc +++ b/test/core/gprpp/inlined_vector_test.cc @@ -17,20 +17,30 @@ */ #include "src/core/lib/gprpp/inlined_vector.h" +#include #include #include "src/core/lib/gprpp/memory.h" #include "test/core/util/test_config.h" namespace grpc_core { namespace testing { +namespace { + +template +static void FillVector(Vector* v, int len, int offset = 0) { + for (int i = 0; i < len; i++) { + v->push_back(i + offset); + EXPECT_EQ(i + 1UL, v->size()); + } +} + +} // namespace TEST(InlinedVectorTest, CreateAndIterate) { const int kNumElements = 9; InlinedVector v; EXPECT_TRUE(v.empty()); - for (int i = 0; i < kNumElements; ++i) { - v.push_back(i); - } + FillVector(&v, kNumElements); EXPECT_EQ(static_cast(kNumElements), v.size()); EXPECT_FALSE(v.empty()); for (int i = 0; i < kNumElements; ++i) { @@ -42,9 +52,7 @@ TEST(InlinedVectorTest, CreateAndIterate) { TEST(InlinedVectorTest, ValuesAreInlined) { const int kNumElements = 5; InlinedVector v; - for (int i = 0; i < kNumElements; ++i) { - v.push_back(i); - } + FillVector(&v, kNumElements); EXPECT_EQ(static_cast(kNumElements), v.size()); for (int i = 0; i < kNumElements; ++i) { EXPECT_EQ(i, v[i]); @@ -71,19 +79,13 @@ TEST(InlinedVectorTest, ClearAndRepopulate) { const int kNumElements = 10; InlinedVector v; EXPECT_EQ(0UL, v.size()); - for (int i = 0; i < kNumElements; ++i) { - v.push_back(i); - EXPECT_EQ(i + 1UL, v.size()); - } + FillVector(&v, kNumElements); for (int i = 0; i < kNumElements; ++i) { EXPECT_EQ(i, v[i]); } v.clear(); EXPECT_EQ(0UL, v.size()); - for (int i = 0; i < kNumElements; ++i) { - v.push_back(kNumElements + i); - EXPECT_EQ(i + 1UL, v.size()); - } + FillVector(&v, kNumElements, kNumElements); for (int i = 0; i < kNumElements; ++i) { EXPECT_EQ(kNumElements + i, v[i]); } @@ -93,10 +95,7 @@ TEST(InlinedVectorTest, ConstIndexOperator) { constexpr int kNumElements = 10; InlinedVector v; EXPECT_EQ(0UL, v.size()); - for (int i = 0; i < kNumElements; ++i) { - v.push_back(i); - EXPECT_EQ(i + 1UL, v.size()); - } + FillVector(&v, kNumElements); // The following lambda function is exceptionally allowed to use an anonymous // capture due to the erroneous behavior of the MSVC compiler, that refuses to // capture the kNumElements constexpr, something allowed by the standard. @@ -108,6 +107,72 @@ TEST(InlinedVectorTest, ConstIndexOperator) { const_func(v); } +TEST(InlinedVectorTest, CopyConstructorAndAssignment) { + typedef InlinedVector IntVec8; + for (size_t len = 0; len < 20; len++) { + IntVec8 original; + FillVector(&original, len); + EXPECT_EQ(len, original.size()); + EXPECT_LE(len, original.capacity()); + + IntVec8 copy_constructed(original); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_TRUE(original[i] == copy_constructed[i]); + } + + for (size_t start_len = 0; start_len < 20; start_len++) { + IntVec8 copy_assigned; + FillVector(©_assigned, start_len, 99); // Add dummy elements + copy_assigned = original; + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_TRUE(original[i] == copy_assigned[i]); + } + } + } +} + +TEST(InlinedVectorTest, MoveConstructorAndAssignment) { + typedef InlinedVector IntVec8; + for (size_t len = 0; len < 20; len++) { + IntVec8 original; + const size_t inlined_capacity = original.capacity(); + FillVector(&original, len); + EXPECT_EQ(len, original.size()); + EXPECT_LE(len, original.capacity()); + + { + IntVec8 tmp(original); + auto* old_data = tmp.data(); + IntVec8 move_constructed(std::move(tmp)); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_TRUE(original[i] == move_constructed[i]); + } + if (original.size() > inlined_capacity) { + // Allocation is moved as a whole, data stays in place. + EXPECT_TRUE(move_constructed.data() == old_data); + } else { + EXPECT_FALSE(move_constructed.data() == old_data); + } + } + for (size_t start_len = 0; start_len < 20; start_len++) { + IntVec8 move_assigned; + FillVector(&move_assigned, start_len, 99); // Add dummy elements + IntVec8 tmp(original); + auto* old_data = tmp.data(); + move_assigned = std::move(tmp); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_TRUE(original[i] == move_assigned[i]); + } + if (original.size() > inlined_capacity) { + // Allocation is moved as a whole, data stays in place. + EXPECT_TRUE(move_assigned.data() == old_data); + } else { + EXPECT_FALSE(move_assigned.data() == old_data); + } + } + } +} + } // namespace testing } // namespace grpc_core -- cgit v1.2.3 From 5fd07bd9ef72c2dcef3f0da159b41ca6a0a0f6b0 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 13 Jul 2018 15:05:47 -0700 Subject: Fix sanity and build --- grpc.def | 1 - src/core/lib/gprpp/inlined_vector.h | 1 + src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 -- src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 --- test/core/surface/public_headers_must_be_c89.c | 1 - 5 files changed, 1 insertion(+), 7 deletions(-) (limited to 'test/core') diff --git a/grpc.def b/grpc.def index 7d33e08575..06db74cad5 100644 --- a/grpc.def +++ b/grpc.def @@ -199,7 +199,6 @@ EXPORTS gpr_format_message gpr_strdup gpr_asprintf - gpr_format_timespec gpr_mu_init gpr_mu_destroy gpr_mu_lock diff --git a/src/core/lib/gprpp/inlined_vector.h b/src/core/lib/gprpp/inlined_vector.h index 276d5a078d..9c2e131455 100644 --- a/src/core/lib/gprpp/inlined_vector.h +++ b/src/core/lib/gprpp/inlined_vector.h @@ -22,6 +22,7 @@ #include #include +#include #include "src/core/lib/gprpp/memory.h" diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 1086b7dfcb..4e235121e2 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -222,7 +222,6 @@ gpr_cpu_current_cpu_type gpr_cpu_current_cpu_import; gpr_format_message_type gpr_format_message_import; gpr_strdup_type gpr_strdup_import; gpr_asprintf_type gpr_asprintf_import; -gpr_format_timespec_type gpr_format_timespec_import; gpr_mu_init_type gpr_mu_init_import; gpr_mu_destroy_type gpr_mu_destroy_import; gpr_mu_lock_type gpr_mu_lock_import; @@ -471,7 +470,6 @@ void grpc_rb_load_imports(HMODULE library) { gpr_format_message_import = (gpr_format_message_type) GetProcAddress(library, "gpr_format_message"); gpr_strdup_import = (gpr_strdup_type) GetProcAddress(library, "gpr_strdup"); gpr_asprintf_import = (gpr_asprintf_type) GetProcAddress(library, "gpr_asprintf"); - gpr_format_timespec_import = (gpr_format_timespec_type) GetProcAddress(library, "gpr_format_timespec"); gpr_mu_init_import = (gpr_mu_init_type) GetProcAddress(library, "gpr_mu_init"); gpr_mu_destroy_import = (gpr_mu_destroy_type) GetProcAddress(library, "gpr_mu_destroy"); gpr_mu_lock_import = (gpr_mu_lock_type) GetProcAddress(library, "gpr_mu_lock"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index b4107641a4..f01c9c8248 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -641,9 +641,6 @@ extern gpr_strdup_type gpr_strdup_import; typedef int(*gpr_asprintf_type)(char** strp, const char* format, ...) GPR_PRINT_FORMAT_CHECK(2, 3); extern gpr_asprintf_type gpr_asprintf_import; #define gpr_asprintf gpr_asprintf_import -typedef char*(*gpr_format_timespec_type)(gpr_timespec); -extern gpr_format_timespec_type gpr_format_timespec_import; -#define gpr_format_timespec gpr_format_timespec_import typedef void(*gpr_mu_init_type)(gpr_mu* mu); extern gpr_mu_init_type gpr_mu_init_import; #define gpr_mu_init gpr_mu_init_import diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 95deb1f17a..9a79b468dd 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -257,7 +257,6 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) gpr_cpu_current_cpu); printf("%lx", (unsigned long) gpr_strdup); printf("%lx", (unsigned long) gpr_asprintf); - printf("%lx", (unsigned long) gpr_format_timespec); printf("%lx", (unsigned long) gpr_mu_init); printf("%lx", (unsigned long) gpr_mu_destroy); printf("%lx", (unsigned long) gpr_mu_lock); -- cgit v1.2.3 From 9a6c722e301be70715fa4f16cea22d172d605615 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 13 Jul 2018 12:09:55 -0700 Subject: Rewrite registry to know type --- src/core/lib/channel/channelz.cc | 4 +- src/core/lib/channel/channelz_registry.cc | 30 ++++++-- src/core/lib/channel/channelz_registry.h | 72 +++++++++----------- src/core/lib/surface/init.cc | 4 +- test/core/channel/channelz_registry_test.cc | 102 +++++++++++++++------------- 5 files changed, 118 insertions(+), 94 deletions(-) (limited to 'test/core') diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 2074cb0cc5..923b8043cd 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -92,14 +92,14 @@ ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes) : channel_(channel), target_(nullptr), channel_uuid_(-1) { trace_.Init(channel_tracer_max_nodes); target_ = UniquePtr(grpc_channel_get_target(channel_)); - channel_uuid_ = ChannelzRegistry::Register(this); + channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } ChannelNode::~ChannelNode() { trace_.Destroy(); - ChannelzRegistry::Unregister(channel_uuid_); + ChannelzRegistry::UnregisterChannelNode(channel_uuid_); } void ChannelNode::RecordCallStarted() { diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 023ede552a..43cace1975 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -25,10 +25,12 @@ #include #include +#include #include namespace grpc_core { +namespace channelz { namespace { // singleton instance of the registry. @@ -49,12 +51,32 @@ ChannelzRegistry::ChannelzRegistry() { gpr_mu_init(&mu_); } ChannelzRegistry::~ChannelzRegistry() { gpr_mu_destroy(&mu_); } -void ChannelzRegistry::InternalUnregister(intptr_t uuid) { +intptr_t ChannelzRegistry::InternalRegisterEntry(const RegistryEntry& entry) { + mu_guard guard(&mu_); + entities_.push_back(entry); + intptr_t uuid = entities_.size(); + return uuid; +} + +void ChannelzRegistry::InternalUnregisterEntry(intptr_t uuid, EntityType type) { GPR_ASSERT(uuid >= 1); - gpr_mu_lock(&mu_); + mu_guard guard(&mu_); GPR_ASSERT(static_cast(uuid) <= entities_.size()); - entities_[uuid - 1] = nullptr; - gpr_mu_unlock(&mu_); + GPR_ASSERT(entities_[uuid - 1].type == type); + entities_[uuid - 1].object = nullptr; +} + +void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) { + mu_guard guard(&mu_); + if (uuid < 1 || uuid > static_cast(entities_.size())) { + return nullptr; + } + if (entities_[uuid - 1].type == type) { + return entities_[uuid - 1].object; + } else { + return nullptr; + } } +} // namespace channelz } // namespace grpc_core diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h index a5a187a054..cc069d9145 100644 --- a/src/core/lib/channel/channelz_registry.h +++ b/src/core/lib/channel/channelz_registry.h @@ -27,6 +27,7 @@ #include namespace grpc_core { +namespace channelz { // singleton registry object to track all objects that are needed to support // channelz bookkeeping. All objects share globally distributed uuids. @@ -38,23 +39,31 @@ class ChannelzRegistry { // To be callen in grpc_shutdown(); static void Shutdown(); - // globally registers a channelz Object. Returns its unique uuid - template - static intptr_t Register(Object* object) { - return Default()->InternalRegister(object); + static intptr_t RegisterChannelNode(ChannelNode* channel_node) { + RegistryEntry entry(channel_node, EntityType::kChannelNode); + return Default()->InternalRegisterEntry(entry); } - - // globally unregisters the object that is associated to uuid. - static void Unregister(intptr_t uuid) { Default()->InternalUnregister(uuid); } - - // if object with uuid has previously been registered, returns the - // Object associated with that uuid. Else returns nullptr. - template - static Object* Get(intptr_t uuid) { - return Default()->InternalGet(uuid); + static void UnregisterChannelNode(intptr_t uuid) { + Default()->InternalUnregisterEntry(uuid, EntityType::kChannelNode); + } + static ChannelNode* GetChannelNode(intptr_t uuid) { + void* gotten = Default()->InternalGetEntry(uuid, EntityType::kChannelNode); + return gotten == nullptr ? nullptr : static_cast(gotten); } private: + enum class EntityType { + kChannelNode, + kUnset, + }; + + struct RegistryEntry { + RegistryEntry(void* object_in, EntityType type_in) + : object(object_in), type(type_in) {} + void* object; + EntityType type; + }; + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE @@ -64,40 +73,23 @@ class ChannelzRegistry { // Returned the singleton instance of ChannelzRegistry; static ChannelzRegistry* Default(); - // globally registers a channelz Object. Returns its unique uuid - template - intptr_t InternalRegister(Object* object) { - gpr_mu_lock(&mu_); - entities_.push_back(static_cast(object)); - intptr_t uuid = entities_.size(); - gpr_mu_unlock(&mu_); - return uuid; - } + // globally registers an Entry. Returns its unique uuid + intptr_t InternalRegisterEntry(const RegistryEntry& entry); - // globally unregisters the object that is associated to uuid. - void InternalUnregister(intptr_t uuid); - - // if object with uuid has previously been registered, returns the - // Object associated with that uuid. Else returns nullptr. - template - Object* InternalGet(intptr_t uuid) { - gpr_mu_lock(&mu_); - if (uuid < 1 || uuid > static_cast(entities_.size())) { - gpr_mu_unlock(&mu_); - return nullptr; - } - Object* ret = static_cast(entities_[uuid - 1]); - gpr_mu_unlock(&mu_); - return ret; - } + // globally unregisters the object that is associated to uuid. Also does + // sanity check that an object doesn't try to unregister the wrong type. + void InternalUnregisterEntry(intptr_t uuid, EntityType type); - // private members + // if object with uuid has previously been registered as the correct type, + // returns the void* associated with that uuid. Else returns nullptr. + void* InternalGetEntry(intptr_t uuid, EntityType type); // protects entities_ and uuid_ gpr_mu mu_; - InlinedVector entities_; + InlinedVector entities_; }; +} // namespace channelz } // namespace grpc_core #endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H */ diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index 16be81e9c2..0ad82fed99 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -127,7 +127,7 @@ void grpc_init(void) { grpc_slice_intern_init(); grpc_mdctx_global_init(); grpc_channel_init_init(); - grpc_core::ChannelzRegistry::Init(); + grpc_core::channelz::ChannelzRegistry::Init(); grpc_security_pre_init(); grpc_core::ExecCtx::GlobalInit(); grpc_iomgr_init(); @@ -176,7 +176,7 @@ void grpc_shutdown(void) { grpc_mdctx_global_shutdown(); grpc_handshaker_factory_registry_shutdown(); grpc_slice_intern_shutdown(); - grpc_core::ChannelzRegistry::Shutdown(); + grpc_core::channelz::ChannelzRegistry::Shutdown(); grpc_stats_shutdown(); grpc_core::Fork::GlobalShutdown(); } diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc index 24e50933d7..06363d00e2 100644 --- a/test/core/channel/channelz_registry_test.cc +++ b/test/core/channel/channelz_registry_test.cc @@ -19,17 +19,20 @@ #include #include +#include #include #include #include #include "src/core/lib/channel/channel_trace.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/json/json.h" +#include "src/core/lib/surface/channel.h" #include "test/core/util/test_config.h" @@ -37,27 +40,55 @@ #include namespace grpc_core { +namespace channelz { namespace testing { +namespace { + +class ChannelFixture { + public: + ChannelFixture() { + grpc_arg client_a[1]; + client_a[0].type = GRPC_ARG_INTEGER; + client_a[0].key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); + client_a[0].value.integer = true; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; + channel_ = + grpc_insecure_channel_create("fake_target", &client_args, nullptr); + } + + ~ChannelFixture() { grpc_channel_destroy(channel_); } + + grpc_channel* channel() { return channel_; } + + private: + grpc_channel* channel_; +}; + +} // namespace // Tests basic ChannelTrace functionality like construction, adding trace, and // lookups by uuid. TEST(ChannelzRegistryTest, UuidStartsAboveZeroTest) { - int object_to_register; - intptr_t uuid = ChannelzRegistry::Register(&object_to_register); + ChannelFixture channel; + ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(channel.channel()); + intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); EXPECT_GT(uuid, 0) << "First uuid chose must be greater than zero. Zero if " "reserved according to " "https://github.com/grpc/proposal/blob/master/" "A14-channelz.md"; - ChannelzRegistry::Unregister(uuid); + ChannelzRegistry::UnregisterChannelNode(uuid); } TEST(ChannelzRegistryTest, UuidsAreIncreasing) { - int object_to_register; + ChannelFixture channel; + ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(channel.channel()); std::vector uuids; uuids.reserve(10); for (int i = 0; i < 10; ++i) { // reregister the same object. It's ok since we are just testing uuids - uuids.push_back(ChannelzRegistry::Register(&object_to_register)); + uuids.push_back(ChannelzRegistry::RegisterChannelNode(channelz_channel)); } for (size_t i = 1; i < uuids.size(); ++i) { EXPECT_LT(uuids[i - 1], uuids[i]) << "Uuids must always be increasing"; @@ -65,60 +96,39 @@ TEST(ChannelzRegistryTest, UuidsAreIncreasing) { } TEST(ChannelzRegistryTest, RegisterGetTest) { - int object_to_register = 42; - intptr_t uuid = ChannelzRegistry::Register(&object_to_register); - int* retrieved = ChannelzRegistry::Get(uuid); - EXPECT_EQ(&object_to_register, retrieved); -} - -TEST(ChannelzRegistryTest, MultipleTypeTest) { - int int_to_register = 42; - intptr_t int_uuid = ChannelzRegistry::Register(&int_to_register); - std::string str_to_register = "hello world"; - intptr_t str_uuid = ChannelzRegistry::Register(&str_to_register); - int* retrieved_int = ChannelzRegistry::Get(int_uuid); - std::string* retrieved_str = ChannelzRegistry::Get(str_uuid); - EXPECT_EQ(&int_to_register, retrieved_int); - EXPECT_EQ(&str_to_register, retrieved_str); + ChannelFixture channel; + ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(channel.channel()); + intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); + ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); + EXPECT_EQ(channelz_channel, retrieved); } TEST(ChannelzRegistryTest, RegisterManyItems) { - int object_to_register = 42; + ChannelFixture channel; + ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(channel.channel()); for (int i = 0; i < 100; i++) { - intptr_t uuid = ChannelzRegistry::Register(&object_to_register); - int* retrieved = ChannelzRegistry::Get(uuid); - EXPECT_EQ(&object_to_register, retrieved); + intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); + ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); + EXPECT_EQ(channelz_channel, retrieved); } } -namespace { -class Foo { - public: - int bar; -}; -} // namespace - -TEST(ChannelzRegistryTest, CustomObjectTest) { - Foo* foo = New(); - foo->bar = 1024; - intptr_t uuid = ChannelzRegistry::Register(foo); - Foo* retrieved = ChannelzRegistry::Get(uuid); - EXPECT_EQ(foo, retrieved); - Delete(foo); -} - TEST(ChannelzRegistryTest, NullIfNotPresentTest) { - int object_to_register = 42; - intptr_t uuid = ChannelzRegistry::Register(&object_to_register); + ChannelFixture channel; + ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(channel.channel()); + intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); // try to pull out a uuid that does not exist. - int* nonexistant = ChannelzRegistry::Get(uuid + 1); + ChannelNode* nonexistant = ChannelzRegistry::GetChannelNode(uuid + 1); EXPECT_EQ(nonexistant, nullptr); - int* retrieved = ChannelzRegistry::Get(uuid); - EXPECT_EQ(object_to_register, *retrieved); - EXPECT_EQ(&object_to_register, retrieved); + ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); + EXPECT_EQ(channelz_channel, retrieved); } } // namespace testing +} // namespace channelz } // namespace grpc_core int main(int argc, char** argv) { -- cgit v1.2.3 From 97066fd0e46a82ffa6b012117cfd428888d255f3 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 13 Jul 2018 14:05:27 -0700 Subject: Support for GetTopChannels --- .../client_channel/lb_policy/grpclb/grpclb.cc | 3 + src/core/lib/channel/channel_trace.cc | 2 +- src/core/lib/channel/channel_trace.h | 2 +- src/core/lib/channel/channelz.cc | 37 ++++++---- src/core/lib/channel/channelz.h | 12 +++- src/core/lib/channel/channelz_registry.cc | 45 ++++++++++++ src/core/lib/channel/channelz_registry.h | 7 ++ src/core/lib/surface/channel.cc | 7 ++ test/core/channel/channel_trace_test.cc | 2 +- test/core/channel/channelz_test.cc | 81 ++++++++++++++++++++-- test/core/end2end/tests/channelz.cc | 16 ++--- test/cpp/util/channel_trace_proto_helper.cc | 14 ++-- test/cpp/util/channel_trace_proto_helper.h | 5 +- 13 files changed, 195 insertions(+), 38 deletions(-) (limited to 'test/core') diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 263b51ae89..01d05dbb14 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -1004,6 +1004,9 @@ grpc_channel_args* BuildBalancerChannelArgs( // A channel arg indicating the target is a grpclb load balancer. grpc_channel_arg_integer_create( const_cast(GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 1), + // A channel arg indicating the target is a grpclb load balancer. + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL), 1), }; // Construct channel args. grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove( diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index 0f655d8716..5a4cf8c7e1 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -206,7 +206,7 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { } } -grpc_json* ChannelTrace::RenderJSON() const { +grpc_json* ChannelTrace::RenderJson() const { if (!max_list_size_) return nullptr; // tracing is disabled if max_events == 0 grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT); diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h index 0dd162a777..596af7402f 100644 --- a/src/core/lib/channel/channel_trace.h +++ b/src/core/lib/channel/channel_trace.h @@ -71,7 +71,7 @@ class ChannelTrace { // Creates and returns the raw grpc_json object, so a parent channelz // object may incorporate the json before rendering. - grpc_json* RenderJSON() const; + grpc_json* RenderJson() const; private: // Types of objects that can be references by trace events. diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 923b8043cd..c8a1d179fa 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -110,7 +110,7 @@ void ChannelNode::RecordCallStarted() { void ChannelNode::PopulateConnectivityState(grpc_json* json) {} -char* ChannelNode::RenderJSON() { +grpc_json* ChannelNode::RenderJson() { // We need to track these three json objects to build our object grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; @@ -130,13 +130,14 @@ char* ChannelNode::RenderJSON() { json = data; json_iterator = nullptr; PopulateConnectivityState(json); + GPR_ASSERT(target_.get() != nullptr); json_iterator = grpc_json_create_child( json_iterator, json, "target", target_.get(), GRPC_JSON_STRING, false); // fill in the channel trace if applicable - grpc_json* trace = trace_->RenderJSON(); + grpc_json* trace = trace_->RenderJson(); if (trace != nullptr) { // we manuall link up and fill the child since it was created for us in - // ChannelTrace::RenderJSON + // ChannelTrace::RenderJson json_iterator = grpc_json_link_child(json, trace, json_iterator); trace->parent = json; trace->value = nullptr; @@ -146,22 +147,30 @@ char* ChannelNode::RenderJSON() { // reset the parent to be the data object. json = data; json_iterator = nullptr; - // We use -1 as sentinel values since proto default value for integers is - // zero, and the confuses the parser into thinking the value weren't present - json_iterator = - add_num_str(json, json_iterator, "callsStarted", calls_started_); - json_iterator = - add_num_str(json, json_iterator, "callsSucceeded", calls_succeeded_); - json_iterator = - add_num_str(json, json_iterator, "callsFailed", calls_failed_); + if (calls_started_ != 0) { + json_iterator = + add_num_str(json, json_iterator, "callsStarted", calls_started_); + } + if (calls_succeeded_ != 0) { + json_iterator = + add_num_str(json, json_iterator, "callsSucceeded", calls_succeeded_); + } + if (calls_failed_) { + json_iterator = + add_num_str(json, json_iterator, "callsFailed", calls_failed_); + } gpr_timespec ts = grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME); json_iterator = grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp", fmt_time(ts), GRPC_JSON_STRING, true); - // render and return the over json object - char* json_str = grpc_json_dump_to_string(top_level_json, 0); - grpc_json_destroy(top_level_json); + return top_level_json; +} + +char* ChannelNode::RenderJsonString() { + grpc_json* json = RenderJson(); + char* json_str = grpc_json_dump_to_string(json, 0); + grpc_json_destroy(json); return json_str; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 9bd01ece50..abcf907c2b 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -35,6 +35,10 @@ #define GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC \ "grpc.channelz_channel_node_creation_func" +// Channel arg key to signal that the channel is an internal channel. +#define GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL \ + "grpc.channelz_channel_is_internal_channel" + namespace grpc_core { namespace channelz { @@ -55,7 +59,8 @@ class ChannelNode : public RefCounted { gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1))); } - char* RenderJSON(); + grpc_json* RenderJson(); + char* RenderJsonString(); // helper for getting and populating connectivity state. It is virtual // because it allows the client_channel specific code to live in ext/ @@ -72,6 +77,10 @@ class ChannelNode : public RefCounted { bool ChannelIsDestroyed() { return channel_ == nullptr; } intptr_t channel_uuid() { return channel_uuid_; } + bool is_top_level_channel() { return is_top_level_channel_; } + void set_is_top_level_channel(bool is_top_level_channel) { + is_top_level_channel_ = is_top_level_channel; + } protected: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE @@ -90,6 +99,7 @@ class ChannelNode : public RefCounted { gpr_atm calls_failed_ = 0; gpr_atm last_call_started_millis_ = 0; intptr_t channel_uuid_; + bool is_top_level_channel_ = true; ManualConstructor trace_; }; diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 43cace1975..b4dc3d1103 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -19,6 +19,7 @@ #include #include "src/core/lib/channel/channel_trace.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/memory.h" @@ -64,6 +65,7 @@ void ChannelzRegistry::InternalUnregisterEntry(intptr_t uuid, EntityType type) { GPR_ASSERT(static_cast(uuid) <= entities_.size()); GPR_ASSERT(entities_[uuid - 1].type == type); entities_[uuid - 1].object = nullptr; + entities_[uuid - 1].type = EntityType::kUnset; } void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) { @@ -78,5 +80,48 @@ void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) { } } +char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + InlinedVector top_level_channels; + // uuids index into entities one-off (idx 0 is really uuid 1, since 0 is + // reserver). However, we want to support requests coming in which + // start_channel_id=0, which signifies "give me everything." Hence this + // funky looking line below. + size_t start_idx = start_channel_id == 0 ? 0 : start_channel_id - 1; + for (size_t i = start_idx; i < entities_.size(); ++i) { + if (entities_[i].type == EntityType::kChannelNode) { + ChannelNode* channel_node = + static_cast(entities_[i].object); + if (channel_node->is_top_level_channel()) { + top_level_channels.push_back(channel_node); + } + } + } + if (top_level_channels.size() > 0) { + // create list of channels + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "channel", nullptr, GRPC_JSON_ARRAY, false); + for (size_t i = 0; i < top_level_channels.size(); ++i) { + grpc_json* channel_json = top_level_channels[i]->RenderJson(); + json_iterator = + grpc_json_link_child(array_parent, channel_json, json_iterator); + channel_json->parent = array_parent; + channel_json->value = nullptr; + channel_json->key = nullptr; + channel_json->owns_value = false; + } + } + // For now we do not have any pagination rules. In the future we could + // pick a constant for max_channels_sent for a GetTopChannels request. + // Tracking: https://github.com/grpc/grpc/issues/16019. + json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr, + GRPC_JSON_TRUE, false); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} + } // namespace channelz } // namespace grpc_core diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h index cc069d9145..2fefc9f629 100644 --- a/src/core/lib/channel/channelz_registry.h +++ b/src/core/lib/channel/channelz_registry.h @@ -51,6 +51,11 @@ class ChannelzRegistry { return gotten == nullptr ? nullptr : static_cast(gotten); } + // todo, protect me + static char* GetTopChannels(intptr_t start_channel_id) { + return Default()->InternalGetTopChannels(start_channel_id); + } + private: enum class EntityType { kChannelNode, @@ -84,6 +89,8 @@ class ChannelzRegistry { // returns the void* associated with that uuid. Else returns nullptr. void* InternalGetEntry(intptr_t uuid, EntityType type); + char* InternalGetTopChannels(intptr_t start_channel_id); + // protects entities_ and uuid_ gpr_mu mu_; InlinedVector entities_; diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 8f3ad6c191..dd3880f18e 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -105,6 +105,7 @@ grpc_channel* grpc_channel_create_with_builder( channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type); size_t channel_tracer_max_nodes = 0; // default to off bool channelz_enabled = false; + bool internal_channel = false; // this creates the default ChannelNode. Different types of channels may // override this to ensure a correct ChannelNode is created. grpc_core::channelz::ChannelNodeCreationFunc channel_node_create_func = @@ -158,6 +159,9 @@ grpc_channel* grpc_channel_create_with_builder( channel_node_create_func = reinterpret_cast( args->args[i].value.pointer.p); + } else if (0 == strcmp(args->args[i].key, + GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL)) { + internal_channel = grpc_channel_arg_get_bool(&args->args[i], false); } } @@ -165,6 +169,9 @@ grpc_channel* grpc_channel_create_with_builder( if (channelz_enabled) { channel->channelz_channel = channel_node_create_func(channel, channel_tracer_max_nodes); + if (internal_channel || !channel->is_client) { + channel->channelz_channel->set_is_top_level_channel(false); + } channel->channelz_channel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index bbddee3f14..07b0e3de06 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -88,7 +88,7 @@ void AddSimpleTrace(ChannelTrace* tracer) { void ValidateChannelTrace(ChannelTrace* tracer, size_t expected_num_event_logged, size_t max_nodes) { if (!max_nodes) return; - grpc_json* json = tracer->RenderJSON(); + grpc_json* json = tracer->RenderJson(); EXPECT_NE(json, nullptr); char* json_str = grpc_json_dump_to_string(json, 0); grpc_json_destroy(json); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 058eea914c..1ed36acb61 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -67,9 +67,39 @@ grpc_json* GetJsonChild(grpc_json* parent, const char* key) { return nullptr; } +void ValidateJsonArraySize(grpc_json* json, const char* key, + size_t expected_size) { + grpc_json* arr = GetJsonChild(json, key); + if (expected_size == 0) { + ASSERT_EQ(arr, nullptr); + return; + } + ASSERT_NE(arr, nullptr); + ASSERT_EQ(arr->type, GRPC_JSON_ARRAY); + size_t count = 0; + for (grpc_json* child = arr->child; child != nullptr; child = child->next) { + ++count; + } + ASSERT_EQ(count, expected_size); +} + +void ValidateGetTopChannels(size_t expected_channels) { + char* json_str = ChannelzRegistry::GetTopChannels(0); + grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(json_str); + grpc_json* parsed_json = grpc_json_parse_string(json_str); + // This check will naturally have to change when we support pagination. + // tracked: https://github.com/grpc/grpc/issues/16019. + ValidateJsonArraySize(parsed_json, "channel", expected_channels); + grpc_json* end = GetJsonChild(parsed_json, "end"); + EXPECT_NE(end, nullptr); + EXPECT_EQ(end->type, GRPC_JSON_TRUE); + grpc_json_destroy(parsed_json); + gpr_free(json_str); +} + class ChannelFixture { public: - ChannelFixture(int max_trace_nodes) { + ChannelFixture(int max_trace_nodes = 0) { grpc_arg client_a[2]; client_a[0].type = GRPC_ARG_INTEGER; client_a[0].key = @@ -99,6 +129,10 @@ struct validate_channel_data_args { void ValidateChildInteger(grpc_json* json, int64_t expect, const char* key) { grpc_json* gotten_json = GetJsonChild(json, key); + if (expect == 0) { + ASSERT_EQ(gotten_json, nullptr); + return; + } ASSERT_NE(gotten_json, nullptr); int64_t gotten_number = (int64_t)strtol(gotten_json->value, nullptr, 0); EXPECT_EQ(gotten_number, expect); @@ -115,7 +149,7 @@ void ValidateCounters(char* json_str, validate_channel_data_args args) { } void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { - char* json_str = channel->RenderJSON(); + char* json_str = channel->RenderJsonString(); grpc::testing::ValidateChannelProtoJsonTranslation(json_str); ValidateCounters(json_str, args); gpr_free(json_str); @@ -141,9 +175,7 @@ TEST_P(ChannelzChannelTest, BasicChannel) { ChannelFixture channel(GetParam()); ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel.channel()); - char* json_str = channelz_channel->RenderJSON(); - ValidateCounters(json_str, {0, 0, 0}); - gpr_free(json_str); + ValidateChannel(channelz_channel, {0, 0, 0}); } TEST(ChannelzChannelTest, ChannelzDisabled) { @@ -199,6 +231,45 @@ TEST_P(ChannelzChannelTest, LastCallStartedMillis) { EXPECT_NE(millis1, millis4); } +TEST(ChannelzGetTopChannelsTest, BasicTest) { + grpc_core::ExecCtx exec_ctx; + ChannelFixture channel; + ValidateGetTopChannels(1); +} + +TEST(ChannelzGetTopChannelsTest, NoChannelsTest) { + grpc_core::ExecCtx exec_ctx; + ValidateGetTopChannels(0); +} + +TEST(ChannelzGetTopChannelsTest, ManyChannelsTest) { + grpc_core::ExecCtx exec_ctx; + ChannelFixture channels[10]; + (void)channels; // suppress unused variable error + ValidateGetTopChannels(10); +} + +TEST(ChannelzGetTopChannelsTest, InternalChannelTest) { + grpc_core::ExecCtx exec_ctx; + ChannelFixture channels[10]; + (void)channels; // suppress unused variable error + // create an internal channel + grpc_arg client_a[2]; + client_a[0].type = GRPC_ARG_INTEGER; + client_a[0].key = + const_cast(GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL); + client_a[0].value.integer = 1; + client_a[1].type = GRPC_ARG_INTEGER; + client_a[1].key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); + client_a[1].value.integer = true; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; + grpc_channel* internal_channel = + grpc_insecure_channel_create("fake_target", &client_args, nullptr); + // The internal channel should not be returned from the request + ValidateGetTopChannels(10); + grpc_channel_destroy(internal_channel); +} + INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest, ::testing::Values(0, 1, 2, 6, 10, 15)); diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index eb052119ca..533703a2be 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -209,27 +209,27 @@ static void test_channelz(grpc_end2end_test_config config) { grpc_channel_get_channelz_node(f.client); GPR_ASSERT(channelz_channel != nullptr); - char* json = channelz_channel->RenderJSON(); + char* json = channelz_channel->RenderJsonString(); GPR_ASSERT(json != nullptr); - GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"0\"")); - GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"0\"")); - GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"0\"")); + // nothing is present yet + GPR_ASSERT(nullptr == strstr(json, "\"callsStarted\"")); + GPR_ASSERT(nullptr == strstr(json, "\"callsFailed\"")); + GPR_ASSERT(nullptr == strstr(json, "\"callsSucceeded\"")); gpr_free(json); // one successful request run_one_request(config, f, true); - json = channelz_channel->RenderJSON(); + json = channelz_channel->RenderJsonString(); GPR_ASSERT(json != nullptr); GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"1\"")); - GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"0\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); gpr_free(json); // one failed request run_one_request(config, f, false); - json = channelz_channel->RenderJSON(); + json = channelz_channel->RenderJsonString(); GPR_ASSERT(json != nullptr); gpr_log(GPR_INFO, "%s", json); GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); @@ -264,7 +264,7 @@ static void test_channelz_with_channel_trace(grpc_end2end_test_config config) { grpc_channel_get_channelz_node(f.client); GPR_ASSERT(channelz_channel != nullptr); - char* json = channelz_channel->RenderJSON(); + char* json = channelz_channel->RenderJsonString(); GPR_ASSERT(json != nullptr); gpr_log(GPR_INFO, "%s", json); GPR_ASSERT(nullptr != strstr(json, "\"trace\"")); diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index ee310784c2..137f278640 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -64,13 +64,17 @@ void VaidateProtoJsonTranslation(char* json_c_str) { } // namespace -void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str) { - VaidateProtoJsonTranslation( - tracer_json_c_str); +void ValidateChannelTraceProtoJsonTranslation(char* json_c_str) { + VaidateProtoJsonTranslation(json_c_str); } -void ValidateChannelProtoJsonTranslation(char* channel_json_c_str) { - VaidateProtoJsonTranslation(channel_json_c_str); +void ValidateChannelProtoJsonTranslation(char* json_c_str) { + VaidateProtoJsonTranslation(json_c_str); +} + +void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str) { + VaidateProtoJsonTranslation( + json_c_str); } } // namespace testing diff --git a/test/cpp/util/channel_trace_proto_helper.h b/test/cpp/util/channel_trace_proto_helper.h index d1a3603372..74c15f04f1 100644 --- a/test/cpp/util/channel_trace_proto_helper.h +++ b/test/cpp/util/channel_trace_proto_helper.h @@ -22,8 +22,9 @@ namespace grpc { namespace testing { -void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str); -void ValidateChannelProtoJsonTranslation(char* channel_json_c_str); +void ValidateChannelTraceProtoJsonTranslation(char* json_c_str); +void ValidateChannelProtoJsonTranslation(char* json_c_str); +void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str); } // namespace testing } // namespace grpc -- cgit v1.2.3 From adfa81987af4b61eb11c92c6e4bedc3bed3028c9 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 17 Jul 2018 09:35:56 -0700 Subject: Un-pare simple_request --- test/core/end2end/tests/simple_request.cc | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'test/core') diff --git a/test/core/end2end/tests/simple_request.cc b/test/core/end2end/tests/simple_request.cc index 7ec11d8ac3..941d9ae319 100644 --- a/test/core/end2end/tests/simple_request.cc +++ b/test/core/end2end/tests/simple_request.cc @@ -256,24 +256,24 @@ static void test_invoke_simple_request(grpc_end2end_test_config config) { config.tear_down_data(&f); } -// static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { -// int i; -// grpc_end2end_test_fixture f = -// begin_test(config, "test_invoke_10_simple_requests", nullptr, nullptr); -// for (i = 0; i < 10; i++) { -// simple_request_body(config, f); -// gpr_log(GPR_INFO, "Running test: Passed simple request %d", i); -// } -// end_test(&f); -// config.tear_down_data(&f); -// } +static void test_invoke_10_simple_requests(grpc_end2end_test_config config) { + int i; + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_10_simple_requests", nullptr, nullptr); + for (i = 0; i < 10; i++) { + simple_request_body(config, f); + gpr_log(GPR_INFO, "Running test: Passed simple request %d", i); + } + end_test(&f); + config.tear_down_data(&f); +} void simple_request(grpc_end2end_test_config config) { - // int i; - // for (i = 0; i < 10; i++) { - test_invoke_simple_request(config); - // } - // test_invoke_10_simple_requests(config); + int i; + for (i = 0; i < 10; i++) { + test_invoke_simple_request(config); + } + test_invoke_10_simple_requests(config); } void simple_request_pre_init(void) {} -- cgit v1.2.3 From 0f6e4dd20d3e79d3465a7bf8a21d704e7b67b102 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 17 Jul 2018 11:26:55 -0700 Subject: reviewer feedback: --- .../client_channel/client_channel_channelz.h | 3 + src/core/ext/filters/client_channel/lb_policy.h | 1 + .../client_channel/lb_policy/grpclb/grpclb.cc | 1 + .../lb_policy/pick_first/pick_first.cc | 8 +- .../lb_policy/round_robin/round_robin.cc | 1 + src/core/ext/filters/client_channel/subchannel.cc | 5 +- src/core/ext/filters/client_channel/subchannel.h | 5 +- src/core/lib/channel/channelz.cc | 2 +- src/core/lib/channel/channelz.h | 4 +- src/core/lib/gprpp/inlined_vector.h | 88 ++++---- test/core/gprpp/inlined_vector_test.cc | 236 ++++++++++++++++----- 11 files changed, 232 insertions(+), 122 deletions(-) (limited to 'test/core') diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index e5be52e778..0547109d36 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -28,6 +28,9 @@ namespace grpc_core { +// TODO(ncteisen), this only contains the uuids of the children for now, +// since that is all that is strictly needed. In a future enhancement we will +// add human readable names as in the channelz.proto typedef InlinedVector ChildRefsList; namespace channelz { diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h index 7bc224ad81..3150df8847 100644 --- a/src/core/ext/filters/client_channel/lb_policy.h +++ b/src/core/ext/filters/client_channel/lb_policy.h @@ -208,6 +208,7 @@ class LoadBalancingPolicy // Dummy classes needed for alignment issues. // See https://github.com/grpc/grpc/issues/16032 for context. + // TODO(ncteisen): remove this as soon as the issue is resolved. ChildRefsList dummy_list_foo; ChildRefsList dummy_list_bar; }; diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 622c03a8d1..f757d6057c 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -135,6 +135,7 @@ class GrpcLb : public LoadBalancingPolicy { void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override; void PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) override; void ExitIdleLocked() override; + // TODO(ncteisen): implement this in a follow up PR void FillChildRefsForChannelz(ChildRefsList* child_subchannels, ChildRefsList* child_channels) override {} diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 390b4ee1bb..c50deb9679 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -311,13 +311,14 @@ void PickFirst::FillChildRefsForChannelz( // TODO(ncteisen): implement a de dup loop that is not O(n^2). Might // have to implement lightweight set. For now, we don't care about // performance when channelz requests are made. - bool add_elt = true; + bool found = false; for (size_t j = 0; j < child_subchannels_to_fill->size(); ++j) { if ((*child_subchannels_to_fill)[j] == child_subchannels_[i]) { - add_elt = false; + found = true; + break; } } - if (add_elt) { + if (!found) { child_subchannels_to_fill->push_back(child_subchannels_[i]); } } @@ -351,7 +352,6 @@ void PickFirst::UpdateChildRefsLocked() { } } } - // atomically update the data that channelz will actually be looking at. mu_guard guard(&child_refs_mu_); child_subchannels_ = std::move(cs); diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index e6bc94a008..4c42b2063f 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -69,6 +69,7 @@ class RoundRobin : public LoadBalancingPolicy { void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override; void PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) override; void ExitIdleLocked() override; + // TODO(ncteisen): implement this in a follow up PR void FillChildRefsForChannelz(ChildRefsList* child_subchannels, ChildRefsList* child_channels) override {} diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 86026b70a5..9d608c3c55 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -181,9 +181,7 @@ static void connection_destroy(void* arg, grpc_error* error) { static void subchannel_destroy(void* arg, grpc_error* error) { grpc_subchannel* c = static_cast(arg); - if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel.reset(); - } + c->channelz_subchannel.reset(); gpr_free((void*)c->filters); grpc_channel_args_destroy(c->args); grpc_connectivity_state_destroy(&c->state_tracker); @@ -380,7 +378,6 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, c->backoff.Init(backoff_options); gpr_mu_init(&c->mu); - // This is just a placeholder channelz class for for now. const grpc_arg* arg = grpc_channel_args_find(c->args, GRPC_ARG_ENABLE_CHANNELZ); bool channelz_enabled = grpc_channel_arg_get_bool(arg, false); diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index f76be81543..9e53f7d542 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -21,6 +21,7 @@ #include +#include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/connector.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/gpr/arena.h" @@ -71,10 +72,6 @@ typedef struct grpc_subchannel_key grpc_subchannel_key; namespace grpc_core { -namespace channelz { -class SubchannelNode; -} - class ConnectedSubchannel : public RefCountedWithTracing { public: struct CallArgs { diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 5a0620c51f..79a9220503 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -131,7 +131,7 @@ RefCountedPtr ChannelNode::MakeChannelNode( channel, channel_tracer_max_nodes); } -SubchannelNode::SubchannelNode() : subchannel_uuid_(-1) { +SubchannelNode::SubchannelNode() { subchannel_uuid_ = ChannelzRegistry::Register(this); } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index f2c5ecddbf..7184af93ec 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -96,8 +96,8 @@ class ChannelNode : public RefCounted { }; // Placeholds channelz class for subchannels. All this can do now is track its -// uuid (this information is needed by the parent channelz class). In the next -// PR I will build this out to support the GetSubchannel channelz request. +// uuid (this information is needed by the parent channelz class). +// TODO(ncteisen): build this out to support the GetSubchannel channelz request. class SubchannelNode : public RefCounted { public: SubchannelNode(); diff --git a/src/core/lib/gprpp/inlined_vector.h b/src/core/lib/gprpp/inlined_vector.h index 9c2e131455..508fb2eed1 100644 --- a/src/core/lib/gprpp/inlined_vector.h +++ b/src/core/lib/gprpp/inlined_vector.h @@ -51,73 +51,30 @@ class InlinedVector { InlinedVector() { init_data(); } ~InlinedVector() { destroy_elements(); } - // copy constructors + // copy constructor InlinedVector(const InlinedVector& v) { init_data(); - // if v is allocated, then we copy it's buffer - if (v.dynamic_ != nullptr) { - reserve(v.capacity_); - memcpy(dynamic_, v.dynamic_, v.capacity_ * sizeof(T)); - } else { - memcpy(inline_, v.inline_, v.capacity_ * sizeof(T)); - dynamic_ = nullptr; - } - // copy over metadata - size_ = v.size_; - capacity_ = v.capacity_; + copy_from(v); } + InlinedVector& operator=(const InlinedVector& v) { if (this != &v) { clear(); - // if v is allocated, then we copy it's buffer - if (v.dynamic_ != nullptr) { - reserve(v.capacity_); - memcpy(dynamic_, v.dynamic_, v.capacity_ * sizeof(T)); - } else { - memcpy(inline_, v.inline_, v.capacity_ * sizeof(T)); - dynamic_ = nullptr; - } - // copy over metadata - size_ = v.size_; - capacity_ = v.capacity_; + copy_from(v); } return *this; } - // move constructors + // move constructor InlinedVector(InlinedVector&& v) { - // if v is allocated, then we steal it's buffer - if (v.dynamic_ != nullptr) { - dynamic_ = v.dynamic_; - } else { - memcpy(inline_, v.inline_, v.capacity_ * sizeof(T)); - dynamic_ = nullptr; - } - // copy over metadata - size_ = v.size_; - capacity_ = v.capacity_; - // null out the original - v.dynamic_ = nullptr; - v.size_ = 0; - v.capacity_ = 0; + init_data(); + move_from(v); } + InlinedVector& operator=(InlinedVector&& v) { if (this != &v) { clear(); - // if v is allocated, then we steal it's buffer - if (v.dynamic_ != nullptr) { - dynamic_ = v.dynamic_; - } else { - memcpy(inline_, v.inline_, v.capacity_ * sizeof(T)); - dynamic_ = nullptr; - } - // copy over metadata - size_ = v.size_; - capacity_ = v.capacity_; - // null out the original - v.dynamic_ = nullptr; - v.size_ = 0; - v.capacity_ = 0; + move_from(v); } return *this; } @@ -166,6 +123,33 @@ class InlinedVector { void push_back(T&& value) { emplace_back(std::move(value)); } + void copy_from(const InlinedVector& v) { + // if copy over the buffer from v. + if (v.dynamic_ != nullptr) { + reserve(v.capacity_); + memcpy(dynamic_, v.dynamic_, v.size_ * sizeof(T)); + } else { + memcpy(inline_, v.inline_, v.size_ * sizeof(T)); + } + // copy over metadata + size_ = v.size_; + capacity_ = v.capacity_; + } + + void move_from(InlinedVector& v) { + // if v is allocated, then we steal its buffer, else we copy it. + if (v.dynamic_ != nullptr) { + dynamic_ = v.dynamic_; + } else { + memcpy(inline_, v.inline_, v.size_ * sizeof(T)); + } + // copy over metadata + size_ = v.size_; + capacity_ = v.capacity_; + // null out the original + v.init_data(); + } + size_t size() const { return size_; } bool empty() const { return size_ == 0; } diff --git a/test/core/gprpp/inlined_vector_test.cc b/test/core/gprpp/inlined_vector_test.cc index ba2f4d9e6f..1ef7da465c 100644 --- a/test/core/gprpp/inlined_vector_test.cc +++ b/test/core/gprpp/inlined_vector_test.cc @@ -27,9 +27,9 @@ namespace testing { namespace { template -static void FillVector(Vector* v, int len, int offset = 0) { +static void FillVector(Vector* v, int len, int start = 0) { for (int i = 0; i < len; i++) { - v->push_back(i + offset); + v->push_back(i + start); EXPECT_EQ(i + 1UL, v->size()); } } @@ -107,69 +107,195 @@ TEST(InlinedVectorTest, ConstIndexOperator) { const_func(v); } -TEST(InlinedVectorTest, CopyConstructorAndAssignment) { - typedef InlinedVector IntVec8; - for (size_t len = 0; len < 20; len++) { - IntVec8 original; - FillVector(&original, len); - EXPECT_EQ(len, original.size()); - EXPECT_LE(len, original.capacity()); +TEST(InlinedVectorTest, CopyConstructerInlined) { + const size_t kInlinedLength = 8; + const size_t kFillSize = kInlinedLength - 1; + typedef InlinedVector IntVec8; + IntVec8 original; + FillVector(&original, kFillSize); + EXPECT_EQ(kFillSize, original.size()); + EXPECT_LE(kFillSize, original.capacity()); + IntVec8 copy_constructed(original); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], copy_constructed[i]); + } +} + +TEST(InlinedVectorTest, CopyConstructerAllocated) { + const size_t kInlinedLength = 8; + const size_t kFillSize = kInlinedLength + 1; + typedef InlinedVector IntVec8; + IntVec8 original; + FillVector(&original, kFillSize); + EXPECT_EQ(kFillSize, original.size()); + EXPECT_LE(kFillSize, original.capacity()); + IntVec8 copy_constructed(original); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], copy_constructed[i]); + } +} - IntVec8 copy_constructed(original); +TEST(InlinedVectorTest, CopyAssignementInlined) { + const size_t kInlinedLength = 8; + const size_t kFillSize = kInlinedLength - 1; + typedef InlinedVector IntVec8; + IntVec8 original; + FillVector(&original, kFillSize); + EXPECT_EQ(kFillSize, original.size()); + EXPECT_LE(kFillSize, original.capacity()); + // copy assigned vector is inlined + { + IntVec8 copy_assigned; + FillVector(©_assigned, kInlinedLength - 1, 99); + copy_assigned = original; + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], copy_assigned[i]); + } + } + // copy assigned vector is allocated + { + IntVec8 copy_assigned; + FillVector(©_assigned, kInlinedLength + 1, 99); + copy_assigned = original; for (size_t i = 0; i < original.size(); ++i) { - EXPECT_TRUE(original[i] == copy_constructed[i]); + EXPECT_EQ(original[i], copy_assigned[i]); } + } +} - for (size_t start_len = 0; start_len < 20; start_len++) { - IntVec8 copy_assigned; - FillVector(©_assigned, start_len, 99); // Add dummy elements - copy_assigned = original; - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_TRUE(original[i] == copy_assigned[i]); - } +TEST(InlinedVectorTest, CopyAssignementAllocated) { + const size_t kInlinedLength = 8; + const size_t kFillSize = kInlinedLength + 1; + typedef InlinedVector IntVec8; + IntVec8 original; + FillVector(&original, kFillSize); + EXPECT_EQ(kFillSize, original.size()); + EXPECT_LE(kFillSize, original.capacity()); + // copy assigned vector is inlined + { + IntVec8 copy_assigned; + FillVector(©_assigned, kInlinedLength - 1, 99); + copy_assigned = original; + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], copy_assigned[i]); + } + } + // copy assigned vector is allocated + { + IntVec8 copy_assigned; + FillVector(©_assigned, kInlinedLength + 1, 99); + copy_assigned = original; + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], copy_assigned[i]); } } } -TEST(InlinedVectorTest, MoveConstructorAndAssignment) { - typedef InlinedVector IntVec8; - for (size_t len = 0; len < 20; len++) { - IntVec8 original; - const size_t inlined_capacity = original.capacity(); - FillVector(&original, len); - EXPECT_EQ(len, original.size()); - EXPECT_LE(len, original.capacity()); - - { - IntVec8 tmp(original); - auto* old_data = tmp.data(); - IntVec8 move_constructed(std::move(tmp)); - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_TRUE(original[i] == move_constructed[i]); - } - if (original.size() > inlined_capacity) { - // Allocation is moved as a whole, data stays in place. - EXPECT_TRUE(move_constructed.data() == old_data); - } else { - EXPECT_FALSE(move_constructed.data() == old_data); - } +TEST(InlinedVectorTest, MoveConstructorInlined) { + const size_t kInlinedLength = 8; + const size_t kFillSize = kInlinedLength - 1; + typedef InlinedVector IntVec8; + IntVec8 original; + FillVector(&original, kFillSize); + EXPECT_EQ(kFillSize, original.size()); + EXPECT_LE(kFillSize, original.capacity()); + IntVec8 tmp(original); + auto* old_data = tmp.data(); + IntVec8 move_constructed(std::move(tmp)); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], move_constructed[i]); + } + // original data was inlined so it should have been copied, not moved. + EXPECT_NE(move_constructed.data(), old_data); +} + +TEST(InlinedVectorTest, MoveConstructorAllocated) { + const size_t kInlinedLength = 8; + const size_t kFillSize = kInlinedLength + 1; + typedef InlinedVector IntVec8; + IntVec8 original; + FillVector(&original, kFillSize); + EXPECT_EQ(kFillSize, original.size()); + EXPECT_LE(kFillSize, original.capacity()); + IntVec8 tmp(original); + auto* old_data = tmp.data(); + IntVec8 move_constructed(std::move(tmp)); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], move_constructed[i]); + } + // original data was allocated, so it should been moved, not copied + EXPECT_EQ(move_constructed.data(), old_data); +} + +TEST(InlinedVectorTest, MoveAssignmentInlined) { + const size_t kInlinedLength = 8; + const size_t kFillSize = kInlinedLength - 1; + typedef InlinedVector IntVec8; + IntVec8 original; + FillVector(&original, kFillSize); + EXPECT_EQ(kFillSize, original.size()); + EXPECT_LE(kFillSize, original.capacity()); + // move assigned vector is inlined + { + IntVec8 move_assigned; + FillVector(&move_assigned, kInlinedLength - 1, 99); // Add dummy elements + IntVec8 tmp(original); + auto* old_data = tmp.data(); + move_assigned = std::move(tmp); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], move_assigned[i]); + } + // original data was inlined so it should have been copied, not moved. + EXPECT_NE(move_assigned.data(), old_data); + } + // move assigned vector is allocated + { + IntVec8 move_assigned; + FillVector(&move_assigned, kInlinedLength + 1, 99); // Add dummy elements + IntVec8 tmp(original); + auto* old_data = tmp.data(); + move_assigned = std::move(tmp); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], move_assigned[i]); } - for (size_t start_len = 0; start_len < 20; start_len++) { - IntVec8 move_assigned; - FillVector(&move_assigned, start_len, 99); // Add dummy elements - IntVec8 tmp(original); - auto* old_data = tmp.data(); - move_assigned = std::move(tmp); - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_TRUE(original[i] == move_assigned[i]); - } - if (original.size() > inlined_capacity) { - // Allocation is moved as a whole, data stays in place. - EXPECT_TRUE(move_assigned.data() == old_data); - } else { - EXPECT_FALSE(move_assigned.data() == old_data); - } + // original data was inlined so it should have been copied, not moved. + EXPECT_NE(move_assigned.data(), old_data); + } +} + +TEST(InlinedVectorTest, MoveAssignmentAllocated) { + const size_t kInlinedLength = 8; + const size_t kFillSize = kInlinedLength + 1; + typedef InlinedVector IntVec8; + IntVec8 original; + FillVector(&original, kFillSize); + EXPECT_EQ(kFillSize, original.size()); + EXPECT_LE(kFillSize, original.capacity()); + // move assigned vector is inlined + { + IntVec8 move_assigned; + FillVector(&move_assigned, kInlinedLength - 1, 99); // Add dummy elements + IntVec8 tmp(original); + auto* old_data = tmp.data(); + move_assigned = std::move(tmp); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], move_assigned[i]); + } + // original data was allocated so it should have been moved, not copied. + EXPECT_EQ(move_assigned.data(), old_data); + } + // move assigned vector is allocated + { + IntVec8 move_assigned; + FillVector(&move_assigned, kInlinedLength + 1, 99); // Add dummy elements + IntVec8 tmp(original); + auto* old_data = tmp.data(); + move_assigned = std::move(tmp); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], move_assigned[i]); } + // original data was allocated so it should have been moved, not copied. + EXPECT_EQ(move_assigned.data(), old_data); } } -- cgit v1.2.3 From 2968bf687af0f5e0db591d20276b79a7fd627c31 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 17 Jul 2018 15:11:27 -0700 Subject: reviewer feedback --- src/core/lib/gprpp/inlined_vector.h | 2 +- test/core/gprpp/inlined_vector_test.cc | 229 ++++++++++++++------------------- 2 files changed, 98 insertions(+), 133 deletions(-) (limited to 'test/core') diff --git a/src/core/lib/gprpp/inlined_vector.h b/src/core/lib/gprpp/inlined_vector.h index 508fb2eed1..76e2f0a785 100644 --- a/src/core/lib/gprpp/inlined_vector.h +++ b/src/core/lib/gprpp/inlined_vector.h @@ -124,7 +124,7 @@ class InlinedVector { void push_back(T&& value) { emplace_back(std::move(value)); } void copy_from(const InlinedVector& v) { - // if copy over the buffer from v. + // if v is allocated, copy over the buffer. if (v.dynamic_ != nullptr) { reserve(v.capacity_); memcpy(dynamic_, v.dynamic_, v.size_ * sizeof(T)); diff --git a/test/core/gprpp/inlined_vector_test.cc b/test/core/gprpp/inlined_vector_test.cc index 1ef7da465c..e9d1eb2c76 100644 --- a/test/core/gprpp/inlined_vector_test.cc +++ b/test/core/gprpp/inlined_vector_test.cc @@ -32,6 +32,8 @@ static void FillVector(Vector* v, int len, int start = 0) { v->push_back(i + start); EXPECT_EQ(i + 1UL, v->size()); } + EXPECT_EQ(static_cast(len), v->size()); + EXPECT_LE(static_cast(len), v->capacity()); } } // namespace @@ -107,14 +109,16 @@ TEST(InlinedVectorTest, ConstIndexOperator) { const_func(v); } +// the following constants and typedefs are used for copy/move +// construction/assignment +const size_t kInlinedLength = 8; +typedef InlinedVector IntVec8; +const size_t kInlinedFillSize = kInlinedLength - 1; +const size_t kAllocatedFillSize = kInlinedLength + 1; + TEST(InlinedVectorTest, CopyConstructerInlined) { - const size_t kInlinedLength = 8; - const size_t kFillSize = kInlinedLength - 1; - typedef InlinedVector IntVec8; IntVec8 original; - FillVector(&original, kFillSize); - EXPECT_EQ(kFillSize, original.size()); - EXPECT_LE(kFillSize, original.capacity()); + FillVector(&original, kInlinedFillSize); IntVec8 copy_constructed(original); for (size_t i = 0; i < original.size(); ++i) { EXPECT_EQ(original[i], copy_constructed[i]); @@ -122,83 +126,61 @@ TEST(InlinedVectorTest, CopyConstructerInlined) { } TEST(InlinedVectorTest, CopyConstructerAllocated) { - const size_t kInlinedLength = 8; - const size_t kFillSize = kInlinedLength + 1; - typedef InlinedVector IntVec8; IntVec8 original; - FillVector(&original, kFillSize); - EXPECT_EQ(kFillSize, original.size()); - EXPECT_LE(kFillSize, original.capacity()); + FillVector(&original, kAllocatedFillSize); IntVec8 copy_constructed(original); for (size_t i = 0; i < original.size(); ++i) { EXPECT_EQ(original[i], copy_constructed[i]); } } -TEST(InlinedVectorTest, CopyAssignementInlined) { - const size_t kInlinedLength = 8; - const size_t kFillSize = kInlinedLength - 1; - typedef InlinedVector IntVec8; +TEST(InlinedVectorTest, CopyAssignementInlinedInlined) { IntVec8 original; - FillVector(&original, kFillSize); - EXPECT_EQ(kFillSize, original.size()); - EXPECT_LE(kFillSize, original.capacity()); - // copy assigned vector is inlined - { - IntVec8 copy_assigned; - FillVector(©_assigned, kInlinedLength - 1, 99); - copy_assigned = original; - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_EQ(original[i], copy_assigned[i]); - } + FillVector(&original, kInlinedFillSize); + IntVec8 copy_assigned; + FillVector(©_assigned, kInlinedFillSize, 99); + copy_assigned = original; + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], copy_assigned[i]); } - // copy assigned vector is allocated - { - IntVec8 copy_assigned; - FillVector(©_assigned, kInlinedLength + 1, 99); - copy_assigned = original; - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_EQ(original[i], copy_assigned[i]); - } +} + +TEST(InlinedVectorTest, CopyAssignementInlinedAllocated) { + IntVec8 original; + FillVector(&original, kInlinedFillSize); + IntVec8 copy_assigned; + FillVector(©_assigned, kAllocatedFillSize, 99); + copy_assigned = original; + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], copy_assigned[i]); } } -TEST(InlinedVectorTest, CopyAssignementAllocated) { - const size_t kInlinedLength = 8; - const size_t kFillSize = kInlinedLength + 1; - typedef InlinedVector IntVec8; +TEST(InlinedVectorTest, CopyAssignementAllocatedInlined) { IntVec8 original; - FillVector(&original, kFillSize); - EXPECT_EQ(kFillSize, original.size()); - EXPECT_LE(kFillSize, original.capacity()); - // copy assigned vector is inlined - { - IntVec8 copy_assigned; - FillVector(©_assigned, kInlinedLength - 1, 99); - copy_assigned = original; - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_EQ(original[i], copy_assigned[i]); - } + FillVector(&original, kAllocatedFillSize); + IntVec8 copy_assigned; + FillVector(©_assigned, kInlinedFillSize, 99); + copy_assigned = original; + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], copy_assigned[i]); } - // copy assigned vector is allocated - { - IntVec8 copy_assigned; - FillVector(©_assigned, kInlinedLength + 1, 99); - copy_assigned = original; - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_EQ(original[i], copy_assigned[i]); - } +} + +TEST(InlinedVectorTest, CopyAssignementAllocatedAllocated) { + IntVec8 original; + FillVector(&original, kAllocatedFillSize); + IntVec8 copy_assigned; + FillVector(©_assigned, kAllocatedFillSize, 99); + copy_assigned = original; + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], copy_assigned[i]); } } TEST(InlinedVectorTest, MoveConstructorInlined) { - const size_t kInlinedLength = 8; - const size_t kFillSize = kInlinedLength - 1; - typedef InlinedVector IntVec8; IntVec8 original; - FillVector(&original, kFillSize); - EXPECT_EQ(kFillSize, original.size()); - EXPECT_LE(kFillSize, original.capacity()); + FillVector(&original, kInlinedFillSize); IntVec8 tmp(original); auto* old_data = tmp.data(); IntVec8 move_constructed(std::move(tmp)); @@ -210,13 +192,8 @@ TEST(InlinedVectorTest, MoveConstructorInlined) { } TEST(InlinedVectorTest, MoveConstructorAllocated) { - const size_t kInlinedLength = 8; - const size_t kFillSize = kInlinedLength + 1; - typedef InlinedVector IntVec8; IntVec8 original; - FillVector(&original, kFillSize); - EXPECT_EQ(kFillSize, original.size()); - EXPECT_LE(kFillSize, original.capacity()); + FillVector(&original, kAllocatedFillSize); IntVec8 tmp(original); auto* old_data = tmp.data(); IntVec8 move_constructed(std::move(tmp)); @@ -227,76 +204,64 @@ TEST(InlinedVectorTest, MoveConstructorAllocated) { EXPECT_EQ(move_constructed.data(), old_data); } -TEST(InlinedVectorTest, MoveAssignmentInlined) { - const size_t kInlinedLength = 8; - const size_t kFillSize = kInlinedLength - 1; - typedef InlinedVector IntVec8; +TEST(InlinedVectorTest, MoveAssignmentInlinedInlined) { IntVec8 original; - FillVector(&original, kFillSize); - EXPECT_EQ(kFillSize, original.size()); - EXPECT_LE(kFillSize, original.capacity()); - // move assigned vector is inlined - { - IntVec8 move_assigned; - FillVector(&move_assigned, kInlinedLength - 1, 99); // Add dummy elements - IntVec8 tmp(original); - auto* old_data = tmp.data(); - move_assigned = std::move(tmp); - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_EQ(original[i], move_assigned[i]); - } - // original data was inlined so it should have been copied, not moved. - EXPECT_NE(move_assigned.data(), old_data); + FillVector(&original, kInlinedFillSize); + IntVec8 move_assigned; + FillVector(&move_assigned, kInlinedFillSize, 99); // Add dummy elements + IntVec8 tmp(original); + auto* old_data = tmp.data(); + move_assigned = std::move(tmp); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], move_assigned[i]); } - // move assigned vector is allocated - { - IntVec8 move_assigned; - FillVector(&move_assigned, kInlinedLength + 1, 99); // Add dummy elements - IntVec8 tmp(original); - auto* old_data = tmp.data(); - move_assigned = std::move(tmp); - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_EQ(original[i], move_assigned[i]); - } - // original data was inlined so it should have been copied, not moved. - EXPECT_NE(move_assigned.data(), old_data); + // original data was inlined so it should have been copied, not moved. + EXPECT_NE(move_assigned.data(), old_data); +} + +TEST(InlinedVectorTest, MoveAssignmentInlinedAllocated) { + IntVec8 original; + FillVector(&original, kInlinedFillSize); + IntVec8 move_assigned; + FillVector(&move_assigned, kAllocatedFillSize, 99); // Add dummy elements + IntVec8 tmp(original); + auto* old_data = tmp.data(); + move_assigned = std::move(tmp); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], move_assigned[i]); } + // original data was inlined so it should have been copied, not moved. + EXPECT_NE(move_assigned.data(), old_data); } -TEST(InlinedVectorTest, MoveAssignmentAllocated) { - const size_t kInlinedLength = 8; - const size_t kFillSize = kInlinedLength + 1; - typedef InlinedVector IntVec8; +TEST(InlinedVectorTest, MoveAssignmentAllocatedInlined) { IntVec8 original; - FillVector(&original, kFillSize); - EXPECT_EQ(kFillSize, original.size()); - EXPECT_LE(kFillSize, original.capacity()); - // move assigned vector is inlined - { - IntVec8 move_assigned; - FillVector(&move_assigned, kInlinedLength - 1, 99); // Add dummy elements - IntVec8 tmp(original); - auto* old_data = tmp.data(); - move_assigned = std::move(tmp); - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_EQ(original[i], move_assigned[i]); - } - // original data was allocated so it should have been moved, not copied. - EXPECT_EQ(move_assigned.data(), old_data); + FillVector(&original, kAllocatedFillSize); + IntVec8 move_assigned; + FillVector(&move_assigned, kInlinedFillSize, 99); // Add dummy elements + IntVec8 tmp(original); + auto* old_data = tmp.data(); + move_assigned = std::move(tmp); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], move_assigned[i]); } - // move assigned vector is allocated - { - IntVec8 move_assigned; - FillVector(&move_assigned, kInlinedLength + 1, 99); // Add dummy elements - IntVec8 tmp(original); - auto* old_data = tmp.data(); - move_assigned = std::move(tmp); - for (size_t i = 0; i < original.size(); ++i) { - EXPECT_EQ(original[i], move_assigned[i]); - } - // original data was allocated so it should have been moved, not copied. - EXPECT_EQ(move_assigned.data(), old_data); + // original data was allocated so it should have been moved, not copied. + EXPECT_EQ(move_assigned.data(), old_data); +} + +TEST(InlinedVectorTest, MoveAssignmentAllocatedAllocated) { + IntVec8 original; + FillVector(&original, kAllocatedFillSize); + IntVec8 move_assigned; + FillVector(&move_assigned, kAllocatedFillSize, 99); // Add dummy elements + IntVec8 tmp(original); + auto* old_data = tmp.data(); + move_assigned = std::move(tmp); + for (size_t i = 0; i < original.size(); ++i) { + EXPECT_EQ(original[i], move_assigned[i]); } + // original data was allocated so it should have been moved, not copied. + EXPECT_EQ(move_assigned.data(), old_data); } } // namespace testing -- cgit v1.2.3 From 5d373c40bdd616d2d0e65b1c6936cc2d07ba4044 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 17 Jul 2018 11:57:31 -0700 Subject: reviewer feedback --- .../client_channel/client_channel_channelz.cc | 10 +++-- .../client_channel/client_channel_channelz.h | 6 ++- .../client_channel/lb_policy/grpclb/grpclb.cc | 3 +- src/core/lib/channel/channelz.cc | 15 +++++--- src/core/lib/channel/channelz.h | 11 +++--- src/core/lib/channel/channelz_registry.cc | 5 +-- src/core/lib/channel/channelz_registry.h | 5 ++- src/core/lib/surface/channel.cc | 8 ++-- test/core/channel/channel_trace_test.cc | 12 +++--- test/core/channel/channelz_registry_test.cc | 45 +++------------------- test/core/channel/channelz_test.cc | 27 ++++++------- 11 files changed, 55 insertions(+), 92 deletions(-) (limited to 'test/core') diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 08ceb2dd05..88a936f9b7 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -41,8 +41,9 @@ static const grpc_arg_pointer_vtable client_channel_channelz_vtable = { client_channel_channelz_cmp}; ClientChannelNode::ClientChannelNode(grpc_channel* channel, - size_t channel_tracer_max_nodes) - : ChannelNode(channel, channel_tracer_max_nodes) { + size_t channel_tracer_max_nodes, + bool is_top_level_channel) + : ChannelNode(channel, channel_tracer_max_nodes, is_top_level_channel) { client_channel_ = grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); GPR_ASSERT(client_channel_->filter == &grpc_client_channel_filter); @@ -71,9 +72,10 @@ grpc_arg ClientChannelNode::CreateChannelArg() { } RefCountedPtr ClientChannelNode::MakeClientChannelNode( - grpc_channel* channel, size_t channel_tracer_max_nodes) { + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel) { return MakePolymorphicRefCounted( - channel, channel_tracer_max_nodes); + channel, channel_tracer_max_nodes, is_top_level_channel); } } // namespace channelz diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index cf3ef7b6f2..6fb475399f 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -32,7 +32,8 @@ namespace channelz { class ClientChannelNode : public ChannelNode { public: static RefCountedPtr MakeClientChannelNode( - grpc_channel* channel, size_t channel_tracer_max_nodes); + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); // Override this functionality since client_channels have a notion of // channel connectivity. @@ -45,7 +46,8 @@ class ClientChannelNode : public ChannelNode { protected: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes); + ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); virtual ~ClientChannelNode() {} private: diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 01d05dbb14..e7526cb7e2 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -1004,7 +1004,8 @@ grpc_channel_args* BuildBalancerChannelArgs( // A channel arg indicating the target is a grpclb load balancer. grpc_channel_arg_integer_create( const_cast(GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 1), - // A channel arg indicating the target is a grpclb load balancer. + // A channel arg indicating this is an internal channels, aka it is + // owned by components in Core, not by the user application. grpc_channel_arg_integer_create( const_cast(GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL), 1), }; diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index c8a1d179fa..c78ea99e63 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -88,8 +88,12 @@ grpc_json* add_num_str(grpc_json* parent, grpc_json* it, const char* name, } // namespace -ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes) - : channel_(channel), target_(nullptr), channel_uuid_(-1) { +ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel) + : channel_(channel), + target_(nullptr), + channel_uuid_(-1), + is_top_level_channel_(is_top_level_channel) { trace_.Init(channel_tracer_max_nodes); target_ = UniquePtr(grpc_channel_get_target(channel_)); channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this); @@ -136,7 +140,7 @@ grpc_json* ChannelNode::RenderJson() { // fill in the channel trace if applicable grpc_json* trace = trace_->RenderJson(); if (trace != nullptr) { - // we manuall link up and fill the child since it was created for us in + // we manually link up and fill the child since it was created for us in // ChannelTrace::RenderJson json_iterator = grpc_json_link_child(json, trace, json_iterator); trace->parent = json; @@ -175,9 +179,10 @@ char* ChannelNode::RenderJsonString() { } RefCountedPtr ChannelNode::MakeChannelNode( - grpc_channel* channel, size_t channel_tracer_max_nodes) { + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel) { return MakeRefCounted( - channel, channel_tracer_max_nodes); + channel, channel_tracer_max_nodes, is_top_level_channel); } } // namespace channelz diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index abcf907c2b..4794a280d0 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -49,7 +49,8 @@ class ChannelNodePeer; class ChannelNode : public RefCounted { public: static RefCountedPtr MakeChannelNode( - grpc_channel* channel, size_t channel_tracer_max_nodes); + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); void RecordCallStarted(); void RecordCallFailed() { @@ -78,14 +79,12 @@ class ChannelNode : public RefCounted { intptr_t channel_uuid() { return channel_uuid_; } bool is_top_level_channel() { return is_top_level_channel_; } - void set_is_top_level_channel(bool is_top_level_channel) { - is_top_level_channel_ = is_top_level_channel; - } protected: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes); + ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); virtual ~ChannelNode(); private: @@ -106,7 +105,7 @@ class ChannelNode : public RefCounted { // Creation functions typedef RefCountedPtr (*ChannelNodeCreationFunc)(grpc_channel*, - size_t); + size_t, bool); } // namespace channelz } // namespace grpc_core diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index b4dc3d1103..7ca3fc5836 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -86,7 +86,7 @@ char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { grpc_json* json_iterator = nullptr; InlinedVector top_level_channels; // uuids index into entities one-off (idx 0 is really uuid 1, since 0 is - // reserver). However, we want to support requests coming in which + // reserved). However, we want to support requests coming in this // start_channel_id=0, which signifies "give me everything." Hence this // funky looking line below. size_t start_idx = start_channel_id == 0 ? 0 : start_channel_id - 1; @@ -108,9 +108,6 @@ char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { json_iterator = grpc_json_link_child(array_parent, channel_json, json_iterator); channel_json->parent = array_parent; - channel_json->value = nullptr; - channel_json->key = nullptr; - channel_json->owns_value = false; } } // For now we do not have any pagination rules. In the future we could diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h index 2fefc9f629..c378467f34 100644 --- a/src/core/lib/channel/channelz_registry.h +++ b/src/core/lib/channel/channelz_registry.h @@ -36,7 +36,7 @@ class ChannelzRegistry { // To be called in grpc_init() static void Init(); - // To be callen in grpc_shutdown(); + // To be called in grpc_shutdown(); static void Shutdown(); static intptr_t RegisterChannelNode(ChannelNode* channel_node) { @@ -51,7 +51,8 @@ class ChannelzRegistry { return gotten == nullptr ? nullptr : static_cast(gotten); } - // todo, protect me + // Returns the allocated JSON string that represents the proto + // GetTopChannelsResponse as per channelz.proto. static char* GetTopChannels(intptr_t start_channel_id) { return Default()->InternalGetTopChannels(start_channel_id); } diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index dd3880f18e..7cbd61adef 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -167,11 +167,9 @@ grpc_channel* grpc_channel_create_with_builder( grpc_channel_args_destroy(args); if (channelz_enabled) { - channel->channelz_channel = - channel_node_create_func(channel, channel_tracer_max_nodes); - if (internal_channel || !channel->is_client) { - channel->channelz_channel->set_is_top_level_channel(false); - } + bool is_top_level_channel = channel->is_client && !internal_channel; + channel->channelz_channel = channel_node_create_func( + channel, channel_tracer_max_nodes, is_top_level_channel); channel->channelz_channel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 07b0e3de06..99d9a4847f 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -34,8 +34,6 @@ #include "test/core/util/test_config.h" #include "test/cpp/util/channel_trace_proto_helper.h" -// remove me -#include #include #include @@ -157,7 +155,7 @@ TEST_P(ChannelTracerTest, ComplexTest) { AddSimpleTrace(&tracer); ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = - MakeRefCounted(channel1.channel(), GetParam()); + MakeRefCounted(channel1.channel(), GetParam(), true); tracer.AddTraceEventReferencingSubchannel( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); @@ -175,7 +173,7 @@ TEST_P(ChannelTracerTest, ComplexTest) { ValidateChannelTrace(&tracer, 5, GetParam()); ChannelFixture channel2(GetParam()); RefCountedPtr sc2 = - MakeRefCounted(channel2.channel(), GetParam()); + MakeRefCounted(channel2.channel(), GetParam(), true); tracer.AddTraceEventReferencingChannel( ChannelTrace::Severity::Info, grpc_slice_from_static_string("LB channel two created"), sc2); @@ -204,7 +202,7 @@ TEST_P(ChannelTracerTest, TestNesting) { ValidateChannelTrace(&tracer, 2, GetParam()); ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = - MakeRefCounted(channel1.channel(), GetParam()); + MakeRefCounted(channel1.channel(), GetParam(), true); tracer.AddTraceEventReferencingChannel( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); @@ -212,7 +210,7 @@ TEST_P(ChannelTracerTest, TestNesting) { AddSimpleTrace(sc1->trace()); ChannelFixture channel2(GetParam()); RefCountedPtr conn1 = - MakeRefCounted(channel2.channel(), GetParam()); + MakeRefCounted(channel2.channel(), GetParam(), true); // nesting one level deeper. sc1->trace()->AddTraceEventReferencingSubchannel( ChannelTrace::Severity::Info, @@ -225,7 +223,7 @@ TEST_P(ChannelTracerTest, TestNesting) { ValidateChannelTrace(conn1->trace(), 1, GetParam()); ChannelFixture channel3(GetParam()); RefCountedPtr sc2 = - MakeRefCounted(channel3.channel(), GetParam()); + MakeRefCounted(channel3.channel(), GetParam(), true); tracer.AddTraceEventReferencingSubchannel( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel two created"), sc2); diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc index 06363d00e2..990cd3d205 100644 --- a/test/core/channel/channelz_registry_test.cc +++ b/test/core/channel/channelz_registry_test.cc @@ -42,36 +42,9 @@ namespace grpc_core { namespace channelz { namespace testing { -namespace { -class ChannelFixture { - public: - ChannelFixture() { - grpc_arg client_a[1]; - client_a[0].type = GRPC_ARG_INTEGER; - client_a[0].key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); - client_a[0].value.integer = true; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; - channel_ = - grpc_insecure_channel_create("fake_target", &client_args, nullptr); - } - - ~ChannelFixture() { grpc_channel_destroy(channel_); } - - grpc_channel* channel() { return channel_; } - - private: - grpc_channel* channel_; -}; - -} // namespace - -// Tests basic ChannelTrace functionality like construction, adding trace, and -// lookups by uuid. TEST(ChannelzRegistryTest, UuidStartsAboveZeroTest) { - ChannelFixture channel; - ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(channel.channel()); + ChannelNode* channelz_channel = nullptr; intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); EXPECT_GT(uuid, 0) << "First uuid chose must be greater than zero. Zero if " "reserved according to " @@ -81,9 +54,7 @@ TEST(ChannelzRegistryTest, UuidStartsAboveZeroTest) { } TEST(ChannelzRegistryTest, UuidsAreIncreasing) { - ChannelFixture channel; - ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(channel.channel()); + ChannelNode* channelz_channel = nullptr; std::vector uuids; uuids.reserve(10); for (int i = 0; i < 10; ++i) { @@ -96,18 +67,14 @@ TEST(ChannelzRegistryTest, UuidsAreIncreasing) { } TEST(ChannelzRegistryTest, RegisterGetTest) { - ChannelFixture channel; - ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(channel.channel()); + ChannelNode* channelz_channel = nullptr; intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); EXPECT_EQ(channelz_channel, retrieved); } TEST(ChannelzRegistryTest, RegisterManyItems) { - ChannelFixture channel; - ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(channel.channel()); + ChannelNode* channelz_channel = nullptr; for (int i = 0; i < 100; i++) { intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); @@ -116,9 +83,7 @@ TEST(ChannelzRegistryTest, RegisterManyItems) { } TEST(ChannelzRegistryTest, NullIfNotPresentTest) { - ChannelFixture channel; - ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(channel.channel()); + ChannelNode* channelz_channel = nullptr; intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); // try to pull out a uuid that does not exist. ChannelNode* nonexistant = ChannelzRegistry::GetChannelNode(uuid + 1); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 1ed36acb61..d12f529726 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -80,7 +80,7 @@ void ValidateJsonArraySize(grpc_json* json, const char* key, for (grpc_json* child = arr->child; child != nullptr; child = child->next) { ++count; } - ASSERT_EQ(count, expected_size); + EXPECT_EQ(count, expected_size); } void ValidateGetTopChannels(size_t expected_channels) { @@ -91,7 +91,7 @@ void ValidateGetTopChannels(size_t expected_channels) { // tracked: https://github.com/grpc/grpc/issues/16019. ValidateJsonArraySize(parsed_json, "channel", expected_channels); grpc_json* end = GetJsonChild(parsed_json, "end"); - EXPECT_NE(end, nullptr); + ASSERT_NE(end, nullptr); EXPECT_EQ(end->type, GRPC_JSON_TRUE); grpc_json_destroy(parsed_json); gpr_free(json_str); @@ -101,13 +101,11 @@ class ChannelFixture { public: ChannelFixture(int max_trace_nodes = 0) { grpc_arg client_a[2]; - client_a[0].type = GRPC_ARG_INTEGER; - client_a[0].key = - const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE); - client_a[0].value.integer = max_trace_nodes; - client_a[1].type = GRPC_ARG_INTEGER; - client_a[1].key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); - client_a[1].value.integer = true; + client_a[0] = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE), + max_trace_nodes); + client_a[1] = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_CHANNELZ), true); grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; channel_ = grpc_insecure_channel_create("fake_target", &client_args, nullptr); @@ -255,13 +253,10 @@ TEST(ChannelzGetTopChannelsTest, InternalChannelTest) { (void)channels; // suppress unused variable error // create an internal channel grpc_arg client_a[2]; - client_a[0].type = GRPC_ARG_INTEGER; - client_a[0].key = - const_cast(GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL); - client_a[0].value.integer = 1; - client_a[1].type = GRPC_ARG_INTEGER; - client_a[1].key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); - client_a[1].value.integer = true; + client_a[0] = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL), true); + client_a[1] = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_CHANNELZ), true); grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; grpc_channel* internal_channel = grpc_insecure_channel_create("fake_target", &client_args, nullptr); -- cgit v1.2.3 From 891cf34004e19f0071964b964f65eb3d156575ac Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 18 Jul 2018 08:59:28 -0700 Subject: Use intptr_ts for channel registry test --- test/core/channel/channelz_registry_test.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'test/core') diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc index 990cd3d205..581e867584 100644 --- a/test/core/channel/channelz_registry_test.cc +++ b/test/core/channel/channelz_registry_test.cc @@ -67,14 +67,16 @@ TEST(ChannelzRegistryTest, UuidsAreIncreasing) { } TEST(ChannelzRegistryTest, RegisterGetTest) { - ChannelNode* channelz_channel = nullptr; + // we hackily jam an intptr_t into this pointer to check for equality later + ChannelNode* channelz_channel = (ChannelNode*)42; intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); EXPECT_EQ(channelz_channel, retrieved); } TEST(ChannelzRegistryTest, RegisterManyItems) { - ChannelNode* channelz_channel = nullptr; + // we hackily jam an intptr_t into this pointer to check for equality later + ChannelNode* channelz_channel = (ChannelNode*)42; for (int i = 0; i < 100; i++) { intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); @@ -83,7 +85,8 @@ TEST(ChannelzRegistryTest, RegisterManyItems) { } TEST(ChannelzRegistryTest, NullIfNotPresentTest) { - ChannelNode* channelz_channel = nullptr; + // we hackily jam an intptr_t into this pointer to check for equality later + ChannelNode* channelz_channel = (ChannelNode*)42; intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); // try to pull out a uuid that does not exist. ChannelNode* nonexistant = ChannelzRegistry::GetChannelNode(uuid + 1); -- cgit v1.2.3 From b86a74475189e0ed97cdd3ddc48d96e94cec366a Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 11 Jul 2018 17:11:01 -0700 Subject: Expose GetChannel and GetTopChannels Core API --- grpc.def | 2 ++ include/grpc/grpc.h | 23 +++++++++++++++++++++++ src/core/lib/channel/channelz_registry.cc | 21 +++++++++++++++++++++ src/ruby/ext/grpc/rb_grpc_imports.generated.c | 4 ++++ src/ruby/ext/grpc/rb_grpc_imports.generated.h | 6 ++++++ test/core/channel/channelz_test.cc | 10 ++++++++++ test/core/surface/public_headers_must_be_c89.c | 2 ++ test/cpp/util/channel_trace_proto_helper.cc | 5 +++++ test/cpp/util/channel_trace_proto_helper.h | 1 + 9 files changed, 74 insertions(+) (limited to 'test/core') diff --git a/grpc.def b/grpc.def index 06db74cad5..5b98792662 100644 --- a/grpc.def +++ b/grpc.def @@ -69,6 +69,8 @@ EXPORTS grpc_resource_quota_unref grpc_resource_quota_resize grpc_resource_quota_arg_vtable + grpc_channelz_get_top_channels + grpc_channelz_get_channel grpc_insecure_channel_create_from_fd grpc_server_add_insecure_channel_from_fd grpc_use_signal diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index c129a66949..f0eb2c0121 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -454,6 +454,29 @@ GRPCAPI void grpc_resource_quota_resize(grpc_resource_quota* resource_quota, */ GRPCAPI const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void); +/************* CHANNELZ API *************/ +/** Channelz is under active development. The following APIs will see some + churn as the feature is implemented. This comment will be removed once + channelz is officially supported, and these APIs become stable. For now + you may track the progress by following this github issue: + https://github.com/grpc/grpc/issues/15340 + + the following APIs return allocated JSON strings that match the response + objects from the channelz proto, found here: + https://github.com/grpc/grpc/blob/master/src/proto/grpc/channelz/channelz.proto. + + For easy conversion to protobuf, The JSON is formatted according to: + https://developers.google.com/protocol-buffers/docs/proto3#json. */ + +/* Gets all root channels (i.e. channels the application has directly + created). This does not include subchannels nor non-top level channels. + The returned string is allocated and must be freed by the application. */ +GRPCAPI char* grpc_channelz_get_top_channels(intptr_t start_channel_id); + +/* Returns a single Channel, or else a NOT_FOUND code. The returned string + is allocated and must be freed by the application. */ +GRPCAPI char* grpc_channelz_get_channel(intptr_t channel_id); + #ifdef __cplusplus } #endif diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index a16798d524..38496b3d78 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -121,3 +121,24 @@ char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { } // namespace channelz } // namespace grpc_core + +char* grpc_channelz_get_top_channels(intptr_t start_channel_id) { + return grpc_core::channelz::ChannelzRegistry::GetTopChannels( + start_channel_id); +} + +char* grpc_channelz_get_channel(intptr_t channel_id) { + grpc_core::channelz::ChannelNode* channel_node = + grpc_core::channelz::ChannelzRegistry::GetChannelNode(channel_id); + if (channel_node == nullptr) { + return nullptr; + } + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* channel_json = channel_node->RenderJson(); + channel_json->key = "channel"; + grpc_json_link_child(json, channel_json, nullptr); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 4e235121e2..2443532bb8 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -92,6 +92,8 @@ grpc_resource_quota_ref_type grpc_resource_quota_ref_import; grpc_resource_quota_unref_type grpc_resource_quota_unref_import; grpc_resource_quota_resize_type grpc_resource_quota_resize_import; grpc_resource_quota_arg_vtable_type grpc_resource_quota_arg_vtable_import; +grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import; +grpc_channelz_get_channel_type grpc_channelz_get_channel_import; grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import; grpc_server_add_insecure_channel_from_fd_type grpc_server_add_insecure_channel_from_fd_import; grpc_use_signal_type grpc_use_signal_import; @@ -340,6 +342,8 @@ void grpc_rb_load_imports(HMODULE library) { grpc_resource_quota_unref_import = (grpc_resource_quota_unref_type) GetProcAddress(library, "grpc_resource_quota_unref"); grpc_resource_quota_resize_import = (grpc_resource_quota_resize_type) GetProcAddress(library, "grpc_resource_quota_resize"); grpc_resource_quota_arg_vtable_import = (grpc_resource_quota_arg_vtable_type) GetProcAddress(library, "grpc_resource_quota_arg_vtable"); + grpc_channelz_get_top_channels_import = (grpc_channelz_get_top_channels_type) GetProcAddress(library, "grpc_channelz_get_top_channels"); + grpc_channelz_get_channel_import = (grpc_channelz_get_channel_type) GetProcAddress(library, "grpc_channelz_get_channel"); grpc_insecure_channel_create_from_fd_import = (grpc_insecure_channel_create_from_fd_type) GetProcAddress(library, "grpc_insecure_channel_create_from_fd"); grpc_server_add_insecure_channel_from_fd_import = (grpc_server_add_insecure_channel_from_fd_type) GetProcAddress(library, "grpc_server_add_insecure_channel_from_fd"); grpc_use_signal_import = (grpc_use_signal_type) GetProcAddress(library, "grpc_use_signal"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index f01c9c8248..b08a1f94f7 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -251,6 +251,12 @@ extern grpc_resource_quota_resize_type grpc_resource_quota_resize_import; typedef const grpc_arg_pointer_vtable*(*grpc_resource_quota_arg_vtable_type)(void); extern grpc_resource_quota_arg_vtable_type grpc_resource_quota_arg_vtable_import; #define grpc_resource_quota_arg_vtable grpc_resource_quota_arg_vtable_import +typedef char*(*grpc_channelz_get_top_channels_type)(intptr_t start_channel_id); +extern grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import; +#define grpc_channelz_get_top_channels grpc_channelz_get_top_channels_import +typedef char*(*grpc_channelz_get_channel_type)(intptr_t channel_id); +extern grpc_channelz_get_channel_type grpc_channelz_get_channel_import; +#define grpc_channelz_get_channel grpc_channelz_get_channel_import typedef grpc_channel*(*grpc_insecure_channel_create_from_fd_type)(const char* target, int fd, const grpc_channel_args* args); extern grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import; #define grpc_insecure_channel_create_from_fd grpc_insecure_channel_create_from_fd_import diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index d12f529726..ad5f86d934 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -95,6 +95,11 @@ void ValidateGetTopChannels(size_t expected_channels) { EXPECT_EQ(end->type, GRPC_JSON_TRUE); grpc_json_destroy(parsed_json); gpr_free(json_str); + // also check that the core API formats this correctly + char* core_api_json_str = grpc_channelz_get_top_channels(0); + grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation( + core_api_json_str); + gpr_free(core_api_json_str); } class ChannelFixture { @@ -151,6 +156,11 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { grpc::testing::ValidateChannelProtoJsonTranslation(json_str); ValidateCounters(json_str, args); gpr_free(json_str); + // also check that the core API formats this the correct way + char* core_api_json_str = grpc_channelz_get_channel(channel->channel_uuid()); + grpc::testing::ValidateGetChannelResponseProtoJsonTranslation( + core_api_json_str); + gpr_free(core_api_json_str); } grpc_millis GetLastCallStartedMillis(ChannelNode* channel) { diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 9a79b468dd..9f4ad2b4d7 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -131,6 +131,8 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_resource_quota_unref); printf("%lx", (unsigned long) grpc_resource_quota_resize); printf("%lx", (unsigned long) grpc_resource_quota_arg_vtable); + printf("%lx", (unsigned long) grpc_channelz_get_top_channels); + printf("%lx", (unsigned long) grpc_channelz_get_channel); printf("%lx", (unsigned long) grpc_auth_property_iterator_next); printf("%lx", (unsigned long) grpc_auth_context_property_iterator); printf("%lx", (unsigned long) grpc_auth_context_peer_identity); diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index 137f278640..b4704bfe6a 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -77,5 +77,10 @@ void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str) { json_c_str); } +void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str) { + VaidateProtoJsonTranslation( + json_c_str); +} + } // namespace testing } // namespace grpc diff --git a/test/cpp/util/channel_trace_proto_helper.h b/test/cpp/util/channel_trace_proto_helper.h index 74c15f04f1..18e3d54b6b 100644 --- a/test/cpp/util/channel_trace_proto_helper.h +++ b/test/cpp/util/channel_trace_proto_helper.h @@ -25,6 +25,7 @@ namespace testing { void ValidateChannelTraceProtoJsonTranslation(char* json_c_str); void ValidateChannelProtoJsonTranslation(char* json_c_str); void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str); +void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str); } // namespace testing } // namespace grpc -- cgit v1.2.3 From b95772eeb926f78b8ac14e03b36ed3e73b2e1a2c Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Mon, 23 Jul 2018 23:38:13 -0700 Subject: Add Tests in Core and C++ and fix a few related bugs in thread_manager.cc --- src/core/lib/iomgr/resource_quota.cc | 7 ++ src/cpp/server/server_cc.cc | 10 +- src/cpp/thread_manager/thread_manager.cc | 70 ++++++------ src/cpp/thread_manager/thread_manager.h | 42 +++++-- test/core/iomgr/resource_quota_test.cc | 96 ++++++++++++++++ test/cpp/thread_manager/thread_manager_test.cc | 147 ++++++++++++++++++------- 6 files changed, 288 insertions(+), 84 deletions(-) (limited to 'test/core') diff --git a/src/core/lib/iomgr/resource_quota.cc b/src/core/lib/iomgr/resource_quota.cc index a30688bd87..67d05aa202 100644 --- a/src/core/lib/iomgr/resource_quota.cc +++ b/src/core/lib/iomgr/resource_quota.cc @@ -547,6 +547,11 @@ static void ru_shutdown(void* ru, grpc_error* error) { static void ru_destroy(void* ru, grpc_error* error) { grpc_resource_user* resource_user = static_cast(ru); GPR_ASSERT(gpr_atm_no_barrier_load(&resource_user->refs) == 0); + // Free all the remaining thread quota + grpc_resource_user_free_threads( + resource_user, + static_cast(gpr_atm_no_barrier_load(&resource_user->num_threads))); + for (int i = 0; i < GRPC_RULIST_COUNT; i++) { rulist_remove(resource_user, static_cast(i)); } @@ -642,6 +647,7 @@ grpc_resource_quota* grpc_resource_quota_create(const char* name) { void grpc_resource_quota_unref_internal(grpc_resource_quota* resource_quota) { if (gpr_unref(&resource_quota->refs)) { + GPR_ASSERT(resource_quota->num_threads == 0); // No outstanding thd quota GRPC_COMBINER_UNREF(resource_quota->combiner, "resource_quota"); gpr_free(resource_quota->name); gpr_free(resource_quota); @@ -846,6 +852,7 @@ void grpc_resource_user_free_threads(grpc_resource_user* resource_user, "Releasing more threads (%d) that currently allocated (rq threads: " "%d, ru threads: %d)", thd_count, old_cnt, rq->num_threads + thd_count); + abort(); } gpr_mu_unlock(&resource_user->resource_quota->thd_mu); } diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 6e6e0bfffe..786ef44e3e 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -47,6 +47,12 @@ namespace grpc { namespace { +// The default value for maximum number of threads that can be created in the +// sync server. This value of 1500 is empirically chosen. To increase the max +// number of threads in a sync server, pass a custom ResourceQuota object (with +// the desired number of max-threads set) to the server builder +#define DEFAULT_MAX_SYNC_SERVER_THREADS 1500 + class DefaultGlobalCallbacks final : public Server::GlobalCallbacks { public: ~DefaultGlobalCallbacks() override {} @@ -395,7 +401,9 @@ Server::Server( if (sync_server_cqs_ != nullptr) { bool default_rq_created = false; if (server_rq == nullptr) { - server_rq = grpc_resource_quota_create("SyncServer-Default"); + server_rq = grpc_resource_quota_create("SyncServer-default-rq"); + grpc_resource_quota_set_max_threads(server_rq, + DEFAULT_MAX_SYNC_SERVER_THREADS); default_rq_created = true; } diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc index c0fa98798a..5d367511e2 100644 --- a/src/cpp/thread_manager/thread_manager.cc +++ b/src/cpp/thread_manager/thread_manager.cc @@ -22,8 +22,8 @@ #include #include - #include "src/core/lib/gprpp/thd.h" +#include "src/core/lib/iomgr/exec_ctx.h" namespace grpc { @@ -55,7 +55,8 @@ ThreadManager::ThreadManager(const char* name, num_pollers_(0), min_pollers_(min_pollers), max_pollers_(max_pollers == -1 ? INT_MAX : max_pollers), - num_threads_(0) { + num_threads_(0), + max_active_threads_sofar_(0) { resource_user_ = grpc_resource_user_create(resource_quota, name); } @@ -65,6 +66,7 @@ ThreadManager::~ThreadManager() { GPR_ASSERT(num_threads_ == 0); } + grpc_core::ExecCtx exec_ctx; // grpc_resource_user_unref needs an exec_ctx grpc_resource_user_unref(resource_user_); CleanupCompletedThreads(); } @@ -86,17 +88,27 @@ bool ThreadManager::IsShutdown() { return shutdown_; } +int ThreadManager::GetMaxActiveThreadsSoFar() { + std::lock_guard list_lock(list_mu_); + return max_active_threads_sofar_; +} + void ThreadManager::MarkAsCompleted(WorkerThread* thd) { { std::lock_guard list_lock(list_mu_); completed_threads_.push_back(thd); } - std::lock_guard lock(mu_); - num_threads_--; - if (num_threads_ == 0) { - shutdown_cv_.notify_one(); + { + std::lock_guard lock(mu_); + num_threads_--; + if (num_threads_ == 0) { + shutdown_cv_.notify_one(); + } } + + // Give a thread back to the resource quota + grpc_resource_user_free_threads(resource_user_, 1); } void ThreadManager::CleanupCompletedThreads() { @@ -111,34 +123,24 @@ void ThreadManager::CleanupCompletedThreads() { } void ThreadManager::Initialize() { + if (!grpc_resource_user_alloc_threads(resource_user_, min_pollers_)) { + gpr_log(GPR_ERROR, + "No thread quota available to even create the minimum required " + "polling threads (i.e %d). Unable to start the thread manager", + min_pollers_); + abort(); + } + { std::unique_lock lock(mu_); num_pollers_ = min_pollers_; num_threads_ = min_pollers_; + max_active_threads_sofar_ = min_pollers_; } for (int i = 0; i < min_pollers_; i++) { - if (!CreateNewThread(this)) { - gpr_log(GPR_ERROR, - "No quota available to create additional threads. Created %d (of " - "%d) threads", - i, min_pollers_); - break; - } - } -} - -bool ThreadManager::CreateNewThread(ThreadManager* thd_mgr) { - if (!grpc_resource_user_alloc_threads(thd_mgr->resource_user_, 1)) { - return false; + new WorkerThread(this); } - // Create a new thread (which ends up calling the MainWorkLoop() function - new WorkerThread(thd_mgr); - return true; -} - -void ThreadManager::ReleaseThread(ThreadManager* thd_mgr) { - grpc_resource_user_free_threads(thd_mgr->resource_user_, 1); } void ThreadManager::MainWorkLoop() { @@ -162,14 +164,17 @@ void ThreadManager::MainWorkLoop() { done = true; break; case WORK_FOUND: - // If we got work and there are now insufficient pollers, start a new - // one - if (!shutdown_ && num_pollers_ < min_pollers_) { + // If we got work and there are now insufficient pollers and there is + // quota available to create a new thread,start a new poller thread + if (!shutdown_ && num_pollers_ < min_pollers_ && + grpc_resource_user_alloc_threads(resource_user_, 1)) { num_pollers_++; num_threads_++; + max_active_threads_sofar_ = + std::max(max_active_threads_sofar_, num_threads_); // Drop lock before spawning thread to avoid contention lock.unlock(); - CreateNewThread(this); + new WorkerThread(this); } else { // Drop lock for consistency with above branch lock.unlock(); @@ -219,10 +224,9 @@ void ThreadManager::MainWorkLoop() { } }; - // This thread is exiting. Do some cleanup work (i.e delete already completed - // worker threads and also release 1 thread back to the resource quota) + // This thread is exiting. Do some cleanup work i.e delete already completed + // worker threads CleanupCompletedThreads(); - ReleaseThread(this); // If we are here, either ThreadManager is shutting down or it already has // enough threads. diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h index 23bd38ee4f..8332befed0 100644 --- a/src/cpp/thread_manager/thread_manager.h +++ b/src/cpp/thread_manager/thread_manager.h @@ -86,6 +86,11 @@ class ThreadManager { // all the threads have drained all the outstanding work virtual void Wait(); + // Max number of concurrent threads that were ever active in this thread + // manager so far. This is useful for debugging purposes (and in unit tests) + // to check if resource_quota is properly being enforced. + int GetMaxActiveThreadsSoFar(); + private: // Helper wrapper class around grpc_core::Thread. Takes a ThreadManager object // and starts a new grpc_core::Thread to calls the Run() function. @@ -93,6 +98,23 @@ class ThreadManager { // The Run() function calls ThreadManager::MainWorkLoop() function and once // that completes, it marks the WorkerThread completed by calling // ThreadManager::MarkAsCompleted() + // + // WHY IS THIS NEEDED?: + // When a thread terminates, some other tread *must* call Join() on that + // thread so that the resources are released. Having a WorkerThread wrapper + // will make this easier. Once Run() completes, each thread calls the + // following two functions: + // ThreadManager::CleanupCompletedThreads() + // ThreadManager::MarkAsCompleted() + // + // - MarkAsCompleted() puts the WorkerThread object in the ThreadManger's + // completed_threads_ list + // - CleanupCompletedThreads() calls "Join()" on the threads that are already + // in the completed_threads_ list (since a thread cannot call Join() on + // itself, it calls CleanupCompletedThreads() *before* calling + // MarkAsCompleted()) + // TODO: sreek - consider creating the threads 'detached' so that Join() need + // not be called class WorkerThread { public: WorkerThread(ThreadManager* thd_mgr); @@ -113,15 +135,8 @@ class ThreadManager { void MarkAsCompleted(WorkerThread* thd); void CleanupCompletedThreads(); - // Checks the resource quota and if available, creates a thread and returns - // true. If quota is not available, returns false (and thread is not created) - static bool CreateNewThread(ThreadManager* thd_mgr); - - // Give back a thread to the resource quota - static void ReleaseThread(ThreadManager* thd_mgr); - - // Protects shutdown_, num_pollers_ and num_threads_ - // TODO: sreek - Change num_pollers and num_threads_ to atomics + // Protects shutdown_, num_pollers_, num_threads_ and + // max_active_threads_sofar_ std::mutex mu_; bool shutdown_; @@ -142,10 +157,15 @@ class ThreadManager { int min_pollers_; int max_pollers_; - // The total number of threads (includes threads includes the threads that are - // currently polling i.e num_pollers_) + // The total number of threads currently active (includes threads includes the + // threads that are currently polling i.e num_pollers_) int num_threads_; + // See GetMaxActiveThreadsSoFar()'s description. + // To be more specific, this variable tracks the max value num_threads_ was + // ever set so far + int max_active_threads_sofar_; + std::mutex list_mu_; std::list completed_threads_; }; diff --git a/test/core/iomgr/resource_quota_test.cc b/test/core/iomgr/resource_quota_test.cc index 059ff7b5f8..573e4010fa 100644 --- a/test/core/iomgr/resource_quota_test.cc +++ b/test/core/iomgr/resource_quota_test.cc @@ -798,6 +798,97 @@ static void test_negative_rq_free_pool(void) { } } +// Simple test to check resource quota thread limits +static void test_thread_limit() { + grpc_core::ExecCtx exec_ctx; + + grpc_resource_quota* rq = grpc_resource_quota_create("test_thread_limit"); + grpc_resource_user* ru1 = grpc_resource_user_create(rq, "ru1"); + grpc_resource_user* ru2 = grpc_resource_user_create(rq, "ru2"); + + // Max threads = 100 + grpc_resource_quota_set_max_threads(rq, 100); + + // Request quota for 100 threads (50 for ru1, 50 for ru2) + GPR_ASSERT(grpc_resource_user_alloc_threads(ru1, 10)); + GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 10)); + GPR_ASSERT(grpc_resource_user_alloc_threads(ru1, 40)); + GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 40)); + + // Threads exhaused. Next request must fail + GPR_ASSERT(!grpc_resource_user_alloc_threads(ru2, 20)); + + // Free 20 threads from two different users + grpc_resource_user_free_threads(ru1, 10); + grpc_resource_user_free_threads(ru2, 10); + + // Next request to 20 threads must succeed + GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 20)); + + // No more thread quota again + GPR_ASSERT(!grpc_resource_user_alloc_threads(ru1, 20)); + + // Free 10 more + grpc_resource_user_free_threads(ru1, 10); + + GPR_ASSERT(grpc_resource_user_alloc_threads(ru1, 5)); + GPR_ASSERT(!grpc_resource_user_alloc_threads(ru2, 10)); // Only 5 available + GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 5)); + + // Teardown (ru1 and ru2 release all the quota back to rq) + grpc_resource_user_unref(ru1); + grpc_resource_user_unref(ru2); + grpc_resource_quota_unref(rq); +} + +// Change max quota in either directions dynamically +static void test_thread_maxquota_change() { + grpc_core::ExecCtx exec_ctx; + + grpc_resource_quota* rq = + grpc_resource_quota_create("test_thread_maxquota_change"); + grpc_resource_user* ru1 = grpc_resource_user_create(rq, "ru1"); + grpc_resource_user* ru2 = grpc_resource_user_create(rq, "ru2"); + + // Max threads = 100 + grpc_resource_quota_set_max_threads(rq, 100); + + // Request quota for 100 threads (50 for ru1, 50 for ru2) + GPR_ASSERT(grpc_resource_user_alloc_threads(ru1, 50)); + GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 50)); + + // Threads exhaused. Next request must fail + GPR_ASSERT(!grpc_resource_user_alloc_threads(ru2, 20)); + + // Increase maxquota and retry + // Max threads = 150; + grpc_resource_quota_set_max_threads(rq, 150); + GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 20)); // ru2 = 70, ru1 = 50 + + // Decrease maxquota (Note: Quota already given to ru1 and ru2 is unaffected) + // Max threads = 10; + grpc_resource_quota_set_max_threads(rq, 10); + + // New requests will fail until quota is available + GPR_ASSERT(!grpc_resource_user_alloc_threads(ru1, 10)); + + // Make quota available + grpc_resource_user_free_threads(ru1, 50); // ru1 now has 0 + GPR_ASSERT(!grpc_resource_user_alloc_threads(ru1, 10)); // Still not enough + + grpc_resource_user_free_threads(ru2, 70); // ru2 now has 0 + + // Now we can get quota up-to 10, the current max + GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 10)); + // No more thread quota again + GPR_ASSERT(!grpc_resource_user_alloc_threads(ru1, 10)); + + // Teardown (ru1 and ru2 release all the quota back to rq) + grpc_resource_user_unref(ru1); + grpc_resource_user_unref(ru2); + grpc_resource_quota_unref(rq); +} + int main(int argc, char** argv) { grpc_test_init(argc, argv); grpc_init(); @@ -827,6 +918,11 @@ int main(int argc, char** argv) { test_negative_rq_free_pool(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_cv); + + // Resource quota thread related + test_thread_limit(); + test_thread_maxquota_change(); + grpc_shutdown(); return 0; } diff --git a/test/cpp/thread_manager/thread_manager_test.cc b/test/cpp/thread_manager/thread_manager_test.cc index cf2cf770e6..a7ed2dd380 100644 --- a/test/cpp/thread_manager/thread_manager_test.cc +++ b/test/cpp/thread_manager/thread_manager_test.cc @@ -30,30 +30,44 @@ #include "test/cpp/util/test_config.h" namespace grpc { + +struct ThreadManagerTestSettings { + // The min number of pollers that SHOULD be active in ThreadManager + int min_pollers; + // The max number of pollers that could be active in ThreadManager + int max_pollers; + // The sleep duration in PollForWork() function to simulate "polling" + int poll_duration_ms; + // The sleep duration in DoWork() function to simulate "work" + int work_duration_ms; + // Max number of times PollForWork() is called before shutting down + int max_poll_calls; +}; + class ThreadManagerTest final : public grpc::ThreadManager { public: - ThreadManagerTest(const char* name, grpc_resource_quota* rq) - : ThreadManager(name, rq, kMinPollers, kMaxPollers), + ThreadManagerTest(const char* name, grpc_resource_quota* rq, + const ThreadManagerTestSettings& settings) + : ThreadManager(name, rq, settings.min_pollers, settings.max_pollers), + settings_(settings), num_do_work_(0), num_poll_for_work_(0), num_work_found_(0) {} grpc::ThreadManager::WorkStatus PollForWork(void** tag, bool* ok) override; void DoWork(void* tag, bool ok) override; - void PerformTest(); + + // Get number of times PollForWork() returned WORK_FOUND + int GetNumWorkFound(); + // Get number of times DoWork() was called + int GetNumDoWork(); private: void SleepForMs(int sleep_time_ms); - static const int kMinPollers = 2; - static const int kMaxPollers = 10; - - static const int kPollingTimeoutMsec = 10; - static const int kDoWorkDurationMsec = 1; - - // PollForWork will return SHUTDOWN after these many number of invocations - static const int kMaxNumPollForWork = 50; + ThreadManagerTestSettings settings_; + // Counters gpr_atm num_do_work_; // Number of calls to DoWork gpr_atm num_poll_for_work_; // Number of calls to PollForWork gpr_atm num_work_found_; // Number of times WORK_FOUND was returned @@ -69,58 +83,113 @@ void ThreadManagerTest::SleepForMs(int duration_ms) { grpc::ThreadManager::WorkStatus ThreadManagerTest::PollForWork(void** tag, bool* ok) { int call_num = gpr_atm_no_barrier_fetch_add(&num_poll_for_work_, 1); - - if (call_num >= kMaxNumPollForWork) { + if (call_num >= settings_.max_poll_calls) { Shutdown(); return SHUTDOWN; } - // Simulate "polling for work" by sleeping for sometime - SleepForMs(kPollingTimeoutMsec); - + SleepForMs(settings_.poll_duration_ms); // Simulate "polling" duration *tag = nullptr; *ok = true; - // Return timeout roughly 1 out of every 3 calls + // Return timeout roughly 1 out of every 3 calls just to make the test a bit + // more interesting if (call_num % 3 == 0) { return TIMEOUT; - } else { - gpr_atm_no_barrier_fetch_add(&num_work_found_, 1); - return WORK_FOUND; } + + gpr_atm_no_barrier_fetch_add(&num_work_found_, 1); + return WORK_FOUND; } void ThreadManagerTest::DoWork(void* tag, bool ok) { gpr_atm_no_barrier_fetch_add(&num_do_work_, 1); - SleepForMs(kDoWorkDurationMsec); // Simulate doing work by sleeping + SleepForMs(settings_.work_duration_ms); // Simulate work by sleeping } -void ThreadManagerTest::PerformTest() { - // Initialize() starts the ThreadManager - Initialize(); - - // Wait for all the threads to gracefully terminate - Wait(); +int ThreadManagerTest::GetNumWorkFound() { + return static_cast(gpr_atm_no_barrier_load(&num_work_found_)); +} - // The number of times DoWork() was called is equal to the number of times - // WORK_FOUND was returned - gpr_log(GPR_DEBUG, "DoWork() called %" PRIdPTR " times", - gpr_atm_no_barrier_load(&num_do_work_)); - GPR_ASSERT(gpr_atm_no_barrier_load(&num_do_work_) == - gpr_atm_no_barrier_load(&num_work_found_)); +int ThreadManagerTest::GetNumDoWork() { + return static_cast(gpr_atm_no_barrier_load(&num_do_work_)); } } // namespace grpc -int main(int argc, char** argv) { - std::srand(std::time(nullptr)); +// Test that the number of times DoWork() is called is equal to the number of +// times PollForWork() returned WORK_FOUND +static void TestPollAndWork() { + grpc_resource_quota* rq = grpc_resource_quota_create("Test-poll-and-work"); + grpc::ThreadManagerTestSettings settings = { + 2 /* min_pollers */, 10 /* max_pollers */, 10 /* poll_duration_ms */, + 1 /* work_duration_ms */, 50 /* max_poll_calls */}; - grpc::testing::InitTest(&argc, &argv, true); + grpc::ThreadManagerTest test_thd_mgr("TestThreadManager", rq, settings); + grpc_resource_quota_unref(rq); + + test_thd_mgr.Initialize(); // Start the thread manager + test_thd_mgr.Wait(); // Wait for all threads to finish + + // Verify that The number of times DoWork() was called is equal to the number + // of times WORK_FOUND was returned + gpr_log(GPR_DEBUG, "DoWork() called %d times", test_thd_mgr.GetNumDoWork()); + GPR_ASSERT(test_thd_mgr.GetNumDoWork() == test_thd_mgr.GetNumWorkFound()); +} - grpc_resource_quota* rq = grpc_resource_quota_create("Test"); - grpc::ThreadManagerTest test_rpc_manager("TestThreadManager", rq); +static void TestThreadQuota() { + const int kMaxNumThreads = 3; + grpc_resource_quota* rq = grpc_resource_quota_create("Test-thread-quota"); + grpc_resource_quota_set_max_threads(rq, kMaxNumThreads); + + // Set work_duration_ms to be much greater than poll_duration_ms. This way, + // the thread manager will be forced to create more 'polling' threads to + // honor the min_pollers guarantee + grpc::ThreadManagerTestSettings settings = { + 1 /* min_pollers */, 1 /* max_pollers */, 1 /* poll_duration_ms */, + 10 /* work_duration_ms */, 50 /* max_poll_calls */}; + + // Create two thread managers (but with same resource quota). This means + // that the max number of active threads across BOTH the thread managers + // cannot be greater than kMaxNumthreads + grpc::ThreadManagerTest test_thd_mgr_1("TestThreadManager-1", rq, settings); + grpc::ThreadManagerTest test_thd_mgr_2("TestThreadManager-2", rq, settings); + // It is ok to unref resource quota before starting thread managers. grpc_resource_quota_unref(rq); - test_rpc_manager.PerformTest(); + // Start both thread managers + test_thd_mgr_1.Initialize(); + test_thd_mgr_2.Initialize(); + + // Wait for both to finish + test_thd_mgr_1.Wait(); + test_thd_mgr_2.Wait(); + + // Now verify that the total number of active threads in either thread manager + // never exceeds kMaxNumThreads + // + // NOTE: Actually the total active threads across *both* thread managers at + // any point of time never exceeds kMaxNumThreads but unfortunately there is + // no easy way to verify it (i.e we can't just do (max1 + max2 <= k)) + // Its okay to not test this case here. The resource quota c-core tests + // provide enough coverage to resource quota object with multiple resource + // users + int max1 = test_thd_mgr_1.GetMaxActiveThreadsSoFar(); + int max2 = test_thd_mgr_2.GetMaxActiveThreadsSoFar(); + gpr_log( + GPR_DEBUG, + "MaxActiveThreads in TestThreadManager_1: %d, TestThreadManager_2: %d", + max1, max2); + GPR_ASSERT(max1 <= kMaxNumThreads && max2 <= kMaxNumThreads); +} + +int main(int argc, char** argv) { + std::srand(std::time(nullptr)); + grpc::testing::InitTest(&argc, &argv, true); + grpc_init(); + + TestPollAndWork(); + TestThreadQuota(); + grpc_shutdown(); return 0; } -- cgit v1.2.3 From 9bc8ee42c20385214027ced5991b9973a0282655 Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Wed, 25 Jul 2018 10:58:33 -0700 Subject: generate_projects.sh --- grpc.def | 1 + src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 ++ src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 +++ test/core/surface/public_headers_must_be_c89.c | 1 + 4 files changed, 7 insertions(+) (limited to 'test/core') diff --git a/grpc.def b/grpc.def index 5b98792662..312e916682 100644 --- a/grpc.def +++ b/grpc.def @@ -68,6 +68,7 @@ EXPORTS grpc_resource_quota_ref grpc_resource_quota_unref grpc_resource_quota_resize + grpc_resource_quota_set_max_threads grpc_resource_quota_arg_vtable grpc_channelz_get_top_channels grpc_channelz_get_channel diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 2443532bb8..78090afd6c 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -91,6 +91,7 @@ grpc_resource_quota_create_type grpc_resource_quota_create_import; grpc_resource_quota_ref_type grpc_resource_quota_ref_import; grpc_resource_quota_unref_type grpc_resource_quota_unref_import; grpc_resource_quota_resize_type grpc_resource_quota_resize_import; +grpc_resource_quota_set_max_threads_type grpc_resource_quota_set_max_threads_import; grpc_resource_quota_arg_vtable_type grpc_resource_quota_arg_vtable_import; grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import; grpc_channelz_get_channel_type grpc_channelz_get_channel_import; @@ -341,6 +342,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_resource_quota_ref_import = (grpc_resource_quota_ref_type) GetProcAddress(library, "grpc_resource_quota_ref"); grpc_resource_quota_unref_import = (grpc_resource_quota_unref_type) GetProcAddress(library, "grpc_resource_quota_unref"); grpc_resource_quota_resize_import = (grpc_resource_quota_resize_type) GetProcAddress(library, "grpc_resource_quota_resize"); + grpc_resource_quota_set_max_threads_import = (grpc_resource_quota_set_max_threads_type) GetProcAddress(library, "grpc_resource_quota_set_max_threads"); grpc_resource_quota_arg_vtable_import = (grpc_resource_quota_arg_vtable_type) GetProcAddress(library, "grpc_resource_quota_arg_vtable"); grpc_channelz_get_top_channels_import = (grpc_channelz_get_top_channels_type) GetProcAddress(library, "grpc_channelz_get_top_channels"); grpc_channelz_get_channel_import = (grpc_channelz_get_channel_type) GetProcAddress(library, "grpc_channelz_get_channel"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index b08a1f94f7..1807efa761 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -248,6 +248,9 @@ extern grpc_resource_quota_unref_type grpc_resource_quota_unref_import; typedef void(*grpc_resource_quota_resize_type)(grpc_resource_quota* resource_quota, size_t new_size); extern grpc_resource_quota_resize_type grpc_resource_quota_resize_import; #define grpc_resource_quota_resize grpc_resource_quota_resize_import +typedef void(*grpc_resource_quota_set_max_threads_type)(grpc_resource_quota* resource_quota, int new_max_threads); +extern grpc_resource_quota_set_max_threads_type grpc_resource_quota_set_max_threads_import; +#define grpc_resource_quota_set_max_threads grpc_resource_quota_set_max_threads_import typedef const grpc_arg_pointer_vtable*(*grpc_resource_quota_arg_vtable_type)(void); extern grpc_resource_quota_arg_vtable_type grpc_resource_quota_arg_vtable_import; #define grpc_resource_quota_arg_vtable grpc_resource_quota_arg_vtable_import diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 9f4ad2b4d7..497f7194d5 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -130,6 +130,7 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_resource_quota_ref); printf("%lx", (unsigned long) grpc_resource_quota_unref); printf("%lx", (unsigned long) grpc_resource_quota_resize); + printf("%lx", (unsigned long) grpc_resource_quota_set_max_threads); printf("%lx", (unsigned long) grpc_resource_quota_arg_vtable); printf("%lx", (unsigned long) grpc_channelz_get_top_channels); printf("%lx", (unsigned long) grpc_channelz_get_channel); -- cgit v1.2.3 From 1b1d5e52e7aa0ecdd455ad084aa7930ea89bbfd1 Mon Sep 17 00:00:00 2001 From: Alex Polcyn Date: Sat, 16 Jun 2018 04:08:55 +0000 Subject: Get c-ares to compile and do address sorting on windows --- BUILD | 3 + CMakeLists.txt | 44 ++++-- Makefile | 42 ++++++ build.yaml | 15 ++ config.m4 | 3 + config.w32 | 3 + gRPC-Core.podspec | 3 + grpc.gemspec | 3 + grpc.gyp | 6 + include/grpc/impl/codegen/port_platform.h | 4 - package.xml | 3 + .../resolver/dns/c_ares/dns_resolver_ares.cc | 5 +- .../resolver/dns/c_ares/grpc_ares_ev_driver.cc | 6 +- .../dns/c_ares/grpc_ares_ev_driver_windows.cc | 59 ++++++++ .../resolver/dns/c_ares/grpc_ares_wrapper.cc | 9 +- .../resolver/dns/c_ares/grpc_ares_wrapper.h | 4 + .../resolver/dns/c_ares/grpc_ares_wrapper_posix.cc | 29 ++++ .../dns/c_ares/grpc_ares_wrapper_windows.cc | 29 ++++ src/core/lib/iomgr/socket_windows.cc | 29 ++++ src/core/lib/iomgr/socket_windows.h | 4 + src/python/grpcio/grpc_core_dependencies.py | 3 + test/core/iomgr/BUILD | 13 ++ .../iomgr/grpc_ipv6_loopback_available_test.cc | 48 +++++++ test/cpp/naming/address_sorting_test.cc | 160 ++++++++++++++++----- test/cpp/naming/gen_build_yaml.py | 2 +- third_party/address_sorting/address_sorting.c | 9 +- .../address_sorting/address_sorting_windows.c | 46 +++++- .../include/address_sorting/address_sorting.h | 3 + tools/doxygen/Doxyfile.core.internal | 3 + tools/run_tests/generated/sources_and_headers.json | 22 ++- tools/run_tests/generated/tests.json | 38 ++++- 31 files changed, 577 insertions(+), 73 deletions(-) create mode 100644 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc create mode 100644 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc create mode 100644 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc create mode 100644 test/core/iomgr/grpc_ipv6_loopback_available_test.cc (limited to 'test/core') diff --git a/BUILD b/BUILD index ee4b5dfaec..81390dd1aa 100644 --- a/BUILD +++ b/BUILD @@ -1433,7 +1433,10 @@ grpc_cc_library( "src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc", ], hdrs = [ diff --git a/CMakeLists.txt b/CMakeLists.txt index 84e9c08cb5..e8e65d4b71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,6 +298,7 @@ add_dependencies(buildtests_c grpc_completion_queue_test) add_dependencies(buildtests_c grpc_completion_queue_threading_test) add_dependencies(buildtests_c grpc_credentials_test) add_dependencies(buildtests_c grpc_fetch_oauth2) +add_dependencies(buildtests_c grpc_ipv6_loopback_available_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c grpc_json_token_test) endif() @@ -671,12 +672,8 @@ endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx resolver_component_tests_runner_invoker) endif() -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx address_sorting_test_unsecure) -endif() -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx address_sorting_test) -endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx cancel_ares_query_test) endif() @@ -1236,8 +1233,11 @@ add_library(grpc src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc src/cpp/ext/filters/census/grpc_context.cc @@ -2538,8 +2538,11 @@ add_library(grpc_unsecure src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc @@ -7323,6 +7326,35 @@ target_link_libraries(grpc_fetch_oauth2 gpr ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + +add_executable(grpc_ipv6_loopback_available_test + test/core/iomgr/grpc_ipv6_loopback_available_test.cc +) + + +target_include_directories(grpc_ipv6_loopback_available_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} +) + +target_link_libraries(grpc_ipv6_loopback_available_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr +) + endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -16351,7 +16383,6 @@ target_link_libraries(resolver_component_tests_runner_invoker endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(address_sorting_test_unsecure test/cpp/naming/address_sorting_test.cc @@ -16391,10 +16422,8 @@ target_link_libraries(address_sorting_test_unsecure ${_gRPC_GFLAGS_LIBRARIES} ) -endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(address_sorting_test test/cpp/naming/address_sorting_test.cc @@ -16434,7 +16463,6 @@ target_link_libraries(address_sorting_test ${_gRPC_GFLAGS_LIBRARIES} ) -endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) diff --git a/Makefile b/Makefile index bad41975a0..5174ab6719 100644 --- a/Makefile +++ b/Makefile @@ -1022,6 +1022,7 @@ grpc_completion_queue_threading_test: $(BINDIR)/$(CONFIG)/grpc_completion_queue_ grpc_create_jwt: $(BINDIR)/$(CONFIG)/grpc_create_jwt grpc_credentials_test: $(BINDIR)/$(CONFIG)/grpc_credentials_test grpc_fetch_oauth2: $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 +grpc_ipv6_loopback_available_test: $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test grpc_json_token_test: $(BINDIR)/$(CONFIG)/grpc_json_token_test grpc_jwt_verifier_test: $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test grpc_print_google_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token @@ -1472,6 +1473,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test \ $(BINDIR)/$(CONFIG)/grpc_credentials_test \ $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 \ + $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test \ $(BINDIR)/$(CONFIG)/grpc_json_token_test \ $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test \ $(BINDIR)/$(CONFIG)/grpc_security_connector_test \ @@ -2028,6 +2030,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test || ( echo test grpc_completion_queue_threading_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_credentials_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_credentials_test || ( echo test grpc_credentials_test failed ; exit 1 ) + $(E) "[RUN] Testing grpc_ipv6_loopback_available_test" + $(Q) $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test || ( echo test grpc_ipv6_loopback_available_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_json_token_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_json_token_test || ( echo test grpc_json_token_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_jwt_verifier_test" @@ -3704,8 +3708,11 @@ LIBGRPC_SRC = \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \ src/cpp/ext/filters/census/grpc_context.cc \ @@ -4972,8 +4979,11 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ @@ -12365,6 +12375,38 @@ endif endif +GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_SRC = \ + test/core/iomgr/grpc_ipv6_loopback_available_test.cc \ + +GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test: $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/grpc_ipv6_loopback_available_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_grpc_ipv6_loopback_available_test: $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS:.o=.dep) +endif +endif + + GRPC_JSON_TOKEN_TEST_SRC = \ test/core/security/json_token_test.cc \ diff --git a/build.yaml b/build.yaml index 30389ec114..70af96046c 100644 --- a/build.yaml +++ b/build.yaml @@ -740,8 +740,11 @@ filegroups: - src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc + - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc + - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc + - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc plugin: grpc_resolver_dns_ares uses: - grpc_base @@ -2730,6 +2733,18 @@ targets: - grpc - gpr_test_util - gpr +- name: grpc_ipv6_loopback_available_test + build: test + language: c + src: + - test/core/iomgr/grpc_ipv6_loopback_available_test.cc + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + exclude_iomgrs: + - uv - name: grpc_json_token_test build: test language: c diff --git a/config.m4 b/config.m4 index c277ccafc8..aa40a698a6 100644 --- a/config.m4 +++ b/config.m4 @@ -380,8 +380,11 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \ src/cpp/ext/filters/census/grpc_context.cc \ diff --git a/config.w32 b/config.w32 index 2857781dd5..5afa4466ac 100644 --- a/config.w32 +++ b/config.w32 @@ -355,8 +355,11 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\dns_resolver_ares.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_posix.cc " + + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_windows.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_fallback.cc " + + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_posix.cc " + + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_windows.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\native\\dns_resolver.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\sockaddr\\sockaddr_resolver.cc " + "src\\cpp\\ext\\filters\\census\\grpc_context.cc " + diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 23edaec656..5c3649afbd 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -802,8 +802,11 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/cpp/ext/filters/census/grpc_context.cc', diff --git a/grpc.gemspec b/grpc.gemspec index b69d5a7c6f..c250316b99 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -742,8 +742,11 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc ) s.files += %w( src/cpp/ext/filters/census/grpc_context.cc ) diff --git a/grpc.gyp b/grpc.gyp index e1485efa05..25082fe540 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -572,8 +572,11 @@ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/cpp/ext/filters/census/grpc_context.cc', @@ -1287,8 +1290,11 @@ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc', diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index 01ce5f03e9..2b61a8816d 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -420,12 +420,8 @@ typedef unsigned __int64 uint64_t; #define GPR_MAX_ALIGNMENT 16 #ifndef GRPC_ARES -#ifdef GPR_WINDOWS -#define GRPC_ARES 0 -#else #define GRPC_ARES 1 #endif -#endif #ifndef GRPC_MUST_USE_RESULT #if defined(__GNUC__) && !defined(__MINGW32__) diff --git a/package.xml b/package.xml index 7f71536b1d..acdc6ffdb3 100644 --- a/package.xml +++ b/package.xml @@ -747,8 +747,11 @@ + + + diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index f4f6444c5f..7050e82121 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -142,8 +141,8 @@ AresDnsResolver::AresDnsResolver(const ResolverArgs& args) channel_args_ = grpc_channel_args_copy(args.args); const grpc_arg* arg = grpc_channel_args_find( channel_args_, GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION); - request_service_config_ = !grpc_channel_arg_get_integer( - arg, (grpc_integer_options){false, false, true}); + grpc_integer_options integer_options = {false, false, true}; + request_service_config_ = !grpc_channel_arg_get_integer(arg, integer_options); arg = grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS); min_time_between_resolutions_ = diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc index c886795608..0068d0d5f4 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc @@ -18,11 +18,10 @@ #include #include "src/core/lib/iomgr/port.h" -#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) +#if GRPC_ARES == 1 && !defined(GRPC_UV) #include #include -#include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" @@ -32,7 +31,6 @@ #include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -314,4 +312,4 @@ void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver) { } } -#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ +#endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc new file mode 100644 index 0000000000..5d65ae3ab3 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc @@ -0,0 +1,59 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include + +#include "src/core/lib/iomgr/port.h" +#if GRPC_ARES == 1 && defined(GPR_WINDOWS) + +#include +#include +#include "src/core/lib/gprpp/memory.h" + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" + +namespace grpc_core { + +/* TODO: fill in the body of GrpcPolledFdWindows to enable c-ares on Windows. + This dummy implementation only allows grpc to compile on windows with + GRPC_ARES=1. */ +class GrpcPolledFdWindows : public GrpcPolledFd { + public: + GrpcPolledFdWindows() { abort(); } + ~GrpcPolledFdWindows() { abort(); } + void RegisterForOnReadableLocked(grpc_closure* read_closure) override { + abort(); + } + void RegisterForOnWriteableLocked(grpc_closure* write_closure) override { + abort(); + } + bool IsFdStillReadableLocked() override { abort(); } + void ShutdownLocked(grpc_error* error) override { abort(); } + ares_socket_t GetWrappedAresSocketLocked() override { abort(); } + const char* GetName() override { abort(); } +}; + +GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as, + grpc_pollset_set* driver_pollset_set) { + return nullptr; +} + +void ConfigureAresChannelLocked(ares_channel* channel) { abort(); } + +} // namespace grpc_core + +#endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc index 497ad998af..b3d6437e9a 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc @@ -22,7 +22,6 @@ #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/socket_utils_posix.h" #include #include @@ -215,7 +214,7 @@ static void on_hostbyname_done_locked(void* arg, int status, int timeouts, memset(&addr, 0, addr_len); memcpy(&addr.sin6_addr, hostent->h_addr_list[i - prev_naddr], sizeof(struct in6_addr)); - addr.sin6_family = static_cast(hostent->h_addrtype); + addr.sin6_family = static_cast(hostent->h_addrtype); addr.sin6_port = hr->port; grpc_lb_addresses_set_address( *lb_addresses, i, &addr, addr_len, @@ -236,7 +235,7 @@ static void on_hostbyname_done_locked(void* arg, int status, int timeouts, memset(&addr, 0, addr_len); memcpy(&addr.sin_addr, hostent->h_addr_list[i - prev_naddr], sizeof(struct in_addr)); - addr.sin_family = static_cast(hostent->h_addrtype); + addr.sin_family = static_cast(hostent->h_addrtype); addr.sin_port = hr->port; grpc_lb_addresses_set_address( *lb_addresses, i, &addr, addr_len, @@ -281,7 +280,7 @@ static void on_srv_query_done_locked(void* arg, int status, int timeouts, grpc_ares_ev_driver_get_channel_locked(r->ev_driver); for (struct ares_srv_reply* srv_it = reply; srv_it != nullptr; srv_it = srv_it->next) { - if (grpc_ipv6_loopback_available()) { + if (grpc_ares_query_ipv6()) { grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked( r, srv_it->host, htons(srv_it->port), true /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET6, @@ -452,7 +451,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( } } r->pending_queries = 1; - if (grpc_ipv6_loopback_available()) { + if (grpc_ares_query_ipv6()) { hr = create_hostbyname_request_locked(r, host, strhtons(port), false /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked, diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h index ce26f5d524..17eaa7ccf0 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h @@ -70,6 +70,10 @@ void grpc_ares_cleanup(void); * and destroys the grpc_ares_request */ void grpc_ares_complete_request_locked(grpc_ares_request* request); +/* Indicates whether or not AAAA queries should be attempted. */ +/* E.g., return false if ipv6 is known to not be available. */ +bool grpc_ares_query_ipv6(); + /* Exposed only for testing */ void grpc_cares_wrapper_test_only_address_sorting_sort( grpc_lb_addresses* lb_addrs); diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc new file mode 100644 index 0000000000..23c0fec74f --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc @@ -0,0 +1,29 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/port.h" +#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" + +bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } + +#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc new file mode 100644 index 0000000000..ee827e284e --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc @@ -0,0 +1,29 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/port.h" +#if GRPC_ARES == 1 && defined(GPR_WINDOWS) + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/iomgr/socket_windows.h" + +bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } + +#endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */ diff --git a/src/core/lib/iomgr/socket_windows.cc b/src/core/lib/iomgr/socket_windows.cc index 2e23409582..4ad31cb35d 100644 --- a/src/core/lib/iomgr/socket_windows.cc +++ b/src/core/lib/iomgr/socket_windows.cc @@ -36,6 +36,7 @@ #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_windows.h" +#include "src/core/lib/iomgr/sockaddr_windows.h" #include "src/core/lib/iomgr/socket_windows.h" grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name) { @@ -148,4 +149,32 @@ void grpc_socket_become_ready(grpc_winsocket* socket, if (should_destroy) destroy(socket); } +static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT; +static bool g_ipv6_loopback_available = false; + +static void probe_ipv6_once(void) { + SOCKET s = socket(AF_INET6, SOCK_STREAM, 0); + g_ipv6_loopback_available = 0; + if (s == INVALID_SOCKET) { + gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed."); + } else { + grpc_sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */ + if (bind(s, reinterpret_cast(&addr), sizeof(addr)) == 0) { + g_ipv6_loopback_available = 1; + } else { + gpr_log(GPR_INFO, + "Disabling AF_INET6 sockets because ::1 is not available."); + } + closesocket(s); + } +} + +int grpc_ipv6_loopback_available(void) { + gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once); + return g_ipv6_loopback_available; +} + #endif /* GRPC_WINSOCK_SOCKET */ diff --git a/src/core/lib/iomgr/socket_windows.h b/src/core/lib/iomgr/socket_windows.h index 7bd01eded5..b09b9da562 100644 --- a/src/core/lib/iomgr/socket_windows.h +++ b/src/core/lib/iomgr/socket_windows.h @@ -108,6 +108,10 @@ void grpc_socket_notify_on_read(grpc_winsocket* winsocket, void grpc_socket_become_ready(grpc_winsocket* winsocket, grpc_winsocket_callback_info* ci); +/* Returns true if this system can create AF_INET6 sockets bound to ::1. + The value is probed once, and cached for the life of the process. */ +int grpc_ipv6_loopback_available(void); + #endif #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H */ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 49185cc648..d6efb49750 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -354,8 +354,11 @@ CORE_SOURCE_FILES = [ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/cpp/ext/filters/census/grpc_context.cc', diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index fb0490a95f..002671a5fa 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -124,6 +124,19 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "grpc_ipv6_loopback_available_test", + srcs = ["grpc_ipv6_loopback_available_test.cc"], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + + grpc_cc_test( name = "load_file_test", srcs = ["load_file_test.cc"], diff --git a/test/core/iomgr/grpc_ipv6_loopback_available_test.cc b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc new file mode 100644 index 0000000000..329aa9a851 --- /dev/null +++ b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc @@ -0,0 +1,48 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// grpc_ipv6_loopback_available isn't currently available on UV. +#ifndef GRPC_UV + +#include +#include +#include "test/core/util/test_config.h" + +#ifdef GPR_WINDOWS +#include "src/core/lib/iomgr/socket_windows.h" +#else +#include "src/core/lib/iomgr/socket_utils_posix.h" +#endif + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + grpc_init(); + // This test assumes that the ipv6 loopback is available + // in all environments in which grpc tests run in. + GPR_ASSERT(grpc_ipv6_loopback_available()); + grpc_shutdown(); + return 0; +} + +#else + +int main(int argc, char** argv) { return 0; } + +#endif /* GRPC_UV */ diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc index a92e9e3b3e..04c300876c 100644 --- a/test/cpp/naming/address_sorting_test.cc +++ b/test/cpp/naming/address_sorting_test.cc @@ -24,10 +24,8 @@ #include #include -#include #include #include -#include #include #include @@ -51,6 +49,11 @@ #include "test/core/util/port.h" #include "test/core/util/test_config.h" +#ifndef GPR_WINDOWS +#include +#include +#endif + namespace { struct TestAddress { @@ -190,10 +193,18 @@ void VerifyLbAddrOutputs(grpc_lb_addresses* lb_addrs, grpc_lb_addresses_destroy(lb_addrs); } -} // namespace +/* We need to run each test case inside of its own + * isolated grpc_init/grpc_shutdown pair, so that + * the "address sorting source addr factory" can be + * restored to its default for each test case. */ +class AddressSortingTest : public ::testing::Test { + protected: + void SetUp() override { grpc_init(); } + void TearDown() override { grpc_shutdown(); } +}; /* Tests for rule 1 */ -TEST(AddressSortingTest, TestDepriotizesUnreachableAddresses) { +TEST_F(AddressSortingTest, TestDepriotizesUnreachableAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -212,7 +223,7 @@ TEST(AddressSortingTest, TestDepriotizesUnreachableAddresses) { }); } -TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { +TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { bool ipv4_supported = true; bool ipv6_supported = false; OverrideAddressSortingSourceAddrFactory( @@ -231,7 +242,7 @@ TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { }); } -TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { +TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { bool ipv4_supported = false; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -253,7 +264,7 @@ TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { /* Tests for rule 2 */ -TEST(AddressSortingTest, TestDepriotizesNonMatchingScope) { +TEST_F(AddressSortingTest, TestDepriotizesNonMatchingScope) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -277,7 +288,7 @@ TEST(AddressSortingTest, TestDepriotizesNonMatchingScope) { /* Tests for rule 5 */ -TEST(AddressSortingTest, TestUsesLabelFromDefaultTable) { +TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTable) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -300,7 +311,7 @@ TEST(AddressSortingTest, TestUsesLabelFromDefaultTable) { /* Flip the input on the test above to reorder the sort function's * comparator's inputs. */ -TEST(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { +TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -323,8 +334,8 @@ TEST(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { /* Tests for rule 6 */ -TEST(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address) { +TEST_F(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -348,8 +359,8 @@ TEST(AddressSortingTest, }); } -TEST(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress) { +TEST_F(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress) { bool ipv4_supported = true; bool ipv6_supported = true; // Handle unique observed behavior of inet_ntop(v4-compatible-address) on OS X. @@ -377,8 +388,8 @@ TEST(AddressSortingTest, }); } -TEST(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress) { +TEST_F(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -403,8 +414,8 @@ TEST(AddressSortingTest, }); } -TEST(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress) { +TEST_F(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -426,7 +437,7 @@ TEST(AddressSortingTest, }); } -TEST( +TEST_F( AddressSortingTest, TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddressEnsurePrefixMatchHasNoEffect) { bool ipv4_supported = true; @@ -448,8 +459,8 @@ TEST( }); } -TEST(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses) { +TEST_F(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -469,19 +480,22 @@ TEST(AddressSortingTest, }); } -TEST( +TEST_F( AddressSortingTest, TestUsesDestinationWithHigherPrecedenceWithCatchAllAndAndV4MappedAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; + // Use embedded ipv4 addresses with leading 1's instead of zero's to be + // compatible with inet_ntop implementations that can display such + // addresses with leading zero's as e.g.: "::ffff:0:2", as on windows. OverrideAddressSortingSourceAddrFactory( ipv4_supported, ipv6_supported, { - {"[::ffff:0.0.0.2]:443", {"[::ffff:0.0.0.3]:0", AF_INET6}}, + {"[::ffff:1.1.1.2]:443", {"[::ffff:1.1.1.3]:0", AF_INET6}}, {"[1234::2]:443", {"[1234::3]:0", AF_INET6}}, }); grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({ - {"[::ffff:0.0.0.2]:443", AF_INET6}, + {"[::ffff:1.1.1.2]:443", AF_INET6}, {"[1234::2]:443", AF_INET6}, }); grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); @@ -489,13 +503,13 @@ TEST( // ::ffff:0:2 should match the v4-mapped // precedence entry and be deprioritized. "[1234::2]:443", - "[::ffff:0.0.0.2]:443", + "[::ffff:1.1.1.2]:443", }); } /* Tests for rule 8 */ -TEST(AddressSortingTest, TestPrefersSmallerScope) { +TEST_F(AddressSortingTest, TestPrefersSmallerScope) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -520,7 +534,7 @@ TEST(AddressSortingTest, TestPrefersSmallerScope) { /* Tests for rule 9 */ -TEST(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { +TEST_F(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -543,8 +557,8 @@ TEST(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { }); } -TEST(AddressSortingTest, - TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress) { +TEST_F(AddressSortingTest, + TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -564,7 +578,7 @@ TEST(AddressSortingTest, }); } -TEST(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { +TEST_F(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -584,7 +598,7 @@ TEST(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { }); } -TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { +TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -604,7 +618,7 @@ TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { }); } -TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { +TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -628,7 +642,7 @@ TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { /* Tests for rule 10 */ -TEST(AddressSortingTest, TestStableSort) { +TEST_F(AddressSortingTest, TestStableSort) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -648,7 +662,7 @@ TEST(AddressSortingTest, TestStableSort) { }); } -TEST(AddressSortingTest, TestStableSortFiveElements) { +TEST_F(AddressSortingTest, TestStableSortFiveElements) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -677,7 +691,7 @@ TEST(AddressSortingTest, TestStableSortFiveElements) { }); } -TEST(AddressSortingTest, TestStableSortNoSrcAddrsExist) { +TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExist) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {}); @@ -698,7 +712,7 @@ TEST(AddressSortingTest, TestStableSortNoSrcAddrsExist) { }); } -TEST(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { +TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {}); @@ -713,7 +727,7 @@ TEST(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { }); } -TEST(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { +TEST_F(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; // Handle unique observed behavior of inet_ntop(v4-compatible-address) on OS X. @@ -744,6 +758,78 @@ TEST(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { }); } +/* TestPrefersIpv6Loopback tests the actual "address probing" code + * for the current platform, without any mocks. + * This test relies on the assumption that the ipv6 loopback address is + * available in the hosts/containers that grpc C/C++ tests run on + * (whether ipv4 loopback is available or not, an available ipv6 + * loopback should be preferred). */ +TEST_F(AddressSortingTest, TestPrefersIpv6Loopback) { + grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({ + {"[::1]:443", AF_INET6}, + {"127.0.0.1:443", AF_INET}, + }); + grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + VerifyLbAddrOutputs(lb_addrs, { + "[::1]:443", + "127.0.0.1:443", + }); +} + +/* Flip the order of the inputs above and expect the same output order + * (try to rule out influence of arbitrary qsort ordering) */ +TEST_F(AddressSortingTest, TestPrefersIpv6LoopbackInputsFlipped) { + grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({ + {"127.0.0.1:443", AF_INET}, + {"[::1]:443", AF_INET6}, + }); + grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + VerifyLbAddrOutputs(lb_addrs, { + "[::1]:443", + "127.0.0.1:443", + }); +} + +/* Try to rule out false positives in the above two tests in which + * the sorter might think that neither ipv6 or ipv4 loopback is + * available, but ipv6 loopback is still preferred only due + * to precedance table lookups. */ +TEST_F(AddressSortingTest, TestSorterKnowsIpv6LoopbackIsAvailable) { + sockaddr_in6 ipv6_loopback; + memset(&ipv6_loopback, 0, sizeof(ipv6_loopback)); + ipv6_loopback.sin6_family = AF_INET6; + ((char*)&ipv6_loopback.sin6_addr)[15] = 1; + ipv6_loopback.sin6_port = htons(443); + // Set up the source and destination parameters of + // address_sorting_get_source_addr + address_sorting_address sort_input_dest; + memcpy(&sort_input_dest.addr, &ipv6_loopback, sizeof(ipv6_loopback)); + sort_input_dest.len = sizeof(ipv6_loopback); + address_sorting_address source_for_sort_input_dest; + memset(&source_for_sort_input_dest, 0, sizeof(source_for_sort_input_dest)); + // address_sorting_get_source_addr returns true if a source address was found + // for the destination address, otherwise false. + EXPECT_TRUE(address_sorting_get_source_addr_for_testing( + &sort_input_dest, &source_for_sort_input_dest)); + // Now also check that the source address was filled in correctly. + EXPECT_GT(source_for_sort_input_dest.len, 0u); + sockaddr_in6* source_addr_output = + (sockaddr_in6*)source_for_sort_input_dest.addr; + EXPECT_EQ(source_addr_output->sin6_family, AF_INET6); + char* buf = static_cast(gpr_zalloc(100)); + EXPECT_NE(inet_ntop(AF_INET6, &source_addr_output->sin6_addr, buf, 100), + nullptr) + << "inet_ntop failed. Errno: " + std::to_string(errno); + std::string source_addr_str(buf); + gpr_free(buf); + // This test + // assumes that the source address for any loopback destination is also the + // loopback address. + EXPECT_EQ(source_addr_str, "::1"); +} + +} // namespace + int main(int argc, char** argv) { char* resolver = gpr_getenv("GRPC_DNS_RESOLVER"); if (resolver == nullptr || strlen(resolver) == 0) { @@ -754,9 +840,7 @@ int main(int argc, char** argv) { gpr_free(resolver); grpc_test_init(argc, argv); ::testing::InitGoogleTest(&argc, argv); - grpc_init(); auto result = RUN_ALL_TESTS(); - grpc_shutdown(); // Test sequential and nested inits and shutdowns. grpc_init(); grpc_init(); diff --git a/test/cpp/naming/gen_build_yaml.py b/test/cpp/naming/gen_build_yaml.py index baa6512f62..5dad2ea7af 100755 --- a/test/cpp/naming/gen_build_yaml.py +++ b/test/cpp/naming/gen_build_yaml.py @@ -110,7 +110,7 @@ def main(): 'gtest': True, 'run': True, 'src': ['test/cpp/naming/address_sorting_test.cc'], - 'platforms': ['linux', 'posix', 'mac'], + 'platforms': ['linux', 'posix', 'mac', 'windows'], 'deps': [ 'grpc++_test_util' + unsecure_build_config_suffix, 'grpc_test_util' + unsecure_build_config_suffix, diff --git a/third_party/address_sorting/address_sorting.c b/third_party/address_sorting/address_sorting.c index e4f3b53799..9aee0a5419 100644 --- a/third_party/address_sorting/address_sorting.c +++ b/third_party/address_sorting/address_sorting.c @@ -55,12 +55,17 @@ static const int kIPv6AddrScopeGlobal = 3; static address_sorting_source_addr_factory* g_current_source_addr_factory = NULL; -static int address_sorting_get_source_addr(const address_sorting_address* dest, - address_sorting_address* source) { +static bool address_sorting_get_source_addr(const address_sorting_address* dest, + address_sorting_address* source) { return g_current_source_addr_factory->vtable->get_source_addr( g_current_source_addr_factory, dest, source); } +bool address_sorting_get_source_addr_for_testing( + const address_sorting_address* dest, address_sorting_address* source) { + return address_sorting_get_source_addr(dest, source); +} + static int ipv6_prefix_match_length(const struct sockaddr_in6* sa, const struct sockaddr_in6* sb) { unsigned char* a = (unsigned char*)&sa->sin6_addr; diff --git a/third_party/address_sorting/address_sorting_windows.c b/third_party/address_sorting/address_sorting_windows.c index b2f5708649..662a88248e 100644 --- a/third_party/address_sorting/address_sorting_windows.c +++ b/third_party/address_sorting/address_sorting_windows.c @@ -42,14 +42,54 @@ #if defined(ADDRESS_SORTING_WINDOWS) +#include +#include +#include #include +#include +#include -/* TODO : Add address sorting functionality to work on windows. */ +static bool windows_source_addr_factory_get_source_addr( + address_sorting_source_addr_factory* factory, + const address_sorting_address* dest_addr, + address_sorting_address* source_addr) { + bool source_addr_exists = false; + SOCKET s = socket(((struct sockaddr_in6*)dest_addr)->sin6_family, SOCK_DGRAM, + IPPROTO_UDP); + if (s != INVALID_SOCKET) { + if (connect(s, (struct sockaddr*)dest_addr, (int)dest_addr->len) == 0) { + address_sorting_address found_source_addr; + memset(&found_source_addr, 0, sizeof(found_source_addr)); + found_source_addr.len = sizeof(found_source_addr.addr); + if (getsockname(s, (struct sockaddr*)&found_source_addr.addr, + (socklen_t*)&found_source_addr.len) == 0) { + source_addr_exists = true; + *source_addr = found_source_addr; + } + } + closesocket(s); + } + return source_addr_exists; +} + +static void windows_source_addr_factory_destroy( + address_sorting_source_addr_factory* self) { + free(self); +} + +static const address_sorting_source_addr_factory_vtable + windows_source_addr_factory_vtable = { + windows_source_addr_factory_get_source_addr, + windows_source_addr_factory_destroy, +}; address_sorting_source_addr_factory* address_sorting_create_source_addr_factory_for_current_platform() { - abort(); - return NULL; + address_sorting_source_addr_factory* factory = + malloc(sizeof(address_sorting_source_addr_factory)); + memset(factory, 0, sizeof(address_sorting_source_addr_factory)); + factory->vtable = &windows_source_addr_factory_vtable; + return factory; } #endif // defined(ADDRESS_SORTING_WINDOWS) diff --git a/third_party/address_sorting/include/address_sorting/address_sorting.h b/third_party/address_sorting/include/address_sorting/address_sorting.h index f11cd424b5..c58fafe3f7 100644 --- a/third_party/address_sorting/include/address_sorting/address_sorting.h +++ b/third_party/address_sorting/include/address_sorting/address_sorting.h @@ -103,6 +103,9 @@ address_sorting_family address_sorting_abstract_get_family( void address_sorting_override_source_addr_factory_for_testing( address_sorting_source_addr_factory* factory); +bool address_sorting_get_source_addr_for_testing( + const address_sorting_address* dest, address_sorting_address* source); + #ifdef __cplusplus } #endif diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 576950934e..18f56984fe 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -924,9 +924,12 @@ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ +src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ +src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ +src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/README.md \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 072402b2cf..a686dae8b4 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1032,6 +1032,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "grpc_ipv6_loopback_available_test", + "src": [ + "test/core/iomgr/grpc_ipv6_loopback_available_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -10254,9 +10271,12 @@ "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h", - "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc" + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc" ], "third_party": false, "type": "filegroup" diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index a5439a5db1..5815f82fef 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -1313,6 +1313,32 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "gtest": false, + "language": "c", + "name": "grpc_ipv6_loopback_available_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, @@ -5710,7 +5736,8 @@ "ci_platforms": [ "linux", "mac", - "posix" + "posix", + "windows" ], "cpu_cost": 1.0, "exclude_configs": [], @@ -5722,7 +5749,8 @@ "platforms": [ "linux", "mac", - "posix" + "posix", + "windows" ], "uses_polling": true }, @@ -5732,7 +5760,8 @@ "ci_platforms": [ "linux", "mac", - "posix" + "posix", + "windows" ], "cpu_cost": 1.0, "exclude_configs": [], @@ -5744,7 +5773,8 @@ "platforms": [ "linux", "mac", - "posix" + "posix", + "windows" ], "uses_polling": true }, -- cgit v1.2.3 From 87e772fa7bf8f29666031d490a61a36aeeb845ae Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 26 Jul 2018 14:30:58 -0700 Subject: Fix RefCountedPtr to handle polymorphism. --- src/core/lib/gprpp/orphanable.h | 6 ++-- src/core/lib/gprpp/ref_counted.h | 6 ++-- src/core/lib/gprpp/ref_counted_ptr.h | 59 +++++++++++++++++++++++++++++---- test/core/gprpp/ref_counted_ptr_test.cc | 26 ++++++++++++++- 4 files changed, 86 insertions(+), 11 deletions(-) (limited to 'test/core') diff --git a/src/core/lib/gprpp/orphanable.h b/src/core/lib/gprpp/orphanable.h index d0ec9b6461..3123e3f5a3 100644 --- a/src/core/lib/gprpp/orphanable.h +++ b/src/core/lib/gprpp/orphanable.h @@ -86,7 +86,8 @@ class InternallyRefCounted : public Orphanable { GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE // Allow RefCountedPtr<> to access Unref() and IncrementRefCount(). - friend class RefCountedPtr; + template + friend class RefCountedPtr; InternallyRefCounted() { gpr_ref_init(&refs_, 1); } virtual ~InternallyRefCounted() {} @@ -129,7 +130,8 @@ class InternallyRefCountedWithTracing : public Orphanable { GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE // Allow RefCountedPtr<> to access Unref() and IncrementRefCount(). - friend class RefCountedPtr; + template + friend class RefCountedPtr; InternallyRefCountedWithTracing() : InternallyRefCountedWithTracing(static_cast(nullptr)) {} diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h index ddac5bd475..03c293f6ed 100644 --- a/src/core/lib/gprpp/ref_counted.h +++ b/src/core/lib/gprpp/ref_counted.h @@ -73,7 +73,8 @@ class RefCounted { private: // Allow RefCountedPtr<> to access IncrementRefCount(). - friend class RefCountedPtr; + template + friend class RefCountedPtr; void IncrementRefCount() { gpr_ref(&refs_); } @@ -152,7 +153,8 @@ class RefCountedWithTracing { private: // Allow RefCountedPtr<> to access IncrementRefCount(). - friend class RefCountedPtr; + template + friend class RefCountedPtr; void IncrementRefCount() { gpr_ref(&refs_); } diff --git a/src/core/lib/gprpp/ref_counted_ptr.h b/src/core/lib/gprpp/ref_counted_ptr.h index 534d3d03cb..8a6615a779 100644 --- a/src/core/lib/gprpp/ref_counted_ptr.h +++ b/src/core/lib/gprpp/ref_counted_ptr.h @@ -36,7 +36,8 @@ class RefCountedPtr { RefCountedPtr(std::nullptr_t) {} // If value is non-null, we take ownership of a ref to it. - explicit RefCountedPtr(T* value) { value_ = value; } + template + explicit RefCountedPtr(Y* value) { value_ = value; } // Move support. RefCountedPtr(RefCountedPtr&& other) { @@ -49,6 +50,18 @@ class RefCountedPtr { other.value_ = nullptr; return *this; } + template + RefCountedPtr(RefCountedPtr&& other) { + value_ = other.value_; + other.value_ = nullptr; + } + template + RefCountedPtr& operator=(RefCountedPtr&& other) { + if (value_ != nullptr) value_->Unref(); + value_ = other.value_; + other.value_ = nullptr; + return *this; + } // Copy support. RefCountedPtr(const RefCountedPtr& other) { @@ -63,17 +76,37 @@ class RefCountedPtr { value_ = other.value_; return *this; } + template + RefCountedPtr(const RefCountedPtr& other) { + if (other.value_ != nullptr) other.value_->IncrementRefCount(); + value_ = other.value_; + } + template + RefCountedPtr& operator=(const RefCountedPtr& other) { + // Note: Order of reffing and unreffing is important here in case value_ + // and other.value_ are the same object. + if (other.value_ != nullptr) other.value_->IncrementRefCount(); + if (value_ != nullptr) value_->Unref(); + value_ = other.value_; + return *this; + } ~RefCountedPtr() { if (value_ != nullptr) value_->Unref(); } // If value is non-null, we take ownership of a ref to it. - void reset(T* value = nullptr) { + template + void reset(Y* value) { if (value_ != nullptr) value_->Unref(); value_ = value; } + void reset() { + if (value_ != nullptr) value_->Unref(); + value_ = nullptr; + } + // TODO(roth): This method exists solely as a transition mechanism to allow // us to pass a ref to idiomatic C code that does not use RefCountedPtr<>. // Once all of our code has been converted to idiomatic C++, this @@ -89,16 +122,30 @@ class RefCountedPtr { T& operator*() const { return *value_; } T* operator->() const { return value_; } - bool operator==(const RefCountedPtr& other) const { + template + bool operator==(const RefCountedPtr& other) const { return value_ == other.value_; } - bool operator==(const T* other) const { return value_ == other; } - bool operator!=(const RefCountedPtr& other) const { + + template + bool operator==(const Y* other) const { return value_ == other; } + + bool operator==(std::nullptr_t) const { return value_ == nullptr; } + + template + bool operator!=(const RefCountedPtr& other) const { return value_ != other.value_; } - bool operator!=(const T* other) const { return value_ != other; } + + template + bool operator!=(const Y* other) const { return value_ != other; } + + bool operator!=(std::nullptr_t) const { return value_ != nullptr; } private: + template + friend class RefCountedPtr; + T* value_ = nullptr; }; diff --git a/test/core/gprpp/ref_counted_ptr_test.cc b/test/core/gprpp/ref_counted_ptr_test.cc index aa30b72282..6df6e348c6 100644 --- a/test/core/gprpp/ref_counted_ptr_test.cc +++ b/test/core/gprpp/ref_counted_ptr_test.cc @@ -127,7 +127,7 @@ TEST(RefCountedPtr, ResetFromNonNullToNull) { TEST(RefCountedPtr, ResetFromNullToNull) { RefCountedPtr foo; EXPECT_EQ(nullptr, foo.get()); - foo.reset(nullptr); + foo.reset(); EXPECT_EQ(nullptr, foo.get()); } @@ -175,6 +175,30 @@ TEST(RefCountedPtr, RefCountedWithTracing) { foo->Unref(DEBUG_LOCATION, "foo"); } +class Parent : public RefCounted { + public: + Parent() {} +}; + +class Child : public Parent { + public: + Child() {} +}; + +void FunctionTakingParent(RefCountedPtr o) {} + +void FunctionTakingChild(RefCountedPtr o) {} + +TEST(RefCountedPtr, CanPassChildToFunctionExpectingParent) { + RefCountedPtr child = MakeRefCounted(); + FunctionTakingParent(child); +} + +TEST(RefCountedPtr, CanPassChildToFunctionExpectingChild) { + RefCountedPtr child = MakeRefCounted(); + FunctionTakingChild(child); +} + } // namespace } // namespace testing } // namespace grpc_core -- cgit v1.2.3 From f34c65393622878e9610939193fd9c754b7c0a74 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 26 Jul 2018 14:32:07 -0700 Subject: Revert "Merge pull request #15797 from apolcyn/windows_compile_and_sort" This reverts commit ae8d3efc3a360b289f0b33e1c53c8c73960cb31f, reversing changes made to e41215e181564a61320b9b69ae5feb7f7c3625fe. --- BUILD | 3 - CMakeLists.txt | 44 ++---- Makefile | 42 ------ build.yaml | 15 -- config.m4 | 3 - config.w32 | 3 - gRPC-Core.podspec | 3 - grpc.gemspec | 3 - grpc.gyp | 6 - include/grpc/impl/codegen/port_platform.h | 4 + package.xml | 3 - .../resolver/dns/c_ares/dns_resolver_ares.cc | 5 +- .../resolver/dns/c_ares/grpc_ares_ev_driver.cc | 6 +- .../dns/c_ares/grpc_ares_ev_driver_windows.cc | 59 -------- .../resolver/dns/c_ares/grpc_ares_wrapper.cc | 9 +- .../resolver/dns/c_ares/grpc_ares_wrapper.h | 4 - .../resolver/dns/c_ares/grpc_ares_wrapper_posix.cc | 29 ---- .../dns/c_ares/grpc_ares_wrapper_windows.cc | 29 ---- src/core/lib/iomgr/socket_windows.cc | 29 ---- src/core/lib/iomgr/socket_windows.h | 4 - src/python/grpcio/grpc_core_dependencies.py | 3 - test/core/iomgr/BUILD | 13 -- .../iomgr/grpc_ipv6_loopback_available_test.cc | 48 ------- test/cpp/naming/address_sorting_test.cc | 160 +++++---------------- test/cpp/naming/gen_build_yaml.py | 2 +- third_party/address_sorting/address_sorting.c | 9 +- .../address_sorting/address_sorting_windows.c | 46 +----- .../include/address_sorting/address_sorting.h | 3 - tools/doxygen/Doxyfile.core.internal | 3 - tools/run_tests/generated/sources_and_headers.json | 22 +-- tools/run_tests/generated/tests.json | 38 +---- 31 files changed, 73 insertions(+), 577 deletions(-) delete mode 100644 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc delete mode 100644 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc delete mode 100644 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc delete mode 100644 test/core/iomgr/grpc_ipv6_loopback_available_test.cc (limited to 'test/core') diff --git a/BUILD b/BUILD index 81390dd1aa..ee4b5dfaec 100644 --- a/BUILD +++ b/BUILD @@ -1433,10 +1433,7 @@ grpc_cc_library( "src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc", - "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc", - "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc", - "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc", ], hdrs = [ diff --git a/CMakeLists.txt b/CMakeLists.txt index e8e65d4b71..84e9c08cb5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,7 +298,6 @@ add_dependencies(buildtests_c grpc_completion_queue_test) add_dependencies(buildtests_c grpc_completion_queue_threading_test) add_dependencies(buildtests_c grpc_credentials_test) add_dependencies(buildtests_c grpc_fetch_oauth2) -add_dependencies(buildtests_c grpc_ipv6_loopback_available_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c grpc_json_token_test) endif() @@ -672,8 +671,12 @@ endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx resolver_component_tests_runner_invoker) endif() +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx address_sorting_test_unsecure) +endif() +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx address_sorting_test) +endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx cancel_ares_query_test) endif() @@ -1233,11 +1236,8 @@ add_library(grpc src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc src/cpp/ext/filters/census/grpc_context.cc @@ -2538,11 +2538,8 @@ add_library(grpc_unsecure src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc @@ -7326,35 +7323,6 @@ target_link_libraries(grpc_fetch_oauth2 gpr ) -endif (gRPC_BUILD_TESTS) -if (gRPC_BUILD_TESTS) - -add_executable(grpc_ipv6_loopback_available_test - test/core/iomgr/grpc_ipv6_loopback_available_test.cc -) - - -target_include_directories(grpc_ipv6_loopback_available_test - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include - PRIVATE ${_gRPC_SSL_INCLUDE_DIR} - PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} - PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} - PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} - PRIVATE ${_gRPC_CARES_INCLUDE_DIR} - PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} - PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} -) - -target_link_libraries(grpc_ipv6_loopback_available_test - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util - grpc - gpr_test_util - gpr -) - endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -16383,6 +16351,7 @@ target_link_libraries(resolver_component_tests_runner_invoker endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(address_sorting_test_unsecure test/cpp/naming/address_sorting_test.cc @@ -16422,8 +16391,10 @@ target_link_libraries(address_sorting_test_unsecure ${_gRPC_GFLAGS_LIBRARIES} ) +endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(address_sorting_test test/cpp/naming/address_sorting_test.cc @@ -16463,6 +16434,7 @@ target_link_libraries(address_sorting_test ${_gRPC_GFLAGS_LIBRARIES} ) +endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) diff --git a/Makefile b/Makefile index 5174ab6719..bad41975a0 100644 --- a/Makefile +++ b/Makefile @@ -1022,7 +1022,6 @@ grpc_completion_queue_threading_test: $(BINDIR)/$(CONFIG)/grpc_completion_queue_ grpc_create_jwt: $(BINDIR)/$(CONFIG)/grpc_create_jwt grpc_credentials_test: $(BINDIR)/$(CONFIG)/grpc_credentials_test grpc_fetch_oauth2: $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 -grpc_ipv6_loopback_available_test: $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test grpc_json_token_test: $(BINDIR)/$(CONFIG)/grpc_json_token_test grpc_jwt_verifier_test: $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test grpc_print_google_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token @@ -1473,7 +1472,6 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test \ $(BINDIR)/$(CONFIG)/grpc_credentials_test \ $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 \ - $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test \ $(BINDIR)/$(CONFIG)/grpc_json_token_test \ $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test \ $(BINDIR)/$(CONFIG)/grpc_security_connector_test \ @@ -2030,8 +2028,6 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test || ( echo test grpc_completion_queue_threading_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_credentials_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_credentials_test || ( echo test grpc_credentials_test failed ; exit 1 ) - $(E) "[RUN] Testing grpc_ipv6_loopback_available_test" - $(Q) $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test || ( echo test grpc_ipv6_loopback_available_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_json_token_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_json_token_test || ( echo test grpc_json_token_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_jwt_verifier_test" @@ -3708,11 +3704,8 @@ LIBGRPC_SRC = \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \ src/cpp/ext/filters/census/grpc_context.cc \ @@ -4979,11 +4972,8 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ @@ -12375,38 +12365,6 @@ endif endif -GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_SRC = \ - test/core/iomgr/grpc_ipv6_loopback_available_test.cc \ - -GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL. - -$(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test: openssl_dep_error - -else - - - -$(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test: $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/iomgr/grpc_ipv6_loopback_available_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - -deps_grpc_ipv6_loopback_available_test: $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS:.o=.dep) -endif -endif - - GRPC_JSON_TOKEN_TEST_SRC = \ test/core/security/json_token_test.cc \ diff --git a/build.yaml b/build.yaml index 70af96046c..30389ec114 100644 --- a/build.yaml +++ b/build.yaml @@ -740,11 +740,8 @@ filegroups: - src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc - - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc - - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc - - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc plugin: grpc_resolver_dns_ares uses: - grpc_base @@ -2733,18 +2730,6 @@ targets: - grpc - gpr_test_util - gpr -- name: grpc_ipv6_loopback_available_test - build: test - language: c - src: - - test/core/iomgr/grpc_ipv6_loopback_available_test.cc - deps: - - grpc_test_util - - grpc - - gpr_test_util - - gpr - exclude_iomgrs: - - uv - name: grpc_json_token_test build: test language: c diff --git a/config.m4 b/config.m4 index aa40a698a6..c277ccafc8 100644 --- a/config.m4 +++ b/config.m4 @@ -380,11 +380,8 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \ src/cpp/ext/filters/census/grpc_context.cc \ diff --git a/config.w32 b/config.w32 index 5afa4466ac..2857781dd5 100644 --- a/config.w32 +++ b/config.w32 @@ -355,11 +355,8 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\dns_resolver_ares.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_posix.cc " + - "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_windows.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_fallback.cc " + - "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_posix.cc " + - "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_windows.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\native\\dns_resolver.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\sockaddr\\sockaddr_resolver.cc " + "src\\cpp\\ext\\filters\\census\\grpc_context.cc " + diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 5c3649afbd..23edaec656 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -802,11 +802,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/cpp/ext/filters/census/grpc_context.cc', diff --git a/grpc.gemspec b/grpc.gemspec index c250316b99..b69d5a7c6f 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -742,11 +742,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc ) - s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc ) - s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc ) - s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc ) s.files += %w( src/cpp/ext/filters/census/grpc_context.cc ) diff --git a/grpc.gyp b/grpc.gyp index 25082fe540..e1485efa05 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -572,11 +572,8 @@ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/cpp/ext/filters/census/grpc_context.cc', @@ -1290,11 +1287,8 @@ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc', diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index 2b61a8816d..01ce5f03e9 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -420,8 +420,12 @@ typedef unsigned __int64 uint64_t; #define GPR_MAX_ALIGNMENT 16 #ifndef GRPC_ARES +#ifdef GPR_WINDOWS +#define GRPC_ARES 0 +#else #define GRPC_ARES 1 #endif +#endif #ifndef GRPC_MUST_USE_RESULT #if defined(__GNUC__) && !defined(__MINGW32__) diff --git a/package.xml b/package.xml index acdc6ffdb3..7f71536b1d 100644 --- a/package.xml +++ b/package.xml @@ -747,11 +747,8 @@ - - - diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index 7050e82121..f4f6444c5f 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -141,8 +142,8 @@ AresDnsResolver::AresDnsResolver(const ResolverArgs& args) channel_args_ = grpc_channel_args_copy(args.args); const grpc_arg* arg = grpc_channel_args_find( channel_args_, GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION); - grpc_integer_options integer_options = {false, false, true}; - request_service_config_ = !grpc_channel_arg_get_integer(arg, integer_options); + request_service_config_ = !grpc_channel_arg_get_integer( + arg, (grpc_integer_options){false, false, true}); arg = grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS); min_time_between_resolutions_ = diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc index 0068d0d5f4..c886795608 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc @@ -18,10 +18,11 @@ #include #include "src/core/lib/iomgr/port.h" -#if GRPC_ARES == 1 && !defined(GRPC_UV) +#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) #include #include +#include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" @@ -31,6 +32,7 @@ #include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -312,4 +314,4 @@ void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver) { } } -#endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */ +#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc deleted file mode 100644 index 5d65ae3ab3..0000000000 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include - -#include "src/core/lib/iomgr/port.h" -#if GRPC_ARES == 1 && defined(GPR_WINDOWS) - -#include -#include -#include "src/core/lib/gprpp/memory.h" - -#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" - -namespace grpc_core { - -/* TODO: fill in the body of GrpcPolledFdWindows to enable c-ares on Windows. - This dummy implementation only allows grpc to compile on windows with - GRPC_ARES=1. */ -class GrpcPolledFdWindows : public GrpcPolledFd { - public: - GrpcPolledFdWindows() { abort(); } - ~GrpcPolledFdWindows() { abort(); } - void RegisterForOnReadableLocked(grpc_closure* read_closure) override { - abort(); - } - void RegisterForOnWriteableLocked(grpc_closure* write_closure) override { - abort(); - } - bool IsFdStillReadableLocked() override { abort(); } - void ShutdownLocked(grpc_error* error) override { abort(); } - ares_socket_t GetWrappedAresSocketLocked() override { abort(); } - const char* GetName() override { abort(); } -}; - -GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as, - grpc_pollset_set* driver_pollset_set) { - return nullptr; -} - -void ConfigureAresChannelLocked(ares_channel* channel) { abort(); } - -} // namespace grpc_core - -#endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc index b3d6437e9a..497ad998af 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc @@ -22,6 +22,7 @@ #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" #include #include @@ -214,7 +215,7 @@ static void on_hostbyname_done_locked(void* arg, int status, int timeouts, memset(&addr, 0, addr_len); memcpy(&addr.sin6_addr, hostent->h_addr_list[i - prev_naddr], sizeof(struct in6_addr)); - addr.sin6_family = static_cast(hostent->h_addrtype); + addr.sin6_family = static_cast(hostent->h_addrtype); addr.sin6_port = hr->port; grpc_lb_addresses_set_address( *lb_addresses, i, &addr, addr_len, @@ -235,7 +236,7 @@ static void on_hostbyname_done_locked(void* arg, int status, int timeouts, memset(&addr, 0, addr_len); memcpy(&addr.sin_addr, hostent->h_addr_list[i - prev_naddr], sizeof(struct in_addr)); - addr.sin_family = static_cast(hostent->h_addrtype); + addr.sin_family = static_cast(hostent->h_addrtype); addr.sin_port = hr->port; grpc_lb_addresses_set_address( *lb_addresses, i, &addr, addr_len, @@ -280,7 +281,7 @@ static void on_srv_query_done_locked(void* arg, int status, int timeouts, grpc_ares_ev_driver_get_channel_locked(r->ev_driver); for (struct ares_srv_reply* srv_it = reply; srv_it != nullptr; srv_it = srv_it->next) { - if (grpc_ares_query_ipv6()) { + if (grpc_ipv6_loopback_available()) { grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked( r, srv_it->host, htons(srv_it->port), true /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET6, @@ -451,7 +452,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( } } r->pending_queries = 1; - if (grpc_ares_query_ipv6()) { + if (grpc_ipv6_loopback_available()) { hr = create_hostbyname_request_locked(r, host, strhtons(port), false /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked, diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h index 17eaa7ccf0..ce26f5d524 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h @@ -70,10 +70,6 @@ void grpc_ares_cleanup(void); * and destroys the grpc_ares_request */ void grpc_ares_complete_request_locked(grpc_ares_request* request); -/* Indicates whether or not AAAA queries should be attempted. */ -/* E.g., return false if ipv6 is known to not be available. */ -bool grpc_ares_query_ipv6(); - /* Exposed only for testing */ void grpc_cares_wrapper_test_only_address_sorting_sort( grpc_lb_addresses* lb_addrs); diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc deleted file mode 100644 index 23c0fec74f..0000000000 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/iomgr/port.h" -#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) - -#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" -#include "src/core/lib/iomgr/socket_utils_posix.h" - -bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } - -#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc deleted file mode 100644 index ee827e284e..0000000000 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/iomgr/port.h" -#if GRPC_ARES == 1 && defined(GPR_WINDOWS) - -#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" -#include "src/core/lib/iomgr/socket_windows.h" - -bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } - -#endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */ diff --git a/src/core/lib/iomgr/socket_windows.cc b/src/core/lib/iomgr/socket_windows.cc index 4ad31cb35d..2e23409582 100644 --- a/src/core/lib/iomgr/socket_windows.cc +++ b/src/core/lib/iomgr/socket_windows.cc @@ -36,7 +36,6 @@ #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_windows.h" -#include "src/core/lib/iomgr/sockaddr_windows.h" #include "src/core/lib/iomgr/socket_windows.h" grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name) { @@ -149,32 +148,4 @@ void grpc_socket_become_ready(grpc_winsocket* socket, if (should_destroy) destroy(socket); } -static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT; -static bool g_ipv6_loopback_available = false; - -static void probe_ipv6_once(void) { - SOCKET s = socket(AF_INET6, SOCK_STREAM, 0); - g_ipv6_loopback_available = 0; - if (s == INVALID_SOCKET) { - gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed."); - } else { - grpc_sockaddr_in6 addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */ - if (bind(s, reinterpret_cast(&addr), sizeof(addr)) == 0) { - g_ipv6_loopback_available = 1; - } else { - gpr_log(GPR_INFO, - "Disabling AF_INET6 sockets because ::1 is not available."); - } - closesocket(s); - } -} - -int grpc_ipv6_loopback_available(void) { - gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once); - return g_ipv6_loopback_available; -} - #endif /* GRPC_WINSOCK_SOCKET */ diff --git a/src/core/lib/iomgr/socket_windows.h b/src/core/lib/iomgr/socket_windows.h index b09b9da562..7bd01eded5 100644 --- a/src/core/lib/iomgr/socket_windows.h +++ b/src/core/lib/iomgr/socket_windows.h @@ -108,10 +108,6 @@ void grpc_socket_notify_on_read(grpc_winsocket* winsocket, void grpc_socket_become_ready(grpc_winsocket* winsocket, grpc_winsocket_callback_info* ci); -/* Returns true if this system can create AF_INET6 sockets bound to ::1. - The value is probed once, and cached for the life of the process. */ -int grpc_ipv6_loopback_available(void); - #endif #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H */ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index d6efb49750..49185cc648 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -354,11 +354,8 @@ CORE_SOURCE_FILES = [ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', - 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/cpp/ext/filters/census/grpc_context.cc', diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index 002671a5fa..fb0490a95f 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -124,19 +124,6 @@ grpc_cc_test( ], ) -grpc_cc_test( - name = "grpc_ipv6_loopback_available_test", - srcs = ["grpc_ipv6_loopback_available_test.cc"], - language = "C++", - deps = [ - "//:gpr", - "//:grpc", - "//test/core/util:gpr_test_util", - "//test/core/util:grpc_test_util", - ], -) - - grpc_cc_test( name = "load_file_test", srcs = ["load_file_test.cc"], diff --git a/test/core/iomgr/grpc_ipv6_loopback_available_test.cc b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc deleted file mode 100644 index 329aa9a851..0000000000 --- a/test/core/iomgr/grpc_ipv6_loopback_available_test.cc +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/port.h" - -// grpc_ipv6_loopback_available isn't currently available on UV. -#ifndef GRPC_UV - -#include -#include -#include "test/core/util/test_config.h" - -#ifdef GPR_WINDOWS -#include "src/core/lib/iomgr/socket_windows.h" -#else -#include "src/core/lib/iomgr/socket_utils_posix.h" -#endif - -int main(int argc, char** argv) { - grpc_test_init(argc, argv); - grpc_init(); - // This test assumes that the ipv6 loopback is available - // in all environments in which grpc tests run in. - GPR_ASSERT(grpc_ipv6_loopback_available()); - grpc_shutdown(); - return 0; -} - -#else - -int main(int argc, char** argv) { return 0; } - -#endif /* GRPC_UV */ diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc index 04c300876c..a92e9e3b3e 100644 --- a/test/cpp/naming/address_sorting_test.cc +++ b/test/cpp/naming/address_sorting_test.cc @@ -24,8 +24,10 @@ #include #include +#include #include #include +#include #include #include @@ -49,11 +51,6 @@ #include "test/core/util/port.h" #include "test/core/util/test_config.h" -#ifndef GPR_WINDOWS -#include -#include -#endif - namespace { struct TestAddress { @@ -193,18 +190,10 @@ void VerifyLbAddrOutputs(grpc_lb_addresses* lb_addrs, grpc_lb_addresses_destroy(lb_addrs); } -/* We need to run each test case inside of its own - * isolated grpc_init/grpc_shutdown pair, so that - * the "address sorting source addr factory" can be - * restored to its default for each test case. */ -class AddressSortingTest : public ::testing::Test { - protected: - void SetUp() override { grpc_init(); } - void TearDown() override { grpc_shutdown(); } -}; +} // namespace /* Tests for rule 1 */ -TEST_F(AddressSortingTest, TestDepriotizesUnreachableAddresses) { +TEST(AddressSortingTest, TestDepriotizesUnreachableAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -223,7 +212,7 @@ TEST_F(AddressSortingTest, TestDepriotizesUnreachableAddresses) { }); } -TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { +TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { bool ipv4_supported = true; bool ipv6_supported = false; OverrideAddressSortingSourceAddrFactory( @@ -242,7 +231,7 @@ TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { }); } -TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { +TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { bool ipv4_supported = false; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -264,7 +253,7 @@ TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { /* Tests for rule 2 */ -TEST_F(AddressSortingTest, TestDepriotizesNonMatchingScope) { +TEST(AddressSortingTest, TestDepriotizesNonMatchingScope) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -288,7 +277,7 @@ TEST_F(AddressSortingTest, TestDepriotizesNonMatchingScope) { /* Tests for rule 5 */ -TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTable) { +TEST(AddressSortingTest, TestUsesLabelFromDefaultTable) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -311,7 +300,7 @@ TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTable) { /* Flip the input on the test above to reorder the sort function's * comparator's inputs. */ -TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { +TEST(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -334,8 +323,8 @@ TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { /* Tests for rule 6 */ -TEST_F(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address) { +TEST(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -359,8 +348,8 @@ TEST_F(AddressSortingTest, }); } -TEST_F(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress) { +TEST(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress) { bool ipv4_supported = true; bool ipv6_supported = true; // Handle unique observed behavior of inet_ntop(v4-compatible-address) on OS X. @@ -388,8 +377,8 @@ TEST_F(AddressSortingTest, }); } -TEST_F(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress) { +TEST(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -414,8 +403,8 @@ TEST_F(AddressSortingTest, }); } -TEST_F(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress) { +TEST(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -437,7 +426,7 @@ TEST_F(AddressSortingTest, }); } -TEST_F( +TEST( AddressSortingTest, TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddressEnsurePrefixMatchHasNoEffect) { bool ipv4_supported = true; @@ -459,8 +448,8 @@ TEST_F( }); } -TEST_F(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses) { +TEST(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -480,22 +469,19 @@ TEST_F(AddressSortingTest, }); } -TEST_F( +TEST( AddressSortingTest, TestUsesDestinationWithHigherPrecedenceWithCatchAllAndAndV4MappedAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; - // Use embedded ipv4 addresses with leading 1's instead of zero's to be - // compatible with inet_ntop implementations that can display such - // addresses with leading zero's as e.g.: "::ffff:0:2", as on windows. OverrideAddressSortingSourceAddrFactory( ipv4_supported, ipv6_supported, { - {"[::ffff:1.1.1.2]:443", {"[::ffff:1.1.1.3]:0", AF_INET6}}, + {"[::ffff:0.0.0.2]:443", {"[::ffff:0.0.0.3]:0", AF_INET6}}, {"[1234::2]:443", {"[1234::3]:0", AF_INET6}}, }); grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({ - {"[::ffff:1.1.1.2]:443", AF_INET6}, + {"[::ffff:0.0.0.2]:443", AF_INET6}, {"[1234::2]:443", AF_INET6}, }); grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); @@ -503,13 +489,13 @@ TEST_F( // ::ffff:0:2 should match the v4-mapped // precedence entry and be deprioritized. "[1234::2]:443", - "[::ffff:1.1.1.2]:443", + "[::ffff:0.0.0.2]:443", }); } /* Tests for rule 8 */ -TEST_F(AddressSortingTest, TestPrefersSmallerScope) { +TEST(AddressSortingTest, TestPrefersSmallerScope) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -534,7 +520,7 @@ TEST_F(AddressSortingTest, TestPrefersSmallerScope) { /* Tests for rule 9 */ -TEST_F(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { +TEST(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -557,8 +543,8 @@ TEST_F(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { }); } -TEST_F(AddressSortingTest, - TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress) { +TEST(AddressSortingTest, + TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -578,7 +564,7 @@ TEST_F(AddressSortingTest, }); } -TEST_F(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { +TEST(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -598,7 +584,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { }); } -TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { +TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -618,7 +604,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { }); } -TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { +TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -642,7 +628,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { /* Tests for rule 10 */ -TEST_F(AddressSortingTest, TestStableSort) { +TEST(AddressSortingTest, TestStableSort) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -662,7 +648,7 @@ TEST_F(AddressSortingTest, TestStableSort) { }); } -TEST_F(AddressSortingTest, TestStableSortFiveElements) { +TEST(AddressSortingTest, TestStableSortFiveElements) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -691,7 +677,7 @@ TEST_F(AddressSortingTest, TestStableSortFiveElements) { }); } -TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExist) { +TEST(AddressSortingTest, TestStableSortNoSrcAddrsExist) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {}); @@ -712,7 +698,7 @@ TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExist) { }); } -TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { +TEST(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {}); @@ -727,7 +713,7 @@ TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { }); } -TEST_F(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { +TEST(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; // Handle unique observed behavior of inet_ntop(v4-compatible-address) on OS X. @@ -758,78 +744,6 @@ TEST_F(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { }); } -/* TestPrefersIpv6Loopback tests the actual "address probing" code - * for the current platform, without any mocks. - * This test relies on the assumption that the ipv6 loopback address is - * available in the hosts/containers that grpc C/C++ tests run on - * (whether ipv4 loopback is available or not, an available ipv6 - * loopback should be preferred). */ -TEST_F(AddressSortingTest, TestPrefersIpv6Loopback) { - grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({ - {"[::1]:443", AF_INET6}, - {"127.0.0.1:443", AF_INET}, - }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); - VerifyLbAddrOutputs(lb_addrs, { - "[::1]:443", - "127.0.0.1:443", - }); -} - -/* Flip the order of the inputs above and expect the same output order - * (try to rule out influence of arbitrary qsort ordering) */ -TEST_F(AddressSortingTest, TestPrefersIpv6LoopbackInputsFlipped) { - grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({ - {"127.0.0.1:443", AF_INET}, - {"[::1]:443", AF_INET6}, - }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); - VerifyLbAddrOutputs(lb_addrs, { - "[::1]:443", - "127.0.0.1:443", - }); -} - -/* Try to rule out false positives in the above two tests in which - * the sorter might think that neither ipv6 or ipv4 loopback is - * available, but ipv6 loopback is still preferred only due - * to precedance table lookups. */ -TEST_F(AddressSortingTest, TestSorterKnowsIpv6LoopbackIsAvailable) { - sockaddr_in6 ipv6_loopback; - memset(&ipv6_loopback, 0, sizeof(ipv6_loopback)); - ipv6_loopback.sin6_family = AF_INET6; - ((char*)&ipv6_loopback.sin6_addr)[15] = 1; - ipv6_loopback.sin6_port = htons(443); - // Set up the source and destination parameters of - // address_sorting_get_source_addr - address_sorting_address sort_input_dest; - memcpy(&sort_input_dest.addr, &ipv6_loopback, sizeof(ipv6_loopback)); - sort_input_dest.len = sizeof(ipv6_loopback); - address_sorting_address source_for_sort_input_dest; - memset(&source_for_sort_input_dest, 0, sizeof(source_for_sort_input_dest)); - // address_sorting_get_source_addr returns true if a source address was found - // for the destination address, otherwise false. - EXPECT_TRUE(address_sorting_get_source_addr_for_testing( - &sort_input_dest, &source_for_sort_input_dest)); - // Now also check that the source address was filled in correctly. - EXPECT_GT(source_for_sort_input_dest.len, 0u); - sockaddr_in6* source_addr_output = - (sockaddr_in6*)source_for_sort_input_dest.addr; - EXPECT_EQ(source_addr_output->sin6_family, AF_INET6); - char* buf = static_cast(gpr_zalloc(100)); - EXPECT_NE(inet_ntop(AF_INET6, &source_addr_output->sin6_addr, buf, 100), - nullptr) - << "inet_ntop failed. Errno: " + std::to_string(errno); - std::string source_addr_str(buf); - gpr_free(buf); - // This test - // assumes that the source address for any loopback destination is also the - // loopback address. - EXPECT_EQ(source_addr_str, "::1"); -} - -} // namespace - int main(int argc, char** argv) { char* resolver = gpr_getenv("GRPC_DNS_RESOLVER"); if (resolver == nullptr || strlen(resolver) == 0) { @@ -840,7 +754,9 @@ int main(int argc, char** argv) { gpr_free(resolver); grpc_test_init(argc, argv); ::testing::InitGoogleTest(&argc, argv); + grpc_init(); auto result = RUN_ALL_TESTS(); + grpc_shutdown(); // Test sequential and nested inits and shutdowns. grpc_init(); grpc_init(); diff --git a/test/cpp/naming/gen_build_yaml.py b/test/cpp/naming/gen_build_yaml.py index 5dad2ea7af..baa6512f62 100755 --- a/test/cpp/naming/gen_build_yaml.py +++ b/test/cpp/naming/gen_build_yaml.py @@ -110,7 +110,7 @@ def main(): 'gtest': True, 'run': True, 'src': ['test/cpp/naming/address_sorting_test.cc'], - 'platforms': ['linux', 'posix', 'mac', 'windows'], + 'platforms': ['linux', 'posix', 'mac'], 'deps': [ 'grpc++_test_util' + unsecure_build_config_suffix, 'grpc_test_util' + unsecure_build_config_suffix, diff --git a/third_party/address_sorting/address_sorting.c b/third_party/address_sorting/address_sorting.c index 9aee0a5419..e4f3b53799 100644 --- a/third_party/address_sorting/address_sorting.c +++ b/third_party/address_sorting/address_sorting.c @@ -55,17 +55,12 @@ static const int kIPv6AddrScopeGlobal = 3; static address_sorting_source_addr_factory* g_current_source_addr_factory = NULL; -static bool address_sorting_get_source_addr(const address_sorting_address* dest, - address_sorting_address* source) { +static int address_sorting_get_source_addr(const address_sorting_address* dest, + address_sorting_address* source) { return g_current_source_addr_factory->vtable->get_source_addr( g_current_source_addr_factory, dest, source); } -bool address_sorting_get_source_addr_for_testing( - const address_sorting_address* dest, address_sorting_address* source) { - return address_sorting_get_source_addr(dest, source); -} - static int ipv6_prefix_match_length(const struct sockaddr_in6* sa, const struct sockaddr_in6* sb) { unsigned char* a = (unsigned char*)&sa->sin6_addr; diff --git a/third_party/address_sorting/address_sorting_windows.c b/third_party/address_sorting/address_sorting_windows.c index 662a88248e..b2f5708649 100644 --- a/third_party/address_sorting/address_sorting_windows.c +++ b/third_party/address_sorting/address_sorting_windows.c @@ -42,54 +42,14 @@ #if defined(ADDRESS_SORTING_WINDOWS) -#include -#include -#include #include -#include -#include -static bool windows_source_addr_factory_get_source_addr( - address_sorting_source_addr_factory* factory, - const address_sorting_address* dest_addr, - address_sorting_address* source_addr) { - bool source_addr_exists = false; - SOCKET s = socket(((struct sockaddr_in6*)dest_addr)->sin6_family, SOCK_DGRAM, - IPPROTO_UDP); - if (s != INVALID_SOCKET) { - if (connect(s, (struct sockaddr*)dest_addr, (int)dest_addr->len) == 0) { - address_sorting_address found_source_addr; - memset(&found_source_addr, 0, sizeof(found_source_addr)); - found_source_addr.len = sizeof(found_source_addr.addr); - if (getsockname(s, (struct sockaddr*)&found_source_addr.addr, - (socklen_t*)&found_source_addr.len) == 0) { - source_addr_exists = true; - *source_addr = found_source_addr; - } - } - closesocket(s); - } - return source_addr_exists; -} - -static void windows_source_addr_factory_destroy( - address_sorting_source_addr_factory* self) { - free(self); -} - -static const address_sorting_source_addr_factory_vtable - windows_source_addr_factory_vtable = { - windows_source_addr_factory_get_source_addr, - windows_source_addr_factory_destroy, -}; +/* TODO : Add address sorting functionality to work on windows. */ address_sorting_source_addr_factory* address_sorting_create_source_addr_factory_for_current_platform() { - address_sorting_source_addr_factory* factory = - malloc(sizeof(address_sorting_source_addr_factory)); - memset(factory, 0, sizeof(address_sorting_source_addr_factory)); - factory->vtable = &windows_source_addr_factory_vtable; - return factory; + abort(); + return NULL; } #endif // defined(ADDRESS_SORTING_WINDOWS) diff --git a/third_party/address_sorting/include/address_sorting/address_sorting.h b/third_party/address_sorting/include/address_sorting/address_sorting.h index c58fafe3f7..f11cd424b5 100644 --- a/third_party/address_sorting/include/address_sorting/address_sorting.h +++ b/third_party/address_sorting/include/address_sorting/address_sorting.h @@ -103,9 +103,6 @@ address_sorting_family address_sorting_abstract_get_family( void address_sorting_override_source_addr_factory_for_testing( address_sorting_source_addr_factory* factory); -bool address_sorting_get_source_addr_for_testing( - const address_sorting_address* dest, address_sorting_address* source); - #ifdef __cplusplus } #endif diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 18f56984fe..576950934e 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -924,12 +924,9 @@ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ -src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ -src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ -src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/README.md \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index a686dae8b4..072402b2cf 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1032,23 +1032,6 @@ "third_party": false, "type": "target" }, - { - "deps": [ - "gpr", - "gpr_test_util", - "grpc", - "grpc_test_util" - ], - "headers": [], - "is_filegroup": false, - "language": "c", - "name": "grpc_ipv6_loopback_available_test", - "src": [ - "test/core/iomgr/grpc_ipv6_loopback_available_test.cc" - ], - "third_party": false, - "type": "target" - }, { "deps": [ "gpr", @@ -10271,12 +10254,9 @@ "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc", - "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h", - "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc", - "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc", - "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc" + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc" ], "third_party": false, "type": "filegroup" diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 5815f82fef..a5439a5db1 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -1313,32 +1313,6 @@ ], "uses_polling": true }, - { - "args": [], - "benchmark": false, - "ci_platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "gtest": false, - "language": "c", - "name": "grpc_ipv6_loopback_available_test", - "platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "uses_polling": true - }, { "args": [], "benchmark": false, @@ -5736,8 +5710,7 @@ "ci_platforms": [ "linux", "mac", - "posix", - "windows" + "posix" ], "cpu_cost": 1.0, "exclude_configs": [], @@ -5749,8 +5722,7 @@ "platforms": [ "linux", "mac", - "posix", - "windows" + "posix" ], "uses_polling": true }, @@ -5760,8 +5732,7 @@ "ci_platforms": [ "linux", "mac", - "posix", - "windows" + "posix" ], "cpu_cost": 1.0, "exclude_configs": [], @@ -5773,8 +5744,7 @@ "platforms": [ "linux", "mac", - "posix", - "windows" + "posix" ], "uses_polling": true }, -- cgit v1.2.3 From 32b8a11b258e6bf35398c6c60d3c2b4ac2d40cc6 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 26 Jul 2018 14:56:29 -0700 Subject: Fix build. --- test/core/channel/channel_trace_test.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'test/core') diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 99d9a4847f..f224457a55 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -187,8 +187,8 @@ TEST_P(ChannelTracerTest, ComplexTest) { AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); - sc1.reset(nullptr); - sc2.reset(nullptr); + sc1.reset(); + sc2.reset(); } // Test a case in which the parent channel has subchannels and the subchannels @@ -234,9 +234,9 @@ TEST_P(ChannelTracerTest, TestNesting) { grpc_slice_from_static_string("subchannel one inactive"), sc1); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 8, GetParam()); - sc1.reset(nullptr); - sc2.reset(nullptr); - conn1.reset(nullptr); + sc1.reset(); + sc2.reset(); + conn1.reset(); } INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest, -- cgit v1.2.3 From 9896c641860a70e41b006a982e44f40bb3f41053 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Fri, 27 Jul 2018 01:38:26 -0700 Subject: Revert "Merge pull request #16158 from apolcyn/revert_windows_breakage" This reverts commit d9e8f86675cf923714b3ead4b06087e14a88c08c, reversing changes made to 04847aeb1e62bc528d88fa3c47daa24a4cf629b3. --- BUILD | 3 + CMakeLists.txt | 44 ++++-- Makefile | 42 ++++++ build.yaml | 15 ++ config.m4 | 3 + config.w32 | 3 + gRPC-Core.podspec | 3 + grpc.gemspec | 3 + grpc.gyp | 6 + include/grpc/impl/codegen/port_platform.h | 4 - package.xml | 3 + .../resolver/dns/c_ares/dns_resolver_ares.cc | 5 +- .../resolver/dns/c_ares/grpc_ares_ev_driver.cc | 6 +- .../dns/c_ares/grpc_ares_ev_driver_windows.cc | 59 ++++++++ .../resolver/dns/c_ares/grpc_ares_wrapper.cc | 9 +- .../resolver/dns/c_ares/grpc_ares_wrapper.h | 4 + .../resolver/dns/c_ares/grpc_ares_wrapper_posix.cc | 29 ++++ .../dns/c_ares/grpc_ares_wrapper_windows.cc | 29 ++++ src/core/lib/iomgr/socket_windows.cc | 29 ++++ src/core/lib/iomgr/socket_windows.h | 4 + src/python/grpcio/grpc_core_dependencies.py | 3 + test/core/iomgr/BUILD | 13 ++ .../iomgr/grpc_ipv6_loopback_available_test.cc | 48 +++++++ test/cpp/naming/address_sorting_test.cc | 160 ++++++++++++++++----- test/cpp/naming/gen_build_yaml.py | 2 +- third_party/address_sorting/address_sorting.c | 9 +- .../address_sorting/address_sorting_windows.c | 46 +++++- .../include/address_sorting/address_sorting.h | 3 + tools/doxygen/Doxyfile.core.internal | 3 + tools/run_tests/generated/sources_and_headers.json | 22 ++- tools/run_tests/generated/tests.json | 38 ++++- 31 files changed, 577 insertions(+), 73 deletions(-) create mode 100644 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc create mode 100644 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc create mode 100644 src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc create mode 100644 test/core/iomgr/grpc_ipv6_loopback_available_test.cc (limited to 'test/core') diff --git a/BUILD b/BUILD index ee4b5dfaec..81390dd1aa 100644 --- a/BUILD +++ b/BUILD @@ -1433,7 +1433,10 @@ grpc_cc_library( "src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc", ], hdrs = [ diff --git a/CMakeLists.txt b/CMakeLists.txt index 84e9c08cb5..e8e65d4b71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,6 +298,7 @@ add_dependencies(buildtests_c grpc_completion_queue_test) add_dependencies(buildtests_c grpc_completion_queue_threading_test) add_dependencies(buildtests_c grpc_credentials_test) add_dependencies(buildtests_c grpc_fetch_oauth2) +add_dependencies(buildtests_c grpc_ipv6_loopback_available_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c grpc_json_token_test) endif() @@ -671,12 +672,8 @@ endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx resolver_component_tests_runner_invoker) endif() -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx address_sorting_test_unsecure) -endif() -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx address_sorting_test) -endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx cancel_ares_query_test) endif() @@ -1236,8 +1233,11 @@ add_library(grpc src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc src/cpp/ext/filters/census/grpc_context.cc @@ -2538,8 +2538,11 @@ add_library(grpc_unsecure src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc @@ -7323,6 +7326,35 @@ target_link_libraries(grpc_fetch_oauth2 gpr ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + +add_executable(grpc_ipv6_loopback_available_test + test/core/iomgr/grpc_ipv6_loopback_available_test.cc +) + + +target_include_directories(grpc_ipv6_loopback_available_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} +) + +target_link_libraries(grpc_ipv6_loopback_available_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr +) + endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -16351,7 +16383,6 @@ target_link_libraries(resolver_component_tests_runner_invoker endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(address_sorting_test_unsecure test/cpp/naming/address_sorting_test.cc @@ -16391,10 +16422,8 @@ target_link_libraries(address_sorting_test_unsecure ${_gRPC_GFLAGS_LIBRARIES} ) -endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(address_sorting_test test/cpp/naming/address_sorting_test.cc @@ -16434,7 +16463,6 @@ target_link_libraries(address_sorting_test ${_gRPC_GFLAGS_LIBRARIES} ) -endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) diff --git a/Makefile b/Makefile index bad41975a0..5174ab6719 100644 --- a/Makefile +++ b/Makefile @@ -1022,6 +1022,7 @@ grpc_completion_queue_threading_test: $(BINDIR)/$(CONFIG)/grpc_completion_queue_ grpc_create_jwt: $(BINDIR)/$(CONFIG)/grpc_create_jwt grpc_credentials_test: $(BINDIR)/$(CONFIG)/grpc_credentials_test grpc_fetch_oauth2: $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 +grpc_ipv6_loopback_available_test: $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test grpc_json_token_test: $(BINDIR)/$(CONFIG)/grpc_json_token_test grpc_jwt_verifier_test: $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test grpc_print_google_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token @@ -1472,6 +1473,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test \ $(BINDIR)/$(CONFIG)/grpc_credentials_test \ $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 \ + $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test \ $(BINDIR)/$(CONFIG)/grpc_json_token_test \ $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test \ $(BINDIR)/$(CONFIG)/grpc_security_connector_test \ @@ -2028,6 +2030,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test || ( echo test grpc_completion_queue_threading_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_credentials_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_credentials_test || ( echo test grpc_credentials_test failed ; exit 1 ) + $(E) "[RUN] Testing grpc_ipv6_loopback_available_test" + $(Q) $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test || ( echo test grpc_ipv6_loopback_available_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_json_token_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_json_token_test || ( echo test grpc_json_token_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_jwt_verifier_test" @@ -3704,8 +3708,11 @@ LIBGRPC_SRC = \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \ src/cpp/ext/filters/census/grpc_context.cc \ @@ -4972,8 +4979,11 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ @@ -12365,6 +12375,38 @@ endif endif +GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_SRC = \ + test/core/iomgr/grpc_ipv6_loopback_available_test.cc \ + +GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test: $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_ipv6_loopback_available_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/grpc_ipv6_loopback_available_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_grpc_ipv6_loopback_available_test: $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(GRPC_IPV6_LOOPBACK_AVAILABLE_TEST_OBJS:.o=.dep) +endif +endif + + GRPC_JSON_TOKEN_TEST_SRC = \ test/core/security/json_token_test.cc \ diff --git a/build.yaml b/build.yaml index 30389ec114..70af96046c 100644 --- a/build.yaml +++ b/build.yaml @@ -740,8 +740,11 @@ filegroups: - src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc + - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc + - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc + - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc plugin: grpc_resolver_dns_ares uses: - grpc_base @@ -2730,6 +2733,18 @@ targets: - grpc - gpr_test_util - gpr +- name: grpc_ipv6_loopback_available_test + build: test + language: c + src: + - test/core/iomgr/grpc_ipv6_loopback_available_test.cc + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + exclude_iomgrs: + - uv - name: grpc_json_token_test build: test language: c diff --git a/config.m4 b/config.m4 index c277ccafc8..aa40a698a6 100644 --- a/config.m4 +++ b/config.m4 @@ -380,8 +380,11 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ + src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \ src/cpp/ext/filters/census/grpc_context.cc \ diff --git a/config.w32 b/config.w32 index 2857781dd5..5afa4466ac 100644 --- a/config.w32 +++ b/config.w32 @@ -355,8 +355,11 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\dns_resolver_ares.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_posix.cc " + + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_windows.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_fallback.cc " + + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_posix.cc " + + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_windows.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\native\\dns_resolver.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\sockaddr\\sockaddr_resolver.cc " + "src\\cpp\\ext\\filters\\census\\grpc_context.cc " + diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 23edaec656..5c3649afbd 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -802,8 +802,11 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/cpp/ext/filters/census/grpc_context.cc', diff --git a/grpc.gemspec b/grpc.gemspec index b69d5a7c6f..c250316b99 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -742,8 +742,11 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc ) + s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc ) s.files += %w( src/cpp/ext/filters/census/grpc_context.cc ) diff --git a/grpc.gyp b/grpc.gyp index e1485efa05..25082fe540 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -572,8 +572,11 @@ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/cpp/ext/filters/census/grpc_context.cc', @@ -1287,8 +1290,11 @@ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc', diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index 01ce5f03e9..2b61a8816d 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -420,12 +420,8 @@ typedef unsigned __int64 uint64_t; #define GPR_MAX_ALIGNMENT 16 #ifndef GRPC_ARES -#ifdef GPR_WINDOWS -#define GRPC_ARES 0 -#else #define GRPC_ARES 1 #endif -#endif #ifndef GRPC_MUST_USE_RESULT #if defined(__GNUC__) && !defined(__MINGW32__) diff --git a/package.xml b/package.xml index 7f71536b1d..acdc6ffdb3 100644 --- a/package.xml +++ b/package.xml @@ -747,8 +747,11 @@ + + + diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index f4f6444c5f..7050e82121 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -142,8 +141,8 @@ AresDnsResolver::AresDnsResolver(const ResolverArgs& args) channel_args_ = grpc_channel_args_copy(args.args); const grpc_arg* arg = grpc_channel_args_find( channel_args_, GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION); - request_service_config_ = !grpc_channel_arg_get_integer( - arg, (grpc_integer_options){false, false, true}); + grpc_integer_options integer_options = {false, false, true}; + request_service_config_ = !grpc_channel_arg_get_integer(arg, integer_options); arg = grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS); min_time_between_resolutions_ = diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc index c886795608..0068d0d5f4 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc @@ -18,11 +18,10 @@ #include #include "src/core/lib/iomgr/port.h" -#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) +#if GRPC_ARES == 1 && !defined(GRPC_UV) #include #include -#include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" @@ -32,7 +31,6 @@ #include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -314,4 +312,4 @@ void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver) { } } -#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ +#endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc new file mode 100644 index 0000000000..5d65ae3ab3 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc @@ -0,0 +1,59 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include + +#include "src/core/lib/iomgr/port.h" +#if GRPC_ARES == 1 && defined(GPR_WINDOWS) + +#include +#include +#include "src/core/lib/gprpp/memory.h" + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" + +namespace grpc_core { + +/* TODO: fill in the body of GrpcPolledFdWindows to enable c-ares on Windows. + This dummy implementation only allows grpc to compile on windows with + GRPC_ARES=1. */ +class GrpcPolledFdWindows : public GrpcPolledFd { + public: + GrpcPolledFdWindows() { abort(); } + ~GrpcPolledFdWindows() { abort(); } + void RegisterForOnReadableLocked(grpc_closure* read_closure) override { + abort(); + } + void RegisterForOnWriteableLocked(grpc_closure* write_closure) override { + abort(); + } + bool IsFdStillReadableLocked() override { abort(); } + void ShutdownLocked(grpc_error* error) override { abort(); } + ares_socket_t GetWrappedAresSocketLocked() override { abort(); } + const char* GetName() override { abort(); } +}; + +GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as, + grpc_pollset_set* driver_pollset_set) { + return nullptr; +} + +void ConfigureAresChannelLocked(ares_channel* channel) { abort(); } + +} // namespace grpc_core + +#endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc index 497ad998af..b3d6437e9a 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc @@ -22,7 +22,6 @@ #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/socket_utils_posix.h" #include #include @@ -215,7 +214,7 @@ static void on_hostbyname_done_locked(void* arg, int status, int timeouts, memset(&addr, 0, addr_len); memcpy(&addr.sin6_addr, hostent->h_addr_list[i - prev_naddr], sizeof(struct in6_addr)); - addr.sin6_family = static_cast(hostent->h_addrtype); + addr.sin6_family = static_cast(hostent->h_addrtype); addr.sin6_port = hr->port; grpc_lb_addresses_set_address( *lb_addresses, i, &addr, addr_len, @@ -236,7 +235,7 @@ static void on_hostbyname_done_locked(void* arg, int status, int timeouts, memset(&addr, 0, addr_len); memcpy(&addr.sin_addr, hostent->h_addr_list[i - prev_naddr], sizeof(struct in_addr)); - addr.sin_family = static_cast(hostent->h_addrtype); + addr.sin_family = static_cast(hostent->h_addrtype); addr.sin_port = hr->port; grpc_lb_addresses_set_address( *lb_addresses, i, &addr, addr_len, @@ -281,7 +280,7 @@ static void on_srv_query_done_locked(void* arg, int status, int timeouts, grpc_ares_ev_driver_get_channel_locked(r->ev_driver); for (struct ares_srv_reply* srv_it = reply; srv_it != nullptr; srv_it = srv_it->next) { - if (grpc_ipv6_loopback_available()) { + if (grpc_ares_query_ipv6()) { grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked( r, srv_it->host, htons(srv_it->port), true /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET6, @@ -452,7 +451,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( } } r->pending_queries = 1; - if (grpc_ipv6_loopback_available()) { + if (grpc_ares_query_ipv6()) { hr = create_hostbyname_request_locked(r, host, strhtons(port), false /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked, diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h index ce26f5d524..17eaa7ccf0 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h @@ -70,6 +70,10 @@ void grpc_ares_cleanup(void); * and destroys the grpc_ares_request */ void grpc_ares_complete_request_locked(grpc_ares_request* request); +/* Indicates whether or not AAAA queries should be attempted. */ +/* E.g., return false if ipv6 is known to not be available. */ +bool grpc_ares_query_ipv6(); + /* Exposed only for testing */ void grpc_cares_wrapper_test_only_address_sorting_sort( grpc_lb_addresses* lb_addrs); diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc new file mode 100644 index 0000000000..23c0fec74f --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc @@ -0,0 +1,29 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/port.h" +#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" + +bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } + +#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc new file mode 100644 index 0000000000..ee827e284e --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc @@ -0,0 +1,29 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/port.h" +#if GRPC_ARES == 1 && defined(GPR_WINDOWS) + +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/iomgr/socket_windows.h" + +bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } + +#endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */ diff --git a/src/core/lib/iomgr/socket_windows.cc b/src/core/lib/iomgr/socket_windows.cc index 2e23409582..4ad31cb35d 100644 --- a/src/core/lib/iomgr/socket_windows.cc +++ b/src/core/lib/iomgr/socket_windows.cc @@ -36,6 +36,7 @@ #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_windows.h" +#include "src/core/lib/iomgr/sockaddr_windows.h" #include "src/core/lib/iomgr/socket_windows.h" grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name) { @@ -148,4 +149,32 @@ void grpc_socket_become_ready(grpc_winsocket* socket, if (should_destroy) destroy(socket); } +static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT; +static bool g_ipv6_loopback_available = false; + +static void probe_ipv6_once(void) { + SOCKET s = socket(AF_INET6, SOCK_STREAM, 0); + g_ipv6_loopback_available = 0; + if (s == INVALID_SOCKET) { + gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed."); + } else { + grpc_sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */ + if (bind(s, reinterpret_cast(&addr), sizeof(addr)) == 0) { + g_ipv6_loopback_available = 1; + } else { + gpr_log(GPR_INFO, + "Disabling AF_INET6 sockets because ::1 is not available."); + } + closesocket(s); + } +} + +int grpc_ipv6_loopback_available(void) { + gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once); + return g_ipv6_loopback_available; +} + #endif /* GRPC_WINSOCK_SOCKET */ diff --git a/src/core/lib/iomgr/socket_windows.h b/src/core/lib/iomgr/socket_windows.h index 7bd01eded5..b09b9da562 100644 --- a/src/core/lib/iomgr/socket_windows.h +++ b/src/core/lib/iomgr/socket_windows.h @@ -108,6 +108,10 @@ void grpc_socket_notify_on_read(grpc_winsocket* winsocket, void grpc_socket_become_ready(grpc_winsocket* winsocket, grpc_winsocket_callback_info* ci); +/* Returns true if this system can create AF_INET6 sockets bound to ::1. + The value is probed once, and cached for the life of the process. */ +int grpc_ipv6_loopback_available(void); + #endif #endif /* GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H */ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 49185cc648..d6efb49750 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -354,8 +354,11 @@ CORE_SOURCE_FILES = [ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc', + 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc', 'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc', 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/cpp/ext/filters/census/grpc_context.cc', diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index fb0490a95f..002671a5fa 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -124,6 +124,19 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "grpc_ipv6_loopback_available_test", + srcs = ["grpc_ipv6_loopback_available_test.cc"], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + + grpc_cc_test( name = "load_file_test", srcs = ["load_file_test.cc"], diff --git a/test/core/iomgr/grpc_ipv6_loopback_available_test.cc b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc new file mode 100644 index 0000000000..329aa9a851 --- /dev/null +++ b/test/core/iomgr/grpc_ipv6_loopback_available_test.cc @@ -0,0 +1,48 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +// grpc_ipv6_loopback_available isn't currently available on UV. +#ifndef GRPC_UV + +#include +#include +#include "test/core/util/test_config.h" + +#ifdef GPR_WINDOWS +#include "src/core/lib/iomgr/socket_windows.h" +#else +#include "src/core/lib/iomgr/socket_utils_posix.h" +#endif + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + grpc_init(); + // This test assumes that the ipv6 loopback is available + // in all environments in which grpc tests run in. + GPR_ASSERT(grpc_ipv6_loopback_available()); + grpc_shutdown(); + return 0; +} + +#else + +int main(int argc, char** argv) { return 0; } + +#endif /* GRPC_UV */ diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc index a92e9e3b3e..04c300876c 100644 --- a/test/cpp/naming/address_sorting_test.cc +++ b/test/cpp/naming/address_sorting_test.cc @@ -24,10 +24,8 @@ #include #include -#include #include #include -#include #include #include @@ -51,6 +49,11 @@ #include "test/core/util/port.h" #include "test/core/util/test_config.h" +#ifndef GPR_WINDOWS +#include +#include +#endif + namespace { struct TestAddress { @@ -190,10 +193,18 @@ void VerifyLbAddrOutputs(grpc_lb_addresses* lb_addrs, grpc_lb_addresses_destroy(lb_addrs); } -} // namespace +/* We need to run each test case inside of its own + * isolated grpc_init/grpc_shutdown pair, so that + * the "address sorting source addr factory" can be + * restored to its default for each test case. */ +class AddressSortingTest : public ::testing::Test { + protected: + void SetUp() override { grpc_init(); } + void TearDown() override { grpc_shutdown(); } +}; /* Tests for rule 1 */ -TEST(AddressSortingTest, TestDepriotizesUnreachableAddresses) { +TEST_F(AddressSortingTest, TestDepriotizesUnreachableAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -212,7 +223,7 @@ TEST(AddressSortingTest, TestDepriotizesUnreachableAddresses) { }); } -TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { +TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { bool ipv4_supported = true; bool ipv6_supported = false; OverrideAddressSortingSourceAddrFactory( @@ -231,7 +242,7 @@ TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { }); } -TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { +TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { bool ipv4_supported = false; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -253,7 +264,7 @@ TEST(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { /* Tests for rule 2 */ -TEST(AddressSortingTest, TestDepriotizesNonMatchingScope) { +TEST_F(AddressSortingTest, TestDepriotizesNonMatchingScope) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -277,7 +288,7 @@ TEST(AddressSortingTest, TestDepriotizesNonMatchingScope) { /* Tests for rule 5 */ -TEST(AddressSortingTest, TestUsesLabelFromDefaultTable) { +TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTable) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -300,7 +311,7 @@ TEST(AddressSortingTest, TestUsesLabelFromDefaultTable) { /* Flip the input on the test above to reorder the sort function's * comparator's inputs. */ -TEST(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { +TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -323,8 +334,8 @@ TEST(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { /* Tests for rule 6 */ -TEST(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address) { +TEST_F(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithAnIpv4Address) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -348,8 +359,8 @@ TEST(AddressSortingTest, }); } -TEST(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress) { +TEST_F(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithV4CompatAndLocalhostAddress) { bool ipv4_supported = true; bool ipv6_supported = true; // Handle unique observed behavior of inet_ntop(v4-compatible-address) on OS X. @@ -377,8 +388,8 @@ TEST(AddressSortingTest, }); } -TEST(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress) { +TEST_F(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithCatchAllAndLocalhostAddress) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -403,8 +414,8 @@ TEST(AddressSortingTest, }); } -TEST(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress) { +TEST_F(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddress) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -426,7 +437,7 @@ TEST(AddressSortingTest, }); } -TEST( +TEST_F( AddressSortingTest, TestUsesDestinationWithHigherPrecedenceWith2000PrefixedAddressEnsurePrefixMatchHasNoEffect) { bool ipv4_supported = true; @@ -448,8 +459,8 @@ TEST( }); } -TEST(AddressSortingTest, - TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses) { +TEST_F(AddressSortingTest, + TestUsesDestinationWithHigherPrecedenceWithLinkAndSiteLocalAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -469,19 +480,22 @@ TEST(AddressSortingTest, }); } -TEST( +TEST_F( AddressSortingTest, TestUsesDestinationWithHigherPrecedenceWithCatchAllAndAndV4MappedAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; + // Use embedded ipv4 addresses with leading 1's instead of zero's to be + // compatible with inet_ntop implementations that can display such + // addresses with leading zero's as e.g.: "::ffff:0:2", as on windows. OverrideAddressSortingSourceAddrFactory( ipv4_supported, ipv6_supported, { - {"[::ffff:0.0.0.2]:443", {"[::ffff:0.0.0.3]:0", AF_INET6}}, + {"[::ffff:1.1.1.2]:443", {"[::ffff:1.1.1.3]:0", AF_INET6}}, {"[1234::2]:443", {"[1234::3]:0", AF_INET6}}, }); grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({ - {"[::ffff:0.0.0.2]:443", AF_INET6}, + {"[::ffff:1.1.1.2]:443", AF_INET6}, {"[1234::2]:443", AF_INET6}, }); grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); @@ -489,13 +503,13 @@ TEST( // ::ffff:0:2 should match the v4-mapped // precedence entry and be deprioritized. "[1234::2]:443", - "[::ffff:0.0.0.2]:443", + "[::ffff:1.1.1.2]:443", }); } /* Tests for rule 8 */ -TEST(AddressSortingTest, TestPrefersSmallerScope) { +TEST_F(AddressSortingTest, TestPrefersSmallerScope) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -520,7 +534,7 @@ TEST(AddressSortingTest, TestPrefersSmallerScope) { /* Tests for rule 9 */ -TEST(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { +TEST_F(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -543,8 +557,8 @@ TEST(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { }); } -TEST(AddressSortingTest, - TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress) { +TEST_F(AddressSortingTest, + TestPrefersLongestMatchingSrcDstPrefixMatchesWholeAddress) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -564,7 +578,7 @@ TEST(AddressSortingTest, }); } -TEST(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { +TEST_F(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -584,7 +598,7 @@ TEST(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { }); } -TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { +TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -604,7 +618,7 @@ TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { }); } -TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { +TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -628,7 +642,7 @@ TEST(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { /* Tests for rule 10 */ -TEST(AddressSortingTest, TestStableSort) { +TEST_F(AddressSortingTest, TestStableSort) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -648,7 +662,7 @@ TEST(AddressSortingTest, TestStableSort) { }); } -TEST(AddressSortingTest, TestStableSortFiveElements) { +TEST_F(AddressSortingTest, TestStableSortFiveElements) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory( @@ -677,7 +691,7 @@ TEST(AddressSortingTest, TestStableSortFiveElements) { }); } -TEST(AddressSortingTest, TestStableSortNoSrcAddrsExist) { +TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExist) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {}); @@ -698,7 +712,7 @@ TEST(AddressSortingTest, TestStableSortNoSrcAddrsExist) { }); } -TEST(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { +TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { bool ipv4_supported = true; bool ipv6_supported = true; OverrideAddressSortingSourceAddrFactory(ipv4_supported, ipv6_supported, {}); @@ -713,7 +727,7 @@ TEST(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { }); } -TEST(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { +TEST_F(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { bool ipv4_supported = true; bool ipv6_supported = true; // Handle unique observed behavior of inet_ntop(v4-compatible-address) on OS X. @@ -744,6 +758,78 @@ TEST(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { }); } +/* TestPrefersIpv6Loopback tests the actual "address probing" code + * for the current platform, without any mocks. + * This test relies on the assumption that the ipv6 loopback address is + * available in the hosts/containers that grpc C/C++ tests run on + * (whether ipv4 loopback is available or not, an available ipv6 + * loopback should be preferred). */ +TEST_F(AddressSortingTest, TestPrefersIpv6Loopback) { + grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({ + {"[::1]:443", AF_INET6}, + {"127.0.0.1:443", AF_INET}, + }); + grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + VerifyLbAddrOutputs(lb_addrs, { + "[::1]:443", + "127.0.0.1:443", + }); +} + +/* Flip the order of the inputs above and expect the same output order + * (try to rule out influence of arbitrary qsort ordering) */ +TEST_F(AddressSortingTest, TestPrefersIpv6LoopbackInputsFlipped) { + grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({ + {"127.0.0.1:443", AF_INET}, + {"[::1]:443", AF_INET6}, + }); + grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + VerifyLbAddrOutputs(lb_addrs, { + "[::1]:443", + "127.0.0.1:443", + }); +} + +/* Try to rule out false positives in the above two tests in which + * the sorter might think that neither ipv6 or ipv4 loopback is + * available, but ipv6 loopback is still preferred only due + * to precedance table lookups. */ +TEST_F(AddressSortingTest, TestSorterKnowsIpv6LoopbackIsAvailable) { + sockaddr_in6 ipv6_loopback; + memset(&ipv6_loopback, 0, sizeof(ipv6_loopback)); + ipv6_loopback.sin6_family = AF_INET6; + ((char*)&ipv6_loopback.sin6_addr)[15] = 1; + ipv6_loopback.sin6_port = htons(443); + // Set up the source and destination parameters of + // address_sorting_get_source_addr + address_sorting_address sort_input_dest; + memcpy(&sort_input_dest.addr, &ipv6_loopback, sizeof(ipv6_loopback)); + sort_input_dest.len = sizeof(ipv6_loopback); + address_sorting_address source_for_sort_input_dest; + memset(&source_for_sort_input_dest, 0, sizeof(source_for_sort_input_dest)); + // address_sorting_get_source_addr returns true if a source address was found + // for the destination address, otherwise false. + EXPECT_TRUE(address_sorting_get_source_addr_for_testing( + &sort_input_dest, &source_for_sort_input_dest)); + // Now also check that the source address was filled in correctly. + EXPECT_GT(source_for_sort_input_dest.len, 0u); + sockaddr_in6* source_addr_output = + (sockaddr_in6*)source_for_sort_input_dest.addr; + EXPECT_EQ(source_addr_output->sin6_family, AF_INET6); + char* buf = static_cast(gpr_zalloc(100)); + EXPECT_NE(inet_ntop(AF_INET6, &source_addr_output->sin6_addr, buf, 100), + nullptr) + << "inet_ntop failed. Errno: " + std::to_string(errno); + std::string source_addr_str(buf); + gpr_free(buf); + // This test + // assumes that the source address for any loopback destination is also the + // loopback address. + EXPECT_EQ(source_addr_str, "::1"); +} + +} // namespace + int main(int argc, char** argv) { char* resolver = gpr_getenv("GRPC_DNS_RESOLVER"); if (resolver == nullptr || strlen(resolver) == 0) { @@ -754,9 +840,7 @@ int main(int argc, char** argv) { gpr_free(resolver); grpc_test_init(argc, argv); ::testing::InitGoogleTest(&argc, argv); - grpc_init(); auto result = RUN_ALL_TESTS(); - grpc_shutdown(); // Test sequential and nested inits and shutdowns. grpc_init(); grpc_init(); diff --git a/test/cpp/naming/gen_build_yaml.py b/test/cpp/naming/gen_build_yaml.py index baa6512f62..5dad2ea7af 100755 --- a/test/cpp/naming/gen_build_yaml.py +++ b/test/cpp/naming/gen_build_yaml.py @@ -110,7 +110,7 @@ def main(): 'gtest': True, 'run': True, 'src': ['test/cpp/naming/address_sorting_test.cc'], - 'platforms': ['linux', 'posix', 'mac'], + 'platforms': ['linux', 'posix', 'mac', 'windows'], 'deps': [ 'grpc++_test_util' + unsecure_build_config_suffix, 'grpc_test_util' + unsecure_build_config_suffix, diff --git a/third_party/address_sorting/address_sorting.c b/third_party/address_sorting/address_sorting.c index e4f3b53799..9aee0a5419 100644 --- a/third_party/address_sorting/address_sorting.c +++ b/third_party/address_sorting/address_sorting.c @@ -55,12 +55,17 @@ static const int kIPv6AddrScopeGlobal = 3; static address_sorting_source_addr_factory* g_current_source_addr_factory = NULL; -static int address_sorting_get_source_addr(const address_sorting_address* dest, - address_sorting_address* source) { +static bool address_sorting_get_source_addr(const address_sorting_address* dest, + address_sorting_address* source) { return g_current_source_addr_factory->vtable->get_source_addr( g_current_source_addr_factory, dest, source); } +bool address_sorting_get_source_addr_for_testing( + const address_sorting_address* dest, address_sorting_address* source) { + return address_sorting_get_source_addr(dest, source); +} + static int ipv6_prefix_match_length(const struct sockaddr_in6* sa, const struct sockaddr_in6* sb) { unsigned char* a = (unsigned char*)&sa->sin6_addr; diff --git a/third_party/address_sorting/address_sorting_windows.c b/third_party/address_sorting/address_sorting_windows.c index b2f5708649..662a88248e 100644 --- a/third_party/address_sorting/address_sorting_windows.c +++ b/third_party/address_sorting/address_sorting_windows.c @@ -42,14 +42,54 @@ #if defined(ADDRESS_SORTING_WINDOWS) +#include +#include +#include #include +#include +#include -/* TODO : Add address sorting functionality to work on windows. */ +static bool windows_source_addr_factory_get_source_addr( + address_sorting_source_addr_factory* factory, + const address_sorting_address* dest_addr, + address_sorting_address* source_addr) { + bool source_addr_exists = false; + SOCKET s = socket(((struct sockaddr_in6*)dest_addr)->sin6_family, SOCK_DGRAM, + IPPROTO_UDP); + if (s != INVALID_SOCKET) { + if (connect(s, (struct sockaddr*)dest_addr, (int)dest_addr->len) == 0) { + address_sorting_address found_source_addr; + memset(&found_source_addr, 0, sizeof(found_source_addr)); + found_source_addr.len = sizeof(found_source_addr.addr); + if (getsockname(s, (struct sockaddr*)&found_source_addr.addr, + (socklen_t*)&found_source_addr.len) == 0) { + source_addr_exists = true; + *source_addr = found_source_addr; + } + } + closesocket(s); + } + return source_addr_exists; +} + +static void windows_source_addr_factory_destroy( + address_sorting_source_addr_factory* self) { + free(self); +} + +static const address_sorting_source_addr_factory_vtable + windows_source_addr_factory_vtable = { + windows_source_addr_factory_get_source_addr, + windows_source_addr_factory_destroy, +}; address_sorting_source_addr_factory* address_sorting_create_source_addr_factory_for_current_platform() { - abort(); - return NULL; + address_sorting_source_addr_factory* factory = + malloc(sizeof(address_sorting_source_addr_factory)); + memset(factory, 0, sizeof(address_sorting_source_addr_factory)); + factory->vtable = &windows_source_addr_factory_vtable; + return factory; } #endif // defined(ADDRESS_SORTING_WINDOWS) diff --git a/third_party/address_sorting/include/address_sorting/address_sorting.h b/third_party/address_sorting/include/address_sorting/address_sorting.h index f11cd424b5..c58fafe3f7 100644 --- a/third_party/address_sorting/include/address_sorting/address_sorting.h +++ b/third_party/address_sorting/include/address_sorting/address_sorting.h @@ -103,6 +103,9 @@ address_sorting_family address_sorting_abstract_get_family( void address_sorting_override_source_addr_factory_for_testing( address_sorting_source_addr_factory* factory); +bool address_sorting_get_source_addr_for_testing( + const address_sorting_address* dest, address_sorting_address* source); + #ifdef __cplusplus } #endif diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 576950934e..18f56984fe 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -924,9 +924,12 @@ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ +src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \ +src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc \ +src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc \ src/core/ext/filters/client_channel/resolver/dns/native/README.md \ src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \ src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 072402b2cf..a686dae8b4 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1032,6 +1032,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "grpc_ipv6_loopback_available_test", + "src": [ + "test/core/iomgr/grpc_ipv6_loopback_available_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -10254,9 +10271,12 @@ "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc", "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h", - "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc" + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc", + "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc" ], "third_party": false, "type": "filegroup" diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index a5439a5db1..5815f82fef 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -1313,6 +1313,32 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "gtest": false, + "language": "c", + "name": "grpc_ipv6_loopback_available_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, @@ -5710,7 +5736,8 @@ "ci_platforms": [ "linux", "mac", - "posix" + "posix", + "windows" ], "cpu_cost": 1.0, "exclude_configs": [], @@ -5722,7 +5749,8 @@ "platforms": [ "linux", "mac", - "posix" + "posix", + "windows" ], "uses_polling": true }, @@ -5732,7 +5760,8 @@ "ci_platforms": [ "linux", "mac", - "posix" + "posix", + "windows" ], "cpu_cost": 1.0, "exclude_configs": [], @@ -5744,7 +5773,8 @@ "platforms": [ "linux", "mac", - "posix" + "posix", + "windows" ], "uses_polling": true }, -- cgit v1.2.3 From 326f82e5e25a8144cc0566cf2cf61bcdc0cd25f4 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 27 Jul 2018 08:04:24 -0700 Subject: A bit of cleanup and add more tests. --- src/core/lib/gprpp/ref_counted_ptr.h | 28 +++++++++------- test/core/gprpp/ref_counted_ptr_test.cc | 57 ++++++++++++++++++++++++++------- 2 files changed, 61 insertions(+), 24 deletions(-) (limited to 'test/core') diff --git a/src/core/lib/gprpp/ref_counted_ptr.h b/src/core/lib/gprpp/ref_counted_ptr.h index 91ca8eae63..c2dfbdd90f 100644 --- a/src/core/lib/gprpp/ref_counted_ptr.h +++ b/src/core/lib/gprpp/ref_counted_ptr.h @@ -41,21 +41,23 @@ class RefCountedPtr { value_ = value; } - // Move support. + // Move ctors. RefCountedPtr(RefCountedPtr&& other) { value_ = other.value_; other.value_ = nullptr; } - RefCountedPtr& operator=(RefCountedPtr&& other) { - if (value_ != nullptr) value_->Unref(); + template + RefCountedPtr(RefCountedPtr&& other) { value_ = other.value_; other.value_ = nullptr; - return *this; } - template - RefCountedPtr(RefCountedPtr&& other) { + + // Move assignment. + RefCountedPtr& operator=(RefCountedPtr&& other) { + if (value_ != nullptr) value_->Unref(); value_ = other.value_; other.value_ = nullptr; + return *this; } template RefCountedPtr& operator=(RefCountedPtr&& other) { @@ -65,11 +67,18 @@ class RefCountedPtr { return *this; } - // Copy support. + // Copy ctors. RefCountedPtr(const RefCountedPtr& other) { if (other.value_ != nullptr) other.value_->IncrementRefCount(); value_ = other.value_; } + template + RefCountedPtr(const RefCountedPtr& other) { + if (other.value_ != nullptr) other.value_->IncrementRefCount(); + value_ = other.value_; + } + + // Copy assignment. RefCountedPtr& operator=(const RefCountedPtr& other) { // Note: Order of reffing and unreffing is important here in case value_ // and other.value_ are the same object. @@ -79,11 +88,6 @@ class RefCountedPtr { return *this; } template - RefCountedPtr(const RefCountedPtr& other) { - if (other.value_ != nullptr) other.value_->IncrementRefCount(); - value_ = other.value_; - } - template RefCountedPtr& operator=(const RefCountedPtr& other) { // Note: Order of reffing and unreffing is important here in case value_ // and other.value_ are the same object. diff --git a/test/core/gprpp/ref_counted_ptr_test.cc b/test/core/gprpp/ref_counted_ptr_test.cc index 6df6e348c6..1e030c5ba3 100644 --- a/test/core/gprpp/ref_counted_ptr_test.cc +++ b/test/core/gprpp/ref_counted_ptr_test.cc @@ -175,28 +175,61 @@ TEST(RefCountedPtr, RefCountedWithTracing) { foo->Unref(DEBUG_LOCATION, "foo"); } -class Parent : public RefCounted { +class BaseClass : public RefCounted { public: - Parent() {} + BaseClass() {} }; -class Child : public Parent { +class Subclass : public BaseClass { public: - Child() {} + Subclass() {} }; -void FunctionTakingParent(RefCountedPtr o) {} +void FunctionTakingBaseClass(RefCountedPtr p) {} -void FunctionTakingChild(RefCountedPtr o) {} +void FunctionTakingSubclass(RefCountedPtr p) {} -TEST(RefCountedPtr, CanPassChildToFunctionExpectingParent) { - RefCountedPtr child = MakeRefCounted(); - FunctionTakingParent(child); +TEST(RefCountedPtr, ConstructFromSubclass) { + RefCountedPtr p(New()); } -TEST(RefCountedPtr, CanPassChildToFunctionExpectingChild) { - RefCountedPtr child = MakeRefCounted(); - FunctionTakingChild(child); +TEST(RefCountedPtr, CopyAssignFromSubclass) { + RefCountedPtr b; + EXPECT_EQ(nullptr, b.get()); + RefCountedPtr s = MakeRefCounted(); + b = s; + EXPECT_NE(nullptr, b.get()); +} + +TEST(RefCountedPtr, MoveAssignFromSubclass) { + RefCountedPtr b; + EXPECT_EQ(nullptr, b.get()); + RefCountedPtr s = MakeRefCounted(); + b = std::move(s); + EXPECT_NE(nullptr, b.get()); +} + +TEST(RefCountedPtr, ResetFromSubclass) { + RefCountedPtr b; + EXPECT_EQ(nullptr, b.get()); + b.reset(New()); + EXPECT_NE(nullptr, b.get()); +} + +TEST(RefCountedPtr, EqualityWithSubclass) { + Subclass* s = New(); + RefCountedPtr b(s); + EXPECT_EQ(b, s); +} + +TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingBaseClass) { + RefCountedPtr p = MakeRefCounted(); + FunctionTakingBaseClass(p); +} + +TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingSubclass) { + RefCountedPtr p = MakeRefCounted(); + FunctionTakingSubclass(p); } } // namespace -- cgit v1.2.3 From 3abd6201342c321c106ed50699e78090c9e3e497 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 27 Jul 2018 08:20:31 -0700 Subject: fix clang_tidy --- test/core/gprpp/ref_counted_ptr_test.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'test/core') diff --git a/test/core/gprpp/ref_counted_ptr_test.cc b/test/core/gprpp/ref_counted_ptr_test.cc index 1e030c5ba3..463b5e8966 100644 --- a/test/core/gprpp/ref_counted_ptr_test.cc +++ b/test/core/gprpp/ref_counted_ptr_test.cc @@ -185,10 +185,6 @@ class Subclass : public BaseClass { Subclass() {} }; -void FunctionTakingBaseClass(RefCountedPtr p) {} - -void FunctionTakingSubclass(RefCountedPtr p) {} - TEST(RefCountedPtr, ConstructFromSubclass) { RefCountedPtr p(New()); } @@ -222,11 +218,19 @@ TEST(RefCountedPtr, EqualityWithSubclass) { EXPECT_EQ(b, s); } +void FunctionTakingBaseClass(RefCountedPtr p) { + p.reset(); // To appease clang-tidy. +} + TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingBaseClass) { RefCountedPtr p = MakeRefCounted(); FunctionTakingBaseClass(p); } +void FunctionTakingSubclass(RefCountedPtr p) { + p.reset(); // To appease clang-tidy. +} + TEST(RefCountedPtr, CanPassSubclassToFunctionExpectingSubclass) { RefCountedPtr p = MakeRefCounted(); FunctionTakingSubclass(p); -- cgit v1.2.3 From c2a22a1ab8e8221c95f8874668eb6260c1e171b4 Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Fri, 27 Jul 2018 16:19:03 -0700 Subject: Address core review comments --- src/core/lib/iomgr/resource_quota.cc | 80 ++++++++++++++------------ src/core/lib/iomgr/resource_quota.h | 8 +-- src/cpp/thread_manager/thread_manager.cc | 6 +- src/cpp/thread_manager/thread_manager.h | 7 ++- test/core/iomgr/resource_quota_test.cc | 45 ++++++++------- test/cpp/thread_manager/thread_manager_test.cc | 30 +++++----- 6 files changed, 94 insertions(+), 82 deletions(-) (limited to 'test/core') diff --git a/src/core/lib/iomgr/resource_quota.cc b/src/core/lib/iomgr/resource_quota.cc index 47b7856e95..b6fc7579f7 100644 --- a/src/core/lib/iomgr/resource_quota.cc +++ b/src/core/lib/iomgr/resource_quota.cc @@ -97,7 +97,7 @@ struct grpc_resource_user { bool added_to_free_pool; /* The number of threads currently allocated to this resource user */ - gpr_atm num_threads; + gpr_atm num_threads_allocated; /* Reclaimers: index 0 is the benign reclaimer, 1 is the destructive reclaimer */ @@ -138,22 +138,23 @@ struct grpc_resource_quota { gpr_atm last_size; - /* Mutex to protect max_threads and num_threads */ - /* Note: We could have used gpr_atm for max_threads and num_threads and avoid - * having this mutex; but in that case, each invocation of the function - * grpc_resource_user_alloc_threads() would have had to do at least two atomic - * loads (for max_threads and num_threads) followed by a CAS (on num_threads). - * Moreover, we expect grpc_resource_user_alloc_threads() to be often called - * concurrently thereby increasing the chances of failing the CAS operation. - * This additional complexity is not worth the tiny perf gain we may (or may - * not) have by using atomics */ - gpr_mu thd_mu; + /* Mutex to protect max_threads and num_threads_allocated */ + /* Note: We could have used gpr_atm for max_threads and num_threads_allocated + * and avoid having this mutex; but in that case, each invocation of the + * function grpc_resource_user_allocate_threads() would have had to do at + * least two atomic loads (for max_threads and num_threads_allocated) followed + * by a CAS (on num_threads_allocated). + * Moreover, we expect grpc_resource_user_allocate_threads() to be often + * called concurrently thereby increasing the chances of failing the CAS + * operation. This additional complexity is not worth the tiny perf gain we + * may (or may not) have by using atomics */ + gpr_mu thread_count_mu; /* Max number of threads allowed */ int max_threads; /* Number of threads currently allocated via this resource_quota object */ - int num_threads; + int num_threads_allocated; /* Has rq_step been scheduled to occur? */ bool step_scheduled; @@ -548,9 +549,9 @@ static void ru_destroy(void* ru, grpc_error* error) { grpc_resource_user* resource_user = static_cast(ru); GPR_ASSERT(gpr_atm_no_barrier_load(&resource_user->refs) == 0); // Free all the remaining thread quota - grpc_resource_user_free_threads( - resource_user, - static_cast(gpr_atm_no_barrier_load(&resource_user->num_threads))); + grpc_resource_user_free_threads(resource_user, + static_cast(gpr_atm_no_barrier_load( + &resource_user->num_threads_allocated))); for (int i = 0; i < GRPC_RULIST_COUNT; i++) { rulist_remove(resource_user, static_cast(i)); @@ -622,9 +623,9 @@ grpc_resource_quota* grpc_resource_quota_create(const char* name) { resource_quota->free_pool = INT64_MAX; resource_quota->size = INT64_MAX; gpr_atm_no_barrier_store(&resource_quota->last_size, GPR_ATM_MAX); - gpr_mu_init(&resource_quota->thd_mu); + gpr_mu_init(&resource_quota->thread_count_mu); resource_quota->max_threads = INT_MAX; - resource_quota->num_threads = 0; + resource_quota->num_threads_allocated = 0; resource_quota->step_scheduled = false; resource_quota->reclaiming = false; gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation, 0); @@ -647,7 +648,8 @@ grpc_resource_quota* grpc_resource_quota_create(const char* name) { void grpc_resource_quota_unref_internal(grpc_resource_quota* resource_quota) { if (gpr_unref(&resource_quota->refs)) { - GPR_ASSERT(resource_quota->num_threads == 0); // No outstanding thd quota + // No outstanding thread quota + GPR_ASSERT(resource_quota->num_threads_allocated == 0); GRPC_COMBINER_UNREF(resource_quota->combiner, "resource_quota"); gpr_free(resource_quota->name); gpr_free(resource_quota); @@ -681,9 +683,10 @@ double grpc_resource_quota_get_memory_pressure( /* Public API */ void grpc_resource_quota_set_max_threads(grpc_resource_quota* resource_quota, int new_max_threads) { - gpr_mu_lock(&resource_quota->thd_mu); + GPR_ASSERT(new_max_threads >= 0); + gpr_mu_lock(&resource_quota->thread_count_mu); resource_quota->max_threads = new_max_threads; - gpr_mu_unlock(&resource_quota->thd_mu); + gpr_mu_unlock(&resource_quota->thread_count_mu); } /* Public API */ @@ -771,7 +774,7 @@ grpc_resource_user* grpc_resource_user_create( grpc_closure_list_init(&resource_user->on_allocated); resource_user->allocating = false; resource_user->added_to_free_pool = false; - gpr_atm_no_barrier_store(&resource_user->num_threads, 0); + gpr_atm_no_barrier_store(&resource_user->num_threads_allocated, 0); resource_user->reclaimers[0] = nullptr; resource_user->reclaimers[1] = nullptr; resource_user->new_reclaimers[0] = nullptr; @@ -826,35 +829,38 @@ void grpc_resource_user_shutdown(grpc_resource_user* resource_user) { } } -bool grpc_resource_user_alloc_threads(grpc_resource_user* resource_user, - int thd_count) { +bool grpc_resource_user_allocate_threads(grpc_resource_user* resource_user, + int thread_count) { + GPR_ASSERT(thread_count >= 0); bool is_success = false; - gpr_mu_lock(&resource_user->resource_quota->thd_mu); + gpr_mu_lock(&resource_user->resource_quota->thread_count_mu); grpc_resource_quota* rq = resource_user->resource_quota; - if (rq->num_threads + thd_count <= rq->max_threads) { - rq->num_threads += thd_count; - gpr_atm_no_barrier_fetch_add(&resource_user->num_threads, thd_count); + if (rq->num_threads_allocated + thread_count <= rq->max_threads) { + rq->num_threads_allocated += thread_count; + gpr_atm_no_barrier_fetch_add(&resource_user->num_threads_allocated, + thread_count); is_success = true; } - gpr_mu_unlock(&resource_user->resource_quota->thd_mu); + gpr_mu_unlock(&resource_user->resource_quota->thread_count_mu); return is_success; } void grpc_resource_user_free_threads(grpc_resource_user* resource_user, - int thd_count) { - gpr_mu_lock(&resource_user->resource_quota->thd_mu); + int thread_count) { + GPR_ASSERT(thread_count >= 0); + gpr_mu_lock(&resource_user->resource_quota->thread_count_mu); grpc_resource_quota* rq = resource_user->resource_quota; - rq->num_threads -= thd_count; - int old_cnt = static_cast( - gpr_atm_no_barrier_fetch_add(&resource_user->num_threads, -thd_count)); - if (old_cnt < thd_count || rq->num_threads < 0) { + rq->num_threads_allocated -= thread_count; + int old_count = static_cast(gpr_atm_no_barrier_fetch_add( + &resource_user->num_threads_allocated, -thread_count)); + if (old_count < thread_count || rq->num_threads_allocated < 0) { gpr_log(GPR_ERROR, - "Releasing more threads (%d) that currently allocated (rq threads: " + "Releasing more threads (%d) than currently allocated (rq threads: " "%d, ru threads: %d)", - thd_count, old_cnt, rq->num_threads + thd_count); + thread_count, rq->num_threads_allocated + thread_count, old_count); abort(); } - gpr_mu_unlock(&resource_user->resource_quota->thd_mu); + gpr_mu_unlock(&resource_user->resource_quota->thread_count_mu); } void grpc_resource_user_alloc(grpc_resource_user* resource_user, size_t size, diff --git a/src/core/lib/iomgr/resource_quota.h b/src/core/lib/iomgr/resource_quota.h index 7342ef84c8..1d5e95e04a 100644 --- a/src/core/lib/iomgr/resource_quota.h +++ b/src/core/lib/iomgr/resource_quota.h @@ -96,14 +96,14 @@ void grpc_resource_user_shutdown(grpc_resource_user* resource_user); /* Attempts to get quota (from the resource_user) to create 'thd_count' number * of threads. Returns true if successful (i.e the caller is now free to create * 'thd_count' number of threads) or false if quota is not available */ -bool grpc_resource_user_alloc_threads(grpc_resource_user* resource_user, - int thd_count); +bool grpc_resource_user_allocate_threads(grpc_resource_user* resource_user, + int thd_count); /* Releases 'thd_count' worth of quota back to the resource user. The quota * should have been previously obtained successfully by calling - * grpc_resource_user_alloc_threads(). + * grpc_resource_user_allocate_threads(). * * Note: There need not be an exact one-to-one correspondence between - * grpc_resource_user_alloc_threads() and grpc_resource_user_free_threads() + * grpc_resource_user_allocate_threads() and grpc_resource_user_free_threads() * calls. The only requirement is that the number of threads allocated should * all be eventually released */ void grpc_resource_user_free_threads(grpc_resource_user* resource_user, diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc index 5d367511e2..57067d4696 100644 --- a/src/cpp/thread_manager/thread_manager.cc +++ b/src/cpp/thread_manager/thread_manager.cc @@ -123,7 +123,7 @@ void ThreadManager::CleanupCompletedThreads() { } void ThreadManager::Initialize() { - if (!grpc_resource_user_alloc_threads(resource_user_, min_pollers_)) { + if (!grpc_resource_user_allocate_threads(resource_user_, min_pollers_)) { gpr_log(GPR_ERROR, "No thread quota available to even create the minimum required " "polling threads (i.e %d). Unable to start the thread manager", @@ -165,9 +165,9 @@ void ThreadManager::MainWorkLoop() { break; case WORK_FOUND: // If we got work and there are now insufficient pollers and there is - // quota available to create a new thread,start a new poller thread + // quota available to create a new thread, start a new poller thread if (!shutdown_ && num_pollers_ < min_pollers_ && - grpc_resource_user_alloc_threads(resource_user_, 1)) { + grpc_resource_user_allocate_threads(resource_user_, 1)) { num_pollers_++; num_threads_++; max_active_threads_sofar_ = diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h index 8332befed0..01043edb31 100644 --- a/src/cpp/thread_manager/thread_manager.h +++ b/src/cpp/thread_manager/thread_manager.h @@ -100,7 +100,7 @@ class ThreadManager { // ThreadManager::MarkAsCompleted() // // WHY IS THIS NEEDED?: - // When a thread terminates, some other tread *must* call Join() on that + // When a thread terminates, some other thread *must* call Join() on that // thread so that the resources are released. Having a WorkerThread wrapper // will make this easier. Once Run() completes, each thread calls the // following two functions: @@ -113,8 +113,9 @@ class ThreadManager { // in the completed_threads_ list (since a thread cannot call Join() on // itself, it calls CleanupCompletedThreads() *before* calling // MarkAsCompleted()) - // TODO: sreek - consider creating the threads 'detached' so that Join() need - // not be called + // + // TODO(sreek): Consider creating the threads 'detached' so that Join() need + // not be called (and the need for this WorkerThread class is eliminated) class WorkerThread { public: WorkerThread(ThreadManager* thd_mgr); diff --git a/test/core/iomgr/resource_quota_test.cc b/test/core/iomgr/resource_quota_test.cc index 573e4010fa..f3b35fed32 100644 --- a/test/core/iomgr/resource_quota_test.cc +++ b/test/core/iomgr/resource_quota_test.cc @@ -810,30 +810,31 @@ static void test_thread_limit() { grpc_resource_quota_set_max_threads(rq, 100); // Request quota for 100 threads (50 for ru1, 50 for ru2) - GPR_ASSERT(grpc_resource_user_alloc_threads(ru1, 10)); - GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 10)); - GPR_ASSERT(grpc_resource_user_alloc_threads(ru1, 40)); - GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 40)); + GPR_ASSERT(grpc_resource_user_allocate_threads(ru1, 10)); + GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 10)); + GPR_ASSERT(grpc_resource_user_allocate_threads(ru1, 40)); + GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 40)); - // Threads exhaused. Next request must fail - GPR_ASSERT(!grpc_resource_user_alloc_threads(ru2, 20)); + // Threads exhausted. Next request must fail + GPR_ASSERT(!grpc_resource_user_allocate_threads(ru2, 20)); // Free 20 threads from two different users grpc_resource_user_free_threads(ru1, 10); grpc_resource_user_free_threads(ru2, 10); // Next request to 20 threads must succeed - GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 20)); + GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 20)); // No more thread quota again - GPR_ASSERT(!grpc_resource_user_alloc_threads(ru1, 20)); + GPR_ASSERT(!grpc_resource_user_allocate_threads(ru1, 20)); // Free 10 more grpc_resource_user_free_threads(ru1, 10); - GPR_ASSERT(grpc_resource_user_alloc_threads(ru1, 5)); - GPR_ASSERT(!grpc_resource_user_alloc_threads(ru2, 10)); // Only 5 available - GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 5)); + GPR_ASSERT(grpc_resource_user_allocate_threads(ru1, 5)); + GPR_ASSERT( + !grpc_resource_user_allocate_threads(ru2, 10)); // Only 5 available + GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 5)); // Teardown (ru1 and ru2 release all the quota back to rq) grpc_resource_user_unref(ru1); @@ -841,7 +842,7 @@ static void test_thread_limit() { grpc_resource_quota_unref(rq); } -// Change max quota in either directions dynamically +// Change max quota in either direction dynamically static void test_thread_maxquota_change() { grpc_core::ExecCtx exec_ctx; @@ -854,34 +855,34 @@ static void test_thread_maxquota_change() { grpc_resource_quota_set_max_threads(rq, 100); // Request quota for 100 threads (50 for ru1, 50 for ru2) - GPR_ASSERT(grpc_resource_user_alloc_threads(ru1, 50)); - GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 50)); + GPR_ASSERT(grpc_resource_user_allocate_threads(ru1, 50)); + GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 50)); - // Threads exhaused. Next request must fail - GPR_ASSERT(!grpc_resource_user_alloc_threads(ru2, 20)); + // Threads exhausted. Next request must fail + GPR_ASSERT(!grpc_resource_user_allocate_threads(ru2, 20)); // Increase maxquota and retry // Max threads = 150; grpc_resource_quota_set_max_threads(rq, 150); - GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 20)); // ru2 = 70, ru1 = 50 + GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 20)); // ru2=70, ru1=50 // Decrease maxquota (Note: Quota already given to ru1 and ru2 is unaffected) // Max threads = 10; grpc_resource_quota_set_max_threads(rq, 10); // New requests will fail until quota is available - GPR_ASSERT(!grpc_resource_user_alloc_threads(ru1, 10)); + GPR_ASSERT(!grpc_resource_user_allocate_threads(ru1, 10)); // Make quota available - grpc_resource_user_free_threads(ru1, 50); // ru1 now has 0 - GPR_ASSERT(!grpc_resource_user_alloc_threads(ru1, 10)); // Still not enough + grpc_resource_user_free_threads(ru1, 50); // ru1 now has 0 + GPR_ASSERT(!grpc_resource_user_allocate_threads(ru1, 10)); // not enough grpc_resource_user_free_threads(ru2, 70); // ru2 now has 0 // Now we can get quota up-to 10, the current max - GPR_ASSERT(grpc_resource_user_alloc_threads(ru2, 10)); + GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 10)); // No more thread quota again - GPR_ASSERT(!grpc_resource_user_alloc_threads(ru1, 10)); + GPR_ASSERT(!grpc_resource_user_allocate_threads(ru1, 10)); // Teardown (ru1 and ru2 release all the quota back to rq) grpc_resource_user_unref(ru1); diff --git a/test/cpp/thread_manager/thread_manager_test.cc b/test/cpp/thread_manager/thread_manager_test.cc index a7ed2dd380..838f5f72ad 100644 --- a/test/cpp/thread_manager/thread_manager_test.cc +++ b/test/cpp/thread_manager/thread_manager_test.cc @@ -124,16 +124,18 @@ static void TestPollAndWork() { 2 /* min_pollers */, 10 /* max_pollers */, 10 /* poll_duration_ms */, 1 /* work_duration_ms */, 50 /* max_poll_calls */}; - grpc::ThreadManagerTest test_thd_mgr("TestThreadManager", rq, settings); + grpc::ThreadManagerTest test_thread_mgr("TestThreadManager", rq, settings); grpc_resource_quota_unref(rq); - test_thd_mgr.Initialize(); // Start the thread manager - test_thd_mgr.Wait(); // Wait for all threads to finish + test_thread_mgr.Initialize(); // Start the thread manager + test_thread_mgr.Wait(); // Wait for all threads to finish // Verify that The number of times DoWork() was called is equal to the number // of times WORK_FOUND was returned - gpr_log(GPR_DEBUG, "DoWork() called %d times", test_thd_mgr.GetNumDoWork()); - GPR_ASSERT(test_thd_mgr.GetNumDoWork() == test_thd_mgr.GetNumWorkFound()); + gpr_log(GPR_DEBUG, "DoWork() called %d times", + test_thread_mgr.GetNumDoWork()); + GPR_ASSERT(test_thread_mgr.GetNumDoWork() == + test_thread_mgr.GetNumWorkFound()); } static void TestThreadQuota() { @@ -151,18 +153,20 @@ static void TestThreadQuota() { // Create two thread managers (but with same resource quota). This means // that the max number of active threads across BOTH the thread managers // cannot be greater than kMaxNumthreads - grpc::ThreadManagerTest test_thd_mgr_1("TestThreadManager-1", rq, settings); - grpc::ThreadManagerTest test_thd_mgr_2("TestThreadManager-2", rq, settings); + grpc::ThreadManagerTest test_thread_mgr_1("TestThreadManager-1", rq, + settings); + grpc::ThreadManagerTest test_thread_mgr_2("TestThreadManager-2", rq, + settings); // It is ok to unref resource quota before starting thread managers. grpc_resource_quota_unref(rq); // Start both thread managers - test_thd_mgr_1.Initialize(); - test_thd_mgr_2.Initialize(); + test_thread_mgr_1.Initialize(); + test_thread_mgr_2.Initialize(); // Wait for both to finish - test_thd_mgr_1.Wait(); - test_thd_mgr_2.Wait(); + test_thread_mgr_1.Wait(); + test_thread_mgr_2.Wait(); // Now verify that the total number of active threads in either thread manager // never exceeds kMaxNumThreads @@ -173,8 +177,8 @@ static void TestThreadQuota() { // Its okay to not test this case here. The resource quota c-core tests // provide enough coverage to resource quota object with multiple resource // users - int max1 = test_thd_mgr_1.GetMaxActiveThreadsSoFar(); - int max2 = test_thd_mgr_2.GetMaxActiveThreadsSoFar(); + int max1 = test_thread_mgr_1.GetMaxActiveThreadsSoFar(); + int max2 = test_thread_mgr_2.GetMaxActiveThreadsSoFar(); gpr_log( GPR_DEBUG, "MaxActiveThreads in TestThreadManager_1: %d, TestThreadManager_2: %d", -- cgit v1.2.3 From bea98c3c1b32f5959e57f00bb8fd4e129531b671 Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Tue, 31 Jul 2018 21:12:45 -0700 Subject: Revert "Restrict the number of threads in C++ sync server" --- grpc.def | 1 - include/grpc/grpc.h | 4 - include/grpcpp/resource_quota.h | 16 +-- include/grpcpp/server.h | 3 +- src/core/lib/iomgr/resource_quota.cc | 78 ------------- src/core/lib/iomgr/resource_quota.h | 16 --- src/cpp/common/resource_quota_cc.cc | 4 - src/cpp/server/server_builder.cc | 2 +- src/cpp/server/server_cc.cc | 31 +---- src/cpp/thread_manager/thread_manager.cc | 53 ++------- src/cpp/thread_manager/thread_manager.h | 48 +------- src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 - src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 - test/core/iomgr/resource_quota_test.cc | 97 ---------------- test/core/surface/public_headers_must_be_c89.c | 1 - test/cpp/thread_manager/thread_manager_test.cc | 149 ++++++------------------- 16 files changed, 63 insertions(+), 445 deletions(-) (limited to 'test/core') diff --git a/grpc.def b/grpc.def index 312e916682..5b98792662 100644 --- a/grpc.def +++ b/grpc.def @@ -68,7 +68,6 @@ EXPORTS grpc_resource_quota_ref grpc_resource_quota_unref grpc_resource_quota_resize - grpc_resource_quota_set_max_threads grpc_resource_quota_arg_vtable grpc_channelz_get_top_channels grpc_channelz_get_channel diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index eb0251443c..f0eb2c0121 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -450,10 +450,6 @@ GRPCAPI void grpc_resource_quota_unref(grpc_resource_quota* resource_quota); GRPCAPI void grpc_resource_quota_resize(grpc_resource_quota* resource_quota, size_t new_size); -/** Update the size of the maximum number of threads allowed */ -GRPCAPI void grpc_resource_quota_set_max_threads( - grpc_resource_quota* resource_quota, int new_max_threads); - /** Fetch a vtable for a grpc_channel_arg that points to a grpc_resource_quota */ GRPCAPI const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void); diff --git a/include/grpcpp/resource_quota.h b/include/grpcpp/resource_quota.h index 50bd1cb849..554437a40d 100644 --- a/include/grpcpp/resource_quota.h +++ b/include/grpcpp/resource_quota.h @@ -26,10 +26,10 @@ struct grpc_resource_quota; namespace grpc { -/// ResourceQuota represents a bound on memory and thread usage by the gRPC -/// library. A ResourceQuota can be attached to a server (via \a ServerBuilder), +/// ResourceQuota represents a bound on memory usage by the gRPC library. +/// A ResourceQuota can be attached to a server (via \a ServerBuilder), /// or a client channel (via \a ChannelArguments). -/// gRPC will attempt to keep memory and threads used by all attached entities +/// gRPC will attempt to keep memory used by all attached entities /// below the ResourceQuota bound. class ResourceQuota final : private GrpcLibraryCodegen { public: @@ -44,16 +44,6 @@ class ResourceQuota final : private GrpcLibraryCodegen { /// No time bound is given for this to occur however. ResourceQuota& Resize(size_t new_size); - /// Set the max number of threads that can be allocated from this - /// ResourceQuota object. - /// - /// If the new_max_threads value is smaller than the current value, no new - /// threads are allocated until the number of active threads fall below - /// new_max_threads. There is no time bound on when this may happen i.e none - /// of the current threads are forcefully destroyed and all threads run their - /// normal course. - ResourceQuota& SetMaxThreads(int new_max_threads); - grpc_resource_quota* c_resource_quota() const { return impl_; } private: diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index 189cf8accf..81c3907f86 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -144,8 +144,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { Server(int max_message_size, ChannelArguments* args, std::shared_ptr>> sync_server_cqs, - grpc_resource_quota* server_rq, int min_pollers, int max_pollers, - int sync_cq_timeout_msec); + int min_pollers, int max_pollers, int sync_cq_timeout_msec); /// Start the server. /// diff --git a/src/core/lib/iomgr/resource_quota.cc b/src/core/lib/iomgr/resource_quota.cc index b6fc7579f7..539bc120ce 100644 --- a/src/core/lib/iomgr/resource_quota.cc +++ b/src/core/lib/iomgr/resource_quota.cc @@ -96,9 +96,6 @@ struct grpc_resource_user { list, false otherwise */ bool added_to_free_pool; - /* The number of threads currently allocated to this resource user */ - gpr_atm num_threads_allocated; - /* Reclaimers: index 0 is the benign reclaimer, 1 is the destructive reclaimer */ grpc_closure* reclaimers[2]; @@ -138,33 +135,12 @@ struct grpc_resource_quota { gpr_atm last_size; - /* Mutex to protect max_threads and num_threads_allocated */ - /* Note: We could have used gpr_atm for max_threads and num_threads_allocated - * and avoid having this mutex; but in that case, each invocation of the - * function grpc_resource_user_allocate_threads() would have had to do at - * least two atomic loads (for max_threads and num_threads_allocated) followed - * by a CAS (on num_threads_allocated). - * Moreover, we expect grpc_resource_user_allocate_threads() to be often - * called concurrently thereby increasing the chances of failing the CAS - * operation. This additional complexity is not worth the tiny perf gain we - * may (or may not) have by using atomics */ - gpr_mu thread_count_mu; - - /* Max number of threads allowed */ - int max_threads; - - /* Number of threads currently allocated via this resource_quota object */ - int num_threads_allocated; - /* Has rq_step been scheduled to occur? */ bool step_scheduled; - /* Are we currently reclaiming memory */ bool reclaiming; - /* Closure around rq_step */ grpc_closure rq_step_closure; - /* Closure around rq_reclamation_done */ grpc_closure rq_reclamation_done_closure; @@ -548,11 +524,6 @@ static void ru_shutdown(void* ru, grpc_error* error) { static void ru_destroy(void* ru, grpc_error* error) { grpc_resource_user* resource_user = static_cast(ru); GPR_ASSERT(gpr_atm_no_barrier_load(&resource_user->refs) == 0); - // Free all the remaining thread quota - grpc_resource_user_free_threads(resource_user, - static_cast(gpr_atm_no_barrier_load( - &resource_user->num_threads_allocated))); - for (int i = 0; i < GRPC_RULIST_COUNT; i++) { rulist_remove(resource_user, static_cast(i)); } @@ -623,9 +594,6 @@ grpc_resource_quota* grpc_resource_quota_create(const char* name) { resource_quota->free_pool = INT64_MAX; resource_quota->size = INT64_MAX; gpr_atm_no_barrier_store(&resource_quota->last_size, GPR_ATM_MAX); - gpr_mu_init(&resource_quota->thread_count_mu); - resource_quota->max_threads = INT_MAX; - resource_quota->num_threads_allocated = 0; resource_quota->step_scheduled = false; resource_quota->reclaiming = false; gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation, 0); @@ -648,8 +616,6 @@ grpc_resource_quota* grpc_resource_quota_create(const char* name) { void grpc_resource_quota_unref_internal(grpc_resource_quota* resource_quota) { if (gpr_unref(&resource_quota->refs)) { - // No outstanding thread quota - GPR_ASSERT(resource_quota->num_threads_allocated == 0); GRPC_COMBINER_UNREF(resource_quota->combiner, "resource_quota"); gpr_free(resource_quota->name); gpr_free(resource_quota); @@ -680,15 +646,6 @@ double grpc_resource_quota_get_memory_pressure( (static_cast(MEMORY_USAGE_ESTIMATION_MAX)); } -/* Public API */ -void grpc_resource_quota_set_max_threads(grpc_resource_quota* resource_quota, - int new_max_threads) { - GPR_ASSERT(new_max_threads >= 0); - gpr_mu_lock(&resource_quota->thread_count_mu); - resource_quota->max_threads = new_max_threads; - gpr_mu_unlock(&resource_quota->thread_count_mu); -} - /* Public API */ void grpc_resource_quota_resize(grpc_resource_quota* resource_quota, size_t size) { @@ -774,7 +731,6 @@ grpc_resource_user* grpc_resource_user_create( grpc_closure_list_init(&resource_user->on_allocated); resource_user->allocating = false; resource_user->added_to_free_pool = false; - gpr_atm_no_barrier_store(&resource_user->num_threads_allocated, 0); resource_user->reclaimers[0] = nullptr; resource_user->reclaimers[1] = nullptr; resource_user->new_reclaimers[0] = nullptr; @@ -829,40 +785,6 @@ void grpc_resource_user_shutdown(grpc_resource_user* resource_user) { } } -bool grpc_resource_user_allocate_threads(grpc_resource_user* resource_user, - int thread_count) { - GPR_ASSERT(thread_count >= 0); - bool is_success = false; - gpr_mu_lock(&resource_user->resource_quota->thread_count_mu); - grpc_resource_quota* rq = resource_user->resource_quota; - if (rq->num_threads_allocated + thread_count <= rq->max_threads) { - rq->num_threads_allocated += thread_count; - gpr_atm_no_barrier_fetch_add(&resource_user->num_threads_allocated, - thread_count); - is_success = true; - } - gpr_mu_unlock(&resource_user->resource_quota->thread_count_mu); - return is_success; -} - -void grpc_resource_user_free_threads(grpc_resource_user* resource_user, - int thread_count) { - GPR_ASSERT(thread_count >= 0); - gpr_mu_lock(&resource_user->resource_quota->thread_count_mu); - grpc_resource_quota* rq = resource_user->resource_quota; - rq->num_threads_allocated -= thread_count; - int old_count = static_cast(gpr_atm_no_barrier_fetch_add( - &resource_user->num_threads_allocated, -thread_count)); - if (old_count < thread_count || rq->num_threads_allocated < 0) { - gpr_log(GPR_ERROR, - "Releasing more threads (%d) than currently allocated (rq threads: " - "%d, ru threads: %d)", - thread_count, rq->num_threads_allocated + thread_count, old_count); - abort(); - } - gpr_mu_unlock(&resource_user->resource_quota->thread_count_mu); -} - void grpc_resource_user_alloc(grpc_resource_user* resource_user, size_t size, grpc_closure* optional_on_done) { gpr_mu_lock(&resource_user->mu); diff --git a/src/core/lib/iomgr/resource_quota.h b/src/core/lib/iomgr/resource_quota.h index 1d5e95e04a..937daf8728 100644 --- a/src/core/lib/iomgr/resource_quota.h +++ b/src/core/lib/iomgr/resource_quota.h @@ -93,22 +93,6 @@ void grpc_resource_user_ref(grpc_resource_user* resource_user); void grpc_resource_user_unref(grpc_resource_user* resource_user); void grpc_resource_user_shutdown(grpc_resource_user* resource_user); -/* Attempts to get quota (from the resource_user) to create 'thd_count' number - * of threads. Returns true if successful (i.e the caller is now free to create - * 'thd_count' number of threads) or false if quota is not available */ -bool grpc_resource_user_allocate_threads(grpc_resource_user* resource_user, - int thd_count); -/* Releases 'thd_count' worth of quota back to the resource user. The quota - * should have been previously obtained successfully by calling - * grpc_resource_user_allocate_threads(). - * - * Note: There need not be an exact one-to-one correspondence between - * grpc_resource_user_allocate_threads() and grpc_resource_user_free_threads() - * calls. The only requirement is that the number of threads allocated should - * all be eventually released */ -void grpc_resource_user_free_threads(grpc_resource_user* resource_user, - int thd_count); - /* Allocate from the resource user (and its quota). If optional_on_done is NULL, then allocate immediately. This may push the quota over-limit, at which point reclamation will kick in. diff --git a/src/cpp/common/resource_quota_cc.cc b/src/cpp/common/resource_quota_cc.cc index 276e5f7954..daeb0ba171 100644 --- a/src/cpp/common/resource_quota_cc.cc +++ b/src/cpp/common/resource_quota_cc.cc @@ -33,8 +33,4 @@ ResourceQuota& ResourceQuota::Resize(size_t new_size) { return *this; } -ResourceQuota& ResourceQuota::SetMaxThreads(int new_max_threads) { - grpc_resource_quota_set_max_threads(impl_, new_max_threads); - return *this; -} } // namespace grpc diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index 0ab3cd0e32..e0b9b7a62b 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -261,7 +261,7 @@ std::unique_ptr ServerBuilder::BuildAndStart() { } std::unique_ptr server(new Server( - max_receive_message_size_, &args, sync_server_cqs, resource_quota_, + max_receive_message_size_, &args, sync_server_cqs, sync_server_settings_.min_pollers, sync_server_settings_.max_pollers, sync_server_settings_.cq_timeout_msec)); diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 472c5035fc..0d77510e29 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -47,12 +47,6 @@ namespace grpc { namespace { -// The default value for maximum number of threads that can be created in the -// sync server. This value of 500 is empirically chosen. To increase the max -// number of threads in a sync server, pass a custom ResourceQuota object (with -// the desired number of max-threads set) to the server builder -#define DEFAULT_MAX_SYNC_SERVER_THREADS 500 - class DefaultGlobalCallbacks final : public Server::GlobalCallbacks { public: ~DefaultGlobalCallbacks() override {} @@ -272,9 +266,9 @@ class Server::SyncRequestThreadManager : public ThreadManager { public: SyncRequestThreadManager(Server* server, CompletionQueue* server_cq, std::shared_ptr global_callbacks, - grpc_resource_quota* rq, int min_pollers, - int max_pollers, int cq_timeout_msec) - : ThreadManager("SyncServer", rq, min_pollers, max_pollers), + int min_pollers, int max_pollers, + int cq_timeout_msec) + : ThreadManager(min_pollers, max_pollers), server_(server), server_cq_(server_cq), cq_timeout_msec_(cq_timeout_msec), @@ -382,8 +376,7 @@ Server::Server( int max_receive_message_size, ChannelArguments* args, std::shared_ptr>> sync_server_cqs, - grpc_resource_quota* server_rq, int min_pollers, int max_pollers, - int sync_cq_timeout_msec) + int min_pollers, int max_pollers, int sync_cq_timeout_msec) : max_receive_message_size_(max_receive_message_size), sync_server_cqs_(std::move(sync_server_cqs)), started_(false), @@ -399,22 +392,10 @@ Server::Server( global_callbacks_->UpdateArguments(args); if (sync_server_cqs_ != nullptr) { - bool default_rq_created = false; - if (server_rq == nullptr) { - server_rq = grpc_resource_quota_create("SyncServer-default-rq"); - grpc_resource_quota_set_max_threads(server_rq, - DEFAULT_MAX_SYNC_SERVER_THREADS); - default_rq_created = true; - } - for (const auto& it : *sync_server_cqs_) { sync_req_mgrs_.emplace_back(new SyncRequestThreadManager( - this, it.get(), global_callbacks_, server_rq, min_pollers, - max_pollers, sync_cq_timeout_msec)); - } - - if (default_rq_created) { - grpc_resource_quota_unref(server_rq); + this, it.get(), global_callbacks_, min_pollers, max_pollers, + sync_cq_timeout_msec)); } } diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc index fa9eec5f9b..02ac56a3fd 100644 --- a/src/cpp/thread_manager/thread_manager.cc +++ b/src/cpp/thread_manager/thread_manager.cc @@ -22,8 +22,8 @@ #include #include + #include "src/core/lib/gprpp/thd.h" -#include "src/core/lib/iomgr/exec_ctx.h" namespace grpc { @@ -48,17 +48,12 @@ ThreadManager::WorkerThread::~WorkerThread() { thd_.Join(); } -ThreadManager::ThreadManager(const char* name, - grpc_resource_quota* resource_quota, - int min_pollers, int max_pollers) +ThreadManager::ThreadManager(int min_pollers, int max_pollers) : shutdown_(false), num_pollers_(0), min_pollers_(min_pollers), max_pollers_(max_pollers == -1 ? INT_MAX : max_pollers), - num_threads_(0), - max_active_threads_sofar_(0) { - resource_user_ = grpc_resource_user_create(resource_quota, name); -} + num_threads_(0) {} ThreadManager::~ThreadManager() { { @@ -66,8 +61,6 @@ ThreadManager::~ThreadManager() { GPR_ASSERT(num_threads_ == 0); } - grpc_core::ExecCtx exec_ctx; // grpc_resource_user_unref needs an exec_ctx - grpc_resource_user_unref(resource_user_); CleanupCompletedThreads(); } @@ -88,27 +81,17 @@ bool ThreadManager::IsShutdown() { return shutdown_; } -int ThreadManager::GetMaxActiveThreadsSoFar() { - std::lock_guard list_lock(list_mu_); - return max_active_threads_sofar_; -} - void ThreadManager::MarkAsCompleted(WorkerThread* thd) { { std::lock_guard list_lock(list_mu_); completed_threads_.push_back(thd); } - { - std::lock_guard lock(mu_); - num_threads_--; - if (num_threads_ == 0) { - shutdown_cv_.notify_one(); - } + std::lock_guard lock(mu_); + num_threads_--; + if (num_threads_ == 0) { + shutdown_cv_.notify_one(); } - - // Give a thread back to the resource quota - grpc_resource_user_free_threads(resource_user_, 1); } void ThreadManager::CleanupCompletedThreads() { @@ -123,22 +106,14 @@ void ThreadManager::CleanupCompletedThreads() { } void ThreadManager::Initialize() { - if (!grpc_resource_user_allocate_threads(resource_user_, min_pollers_)) { - gpr_log(GPR_ERROR, - "No thread quota available to even create the minimum required " - "polling threads (i.e %d). Unable to start the thread manager", - min_pollers_); - abort(); - } - { std::unique_lock lock(mu_); num_pollers_ = min_pollers_; num_threads_ = min_pollers_; - max_active_threads_sofar_ = min_pollers_; } for (int i = 0; i < min_pollers_; i++) { + // Create a new thread (which ends up calling the MainWorkLoop() function new WorkerThread(this); } } @@ -164,15 +139,11 @@ void ThreadManager::MainWorkLoop() { done = true; break; case WORK_FOUND: - // If we got work and there are now insufficient pollers and there is - // quota available to create a new thread, start a new poller thread - if (!shutdown_ && num_pollers_ < min_pollers_ && - grpc_resource_user_allocate_threads(resource_user_, 1)) { + // If we got work and there are now insufficient pollers, start a new + // one + if (!shutdown_ && num_pollers_ < min_pollers_) { num_pollers_++; num_threads_++; - if (num_threads_ > max_active_threads_sofar_) { - max_active_threads_sofar_ = num_threads_; - } // Drop lock before spawning thread to avoid contention lock.unlock(); new WorkerThread(this); @@ -225,8 +196,6 @@ void ThreadManager::MainWorkLoop() { } }; - // This thread is exiting. Do some cleanup work i.e delete already completed - // worker threads CleanupCompletedThreads(); // If we are here, either ThreadManager is shutting down or it already has diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h index 01043edb31..5a40f2de47 100644 --- a/src/cpp/thread_manager/thread_manager.h +++ b/src/cpp/thread_manager/thread_manager.h @@ -27,14 +27,12 @@ #include #include "src/core/lib/gprpp/thd.h" -#include "src/core/lib/iomgr/resource_quota.h" namespace grpc { class ThreadManager { public: - explicit ThreadManager(const char* name, grpc_resource_quota* resource_quota, - int min_pollers, int max_pollers); + explicit ThreadManager(int min_pollers, int max_pollers); virtual ~ThreadManager(); // Initializes and Starts the Rpc Manager threads @@ -86,11 +84,6 @@ class ThreadManager { // all the threads have drained all the outstanding work virtual void Wait(); - // Max number of concurrent threads that were ever active in this thread - // manager so far. This is useful for debugging purposes (and in unit tests) - // to check if resource_quota is properly being enforced. - int GetMaxActiveThreadsSoFar(); - private: // Helper wrapper class around grpc_core::Thread. Takes a ThreadManager object // and starts a new grpc_core::Thread to calls the Run() function. @@ -98,24 +91,6 @@ class ThreadManager { // The Run() function calls ThreadManager::MainWorkLoop() function and once // that completes, it marks the WorkerThread completed by calling // ThreadManager::MarkAsCompleted() - // - // WHY IS THIS NEEDED?: - // When a thread terminates, some other thread *must* call Join() on that - // thread so that the resources are released. Having a WorkerThread wrapper - // will make this easier. Once Run() completes, each thread calls the - // following two functions: - // ThreadManager::CleanupCompletedThreads() - // ThreadManager::MarkAsCompleted() - // - // - MarkAsCompleted() puts the WorkerThread object in the ThreadManger's - // completed_threads_ list - // - CleanupCompletedThreads() calls "Join()" on the threads that are already - // in the completed_threads_ list (since a thread cannot call Join() on - // itself, it calls CleanupCompletedThreads() *before* calling - // MarkAsCompleted()) - // - // TODO(sreek): Consider creating the threads 'detached' so that Join() need - // not be called (and the need for this WorkerThread class is eliminated) class WorkerThread { public: WorkerThread(ThreadManager* thd_mgr); @@ -136,21 +111,13 @@ class ThreadManager { void MarkAsCompleted(WorkerThread* thd); void CleanupCompletedThreads(); - // Protects shutdown_, num_pollers_, num_threads_ and - // max_active_threads_sofar_ + // Protects shutdown_, num_pollers_ and num_threads_ + // TODO: sreek - Change num_pollers and num_threads_ to atomics std::mutex mu_; bool shutdown_; std::condition_variable shutdown_cv_; - // The resource user object to use when requesting quota to create threads - // - // Note: The user of this ThreadManager object must create grpc_resource_quota - // object (that contains the actual max thread quota) and a grpc_resource_user - // object through which quota is requested whenver new threads need to be - // created - grpc_resource_user* resource_user_; - // Number of threads doing polling int num_pollers_; @@ -158,15 +125,10 @@ class ThreadManager { int min_pollers_; int max_pollers_; - // The total number of threads currently active (includes threads includes the - // threads that are currently polling i.e num_pollers_) + // The total number of threads (includes threads includes the threads that are + // currently polling i.e num_pollers_) int num_threads_; - // See GetMaxActiveThreadsSoFar()'s description. - // To be more specific, this variable tracks the max value num_threads_ was - // ever set so far - int max_active_threads_sofar_; - std::mutex list_mu_; std::list completed_threads_; }; diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 78090afd6c..2443532bb8 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -91,7 +91,6 @@ grpc_resource_quota_create_type grpc_resource_quota_create_import; grpc_resource_quota_ref_type grpc_resource_quota_ref_import; grpc_resource_quota_unref_type grpc_resource_quota_unref_import; grpc_resource_quota_resize_type grpc_resource_quota_resize_import; -grpc_resource_quota_set_max_threads_type grpc_resource_quota_set_max_threads_import; grpc_resource_quota_arg_vtable_type grpc_resource_quota_arg_vtable_import; grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import; grpc_channelz_get_channel_type grpc_channelz_get_channel_import; @@ -342,7 +341,6 @@ void grpc_rb_load_imports(HMODULE library) { grpc_resource_quota_ref_import = (grpc_resource_quota_ref_type) GetProcAddress(library, "grpc_resource_quota_ref"); grpc_resource_quota_unref_import = (grpc_resource_quota_unref_type) GetProcAddress(library, "grpc_resource_quota_unref"); grpc_resource_quota_resize_import = (grpc_resource_quota_resize_type) GetProcAddress(library, "grpc_resource_quota_resize"); - grpc_resource_quota_set_max_threads_import = (grpc_resource_quota_set_max_threads_type) GetProcAddress(library, "grpc_resource_quota_set_max_threads"); grpc_resource_quota_arg_vtable_import = (grpc_resource_quota_arg_vtable_type) GetProcAddress(library, "grpc_resource_quota_arg_vtable"); grpc_channelz_get_top_channels_import = (grpc_channelz_get_top_channels_type) GetProcAddress(library, "grpc_channelz_get_top_channels"); grpc_channelz_get_channel_import = (grpc_channelz_get_channel_type) GetProcAddress(library, "grpc_channelz_get_channel"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 1807efa761..b08a1f94f7 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -248,9 +248,6 @@ extern grpc_resource_quota_unref_type grpc_resource_quota_unref_import; typedef void(*grpc_resource_quota_resize_type)(grpc_resource_quota* resource_quota, size_t new_size); extern grpc_resource_quota_resize_type grpc_resource_quota_resize_import; #define grpc_resource_quota_resize grpc_resource_quota_resize_import -typedef void(*grpc_resource_quota_set_max_threads_type)(grpc_resource_quota* resource_quota, int new_max_threads); -extern grpc_resource_quota_set_max_threads_type grpc_resource_quota_set_max_threads_import; -#define grpc_resource_quota_set_max_threads grpc_resource_quota_set_max_threads_import typedef const grpc_arg_pointer_vtable*(*grpc_resource_quota_arg_vtable_type)(void); extern grpc_resource_quota_arg_vtable_type grpc_resource_quota_arg_vtable_import; #define grpc_resource_quota_arg_vtable grpc_resource_quota_arg_vtable_import diff --git a/test/core/iomgr/resource_quota_test.cc b/test/core/iomgr/resource_quota_test.cc index f3b35fed32..059ff7b5f8 100644 --- a/test/core/iomgr/resource_quota_test.cc +++ b/test/core/iomgr/resource_quota_test.cc @@ -798,98 +798,6 @@ static void test_negative_rq_free_pool(void) { } } -// Simple test to check resource quota thread limits -static void test_thread_limit() { - grpc_core::ExecCtx exec_ctx; - - grpc_resource_quota* rq = grpc_resource_quota_create("test_thread_limit"); - grpc_resource_user* ru1 = grpc_resource_user_create(rq, "ru1"); - grpc_resource_user* ru2 = grpc_resource_user_create(rq, "ru2"); - - // Max threads = 100 - grpc_resource_quota_set_max_threads(rq, 100); - - // Request quota for 100 threads (50 for ru1, 50 for ru2) - GPR_ASSERT(grpc_resource_user_allocate_threads(ru1, 10)); - GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 10)); - GPR_ASSERT(grpc_resource_user_allocate_threads(ru1, 40)); - GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 40)); - - // Threads exhausted. Next request must fail - GPR_ASSERT(!grpc_resource_user_allocate_threads(ru2, 20)); - - // Free 20 threads from two different users - grpc_resource_user_free_threads(ru1, 10); - grpc_resource_user_free_threads(ru2, 10); - - // Next request to 20 threads must succeed - GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 20)); - - // No more thread quota again - GPR_ASSERT(!grpc_resource_user_allocate_threads(ru1, 20)); - - // Free 10 more - grpc_resource_user_free_threads(ru1, 10); - - GPR_ASSERT(grpc_resource_user_allocate_threads(ru1, 5)); - GPR_ASSERT( - !grpc_resource_user_allocate_threads(ru2, 10)); // Only 5 available - GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 5)); - - // Teardown (ru1 and ru2 release all the quota back to rq) - grpc_resource_user_unref(ru1); - grpc_resource_user_unref(ru2); - grpc_resource_quota_unref(rq); -} - -// Change max quota in either direction dynamically -static void test_thread_maxquota_change() { - grpc_core::ExecCtx exec_ctx; - - grpc_resource_quota* rq = - grpc_resource_quota_create("test_thread_maxquota_change"); - grpc_resource_user* ru1 = grpc_resource_user_create(rq, "ru1"); - grpc_resource_user* ru2 = grpc_resource_user_create(rq, "ru2"); - - // Max threads = 100 - grpc_resource_quota_set_max_threads(rq, 100); - - // Request quota for 100 threads (50 for ru1, 50 for ru2) - GPR_ASSERT(grpc_resource_user_allocate_threads(ru1, 50)); - GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 50)); - - // Threads exhausted. Next request must fail - GPR_ASSERT(!grpc_resource_user_allocate_threads(ru2, 20)); - - // Increase maxquota and retry - // Max threads = 150; - grpc_resource_quota_set_max_threads(rq, 150); - GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 20)); // ru2=70, ru1=50 - - // Decrease maxquota (Note: Quota already given to ru1 and ru2 is unaffected) - // Max threads = 10; - grpc_resource_quota_set_max_threads(rq, 10); - - // New requests will fail until quota is available - GPR_ASSERT(!grpc_resource_user_allocate_threads(ru1, 10)); - - // Make quota available - grpc_resource_user_free_threads(ru1, 50); // ru1 now has 0 - GPR_ASSERT(!grpc_resource_user_allocate_threads(ru1, 10)); // not enough - - grpc_resource_user_free_threads(ru2, 70); // ru2 now has 0 - - // Now we can get quota up-to 10, the current max - GPR_ASSERT(grpc_resource_user_allocate_threads(ru2, 10)); - // No more thread quota again - GPR_ASSERT(!grpc_resource_user_allocate_threads(ru1, 10)); - - // Teardown (ru1 and ru2 release all the quota back to rq) - grpc_resource_user_unref(ru1); - grpc_resource_user_unref(ru2); - grpc_resource_quota_unref(rq); -} - int main(int argc, char** argv) { grpc_test_init(argc, argv); grpc_init(); @@ -919,11 +827,6 @@ int main(int argc, char** argv) { test_negative_rq_free_pool(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_cv); - - // Resource quota thread related - test_thread_limit(); - test_thread_maxquota_change(); - grpc_shutdown(); return 0; } diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 497f7194d5..9f4ad2b4d7 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -130,7 +130,6 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_resource_quota_ref); printf("%lx", (unsigned long) grpc_resource_quota_unref); printf("%lx", (unsigned long) grpc_resource_quota_resize); - printf("%lx", (unsigned long) grpc_resource_quota_set_max_threads); printf("%lx", (unsigned long) grpc_resource_quota_arg_vtable); printf("%lx", (unsigned long) grpc_channelz_get_top_channels); printf("%lx", (unsigned long) grpc_channelz_get_channel); diff --git a/test/cpp/thread_manager/thread_manager_test.cc b/test/cpp/thread_manager/thread_manager_test.cc index 838f5f72ad..7a95a9f17d 100644 --- a/test/cpp/thread_manager/thread_manager_test.cc +++ b/test/cpp/thread_manager/thread_manager_test.cc @@ -30,44 +30,30 @@ #include "test/cpp/util/test_config.h" namespace grpc { - -struct ThreadManagerTestSettings { - // The min number of pollers that SHOULD be active in ThreadManager - int min_pollers; - // The max number of pollers that could be active in ThreadManager - int max_pollers; - // The sleep duration in PollForWork() function to simulate "polling" - int poll_duration_ms; - // The sleep duration in DoWork() function to simulate "work" - int work_duration_ms; - // Max number of times PollForWork() is called before shutting down - int max_poll_calls; -}; - class ThreadManagerTest final : public grpc::ThreadManager { public: - ThreadManagerTest(const char* name, grpc_resource_quota* rq, - const ThreadManagerTestSettings& settings) - : ThreadManager(name, rq, settings.min_pollers, settings.max_pollers), - settings_(settings), + ThreadManagerTest() + : ThreadManager(kMinPollers, kMaxPollers), num_do_work_(0), num_poll_for_work_(0), num_work_found_(0) {} grpc::ThreadManager::WorkStatus PollForWork(void** tag, bool* ok) override; void DoWork(void* tag, bool ok) override; - - // Get number of times PollForWork() returned WORK_FOUND - int GetNumWorkFound(); - // Get number of times DoWork() was called - int GetNumDoWork(); + void PerformTest(); private: void SleepForMs(int sleep_time_ms); - ThreadManagerTestSettings settings_; + static const int kMinPollers = 2; + static const int kMaxPollers = 10; + + static const int kPollingTimeoutMsec = 10; + static const int kDoWorkDurationMsec = 1; + + // PollForWork will return SHUTDOWN after these many number of invocations + static const int kMaxNumPollForWork = 50; - // Counters gpr_atm num_do_work_; // Number of calls to DoWork gpr_atm num_poll_for_work_; // Number of calls to PollForWork gpr_atm num_work_found_; // Number of times WORK_FOUND was returned @@ -83,117 +69,54 @@ void ThreadManagerTest::SleepForMs(int duration_ms) { grpc::ThreadManager::WorkStatus ThreadManagerTest::PollForWork(void** tag, bool* ok) { int call_num = gpr_atm_no_barrier_fetch_add(&num_poll_for_work_, 1); - if (call_num >= settings_.max_poll_calls) { + + if (call_num >= kMaxNumPollForWork) { Shutdown(); return SHUTDOWN; } - SleepForMs(settings_.poll_duration_ms); // Simulate "polling" duration + // Simulate "polling for work" by sleeping for sometime + SleepForMs(kPollingTimeoutMsec); + *tag = nullptr; *ok = true; - // Return timeout roughly 1 out of every 3 calls just to make the test a bit - // more interesting + // Return timeout roughly 1 out of every 3 calls if (call_num % 3 == 0) { return TIMEOUT; + } else { + gpr_atm_no_barrier_fetch_add(&num_work_found_, 1); + return WORK_FOUND; } - - gpr_atm_no_barrier_fetch_add(&num_work_found_, 1); - return WORK_FOUND; } void ThreadManagerTest::DoWork(void* tag, bool ok) { gpr_atm_no_barrier_fetch_add(&num_do_work_, 1); - SleepForMs(settings_.work_duration_ms); // Simulate work by sleeping + SleepForMs(kDoWorkDurationMsec); // Simulate doing work by sleeping } -int ThreadManagerTest::GetNumWorkFound() { - return static_cast(gpr_atm_no_barrier_load(&num_work_found_)); -} - -int ThreadManagerTest::GetNumDoWork() { - return static_cast(gpr_atm_no_barrier_load(&num_do_work_)); -} -} // namespace grpc +void ThreadManagerTest::PerformTest() { + // Initialize() starts the ThreadManager + Initialize(); -// Test that the number of times DoWork() is called is equal to the number of -// times PollForWork() returned WORK_FOUND -static void TestPollAndWork() { - grpc_resource_quota* rq = grpc_resource_quota_create("Test-poll-and-work"); - grpc::ThreadManagerTestSettings settings = { - 2 /* min_pollers */, 10 /* max_pollers */, 10 /* poll_duration_ms */, - 1 /* work_duration_ms */, 50 /* max_poll_calls */}; - - grpc::ThreadManagerTest test_thread_mgr("TestThreadManager", rq, settings); - grpc_resource_quota_unref(rq); - - test_thread_mgr.Initialize(); // Start the thread manager - test_thread_mgr.Wait(); // Wait for all threads to finish - - // Verify that The number of times DoWork() was called is equal to the number - // of times WORK_FOUND was returned - gpr_log(GPR_DEBUG, "DoWork() called %d times", - test_thread_mgr.GetNumDoWork()); - GPR_ASSERT(test_thread_mgr.GetNumDoWork() == - test_thread_mgr.GetNumWorkFound()); -} + // Wait for all the threads to gracefully terminate + Wait(); -static void TestThreadQuota() { - const int kMaxNumThreads = 3; - grpc_resource_quota* rq = grpc_resource_quota_create("Test-thread-quota"); - grpc_resource_quota_set_max_threads(rq, kMaxNumThreads); - - // Set work_duration_ms to be much greater than poll_duration_ms. This way, - // the thread manager will be forced to create more 'polling' threads to - // honor the min_pollers guarantee - grpc::ThreadManagerTestSettings settings = { - 1 /* min_pollers */, 1 /* max_pollers */, 1 /* poll_duration_ms */, - 10 /* work_duration_ms */, 50 /* max_poll_calls */}; - - // Create two thread managers (but with same resource quota). This means - // that the max number of active threads across BOTH the thread managers - // cannot be greater than kMaxNumthreads - grpc::ThreadManagerTest test_thread_mgr_1("TestThreadManager-1", rq, - settings); - grpc::ThreadManagerTest test_thread_mgr_2("TestThreadManager-2", rq, - settings); - // It is ok to unref resource quota before starting thread managers. - grpc_resource_quota_unref(rq); - - // Start both thread managers - test_thread_mgr_1.Initialize(); - test_thread_mgr_2.Initialize(); - - // Wait for both to finish - test_thread_mgr_1.Wait(); - test_thread_mgr_2.Wait(); - - // Now verify that the total number of active threads in either thread manager - // never exceeds kMaxNumThreads - // - // NOTE: Actually the total active threads across *both* thread managers at - // any point of time never exceeds kMaxNumThreads but unfortunately there is - // no easy way to verify it (i.e we can't just do (max1 + max2 <= k)) - // Its okay to not test this case here. The resource quota c-core tests - // provide enough coverage to resource quota object with multiple resource - // users - int max1 = test_thread_mgr_1.GetMaxActiveThreadsSoFar(); - int max2 = test_thread_mgr_2.GetMaxActiveThreadsSoFar(); - gpr_log( - GPR_DEBUG, - "MaxActiveThreads in TestThreadManager_1: %d, TestThreadManager_2: %d", - max1, max2); - GPR_ASSERT(max1 <= kMaxNumThreads && max2 <= kMaxNumThreads); + // The number of times DoWork() was called is equal to the number of times + // WORK_FOUND was returned + gpr_log(GPR_DEBUG, "DoWork() called %" PRIdPTR " times", + gpr_atm_no_barrier_load(&num_do_work_)); + GPR_ASSERT(gpr_atm_no_barrier_load(&num_do_work_) == + gpr_atm_no_barrier_load(&num_work_found_)); } +} // namespace grpc int main(int argc, char** argv) { std::srand(std::time(nullptr)); - grpc::testing::InitTest(&argc, &argv, true); - grpc_init(); - TestPollAndWork(); - TestThreadQuota(); + grpc::testing::InitTest(&argc, &argv, true); + grpc::ThreadManagerTest test_rpc_manager; + test_rpc_manager.PerformTest(); - grpc_shutdown(); return 0; } -- cgit v1.2.3 From d6ef707422c8afba5046f395419a2a524a248472 Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 1 Aug 2018 11:22:32 -0700 Subject: Add more filter priority levels --- .../client_channel/client_channel_plugin.cc | 2 +- .../client_channel/lb_policy/grpclb/grpclb.cc | 2 +- src/core/ext/filters/deadline/deadline_filter.cc | 4 ++-- .../ext/filters/http/client_authority_filter.cc | 12 +++++----- src/core/ext/filters/http/http_filters_plugin.cc | 27 +++++++++++----------- .../load_reporting/server_load_reporting_filter.cc | 3 ++- src/core/ext/filters/max_age/max_age_filter.cc | 2 +- .../filters/message_size/message_size_filter.cc | 6 ++--- src/core/lib/channel/connected_channel.cc | 4 ++-- src/core/lib/channel/connected_channel.h | 4 ++-- src/core/lib/surface/channel_init.h | 27 +++++++++++++++++++++- src/core/lib/surface/init.cc | 26 +++++++++------------ src/core/lib/surface/init_secure.cc | 11 +++++---- src/cpp/common/channel_filter.cc | 9 ++++++-- src/cpp/common/channel_filter.h | 7 +++++- src/cpp/ext/filters/census/grpc_plugin.cc | 6 +++-- test/core/channel/minimal_stack_is_minimal_test.cc | 16 ++++++------- test/core/end2end/tests/filter_call_init_fails.cc | 15 ++++++------ test/core/end2end/tests/filter_latency.cc | 19 ++++++++------- test/core/end2end/tests/filter_status_code.cc | 19 ++++++++------- test/cpp/common/channel_filter_test.cc | 3 ++- test/cpp/end2end/filter_end2end_test.cc | 3 ++- 22 files changed, 133 insertions(+), 94 deletions(-) (limited to 'test/core') diff --git a/src/core/ext/filters/client_channel/client_channel_plugin.cc b/src/core/ext/filters/client_channel/client_channel_plugin.cc index e0784b7e5c..71da648660 100644 --- a/src/core/ext/filters/client_channel/client_channel_plugin.cc +++ b/src/core/ext/filters/client_channel/client_channel_plugin.cc @@ -56,7 +56,7 @@ void grpc_client_channel_init(void) { grpc_register_http_proxy_mapper(); grpc_subchannel_index_init(); grpc_channel_init_register_stage( - GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter, + GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, append_filter, (void*)&grpc_client_channel_filter); grpc_http_connect_register_handshaker_factory(); } diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 2d1f777474..af6f3fe296 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -1880,7 +1880,7 @@ void grpc_lb_policy_grpclb_init() { grpc_core::UniquePtr( grpc_core::New())); grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + GRPC_CHANNEL_INIT_PRIORITY_LOW, maybe_add_client_load_reporting_filter, (void*)&grpc_client_load_reporting_filter); } diff --git a/src/core/ext/filters/deadline/deadline_filter.cc b/src/core/ext/filters/deadline/deadline_filter.cc index d23ad67ad5..3bd3059312 100644 --- a/src/core/ext/filters/deadline/deadline_filter.cc +++ b/src/core/ext/filters/deadline/deadline_filter.cc @@ -379,10 +379,10 @@ static bool maybe_add_deadline_filter(grpc_channel_stack_builder* builder, void grpc_deadline_filter_init(void) { grpc_channel_init_register_stage( - GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_VERY_HIGH, maybe_add_deadline_filter, (void*)&grpc_client_deadline_filter); grpc_channel_init_register_stage( - GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_VERY_HIGH, maybe_add_deadline_filter, (void*)&grpc_server_deadline_filter); } diff --git a/src/core/ext/filters/http/client_authority_filter.cc b/src/core/ext/filters/http/client_authority_filter.cc index ddc939ed12..3c0ae47e8d 100644 --- a/src/core/ext/filters/http/client_authority_filter.cc +++ b/src/core/ext/filters/http/client_authority_filter.cc @@ -146,12 +146,12 @@ static bool add_client_authority_filter(grpc_channel_stack_builder* builder, } void grpc_client_authority_filter_init(void) { - grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX, - add_client_authority_filter, - (void*)&grpc_client_authority_filter); - grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, - add_client_authority_filter, - (void*)&grpc_client_authority_filter); + grpc_channel_init_register_stage( + GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_PRIORITY_HIGH, + add_client_authority_filter, (void*)&grpc_client_authority_filter); + grpc_channel_init_register_stage( + GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_HIGH, + add_client_authority_filter, (void*)&grpc_client_authority_filter); } void grpc_client_authority_filter_shutdown(void) {} diff --git a/src/core/ext/filters/http/http_filters_plugin.cc b/src/core/ext/filters/http/http_filters_plugin.cc index f03fa0141d..38757710f3 100644 --- a/src/core/ext/filters/http/http_filters_plugin.cc +++ b/src/core/ext/filters/http/http_filters_plugin.cc @@ -18,6 +18,7 @@ #include +#include #include #include "src/core/ext/filters/http/client/http_client_filter.h" @@ -51,15 +52,15 @@ static bool maybe_add_optional_filter(grpc_channel_stack_builder* builder, bool enable = grpc_channel_arg_get_bool( grpc_channel_args_find(channel_args, filtarg->control_channel_arg), !grpc_channel_args_want_minimal_stack(channel_args)); - return enable ? grpc_channel_stack_builder_prepend_filter( + return enable ? grpc_channel_stack_builder_append_filter( builder, filtarg->filter, nullptr, nullptr) : true; } -static bool maybe_add_required_filter(grpc_channel_stack_builder* builder, - void* arg) { +static bool maybe_append_required_filter(grpc_channel_stack_builder* builder, + void* arg) { return is_building_http_like_transport(builder) - ? grpc_channel_stack_builder_prepend_filter( + ? grpc_channel_stack_builder_append_filter( builder, static_cast(arg), nullptr, nullptr) : true; @@ -67,23 +68,23 @@ static bool maybe_add_required_filter(grpc_channel_stack_builder* builder, void grpc_http_filters_init(void) { grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + GRPC_CHANNEL_INIT_PRIORITY_HIGH, maybe_add_optional_filter, &compress_filter); grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + GRPC_CHANNEL_INIT_PRIORITY_HIGH, maybe_add_optional_filter, &compress_filter); grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + GRPC_CHANNEL_INIT_PRIORITY_HIGH, maybe_add_optional_filter, &compress_filter); grpc_channel_init_register_stage( - GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, - maybe_add_required_filter, (void*)&grpc_http_client_filter); + GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_PRIORITY_HIGH, + maybe_append_required_filter, (void*)&grpc_http_client_filter); grpc_channel_init_register_stage( - GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, - maybe_add_required_filter, (void*)&grpc_http_client_filter); + GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_HIGH, + maybe_append_required_filter, (void*)&grpc_http_client_filter); grpc_channel_init_register_stage( - GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, - maybe_add_required_filter, (void*)&grpc_http_server_filter); + GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_HIGH, + maybe_append_required_filter, (void*)&grpc_http_server_filter); } void grpc_http_filters_shutdown(void) {} diff --git a/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc b/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc index 6529046a5e..bb2bddf7cb 100644 --- a/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc +++ b/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc @@ -345,7 +345,8 @@ struct ServerLoadReportingFilterStaticRegistrar { if (registered) return; RegisterChannelFilter( - "server_load_reporting", GRPC_SERVER_CHANNEL, INT_MAX, + "server_load_reporting", GRPC_SERVER_CHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_VERY_LOW, true, MaybeAddServerLoadReportingFilter); // Access measures to ensure they are initialized. Otherwise, we can't // create any valid view before the first RPC. diff --git a/src/core/ext/filters/max_age/max_age_filter.cc b/src/core/ext/filters/max_age/max_age_filter.cc index 1fe8288bd0..7db30d5b48 100644 --- a/src/core/ext/filters/max_age/max_age_filter.cc +++ b/src/core/ext/filters/max_age/max_age_filter.cc @@ -536,7 +536,7 @@ static bool maybe_add_max_age_filter(grpc_channel_stack_builder* builder, void grpc_max_age_filter_init(void) { grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + GRPC_CHANNEL_INIT_PRIORITY_LOW, maybe_add_max_age_filter, nullptr); } diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc index c7fc3f2e62..1bd9cf1426 100644 --- a/src/core/ext/filters/message_size/message_size_filter.cc +++ b/src/core/ext/filters/message_size/message_size_filter.cc @@ -311,13 +311,13 @@ static bool maybe_add_message_size_filter(grpc_channel_stack_builder* builder, void grpc_message_size_filter_init(void) { grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + GRPC_CHANNEL_INIT_PRIORITY_LOW, maybe_add_message_size_filter, nullptr); grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + GRPC_CHANNEL_INIT_PRIORITY_LOW, maybe_add_message_size_filter, nullptr); grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + GRPC_CHANNEL_INIT_PRIORITY_LOW, maybe_add_message_size_filter, nullptr); } diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc index e2ea334ded..c78849a29b 100644 --- a/src/core/lib/channel/connected_channel.cc +++ b/src/core/lib/channel/connected_channel.cc @@ -228,8 +228,8 @@ static void bind_transport(grpc_channel_stack* channel_stack, grpc_transport_stream_size(static_cast(t)); } -bool grpc_add_connected_filter(grpc_channel_stack_builder* builder, - void* arg_must_be_null) { +bool grpc_append_connected_filter(grpc_channel_stack_builder* builder, + void* arg_must_be_null) { GPR_ASSERT(arg_must_be_null == nullptr); grpc_transport* t = grpc_channel_stack_builder_get_transport(builder); GPR_ASSERT(t != nullptr); diff --git a/src/core/lib/channel/connected_channel.h b/src/core/lib/channel/connected_channel.h index faa1c73a21..280daf040d 100644 --- a/src/core/lib/channel/connected_channel.h +++ b/src/core/lib/channel/connected_channel.h @@ -25,8 +25,8 @@ extern const grpc_channel_filter grpc_connected_filter; -bool grpc_add_connected_filter(grpc_channel_stack_builder* builder, - void* arg_must_be_null); +bool grpc_append_connected_filter(grpc_channel_stack_builder* builder, + void* arg_must_be_null); /* Debug helper to dig the transport stream out of a call element */ grpc_stream* grpc_connected_channel_get_stream(grpc_call_element* elem); diff --git a/src/core/lib/surface/channel_init.h b/src/core/lib/surface/channel_init.h index f01852473b..cae7cb4754 100644 --- a/src/core/lib/surface/channel_init.h +++ b/src/core/lib/surface/channel_init.h @@ -19,13 +19,38 @@ #ifndef GRPC_CORE_LIB_SURFACE_CHANNEL_INIT_H #define GRPC_CORE_LIB_SURFACE_CHANNEL_INIT_H +#include + #include #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/transport.h" -#define GRPC_CHANNEL_INIT_BUILTIN_PRIORITY 10000 +// Priority for channel registration functions to be used in +// grpc_channel_init_register_stage(). The priority dictates the +// order in which the registration functions run. +// +// When used to register a filter, the filter can either be appended or +// prepended, thus dictating whether the filter goes at the top or bottom of +// the stack. Higher priority functions can get closer to the top or bottom +// of the stack than lower priority functions. +enum { + // Default level. Most of filters should use this level if their location in + // the stack does not matter. + GRPC_CHANNEL_INIT_PRIORITY_LOW = 0, + // For filters that should be added after the group of filters with default + // priority, such as auth filters. + GRPC_CHANNEL_INIT_PRIORITY_MED = 10000, + // For filters that need to be close to top or bottom, such as protocol-level + // filters (client_authority, http-client, http-server) and stats (census). + GRPC_CHANNEL_INIT_PRIORITY_HIGH = 20000, + // For filters that need to be very close to the wire or surface. + GRPC_CHANNEL_INIT_PRIORITY_VERY_HIGH = 30000, + // For things that have to happen last, such as connected channel filter or + // surface server filter. Consider as reserved for gRPC internals. + GRPC_CHANNEL_INIT_PRIORITY_MAX = INT_MAX +}; /// This module provides a way for plugins (and the grpc core library itself) /// to register mutators for channel stacks. diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index 0ad82fed99..7807b261d4 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -70,11 +70,6 @@ static void do_basic_init(void) { g_initializations = 0; } -static bool append_filter(grpc_channel_stack_builder* builder, void* arg) { - return grpc_channel_stack_builder_append_filter( - builder, static_cast(arg), nullptr, nullptr); -} - static bool prepend_filter(grpc_channel_stack_builder* builder, void* arg) { return grpc_channel_stack_builder_prepend_filter( builder, static_cast(arg), nullptr, nullptr); @@ -82,19 +77,20 @@ static bool prepend_filter(grpc_channel_stack_builder* builder, void* arg) { static void register_builtin_channel_init() { grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, - grpc_add_connected_filter, nullptr); + GRPC_CHANNEL_INIT_PRIORITY_MAX, + grpc_append_connected_filter, nullptr); grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, - grpc_add_connected_filter, nullptr); + GRPC_CHANNEL_INIT_PRIORITY_MAX, + grpc_append_connected_filter, nullptr); grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, - grpc_add_connected_filter, nullptr); + GRPC_CHANNEL_INIT_PRIORITY_MAX, + grpc_append_connected_filter, nullptr); grpc_channel_init_register_stage(GRPC_CLIENT_LAME_CHANNEL, - GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, - append_filter, (void*)&grpc_lame_filter); - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, prepend_filter, - (void*)&grpc_server_top_filter); + GRPC_CHANNEL_INIT_PRIORITY_MAX, + prepend_filter, (void*)&grpc_lame_filter); + grpc_channel_init_register_stage( + GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, prepend_filter, + (void*)&grpc_server_top_filter); } typedef struct grpc_plugin { diff --git a/src/core/lib/surface/init_secure.cc b/src/core/lib/surface/init_secure.cc index 28c6f7b121..38feae22f5 100644 --- a/src/core/lib/surface/init_secure.cc +++ b/src/core/lib/surface/init_secure.cc @@ -67,14 +67,17 @@ static bool maybe_prepend_server_auth_filter( } void grpc_register_security_filters(void) { - // Register the auth client with a priority < INT_MAX to allow the authority + // Register the auth client with a low priority to allow the authority // filter -on which the auth filter depends- to be higher on the channel // stack. - grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX - 1, + grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_MED, maybe_prepend_client_auth_filter, nullptr); - grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX - 1, + grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_MED, maybe_prepend_client_auth_filter, nullptr); - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, + grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_MED, maybe_prepend_server_auth_filter, nullptr); } diff --git a/src/cpp/common/channel_filter.cc b/src/cpp/common/channel_filter.cc index 422e7bb65e..0634b0416f 100644 --- a/src/cpp/common/channel_filter.cc +++ b/src/cpp/common/channel_filter.cc @@ -78,8 +78,13 @@ bool MaybeAddFilter(grpc_channel_stack_builder* builder, void* arg) { grpc_channel_stack_builder_get_channel_arguments(builder); if (!filter.include_filter(*args)) return true; } - return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter, - nullptr, nullptr); + if (filter.prepend) { + return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter, + nullptr, nullptr); + } else { + return grpc_channel_stack_builder_append_filter(builder, &filter.filter, + nullptr, nullptr); + } } } // namespace diff --git a/src/cpp/common/channel_filter.h b/src/cpp/common/channel_filter.h index 5e569c97e6..359c72737c 100644 --- a/src/cpp/common/channel_filter.h +++ b/src/cpp/common/channel_filter.h @@ -36,7 +36,8 @@ /// \c ChannelData. Then register the filter using something like this: /// \code{.cpp} /// RegisterChannelFilter( -/// "name-of-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr); +/// "name-of-filter", GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_LOW, +/// true, nullptr); /// \endcode namespace grpc { @@ -351,6 +352,7 @@ class ChannelFilter final { struct FilterRecord { grpc_channel_stack_type stack_type; int priority; + bool prepend; std::function include_filter; grpc_channel_filter filter; }; @@ -363,12 +365,14 @@ void ChannelFilterPluginShutdown(); /// Registers a new filter. /// Must be called by only one thread at a time. +/// The \a prepend argument decides whether to prepend or append the filter. /// The \a include_filter argument specifies a function that will be called /// to determine at run-time whether or not to add the filter. If the /// value is nullptr, the filter will be added unconditionally. template void RegisterChannelFilter( const char* name, grpc_channel_stack_type stack_type, int priority, + bool prepend, std::function include_filter) { // If we haven't been called before, initialize channel_filters and // call grpc_register_plugin(). @@ -383,6 +387,7 @@ void RegisterChannelFilter( internal::FilterRecord filter_record = { stack_type, priority, + prepend, include_filter, {FilterType::StartTransportStreamOpBatch, FilterType::StartTransportOp, FilterType::call_data_size, FilterType::InitCallElement, diff --git a/src/cpp/ext/filters/census/grpc_plugin.cc b/src/cpp/ext/filters/census/grpc_plugin.cc index f978ed3bf5..f79e0e0e96 100644 --- a/src/cpp/ext/filters/census/grpc_plugin.cc +++ b/src/cpp/ext/filters/census/grpc_plugin.cc @@ -32,10 +32,12 @@ namespace grpc { void RegisterOpenCensusPlugin() { RegisterChannelFilter( - "opencensus_client", GRPC_CLIENT_CHANNEL, INT_MAX /* priority */, + "opencensus_client", GRPC_CLIENT_CHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_VERY_HIGH, true /* prepend */, nullptr /* condition function */); RegisterChannelFilter( - "opencensus_server", GRPC_SERVER_CHANNEL, INT_MAX /* priority */, + "opencensus_server", GRPC_SERVER_CHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_VERY_HIGH, true /* prepend */, nullptr /* condition function */); // Access measures to ensure they are initialized. Otherwise, creating a view diff --git a/test/core/channel/minimal_stack_is_minimal_test.cc b/test/core/channel/minimal_stack_is_minimal_test.cc index e5953acedc..5b651ed39b 100644 --- a/test/core/channel/minimal_stack_is_minimal_test.cc +++ b/test/core/channel/minimal_stack_is_minimal_test.cc @@ -85,21 +85,21 @@ int main(int argc, char** argv) { // tests with a default stack errors += - CHECK_STACK("unknown", nullptr, GRPC_CLIENT_DIRECT_CHANNEL, "authority", - "message_size", "deadline", "connected", NULL); + CHECK_STACK("unknown", nullptr, GRPC_CLIENT_DIRECT_CHANNEL, "deadline", + "authority", "message_size", "connected", NULL); errors += CHECK_STACK("unknown", nullptr, GRPC_CLIENT_SUBCHANNEL, "authority", "message_size", "connected", NULL); errors += CHECK_STACK("unknown", nullptr, GRPC_SERVER_CHANNEL, "server", - "message_size", "deadline", "connected", NULL); + "deadline", "message_size", "connected", NULL); errors += CHECK_STACK("chttp2", nullptr, GRPC_CLIENT_DIRECT_CHANNEL, - "authority", "message_size", "deadline", "http-client", - "message_compress", "connected", NULL); + "deadline", "authority", "message_size", + "message_compress", "http-client", "connected", NULL); errors += CHECK_STACK("chttp2", nullptr, GRPC_CLIENT_SUBCHANNEL, "authority", - "message_size", "http-client", "message_compress", + "message_size", "message_compress", "http-client", "connected", NULL); errors += CHECK_STACK("chttp2", nullptr, GRPC_SERVER_CHANNEL, "server", - "message_size", "deadline", "http-server", - "message_compress", "connected", NULL); + "deadline", "message_size", "message_compress", + "http-server", "connected", NULL); errors += CHECK_STACK(nullptr, nullptr, GRPC_CLIENT_CHANNEL, "client-channel", NULL); diff --git a/test/core/end2end/tests/filter_call_init_fails.cc b/test/core/end2end/tests/filter_call_init_fails.cc index ab96879fe4..07e1421446 100644 --- a/test/core/end2end/tests/filter_call_init_fails.cc +++ b/test/core/end2end/tests/filter_call_init_fails.cc @@ -438,7 +438,6 @@ static bool maybe_add_server_channel_filter(grpc_channel_stack_builder* builder, // must be the last one. So we add it right before the last one. grpc_channel_stack_builder_iterator* it = grpc_channel_stack_builder_create_iterator_at_last(builder); - GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); const bool retval = grpc_channel_stack_builder_add_filter_before( it, &test_filter, nullptr, nullptr); grpc_channel_stack_builder_iterator_destroy(it); @@ -457,7 +456,6 @@ static bool maybe_add_client_channel_filter(grpc_channel_stack_builder* builder, // must be the last one. So we add it right before the last one. grpc_channel_stack_builder_iterator* it = grpc_channel_stack_builder_create_iterator_at_last(builder); - GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); const bool retval = grpc_channel_stack_builder_add_filter_before( it, &test_filter, nullptr, nullptr); grpc_channel_stack_builder_iterator_destroy(it); @@ -476,7 +474,6 @@ static bool maybe_add_client_subchannel_filter( // must be the last one. So we add it right before the last one. grpc_channel_stack_builder_iterator* it = grpc_channel_stack_builder_create_iterator_at_last(builder); - GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); const bool retval = grpc_channel_stack_builder_add_filter_before( it, &test_filter, nullptr, nullptr); grpc_channel_stack_builder_iterator_destroy(it); @@ -487,13 +484,17 @@ static bool maybe_add_client_subchannel_filter( } static void init_plugin(void) { - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, + grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_server_channel_filter, nullptr); - grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, + grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_client_channel_filter, nullptr); - grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX, + grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_client_subchannel_filter, nullptr); - grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, + grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_client_channel_filter, nullptr); } diff --git a/test/core/end2end/tests/filter_latency.cc b/test/core/end2end/tests/filter_latency.cc index a89db7b094..02a4d07927 100644 --- a/test/core/end2end/tests/filter_latency.cc +++ b/test/core/end2end/tests/filter_latency.cc @@ -314,7 +314,6 @@ static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) { // must be the last one. So we add it right before the last one. grpc_channel_stack_builder_iterator* it = grpc_channel_stack_builder_create_iterator_at_last(builder); - GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); const bool retval = grpc_channel_stack_builder_add_filter_before( it, filter, nullptr, nullptr); grpc_channel_stack_builder_iterator_destroy(it); @@ -326,15 +325,15 @@ static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) { static void init_plugin(void) { gpr_mu_init(&g_mu); - grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, - maybe_add_filter, - (void*)&test_client_filter); - grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, - maybe_add_filter, - (void*)&test_client_filter); - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, - maybe_add_filter, - (void*)&test_server_filter); + grpc_channel_init_register_stage( + GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_filter, + (void*)&test_client_filter); + grpc_channel_init_register_stage( + GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, + maybe_add_filter, (void*)&test_client_filter); + grpc_channel_init_register_stage( + GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_filter, + (void*)&test_server_filter); } static void destroy_plugin(void) { gpr_mu_destroy(&g_mu); } diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc index ba3cbfa6d1..6ed1de15c6 100644 --- a/test/core/end2end/tests/filter_status_code.cc +++ b/test/core/end2end/tests/filter_status_code.cc @@ -333,7 +333,6 @@ static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) { // So we add it right before the last one. grpc_channel_stack_builder_iterator* it = grpc_channel_stack_builder_create_iterator_at_last(builder); - GPR_ASSERT(grpc_channel_stack_builder_move_prev(it)); const bool retval = grpc_channel_stack_builder_add_filter_before( it, filter, nullptr, nullptr); grpc_channel_stack_builder_iterator_destroy(it); @@ -350,15 +349,15 @@ static void init_plugin(void) { g_client_code_recv = false; g_server_code_recv = false; - grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, - maybe_add_filter, - (void*)&test_client_filter); - grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX, - maybe_add_filter, - (void*)&test_client_filter); - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, - maybe_add_filter, - (void*)&test_server_filter); + grpc_channel_init_register_stage( + GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_filter, + (void*)&test_client_filter); + grpc_channel_init_register_stage( + GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, + maybe_add_filter, (void*)&test_client_filter); + grpc_channel_init_register_stage( + GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, maybe_add_filter, + (void*)&test_server_filter); } static void destroy_plugin(void) { diff --git a/test/cpp/common/channel_filter_test.cc b/test/cpp/common/channel_filter_test.cc index 7bdd53f9e7..9b603ca5b4 100644 --- a/test/cpp/common/channel_filter_test.cc +++ b/test/cpp/common/channel_filter_test.cc @@ -50,7 +50,8 @@ class MyCallData : public CallData { // C-core, we don't accidentally break the C++ filter API. TEST(ChannelFilterTest, RegisterChannelFilter) { grpc::RegisterChannelFilter( - "myfilter", GRPC_CLIENT_CHANNEL, INT_MAX, nullptr); + "myfilter", GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_LOW, true, + nullptr); } // TODO(roth): When we have time, add tests for all methods of the diff --git a/test/cpp/end2end/filter_end2end_test.cc b/test/cpp/end2end/filter_end2end_test.cc index 88f8f380c3..a8022823b1 100644 --- a/test/cpp/end2end/filter_end2end_test.cc +++ b/test/cpp/end2end/filter_end2end_test.cc @@ -323,7 +323,8 @@ TEST_F(FilterEnd2endTest, SimpleBidiStreaming) { void RegisterFilter() { grpc::RegisterChannelFilter( - "test-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr); + "test-filter", GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_LOW, true, + nullptr); } } // namespace -- cgit v1.2.3 From 8c5f24cf3c00891cf061678ad0e3937d2ea7aece Mon Sep 17 00:00:00 2001 From: yang-g Date: Mon, 6 Aug 2018 10:59:15 -0700 Subject: update test --- test/core/end2end/tests/filter_causes_close.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'test/core') diff --git a/test/core/end2end/tests/filter_causes_close.cc b/test/core/end2end/tests/filter_causes_close.cc index a7f4268803..891c1b8c1f 100644 --- a/test/core/end2end/tests/filter_causes_close.cc +++ b/test/core/end2end/tests/filter_causes_close.cc @@ -261,8 +261,9 @@ static bool maybe_add_filter(grpc_channel_stack_builder* builder, void* arg) { } static void init_plugin(void) { - grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, 0, maybe_add_filter, - nullptr); + grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, + GRPC_CHANNEL_INIT_PRIORITY_HIGH, + maybe_add_filter, nullptr); } static void destroy_plugin(void) {} -- cgit v1.2.3 From f7e72560b664cce34bdf3c64b411cd6a153219ad Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Mon, 6 Aug 2018 14:46:37 -0700 Subject: Add experimental API for resetting connection backoff. --- grpc.def | 1 + include/grpc/grpc.h | 5 ++++ include/grpcpp/channel.h | 9 +++++++ .../ext/filters/client_channel/client_channel.cc | 11 ++++++++ src/core/ext/filters/client_channel/lb_policy.h | 5 +++- .../client_channel/lb_policy/grpclb/grpclb.cc | 10 ++++++++ .../lb_policy/pick_first/pick_first.cc | 8 ++++++ .../lb_policy/round_robin/round_robin.cc | 8 ++++++ .../client_channel/lb_policy/subchannel_list.h | 27 +++++++++++++++++++ src/core/ext/filters/client_channel/resolver.h | 8 ++++++ .../resolver/dns/c_ares/dns_resolver_ares.cc | 9 +++++++ .../resolver/dns/native/dns_resolver.cc | 9 +++++++ src/core/ext/filters/client_channel/subchannel.cc | 18 +++++++++++++ src/core/ext/filters/client_channel/subchannel.h | 7 +++++ src/core/lib/surface/channel.cc | 11 ++++++++ src/core/lib/transport/transport.h | 2 ++ src/cpp/client/channel_cc.cc | 8 ++++++ src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 ++ src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 +++ test/core/surface/public_headers_must_be_c89.c | 1 + test/cpp/end2end/client_lb_end2end_test.cc | 30 ++++++++++++++++++++++ 21 files changed, 191 insertions(+), 1 deletion(-) (limited to 'test/core') diff --git a/grpc.def b/grpc.def index 5b98792662..5e9d86c769 100644 --- a/grpc.def +++ b/grpc.def @@ -42,6 +42,7 @@ EXPORTS grpc_census_call_get_context grpc_channel_get_target grpc_channel_get_info + grpc_channel_reset_connect_backoff grpc_insecure_channel_create grpc_lame_client_channel_create grpc_channel_destroy diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index f0eb2c0121..bc6cd340af 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -269,6 +269,11 @@ GRPCAPI char* grpc_channel_get_target(grpc_channel* channel); GRPCAPI void grpc_channel_get_info(grpc_channel* channel, const grpc_channel_info* channel_info); +/** EXPERIMENTAL. Resets the channel's connect backoff. + TODO(roth): When we see whether this proves useful, either promote + to non-experimental or remove it. */ +GRPCAPI void grpc_channel_reset_connect_backoff(grpc_channel* channel); + /** Create a client channel to 'target'. Additional channel level configuration MAY be provided by grpc_channel_args, though the expectation is that most clients will want to simply pass NULL. The user data in 'args' need only diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h index 4b45d5382c..fed02bf7bc 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -30,6 +30,14 @@ struct grpc_channel; namespace grpc { + +namespace experimental { +/// Resets the channel's connection backoff. +/// TODO(roth): Once we see whether this proves useful, either create a gRFC +/// and change this to be a method of the Channel class, or remove it. +void ChannelResetConnectionBackoff(Channel* channel); +} // namespace experimental + /// Channels represent a connection to an endpoint. Created by \a CreateChannel. class Channel final : public ChannelInterface, public internal::CallHook, @@ -52,6 +60,7 @@ class Channel final : public ChannelInterface, private: template friend class internal::BlockingUnaryCallImpl; + friend void experimental::ChannelResetConnectionBackoff(Channel* channel); friend std::shared_ptr CreateChannelInternal( const grpc::string& host, grpc_channel* c_channel); Channel(const grpc::string& host, grpc_channel* c_channel); diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index fead8feb17..b06f09d8c7 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -622,6 +622,17 @@ static void start_transport_op_locked(void* arg, grpc_error* error_ignored) { } GRPC_ERROR_UNREF(op->disconnect_with_error); } + + if (op->reset_connect_backoff) { + if (chand->resolver != nullptr) { + chand->resolver->ResetBackoffLocked(); + chand->resolver->RequestReresolutionLocked(); + } + if (chand->lb_policy != nullptr) { + chand->lb_policy->ResetBackoffLocked(); + } + } + GRPC_CHANNEL_STACK_UNREF(chand->owning_stack, "start_transport_op"); GRPC_CLOSURE_SCHED(op->on_consumed, GRPC_ERROR_NONE); diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h index 31c08246ae..3c0a9c1118 100644 --- a/src/core/ext/filters/client_channel/lb_policy.h +++ b/src/core/ext/filters/client_channel/lb_policy.h @@ -144,7 +144,10 @@ class LoadBalancingPolicy /// consider whether this method is still needed. virtual void ExitIdleLocked() GRPC_ABSTRACT; - /// populates child_subchannels and child_channels with the uuids of this + /// Resets connection backoff. + virtual void ResetBackoffLocked() GRPC_ABSTRACT; + + /// Populates child_subchannels and child_channels with the uuids of this /// LB policy's referenced children. This is not invoked from the /// client_channel's combiner. The implementation is responsible for /// providing its own synchronization. diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 2d1f777474..cf029ef4c1 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -134,6 +134,7 @@ class GrpcLb : public LoadBalancingPolicy { grpc_error** connectivity_error) override; void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override; void ExitIdleLocked() override; + void ResetBackoffLocked() override; void FillChildRefsForChannelz(ChildRefsList* child_subchannels, ChildRefsList* child_channels) override; @@ -1214,6 +1215,15 @@ void GrpcLb::ExitIdleLocked() { } } +void GrpcLb::ResetBackoffLocked() { + if (lb_channel_ != nullptr) { + grpc_channel_reset_connect_backoff(lb_channel_); + } + if (rr_policy_ != nullptr) { + rr_policy_->ResetBackoffLocked(); + } +} + bool GrpcLb::PickLocked(PickState* pick, grpc_error** error) { PendingPick* pp = PendingPickCreate(pick); bool pick_done = false; diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 46acbf628b..2b6a9ba8c5 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -57,6 +57,7 @@ class PickFirst : public LoadBalancingPolicy { grpc_error** connectivity_error) override; void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override; void ExitIdleLocked() override; + void ResetBackoffLocked() override; void FillChildRefsForChannelz(ChildRefsList* child_subchannels, ChildRefsList* ignored) override; @@ -259,6 +260,13 @@ void PickFirst::ExitIdleLocked() { } } +void PickFirst::ResetBackoffLocked() { + subchannel_list_->ResetBackoffLocked(); + if (latest_pending_subchannel_list_ != nullptr) { + latest_pending_subchannel_list_->ResetBackoffLocked(); + } +} + bool PickFirst::PickLocked(PickState* pick, grpc_error** error) { // If we have a selected subchannel already, return synchronously. if (selected_ != nullptr) { diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index 9c3a15c67b..fea84331d8 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -68,6 +68,7 @@ class RoundRobin : public LoadBalancingPolicy { grpc_error** connectivity_error) override; void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override; void ExitIdleLocked() override; + void ResetBackoffLocked() override; void FillChildRefsForChannelz(ChildRefsList* child_subchannels, ChildRefsList* ignored) override; @@ -333,6 +334,13 @@ void RoundRobin::ExitIdleLocked() { } } +void RoundRobin::ResetBackoffLocked() { + subchannel_list_->ResetBackoffLocked(); + if (latest_pending_subchannel_list_ != nullptr) { + latest_pending_subchannel_list_->ResetBackoffLocked(); + } +} + bool RoundRobin::DoPickLocked(PickState* pick) { const size_t next_ready_index = subchannel_list_->GetNextReadySubchannelIndexLocked(); diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index 018ac3bb86..0fa2f04e73 100644 --- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -107,6 +107,11 @@ class SubchannelData { // being unreffed. virtual void UnrefSubchannelLocked(const char* reason); + // Resets the connection backoff. + // TODO(roth): This method should go away when we move the backoff + // code out of the subchannel and into the LB policies. + void ResetBackoffLocked(); + // Starts watching the connectivity state of the subchannel. // ProcessConnectivityChangeLocked() will be called when the // connectivity state changes. @@ -206,6 +211,11 @@ class SubchannelList LoadBalancingPolicy* policy() const { return policy_; } TraceFlag* tracer() const { return tracer_; } + // Resets connection backoff of all subchannels. + // TODO(roth): We will probably need to rethink this as part of moving + // the backoff code out of subchannels and into LB policies. + void ResetBackoffLocked(); + // Note: Caller must ensure that this is invoked inside of the combiner. void Orphan() override { ShutdownLocked(); @@ -298,6 +308,14 @@ void SubchannelData:: } } +template +void SubchannelData::ResetBackoffLocked() { + if (subchannel_ != nullptr) { + grpc_subchannel_reset_backoff(subchannel_); + } +} + template void SubchannelData::StartConnectivityWatchLocked() { @@ -544,6 +562,15 @@ void SubchannelList::ShutdownLocked() { } } +template +void SubchannelList::ResetBackoffLocked() { + for (size_t i = 0; i < subchannels_.size(); i++) { + SubchannelDataType* sd = &subchannels_[i]; + sd->ResetBackoffLocked(); + } +} + } // namespace grpc_core #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_SUBCHANNEL_LIST_H */ diff --git a/src/core/ext/filters/client_channel/resolver.h b/src/core/ext/filters/client_channel/resolver.h index c7e37e4468..48f2e89095 100644 --- a/src/core/ext/filters/client_channel/resolver.h +++ b/src/core/ext/filters/client_channel/resolver.h @@ -94,6 +94,14 @@ class Resolver : public InternallyRefCountedWithTracing { /// throw away unselected subchannels. virtual void RequestReresolutionLocked() GRPC_ABSTRACT; + /// Resets the re-resolution backoff, if any. + /// This needs to be implemented only by pull-based implementations; + /// for push-based implementations, it will be a no-op. + /// TODO(roth): Pull the backoff code out of resolver and into + /// client_channel, so that it can be shared across resolver + /// implementations. At that point, this method can go away. + virtual void ResetBackoffLocked() {} + void Orphan() override { // Invoke ShutdownAndUnrefLocked() inside of the combiner. GRPC_CLOSURE_SCHED( diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index 7050e82121..f2bb5f3c71 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -66,6 +66,8 @@ class AresDnsResolver : public Resolver { void RequestReresolutionLocked() override; + void ResetBackoffLocked() override; + void ShutdownLocked() override; private: @@ -187,6 +189,13 @@ void AresDnsResolver::RequestReresolutionLocked() { } } +void AresDnsResolver::ResetBackoffLocked() { + if (have_next_resolution_timer_) { + grpc_timer_cancel(&next_resolution_timer_); + } + backoff_.Reset(); +} + void AresDnsResolver::ShutdownLocked() { if (have_next_resolution_timer_) { grpc_timer_cancel(&next_resolution_timer_); diff --git a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc index fae4c33a17..282caf215c 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc @@ -58,6 +58,8 @@ class NativeDnsResolver : public Resolver { void RequestReresolutionLocked() override; + void ResetBackoffLocked() override; + void ShutdownLocked() override; private: @@ -158,6 +160,13 @@ void NativeDnsResolver::RequestReresolutionLocked() { } } +void NativeDnsResolver::ResetBackoffLocked() { + if (have_next_resolution_timer_) { + grpc_timer_cancel(&next_resolution_timer_); + } + backoff_.Reset(); +} + void NativeDnsResolver::ShutdownLocked() { if (have_next_resolution_timer_) { grpc_timer_cancel(&next_resolution_timer_); diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 71ef8c518b..48c6030c89 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -132,6 +132,8 @@ struct grpc_subchannel { bool have_alarm; /** have we started the backoff loop */ bool backoff_begun; + // reset_backoff() was called while alarm was pending + bool deferred_reset_backoff; /** our alarm */ grpc_timer alarm; @@ -438,6 +440,9 @@ static void on_alarm(void* arg, grpc_error* error) { if (c->disconnected) { error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", &error, 1); + } else if (c->deferred_reset_backoff) { + c->deferred_reset_backoff = false; + error = GRPC_ERROR_NONE; } else { GRPC_ERROR_REF(error); } @@ -675,6 +680,19 @@ static void on_subchannel_connected(void* arg, grpc_error* error) { grpc_channel_args_destroy(delete_channel_args); } +void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel) { + gpr_mu_lock(&subchannel->mu); + if (subchannel->have_alarm) { + subchannel->deferred_reset_backoff = true; + grpc_timer_cancel(&subchannel->alarm); + } else { + subchannel->backoff_begun = false; + subchannel->backoff->Reset(); + maybe_start_connecting_locked(subchannel); + } + gpr_mu_unlock(&subchannel->mu); +} + /* * grpc_subchannel_call implementation */ diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 9e53f7d542..a135035d62 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -145,6 +145,13 @@ grpc_subchannel_get_connected_subchannel(grpc_subchannel* c); const grpc_subchannel_key* grpc_subchannel_get_key( const grpc_subchannel* subchannel); +// Resets the connection backoff of the subchannel. +// TODO(roth): Move connection backoff out of subchannels and up into LB +// policy code (probably by adding a SubchannelGroup between +// SubchannelList and SubchannelData), at which point this method can +// go away. +void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel); + /** continue processing a transport op */ void grpc_subchannel_call_process_op(grpc_subchannel_call* subchannel_call, grpc_transport_stream_op_batch* op); diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 7cbd61adef..82635d3c21 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -281,6 +281,17 @@ void grpc_channel_get_info(grpc_channel* channel, elem->filter->get_channel_info(elem, channel_info); } +void grpc_channel_reset_connect_backoff(grpc_channel* channel) { + grpc_core::ExecCtx exec_ctx; + GRPC_API_TRACE("grpc_channel_reset_connect_backoff(channel=%p)", 1, + (channel)); + grpc_transport_op* op = grpc_make_transport_op(nullptr); + op->reset_connect_backoff = true; + grpc_channel_element* elem = + grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); + elem->filter->start_transport_op(elem, op); +} + static grpc_call* grpc_channel_create_call_internal( grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, grpc_completion_queue* cq, grpc_pollset_set* pollset_set_alternative, diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 585b9dfae9..9e784635c6 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -282,6 +282,8 @@ typedef struct grpc_transport_op { /** Called when the ping ack is received */ grpc_closure* on_ack; } send_ping; + // If true, will reset the channel's connection backoff. + bool reset_connect_backoff; /*************************************************************************** * remaining fields are initialized and used at the discretion of the diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index 867f31f025..39b891c2e1 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -84,6 +84,14 @@ grpc::string Channel::GetServiceConfigJSON() const { &channel_info.service_config_json); } +namespace experimental { + +void ChannelResetConnectionBackoff(Channel* channel) { + grpc_channel_reset_connect_backoff(channel->c_channel_); +} + +} // namespace experimental + internal::Call Channel::CreateCall(const internal::RpcMethod& method, ClientContext* context, CompletionQueue* cq) { diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 2443532bb8..38b68462df 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -65,6 +65,7 @@ grpc_census_call_set_context_type grpc_census_call_set_context_import; grpc_census_call_get_context_type grpc_census_call_get_context_import; grpc_channel_get_target_type grpc_channel_get_target_import; grpc_channel_get_info_type grpc_channel_get_info_import; +grpc_channel_reset_connect_backoff_type grpc_channel_reset_connect_backoff_import; grpc_insecure_channel_create_type grpc_insecure_channel_create_import; grpc_lame_client_channel_create_type grpc_lame_client_channel_create_import; grpc_channel_destroy_type grpc_channel_destroy_import; @@ -315,6 +316,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_census_call_get_context_import = (grpc_census_call_get_context_type) GetProcAddress(library, "grpc_census_call_get_context"); grpc_channel_get_target_import = (grpc_channel_get_target_type) GetProcAddress(library, "grpc_channel_get_target"); grpc_channel_get_info_import = (grpc_channel_get_info_type) GetProcAddress(library, "grpc_channel_get_info"); + grpc_channel_reset_connect_backoff_import = (grpc_channel_reset_connect_backoff_type) GetProcAddress(library, "grpc_channel_reset_connect_backoff"); grpc_insecure_channel_create_import = (grpc_insecure_channel_create_type) GetProcAddress(library, "grpc_insecure_channel_create"); grpc_lame_client_channel_create_import = (grpc_lame_client_channel_create_type) GetProcAddress(library, "grpc_lame_client_channel_create"); grpc_channel_destroy_import = (grpc_channel_destroy_type) GetProcAddress(library, "grpc_channel_destroy"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index b08a1f94f7..d6add00d12 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -170,6 +170,9 @@ extern grpc_channel_get_target_type grpc_channel_get_target_import; typedef void(*grpc_channel_get_info_type)(grpc_channel* channel, const grpc_channel_info* channel_info); extern grpc_channel_get_info_type grpc_channel_get_info_import; #define grpc_channel_get_info grpc_channel_get_info_import +typedef void(*grpc_channel_reset_connect_backoff_type)(grpc_channel* channel); +extern grpc_channel_reset_connect_backoff_type grpc_channel_reset_connect_backoff_import; +#define grpc_channel_reset_connect_backoff grpc_channel_reset_connect_backoff_import typedef grpc_channel*(*grpc_insecure_channel_create_type)(const char* target, const grpc_channel_args* args, void* reserved); extern grpc_insecure_channel_create_type grpc_insecure_channel_create_import; #define grpc_insecure_channel_create grpc_insecure_channel_create_import diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 9f4ad2b4d7..7b3e875cf0 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -104,6 +104,7 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_census_call_get_context); printf("%lx", (unsigned long) grpc_channel_get_target); printf("%lx", (unsigned long) grpc_channel_get_info); + printf("%lx", (unsigned long) grpc_channel_reset_connect_backoff); printf("%lx", (unsigned long) grpc_insecure_channel_create); printf("%lx", (unsigned long) grpc_lame_client_channel_create); printf("%lx", (unsigned long) grpc_channel_destroy); diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index c5a73a2469..7fe0da8aae 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -408,6 +408,36 @@ TEST_F(ClientLbEnd2endTest, PickFirstBackOffMinReconnect) { gpr_atm_rel_store(&g_connection_delay_ms, 0); } +TEST_F(ClientLbEnd2endTest, PickFirstResetConnectionBackoff) { + ChannelArguments args; + constexpr int kInitialBackOffMs = 1000; + args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, kInitialBackOffMs); + const std::vector ports = {grpc_pick_unused_port_or_die()}; + auto channel = BuildChannel("pick_first", args); + auto stub = BuildStub(channel); + SetNextResolution(ports); + // The channel won't become connected (there's no server). + EXPECT_FALSE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); + // Bring up a server on the chosen port. + StartServers(1, ports); + const gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); + // Wait for connect, but not long enough. This proves that we're + // being throttled by initial backoff. + EXPECT_FALSE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); + // Reset connection backoff. + experimental::ChannelResetConnectionBackoff(channel.get()); + // Wait for connect. Should happen ~immediately. + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(10))); + const gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC); + const grpc_millis waited_ms = gpr_time_to_millis(gpr_time_sub(t1, t0)); + gpr_log(GPR_DEBUG, "Waited %" PRId64 " milliseconds", waited_ms); + // We should have waited less than kInitialBackOffMs. + EXPECT_LT(waited_ms, kInitialBackOffMs); +} + TEST_F(ClientLbEnd2endTest, PickFirstUpdates) { // Start servers and send one RPC per server. const int kNumServers = 3; -- cgit v1.2.3 From bcd747d42d11c92c3d37aef8d8b45a043ff5d79c Mon Sep 17 00:00:00 2001 From: tdbhacks Date: Fri, 20 Jul 2018 16:41:44 -0700 Subject: Added system roots feature to load roots from OS trust store Added a flag-guarded feature that allows gRPC to load TLS/SSL roots from the OS trust store. This is the Linux-specific implementation of such feature. --- BUILD | 4 + CMakeLists.txt | 43 ++++++ Makefile | 54 +++++++ build.yaml | 15 ++ config.m4 | 2 + config.w32 | 2 + gRPC-C++.podspec | 2 + gRPC-Core.podspec | 6 + grpc.gemspec | 4 + grpc.gyp | 2 + package.xml | 4 + .../security_connector/load_system_roots.h | 29 ++++ .../load_system_roots_fallback.cc | 32 ++++ .../security_connector/load_system_roots_linux.cc | 165 +++++++++++++++++++++ .../security_connector/load_system_roots_linux.h | 44 ++++++ .../security_connector/security_connector.cc | 18 ++- src/python/grpcio/grpc_core_dependencies.py | 2 + test/core/security/BUILD | 25 +++- test/core/security/etc/BUILD | 22 +++ test/core/security/etc/README | 2 + test/core/security/etc/bundle.pem | 63 ++++++++ test/core/security/etc/test_roots/cert1.pem | 21 +++ test/core/security/etc/test_roots/cert2.pem | 21 +++ test/core/security/etc/test_roots/cert3.pem | 21 +++ test/core/security/linux_system_roots_test.cc | 104 +++++++++++++ test/core/security/security_connector_test.cc | 12 +- tools/doxygen/Doxyfile.core.internal | 4 + tools/run_tests/generated/sources_and_headers.json | 23 +++ tools/run_tests/generated/tests.json | 24 +++ 29 files changed, 760 insertions(+), 10 deletions(-) create mode 100644 src/core/lib/security/security_connector/load_system_roots.h create mode 100644 src/core/lib/security/security_connector/load_system_roots_fallback.cc create mode 100644 src/core/lib/security/security_connector/load_system_roots_linux.cc create mode 100644 src/core/lib/security/security_connector/load_system_roots_linux.h create mode 100644 test/core/security/etc/BUILD create mode 100644 test/core/security/etc/README create mode 100644 test/core/security/etc/bundle.pem create mode 100644 test/core/security/etc/test_roots/cert1.pem create mode 100644 test/core/security/etc/test_roots/cert2.pem create mode 100644 test/core/security/etc/test_roots/cert3.pem create mode 100644 test/core/security/linux_system_roots_test.cc (limited to 'test/core') diff --git a/BUILD b/BUILD index 81390dd1aa..35cf86288d 100644 --- a/BUILD +++ b/BUILD @@ -1499,6 +1499,8 @@ grpc_cc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.cc", "src/core/lib/security/credentials/ssl/ssl_credentials.cc", "src/core/lib/security/security_connector/alts_security_connector.cc", + "src/core/lib/security/security_connector/load_system_roots_fallback.cc", + "src/core/lib/security/security_connector/load_system_roots_linux.cc", "src/core/lib/security/security_connector/local_security_connector.cc", "src/core/lib/security/security_connector/security_connector.cc", "src/core/lib/security/transport/client_auth_filter.cc", @@ -1527,6 +1529,8 @@ grpc_cc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/security_connector/alts_security_connector.h", + "src/core/lib/security/security_connector/load_system_roots.h", + "src/core/lib/security/security_connector/load_system_roots_linux.h", "src/core/lib/security/security_connector/local_security_connector.h", "src/core/lib/security/security_connector/security_connector.h", "src/core/lib/security/transport/auth_filters.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index f242ee92bb..c4526d2af5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -581,6 +581,7 @@ add_dependencies(buildtests_cxx generic_end2end_test) add_dependencies(buildtests_cxx golden_file_test) add_dependencies(buildtests_cxx grpc_alts_credentials_options_test) add_dependencies(buildtests_cxx grpc_cli) +add_dependencies(buildtests_cxx grpc_linux_system_roots_test) add_dependencies(buildtests_cxx grpc_tool_test) add_dependencies(buildtests_cxx grpclb_api_test) add_dependencies(buildtests_cxx grpclb_end2end_test) @@ -1129,6 +1130,8 @@ add_library(grpc src/core/lib/security/credentials/plugin/plugin_credentials.cc src/core/lib/security/credentials/ssl/ssl_credentials.cc src/core/lib/security/security_connector/alts_security_connector.cc + src/core/lib/security/security_connector/load_system_roots_fallback.cc + src/core/lib/security/security_connector/load_system_roots_linux.cc src/core/lib/security/security_connector/local_security_connector.cc src/core/lib/security/security_connector/security_connector.cc src/core/lib/security/transport/client_auth_filter.cc @@ -1559,6 +1562,8 @@ add_library(grpc_cronet src/core/lib/security/credentials/plugin/plugin_credentials.cc src/core/lib/security/credentials/ssl/ssl_credentials.cc src/core/lib/security/security_connector/alts_security_connector.cc + src/core/lib/security/security_connector/load_system_roots_fallback.cc + src/core/lib/security/security_connector/load_system_roots_linux.cc src/core/lib/security/security_connector/local_security_connector.cc src/core/lib/security/security_connector/security_connector.cc src/core/lib/security/transport/client_auth_filter.cc @@ -12146,6 +12151,44 @@ if (gRPC_INSTALL) endif() endif (gRPC_BUILD_CODEGEN) +if (gRPC_BUILD_TESTS) + +add_executable(grpc_linux_system_roots_test + test/core/security/linux_system_roots_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(grpc_linux_system_roots_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(grpc_linux_system_roots_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + +endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_CODEGEN) add_executable(grpc_node_plugin diff --git a/Makefile b/Makefile index 5174ab6719..9d23de866c 100644 --- a/Makefile +++ b/Makefile @@ -1170,6 +1170,7 @@ grpc_alts_credentials_options_test: $(BINDIR)/$(CONFIG)/grpc_alts_credentials_op grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin grpc_csharp_plugin: $(BINDIR)/$(CONFIG)/grpc_csharp_plugin +grpc_linux_system_roots_test: $(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test grpc_node_plugin: $(BINDIR)/$(CONFIG)/grpc_node_plugin grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin grpc_php_plugin: $(BINDIR)/$(CONFIG)/grpc_php_plugin @@ -1670,6 +1671,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/golden_file_test \ $(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test \ $(BINDIR)/$(CONFIG)/grpc_cli \ + $(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ $(BINDIR)/$(CONFIG)/grpclb_end2end_test \ @@ -1849,6 +1851,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/golden_file_test \ $(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test \ $(BINDIR)/$(CONFIG)/grpc_cli \ + $(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ $(BINDIR)/$(CONFIG)/grpclb_end2end_test \ @@ -2316,6 +2319,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/golden_file_test || ( echo test golden_file_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_alts_credentials_options_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test || ( echo test grpc_alts_credentials_options_test failed ; exit 1 ) + $(E) "[RUN] Testing grpc_linux_system_roots_test" + $(Q) $(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test || ( echo test grpc_linux_system_roots_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_tool_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_tool_test || ( echo test grpc_tool_test failed ; exit 1 ) $(E) "[RUN] Testing grpclb_api_test" @@ -3608,6 +3613,8 @@ LIBGRPC_SRC = \ src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/security_connector/alts_security_connector.cc \ + src/core/lib/security/security_connector/load_system_roots_fallback.cc \ + src/core/lib/security/security_connector/load_system_roots_linux.cc \ src/core/lib/security/security_connector/local_security_connector.cc \ src/core/lib/security/security_connector/security_connector.cc \ src/core/lib/security/transport/client_auth_filter.cc \ @@ -4037,6 +4044,8 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/security_connector/alts_security_connector.cc \ + src/core/lib/security/security_connector/load_system_roots_fallback.cc \ + src/core/lib/security/security_connector/load_system_roots_linux.cc \ src/core/lib/security/security_connector/local_security_connector.cc \ src/core/lib/security/security_connector/security_connector.cc \ src/core/lib/security/transport/client_auth_filter.cc \ @@ -17907,6 +17916,49 @@ ifneq ($(NO_DEPS),true) endif +GRPC_LINUX_SYSTEM_ROOTS_TEST_SRC = \ + test/core/security/linux_system_roots_test.cc \ + +GRPC_LINUX_SYSTEM_ROOTS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_LINUX_SYSTEM_ROOTS_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test: $(PROTOBUF_DEP) $(GRPC_LINUX_SYSTEM_ROOTS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(GRPC_LINUX_SYSTEM_ROOTS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/core/security/linux_system_roots_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_grpc_linux_system_roots_test: $(GRPC_LINUX_SYSTEM_ROOTS_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(GRPC_LINUX_SYSTEM_ROOTS_TEST_OBJS:.o=.dep) +endif +endif + + GRPC_NODE_PLUGIN_SRC = \ src/compiler/node_plugin.cc \ @@ -24651,6 +24703,8 @@ src/core/lib/security/credentials/oauth2/oauth2_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/plugin/plugin_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/ssl/ssl_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/alts_security_connector.cc: $(OPENSSL_DEP) +src/core/lib/security/security_connector/load_system_roots_fallback.cc: $(OPENSSL_DEP) +src/core/lib/security/security_connector/load_system_roots_linux.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/local_security_connector.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/security_connector.cc: $(OPENSSL_DEP) src/core/lib/security/transport/client_auth_filter.cc: $(OPENSSL_DEP) diff --git a/build.yaml b/build.yaml index 70af96046c..bd9c4237a1 100644 --- a/build.yaml +++ b/build.yaml @@ -792,6 +792,8 @@ filegroups: - src/core/lib/security/credentials/plugin/plugin_credentials.h - src/core/lib/security/credentials/ssl/ssl_credentials.h - src/core/lib/security/security_connector/alts_security_connector.h + - src/core/lib/security/security_connector/load_system_roots.h + - src/core/lib/security/security_connector/load_system_roots_linux.h - src/core/lib/security/security_connector/local_security_connector.h - src/core/lib/security/security_connector/security_connector.h - src/core/lib/security/transport/auth_filters.h @@ -819,6 +821,8 @@ filegroups: - src/core/lib/security/credentials/plugin/plugin_credentials.cc - src/core/lib/security/credentials/ssl/ssl_credentials.cc - src/core/lib/security/security_connector/alts_security_connector.cc + - src/core/lib/security/security_connector/load_system_roots_fallback.cc + - src/core/lib/security/security_connector/load_system_roots_linux.cc - src/core/lib/security/security_connector/local_security_connector.cc - src/core/lib/security/security_connector/security_connector.cc - src/core/lib/security/transport/client_auth_filter.cc @@ -4698,6 +4702,17 @@ targets: secure: false vs_config_type: Application vs_project_guid: '{3C813052-A49A-4662-B90A-1ADBEC7EE453}' +- name: grpc_linux_system_roots_test + gtest: true + build: test + language: c++ + src: + - test/core/security/linux_system_roots_test.cc + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr - name: grpc_node_plugin build: protoc language: c++ diff --git a/config.m4 b/config.m4 index aa40a698a6..a46b076fe9 100644 --- a/config.m4 +++ b/config.m4 @@ -280,6 +280,8 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/security_connector/alts_security_connector.cc \ + src/core/lib/security/security_connector/load_system_roots_fallback.cc \ + src/core/lib/security/security_connector/load_system_roots_linux.cc \ src/core/lib/security/security_connector/local_security_connector.cc \ src/core/lib/security/security_connector/security_connector.cc \ src/core/lib/security/transport/client_auth_filter.cc \ diff --git a/config.w32 b/config.w32 index 5afa4466ac..3aea5fa7f2 100644 --- a/config.w32 +++ b/config.w32 @@ -255,6 +255,8 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\security\\credentials\\plugin\\plugin_credentials.cc " + "src\\core\\lib\\security\\credentials\\ssl\\ssl_credentials.cc " + "src\\core\\lib\\security\\security_connector\\alts_security_connector.cc " + + "src\\core\\lib\\security\\security_connector\\load_system_roots_fallback.cc " + + "src\\core\\lib\\security\\security_connector\\load_system_roots_linux.cc " + "src\\core\\lib\\security\\security_connector\\local_security_connector.cc " + "src\\core\\lib\\security\\security_connector\\security_connector.cc " + "src\\core\\lib\\security\\transport\\client_auth_filter.cc " + diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 1d9237bf62..1d3cedb16b 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -278,6 +278,8 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/security_connector/alts_security_connector.h', + 'src/core/lib/security/security_connector/load_system_roots.h', + 'src/core/lib/security/security_connector/load_system_roots_linux.h', 'src/core/lib/security/security_connector/local_security_connector.h', 'src/core/lib/security/security_connector/security_connector.h', 'src/core/lib/security/transport/auth_filters.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 5c3649afbd..1998bc8b4c 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -289,6 +289,8 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/security_connector/alts_security_connector.h', + 'src/core/lib/security/security_connector/load_system_roots.h', + 'src/core/lib/security/security_connector/load_system_roots_linux.h', 'src/core/lib/security/security_connector/local_security_connector.h', 'src/core/lib/security/security_connector/security_connector.h', 'src/core/lib/security/transport/auth_filters.h', @@ -705,6 +707,8 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/security_connector/alts_security_connector.cc', + 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', + 'src/core/lib/security/security_connector/load_system_roots_linux.cc', 'src/core/lib/security/security_connector/local_security_connector.cc', 'src/core/lib/security/security_connector/security_connector.cc', 'src/core/lib/security/transport/client_auth_filter.cc', @@ -882,6 +886,8 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/security_connector/alts_security_connector.h', + 'src/core/lib/security/security_connector/load_system_roots.h', + 'src/core/lib/security/security_connector/load_system_roots_linux.h', 'src/core/lib/security/security_connector/local_security_connector.h', 'src/core/lib/security/security_connector/security_connector.h', 'src/core/lib/security/transport/auth_filters.h', diff --git a/grpc.gemspec b/grpc.gemspec index c250316b99..55d53cb71d 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -222,6 +222,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h ) s.files += %w( src/core/lib/security/security_connector/alts_security_connector.h ) + s.files += %w( src/core/lib/security/security_connector/load_system_roots.h ) + s.files += %w( src/core/lib/security/security_connector/load_system_roots_linux.h ) s.files += %w( src/core/lib/security/security_connector/local_security_connector.h ) s.files += %w( src/core/lib/security/security_connector/security_connector.h ) s.files += %w( src/core/lib/security/transport/auth_filters.h ) @@ -642,6 +644,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.cc ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.cc ) s.files += %w( src/core/lib/security/security_connector/alts_security_connector.cc ) + s.files += %w( src/core/lib/security/security_connector/load_system_roots_fallback.cc ) + s.files += %w( src/core/lib/security/security_connector/load_system_roots_linux.cc ) s.files += %w( src/core/lib/security/security_connector/local_security_connector.cc ) s.files += %w( src/core/lib/security/security_connector/security_connector.cc ) s.files += %w( src/core/lib/security/transport/client_auth_filter.cc ) diff --git a/grpc.gyp b/grpc.gyp index 25082fe540..ba4e8185c6 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -472,6 +472,8 @@ 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/security_connector/alts_security_connector.cc', + 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', + 'src/core/lib/security/security_connector/load_system_roots_linux.cc', 'src/core/lib/security/security_connector/local_security_connector.cc', 'src/core/lib/security/security_connector/security_connector.cc', 'src/core/lib/security/transport/client_auth_filter.cc', diff --git a/package.xml b/package.xml index acdc6ffdb3..76bdd5ac8f 100644 --- a/package.xml +++ b/package.xml @@ -227,6 +227,8 @@ + + @@ -647,6 +649,8 @@ + + diff --git a/src/core/lib/security/security_connector/load_system_roots.h b/src/core/lib/security/security_connector/load_system_roots.h new file mode 100644 index 0000000000..8d4af5b2c6 --- /dev/null +++ b/src/core/lib/security/security_connector/load_system_roots.h @@ -0,0 +1,29 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_H +#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_H + +namespace grpc_core { + +// Returns a slice containing roots from the OS trust store +grpc_slice LoadSystemRootCerts(); + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_H */ \ No newline at end of file diff --git a/src/core/lib/security/security_connector/load_system_roots_fallback.cc b/src/core/lib/security/security_connector/load_system_roots_fallback.cc new file mode 100644 index 0000000000..73d1245f33 --- /dev/null +++ b/src/core/lib/security/security_connector/load_system_roots_fallback.cc @@ -0,0 +1,32 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include "src/core/lib/security/security_connector/load_system_roots.h" + +#ifndef GPR_LINUX + +namespace grpc_core { + +grpc_slice LoadSystemRootCerts() { return grpc_empty_slice(); } + +} // namespace grpc_core + +#endif /* GPR_LINUX */ diff --git a/src/core/lib/security/security_connector/load_system_roots_linux.cc b/src/core/lib/security/security_connector/load_system_roots_linux.cc new file mode 100644 index 0000000000..924fa8a3e2 --- /dev/null +++ b/src/core/lib/security/security_connector/load_system_roots_linux.cc @@ -0,0 +1,165 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include "src/core/lib/security/security_connector/load_system_roots_linux.h" + +#ifdef GPR_LINUX + +#include "src/core/lib/security/security_connector/load_system_roots.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/iomgr/load_file.h" + +namespace grpc_core { +namespace { + +const char* kLinuxCertFiles[] = { + "/etc/ssl/certs/ca-certificates.crt", "/etc/pki/tls/certs/ca-bundle.crt", + "/etc/ssl/ca-bundle.pem", "/etc/pki/tls/cacert.pem", + "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"}; +const char* kLinuxCertDirectories[] = { + "/etc/ssl/certs", "/system/etc/security/cacerts", "/usr/local/share/certs", + "/etc/pki/tls/certs", "/etc/openssl/certs"}; + +grpc_slice GetSystemRootCerts() { + grpc_slice valid_bundle_slice = grpc_empty_slice(); + size_t num_cert_files_ = GPR_ARRAY_SIZE(kLinuxCertFiles); + for (size_t i = 0; i < num_cert_files_; i++) { + grpc_error* error = + grpc_load_file(kLinuxCertFiles[i], 1, &valid_bundle_slice); + if (error == GRPC_ERROR_NONE) { + return valid_bundle_slice; + } + } + return grpc_empty_slice(); +} + +} // namespace + +void GetAbsoluteFilePath(const char* valid_file_dir, + const char* file_entry_name, char* path_buffer) { + if (valid_file_dir != nullptr && file_entry_name != nullptr) { + int path_len = snprintf(path_buffer, MAXPATHLEN, "%s/%s", valid_file_dir, + file_entry_name); + if (path_len == 0) { + gpr_log(GPR_ERROR, "failed to get absolute path for file: %s", + file_entry_name); + } + } +} + +grpc_slice CreateRootCertsBundle(const char* certs_directory) { + grpc_slice bundle_slice = grpc_empty_slice(); + if (certs_directory == nullptr) { + return bundle_slice; + } + DIR* ca_directory = opendir(certs_directory); + if (ca_directory == nullptr) { + return bundle_slice; + } + struct FileData { + char path[MAXPATHLEN]; + off_t size; + }; + InlinedVector roots_filenames; + size_t total_bundle_size = 0; + struct dirent* directory_entry; + while ((directory_entry = readdir(ca_directory)) != nullptr) { + struct stat dir_entry_stat; + const char* file_entry_name = directory_entry->d_name; + FileData file_data; + GetAbsoluteFilePath(certs_directory, file_entry_name, file_data.path); + int stat_return = stat(file_data.path, &dir_entry_stat); + if (stat_return == -1 || !S_ISREG(dir_entry_stat.st_mode)) { + // no subdirectories. + if (stat_return == -1) { + gpr_log(GPR_ERROR, "failed to get status for file: %s", file_data.path); + } + continue; + } + file_data.size = dir_entry_stat.st_size; + total_bundle_size += file_data.size; + roots_filenames.push_back(file_data); + } + closedir(ca_directory); + char* bundle_string = static_cast(gpr_zalloc(total_bundle_size + 1)); + size_t bytes_read = 0; + for (size_t i = 0; i < roots_filenames.size(); i++) { + int file_descriptor = open(roots_filenames[i].path, O_RDONLY); + if (file_descriptor != -1) { + // Read file into bundle. + size_t cert_file_size = roots_filenames[i].size; + int read_ret = + read(file_descriptor, bundle_string + bytes_read, cert_file_size); + if (read_ret != -1) { + bytes_read += read_ret; + } else { + gpr_log(GPR_ERROR, "failed to read file: %s", roots_filenames[i].path); + } + } + } + bundle_slice = grpc_slice_new(bundle_string, bytes_read, gpr_free); + return bundle_slice; +} + +grpc_slice LoadSystemRootCerts() { + grpc_slice result = grpc_empty_slice(); + // Prioritize user-specified custom directory if flag is set. + char* custom_dir = gpr_getenv("GRPC_SYSTEM_SSL_ROOTS_DIR"); + if (custom_dir != nullptr) { + result = CreateRootCertsBundle(custom_dir); + gpr_free(custom_dir); + } + // If the custom directory is empty/invalid/not specified, fallback to + // distribution-specific directory. + if (GRPC_SLICE_IS_EMPTY(result)) { + result = GetSystemRootCerts(); + } + if (GRPC_SLICE_IS_EMPTY(result)) { + for (size_t i = 0; i < GPR_ARRAY_SIZE(kLinuxCertDirectories); i++) { + result = CreateRootCertsBundle(kLinuxCertDirectories[i]); + if (!GRPC_SLICE_IS_EMPTY(result)) { + break; + } + } + } + return result; +} + +} // namespace grpc_core + +#endif /* GPR_LINUX */ diff --git a/src/core/lib/security/security_connector/load_system_roots_linux.h b/src/core/lib/security/security_connector/load_system_roots_linux.h new file mode 100644 index 0000000000..12617df492 --- /dev/null +++ b/src/core/lib/security/security_connector/load_system_roots_linux.h @@ -0,0 +1,44 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_LINUX_H +#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_LINUX_H + +#include + +#ifdef GPR_LINUX + +namespace grpc_core { + +// Creates a bundle slice containing the contents of all certificate files in +// a directory. +// Returns such slice. +// Exposed for testing purposes only. +grpc_slice CreateRootCertsBundle(const char* certs_directory); + +// Gets the absolute file path needed to load a certificate file. +// Populates path_buffer, which must be of size MAXPATHLEN. +// Exposed for testing purposes only. +void GetAbsoluteFilePath(const char* valid_file_dir, + const char* file_entry_name, char* path_buffer); + +} // namespace grpc_core + +#endif /* GPR_LINUX */ +#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_LINUX_H \ + */ diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc index 59cf3a0af1..04b4c87c71 100644 --- a/src/core/lib/security/security_connector/security_connector.cc +++ b/src/core/lib/security/security_connector/security_connector.cc @@ -21,7 +21,6 @@ #include "src/core/lib/security/security_connector/security_connector.h" #include -#include #include #include @@ -39,6 +38,7 @@ #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/security/credentials/ssl/ssl_credentials.h" +#include "src/core/lib/security/security_connector/load_system_roots.h" #include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/security/transport/security_handshaker.h" #include "src/core/lib/security/transport/target_authority_table.h" @@ -57,6 +57,12 @@ static const char* installed_roots_path = INSTALL_PREFIX "/share/grpc/roots.pem"; #endif +/** Environment variable used as a flag to enable/disable loading system root + certificates from the OS trust store. */ +#ifndef GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR +#define GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR "GRPC_USE_SYSTEM_SSL_ROOTS" +#endif + #ifndef TSI_OPENSSL_ALPN_SUPPORT #define TSI_OPENSSL_ALPN_SUPPORT 1 #endif @@ -1186,6 +1192,10 @@ const char* DefaultSslRootStore::GetPemRootCerts() { grpc_slice DefaultSslRootStore::ComputePemRootCerts() { grpc_slice result = grpc_empty_slice(); + char* use_system_roots_env_value = + gpr_getenv(GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR); + const bool use_system_roots = gpr_is_true(use_system_roots_env_value); + gpr_free(use_system_roots_env_value); // First try to load the roots from the environment. char* default_root_certs_path = gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); @@ -1207,7 +1217,11 @@ grpc_slice DefaultSslRootStore::ComputePemRootCerts() { } gpr_free(pem_root_certs); } - // Fall back to installed certs if needed. + // Try loading roots from OS trust store if flag is enabled. + if (GRPC_SLICE_IS_EMPTY(result) && use_system_roots) { + result = LoadSystemRootCerts(); + } + // Fallback to roots manually shipped with gRPC. if (GRPC_SLICE_IS_EMPTY(result) && ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { GRPC_LOG_IF_ERROR("load_file", diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index d6efb49750..a8158311fb 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -254,6 +254,8 @@ CORE_SOURCE_FILES = [ 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', 'src/core/lib/security/security_connector/alts_security_connector.cc', + 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', + 'src/core/lib/security/security_connector/load_system_roots_linux.cc', 'src/core/lib/security/security_connector/local_security_connector.cc', 'src/core/lib/security/security_connector/security_connector.cc', 'src/core/lib/security/transport/client_auth_filter.cc', diff --git a/test/core/security/BUILD b/test/core/security/BUILD index 12aa84d93b..b7de955cdb 100644 --- a/test/core/security/BUILD +++ b/test/core/security/BUILD @@ -128,6 +128,27 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "linux_system_roots_test", + srcs = ["linux_system_roots_test.cc"], + data = [ + "//test/core/security/etc:bundle.pem", + "//test/core/security/etc:test_roots/cert1.pem", + "//test/core/security/etc:test_roots/cert2.pem", + "//test/core/security/etc:test_roots/cert3.pem", + ], + language = "C++", + external_deps = [ + "gtest", + ], + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + grpc_cc_test( name = "ssl_credentials_test", srcs = ["ssl_credentials_test.cc"], @@ -219,9 +240,9 @@ grpc_cc_test( deps = [ "//:gpr", "//:grpc", - "//:grpc_base_c", + "//:grpc_base_c", "//:grpc_secure", - "//:tsi", + "//:tsi", "//:tsi_interface", "//test/core/util:gpr_test_util", ], diff --git a/test/core/security/etc/BUILD b/test/core/security/etc/BUILD new file mode 100644 index 0000000000..2c6ab64a3b --- /dev/null +++ b/test/core/security/etc/BUILD @@ -0,0 +1,22 @@ +# Copyright 2018 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +licenses(["notice"]) # Apache v2 + +exports_files([ + "bundle.pem", + "test_roots/cert1.pem", + "test_roots/cert2.pem", + "test_roots/cert3.pem", +]) diff --git a/test/core/security/etc/README b/test/core/security/etc/README new file mode 100644 index 0000000000..6ba4382586 --- /dev/null +++ b/test/core/security/etc/README @@ -0,0 +1,2 @@ +These files are manual copies of a pem cert from the /etc/ssl/certs/ directory. +They serve only as dummy certificate test files. diff --git a/test/core/security/etc/bundle.pem b/test/core/security/etc/bundle.pem new file mode 100644 index 0000000000..07d7672f83 --- /dev/null +++ b/test/core/security/etc/bundle.pem @@ -0,0 +1,63 @@ +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- diff --git a/test/core/security/etc/test_roots/cert1.pem b/test/core/security/etc/test_roots/cert1.pem new file mode 100644 index 0000000000..988cc68aac --- /dev/null +++ b/test/core/security/etc/test_roots/cert1.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- diff --git a/test/core/security/etc/test_roots/cert2.pem b/test/core/security/etc/test_roots/cert2.pem new file mode 100644 index 0000000000..988cc68aac --- /dev/null +++ b/test/core/security/etc/test_roots/cert2.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- diff --git a/test/core/security/etc/test_roots/cert3.pem b/test/core/security/etc/test_roots/cert3.pem new file mode 100644 index 0000000000..988cc68aac --- /dev/null +++ b/test/core/security/etc/test_roots/cert3.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- diff --git a/test/core/security/linux_system_roots_test.cc b/test/core/security/linux_system_roots_test.cc new file mode 100644 index 0000000000..fce9c8dcc5 --- /dev/null +++ b/test/core/security/linux_system_roots_test.cc @@ -0,0 +1,104 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#ifdef GPR_LINUX +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/tmpfile.h" +#include "src/core/lib/iomgr/load_file.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/security_connector/load_system_roots.h" +#include "src/core/lib/security/security_connector/load_system_roots_linux.h" +#include "src/core/lib/security/security_connector/security_connector.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "src/core/tsi/transport_security.h" +#include "test/core/util/test_config.h" + +#include "gtest/gtest.h" + +#ifndef GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR +#define GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR "GRPC_USE_SYSTEM_SSL_ROOTS" +#endif + +namespace grpc { +namespace { + +TEST(AbsoluteFilePathTest, ConcatenatesCorrectly) { + const char* directory = "nonexistent/test/directory"; + const char* filename = "doesnotexist.txt"; + char result_path[MAXPATHLEN]; + grpc_core::GetAbsoluteFilePath(directory, filename, result_path); + EXPECT_STREQ(result_path, "nonexistent/test/directory/doesnotexist.txt"); +} + +TEST(CreateRootCertsBundleTest, ReturnsEmpty) { + // Test that CreateRootCertsBundle returns an empty slice for null or + // nonexistent cert directories. + grpc_slice result_slice = grpc_core::CreateRootCertsBundle(nullptr); + EXPECT_TRUE(GRPC_SLICE_IS_EMPTY(result_slice)); + grpc_slice_unref(result_slice); + result_slice = grpc_core::CreateRootCertsBundle("does/not/exist"); + EXPECT_TRUE(GRPC_SLICE_IS_EMPTY(result_slice)); + grpc_slice_unref(result_slice); +} + +TEST(CreateRootCertsBundleTest, BundlesCorrectly) { + gpr_setenv(GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR, "true"); + // Test that CreateRootCertsBundle returns a correct slice. + grpc_slice roots_bundle = grpc_empty_slice(); + GRPC_LOG_IF_ERROR( + "load_file", + grpc_load_file("test/core/security/etc/bundle.pem", 1, &roots_bundle)); + // result_slice should have the same content as roots_bundle. + grpc_slice result_slice = + grpc_core::CreateRootCertsBundle("test/core/security/etc/test_roots"); + char* result_str = grpc_slice_to_c_string(result_slice); + char* bundle_str = grpc_slice_to_c_string(roots_bundle); + EXPECT_STREQ(result_str, bundle_str); + // Clean up. + unsetenv(GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR); + gpr_free(result_str); + gpr_free(bundle_str); + grpc_slice_unref(roots_bundle); + grpc_slice_unref(result_slice); +} + +} // namespace +} // namespace grpc + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} +#else +int main() { + printf("*** WARNING: this test is only supported on Linux systems ***\n"); + return 0; +} +#endif // GPR_LINUX diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc index e4c3ace6b4..82d77eef8b 100644 --- a/test/core/security/security_connector_test.cc +++ b/test/core/security/security_connector_test.cc @@ -363,7 +363,7 @@ static void test_ipv6_address_san(void) { namespace grpc_core { namespace { -class TestDefafaultSllRootStore : public DefaultSslRootStore { +class TestDefaultSslRootStore : public DefaultSslRootStore { public: static grpc_slice ComputePemRootCertsForTesting() { return ComputePemRootCerts(); @@ -389,7 +389,7 @@ static void test_default_ssl_roots(void) { gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, ""); grpc_set_ssl_roots_override_callback(override_roots_success); grpc_slice roots = - grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting(); + grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting(); char* roots_contents = grpc_slice_to_c_string(roots); grpc_slice_unref(roots); GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); @@ -398,7 +398,7 @@ static void test_default_ssl_roots(void) { /* Now let's set the env var: We should get the contents pointed value instead. */ gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_env_var_file_path); - roots = grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting(); + roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting(); roots_contents = grpc_slice_to_c_string(roots); grpc_slice_unref(roots); GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0); @@ -407,7 +407,7 @@ static void test_default_ssl_roots(void) { /* Now reset the env var. We should fall back to the value overridden using the api. */ gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, ""); - roots = grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting(); + roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting(); roots_contents = grpc_slice_to_c_string(roots); grpc_slice_unref(roots); GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); @@ -416,10 +416,10 @@ static void test_default_ssl_roots(void) { /* Now setup a permanent failure for the overridden roots and we should get an empty slice. */ grpc_set_ssl_roots_override_callback(override_roots_permanent_failure); - roots = grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting(); + roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting(); GPR_ASSERT(GRPC_SLICE_IS_EMPTY(roots)); const tsi_ssl_root_certs_store* root_store = - grpc_core::TestDefafaultSllRootStore::GetRootStore(); + grpc_core::TestDefaultSslRootStore::GetRootStore(); GPR_ASSERT(root_store == nullptr); /* Cleanup. */ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 18f56984fe..ff76d5a1b4 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1355,6 +1355,10 @@ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.h \ src/core/lib/security/security_connector/alts_security_connector.cc \ src/core/lib/security/security_connector/alts_security_connector.h \ +src/core/lib/security/security_connector/load_system_roots.h \ +src/core/lib/security/security_connector/load_system_roots_fallback.cc \ +src/core/lib/security/security_connector/load_system_roots_linux.cc \ +src/core/lib/security/security_connector/load_system_roots_linux.h \ src/core/lib/security/security_connector/local_security_connector.cc \ src/core/lib/security/security_connector/local_security_connector.h \ src/core/lib/security/security_connector/security_connector.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index a686dae8b4..34e23f09c2 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -3707,6 +3707,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "grpc_linux_system_roots_test", + "src": [ + "test/core/security/linux_system_roots_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "grpc_plugin_support" @@ -10358,6 +10375,8 @@ "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/security_connector/alts_security_connector.h", + "src/core/lib/security/security_connector/load_system_roots.h", + "src/core/lib/security/security_connector/load_system_roots_linux.h", "src/core/lib/security/security_connector/local_security_connector.h", "src/core/lib/security/security_connector/security_connector.h", "src/core/lib/security/transport/auth_filters.h", @@ -10406,6 +10425,10 @@ "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/security_connector/alts_security_connector.cc", "src/core/lib/security/security_connector/alts_security_connector.h", + "src/core/lib/security/security_connector/load_system_roots.h", + "src/core/lib/security/security_connector/load_system_roots_fallback.cc", + "src/core/lib/security/security_connector/load_system_roots_linux.cc", + "src/core/lib/security/security_connector/load_system_roots_linux.h", "src/core/lib/security/security_connector/local_security_connector.cc", "src/core/lib/security/security_connector/local_security_connector.h", "src/core/lib/security/security_connector/security_connector.cc", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index cf3b54e044..de64097ec1 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -4333,6 +4333,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "grpc_linux_system_roots_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, -- cgit v1.2.3