Merge remote-tracking branch 'upstream/master'

pull/23025/head
yulin-liang 5 years ago
commit a58b69d062
  1. 9
      src/core/ext/filters/client_channel/client_channel.cc
  2. 23
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  3. 42
      src/core/ext/filters/client_channel/resolving_lb_policy.cc
  4. 4
      src/core/ext/filters/client_channel/resolving_lb_policy.h
  5. 69
      src/core/ext/filters/client_channel/xds/xds_bootstrap.cc
  6. 46
      src/core/ext/filters/http/client/http_client_filter.cc
  7. 16
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  8. 27
      src/core/lib/channel/channel_args.cc
  9. 4
      src/core/lib/channel/channel_args.h
  10. 24
      src/core/lib/channel/handshaker.cc
  11. 48
      src/core/lib/debug/stats.cc
  12. 2
      src/core/lib/debug/stats.h
  13. 23
      src/core/lib/gpr/string.cc
  14. 16
      src/core/lib/gpr/string.h
  15. 111
      src/core/lib/http/format_request.cc
  16. 38
      src/core/lib/iomgr/ev_epoll1_linux.cc
  17. 45
      src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
  18. 108
      src/core/lib/surface/call_log_batch.cc
  19. 37
      src/core/lib/surface/completion_queue.cc
  20. 43
      src/core/lib/surface/event_string.cc
  21. 4
      src/core/lib/surface/event_string.h
  22. 5
      src/core/lib/transport/transport.h
  23. 163
      src/core/lib/transport/transport_op_string.cc
  24. 2
      src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi
  25. 21
      test/core/bad_client/tests/large_metadata.cc
  26. 56
      test/core/channel/minimal_stack_is_minimal_test.cc
  27. 78
      test/core/end2end/cq_verifier.cc
  28. 6
      test/core/end2end/tests/simple_request.cc
  29. 22
      test/core/gpr/arena_test.cc
  30. 5
      test/core/security/verify_jwt.cc
  31. 54
      test/core/util/cmdline.cc
  32. 4
      test/core/util/cmdline.h
  33. 17
      test/core/util/cmdline_test.cc

@ -3164,10 +3164,9 @@ void CallData::OnComplete(void* arg, grpc_error* error) {
ChannelData* chand = static_cast<ChannelData*>(elem->channel_data); ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
CallData* calld = static_cast<CallData*>(elem->call_data); CallData* calld = static_cast<CallData*>(elem->call_data);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
char* batch_str = grpc_transport_stream_op_batch_string(&batch_data->batch);
gpr_log(GPR_INFO, "chand=%p calld=%p: got on_complete, error=%s, batch=%s", gpr_log(GPR_INFO, "chand=%p calld=%p: got on_complete, error=%s, batch=%s",
chand, calld, grpc_error_string(error), batch_str); chand, calld, grpc_error_string(error),
gpr_free(batch_str); grpc_transport_stream_op_batch_string(&batch_data->batch).c_str());
} }
SubchannelCallRetryState* retry_state = SubchannelCallRetryState* retry_state =
static_cast<SubchannelCallRetryState*>( static_cast<SubchannelCallRetryState*>(
@ -3240,10 +3239,8 @@ void CallData::AddClosureForSubchannelBatch(
GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner, GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner,
batch, grpc_schedule_on_exec_ctx); batch, grpc_schedule_on_exec_ctx);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
char* batch_str = grpc_transport_stream_op_batch_string(batch);
gpr_log(GPR_INFO, "chand=%p calld=%p: starting subchannel batch: %s", chand, gpr_log(GPR_INFO, "chand=%p calld=%p: starting subchannel batch: %s", chand,
this, batch_str); this, grpc_transport_stream_op_batch_string(batch).c_str());
gpr_free(batch_str);
} }
closures->Add(&batch->handler_private.closure, GRPC_ERROR_NONE, closures->Add(&batch->handler_private.closure, GRPC_ERROR_NONE,
"start_subchannel_batch"); "start_subchannel_batch");

@ -65,6 +65,8 @@
#include <string.h> #include <string.h>
#include "absl/container/inlined_vector.h" #include "absl/container/inlined_vector.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/byte_buffer_reader.h> #include <grpc/byte_buffer_reader.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
@ -235,7 +237,7 @@ class GrpcLb : public LoadBalancingPolicy {
const std::vector<GrpcLbServer>& serverlist() const { return serverlist_; } const std::vector<GrpcLbServer>& serverlist() const { return serverlist_; }
// Returns a text representation suitable for logging. // Returns a text representation suitable for logging.
grpc_core::UniquePtr<char> AsText() const; std::string AsText() const;
// Extracts all non-drop entries into a ServerAddressList. // Extracts all non-drop entries into a ServerAddressList.
ServerAddressList GetServerAddressList( ServerAddressList GetServerAddressList(
@ -445,9 +447,8 @@ void ParseServer(const GrpcLbServer& server, grpc_resolved_address* addr) {
} }
} }
grpc_core::UniquePtr<char> GrpcLb::Serverlist::AsText() const { std::string GrpcLb::Serverlist::AsText() const {
gpr_strvec entries; std::vector<std::string> entries;
gpr_strvec_init(&entries);
for (size_t i = 0; i < serverlist_.size(); ++i) { for (size_t i = 0; i < serverlist_.size(); ++i) {
const GrpcLbServer& server = serverlist_[i]; const GrpcLbServer& server = serverlist_[i];
std::string ipport; std::string ipport;
@ -458,14 +459,10 @@ grpc_core::UniquePtr<char> GrpcLb::Serverlist::AsText() const {
ParseServer(server, &addr); ParseServer(server, &addr);
ipport = grpc_sockaddr_to_string(&addr, false); ipport = grpc_sockaddr_to_string(&addr, false);
} }
char* entry; entries.push_back(absl::StrFormat(" %" PRIuPTR ": %s token=%s\n", i,
gpr_asprintf(&entry, " %" PRIuPTR ": %s token=%s\n", i, ipport.c_str(), ipport, server.load_balance_token));
server.load_balance_token);
gpr_strvec_add(&entries, entry);
} }
grpc_core::UniquePtr<char> result(gpr_strvec_flatten(&entries, nullptr)); return absl::StrJoin(entries, "");
gpr_strvec_destroy(&entries);
return result;
} }
// vtables for channel args for LB token and client stats. // vtables for channel args for LB token and client stats.
@ -1057,14 +1054,12 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked() {
auto serverlist_wrapper = auto serverlist_wrapper =
MakeRefCounted<Serverlist>(std::move(response.serverlist)); MakeRefCounted<Serverlist>(std::move(response.serverlist));
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
grpc_core::UniquePtr<char> serverlist_text =
serverlist_wrapper->AsText();
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[grpclb %p] lb_calld=%p: Serverlist with %" PRIuPTR "[grpclb %p] lb_calld=%p: Serverlist with %" PRIuPTR
" servers received:\n%s", " servers received:\n%s",
grpclb_policy(), this, grpclb_policy(), this,
serverlist_wrapper->serverlist().size(), serverlist_wrapper->serverlist().size(),
serverlist_text.get()); serverlist_wrapper->AsText().c_str());
} }
seen_serverlist_ = true; seen_serverlist_ = true;
// Start sending client load report only after we start using the // Start sending client load report only after we start using the

