From 7cb0290d9cec348eb0dde9c6661d78b77ac7b0f6 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Thu, 6 Dec 2018 07:41:58 -0800 Subject: Fix off by one error in channelz --- src/core/lib/channel/channelz.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/core/lib/channel/channelz.cc') diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 8d589f5983..0802143fbe 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -208,11 +208,7 @@ char* ServerNode::RenderServerSockets(intptr_t start_socket_id) { grpc_json* json = top_level_json; grpc_json* json_iterator = nullptr; ChildRefsList socket_refs; - // uuids index into entities one-off (idx 0 is really uuid 1, since 0 is - // reserved). However, we want to support requests coming in with - // start_server_id=0, which signifies "give me everything." - size_t start_idx = start_socket_id == 0 ? 0 : start_socket_id - 1; - grpc_server_populate_server_sockets(server_, &socket_refs, start_idx); + grpc_server_populate_server_sockets(server_, &socket_refs, start_socket_id); if (!socket_refs.empty()) { // create list of socket refs grpc_json* array_parent = grpc_json_create_child( -- cgit v1.2.3 From d7c252c9473a2a97eb441369603d8cc9ad64403c Mon Sep 17 00:00:00 2001 From: ncteisen Date: Thu, 6 Dec 2018 16:53:24 -0800 Subject: Surface socket name --- src/core/ext/filters/client_channel/connector.h | 5 +++-- src/core/ext/filters/client_channel/subchannel.cc | 4 +++- src/core/ext/transport/chttp2/client/chttp2_connector.cc | 4 ++-- src/core/ext/transport/chttp2/server/chttp2_server.cc | 2 +- .../ext/transport/chttp2/transport/chttp2_transport.cc | 9 +++------ src/core/ext/transport/chttp2/transport/chttp2_transport.h | 4 +++- src/core/lib/channel/channelz.cc | 10 ++++++---- src/core/lib/channel/channelz.h | 5 +++++ src/core/lib/surface/server.cc | 14 +++++++------- src/core/lib/surface/server.h | 4 ++-- 10 files changed, 35 insertions(+), 26 deletions(-) (limited to 'src/core/lib/channel/channelz.cc') diff --git a/src/core/ext/filters/client_channel/connector.h b/src/core/ext/filters/client_channel/connector.h index ea34dcdab5..484cc1b3c3 100644 --- a/src/core/ext/filters/client_channel/connector.h +++ b/src/core/ext/filters/client_channel/connector.h @@ -22,6 +22,7 @@ #include #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/transport/transport.h" @@ -48,8 +49,8 @@ typedef struct { /** channel arguments (to be passed to the filters) */ grpc_channel_args* channel_args; - /** socket uuid of the connected transport. 0 if not available */ - intptr_t socket_uuid; + /** socket node of the connected transport */ + grpc_core::channelz::SocketNode* socket_node; } grpc_connect_out_args; struct grpc_connector_vtable { diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 0817b1dd39..e66b0711cf 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -826,7 +826,9 @@ static bool publish_transport_locked(grpc_subchannel* c) { GRPC_ERROR_UNREF(error); return false; } - intptr_t socket_uuid = c->connecting_result.socket_uuid; + intptr_t socket_uuid = c->connecting_result.socket_node == nullptr + ? 0 + : c->connecting_result.socket_node->uuid(); memset(&c->connecting_result, 0, sizeof(c->connecting_result)); if (c->disconnected) { diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/src/core/ext/transport/chttp2/client/chttp2_connector.cc index 60a32022f5..62a07d2ba6 100644 --- a/src/core/ext/transport/chttp2/client/chttp2_connector.cc +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.cc @@ -117,8 +117,8 @@ static void on_handshake_done(void* arg, grpc_error* error) { c->args.interested_parties); c->result->transport = grpc_create_chttp2_transport(args->args, args->endpoint, true); - c->result->socket_uuid = - grpc_chttp2_transport_get_socket_uuid(c->result->transport); + c->result->socket_node = + grpc_chttp2_transport_get_socket_node(c->result->transport); GPR_ASSERT(c->result->transport); // TODO(roth): We ideally want to wait until we receive HTTP/2 // settings from the server before we consider the connection diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.cc b/src/core/ext/transport/chttp2/server/chttp2_server.cc index 33d2b22aa5..3d09187b9b 100644 --- a/src/core/ext/transport/chttp2/server/chttp2_server.cc +++ b/src/core/ext/transport/chttp2/server/chttp2_server.cc @@ -149,7 +149,7 @@ static void on_handshake_done(void* arg, grpc_error* error) { grpc_server_setup_transport( connection_state->svr_state->server, transport, connection_state->accepting_pollset, args->args, - grpc_chttp2_transport_get_socket_uuid(transport), resource_user); + grpc_chttp2_transport_get_socket_node(transport), resource_user); // Use notify_on_receive_settings callback to enforce the // handshake deadline. connection_state->transport = diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 7377287e8c..73e43131a0 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -3145,14 +3145,11 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream), static const grpc_transport_vtable* get_vtable(void) { return &vtable; } -intptr_t grpc_chttp2_transport_get_socket_uuid(grpc_transport* transport) { +grpc_core::channelz::SocketNode* grpc_chttp2_transport_get_socket_node( + grpc_transport* transport) { grpc_chttp2_transport* t = reinterpret_cast(transport); - if (t->channelz_socket != nullptr) { - return t->channelz_socket->uuid(); - } else { - return 0; - } + return t->channelz_socket.get(); } grpc_transport* grpc_create_chttp2_transport( diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.h b/src/core/ext/transport/chttp2/transport/chttp2_transport.h index b3fe1c082e..b9929b1662 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.h +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.h @@ -21,6 +21,7 @@ #include +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/transport/transport.h" @@ -35,7 +36,8 @@ grpc_transport* grpc_create_chttp2_transport( const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client, grpc_resource_user* resource_user = nullptr); -intptr_t grpc_chttp2_transport_get_socket_uuid(grpc_transport* transport); +grpc_core::channelz::SocketNode* grpc_chttp2_transport_get_socket_node( + grpc_transport* transport); /// Takes ownership of \a read_buffer, which (if non-NULL) contains /// leftover bytes previously read from the endpoint (e.g., by handshakers). diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 0802143fbe..0cb2890518 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -207,18 +207,20 @@ char* ServerNode::RenderServerSockets(intptr_t start_socket_id) { grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; grpc_json* json_iterator = nullptr; - ChildRefsList socket_refs; + ChildSocketsList socket_refs; grpc_server_populate_server_sockets(server_, &socket_refs, start_socket_id); if (!socket_refs.empty()) { // create list of socket refs grpc_json* array_parent = grpc_json_create_child( nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); for (size_t i = 0; i < socket_refs.size(); ++i) { - json_iterator = + grpc_json* socket_ref_json = grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, GRPC_JSON_OBJECT, false); - grpc_json_add_number_string_child(json_iterator, nullptr, "socketId", - socket_refs[i]); + json_iterator = grpc_json_add_number_string_child( + socket_ref_json, nullptr, "socketId", socket_refs[i]->uuid()); + grpc_json_create_child(json_iterator, socket_ref_json, "name", + socket_refs[i]->remote(), GRPC_JSON_STRING, false); } } // For now we do not have any pagination rules. In the future we could diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 64ab5cb3a6..96a4333083 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -59,6 +59,9 @@ namespace channelz { // add human readable names as in the channelz.proto typedef InlinedVector ChildRefsList; +class SocketNode; +typedef InlinedVector ChildSocketsList; + namespace testing { class CallCountingHelperPeer; class ChannelNodePeer; @@ -251,6 +254,8 @@ class SocketNode : public BaseNode { gpr_atm_no_barrier_fetch_add(&keepalives_sent_, static_cast(1)); } + const char* remote() { return remote_.get(); } + private: gpr_atm streams_started_ = 0; gpr_atm streams_succeeded_ = 0; diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index 1f66be240e..4c63b6bc39 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -109,7 +109,7 @@ struct channel_data { uint32_t registered_method_max_probes; grpc_closure finish_destroy_channel_closure; grpc_closure channel_connectivity_changed; - intptr_t socket_uuid; + grpc_core::channelz::SocketNode* socket_node; }; typedef struct shutdown_tag { @@ -1158,7 +1158,7 @@ void grpc_server_get_pollsets(grpc_server* server, grpc_pollset*** pollsets, void grpc_server_setup_transport(grpc_server* s, grpc_transport* transport, grpc_pollset* accepting_pollset, const grpc_channel_args* args, - intptr_t socket_uuid, + grpc_core::channelz::SocketNode* socket_node, grpc_resource_user* resource_user) { size_t num_registered_methods; size_t alloc; @@ -1180,7 +1180,7 @@ void grpc_server_setup_transport(grpc_server* s, grpc_transport* transport, chand->server = s; server_ref(s); chand->channel = channel; - chand->socket_uuid = socket_uuid; + chand->socket_node = socket_node; size_t cq_idx; for (cq_idx = 0; cq_idx < s->cq_count; cq_idx++) { @@ -1256,14 +1256,14 @@ void grpc_server_setup_transport(grpc_server* s, grpc_transport* transport, } void grpc_server_populate_server_sockets( - grpc_server* s, grpc_core::channelz::ChildRefsList* server_sockets, + grpc_server* s, grpc_core::channelz::ChildSocketsList* server_sockets, intptr_t start_idx) { gpr_mu_lock(&s->mu_global); channel_data* c = nullptr; for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) { - intptr_t socket_uuid = c->socket_uuid; - if (socket_uuid >= start_idx) { - server_sockets->push_back(socket_uuid); + grpc_core::channelz::SocketNode* socket_node = c->socket_node; + if (socket_node && socket_node->uuid() >= start_idx) { + server_sockets->push_back(socket_node); } } gpr_mu_unlock(&s->mu_global); diff --git a/src/core/lib/surface/server.h b/src/core/lib/surface/server.h index 27038fdb7a..8e8903d76b 100644 --- a/src/core/lib/surface/server.h +++ b/src/core/lib/surface/server.h @@ -47,12 +47,12 @@ void grpc_server_add_listener(grpc_server* server, void* listener, void grpc_server_setup_transport(grpc_server* server, grpc_transport* transport, grpc_pollset* accepting_pollset, const grpc_channel_args* args, - intptr_t socket_uuid, + grpc_core::channelz::SocketNode* socket_node, grpc_resource_user* resource_user = nullptr); /* fills in the uuids of all sockets used for connections on this server */ void grpc_server_populate_server_sockets( - grpc_server* server, grpc_core::channelz::ChildRefsList* server_sockets, + grpc_server* server, grpc_core::channelz::ChildSocketsList* server_sockets, intptr_t start_idx); /* fills in the uuids of all listen sockets on this server */ -- cgit v1.2.3 From f52e54235294cb71c09d880e8f78a6661b2803f2 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 10 Dec 2018 12:45:00 -0800 Subject: Add pagination to serversockets --- src/core/lib/channel/channelz.cc | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/core/lib/channel/channelz.cc') diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 0cb2890518..8d449ee672 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -204,16 +204,27 @@ ServerNode::ServerNode(grpc_server* server, size_t channel_tracer_max_nodes) ServerNode::~ServerNode() {} char* ServerNode::RenderServerSockets(intptr_t start_socket_id) { + const int kPaginationLimit = 100; grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; grpc_json* json_iterator = nullptr; ChildSocketsList socket_refs; grpc_server_populate_server_sockets(server_, &socket_refs, start_socket_id); + int sockets_added = 0; + bool reached_pagination_limit = false; if (!socket_refs.empty()) { // create list of socket refs grpc_json* array_parent = grpc_json_create_child( nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); for (size_t i = 0; i < socket_refs.size(); ++i) { + // check if we are over pagination limit to determine if we need to set + // the "end" element. If we don't go through this block, we know that + // when the loop terminates, we have <= to kPaginationLimit. + if (sockets_added == kPaginationLimit) { + reached_pagination_limit = true; + break; + } + sockets_added++; grpc_json* socket_ref_json = grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, GRPC_JSON_OBJECT, false); @@ -223,11 +234,10 @@ char* ServerNode::RenderServerSockets(intptr_t start_socket_id) { socket_refs[i]->remote(), GRPC_JSON_STRING, false); } } - // For now we do not have any pagination rules. In the future we could - // pick a constant for max_channels_sent for a GetServers request. - // Tracking: https://github.com/grpc/grpc/issues/16019. - json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr, - GRPC_JSON_TRUE, false); + if (!reached_pagination_limit) { + 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; -- cgit v1.2.3 From 7b1fc0faa23b2cc1807450498b8c69afb079c2d2 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Dec 2018 08:22:51 -0800 Subject: Add max_results to ServerSockets --- include/grpc/grpc.h | 3 ++- src/core/lib/channel/channelz.cc | 10 ++++++---- src/core/lib/channel/channelz.h | 3 ++- src/core/lib/channel/channelz_registry.cc | 5 +++-- src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi | 8 +++++--- src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi | 3 ++- src/python/grpcio_channelz/grpc_channelz/v1/channelz.py | 3 ++- src/ruby/ext/grpc/rb_grpc_imports.generated.h | 2 +- test/core/end2end/tests/channelz.cc | 2 +- 9 files changed, 24 insertions(+), 15 deletions(-) (limited to 'src/core/lib/channel/channelz.cc') diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index d3b74cabab..fec7f5269e 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -511,7 +511,8 @@ GRPCAPI char* grpc_channelz_get_server(intptr_t server_id); /* Gets all server sockets that exist in the server. */ GRPCAPI char* grpc_channelz_get_server_sockets(intptr_t server_id, - intptr_t start_socket_id); + intptr_t start_socket_id, + intptr_t max_results); /* Returns a single Channel, or else a NOT_FOUND code. The returned string is allocated and must be freed by the application. */ diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 8d449ee672..3fcfa2a412 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -203,8 +203,10 @@ ServerNode::ServerNode(grpc_server* server, size_t channel_tracer_max_nodes) ServerNode::~ServerNode() {} -char* ServerNode::RenderServerSockets(intptr_t start_socket_id) { - const int kPaginationLimit = 100; +char* ServerNode::RenderServerSockets(intptr_t start_socket_id, + intptr_t max_results) { + // if user does not set max_results, we choose 500. + int pagination_limit = max_results == 0 ? 500 : max_results; grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; grpc_json* json_iterator = nullptr; @@ -219,8 +221,8 @@ char* ServerNode::RenderServerSockets(intptr_t start_socket_id) { for (size_t i = 0; i < socket_refs.size(); ++i) { // check if we are over pagination limit to determine if we need to set // the "end" element. If we don't go through this block, we know that - // when the loop terminates, we have <= to kPaginationLimit. - if (sockets_added == kPaginationLimit) { + // when the loop terminates, we have <= to pagination_limit. + if (sockets_added == pagination_limit) { reached_pagination_limit = true; break; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 96a4333083..e43792126f 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -210,7 +210,8 @@ class ServerNode : public BaseNode { grpc_json* RenderJson() override; - char* RenderServerSockets(intptr_t start_socket_id); + char* RenderServerSockets(intptr_t start_socket_id, + intptr_t pagination_limit); // proxy methods to composed classes. void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index bc23b90a66..7cca247d64 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -252,7 +252,8 @@ char* grpc_channelz_get_server(intptr_t server_id) { } char* grpc_channelz_get_server_sockets(intptr_t server_id, - intptr_t start_socket_id) { + intptr_t start_socket_id, + intptr_t max_results) { grpc_core::channelz::BaseNode* base_node = grpc_core::channelz::ChannelzRegistry::Get(server_id); if (base_node == nullptr || @@ -263,7 +264,7 @@ char* grpc_channelz_get_server_sockets(intptr_t server_id, // actually a server node grpc_core::channelz::ServerNode* server_node = static_cast(base_node); - return server_node->RenderServerSockets(start_socket_id); + return server_node->RenderServerSockets(start_socket_id, max_results); } char* grpc_channelz_get_channel(intptr_t channel_id) { diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi index 113f7976dd..36c8cd121c 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/channelz.pyx.pxi @@ -36,15 +36,17 @@ def channelz_get_server(server_id): ' server_id==%s is valid' % server_id) return c_returned_str -def channelz_get_server_sockets(server_id, start_socket_id): +def channelz_get_server_sockets(server_id, start_socket_id, max_results): cdef char *c_returned_str = grpc_channelz_get_server_sockets( server_id, start_socket_id, + max_results, ) if c_returned_str == NULL: raise ValueError('Failed to get server sockets, please ensure your' \ - ' server_id==%s and start_socket_id==%s is valid' % - (server_id, start_socket_id)) + ' server_id==%s and start_socket_id==%s and' \ + ' max_results==%s is valid' % + (server_id, start_socket_id, max_results)) return c_returned_str def channelz_get_channel(channel_id): diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index 5bbc10af25..fc7a9ba439 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -389,7 +389,8 @@ cdef extern from "grpc/grpc.h": char* grpc_channelz_get_servers(intptr_t start_server_id) char* grpc_channelz_get_server(intptr_t server_id) char* grpc_channelz_get_server_sockets(intptr_t server_id, - intptr_t start_socket_id) + intptr_t start_socket_id, + intptr_t max_results) char* grpc_channelz_get_channel(intptr_t channel_id) char* grpc_channelz_get_subchannel(intptr_t subchannel_id) char* grpc_channelz_get_socket(intptr_t socket_id) diff --git a/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py b/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py index 573b9d0d5a..00eca311dc 100644 --- a/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py +++ b/src/python/grpcio_channelz/grpc_channelz/v1/channelz.py @@ -66,7 +66,8 @@ class ChannelzServicer(_channelz_pb2_grpc.ChannelzServicer): try: return json_format.Parse( cygrpc.channelz_get_server_sockets(request.server_id, - request.start_socket_id), + request.start_socket_id, + request.max_results), _channelz_pb2.GetServerSocketsResponse(), ) except ValueError as e: diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 56d222c7ec..e61a35d09f 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -272,7 +272,7 @@ extern grpc_channelz_get_servers_type grpc_channelz_get_servers_import; typedef char*(*grpc_channelz_get_server_type)(intptr_t server_id); extern grpc_channelz_get_server_type grpc_channelz_get_server_import; #define grpc_channelz_get_server grpc_channelz_get_server_import -typedef char*(*grpc_channelz_get_server_sockets_type)(intptr_t server_id, intptr_t start_socket_id); +typedef char*(*grpc_channelz_get_server_sockets_type)(intptr_t server_id, intptr_t start_socket_id, intptr_t max_results); extern grpc_channelz_get_server_sockets_type grpc_channelz_get_server_sockets_import; #define grpc_channelz_get_server_sockets grpc_channelz_get_server_sockets_import typedef char*(*grpc_channelz_get_channel_type)(intptr_t channel_id); diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 49a0bc8011..169190eec0 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -259,7 +259,7 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); - json = channelz_server->RenderServerSockets(0); + json = channelz_server->RenderServerSockets(0, 100); GPR_ASSERT(nullptr != strstr(json, "\"end\":true")); gpr_free(json); -- cgit v1.2.3 From a6ed43b41fec1201c3d239ee2910aac65cba9d90 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Dec 2018 10:27:11 -0800 Subject: reviewer feedback --- src/core/lib/channel/channelz.cc | 20 ++++++-------------- src/proto/grpc/channelz/channelz.proto | 2 +- 2 files changed, 7 insertions(+), 15 deletions(-) (limited to 'src/core/lib/channel/channelz.cc') diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 3fcfa2a412..10d5e1b581 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -205,28 +205,20 @@ ServerNode::~ServerNode() {} char* ServerNode::RenderServerSockets(intptr_t start_socket_id, intptr_t max_results) { - // if user does not set max_results, we choose 500. - int pagination_limit = max_results == 0 ? 500 : max_results; + // if user does not set max_results, we choose 1000. + size_t pagination_limit = max_results == 0 ? 500 : max_results; grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; grpc_json* json_iterator = nullptr; ChildSocketsList socket_refs; grpc_server_populate_server_sockets(server_, &socket_refs, start_socket_id); - int sockets_added = 0; - bool reached_pagination_limit = false; + // declared early so it can be used outside of the loop. + size_t i = 0; if (!socket_refs.empty()) { // create list of socket refs grpc_json* array_parent = grpc_json_create_child( nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); - for (size_t i = 0; i < socket_refs.size(); ++i) { - // check if we are over pagination limit to determine if we need to set - // the "end" element. If we don't go through this block, we know that - // when the loop terminates, we have <= to pagination_limit. - if (sockets_added == pagination_limit) { - reached_pagination_limit = true; - break; - } - sockets_added++; + for (i = 0; i < GPR_MIN(socket_refs.size(), pagination_limit); ++i) { grpc_json* socket_ref_json = grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, GRPC_JSON_OBJECT, false); @@ -236,7 +228,7 @@ char* ServerNode::RenderServerSockets(intptr_t start_socket_id, socket_refs[i]->remote(), GRPC_JSON_STRING, false); } } - if (!reached_pagination_limit) { + if (i == socket_refs.size()) { json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr, GRPC_JSON_TRUE, false); } diff --git a/src/proto/grpc/channelz/channelz.proto b/src/proto/grpc/channelz/channelz.proto index 9d73f37554..20de23f7fa 100644 --- a/src/proto/grpc/channelz/channelz.proto +++ b/src/proto/grpc/channelz/channelz.proto @@ -561,4 +561,4 @@ message GetSocketResponse { // The Socket that corresponds to the requested socket_id. This field // should be set. Socket socket = 1; -} \ No newline at end of file +} -- cgit v1.2.3 From c7f7db65e0fdc058b4caa2b76baaa308465fda9e Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Dec 2018 11:28:12 -0800 Subject: Add test and fix bug --- src/core/lib/channel/channelz.cc | 7 ++- src/cpp/server/channelz/channelz_service.cc | 4 +- test/cpp/end2end/channelz_service_test.cc | 82 +++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 6 deletions(-) (limited to 'src/core/lib/channel/channelz.cc') diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 10d5e1b581..8a596ad460 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -205,7 +205,7 @@ ServerNode::~ServerNode() {} char* ServerNode::RenderServerSockets(intptr_t start_socket_id, intptr_t max_results) { - // if user does not set max_results, we choose 1000. + // if user does not set max_results, we choose 500. size_t pagination_limit = max_results == 0 ? 500 : max_results; grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; @@ -219,9 +219,8 @@ char* ServerNode::RenderServerSockets(intptr_t start_socket_id, grpc_json* array_parent = grpc_json_create_child( nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); for (i = 0; i < GPR_MIN(socket_refs.size(), pagination_limit); ++i) { - grpc_json* socket_ref_json = - grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr, - GRPC_JSON_OBJECT, false); + grpc_json* socket_ref_json = grpc_json_create_child( + nullptr, array_parent, nullptr, nullptr, GRPC_JSON_OBJECT, false); json_iterator = grpc_json_add_number_string_child( socket_ref_json, nullptr, "socketId", socket_refs[i]->uuid()); grpc_json_create_child(json_iterator, socket_ref_json, "name", diff --git a/src/cpp/server/channelz/channelz_service.cc b/src/cpp/server/channelz/channelz_service.cc index 9ecb9de7e4..c44a9ac0de 100644 --- a/src/cpp/server/channelz/channelz_service.cc +++ b/src/cpp/server/channelz/channelz_service.cc @@ -79,8 +79,8 @@ Status ChannelzService::GetServer(ServerContext* unused, Status ChannelzService::GetServerSockets( ServerContext* unused, const channelz::v1::GetServerSocketsRequest* request, channelz::v1::GetServerSocketsResponse* response) { - char* json_str = grpc_channelz_get_server_sockets(request->server_id(), - request->start_socket_id()); + char* json_str = grpc_channelz_get_server_sockets( + request->server_id(), request->start_socket_id(), request->max_results()); if (json_str == nullptr) { return Status(StatusCode::INTERNAL, "grpc_channelz_get_server_sockets returned null"); diff --git a/test/cpp/end2end/channelz_service_test.cc b/test/cpp/end2end/channelz_service_test.cc index 29b59e4e5e..425334d972 100644 --- a/test/cpp/end2end/channelz_service_test.cc +++ b/test/cpp/end2end/channelz_service_test.cc @@ -54,6 +54,14 @@ using grpc::channelz::v1::GetSubchannelResponse; using grpc::channelz::v1::GetTopChannelsRequest; using grpc::channelz::v1::GetTopChannelsResponse; +// This code snippet can be used to print out any responses for +// visual debugging. +// +// +// string out_str; +// google::protobuf::TextFormat::PrintToString(resp, &out_str); +// std::cout << "resp: " << out_str << "\n"; + namespace grpc { namespace testing { namespace { @@ -164,6 +172,19 @@ class ChannelzServerTest : public ::testing::Test { echo_stub_ = grpc::testing::EchoTestService::NewStub(channel); } + std::unique_ptr NewEchoStub() { + static int salt = 0; + string target = "dns:localhost:" + to_string(proxy_port_); + ChannelArguments args; + // disable channelz. We only want to focus on proxy to backend outbound. + args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0); + // This ensures that gRPC will not do connection sharing. + args.SetInt("salt", salt++); + std::shared_ptr channel = + CreateCustomChannel(target, InsecureChannelCredentials(), args); + return grpc::testing::EchoTestService::NewStub(channel); + } + void SendSuccessfulEcho(int channel_idx) { EchoRequest request; EchoResponse response; @@ -651,6 +672,67 @@ TEST_F(ChannelzServerTest, GetServerSocketsTest) { EXPECT_EQ(get_server_sockets_response.socket_ref_size(), 1); } +TEST_F(ChannelzServerTest, GetServerSocketsPaginationTest) { + ResetStubs(); + ConfigureProxy(1); + std::vector> stubs; + const int kNumServerSocketsCreated = 20; + for (int i = 0; i < kNumServerSocketsCreated; ++i) { + stubs.push_back(NewEchoStub()); + EchoRequest request; + EchoResponse response; + request.set_message("Hello channelz"); + request.mutable_param()->set_backend_channel_idx(0); + ClientContext context; + Status s = stubs.back()->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + } + GetServersRequest get_server_request; + GetServersResponse get_server_response; + get_server_request.set_start_server_id(0); + ClientContext get_server_context; + Status s = channelz_stub_->GetServers(&get_server_context, get_server_request, + &get_server_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_server_response.server_size(), 1); + // Make a request that gets all of the serversockets + { + GetServerSocketsRequest get_server_sockets_request; + GetServerSocketsResponse get_server_sockets_response; + get_server_sockets_request.set_server_id( + get_server_response.server(0).ref().server_id()); + get_server_sockets_request.set_start_socket_id(0); + ClientContext get_server_sockets_context; + s = channelz_stub_->GetServerSockets(&get_server_sockets_context, + get_server_sockets_request, + &get_server_sockets_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + // We add one to account the the channelz stub that will end up creating + // a serversocket. + EXPECT_EQ(get_server_sockets_response.socket_ref_size(), + kNumServerSocketsCreated + 1); + EXPECT_TRUE(get_server_sockets_response.end()); + } + // Now we make a request that exercises pagination. + { + GetServerSocketsRequest get_server_sockets_request; + GetServerSocketsResponse get_server_sockets_response; + get_server_sockets_request.set_server_id( + get_server_response.server(0).ref().server_id()); + get_server_sockets_request.set_start_socket_id(0); + const int kMaxResults = 10; + get_server_sockets_request.set_max_results(kMaxResults); + ClientContext get_server_sockets_context; + s = channelz_stub_->GetServerSockets(&get_server_sockets_context, + get_server_sockets_request, + &get_server_sockets_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_EQ(get_server_sockets_response.socket_ref_size(), kMaxResults); + EXPECT_FALSE(get_server_sockets_response.end()); + } +} + TEST_F(ChannelzServerTest, GetServerListenSocketsTest) { ResetStubs(); ConfigureProxy(1); -- cgit v1.2.3