@ -26,6 +26,9 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
@ -241,7 +244,6 @@ void ResolvingLoadBalancingPolicy::CreateOrUpdateLbPolicyLocked(
} }
// Creates a new LB policy. // Creates a new LB policy.
// Updates trace_strings to indicate what was done.
OrphanablePtr<LoadBalancingPolicy> OrphanablePtr<LoadBalancingPolicy>
ResolvingLoadBalancingPolicy::CreateLbPolicyLocked( ResolvingLoadBalancingPolicy::CreateLbPolicyLocked(
const grpc_channel_args& args) { const grpc_channel_args& args) {
@ -265,31 +267,21 @@ void ResolvingLoadBalancingPolicy::MaybeAddTraceMessagesForAddressChangesLocked(
bool resolution_contains_addresses, TraceStringVector* trace_strings) { bool resolution_contains_addresses, TraceStringVector* trace_strings) {
if (!resolution_contains_addresses && if (!resolution_contains_addresses &&
previous_resolution_contained_addresses_) { previous_resolution_contained_addresses_) {
trace_strings->push_back(gpr_strdup("Address list became empty")); trace_strings->push_back("Address list became empty");
} else if (resolution_contains_addresses && } else if (resolution_contains_addresses &&
!previous_resolution_contained_addresses_) { !previous_resolution_contained_addresses_) {
trace_strings->push_back(gpr_strdup("Address list became non-empty")); trace_strings->push_back("Address list became non-empty");
} }
previous_resolution_contained_addresses_ = resolution_contains_addresses; previous_resolution_contained_addresses_ = resolution_contains_addresses;
} }
void ResolvingLoadBalancingPolicy::ConcatenateAndAddChannelTraceLocked( void ResolvingLoadBalancingPolicy::ConcatenateAndAddChannelTraceLocked(
TraceStringVector* trace_strings) const { const TraceStringVector& trace_strings) const {
if (!trace_strings->empty()) { if (!trace_strings.empty()) {
gpr_strvec v; std::string message =
gpr_strvec_init(&v); absl::StrCat("Resolution event: ", absl::StrJoin(trace_strings, ", "));
gpr_strvec_add(&v, gpr_strdup("Resolution event: "));
bool is_first = 1;
for (size_t i = 0; i < trace_strings->size(); ++i) {
if (!is_first) gpr_strvec_add(&v, gpr_strdup(", "));
is_first = false;
gpr_strvec_add(&v, (*trace_strings)[i]);
}
size_t len = 0;
grpc_core::UniquePtr<char> message(gpr_strvec_flatten(&v, &len));
channel_control_helper()->AddTraceEvent(ChannelControlHelper::TRACE_INFO, channel_control_helper()->AddTraceEvent(ChannelControlHelper::TRACE_INFO,
absl::string_view(message.get())); message);
gpr_strvec_destroy(&v);
} }
} }
@ -314,7 +306,7 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
// Process the resolver result. // Process the resolver result.
RefCountedPtr<LoadBalancingPolicy::Config> lb_policy_config; RefCountedPtr<LoadBalancingPolicy::Config> lb_policy_config;
bool service_config_changed = false; bool service_config_changed = false;
char* service_config_error_string = nullptr; std::string service_config_error_string;
if (process_resolver_result_ != nullptr) { if (process_resolver_result_ != nullptr) {
grpc_error* service_config_error = GRPC_ERROR_NONE; grpc_error* service_config_error = GRPC_ERROR_NONE;
bool no_valid_service_config = false; bool no_valid_service_config = false;
@ -322,8 +314,7 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
process_resolver_result_user_data_, result, &lb_policy_config, process_resolver_result_user_data_, result, &lb_policy_config,
&service_config_error, &no_valid_service_config); &service_config_error, &no_valid_service_config);
if (service_config_error != GRPC_ERROR_NONE) { if (service_config_error != GRPC_ERROR_NONE) {
service_config_error_string = service_config_error_string = grpc_error_string(service_config_error);
gpr_strdup(grpc_error_string(service_config_error));
if (no_valid_service_config) { if (no_valid_service_config) {
// We received an invalid service config and we don't have a // We received an invalid service config and we don't have a
// fallback service config. // fallback service config.
@ -344,15 +335,14 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
if (service_config_changed) { if (service_config_changed) {
// TODO(ncteisen): might be worth somehow including a snippet of the // TODO(ncteisen): might be worth somehow including a snippet of the
// config in the trace, at the risk of bloating the trace logs. // config in the trace, at the risk of bloating the trace logs.
trace_strings.push_back(gpr_strdup("Service config changed")); trace_strings.push_back("Service config changed");
} }
if (service_config_error_string != nullptr) { if (!service_config_error_string.empty()) {
trace_strings.push_back(service_config_error_string); trace_strings.push_back(service_config_error_string.c_str());
service_config_error_string = nullptr;
} }
MaybeAddTraceMessagesForAddressChangesLocked(resolution_contains_addresses, MaybeAddTraceMessagesForAddressChangesLocked(resolution_contains_addresses,
&trace_strings); &trace_strings);
ConcatenateAndAddChannelTraceLocked(&trace_strings); ConcatenateAndAddChannelTraceLocked(trace_strings);
} }
} // namespace grpc_core } // namespace grpc_core

@ -81,7 +81,7 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
void ResetBackoffLocked() override; void ResetBackoffLocked() override;
private: private:
using TraceStringVector = absl::InlinedVector<char*, 3>; using TraceStringVector = absl::InlinedVector<const char*, 3>;
class ResolverResultHandler; class ResolverResultHandler;
class ResolvingControlHelper; class ResolvingControlHelper;
@ -99,7 +99,7 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
void MaybeAddTraceMessagesForAddressChangesLocked( void MaybeAddTraceMessagesForAddressChangesLocked(
bool resolution_contains_addresses, TraceStringVector* trace_strings); bool resolution_contains_addresses, TraceStringVector* trace_strings);
void ConcatenateAndAddChannelTraceLocked( void ConcatenateAndAddChannelTraceLocked(
TraceStringVector* trace_strings) const; const TraceStringVector& trace_strings) const;
void OnResolverResultChangedLocked(Resolver::Result result); void OnResolverResultChangedLocked(Resolver::Result result);
// Passed in from caller at construction time. // Passed in from caller at construction time.

@ -23,6 +23,8 @@
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
@ -36,47 +38,36 @@ namespace grpc_core {
namespace { namespace {
UniquePtr<char> BootstrapString(const XdsBootstrap& bootstrap) { std::string BootstrapString(const XdsBootstrap& bootstrap) {
gpr_strvec v; std::vector<std::string> parts;
gpr_strvec_init(&v);
char* tmp;
if (bootstrap.node() != nullptr) { if (bootstrap.node() != nullptr) {
gpr_asprintf(&tmp, parts.push_back(absl::StrFormat(
"node={\n" "node={\n"
" id=\"%s\",\n" " id=\"%s\",\n"
" cluster=\"%s\",\n" " cluster=\"%s\",\n"
" locality={\n" " locality={\n"
" region=\"%s\",\n" " region=\"%s\",\n"
" zone=\"%s\",\n" " zone=\"%s\",\n"
" subzone=\"%s\"\n" " subzone=\"%s\"\n"
" },\n" " },\n"
" metadata=%s,\n" " metadata=%s,\n"
"},\n", "},\n",
bootstrap.node()->id.c_str(), bootstrap.node()->id, bootstrap.node()->cluster,
bootstrap.node()->cluster.c_str(), bootstrap.node()->locality_region, bootstrap.node()->locality_zone,
bootstrap.node()->locality_region.c_str(), bootstrap.node()->locality_subzone, bootstrap.node()->metadata.Dump()));
bootstrap.node()->locality_zone.c_str(),
bootstrap.node()->locality_subzone.c_str(),
bootstrap.node()->metadata.Dump().c_str());
gpr_strvec_add(&v, tmp);
} }
gpr_asprintf(&tmp, parts.push_back(
"servers=[\n" absl::StrFormat("servers=[\n"
" {\n" " {\n"
" uri=\"%s\",\n" " uri=\"%s\",\n"
" creds=[\n", " creds=[\n",
bootstrap.server().server_uri.c_str()); bootstrap.server().server_uri));
gpr_strvec_add(&v, tmp); for (const auto& creds : bootstrap.server().channel_creds) {
for (size_t i = 0; i < bootstrap.server().channel_creds.size(); ++i) { parts.push_back(absl::StrFormat(" {type=\"%s\", config=%s},\n",
const auto& creds = bootstrap.server().channel_creds[i]; creds.type, creds.config.Dump()));
gpr_asprintf(&tmp, " {type=\"%s\", config=%s},\n", creds.type.c_str(),
creds.config.Dump().c_str());
gpr_strvec_add(&v, tmp);
} }
gpr_strvec_add(&v, gpr_strdup(" ]\n }\n]")); parts.push_back(" ]\n }\n]");
UniquePtr<char> result(gpr_strvec_flatten(&v, nullptr)); return absl::StrJoin(parts, "");
gpr_strvec_destroy(&v);
return result;
} }
} // namespace } // namespace
@ -121,7 +112,7 @@ std::unique_ptr<XdsBootstrap> XdsBootstrap::ReadFromFile(XdsClient* client,
if (*error == GRPC_ERROR_NONE && GRPC_TRACE_FLAG_ENABLED(*tracer)) { if (*error == GRPC_ERROR_NONE && GRPC_TRACE_FLAG_ENABLED(*tracer)) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"[xds_client %p] Bootstrap config for creating xds client:\n%s", "[xds_client %p] Bootstrap config for creating xds client:\n%s",
client, BootstrapString(*result).get()); client, BootstrapString(*result).c_str());
} }
return result; return result;
} }

@ -17,11 +17,19 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <stdint.h>
#include <string.h>
#include <string>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include <stdint.h>
#include <string.h>
#include "src/core/ext/filters/http/client/http_client_filter.h" #include "src/core/ext/filters/http/client/http_client_filter.h"
#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/manual_constructor.h"
@ -520,50 +528,36 @@ static size_t max_payload_size_from_args(const grpc_channel_args* args) {
static grpc_core::ManagedMemorySlice user_agent_from_args( static grpc_core::ManagedMemorySlice user_agent_from_args(
const grpc_channel_args* args, const char* transport_name) { const grpc_channel_args* args, const char* transport_name) {
gpr_strvec v; std::vector<std::string> user_agent_fields;
size_t i;
int is_first = 1;
char* tmp;
gpr_strvec_init(&v); for (size_t i = 0; args && i < args->num_args; i++) {
for (i = 0; args && i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) { if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) {
if (args->args[i].type != GRPC_ARG_STRING) { if (args->args[i].type != GRPC_ARG_STRING) {
gpr_log(GPR_ERROR, "Channel argument '%s' should be a string", gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
GRPC_ARG_PRIMARY_USER_AGENT_STRING); GRPC_ARG_PRIMARY_USER_AGENT_STRING);
} else { } else {
if (!is_first) gpr_strvec_add(&v, gpr_strdup(" ")); user_agent_fields.push_back(args->args[i].value.string);
is_first = 0;
gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
} }
} }
} }
gpr_asprintf(&tmp, "%sgrpc-c/%s (%s; %s)", is_first ? "" : " ", user_agent_fields.push_back(
grpc_version_string(), GPR_PLATFORM_STRING, transport_name); absl::StrFormat("grpc-c/%s (%s; %s)", grpc_version_string(),
is_first = 0; GPR_PLATFORM_STRING, transport_name));
gpr_strvec_add(&v, tmp);
for (i = 0; args && i < args->num_args; i++) { for (size_t i = 0; args && i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) { if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) {
if (args->args[i].type != GRPC_ARG_STRING) { if (args->args[i].type != GRPC_ARG_STRING) {
gpr_log(GPR_ERROR, "Channel argument '%s' should be a string", gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
GRPC_ARG_SECONDARY_USER_AGENT_STRING); GRPC_ARG_SECONDARY_USER_AGENT_STRING);
} else { } else {
if (!is_first) gpr_strvec_add(&v, gpr_strdup(" ")); user_agent_fields.push_back(args->args[i].value.string);
is_first = 0;
gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
} }
} }
} }
tmp = gpr_strvec_flatten(&v, nullptr); std::string user_agent_string = absl::StrJoin(user_agent_fields, " ");
gpr_strvec_destroy(&v); return grpc_core::ManagedMemorySlice(user_agent_string.c_str());
grpc_core::ManagedMemorySlice result(tmp);
gpr_free(tmp);
return result;
} }
/* Constructor for channel_data */ /* Constructor for channel_data */

@ -1356,10 +1356,8 @@ static void perform_stream_op_locked(void* stream_op,
s->context = op->payload->context; s->context = op->payload->context;
s->traced = op->is_traced; s->traced = op->is_traced;
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
char* str = grpc_transport_stream_op_batch_string(op); gpr_log(GPR_INFO, "perform_stream_op_locked: %s; on_complete = %p",
gpr_log(GPR_INFO, "perform_stream_op_locked: %s; on_complete = %p", str, grpc_transport_stream_op_batch_string(op).c_str(), op->on_complete);
op->on_complete);
gpr_free(str);
if (op->send_initial_metadata) { if (op->send_initial_metadata) {
log_metadata(op_payload->send_initial_metadata.send_initial_metadata, log_metadata(op_payload->send_initial_metadata.send_initial_metadata,
s->id, t->is_client, true); s->id, t->is_client, true);
@ -1654,9 +1652,8 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
} }
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
char* str = grpc_transport_stream_op_batch_string(op); gpr_log(GPR_INFO, "perform_stream_op[s=%p]: %s", s,
gpr_log(GPR_INFO, "perform_stream_op[s=%p]: %s", s, str); grpc_transport_stream_op_batch_string(op).c_str());
gpr_free(str);
} }
GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op"); GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op");
@ -1845,9 +1842,8 @@ static void perform_transport_op_locked(void* stream_op,
static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) { static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(gt); grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(gt);
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
char* msg = grpc_transport_op_string(op); gpr_log(GPR_INFO, "perform_transport_op[t=%p]: %s", t,
gpr_log(GPR_INFO, "perform_transport_op[t=%p]: %s", t, msg); grpc_transport_op_string(op).c_str());
gpr_free(msg);
} }
op->handler_private.extra_arg = gt; op->handler_private.extra_arg = gt;
GRPC_CHTTP2_REF_TRANSPORT(t, "transport_op"); GRPC_CHTTP2_REF_TRANSPORT(t, "transport_op");

@ -21,6 +21,11 @@
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/impl/codegen/grpc_types.h> #include <grpc/impl/codegen/grpc_types.h>
#include <grpc/impl/codegen/log.h> #include <grpc/impl/codegen/log.h>
@ -336,32 +341,28 @@ grpc_arg grpc_channel_arg_pointer_create(
return arg; return arg;
} }
char* grpc_channel_args_string(const grpc_channel_args* args) { std::string grpc_channel_args_string(const grpc_channel_args* args) {
if (args == nullptr) return nullptr; if (args == nullptr) return nullptr;
gpr_strvec v; std::vector<std::string> arg_strings;
gpr_strvec_init(&v);
for (size_t i = 0; i < args->num_args; ++i) { for (size_t i = 0; i < args->num_args; ++i) {
const grpc_arg& arg = args->args[i]; const grpc_arg& arg = args->args[i];
char* s; std::string arg_string;
switch (arg.type) { switch (arg.type) {
case GRPC_ARG_INTEGER: case GRPC_ARG_INTEGER:
gpr_asprintf(&s, "%s=%d", arg.key, arg.value.integer); arg_string = absl::StrFormat("%s=%d", arg.key, arg.value.integer);
break; break;
case GRPC_ARG_STRING: case GRPC_ARG_STRING:
gpr_asprintf(&s, "%s=%s", arg.key, arg.value.string); arg_string = absl::StrFormat("%s=%s", arg.key, arg.value.string);
break; break;
case GRPC_ARG_POINTER: case GRPC_ARG_POINTER:
gpr_asprintf(&s, "%s=%p", arg.key, arg.value.pointer.p); arg_string = absl::StrFormat("%s=%p", arg.key, arg.value.pointer.p);
break; break;
default: default:
gpr_asprintf(&s, "arg with unknown type"); arg_string = "arg with unknown type";
} }
gpr_strvec_add(&v, s); arg_strings.push_back(arg_string);
} }
char* result = return absl::StrJoin(arg_strings, ", ");
gpr_strjoin_sep(const_cast<const char**>(v.strs), v.count, ", ", nullptr);
gpr_strvec_destroy(&v);
return result;
} }
namespace { namespace {

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <string>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/surface/channel_stack_type.h"
@ -116,7 +118,7 @@ grpc_arg grpc_channel_arg_pointer_create(char* name, void* value,
// Returns a string representing channel args in human-readable form. // Returns a string representing channel args in human-readable form.
// Callers takes ownership of result. // Callers takes ownership of result.
char* grpc_channel_args_string(const grpc_channel_args* args); std::string grpc_channel_args_string(const grpc_channel_args* args);
// Takes ownership of the old_args // Takes ownership of the old_args
typedef grpc_channel_args* (*grpc_channel_args_client_channel_creation_mutator)( typedef grpc_channel_args* (*grpc_channel_args_client_channel_creation_mutator)(

@ -20,6 +20,8 @@
#include <string.h> #include <string.h>
#include "absl/strings/str_format.h"
#include <grpc/impl/codegen/slice.h> #include <grpc/impl/codegen/slice.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
@ -37,19 +39,16 @@ TraceFlag grpc_handshaker_trace(false, "handshaker");
namespace { namespace {
char* HandshakerArgsString(HandshakerArgs* args) { std::string HandshakerArgsString(HandshakerArgs* args) {
char* args_str = grpc_channel_args_string(args->args);
size_t num_args = args->args != nullptr ? args->args->num_args : 0; size_t num_args = args->args != nullptr ? args->args->num_args : 0;
size_t read_buffer_length = size_t read_buffer_length =
args->read_buffer != nullptr ? args->read_buffer->length : 0; args->read_buffer != nullptr ? args->read_buffer->length : 0;
char* str; return absl::StrFormat(
gpr_asprintf(&str, "{endpoint=%p, args=%p {size=%" PRIuPTR
"{endpoint=%p, args=%p {size=%" PRIuPTR ": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}",
": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}", args->endpoint, args->args, num_args,
args->endpoint, args->args, num_args, args_str, grpc_channel_args_string(args->args), args->read_buffer,
args->read_buffer, read_buffer_length, args->exit_early); read_buffer_length, args->exit_early);
gpr_free(args_str);
return str;
} }
} // namespace } // namespace
@ -127,12 +126,11 @@ void HandshakeManager::Shutdown(grpc_error* why) {
// Returns true if we've scheduled the on_handshake_done callback. // Returns true if we've scheduled the on_handshake_done callback.
bool HandshakeManager::CallNextHandshakerLocked(grpc_error* error) { bool HandshakeManager::CallNextHandshakerLocked(grpc_error* error) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_handshaker_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_handshaker_trace)) {
char* args_str = HandshakerArgsString(&args_);
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"handshake_manager %p: error=%s shutdown=%d index=%" PRIuPTR "handshake_manager %p: error=%s shutdown=%d index=%" PRIuPTR
", args=%s", ", args=%s",
this, grpc_error_string(error), is_shutdown_, index_, args_str); this, grpc_error_string(error), is_shutdown_, index_,
gpr_free(args_str); HandshakerArgsString(&args_).c_str());
} }
GPR_ASSERT(index_ <= handshakers_.size()); GPR_ASSERT(index_ <= handshakers_.size());
// If we got an error or we've been shut down or we're exiting early or // If we got an error or we've been shut down or we're exiting early or

@ -23,6 +23,11 @@
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
@ -140,39 +145,28 @@ double grpc_stats_histo_percentile(const grpc_stats_data* stats,
static_cast<double>(count) * percentile / 100.0); static_cast<double>(count) * percentile / 100.0);
} }
char* grpc_stats_data_as_json(const grpc_stats_data* data) { std::string grpc_stats_data_as_json(const grpc_stats_data* data) {
gpr_strvec v; std::vector<std::string> parts;
char* tmp; parts.push_back("{");
bool is_first = true;
gpr_strvec_init(&v);
gpr_strvec_add(&v, gpr_strdup("{"));
for (size_t i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) { for (size_t i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) {
gpr_asprintf(&tmp, "%s\"%s\": %" PRIdPTR, is_first ? "" : ", ", parts.push_back(absl::StrFormat(
grpc_stats_counter_name[i], data->counters[i]); "\"%s\": %" PRIdPTR, grpc_stats_counter_name[i], data->counters[i]));
gpr_strvec_add(&v, tmp);
is_first = false;
} }
for (size_t i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) { for (size_t i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) {
gpr_asprintf(&tmp, "%s\"%s\": [", is_first ? "" : ", ", parts.push_back(absl::StrFormat("\"%s\": [", grpc_stats_histogram_name[i]));
grpc_stats_histogram_name[i]);
gpr_strvec_add(&v, tmp);
for (int j = 0; j < grpc_stats_histo_buckets[i]; j++) { for (int j = 0; j < grpc_stats_histo_buckets[i]; j++) {
gpr_asprintf(&tmp, "%s%" PRIdPTR, j == 0 ? "" : ",", parts.push_back(
data->histograms[grpc_stats_histo_start[i] + j]); absl::StrFormat("%s%" PRIdPTR, j == 0 ? "" : ",",
gpr_strvec_add(&v, tmp); data->histograms[grpc_stats_histo_start[i] + j]));
} }
gpr_asprintf(&tmp, "], \"%s_bkt\": [", grpc_stats_histogram_name[i]); parts.push_back(
gpr_strvec_add(&v, tmp); absl::StrFormat("], \"%s_bkt\": [", grpc_stats_histogram_name[i]));
for (int j = 0; j < grpc_stats_histo_buckets[i]; j++) { for (int j = 0; j < grpc_stats_histo_buckets[i]; j++) {
gpr_asprintf(&tmp, "%s%d", j == 0 ? "" : ",", parts.push_back(absl::StrFormat(
grpc_stats_histo_bucket_boundaries[i][j]); "%s%d", j == 0 ? "" : ",", grpc_stats_histo_bucket_boundaries[i][j]));
gpr_strvec_add(&v, tmp);
} }
gpr_strvec_add(&v, gpr_strdup("]")); parts.push_back("]");
is_first = false;
} }
gpr_strvec_add(&v, gpr_strdup("}")); parts.push_back("}");
tmp = gpr_strvec_flatten(&v, nullptr); return absl::StrJoin(parts, "");
gpr_strvec_destroy(&v);
return tmp;
} }

@ -56,7 +56,7 @@ void grpc_stats_collect(grpc_stats_data* output);
// c = b-a // c = b-a
void grpc_stats_diff(const grpc_stats_data* b, const grpc_stats_data* a, void grpc_stats_diff(const grpc_stats_data* b, const grpc_stats_data* a,
grpc_stats_data* c); grpc_stats_data* c);
char* grpc_stats_data_as_json(const grpc_stats_data* data); std::string grpc_stats_data_as_json(const grpc_stats_data* data);
int grpc_stats_histo_find_bucket_slow(int value, const int* table, int grpc_stats_histo_find_bucket_slow(int value, const int* table,
int table_size); int table_size);
double grpc_stats_histo_percentile(const grpc_stats_data* data, double grpc_stats_histo_percentile(const grpc_stats_data* data,

@ -266,29 +266,6 @@ char* gpr_strjoin_sep(const char** strs, size_t nstrs, const char* sep,
return out; return out;
} }
void gpr_strvec_init(gpr_strvec* sv) { memset(sv, 0, sizeof(*sv)); }
void gpr_strvec_destroy(gpr_strvec* sv) {
size_t i;
for (i = 0; i < sv->count; i++) {
gpr_free(sv->strs[i]);
}
gpr_free(sv->strs);
}
void gpr_strvec_add(gpr_strvec* sv, char* str) {
if (sv->count == sv->capacity) {
sv->capacity = GPR_MAX(sv->capacity + 8, sv->capacity * 2);
sv->strs = static_cast<char**>(
gpr_realloc(sv->strs, sizeof(char*) * sv->capacity));
}
sv->strs[sv->count++] = str;
}
char* gpr_strvec_flatten(gpr_strvec* sv, size_t* final_length) {
return gpr_strjoin((const char**)sv->strs, sv->count, final_length);
}
int gpr_strincmp(const char* a, const char* b, size_t n) { int gpr_strincmp(const char* a, const char* b, size_t n) {
int ca, cb; int ca, cb;
do { do {

@ -96,22 +96,6 @@ void gpr_string_split(const char* input, const char* sep, char*** strs,
0, 3, 6 or 9 fractional digits. */ 0, 3, 6 or 9 fractional digits. */
char* gpr_format_timespec(gpr_timespec); char* gpr_format_timespec(gpr_timespec);
/* A vector of strings... for building up a final string one piece at a time */
typedef struct {
char** strs;
size_t count;
size_t capacity;
} gpr_strvec;
/* Initialize/destroy */
void gpr_strvec_init(gpr_strvec* strs);
void gpr_strvec_destroy(gpr_strvec* strs);
/* Add a string to a strvec, takes ownership of the string */
void gpr_strvec_add(gpr_strvec* strs, char* add);
/* Return a joined string with all added substrings, optionally setting
total_length as per gpr_strjoin */
char* gpr_strvec_flatten(gpr_strvec* strs, size_t* total_length);
/** Case insensitive string comparison... return <0 if lower(a)<lower(b), ==0 if /** Case insensitive string comparison... return <0 if lower(a)<lower(b), ==0 if
lower(a)==lower(b), >0 if lower(a)>lower(b) */ lower(a)==lower(b), >0 if lower(a)>lower(b) */
int gpr_stricmp(const char* a, const char* b); int gpr_stricmp(const char* a, const char* b);

@ -24,99 +24,80 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/slice.h> #include <grpc/slice.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/string.h"
static void fill_common_header(const grpc_httpcli_request* request, static void fill_common_header(const grpc_httpcli_request* request,
gpr_strvec* buf, bool connection_close) { bool connection_close,
size_t i; std::vector<std::string>* buf) {
gpr_strvec_add(buf, gpr_strdup(request->http.path)); buf->push_back(request->http.path);
gpr_strvec_add(buf, gpr_strdup(" HTTP/1.0\r\n")); buf->push_back(" HTTP/1.0\r\n");
/* just in case some crazy server really expects HTTP/1.1 */ /* just in case some crazy server really expects HTTP/1.1 */
gpr_strvec_add(buf, gpr_strdup("Host: ")); buf->push_back("Host: ");
gpr_strvec_add(buf, gpr_strdup(request->host)); buf->push_back(request->host);
gpr_strvec_add(buf, gpr_strdup("\r\n")); buf->push_back("\r\n");
if (connection_close) if (connection_close) buf->push_back("Connection: close\r\n");
gpr_strvec_add(buf, gpr_strdup("Connection: close\r\n")); buf->push_back("User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n");
gpr_strvec_add(buf,
gpr_strdup("User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n"));
/* user supplied headers */ /* user supplied headers */
for (i = 0; i < request->http.hdr_count; i++) { for (size_t i = 0; i < request->http.hdr_count; i++) {
gpr_strvec_add(buf, gpr_strdup(request->http.hdrs[i].key)); buf->push_back(request->http.hdrs[i].key);
gpr_strvec_add(buf, gpr_strdup(": ")); buf->push_back(": ");
gpr_strvec_add(buf, gpr_strdup(request->http.hdrs[i].value)); buf->push_back(request->http.hdrs[i].value);
gpr_strvec_add(buf, gpr_strdup("\r\n")); buf->push_back("\r\n");
} }
} }
grpc_slice grpc_httpcli_format_get_request( grpc_slice grpc_httpcli_format_get_request(
const grpc_httpcli_request* request) { const grpc_httpcli_request* request) {
gpr_strvec out; std::vector<std::string> out;
char* flat; out.push_back("GET ");
size_t flat_len; fill_common_header(request, true, &out);
out.push_back("\r\n");
gpr_strvec_init(&out); std::string req = absl::StrJoin(out, "");
gpr_strvec_add(&out, gpr_strdup("GET ")); return grpc_slice_from_copied_buffer(req.data(), req.size());
fill_common_header(request, &out, true);
gpr_strvec_add(&out, gpr_strdup("\r\n"));
flat = gpr_strvec_flatten(&out, &flat_len);
gpr_strvec_destroy(&out);
return grpc_slice_new(flat, flat_len, gpr_free);
} }
grpc_slice grpc_httpcli_format_post_request(const grpc_httpcli_request* request, grpc_slice grpc_httpcli_format_post_request(const grpc_httpcli_request* request,
const char* body_bytes, const char* body_bytes,
size_t body_size) { size_t body_size) {
gpr_strvec out; std::vector<std::string> out;
char* tmp; out.push_back("POST ");
size_t out_len; fill_common_header(request, true, &out);
size_t i; if (body_bytes != nullptr) {
bool has_content_type = false;
gpr_strvec_init(&out); for (size_t i = 0; i < request->http.hdr_count; i++) {
gpr_strvec_add(&out, gpr_strdup("POST "));
fill_common_header(request, &out, true);
if (body_bytes) {
uint8_t has_content_type = 0;
for (i = 0; i < request->http.hdr_count; i++) {
if (strcmp(request->http.hdrs[i].key, "Content-Type") == 0) { if (strcmp(request->http.hdrs[i].key, "Content-Type") == 0) {
has_content_type = 1; has_content_type = true;
break; break;
} }
} }
if (!has_content_type) { if (!has_content_type) {
gpr_strvec_add(&out, gpr_strdup("Content-Type: text/plain\r\n")); out.push_back("Content-Type: text/plain\r\n");
} }
gpr_asprintf(&tmp, "Content-Length: %lu\r\n", out.push_back(absl::StrFormat("Content-Length: %lu\r\n",
static_cast<unsigned long>(body_size)); static_cast<unsigned long>(body_size)));
gpr_strvec_add(&out, tmp);
} }
gpr_strvec_add(&out, gpr_strdup("\r\n")); out.push_back("\r\n");
tmp = gpr_strvec_flatten(&out, &out_len); std::string req = absl::StrJoin(out, "");
gpr_strvec_destroy(&out); if (body_bytes != nullptr) {
absl::StrAppend(&req, absl::string_view(body_bytes, body_size));
if (body_bytes) {
tmp = static_cast<char*>(gpr_realloc(tmp, out_len + body_size));
memcpy(tmp + out_len, body_bytes, body_size);
out_len += body_size;
} }
return grpc_slice_from_copied_buffer(req.data(), req.size());
return grpc_slice_new(tmp, out_len, gpr_free);
} }
grpc_slice grpc_httpcli_format_connect_request( grpc_slice grpc_httpcli_format_connect_request(
const grpc_httpcli_request* request) { const grpc_httpcli_request* request) {
gpr_strvec out; std::vector<std::string> out;
gpr_strvec_init(&out); out.push_back("CONNECT ");
gpr_strvec_add(&out, gpr_strdup("CONNECT ")); fill_common_header(request, false, &out);
fill_common_header(request, &out, false); out.push_back("\r\n");
gpr_strvec_add(&out, gpr_strdup("\r\n")); std::string req = absl::StrJoin(out, "");
size_t flat_len; return grpc_slice_from_copied_buffer(req.data(), req.size());
char* flat = gpr_strvec_flatten(&out, &flat_len);
gpr_strvec_destroy(&out);
return grpc_slice_new(flat, flat_len, gpr_free);
} }

@ -38,6 +38,11 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/cpu.h> #include <grpc/support/cpu.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
@ -1064,30 +1069,23 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
GRPC_STATS_INC_POLLSET_KICK(); GRPC_STATS_INC_POLLSET_KICK();
grpc_error* ret_err = GRPC_ERROR_NONE; grpc_error* ret_err = GRPC_ERROR_NONE;
if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
gpr_strvec log; std::vector<std::string> log;
gpr_strvec_init(&log); log.push_back(absl::StrFormat(
char* tmp; "PS:%p KICK:%p curps=%p curworker=%p root=%p", pollset, specific_worker,
gpr_asprintf(&tmp, "PS:%p KICK:%p curps=%p curworker=%p root=%p", pollset, (void*)gpr_tls_get(&g_current_thread_pollset),
specific_worker, (void*)gpr_tls_get(&g_current_thread_pollset), (void*)gpr_tls_get(&g_current_thread_worker), pollset->root_worker));
(void*)gpr_tls_get(&g_current_thread_worker),
pollset->root_worker);
gpr_strvec_add(&log, tmp);
if (pollset->root_worker != nullptr) { if (pollset->root_worker != nullptr) {
gpr_asprintf(&tmp, " {kick_state=%s next=%p {kick_state=%s}}", log.push_back(absl::StrFormat(
kick_state_string(pollset->root_worker->state), " {kick_state=%s next=%p {kick_state=%s}}",
pollset->root_worker->next, kick_state_string(pollset->root_worker->state),
kick_state_string(pollset->root_worker->next->state)); pollset->root_worker->next,
gpr_strvec_add(&log, tmp); kick_state_string(pollset->root_worker->next->state)));
} }
if (specific_worker != nullptr) { if (specific_worker != nullptr) {
gpr_asprintf(&tmp, " worker_kick_state=%s", log.push_back(absl::StrFormat(" worker_kick_state=%s",
kick_state_string(specific_worker->state)); kick_state_string(specific_worker->state)));
gpr_strvec_add(&log, tmp);
} }
tmp = gpr_strvec_flatten(&log, nullptr); gpr_log(GPR_DEBUG, "%s", absl::StrJoin(log, "").c_str());
gpr_strvec_destroy(&log);
gpr_log(GPR_DEBUG, "%s", tmp);
gpr_free(tmp);
} }
if (specific_worker == nullptr) { if (specific_worker == nullptr) {

@ -24,6 +24,7 @@
#include <string.h> #include <string.h>
#include "absl/container/inlined_vector.h" #include "absl/container/inlined_vector.h"
#include "absl/strings/str_join.h"
#include <grpc/grpc_security.h> #include <grpc/grpc_security.h>
#include <grpc/impl/codegen/slice.h> #include <grpc/impl/codegen/slice.h>
@ -523,12 +524,10 @@ namespace grpc_core {
namespace { namespace {
void MaybeAddToBody(gpr_strvec* body_strvec, const char* field_name, void MaybeAddToBody(const char* field_name, const char* field,
const char* field) { std::vector<std::string>* body) {
if (field == nullptr || strlen(field) == 0) return; if (field == nullptr || strlen(field) == 0) return;
char* new_query; body->push_back(absl::StrFormat("&%s=%s", field_name, field));
gpr_asprintf(&new_query, "&%s=%s", field_name, field);
gpr_strvec_add(body_strvec, new_query);
} }
grpc_error* LoadTokenFile(const char* path, gpr_slice* token) { grpc_error* LoadTokenFile(const char* path, gpr_slice* token) {
@ -608,20 +607,18 @@ class StsTokenFetcherCredentials
grpc_error* FillBody(char** body, size_t* body_length) { grpc_error* FillBody(char** body, size_t* body_length) {
*body = nullptr; *body = nullptr;
gpr_strvec body_strvec; std::vector<std::string> body_parts;
gpr_strvec_init(&body_strvec);
grpc_slice subject_token = grpc_empty_slice(); grpc_slice subject_token = grpc_empty_slice();
grpc_slice actor_token = grpc_empty_slice(); grpc_slice actor_token = grpc_empty_slice();
grpc_error* err = GRPC_ERROR_NONE; grpc_error* err = GRPC_ERROR_NONE;
auto cleanup = [&body, &body_length, &body_strvec, &subject_token, auto cleanup = [&body, &body_length, &body_parts, &subject_token,
&actor_token, &err]() { &actor_token, &err]() {
if (err == GRPC_ERROR_NONE) { if (err == GRPC_ERROR_NONE) {
*body = gpr_strvec_flatten(&body_strvec, body_length); std::string body_str = absl::StrJoin(body_parts, "");
} else { *body = gpr_strdup(body_str.c_str());
gpr_free(*body); *body_length = body_str.size();
} }
gpr_strvec_destroy(&body_strvec);
grpc_slice_unref_internal(subject_token); grpc_slice_unref_internal(subject_token);
grpc_slice_unref_internal(actor_token); grpc_slice_unref_internal(actor_token);
return err; return err;
@ -629,23 +626,23 @@ class StsTokenFetcherCredentials
err = LoadTokenFile(subject_token_path_.get(), &subject_token); err = LoadTokenFile(subject_token_path_.get(), &subject_token);
if (err != GRPC_ERROR_NONE) return cleanup(); if (err != GRPC_ERROR_NONE) return cleanup();
gpr_asprintf( body_parts.push_back(absl::StrFormat(
body, GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING, GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING,
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(subject_token)), reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(subject_token)),
subject_token_type_.get()); subject_token_type_.get()));
gpr_strvec_add(&body_strvec, *body); MaybeAddToBody("resource", resource_.get(), &body_parts);
MaybeAddToBody(&body_strvec, "resource", resource_.get()); MaybeAddToBody("audience", audience_.get(), &body_parts);
MaybeAddToBody(&body_strvec, "audience", audience_.get()); MaybeAddToBody("scope", scope_.get(), &body_parts);
MaybeAddToBody(&body_strvec, "scope", scope_.get()); MaybeAddToBody("requested_token_type", requested_token_type_.get(),
MaybeAddToBody(&body_strvec, "requested_token_type", &body_parts);
requested_token_type_.get());
if ((actor_token_path_ != nullptr) && *actor_token_path_ != '\0') { if ((actor_token_path_ != nullptr) && *actor_token_path_ != '\0') {
err = LoadTokenFile(actor_token_path_.get(), &actor_token); err = LoadTokenFile(actor_token_path_.get(), &actor_token);
if (err != GRPC_ERROR_NONE) return cleanup(); if (err != GRPC_ERROR_NONE) return cleanup();
MaybeAddToBody( MaybeAddToBody(
&body_strvec, "actor_token", "actor_token",
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(actor_token))); reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(actor_token)),
MaybeAddToBody(&body_strvec, "actor_token_type", actor_token_type_.get()); &body_parts);
MaybeAddToBody("actor_token_type", actor_token_type_.get(), &body_parts);
} }
return cleanup(); return cleanup();
} }

@ -22,98 +22,90 @@
#include <inttypes.h> #include <inttypes.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/string.h"
#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/slice/slice_string_helpers.h"
static void add_metadata(gpr_strvec* b, const grpc_metadata* md, size_t count) { static void add_metadata(const grpc_metadata* md, size_t count,
size_t i; std::vector<std::string>* b) {
if (md == nullptr) { if (md == nullptr) {
gpr_strvec_add(b, gpr_strdup("(nil)")); b->push_back("(nil)");
return; return;
} }
for (i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
gpr_strvec_add(b, gpr_strdup("\nkey=")); b->push_back("\nkey=");
gpr_strvec_add(b, grpc_slice_to_c_string(md[i].key)); b->push_back(std::string(grpc_core::StringViewFromSlice(md[i].key)));
b->push_back(" value=");
gpr_strvec_add(b, gpr_strdup(" value=")); char* dump = grpc_dump_slice(md[i].value, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_strvec_add(b, b->push_back(dump);
grpc_dump_slice(md[i].value, GPR_DUMP_HEX | GPR_DUMP_ASCII)); gpr_free(dump);
} }
} }
char* grpc_op_string(const grpc_op* op) { static std::string grpc_op_string(const grpc_op* op) {
char* tmp; std::vector<std::string> parts;
char* out;
gpr_strvec b;
gpr_strvec_init(&b);
switch (op->op) { switch (op->op) {
case GRPC_OP_SEND_INITIAL_METADATA: case GRPC_OP_SEND_INITIAL_METADATA:
gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA")); parts.push_back("SEND_INITIAL_METADATA");
add_metadata(&b, op->data.send_initial_metadata.metadata, add_metadata(op->data.send_initial_metadata.metadata,
op->data.send_initial_metadata.count); op->data.send_initial_metadata.count, &parts);
break; break;
case GRPC_OP_SEND_MESSAGE: case GRPC_OP_SEND_MESSAGE:
gpr_asprintf(&tmp, "SEND_MESSAGE ptr=%p", parts.push_back(absl::StrFormat("SEND_MESSAGE ptr=%p",
op->data.send_message.send_message); op->data.send_message.send_message));
gpr_strvec_add(&b, tmp);
break; break;
case GRPC_OP_SEND_CLOSE_FROM_CLIENT: case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
gpr_strvec_add(&b, gpr_strdup("SEND_CLOSE_FROM_CLIENT")); parts.push_back("SEND_CLOSE_FROM_CLIENT");
break; break;
case GRPC_OP_SEND_STATUS_FROM_SERVER: case GRPC_OP_SEND_STATUS_FROM_SERVER:
gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=", parts.push_back(
op->data.send_status_from_server.status); absl::StrFormat("SEND_STATUS_FROM_SERVER status=%d details=",
gpr_strvec_add(&b, tmp); op->data.send_status_from_server.status));
if (op->data.send_status_from_server.status_details != nullptr) { if (op->data.send_status_from_server.status_details != nullptr) {
gpr_strvec_add(&b, grpc_dump_slice( char* dump = grpc_dump_slice(
*op->data.send_status_from_server.status_details, *op->data.send_status_from_server.status_details, GPR_DUMP_ASCII);
GPR_DUMP_ASCII)); parts.push_back(dump);
gpr_free(dump);
} else { } else {
gpr_strvec_add(&b, gpr_strdup("(null)")); parts.push_back("(null)");
} }
add_metadata(&b, op->data.send_status_from_server.trailing_metadata, add_metadata(op->data.send_status_from_server.trailing_metadata,
op->data.send_status_from_server.trailing_metadata_count); op->data.send_status_from_server.trailing_metadata_count,
&parts);
break; break;
case GRPC_OP_RECV_INITIAL_METADATA: case GRPC_OP_RECV_INITIAL_METADATA:
gpr_asprintf(&tmp, "RECV_INITIAL_METADATA ptr=%p", parts.push_back(absl::StrFormat(
op->data.recv_initial_metadata.recv_initial_metadata); "RECV_INITIAL_METADATA ptr=%p",
gpr_strvec_add(&b, tmp); op->data.recv_initial_metadata.recv_initial_metadata));
break; break;
case GRPC_OP_RECV_MESSAGE: case GRPC_OP_RECV_MESSAGE:
gpr_asprintf(&tmp, "RECV_MESSAGE ptr=%p", parts.push_back(absl::StrFormat("RECV_MESSAGE ptr=%p",
op->data.recv_message.recv_message); op->data.recv_message.recv_message));
gpr_strvec_add(&b, tmp);
break; break;
case GRPC_OP_RECV_STATUS_ON_CLIENT: case GRPC_OP_RECV_STATUS_ON_CLIENT:
gpr_asprintf(&tmp, parts.push_back(absl::StrFormat(
"RECV_STATUS_ON_CLIENT metadata=%p status=%p details=%p", "RECV_STATUS_ON_CLIENT metadata=%p status=%p details=%p",
op->data.recv_status_on_client.trailing_metadata, op->data.recv_status_on_client.trailing_metadata,
op->data.recv_status_on_client.status, op->data.recv_status_on_client.status,
op->data.recv_status_on_client.status_details); op->data.recv_status_on_client.status_details));
gpr_strvec_add(&b, tmp);
break; break;
case GRPC_OP_RECV_CLOSE_ON_SERVER: case GRPC_OP_RECV_CLOSE_ON_SERVER:
gpr_asprintf(&tmp, "RECV_CLOSE_ON_SERVER cancelled=%p", parts.push_back(absl::StrFormat("RECV_CLOSE_ON_SERVER cancelled=%p",
op->data.recv_close_on_server.cancelled); op->data.recv_close_on_server.cancelled));
gpr_strvec_add(&b, tmp);
} }
out = gpr_strvec_flatten(&b, nullptr); return absl::StrJoin(parts, "");
gpr_strvec_destroy(&b);
return out;
} }
void grpc_call_log_batch(const char* file, int line, gpr_log_severity severity, void grpc_call_log_batch(const char* file, int line, gpr_log_severity severity,
const grpc_op* ops, size_t nops) { const grpc_op* ops, size_t nops) {
char* tmp; for (size_t i = 0; i < nops; i++) {
size_t i; gpr_log(file, line, severity, "ops[%" PRIuPTR "]: %s", i,
for (i = 0; i < nops; i++) { grpc_op_string(&ops[i]).c_str());
tmp = grpc_op_string(&ops[i]);
gpr_log(file, line, severity, "ops[%" PRIuPTR "]: %s", i, tmp);
gpr_free(tmp);
} }
} }

@ -23,6 +23,11 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/atm.h> #include <grpc/support/atm.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
@ -430,15 +435,14 @@ static const cq_vtable g_cq_vtable[] = {
grpc_core::TraceFlag grpc_cq_pluck_trace(false, "queue_pluck"); grpc_core::TraceFlag grpc_cq_pluck_trace(false, "queue_pluck");
#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \ #define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \
do { \ do { \
if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace) && \ if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace) && \
(GRPC_TRACE_FLAG_ENABLED(grpc_cq_pluck_trace) || \ (GRPC_TRACE_FLAG_ENABLED(grpc_cq_pluck_trace) || \
(event)->type != GRPC_QUEUE_TIMEOUT)) { \ (event)->type != GRPC_QUEUE_TIMEOUT)) { \
char* _ev = grpc_event_string(event); \ gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, \
gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \ grpc_event_string(event).c_str()); \
gpr_free(_ev); \ } \
} \
} while (0) } while (0)
static void on_pollset_shutdown_done(void* cq, grpc_error* error); static void on_pollset_shutdown_done(void* cq, grpc_error* error);
@ -951,21 +955,14 @@ class ExecCtxNext : public grpc_core::ExecCtx {
#ifndef NDEBUG #ifndef NDEBUG
static void dump_pending_tags(grpc_completion_queue* cq) { static void dump_pending_tags(grpc_completion_queue* cq) {
if (!GRPC_TRACE_FLAG_ENABLED(grpc_trace_pending_tags)) return; if (!GRPC_TRACE_FLAG_ENABLED(grpc_trace_pending_tags)) return;
std::vector<std::string> parts;
gpr_strvec v; parts.push_back("PENDING TAGS:");
gpr_strvec_init(&v);
gpr_strvec_add(&v, gpr_strdup("PENDING TAGS:"));
gpr_mu_lock(cq->mu); gpr_mu_lock(cq->mu);
for (size_t i = 0; i < cq->outstanding_tag_count; i++) { for (size_t i = 0; i < cq->outstanding_tag_count; i++) {
char* s; parts.push_back(absl::StrFormat(" %p", cq->outstanding_tags[i]));
gpr_asprintf(&s, " %p", cq->outstanding_tags[i]);
gpr_strvec_add(&v, s);
} }
gpr_mu_unlock(cq->mu); gpr_mu_unlock(cq->mu);
char* out = gpr_strvec_flatten(&v, nullptr); gpr_log(GPR_DEBUG, "%s", absl::StrJoin(parts, "").c_str());
gpr_strvec_destroy(&v);
gpr_log(GPR_DEBUG, "%s", out);
gpr_free(out);
} }
#else #else
static void dump_pending_tags(grpc_completion_queue* /*cq*/) {} static void dump_pending_tags(grpc_completion_queue* /*cq*/) {}

@ -22,47 +22,40 @@
#include <stdio.h> #include <stdio.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/string.h"
static void addhdr(gpr_strvec* buf, grpc_event* ev) { static void addhdr(grpc_event* ev, std::vector<std::string>* buf) {
char* tmp; buf->push_back(absl::StrFormat("tag:%p", ev->tag));
gpr_asprintf(&tmp, "tag:%p", ev->tag);
gpr_strvec_add(buf, tmp);
} }
static const char* errstr(int success) { return success ? "OK" : "ERROR"; } static const char* errstr(int success) { return success ? "OK" : "ERROR"; }
static void adderr(gpr_strvec* buf, int success) { static void adderr(int success, std::vector<std::string>* buf) {
char* tmp; buf->push_back(absl::StrFormat(" %s", errstr(success)));
gpr_asprintf(&tmp, " %s", errstr(success));
gpr_strvec_add(buf, tmp);
} }
char* grpc_event_string(grpc_event* ev) { std::string grpc_event_string(grpc_event* ev) {
char* out; if (ev == nullptr) return "null";
gpr_strvec buf; std::vector<std::string> out;
if (ev == nullptr) return gpr_strdup("null");
gpr_strvec_init(&buf);
switch (ev->type) { switch (ev->type) {
case GRPC_QUEUE_TIMEOUT: case GRPC_QUEUE_TIMEOUT:
gpr_strvec_add(&buf, gpr_strdup("QUEUE_TIMEOUT")); out.push_back("QUEUE_TIMEOUT");
break; break;
case GRPC_QUEUE_SHUTDOWN: case GRPC_QUEUE_SHUTDOWN:
gpr_strvec_add(&buf, gpr_strdup("QUEUE_SHUTDOWN")); out.push_back("QUEUE_SHUTDOWN");
break; break;
case GRPC_OP_COMPLETE: case GRPC_OP_COMPLETE:
gpr_strvec_add(&buf, gpr_strdup("OP_COMPLETE: ")); out.push_back("OP_COMPLETE: ");
addhdr(&buf, ev); addhdr(ev, &out);
adderr(&buf, ev->success); adderr(ev->success, &out);
break; break;
} }
return absl::StrJoin(out, "");
out = gpr_strvec_flatten(&buf, nullptr);
gpr_strvec_destroy(&buf);
return out;
} }

@ -21,9 +21,11 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <string>
#include <grpc/grpc.h> #include <grpc/grpc.h>
/* Returns a string describing an event. Must be later freed with gpr_free() */ /* Returns a string describing an event. Must be later freed with gpr_free() */
char* grpc_event_string(grpc_event* ev); std::string grpc_event_string(grpc_event* ev);
#endif /* GRPC_CORE_LIB_SURFACE_EVENT_STRING_H */ #endif /* GRPC_CORE_LIB_SURFACE_EVENT_STRING_H */

@ -408,8 +408,9 @@ void grpc_transport_stream_op_batch_finish_with_failure(
grpc_transport_stream_op_batch* op, grpc_error* error, grpc_transport_stream_op_batch* op, grpc_error* error,
grpc_core::CallCombiner* call_combiner); grpc_core::CallCombiner* call_combiner);
char* grpc_transport_stream_op_batch_string(grpc_transport_stream_op_batch* op); std::string grpc_transport_stream_op_batch_string(
char* grpc_transport_op_string(grpc_transport_op* op); grpc_transport_stream_op_batch* op);
std::string grpc_transport_op_string(grpc_transport_op* op);
/* Send a batch of operations on a transport /* Send a batch of operations on a transport

@ -25,6 +25,12 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <vector>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/string.h"
@ -34,177 +40,130 @@
/* These routines are here to facilitate debugging - they produce string /* These routines are here to facilitate debugging - they produce string
representations of various transport data structures */ representations of various transport data structures */
static void put_metadata(gpr_strvec* b, grpc_mdelem md) { static void put_metadata(grpc_mdelem md, std::vector<std::string>* out) {
gpr_strvec_add(b, gpr_strdup("key=")); out->push_back("key=");
gpr_strvec_add( char* dump = grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
b, grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII)); out->push_back(dump);
gpr_free(dump);
gpr_strvec_add(b, gpr_strdup(" value=")); out->push_back(" value=");
gpr_strvec_add( dump = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
b, grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII)); out->push_back(dump);
gpr_free(dump);
} }
static void put_metadata_list(gpr_strvec* b, grpc_metadata_batch md) { static void put_metadata_list(grpc_metadata_batch md,
std::vector<std::string>* out) {
grpc_linked_mdelem* m; grpc_linked_mdelem* m;
for (m = md.list.head; m != nullptr; m = m->next) { for (m = md.list.head; m != nullptr; m = m->next) {
if (m != md.list.head) gpr_strvec_add(b, gpr_strdup(", ")); if (m != md.list.head) out->push_back(", ");
put_metadata(b, m->md); put_metadata(m->md, out);
} }
if (md.deadline != GRPC_MILLIS_INF_FUTURE) { if (md.deadline != GRPC_MILLIS_INF_FUTURE) {
char* tmp; out->push_back(absl::StrFormat(" deadline=%" PRId64, md.deadline));
gpr_asprintf(&tmp, " deadline=%" PRId64, md.deadline);
gpr_strvec_add(b, tmp);
} }
} }
char* grpc_transport_stream_op_batch_string( std::string grpc_transport_stream_op_batch_string(
grpc_transport_stream_op_batch* op) { grpc_transport_stream_op_batch* op) {
char* tmp; std::vector<std::string> out;
char* out;
gpr_strvec b;
gpr_strvec_init(&b);
if (op->send_initial_metadata) { if (op->send_initial_metadata) {
gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(" SEND_INITIAL_METADATA{");
gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA{")); put_metadata_list(*op->payload->send_initial_metadata.send_initial_metadata,
put_metadata_list( &out);
&b, *op->payload->send_initial_metadata.send_initial_metadata); out.push_back("}");
gpr_strvec_add(&b, gpr_strdup("}"));
} }
if (op->send_message) { if (op->send_message) {
gpr_strvec_add(&b, gpr_strdup(" "));
if (op->payload->send_message.send_message != nullptr) { if (op->payload->send_message.send_message != nullptr) {
gpr_asprintf(&tmp, "SEND_MESSAGE:flags=0x%08x:len=%d", out.push_back(
op->payload->send_message.send_message->flags(), absl::StrFormat(" SEND_MESSAGE:flags=0x%08x:len=%d",
op->payload->send_message.send_message->length()); op->payload->send_message.send_message->flags(),
op->payload->send_message.send_message->length()));
} else { } else {
// This can happen when we check a batch after the transport has // This can happen when we check a batch after the transport has
// processed and cleared the send_message op. // processed and cleared the send_message op.
tmp = out.push_back(" SEND_MESSAGE(flag and length unknown, already orphaned)");
gpr_strdup("SEND_MESSAGE(flag and length unknown, already orphaned)");
} }
gpr_strvec_add(&b, tmp);
} }
if (op->send_trailing_metadata) { if (op->send_trailing_metadata) {
gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(" SEND_TRAILING_METADATA{");
gpr_strvec_add(&b, gpr_strdup("SEND_TRAILING_METADATA{"));
put_metadata_list( put_metadata_list(
&b, *op->payload->send_trailing_metadata.send_trailing_metadata); *op->payload->send_trailing_metadata.send_trailing_metadata, &out);
gpr_strvec_add(&b, gpr_strdup("}")); out.push_back("}");
} }
if (op->recv_initial_metadata) { if (op->recv_initial_metadata) {
gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(" RECV_INITIAL_METADATA");
gpr_strvec_add(&b, gpr_strdup("RECV_INITIAL_METADATA"));
} }
if (op->recv_message) { if (op->recv_message) {
gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(" RECV_MESSAGE");
gpr_strvec_add(&b, gpr_strdup("RECV_MESSAGE"));
} }
if (op->recv_trailing_metadata) { if (op->recv_trailing_metadata) {
gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(" RECV_TRAILING_METADATA");
gpr_strvec_add(&b, gpr_strdup("RECV_TRAILING_METADATA"));
} }
if (op->cancel_stream) { if (op->cancel_stream) {
gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(absl::StrCat(
const char* msg = " CANCEL:",
grpc_error_string(op->payload->cancel_stream.cancel_error); grpc_error_string(op->payload->cancel_stream.cancel_error)));
gpr_asprintf(&tmp, "CANCEL:%s", msg);
gpr_strvec_add(&b, tmp);
} }
out = gpr_strvec_flatten(&b, nullptr); return absl::StrJoin(out, "");
gpr_strvec_destroy(&b);
return out;
} }
char* grpc_transport_op_string(grpc_transport_op* op) { std::string grpc_transport_op_string(grpc_transport_op* op) {
char* tmp; std::vector<std::string> out;
char* out;
bool first = true;
gpr_strvec b;
gpr_strvec_init(&b);
if (op->start_connectivity_watch != nullptr) { if (op->start_connectivity_watch != nullptr) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(absl::StrFormat(
first = false; " START_CONNECTIVITY_WATCH:watcher=%p:from=%s",
gpr_asprintf(
&tmp, "START_CONNECTIVITY_WATCH:watcher=%p:from=%s",
op->start_connectivity_watch.get(), op->start_connectivity_watch.get(),
grpc_core::ConnectivityStateName(op->start_connectivity_watch_state)); grpc_core::ConnectivityStateName(op->start_connectivity_watch_state)));
gpr_strvec_add(&b, tmp);
} }
if (op->stop_connectivity_watch != nullptr) { if (op->stop_connectivity_watch != nullptr) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(absl::StrFormat(" STOP_CONNECTIVITY_WATCH:watcher=%p",
first = false; op->stop_connectivity_watch));
gpr_asprintf(&tmp, "STOP_CONNECTIVITY_WATCH:watcher=%p",
op->stop_connectivity_watch);
gpr_strvec_add(&b, tmp);
} }
if (op->disconnect_with_error != GRPC_ERROR_NONE) { if (op->disconnect_with_error != GRPC_ERROR_NONE) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(absl::StrCat(" DISCONNECT:",
first = false; grpc_error_string(op->disconnect_with_error)));
const char* err = grpc_error_string(op->disconnect_with_error);
gpr_asprintf(&tmp, "DISCONNECT:%s", err);
gpr_strvec_add(&b, tmp);
} }
if (op->goaway_error) { if (op->goaway_error) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(
first = false; absl::StrCat(" SEND_GOAWAY:%s", grpc_error_string(op->goaway_error)));
const char* msg = grpc_error_string(op->goaway_error);
gpr_asprintf(&tmp, "SEND_GOAWAY:%s", msg);
gpr_strvec_add(&b, tmp);
} }
if (op->set_accept_stream) { if (op->set_accept_stream) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(absl::StrFormat(" SET_ACCEPT_STREAM:%p(%p,...)",
first = false; op->set_accept_stream_fn,
gpr_asprintf(&tmp, "SET_ACCEPT_STREAM:%p(%p,...)", op->set_accept_stream_fn, op->set_accept_stream_user_data));
op->set_accept_stream_user_data);
gpr_strvec_add(&b, tmp);
} }
if (op->bind_pollset != nullptr) { if (op->bind_pollset != nullptr) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(" BIND_POLLSET");
first = false;
gpr_strvec_add(&b, gpr_strdup("BIND_POLLSET"));
} }
if (op->bind_pollset_set != nullptr) { if (op->bind_pollset_set != nullptr) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(" BIND_POLLSET_SET");
first = false;
gpr_strvec_add(&b, gpr_strdup("BIND_POLLSET_SET"));
} }
if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) { if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); out.push_back(" SEND_PING");
// first = false;
gpr_strvec_add(&b, gpr_strdup("SEND_PING"));
} }
out = gpr_strvec_flatten(&b, nullptr); return absl::StrJoin(out, "");
gpr_strvec_destroy(&b);
return out;
} }
void grpc_call_log_op(const char* file, int line, gpr_log_severity severity, void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
grpc_call_element* elem, grpc_call_element* elem,
grpc_transport_stream_op_batch* op) { grpc_transport_stream_op_batch* op) {
char* str = grpc_transport_stream_op_batch_string(op); gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem,
gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem, str); grpc_transport_stream_op_batch_string(op).c_str());
gpr_free(str);
} }

@ -122,7 +122,7 @@ cdef extern from "src/core/lib/iomgr/iomgr_custom.h":
cdef extern from "src/core/lib/iomgr/sockaddr_utils.h": cdef extern from "src/core/lib/iomgr/sockaddr_utils.h":
int grpc_sockaddr_get_port(const grpc_resolved_address *addr); int grpc_sockaddr_get_port(const grpc_resolved_address *addr);
cppstring grpc_sockaddr_to_string(const grpc_resolved_address *addr, cppstring grpc_sockaddr_to_string(const grpc_resolved_address *addr,
bool_t normalize); bool_t normalize);
void grpc_string_to_sockaddr(grpc_resolved_address *out, char* addr, int port); void grpc_string_to_sockaddr(grpc_resolved_address *out, char* addr, int port);
int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr, int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr,
int port) int port)

@ -20,6 +20,9 @@
#include <string.h> #include <string.h>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/string.h"
@ -144,22 +147,17 @@ int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv); grpc::testing::TestEnvironment env(argc, argv);
// Test sending more metadata than the server will accept. // Test sending more metadata than the server will accept.
gpr_strvec headers; std::vector<std::string> headers;
gpr_strvec_init(&headers);
for (i = 0; i < NUM_HEADERS; ++i) { for (i = 0; i < NUM_HEADERS; ++i) {
char* str; headers.push_back(absl::StrFormat(
gpr_asprintf(&str, "%s%02d%s", "%s%02d%s", PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR, i,
PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR, i, PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR));
PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR);
gpr_strvec_add(&headers, str);
} }
size_t headers_len; std::string client_headers = absl::StrJoin(headers, "");
const char* client_headers = gpr_strvec_flatten(&headers, &headers_len);
gpr_strvec_destroy(&headers);
char client_payload[TOO_MUCH_METADATA_FROM_CLIENT_REQUEST_SIZE] = char client_payload[TOO_MUCH_METADATA_FROM_CLIENT_REQUEST_SIZE] =
PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST; PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST;
memcpy(client_payload + sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST) - 1, memcpy(client_payload + sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST) - 1,
client_headers, headers_len); client_headers.data(), client_headers.size());
grpc_bad_client_arg args[2]; grpc_bad_client_arg args[2];
args[0] = connection_preface_arg; args[0] = connection_preface_arg;
args[1].client_validator = rst_stream_client_validator; args[1].client_validator = rst_stream_client_validator;
@ -167,7 +165,6 @@ int main(int argc, char** argv) {
args[1].client_payload_length = sizeof(client_payload) - 1; args[1].client_payload_length = sizeof(client_payload) - 1;
grpc_run_bad_client_test(server_verifier_request_call, args, 2, 0); grpc_run_bad_client_test(server_verifier_request_call, args, 2, 0);
gpr_free((void*)client_headers);
// Test sending more metadata than the client will accept. // Test sending more metadata than the client will accept.
GRPC_RUN_BAD_CLIENT_TEST(server_verifier_sends_too_much_metadata, GRPC_RUN_BAD_CLIENT_TEST(server_verifier_sends_too_much_metadata,

@ -34,6 +34,10 @@
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include <string.h> #include <string.h>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/string.h"
#include "src/core/lib/surface/channel_init.h" #include "src/core/lib/surface/channel_init.h"
@ -138,64 +142,51 @@ static int check_stack(const char* file, int line, const char* transport_name,
} }
// build up our expectation list // build up our expectation list
gpr_strvec v; std::vector<std::string> parts;
gpr_strvec_init(&v);
va_list args; va_list args;
va_start(args, channel_stack_type); va_start(args, channel_stack_type);
for (;;) { for (;;) {
char* a = va_arg(args, char*); char* a = va_arg(args, char*);
if (a == nullptr) break; if (a == nullptr) break;
if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", ")); parts.push_back(a);
gpr_strvec_add(&v, gpr_strdup(a));
} }
va_end(args); va_end(args);
char* expect = gpr_strvec_flatten(&v, nullptr); std::string expect = absl::StrJoin(parts, ", ");
gpr_strvec_destroy(&v);
// build up our "got" list // build up our "got" list
gpr_strvec_init(&v); parts.clear();
grpc_channel_stack_builder_iterator* it = grpc_channel_stack_builder_iterator* it =
grpc_channel_stack_builder_create_iterator_at_first(builder); grpc_channel_stack_builder_create_iterator_at_first(builder);
while (grpc_channel_stack_builder_move_next(it)) { while (grpc_channel_stack_builder_move_next(it)) {
const char* name = grpc_channel_stack_builder_iterator_filter_name(it); const char* name = grpc_channel_stack_builder_iterator_filter_name(it);
if (name == nullptr) continue; if (name == nullptr) continue;
if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", ")); parts.push_back(name);
gpr_strvec_add(&v, gpr_strdup(name));
} }
char* got = gpr_strvec_flatten(&v, nullptr); std::string got = absl::StrJoin(parts, ", ");
gpr_strvec_destroy(&v);
grpc_channel_stack_builder_iterator_destroy(it); grpc_channel_stack_builder_iterator_destroy(it);
// figure out result, log if there's an error // figure out result, log if there's an error
int result = 0; int result = 0;
if (0 != strcmp(got, expect)) { if (got != expect) {
gpr_strvec_init(&v); parts.clear();
gpr_strvec_add(&v, gpr_strdup("{"));
for (size_t i = 0; i < channel_args->num_args; i++) { for (size_t i = 0; i < channel_args->num_args; i++) {
if (i > 0) gpr_strvec_add(&v, gpr_strdup(", ")); std::string value;
gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].key));
gpr_strvec_add(&v, gpr_strdup("="));
switch (channel_args->args[i].type) { switch (channel_args->args[i].type) {
case GRPC_ARG_INTEGER: { case GRPC_ARG_INTEGER: {
char* tmp; value = absl::StrCat(channel_args->args[i].value.integer);
gpr_asprintf(&tmp, "%d", channel_args->args[i].value.integer);
gpr_strvec_add(&v, tmp);
break; break;
} }
case GRPC_ARG_STRING: case GRPC_ARG_STRING:
gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].value.string)); value = channel_args->args[i].value.string;
break; break;
case GRPC_ARG_POINTER: { case GRPC_ARG_POINTER: {
char* tmp; value = absl::StrFormat("%p", channel_args->args[i].value.pointer.p);
gpr_asprintf(&tmp, "%p", channel_args->args[i].value.pointer.p);
gpr_strvec_add(&v, tmp);
break; break;
} }
} }
parts.push_back(absl::StrCat(channel_args->args[i].key, "=", value));
} }
gpr_strvec_add(&v, gpr_strdup("}")); std::string args_str = absl::StrCat("{", absl::StrJoin(parts, ", "), "}");
char* args_str = gpr_strvec_flatten(&v, nullptr);
gpr_strvec_destroy(&v);
gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, gpr_log(file, line, GPR_LOG_SEVERITY_ERROR,
"**************************************************"); "**************************************************");
@ -204,17 +195,12 @@ static int check_stack(const char* file, int line, const char* transport_name,
"FAILED transport=%s; stack_type=%s; channel_args=%s:", transport_name, "FAILED transport=%s; stack_type=%s; channel_args=%s:", transport_name,
grpc_channel_stack_type_string( grpc_channel_stack_type_string(
static_cast<grpc_channel_stack_type>(channel_stack_type)), static_cast<grpc_channel_stack_type>(channel_stack_type)),
args_str); args_str.c_str());
gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "EXPECTED: %s", expect); gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "EXPECTED: %s", expect.c_str());
gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "GOT: %s", got); gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "GOT: %s", got.c_str());
result = 1; result = 1;
gpr_free(args_str);
} }
gpr_free(got);
gpr_free(expect);
{ {
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
grpc_channel_stack_builder_destroy(builder); grpc_channel_stack_builder_destroy(builder);

@ -23,6 +23,12 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <string>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/byte_buffer_reader.h> #include <grpc/byte_buffer_reader.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
@ -171,21 +177,19 @@ int byte_buffer_eq_string(grpc_byte_buffer* bb, const char* str) {
static bool is_probably_integer(void* p) { return ((uintptr_t)p) < 1000000; } static bool is_probably_integer(void* p) { return ((uintptr_t)p) < 1000000; }
static void expectation_to_strvec(gpr_strvec* buf, expectation* e) { namespace {
char* tmp;
if (is_probably_integer(e->tag)) { std::string ExpectationString(const expectation& e) {
gpr_asprintf(&tmp, "tag(%" PRIdPTR ") ", (intptr_t)e->tag); std::string out;
if (is_probably_integer(e.tag)) {
out = absl::StrFormat("tag(%" PRIdPTR ") ", (intptr_t)e.tag);
} else { } else {
gpr_asprintf(&tmp, "%p ", e->tag); out = absl::StrFormat("%p ", e.tag);
} }
gpr_strvec_add(buf, tmp); switch (e.type) {
switch (e->type) {
case GRPC_OP_COMPLETE: case GRPC_OP_COMPLETE:
gpr_asprintf(&tmp, "GRPC_OP_COMPLETE success=%d %s:%d", e->success, absl::StrAppendFormat(&out, "GRPC_OP_COMPLETE success=%d %s:%d",
e->file, e->line); e.success, e.file, e.line);
gpr_strvec_add(buf, tmp);
break; break;
case GRPC_QUEUE_TIMEOUT: case GRPC_QUEUE_TIMEOUT:
case GRPC_QUEUE_SHUTDOWN: case GRPC_QUEUE_SHUTDOWN:
@ -193,27 +197,22 @@ static void expectation_to_strvec(gpr_strvec* buf, expectation* e) {
abort(); abort();
break; break;
} }
return out;
} }
static void expectations_to_strvec(gpr_strvec* buf, cq_verifier* v) { std::string ExpectationsString(const cq_verifier& v) {
expectation* e; std::vector<std::string> expectations;
for (expectation* e = v.first_expectation; e != nullptr; e = e->next) {
for (e = v->first_expectation; e != nullptr; e = e->next) { expectations.push_back(ExpectationString(*e));
expectation_to_strvec(buf, e);
gpr_strvec_add(buf, gpr_strdup("\n"));
} }
return absl::StrJoin(expectations, "\n");
} }
} // namespace
static void fail_no_event_received(cq_verifier* v) { static void fail_no_event_received(cq_verifier* v) {
gpr_strvec buf; gpr_log(GPR_ERROR, "no event received, but expected:%s",
char* msg; ExpectationsString(*v).c_str());
gpr_strvec_init(&buf);
gpr_strvec_add(&buf, gpr_strdup("no event received, but expected:\n"));
expectations_to_strvec(&buf, v);
msg = gpr_strvec_flatten(&buf, nullptr);
gpr_log(GPR_ERROR, "%s", msg);
gpr_strvec_destroy(&buf);
gpr_free(msg);
abort(); abort();
} }
@ -222,13 +221,8 @@ static void verify_matches(expectation* e, grpc_event* ev) {
switch (e->type) { switch (e->type) {
case GRPC_OP_COMPLETE: case GRPC_OP_COMPLETE:
if (e->check_success && e->success != ev->success) { if (e->check_success && e->success != ev->success) {
gpr_strvec expected; gpr_log(GPR_ERROR, "actual success does not match expected: %s",
gpr_strvec_init(&expected); ExpectationString(*e).c_str());
expectation_to_strvec(&expected, e);
char* s = gpr_strvec_flatten(&expected, nullptr);
gpr_strvec_destroy(&expected);
gpr_log(GPR_ERROR, "actual success does not match expected: %s", s);
gpr_free(s);
abort(); abort();
} }
break; break;
@ -264,16 +258,9 @@ void cq_verify(cq_verifier* v) {
prev = e; prev = e;
} }
if (e == nullptr) { if (e == nullptr) {
char* s = grpc_event_string(&ev); gpr_log(GPR_ERROR, "cq returned unexpected event: %s",
gpr_log(GPR_ERROR, "cq returned unexpected event: %s", s); grpc_event_string(&ev).c_str());
gpr_free(s); gpr_log(GPR_ERROR, "expected tags:\n%s", ExpectationsString(*v).c_str());
gpr_strvec expectations;
gpr_strvec_init(&expectations);
expectations_to_strvec(&expectations, v);
s = gpr_strvec_flatten(&expectations, nullptr);
gpr_strvec_destroy(&expectations);
gpr_log(GPR_ERROR, "expected tags:\n%s", s);
gpr_free(s);
abort(); abort();
} }
} }
@ -290,9 +277,8 @@ void cq_verify_empty_timeout(cq_verifier* v, int timeout_sec) {
ev = grpc_completion_queue_next(v->cq, deadline, nullptr); ev = grpc_completion_queue_next(v->cq, deadline, nullptr);
if (ev.type != GRPC_QUEUE_TIMEOUT) { if (ev.type != GRPC_QUEUE_TIMEOUT) {
char* s = grpc_event_string(&ev); gpr_log(GPR_ERROR, "unexpected event (expected nothing): %s",
gpr_log(GPR_ERROR, "unexpected event (expected nothing): %s", s); grpc_event_string(&ev).c_str());
gpr_free(s);
abort(); abort();
} }
} }

@ -21,6 +21,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <string>
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
@ -245,9 +247,7 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_stats_collect(after); grpc_stats_collect(after);
char* stats = grpc_stats_data_as_json(after); gpr_log(GPR_DEBUG, "%s", grpc_stats_data_as_json(after).c_str());
gpr_log(GPR_DEBUG, "%s", stats);
gpr_free(stats);
GPR_ASSERT(after->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] - GPR_ASSERT(after->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] -
before->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] == before->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] ==

@ -21,6 +21,9 @@
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
@ -37,20 +40,15 @@ static void test_noop(void) { Arena::Create(1)->Destroy(); }
static void test(const char* name, size_t init_size, const size_t* allocs, static void test(const char* name, size_t init_size, const size_t* allocs,
size_t nallocs) { size_t nallocs) {
gpr_strvec v; std::vector<std::string> parts;
char* s; parts.push_back(
gpr_strvec_init(&v); absl::StrFormat("test '%s': %" PRIdPTR " <- {", name, init_size));
gpr_asprintf(&s, "test '%s': %" PRIdPTR " <- {", name, init_size);
gpr_strvec_add(&v, s);
for (size_t i = 0; i < nallocs; i++) { for (size_t i = 0; i < nallocs; i++) {
gpr_asprintf(&s, "%" PRIdPTR ",", allocs[i]); parts.push_back(absl::StrFormat("%" PRIdPTR ",", allocs[i]));
gpr_strvec_add(&v, s);
} }
gpr_strvec_add(&v, gpr_strdup("}")); parts.push_back("}");
s = gpr_strvec_flatten(&v, nullptr); std::string s = absl::StrJoin(parts, "");
gpr_strvec_destroy(&v); gpr_log(GPR_INFO, "%s", s.c_str());
gpr_log(GPR_INFO, "%s", s);
gpr_free(s);
Arena* a = Arena::Create(init_size); Arena* a = Arena::Create(init_size);
void** ps = static_cast<void**>(gpr_zalloc(sizeof(*ps) * nallocs)); void** ps = static_cast<void**>(gpr_zalloc(sizeof(*ps) * nallocs));

@ -37,10 +37,9 @@ typedef struct {
} synchronizer; } synchronizer;
static void print_usage_and_exit(gpr_cmdline* cl, const char* argv0) { static void print_usage_and_exit(gpr_cmdline* cl, const char* argv0) {
char* usage = gpr_cmdline_usage_string(cl, argv0); std::string usage = gpr_cmdline_usage_string(cl, argv0);
fprintf(stderr, "%s", usage); fprintf(stderr, "%s", usage.c_str());
fflush(stderr); fflush(stderr);
gpr_free(usage);
gpr_cmdline_destroy(cl); gpr_cmdline_destroy(cl);
exit(1); exit(1);
} }

@ -22,6 +22,12 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <vector>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
@ -124,60 +130,42 @@ void gpr_cmdline_on_extra_arg(
/* recursively descend argument list, adding the last element /* recursively descend argument list, adding the last element
to s first - so that arguments are added in the order they were to s first - so that arguments are added in the order they were
added to the list by api calls */ added to the list by api calls */
static void add_args_to_usage(gpr_strvec* s, arg* a) { static void add_args_to_usage(arg* a, std::vector<std::string>* s) {
char* tmp; if (a == nullptr) return;
add_args_to_usage(a->next, s);
if (!a) return;
add_args_to_usage(s, a->next);
switch (a->type) { switch (a->type) {
case ARGTYPE_BOOL: case ARGTYPE_BOOL:
gpr_asprintf(&tmp, " [--%s|--no-%s]", a->name, a->name); s->push_back(absl::StrFormat(" [--%s|--no-%s]", a->name, a->name));
gpr_strvec_add(s, tmp);
break; break;
case ARGTYPE_STRING: case ARGTYPE_STRING:
gpr_asprintf(&tmp, " [--%s=string]", a->name); s->push_back(absl::StrFormat(" [--%s=string]", a->name));
gpr_strvec_add(s, tmp);
break; break;
case ARGTYPE_INT: case ARGTYPE_INT:
gpr_asprintf(&tmp, " [--%s=int]", a->name); s->push_back(absl::StrFormat(" [--%s=int]", a->name));
gpr_strvec_add(s, tmp);
break; break;
} }
} }
char* gpr_cmdline_usage_string(gpr_cmdline* cl, const char* argv0) { std::string gpr_cmdline_usage_string(gpr_cmdline* cl, const char* argv0) {
/* TODO(ctiller): make this prettier */
gpr_strvec s;
char* tmp;
const char* name = strrchr(argv0, '/'); const char* name = strrchr(argv0, '/');
if (name != nullptr) {
if (name) {
name++; name++;
} else { } else {
name = argv0; name = argv0;
} }
gpr_strvec_init(&s); std::vector<std::string> s;
s.push_back(absl::StrCat("Usage: ", name));
gpr_asprintf(&tmp, "Usage: %s", name); add_args_to_usage(cl->args, &s);
gpr_strvec_add(&s, tmp);
add_args_to_usage(&s, cl->args);
if (cl->extra_arg) { if (cl->extra_arg) {
gpr_asprintf(&tmp, " [%s...]", cl->extra_arg_name); s.push_back(absl::StrFormat(" [%s...]", cl->extra_arg_name));
gpr_strvec_add(&s, tmp);
} }
gpr_strvec_add(&s, gpr_strdup("\n")); s.push_back("\n");
return absl::StrJoin(s, "");
tmp = gpr_strvec_flatten(&s, nullptr);
gpr_strvec_destroy(&s);
return tmp;
} }
static int print_usage_and_die(gpr_cmdline* cl) { static int print_usage_and_die(gpr_cmdline* cl) {
char* usage = gpr_cmdline_usage_string(cl, cl->argv0); fprintf(stderr, "%s", gpr_cmdline_usage_string(cl, cl->argv0).c_str());
fprintf(stderr, "%s", usage);
gpr_free(usage);
if (!cl->survive_failure) { if (!cl->survive_failure) {
exit(1); exit(1);
} }

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <string>
/** Simple command line parser. /** Simple command line parser.
Supports flags that can be specified as -foo, --foo, --no-foo, -no-foo, etc Supports flags that can be specified as -foo, --foo, --no-foo, -no-foo, etc
@ -75,6 +77,6 @@ int gpr_cmdline_parse(gpr_cmdline* cl, int argc, char** argv);
/** Destroy the parser */ /** Destroy the parser */
void gpr_cmdline_destroy(gpr_cmdline* cl); void gpr_cmdline_destroy(gpr_cmdline* cl);
/** Get a string describing usage */ /** Get a string describing usage */
char* gpr_cmdline_usage_string(gpr_cmdline* cl, const char* argv0); std::string gpr_cmdline_usage_string(gpr_cmdline* cl, const char* argv0);
#endif /* GRPC_TEST_CORE_UTIL_CMDLINE_H */ #endif /* GRPC_TEST_CORE_UTIL_CMDLINE_H */

@ -307,7 +307,6 @@ static void test_extra_dashdash(void) {
static void test_usage(void) { static void test_usage(void) {
gpr_cmdline* cl; gpr_cmdline* cl;
char* usage;
const char* str = nullptr; const char* str = nullptr;
int x = 0; int x = 0;
@ -322,17 +321,15 @@ static void test_usage(void) {
gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb, gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb,
nullptr); nullptr);
usage = gpr_cmdline_usage_string(cl, "test"); std::string usage = gpr_cmdline_usage_string(cl, "test");
GPR_ASSERT(0 == strcmp(usage, GPR_ASSERT(usage ==
"Usage: test [--str=string] [--x=int] " "Usage: test [--str=string] [--x=int] "
"[--flag|--no-flag] [file...]\n")); "[--flag|--no-flag] [file...]\n");
gpr_free(usage);
usage = gpr_cmdline_usage_string(cl, "/foo/test"); usage = gpr_cmdline_usage_string(cl, "/foo/test");
GPR_ASSERT(0 == strcmp(usage, GPR_ASSERT(usage ==
"Usage: test [--str=string] [--x=int] " "Usage: test [--str=string] [--x=int] "
"[--flag|--no-flag] [file...]\n")); "[--flag|--no-flag] [file...]\n");
gpr_free(usage);
gpr_cmdline_destroy(cl); gpr_cmdline_destroy(cl);
} }

Loading…
Cancel
Save