From 87daf00f437b2bc9fb3c2ab662e7f7105e3dfccb Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Fri, 8 Jun 2018 13:50:32 -0700 Subject: Simplify call error/status aggregation --- src/core/lib/surface/call.cc | 341 +++++++++++++------------------------------ 1 file changed, 98 insertions(+), 243 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 1cf8ea94e7..e012244b0f 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -70,46 +70,6 @@ // Used to create arena for the first call. #define ESTIMATED_MDELEM_COUNT 16 -/* Status data for a request can come from several sources; this - enumerates them all, and acts as a priority sorting for which - status to return to the application - earlier entries override - later ones */ -typedef enum { - /* Status came from the application layer overriding whatever - the wire says */ - STATUS_FROM_API_OVERRIDE = 0, - /* Status came from 'the wire' - or somewhere below the surface - layer */ - STATUS_FROM_WIRE, - /* Status was created by some internal channel stack operation: must come via - add_batch_error */ - STATUS_FROM_CORE, - /* Status was created by some surface error */ - STATUS_FROM_SURFACE, - /* Status came from the server sending status */ - STATUS_FROM_SERVER_STATUS, - STATUS_SOURCE_COUNT -} status_source; - -typedef struct { - bool is_set; - grpc_error* error; -} received_status; - -static gpr_atm pack_received_status(received_status r) { - return r.is_set ? (1 | (gpr_atm)r.error) : 0; -} - -static received_status unpack_received_status(gpr_atm atm) { - if ((atm & 1) == 0) { - return {false, GRPC_ERROR_NONE}; - } else { - return {true, (grpc_error*)(atm & ~static_cast(1))}; - } -} - -#define MAX_ERRORS_PER_BATCH 4 - typedef struct batch_control { grpc_call* call; /* Share memory for cq_completion and notify_tag as they are never needed @@ -134,10 +94,7 @@ typedef struct batch_control { grpc_closure start_batch; grpc_closure finish_batch; gpr_refcount steps_to_complete; - - grpc_error* errors[MAX_ERRORS_PER_BATCH]; - gpr_atm num_errors; - + grpc_error* batch_error; grpc_transport_stream_op_batch op; } batch_control; @@ -200,9 +157,6 @@ struct grpc_call { // A char* indicating the peer name. gpr_atm peer_string; - /* Packed received call statuses from various sources */ - gpr_atm status[STATUS_SOURCE_COUNT]; - /* Call data useful used for reporting. Only valid after the call has * completed */ grpc_call_final_info final_info; @@ -234,6 +188,7 @@ struct grpc_call { grpc_closure receiving_stream_ready; grpc_closure receiving_initial_metadata_ready; uint32_t test_only_last_message_flags; + bool cancelled; grpc_closure release_call; @@ -247,6 +202,7 @@ struct grpc_call { int* cancelled; } server; } final_op; + grpc_error* status_error; /* recv_state can contain one of the following values: RECV_NONE : : no initial metadata and messages received @@ -279,23 +235,15 @@ grpc_core::TraceFlag grpc_compression_trace(false, "compression"); static void execute_batch(grpc_call* call, grpc_transport_stream_op_batch* op, grpc_closure* start_batch_closure); -static void cancel_with_status(grpc_call* c, status_source source, - grpc_status_code status, + +static void cancel_with_status(grpc_call* c, grpc_status_code status, const char* description); -static void cancel_with_error(grpc_call* c, status_source source, - grpc_error* error); +static void cancel_with_error(grpc_call* c, grpc_error* error); static void destroy_call(void* call_stack, grpc_error* error); static void receiving_slice_ready(void* bctlp, grpc_error* error); -static void get_final_status( - grpc_call* call, void (*set_value)(grpc_status_code code, void* user_data), - void* set_value_user_data, grpc_slice* details, const char** error_string); -static void set_status_value_directly(grpc_status_code status, void* dest); -static void set_status_from_error(grpc_call* call, status_source source, - grpc_error* error); +static void set_final_status(grpc_call* call, grpc_error* error); static void process_data_after_md(batch_control* bctl); static void post_batch_completion(batch_control* bctl); -static void add_batch_error(batch_control* bctl, grpc_error* error, - bool has_cancelled); static void add_init_error(grpc_error** composite, grpc_error* new_err) { if (new_err == GRPC_ERROR_NONE) return; @@ -456,10 +404,10 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, gpr_mu_unlock(&pc->child_list_mu); } if (error != GRPC_ERROR_NONE) { - cancel_with_error(call, STATUS_FROM_SURFACE, GRPC_ERROR_REF(error)); + cancel_with_error(call, GRPC_ERROR_REF(error)); } if (immediately_cancel) { - cancel_with_error(call, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); + cancel_with_error(call, GRPC_ERROR_CANCELLED); } if (args->cq != nullptr) { GPR_ASSERT(args->pollset_set_alternative == nullptr && @@ -520,7 +468,6 @@ static void release_call(void* call, grpc_error* error) { GRPC_CHANNEL_INTERNAL_UNREF(channel, "call"); } -static void set_status_value_directly(grpc_status_code status, void* dest); static void destroy_call(void* call, grpc_error* error) { GPR_TIMER_SCOPE("destroy_call", 0); size_t i; @@ -547,16 +494,14 @@ static void destroy_call(void* call, grpc_error* error) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } - get_final_status(c, set_status_value_directly, &c->final_info.final_status, - nullptr, c->final_info.error_string); + grpc_slice slice = grpc_empty_slice(); + grpc_error_get_status(c->status_error, c->send_deadline, + &c->final_info.final_status, &slice, nullptr, + c->final_info.error_string); + GRPC_ERROR_UNREF(c->status_error); c->final_info.stats.latency = gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time); - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - GRPC_ERROR_UNREF( - unpack_received_status(gpr_atm_acq_load(&c->status[i])).error); - } - grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c), &c->final_info, GRPC_CLOSURE_INIT(&c->release_call, release_call, c, grpc_schedule_on_exec_ctx)); @@ -594,7 +539,7 @@ void grpc_call_unref(grpc_call* c) { bool cancel = gpr_atm_acq_load(&c->any_ops_sent_atm) != 0 && gpr_atm_acq_load(&c->received_final_op_atm) == 0; if (cancel) { - cancel_with_error(c, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); + cancel_with_error(c, GRPC_ERROR_CANCELLED); } else { // Unset the call combiner cancellation closure. This has the // effect of scheduling the previously set cancellation closure, if @@ -609,8 +554,7 @@ grpc_call_error grpc_call_cancel(grpc_call* call, void* reserved) { GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved)); GPR_ASSERT(!reserved); grpc_core::ExecCtx exec_ctx; - cancel_with_error(call, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED); - + cancel_with_error(call, GRPC_ERROR_CANCELLED); return GRPC_CALL_OK; } @@ -664,8 +608,7 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call* c, "c=%p, status=%d, description=%s, reserved=%p)", 4, (c, (int)status, description, reserved)); GPR_ASSERT(reserved == nullptr); - cancel_with_status(c, STATUS_FROM_API_OVERRIDE, status, description); - + cancel_with_status(c, status, description); return GRPC_CALL_OK; } @@ -685,15 +628,18 @@ static void done_termination(void* arg, grpc_error* error) { gpr_free(state); } -static void cancel_with_error(grpc_call* c, status_source source, - grpc_error* error) { +static void cancel_with_error(grpc_call* c, grpc_error* error) { + if (c->cancelled) { + GRPC_ERROR_UNREF(error); + return; + } + c->cancelled = true; GRPC_CALL_INTERNAL_REF(c, "termination"); // Inform the call combiner of the cancellation, so that it can cancel // any in-flight asynchronous actions that may be holding the call // combiner. This ensures that the cancel_stream batch can be sent // down the filter stack in a timely manner. grpc_call_combiner_cancel(&c->call_combiner, GRPC_ERROR_REF(error)); - set_status_from_error(c, source, GRPC_ERROR_REF(error)); cancel_state* state = static_cast(gpr_malloc(sizeof(*state))); state->call = c; GRPC_CLOSURE_INIT(&state->finish_batch, done_termination, state, @@ -716,90 +662,28 @@ static grpc_error* error_from_status(grpc_status_code status, GRPC_ERROR_INT_GRPC_STATUS, status); } -static void cancel_with_status(grpc_call* c, status_source source, - grpc_status_code status, +static void cancel_with_status(grpc_call* c, grpc_status_code status, const char* description) { - cancel_with_error(c, source, error_from_status(status, description)); + cancel_with_error(c, error_from_status(status, description)); } -/******************************************************************************* - * FINAL STATUS CODE MANIPULATION - */ - -static bool get_final_status_from( - grpc_call* call, grpc_error* error, bool allow_ok_status, - void (*set_value)(grpc_status_code code, void* user_data), - void* set_value_user_data, grpc_slice* details, const char** error_string) { - grpc_status_code code; - grpc_slice slice = grpc_empty_slice(); - grpc_error_get_status(error, call->send_deadline, &code, &slice, nullptr, - error_string); - if (code == GRPC_STATUS_OK && !allow_ok_status) { - return false; - } - - set_value(code, set_value_user_data); - if (details != nullptr) { - *details = grpc_slice_ref_internal(slice); - } - return true; -} - -static void get_final_status( - grpc_call* call, void (*set_value)(grpc_status_code code, void* user_data), - void* set_value_user_data, grpc_slice* details, const char** error_string) { - int i; - received_status status[STATUS_SOURCE_COUNT]; - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i])); - } +static void set_final_status(grpc_call* call, grpc_error* error) { if (grpc_call_error_trace.enabled()) { - gpr_log(GPR_INFO, "get_final_status %s", call->is_client ? "CLI" : "SVR"); - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - if (status[i].is_set) { - gpr_log(GPR_INFO, " %d: %s", i, grpc_error_string(status[i].error)); - } - } + gpr_log(GPR_DEBUG, "set_final_status %s", call->is_client ? "CLI" : "SVR"); + gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); } - /* first search through ignoring "OK" statuses: if something went wrong, - * ensure we report it */ - for (int allow_ok_status = 0; allow_ok_status < 2; allow_ok_status++) { - /* search for the best status we can present: ideally the error we use has a - clearly defined grpc-status, and we'll prefer that. */ - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - if (status[i].is_set && - grpc_error_has_clear_grpc_status(status[i].error)) { - if (get_final_status_from(call, status[i].error, allow_ok_status != 0, - set_value, set_value_user_data, details, - error_string)) { - return; - } - } - } - /* If no clearly defined status exists, search for 'anything' */ - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - if (status[i].is_set) { - if (get_final_status_from(call, status[i].error, allow_ok_status != 0, - set_value, set_value_user_data, details, - error_string)) { - return; - } - } - } - } - /* If nothing exists, set some default */ if (call->is_client) { - set_value(GRPC_STATUS_UNKNOWN, set_value_user_data); + const char** error_string = call->final_op.client.error_string; + grpc_status_code code; + grpc_slice slice = grpc_empty_slice(); + grpc_error_get_status(error, call->send_deadline, &code, &slice, nullptr, + error_string); + *call->final_op.client.status = code; + *call->final_op.client.status_details = grpc_slice_ref_internal(slice); + call->status_error = error; } else { - set_value(GRPC_STATUS_OK, set_value_user_data); - } -} - -static void set_status_from_error(grpc_call* call, status_source source, - grpc_error* error) { - if (!gpr_atm_rel_cas(&call->status[source], - pack_received_status({false, GRPC_ERROR_NONE}), - pack_received_status({true, error}))) { + *call->final_op.server.cancelled = + error != GRPC_ERROR_NONE || call->status_error != GRPC_ERROR_NONE; GRPC_ERROR_UNREF(error); } } @@ -1018,6 +902,7 @@ static grpc_stream_compression_algorithm decode_stream_compression( static void publish_app_metadata(grpc_call* call, grpc_metadata_batch* b, int is_trailing) { if (b->list.count == 0) return; + if (!call->is_client && is_trailing) return; if (is_trailing && call->buffered_metadata[1] == nullptr) return; GPR_TIMER_SCOPE("publish_app_metadata", 0); grpc_metadata_array* dest; @@ -1071,9 +956,12 @@ static void recv_initial_filter(grpc_call* call, grpc_metadata_batch* b) { publish_app_metadata(call, b, false); } -static void recv_trailing_filter(void* args, grpc_metadata_batch* b) { +static void recv_trailing_filter(void* args, grpc_metadata_batch* b, + grpc_error* batch_error) { grpc_call* call = static_cast(args); - if (b->idx.named.grpc_status != nullptr) { + if (batch_error != GRPC_ERROR_NONE) { + set_final_status(call, GRPC_ERROR_REF(batch_error)); + } else if (b->idx.named.grpc_status != nullptr) { grpc_status_code status_code = grpc_get_status_code_from_metadata(b->idx.named.grpc_status->md); grpc_error* error = @@ -1092,10 +980,16 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b) { error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, grpc_empty_slice()); } - set_status_from_error(call, STATUS_FROM_WIRE, error); + set_final_status(call, GRPC_ERROR_REF(error)); grpc_metadata_batch_remove(b, b->idx.named.grpc_status); + GRPC_ERROR_UNREF(error); + } else { + // TODO(kpayson) batch completed successfully w/no error + no status, should + // we assert instead? + set_final_status(call, GRPC_ERROR_NONE); } publish_app_metadata(call, b, true); + GRPC_ERROR_UNREF(batch_error); } grpc_call_stack* grpc_call_get_call_stack(grpc_call* call) { @@ -1106,14 +1000,6 @@ grpc_call_stack* grpc_call_get_call_stack(grpc_call* call) { * BATCH API IMPLEMENTATION */ -static void set_status_value_directly(grpc_status_code status, void* dest) { - *static_cast(dest) = status; -} - -static void set_cancelled_value(grpc_status_code status, void* dest) { - *static_cast(dest) = (status != GRPC_STATUS_OK); -} - static bool are_write_flags_valid(uint32_t flags) { /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */ const uint32_t allowed_write_positions = @@ -1181,31 +1067,15 @@ static void finish_batch_completion(void* user_data, GRPC_CALL_INTERNAL_UNREF(call, "completion"); } -static grpc_error* consolidate_batch_errors(batch_control* bctl) { - size_t n = static_cast(gpr_atm_acq_load(&bctl->num_errors)); - if (n == 0) { - return GRPC_ERROR_NONE; - } else if (n == 1) { - /* Skip creating a composite error in the case that only one error was - logged */ - grpc_error* e = bctl->errors[0]; - bctl->errors[0] = nullptr; - return e; - } else { - grpc_error* error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Call batch failed", bctl->errors, n); - for (size_t i = 0; i < n; i++) { - GRPC_ERROR_UNREF(bctl->errors[i]); - bctl->errors[i] = nullptr; - } - return error; - } +static void reset_batch_errors(batch_control* bctl) { + GRPC_ERROR_UNREF(bctl->batch_error); + bctl->batch_error = GRPC_ERROR_NONE; } static void post_batch_completion(batch_control* bctl) { grpc_call* next_child_call; grpc_call* call = bctl->call; - grpc_error* error = consolidate_batch_errors(bctl); + grpc_error* error = GRPC_ERROR_REF(bctl->batch_error); if (bctl->op.send_initial_metadata) { grpc_metadata_batch_destroy( @@ -1223,7 +1093,7 @@ static void post_batch_completion(batch_control* bctl) { if (bctl->op.recv_trailing_metadata) { grpc_metadata_batch* md = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - recv_trailing_filter(call, md); + recv_trailing_filter(call, md, GRPC_ERROR_REF(bctl->batch_error)); /* propagate cancellation to any interested children */ gpr_atm_rel_store(&call->received_final_op_atm, 1); @@ -1237,8 +1107,7 @@ static void post_batch_completion(batch_control* bctl) { next_child_call = child->child->sibling_next; if (child->cancellation_is_inherited) { GRPC_CALL_INTERNAL_REF(child, "propagate_cancel"); - cancel_with_error(child, STATUS_FROM_API_OVERRIDE, - GRPC_ERROR_CANCELLED); + cancel_with_error(child, GRPC_ERROR_CANCELLED); GRPC_CALL_INTERNAL_UNREF(child, "propagate_cancel"); } child = next_child_call; @@ -1247,16 +1116,6 @@ static void post_batch_completion(batch_control* bctl) { gpr_mu_unlock(&pc->child_list_mu); } - if (call->is_client) { - get_final_status(call, set_status_value_directly, - call->final_op.client.status, - call->final_op.client.status_details, - call->final_op.client.error_string); - } else { - get_final_status(call, set_cancelled_value, - call->final_op.server.cancelled, nullptr, nullptr); - } - GRPC_ERROR_UNREF(error); error = GRPC_ERROR_NONE; } @@ -1265,9 +1124,10 @@ static void post_batch_completion(batch_control* bctl) { grpc_byte_buffer_destroy(*call->receiving_buffer); *call->receiving_buffer = nullptr; } + reset_batch_errors(bctl); if (bctl->completion_data.notify_tag.is_closure) { - /* unrefs bctl->error */ + /* unrefs error */ bctl->call = nullptr; /* This closure may be meant to be run within some combiner. Since we aren't * running in any combiner here, we need to use GRPC_CLOSURE_SCHED instead @@ -1277,7 +1137,7 @@ static void post_batch_completion(batch_control* bctl) { error); GRPC_CALL_INTERNAL_UNREF(call, "completion"); } else { - /* unrefs bctl->error */ + /* unrefs error */ grpc_cq_end_op(bctl->call->cq, bctl->completion_data.notify_tag.tag, error, finish_batch_completion, bctl, &bctl->completion_data.cq_completion); @@ -1386,8 +1246,10 @@ static void receiving_stream_ready(void* bctlp, grpc_error* error) { grpc_call* call = bctl->call; if (error != GRPC_ERROR_NONE) { call->receiving_stream.reset(); - add_batch_error(bctl, GRPC_ERROR_REF(error), true); - cancel_with_error(call, STATUS_FROM_SURFACE, GRPC_ERROR_REF(error)); + if (bctl->batch_error == GRPC_ERROR_NONE) { + bctl->batch_error = GRPC_ERROR_REF(error); + } + cancel_with_error(call, GRPC_ERROR_REF(error)); } /* If recv_state is RECV_NONE, we will save the batch_control * object with rel_cas, and will not use it after the cas. Its corresponding @@ -1423,8 +1285,7 @@ static void validate_filtered_metadata(batch_control* bctl) { call->incoming_stream_compression_algorithm, call->incoming_message_compression_algorithm); gpr_log(GPR_ERROR, "%s", error_msg); - cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_INTERNAL, - error_msg); + cancel_with_status(call, GRPC_STATUS_INTERNAL, error_msg); gpr_free(error_msg); } else if ( grpc_compression_algorithm_from_message_stream_compression_algorithm( @@ -1436,8 +1297,7 @@ static void validate_filtered_metadata(batch_control* bctl) { "compression (%d).", call->incoming_stream_compression_algorithm, call->incoming_message_compression_algorithm); - cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_INTERNAL, - error_msg); + cancel_with_status(call, GRPC_STATUS_INTERNAL, error_msg); gpr_free(error_msg); } else { char* error_msg = nullptr; @@ -1447,8 +1307,7 @@ static void validate_filtered_metadata(batch_control* bctl) { gpr_asprintf(&error_msg, "Invalid compression algorithm value '%d'.", compression_algorithm); gpr_log(GPR_ERROR, "%s", error_msg); - cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_UNIMPLEMENTED, - error_msg); + cancel_with_status(call, GRPC_STATUS_UNIMPLEMENTED, error_msg); } else if (grpc_compression_options_is_algorithm_enabled( &compression_options, compression_algorithm) == 0) { /* check if algorithm is supported by current channel config */ @@ -1457,8 +1316,7 @@ static void validate_filtered_metadata(batch_control* bctl) { gpr_asprintf(&error_msg, "Compression algorithm '%s' is disabled.", algo_name); gpr_log(GPR_ERROR, "%s", error_msg); - cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_UNIMPLEMENTED, - error_msg); + cancel_with_status(call, GRPC_STATUS_UNIMPLEMENTED, error_msg); } gpr_free(error_msg); @@ -1476,23 +1334,12 @@ static void validate_filtered_metadata(batch_control* bctl) { } } -static void add_batch_error(batch_control* bctl, grpc_error* error, - bool has_cancelled) { - if (error == GRPC_ERROR_NONE) return; - int idx = static_cast(gpr_atm_full_fetch_add(&bctl->num_errors, 1)); - if (idx == 0 && !has_cancelled) { - cancel_with_error(bctl->call, STATUS_FROM_CORE, GRPC_ERROR_REF(error)); - } - bctl->errors[idx] = error; -} - static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_initial_metadata_ready"); - add_batch_error(bctl, GRPC_ERROR_REF(error), false); if (error == GRPC_ERROR_NONE) { grpc_metadata_batch* md = &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */]; @@ -1505,6 +1352,11 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { if (md->deadline != GRPC_MILLIS_INF_FUTURE && !call->is_client) { call->send_deadline = md->deadline; } + } else { + if (bctl->batch_error == GRPC_ERROR_NONE) { + bctl->batch_error = GRPC_ERROR_REF(error); + } + cancel_with_error(call, GRPC_ERROR_REF(error)); } grpc_closure* saved_rsr_closure = nullptr; @@ -1542,7 +1394,12 @@ static void finish_batch(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete"); - add_batch_error(bctl, GRPC_ERROR_REF(error), false); + if (bctl->batch_error == GRPC_ERROR_NONE) { + bctl->batch_error = GRPC_ERROR_REF(error); + } + if (error != GRPC_ERROR_NONE) { + cancel_with_error(call, GRPC_ERROR_REF(error)); + } finish_batch_step(bctl); } @@ -1740,28 +1597,26 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, call->send_extra_metadata_count = 1; call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem( call->channel, op->data.send_status_from_server.status); - { - grpc_error* override_error = GRPC_ERROR_NONE; - if (op->data.send_status_from_server.status != GRPC_STATUS_OK) { - override_error = - error_from_status(op->data.send_status_from_server.status, - "Returned non-ok status"); - } - if (op->data.send_status_from_server.status_details != nullptr) { - call->send_extra_metadata[1].md = grpc_mdelem_from_slices( - GRPC_MDSTR_GRPC_MESSAGE, - grpc_slice_ref_internal( - *op->data.send_status_from_server.status_details)); - call->send_extra_metadata_count++; - char* msg = grpc_slice_to_c_string( - GRPC_MDVALUE(call->send_extra_metadata[1].md)); - override_error = - grpc_error_set_str(override_error, GRPC_ERROR_STR_GRPC_MESSAGE, - grpc_slice_from_copied_string(msg)); - gpr_free(msg); - } - set_status_from_error(call, STATUS_FROM_API_OVERRIDE, override_error); + if (op->data.send_status_from_server.status_details != nullptr) { + call->send_extra_metadata[1].md = grpc_mdelem_from_slices( + GRPC_MDSTR_GRPC_MESSAGE, + grpc_slice_ref_internal( + *op->data.send_status_from_server.status_details)); + call->send_extra_metadata_count++; + char* msg = grpc_slice_to_c_string( + GRPC_MDVALUE(call->send_extra_metadata[1].md)); + gpr_free(msg); } + grpc_error* status_error = + op->data.send_status_from_server.status == GRPC_STATUS_OK + ? GRPC_ERROR_NONE + : grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Server returned error"), + GRPC_ERROR_INT_GRPC_STATUS, + static_cast( + op->data.send_status_from_server.status)); + call->status_error = status_error; if (!prepare_application_metadata( call, static_cast( -- cgit v1.2.3 From e670c3754c56f3d2cd1612df95953508e299a5a1 Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Tue, 19 Jun 2018 23:16:42 -0700 Subject: Minor bug in timer code during shutdown --- src/core/lib/iomgr/timer_generic.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/timer_generic.cc b/src/core/lib/iomgr/timer_generic.cc index 4294162af7..70417d69b6 100644 --- a/src/core/lib/iomgr/timer_generic.cc +++ b/src/core/lib/iomgr/timer_generic.cc @@ -291,7 +291,7 @@ static void timer_list_init() { static void timer_list_shutdown() { size_t i; run_some_expired_timers( - GPR_ATM_MAX, nullptr, + GRPC_MILLIS_INF_FUTURE, nullptr, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Timer list shutdown")); for (i = 0; i < g_num_shards; i++) { timer_shard* shard = &g_shards[i]; @@ -714,7 +714,7 @@ static grpc_timer_check_result timer_check(grpc_millis* next) { #if GPR_ARCH_64 gpr_log(GPR_INFO, "TIMER CHECK BEGIN: now=%" PRId64 " next=%s tls_min=%" PRId64 - " glob_min=%" PRIdPTR, + " glob_min=%" PRId64, now, next_str, min_timer, gpr_atm_no_barrier_load((gpr_atm*)(&g_shared_mutables.min_timer))); #else -- cgit v1.2.3 From dd0995d0159169d23f92eaf1df228033c337866c Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Thu, 21 Jun 2018 17:22:09 -0700 Subject: Changes --- .../ext/filters/http/client/http_client_filter.cc | 14 +++++++- .../ext/filters/http/server/http_server_filter.cc | 30 +++++++++++++++++ .../filters/message_size/message_size_filter.cc | 38 ++++++++++++---------- src/core/lib/surface/call.cc | 16 +++++++++ 4 files changed, 79 insertions(+), 19 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/http/client/http_client_filter.cc b/src/core/ext/filters/http/client/http_client_filter.cc index 1678051beb..eadb9db1be 100644 --- a/src/core/ext/filters/http/client/http_client_filter.cc +++ b/src/core/ext/filters/http/client/http_client_filter.cc @@ -51,6 +51,7 @@ struct call_data { grpc_linked_mdelem user_agent; // State for handling recv_initial_metadata ops. grpc_metadata_batch* recv_initial_metadata; + grpc_error* recv_initial_metadata_error; grpc_closure* original_recv_initial_metadata_ready; grpc_closure recv_initial_metadata_ready; // State for handling recv_trailing_metadata ops. @@ -147,6 +148,7 @@ static void recv_initial_metadata_ready(void* user_data, grpc_error* error) { call_data* calld = static_cast(elem->call_data); if (error == GRPC_ERROR_NONE) { error = client_filter_incoming_metadata(elem, calld->recv_initial_metadata); + calld->recv_initial_metadata_error = GRPC_ERROR_REF(error); } else { GRPC_ERROR_REF(error); } @@ -162,6 +164,13 @@ static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) { } else { GRPC_ERROR_REF(error); } + if (calld->recv_initial_metadata_error != GRPC_ERROR_NONE) { + if (error == GRPC_ERROR_NONE) { + error = GRPC_ERROR_REF(calld->recv_initial_metadata_error); + } else { + error = grpc_error_add_child(error, calld->recv_initial_metadata_error); + } + } GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, error); } @@ -434,7 +443,10 @@ static grpc_error* init_call_elem(grpc_call_element* elem, /* Destructor for call_data */ static void destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, - grpc_closure* ignored) {} + grpc_closure* ignored) { + call_data* calld = static_cast(elem->call_data); + GRPC_ERROR_UNREF(calld->recv_initial_metadata_error); +} static grpc_mdelem scheme_from_args(const grpc_channel_args* args) { unsigned i; diff --git a/src/core/ext/filters/http/server/http_server_filter.cc b/src/core/ext/filters/http/server/http_server_filter.cc index 3919447f26..48eeb9212c 100644 --- a/src/core/ext/filters/http/server/http_server_filter.cc +++ b/src/core/ext/filters/http/server/http_server_filter.cc @@ -50,6 +50,7 @@ struct call_data { // State for intercepting recv_initial_metadata. grpc_closure recv_initial_metadata_ready; + grpc_error* recv_initial_metadata_ready_error; grpc_closure* original_recv_initial_metadata_ready; grpc_metadata_batch* recv_initial_metadata; uint32_t* recv_initial_metadata_flags; @@ -60,6 +61,9 @@ struct call_data { grpc_closure recv_message_ready; grpc_core::OrphanablePtr* recv_message; bool seen_recv_message_ready; + + grpc_closure recv_trailing_metadata_ready; + grpc_closure* original_recv_trailing_metadata_ready; }; } // namespace @@ -267,6 +271,7 @@ static void hs_recv_initial_metadata_ready(void* user_data, grpc_error* err) { calld->seen_recv_initial_metadata_ready = true; if (err == GRPC_ERROR_NONE) { err = hs_filter_incoming_metadata(elem, calld->recv_initial_metadata); + calld->recv_initial_metadata_ready_error = GRPC_ERROR_REF(err); if (calld->seen_recv_message_ready) { // We've already seen the recv_message callback, but we previously // deferred it, so we need to return it here. @@ -313,6 +318,22 @@ static void hs_recv_message_ready(void* user_data, grpc_error* err) { } } +static void hs_recv_trailing_metadata_ready(void* user_data, grpc_error* err) { + grpc_call_element* elem = static_cast(user_data); + call_data* calld = static_cast(elem->call_data); + if (calld->recv_initial_metadata_ready_error != GRPC_ERROR_NONE) { + if (err == GRPC_ERROR_NONE) { + err = GRPC_ERROR_REF(calld->recv_initial_metadata_ready_error); + } else { + err = grpc_error_add_child(err, calld->recv_initial_metadata_ready_error); + } + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err); + } else { + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, + GRPC_ERROR_REF(err)); + } +} + static grpc_error* hs_mutate_op(grpc_call_element* elem, grpc_transport_stream_op_batch* op) { /* grab pointers to our data from the call element */ @@ -357,6 +378,11 @@ static grpc_error* hs_mutate_op(grpc_call_element* elem, op->payload->recv_message.recv_message_ready = &calld->recv_message_ready; } + if (op->recv_trailing_metadata) { + calld->original_recv_trailing_metadata_ready = + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + } + if (op->send_trailing_metadata) { grpc_error* error = hs_filter_outgoing_metadata( elem, op->payload->send_trailing_metadata.send_trailing_metadata); @@ -389,6 +415,9 @@ static grpc_error* hs_init_call_elem(grpc_call_element* elem, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_INIT(&calld->recv_message_ready, hs_recv_message_ready, elem, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready, + hs_recv_trailing_metadata_ready, elem, + grpc_schedule_on_exec_ctx); return GRPC_ERROR_NONE; } @@ -397,6 +426,7 @@ static void hs_destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* ignored) { call_data* calld = static_cast(elem->call_data); + GRPC_ERROR_UNREF(calld->recv_initial_metadata_ready_error); if (calld->have_read_stream) { calld->read_stream->Orphan(); } diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc index a859476dab..f3081df38d 100644 --- a/src/core/ext/filters/message_size/message_size_filter.cc +++ b/src/core/ext/filters/message_size/message_size_filter.cc @@ -99,7 +99,7 @@ struct call_data { // recv_message_ready up-call on transport_stream_op, and remember to // call our next_recv_message_ready member after handling it. grpc_closure recv_message_ready; - grpc_closure recv_trailing_metadata; + grpc_closure recv_trailing_metadata_ready; // The error caused by a message that is too large, or GRPC_ERROR_NONE grpc_error* error; // Used by recv_message_ready. @@ -107,7 +107,7 @@ struct call_data { // Original recv_message_ready callback, invoked after our own. grpc_closure* next_recv_message_ready; // Original recv_trailing_metadata callback, invoked after our own. - grpc_closure* next_recv_trailing_metadata; + grpc_closure* next_recv_trailing_metadata_ready; }; struct channel_data { @@ -136,13 +136,13 @@ static void recv_message_ready(void* user_data, grpc_error* error) { GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED); GRPC_ERROR_UNREF(calld->error); - calld->error = GRPC_ERROR_REF(new_error); if (error == GRPC_ERROR_NONE) { error = new_error; } else { error = grpc_error_add_child(error, new_error); GRPC_ERROR_UNREF(new_error); } + calld->error = GRPC_ERROR_REF(error); gpr_free(message_string); } else { GRPC_ERROR_REF(error); @@ -153,19 +153,20 @@ static void recv_message_ready(void* user_data, grpc_error* error) { // Callback invoked on completion of recv_trailing_metadata // Notifies the recv_trailing_metadata batch of any message size failures -static void recv_trailing_metadata(void* user_data, grpc_error* error) { - grpc_call_element* elem = (grpc_call_element*)user_data; - call_data* calld = (call_data*)elem->call_data; - if (error == GRPC_ERROR_NONE) { - error = calld->error; - } else if (calld->error == GRPC_ERROR_NONE) { +static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) { + grpc_call_element* elem = static_cast(user_data); + call_data* calld = static_cast(elem->call_data); + if (calld->error != GRPC_ERROR_NONE) { + if (error == GRPC_ERROR_NONE) { + error = GRPC_ERROR_REF(calld->error); + } else { + error = grpc_error_add_child(error, calld->error); + } + } else { error = GRPC_ERROR_REF(error); - } else if (calld->error != error) { - error = grpc_error_add_child(GRPC_ERROR_REF(error), calld->error); } - calld->error = GRPC_ERROR_NONE; // Invoke the next callback. - GRPC_CLOSURE_RUN(calld->next_recv_trailing_metadata, error); + GRPC_CLOSURE_RUN(calld->next_recv_trailing_metadata_ready, error); } // Start transport stream op. @@ -198,10 +199,10 @@ static void start_transport_stream_op_batch( } // Inject callback for receiving trailing metadata. if (op->recv_trailing_metadata) { - calld->next_recv_trailing_metadata = + calld->next_recv_trailing_metadata_ready = op->payload->recv_trailing_metadata.recv_trailing_metadata_ready; op->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - &calld->recv_trailing_metadata; + &calld->recv_trailing_metadata_ready; } // Chain to the next filter. grpc_call_next_op(elem, op); @@ -214,12 +215,13 @@ static grpc_error* init_call_elem(grpc_call_element* elem, call_data* calld = static_cast(elem->call_data); calld->call_combiner = args->call_combiner; calld->next_recv_message_ready = nullptr; - calld->next_recv_trailing_metadata = nullptr; + calld->next_recv_trailing_metadata_ready = nullptr; calld->error = GRPC_ERROR_NONE; GRPC_CLOSURE_INIT(&calld->recv_message_ready, recv_message_ready, elem, grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata, recv_trailing_metadata, - elem, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready, + recv_trailing_metadata_ready, elem, + grpc_schedule_on_exec_ctx); // Get max sizes from channel data, then merge in per-method config values. // Note: Per-method config is only available on the client, so we // apply the max request size to the send limit and the max response diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index eae0110635..38a00b8b67 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -689,6 +689,8 @@ static void set_final_status(grpc_call* call, grpc_error* error) { gpr_log(GPR_DEBUG, "set_final_status %s", call->is_client ? "CLI" : "SVR"); gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); } + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); if (call->is_client) { const char** error_string = call->final_op.client.error_string; grpc_status_code code; @@ -698,9 +700,23 @@ static void set_final_status(grpc_call* call, grpc_error* error) { *call->final_op.client.status = code; *call->final_op.client.status_details = grpc_slice_ref_internal(slice); call->status_error = error; + if (channelz_channel != nullptr) { + if (*call->final_op.client.status != GRPC_STATUS_OK) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } } else { *call->final_op.server.cancelled = error != GRPC_ERROR_NONE || call->status_error != GRPC_ERROR_NONE; + if (channelz_channel != nullptr) { + if (*call->final_op.server.cancelled) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } GRPC_ERROR_UNREF(error); } } -- cgit v1.2.3 From e2a9e6cf721866c17110244f9da6c37f30f1faef Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Fri, 22 Jun 2018 13:25:43 -0700 Subject: Changes --- src/core/lib/surface/call.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 38a00b8b67..b97c2ec760 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1015,10 +1015,15 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b, set_final_status(call, GRPC_ERROR_REF(error)); grpc_metadata_batch_remove(b, b->idx.named.grpc_status); GRPC_ERROR_UNREF(error); - } else { - // TODO(kpayson) batch completed successfully w/no error + no status, should - // we assert instead? + } else if (!call->is_client) { set_final_status(call, GRPC_ERROR_NONE); + } else { + gpr_log(GPR_DEBUG, + "Received trailing metadata with no error and no status"); + set_final_status( + call, grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("No status received"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNKNOWN)); } publish_app_metadata(call, b, true); GRPC_ERROR_UNREF(batch_error); -- cgit v1.2.3 From 2069bf520f5428a5523d3fbd34eb44d63802332e Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Mon, 25 Jun 2018 10:37:51 -0700 Subject: Fix tsan failure --- src/core/lib/surface/call.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index b97c2ec760..2b451e46a1 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -189,7 +189,7 @@ struct grpc_call { grpc_closure receiving_initial_metadata_ready; grpc_closure receiving_trailing_metadata_ready; uint32_t test_only_last_message_flags; - bool cancelled; + gpr_atm cancelled; grpc_closure release_call; @@ -304,6 +304,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, gpr_arena_alloc(arena, ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) + channel_stack->call_stack_size)); gpr_ref_init(&call->ext_ref, 1); + gpr_atm_no_barrier_store(&call->cancelled, 0); call->arena = arena; grpc_call_combiner_init(&call->call_combiner); *out_call = call; @@ -646,11 +647,10 @@ static void done_termination(void* arg, grpc_error* error) { } static void cancel_with_error(grpc_call* c, grpc_error* error) { - if (c->cancelled) { + if (!gpr_atm_rel_cas(&c->cancelled, 0, 1)) { GRPC_ERROR_UNREF(error); return; } - c->cancelled = true; GRPC_CALL_INTERNAL_REF(c, "termination"); // Inform the call combiner of the cancellation, so that it can cancel // any in-flight asynchronous actions that may be holding the call -- cgit v1.2.3 From 299c2c5e115b6a1204d67f3a4ae8de66c5386fe6 Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Mon, 9 Jul 2018 12:10:02 -0700 Subject: Include cancellation error --- src/core/lib/surface/call.cc | 62 ++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 20 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 6f136cd2a9..6f0905a9da 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -190,7 +190,7 @@ struct grpc_call { grpc_closure receiving_initial_metadata_ready; grpc_closure receiving_trailing_metadata_ready; uint32_t test_only_last_message_flags; - gpr_atm cancelled; + gpr_atm cancel_error; grpc_closure release_call; @@ -301,7 +301,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, gpr_arena_alloc(arena, GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) + channel_stack->call_stack_size)); gpr_ref_init(&call->ext_ref, 1); - gpr_atm_no_barrier_store(&call->cancelled, 0); + gpr_atm_no_barrier_store(&call->cancel_error, GRPC_ERROR_NONE); call->arena = arena; grpc_call_combiner_init(&call->call_combiner); *out_call = call; @@ -509,10 +509,33 @@ static void destroy_call(void* call, grpc_error* error) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(c->channel); + if (c->is_client) { + if (channelz_channel != nullptr) { + if (*c->final_op.client.status != GRPC_STATUS_OK) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } + } else { + if (channelz_channel != nullptr) { + if (*c->final_op.server.cancelled || c->status_error != GRPC_ERROR_NONE) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } + } + grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(c->status_error, c->send_deadline, &c->final_info.final_status, &slice, nullptr, c->final_info.error_string); + grpc_error* cancel_error = + (grpc_error*)gpr_atm_no_barrier_load(&c->cancel_error); + GRPC_ERROR_UNREF(cancel_error); GRPC_ERROR_UNREF(c->status_error); c->final_info.stats.latency = gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time); @@ -644,10 +667,12 @@ static void done_termination(void* arg, grpc_error* error) { } static void cancel_with_error(grpc_call* c, grpc_error* error) { - if (!gpr_atm_rel_cas(&c->cancelled, 0, 1)) { + if (!gpr_atm_rel_cas(&c->cancel_error, (gpr_atm)GRPC_ERROR_NONE, + (gpr_atm)error)) { GRPC_ERROR_UNREF(error); return; } + GRPC_ERROR_REF(error); GRPC_CALL_INTERNAL_REF(c, "termination"); // Inform the call combiner of the cancellation, so that it can cancel // any in-flight asynchronous actions that may be holding the call @@ -681,14 +706,26 @@ static void cancel_with_status(grpc_call* c, grpc_status_code status, cancel_with_error(c, error_from_status(status, description)); } +// The final status of a call is determined when the +// recv_trailing_metadata_ready callback is invoked. The status is determined +// based on the following (in order). +// 1. The first cancellation error that has occured prior to the callback. +// 2. The error passed to the recv_trailing_metadata_ready callback. +// 3. The status from the metadata on the call (grpc-status). static void set_final_status(grpc_call* call, grpc_error* error) { if (grpc_call_error_trace.enabled()) { gpr_log(GPR_DEBUG, "set_final_status %s", call->is_client ? "CLI" : "SVR"); gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); } - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(call->channel); + grpc_error* cancel_error = + (grpc_error*)gpr_atm_no_barrier_load(&call->cancel_error); + if (cancel_error != GRPC_ERROR_NONE && error == GRPC_ERROR_NONE) { + error = GRPC_ERROR_REF(cancel_error); + } else if (cancel_error != GRPC_ERROR_NONE && cancel_error != error) { + error = grpc_error_add_child(GRPC_ERROR_REF(cancel_error), error); + } if (call->is_client) { + call->status_error = error; const char** error_string = call->final_op.client.error_string; grpc_status_code code; grpc_slice slice = grpc_empty_slice(); @@ -696,24 +733,9 @@ static void set_final_status(grpc_call* call, grpc_error* error) { error_string); *call->final_op.client.status = code; *call->final_op.client.status_details = grpc_slice_ref_internal(slice); - call->status_error = error; - if (channelz_channel != nullptr) { - if (*call->final_op.client.status != GRPC_STATUS_OK) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); - } - } } else { *call->final_op.server.cancelled = error != GRPC_ERROR_NONE || call->status_error != GRPC_ERROR_NONE; - if (channelz_channel != nullptr) { - if (*call->final_op.server.cancelled) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); - } - } GRPC_ERROR_UNREF(error); } } -- cgit v1.2.3 From a3d93f324b93329de79124d570dbddb47a6862e0 Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Wed, 11 Jul 2018 19:34:24 -0700 Subject: fix format --- src/core/lib/iomgr/timer_generic.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/timer_generic.cc b/src/core/lib/iomgr/timer_generic.cc index 70417d69b6..008d37119a 100644 --- a/src/core/lib/iomgr/timer_generic.cc +++ b/src/core/lib/iomgr/timer_generic.cc @@ -716,7 +716,8 @@ static grpc_timer_check_result timer_check(grpc_millis* next) { "TIMER CHECK BEGIN: now=%" PRId64 " next=%s tls_min=%" PRId64 " glob_min=%" PRId64, now, next_str, min_timer, - gpr_atm_no_barrier_load((gpr_atm*)(&g_shared_mutables.min_timer))); + static_cast(gpr_atm_no_barrier_load( + (gpr_atm*)(&g_shared_mutables.min_timer)))); #else gpr_log(GPR_INFO, "TIMER CHECK BEGIN: now=%" PRId64 " next=%s min=%" PRId64, now, next_str, min_timer); -- cgit v1.2.3 From a135059ce7d2db3180045810f66dd69a8fc88284 Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Fri, 13 Jul 2018 13:24:31 -0700 Subject: Make error strings consistent --- src/core/lib/iomgr/error.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc index 90ed34da11..93a5c20abb 100644 --- a/src/core/lib/iomgr/error.cc +++ b/src/core/lib/iomgr/error.cc @@ -399,14 +399,14 @@ static grpc_error* copy_error_and_unref(grpc_error* in) { out = GRPC_ERROR_CREATE_FROM_STATIC_STRING("unknown"); if (in == GRPC_ERROR_NONE) { internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, - grpc_slice_from_static_string("no error")); + grpc_slice_from_static_string("No Error")); internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK); } else if (in == GRPC_ERROR_OOM) { internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, - grpc_slice_from_static_string("oom")); + grpc_slice_from_static_string("Out of memory")); } else if (in == GRPC_ERROR_CANCELLED) { internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, - grpc_slice_from_static_string("cancelled")); + grpc_slice_from_static_string("Cancelled")); internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED); } } else if (gpr_ref_is_unique(&in->atomics.refs)) { -- cgit v1.2.3 From 5defb7354b620a67ef42cb2ad73bab7bdd512fa6 Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Fri, 13 Jul 2018 13:49:23 -0700 Subject: compile error fix --- src/core/lib/surface/call.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 6f0905a9da..88156ed3bc 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -301,7 +301,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, gpr_arena_alloc(arena, GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) + channel_stack->call_stack_size)); gpr_ref_init(&call->ext_ref, 1); - gpr_atm_no_barrier_store(&call->cancel_error, GRPC_ERROR_NONE); + gpr_atm_no_barrier_store(&call->cancel_error, (gpr_atm)GRPC_ERROR_NONE); call->arena = arena; grpc_call_combiner_init(&call->call_combiner); *out_call = call; -- cgit v1.2.3 From bbee13661c82c13e2f1b728c94f9535112f54d92 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 18 Jul 2018 18:31:09 -0700 Subject: Add channelz subchannel support --- include/grpc/grpc.h | 4 + .../client_channel/client_channel_channelz.cc | 29 +++++ .../client_channel/client_channel_channelz.h | 35 ++++- src/core/ext/filters/client_channel/subchannel.cc | 31 ++++- src/core/ext/filters/client_channel/subchannel.h | 2 + src/core/lib/channel/channel_trace.cc | 30 +++-- src/core/lib/channel/channelz.cc | 142 +++++++++++++-------- src/core/lib/channel/channelz.h | 131 ++++++++++++++----- src/core/lib/channel/channelz_registry.cc | 16 +++ src/core/lib/surface/channel.cc | 3 + test/core/channel/channelz_test.cc | 29 +++++ test/cpp/util/channel_trace_proto_helper.cc | 4 + test/cpp/util/channel_trace_proto_helper.h | 1 + 13 files changed, 354 insertions(+), 103 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index f0eb2c0121..942c83bcde 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -477,6 +477,10 @@ GRPCAPI char* grpc_channelz_get_top_channels(intptr_t start_channel_id); is allocated and must be freed by the application. */ GRPCAPI char* grpc_channelz_get_channel(intptr_t channel_id); +/* Returns a single Subchannel, or else a NOT_FOUND code. The returned string + is allocated and must be freed by the application. */ +GRPCAPI char* grpc_channelz_get_subchannel(intptr_t subchannel_id); + #ifdef __cplusplus } #endif diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index d43e9ea67a..5a0eec5d15 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -24,6 +24,8 @@ #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.h" +#include + namespace grpc_core { namespace channelz { namespace { @@ -109,5 +111,32 @@ RefCountedPtr ClientChannelNode::MakeClientChannelNode( channel, channel_tracer_max_nodes, is_top_level_channel); } +ClientChannelSubchannelNode::ClientChannelSubchannelNode( + size_t channel_tracer_max_nodes, grpc_subchannel* subchannel) + : SubchannelNode(channel_tracer_max_nodes), subchannel_(subchannel) { + target_ = + UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_))); +} + +void ClientChannelSubchannelNode::PopulateTarget(grpc_json* json) { + GPR_ASSERT(target_.get() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_.get(), + GRPC_JSON_STRING, false); +} + +void ClientChannelSubchannelNode::PopulateConnectivityState(grpc_json* json) { + grpc_connectivity_state state; + if (subchannel_ == nullptr) { + state = GRPC_CHANNEL_SHUTDOWN; + } else { + state = grpc_subchannel_check_connectivity(subchannel_, nullptr); + } + json = grpc_json_create_child(nullptr, json, "state", nullptr, + GRPC_JSON_OBJECT, false); + grpc_json_create_child(nullptr, json, "state", + grpc_connectivity_state_name(state), GRPC_JSON_STRING, + false); +} + } // namespace channelz } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 6f27b5c8b7..b1bd8db89e 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -26,6 +26,8 @@ #include "src/core/lib/channel/channelz.h" #include "src/core/lib/gprpp/inlined_vector.h" +typedef struct grpc_subchannel grpc_subchannel; + namespace grpc_core { // TODO(ncteisen), this only contains the uuids of the children for now, @@ -55,16 +57,45 @@ class ClientChannelNode : public ChannelNode { static grpc_arg CreateChannelArg(); protected: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); virtual ~ClientChannelNode() {} private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW grpc_channel_element* client_channel_; }; +// Subtype of SubchannelNode that overrides and provides client_channel +// specific functionality like querying for connectivity_state and +// subchannel target. +class ClientChannelSubchannelNode : public SubchannelNode { + public: + ClientChannelSubchannelNode(size_t channel_tracer_max_nodes, + grpc_subchannel* subchannel); + ~ClientChannelSubchannelNode() override {} + + // Override this functionality since subchannels have a notion of + // channel connectivity. + void PopulateConnectivityState(grpc_json* json) override; + + // Override this functionality since client_channels subchannels hold + // their own target. + void PopulateTarget(grpc_json* json) override; + + void MarkSubchannelDestroyed() { + GPR_ASSERT(subchannel_ != nullptr); + subchannel_ = nullptr; + } + + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + grpc_subchannel* subchannel_; + UniquePtr target_; +}; + } // namespace channelz } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 93df2aff70..0c3313c5de 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -135,7 +135,7 @@ struct grpc_subchannel { /** our alarm */ grpc_timer alarm; - grpc_core::RefCountedPtr + grpc_core::RefCountedPtr channelz_subchannel; }; @@ -181,7 +181,13 @@ static void connection_destroy(void* arg, grpc_error* error) { static void subchannel_destroy(void* arg, grpc_error* error) { grpc_subchannel* c = static_cast(arg); - c->channelz_subchannel.reset(); + if (c->channelz_subchannel != nullptr) { + c->channelz_subchannel->trace()->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Subchannel destroyed")); + c->channelz_subchannel->MarkSubchannelDestroyed(); + c->channelz_subchannel.reset(); + } gpr_free((void*)c->filters); grpc_channel_args_destroy(c->args); grpc_connectivity_state_destroy(&c->state_tracker); @@ -381,9 +387,18 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, const grpc_arg* arg = grpc_channel_args_find(c->args, GRPC_ARG_ENABLE_CHANNELZ); bool channelz_enabled = grpc_channel_arg_get_bool(arg, false); + arg = grpc_channel_args_find(c->args, + GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE); + const grpc_integer_options options = {0, 0, INT_MAX}; + size_t channel_tracer_max_nodes = + (size_t)grpc_channel_arg_get_integer(arg, options); if (channelz_enabled) { - c->channelz_subchannel = - grpc_core::MakeRefCounted(); + c->channelz_subchannel = grpc_core::MakeRefCounted< + grpc_core::channelz::ClientChannelSubchannelNode>( + channel_tracer_max_nodes, c); + c->channelz_subchannel->trace()->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Subchannel created")); } return grpc_subchannel_index_register(key, c); @@ -757,6 +772,14 @@ void grpc_get_subchannel_address_arg(const grpc_channel_args* args, } } +const char* grpc_subchannel_get_target(grpc_subchannel* subchannel) { + const grpc_arg* addr_arg = + grpc_channel_args_find(subchannel->args, GRPC_ARG_SUBCHANNEL_ADDRESS); + const char* addr_str = grpc_channel_arg_get_string(addr_arg); + GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. + return addr_str; +} + const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args) { const grpc_arg* addr_arg = grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 9e53f7d542..dd3a2d9621 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -177,6 +177,8 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, void grpc_get_subchannel_address_arg(const grpc_channel_args* args, grpc_resolved_address* addr); +const char* grpc_subchannel_get_target(grpc_subchannel* subchannel); + /// Returns the URI string for the address to connect to. const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args); diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index b3443310ac..dd6fdeed54 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -178,24 +178,26 @@ grpc_json* ChannelTrace::RenderJson() const { if (!max_list_size_) return nullptr; // tracing is disabled if max_events == 0 grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT); - char* num_events_logged_str; - gpr_asprintf(&num_events_logged_str, "%" PRId64, num_events_logged_); grpc_json* json_iterator = nullptr; - json_iterator = - grpc_json_create_child(json_iterator, json, "numEventsLogged", - num_events_logged_str, GRPC_JSON_STRING, true); + if (num_events_logged_ > 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "numEventsLogged", num_events_logged_); + } json_iterator = grpc_json_create_child( json_iterator, json, "creationTimestamp", gpr_format_timespec(time_created_), GRPC_JSON_STRING, true); - grpc_json* events = grpc_json_create_child(json_iterator, json, "events", - nullptr, GRPC_JSON_ARRAY, false); - json_iterator = nullptr; - TraceEvent* it = head_trace_; - while (it != nullptr) { - json_iterator = grpc_json_create_child(json_iterator, events, nullptr, - nullptr, GRPC_JSON_OBJECT, false); - it->RenderTraceEvent(json_iterator); - it = it->next(); + // only add in the event list if it is non-empty. + if (num_events_logged_ > 0) { + grpc_json* events = grpc_json_create_child(json_iterator, json, "events", + nullptr, GRPC_JSON_ARRAY, false); + json_iterator = nullptr; + TraceEvent* it = head_trace_; + while (it != nullptr) { + json_iterator = grpc_json_create_child(json_iterator, events, nullptr, + nullptr, GRPC_JSON_OBJECT, false); + it->RenderTraceEvent(json_iterator); + it = it->next(); + } } return json; } diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 9d6002ed8a..7fe086da3c 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -41,69 +41,33 @@ namespace grpc_core { namespace channelz { -ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, - bool is_top_level_channel) - : channel_(channel), - target_(nullptr), - channel_uuid_(-1), - is_top_level_channel_(is_top_level_channel) { +CallCountingBase::CallCountingBase(size_t channel_tracer_max_nodes) { trace_.Init(channel_tracer_max_nodes); - target_ = UniquePtr(grpc_channel_get_target(channel_)); - channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -ChannelNode::~ChannelNode() { - trace_.Destroy(); - ChannelzRegistry::UnregisterChannelNode(channel_uuid_); -} +CallCountingBase::~CallCountingBase() { trace_.Destroy(); } -void ChannelNode::RecordCallStarted() { +void CallCountingBase::RecordCallStarted() { gpr_atm_no_barrier_fetch_add(&calls_started_, (gpr_atm)1); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -void ChannelNode::PopulateConnectivityState(grpc_json* json) {} - -void ChannelNode::PopulateChildRefs(grpc_json* json) {} - -grpc_json* ChannelNode::RenderJson() { - // We need to track these three json objects to build our object - grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); - grpc_json* json = top_level_json; - grpc_json* json_iterator = nullptr; - // create and fill the ref child - json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, - GRPC_JSON_OBJECT, false); - json = json_iterator; - json_iterator = nullptr; - json_iterator = grpc_json_add_number_string_child(json, json_iterator, - "channelId", channel_uuid_); - // reset json iterators to top level object - json = top_level_json; - json_iterator = nullptr; - // create and fill the data child. - grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, - GRPC_JSON_OBJECT, false); - json = data; - json_iterator = nullptr; - PopulateConnectivityState(json); - GPR_ASSERT(target_.get() != nullptr); - json_iterator = grpc_json_create_child( - json_iterator, json, "target", target_.get(), GRPC_JSON_STRING, false); +void CallCountingBase::PopulateTrace(grpc_json* json) { // fill in the channel trace if applicable - grpc_json* trace = trace_->RenderJson(); - if (trace != nullptr) { + grpc_json* trace_json = trace_->RenderJson(); + if (trace_json != nullptr) { // we manually link up and fill the child since it was created for us in // ChannelTrace::RenderJson - trace->key = "trace"; // this object is named trace in channelz.proto - json_iterator = grpc_json_link_child(json, trace, json_iterator); + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); } - // reset the parent to be the data object. - json = data; - json_iterator = nullptr; +} + +void CallCountingBase::PopulateCallData(grpc_json* json) { + grpc_json* json_iterator = nullptr; if (calls_started_ != 0) { json_iterator = grpc_json_add_number_string_child( json, json_iterator, "callsStarted", calls_started_); @@ -121,19 +85,62 @@ grpc_json* ChannelNode::RenderJson() { json_iterator = grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp", gpr_format_timespec(ts), GRPC_JSON_STRING, true); - json = top_level_json; - json_iterator = nullptr; - PopulateChildRefs(json); - return top_level_json; } -char* ChannelNode::RenderJsonString() { +char* CallCountingBase::RenderJsonString() { grpc_json* json = RenderJson(); char* json_str = grpc_json_dump_to_string(json, 0); grpc_json_destroy(json); return json_str; } +ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel) + : CallCountingBase(channel_tracer_max_nodes), + channel_(channel), + is_top_level_channel_(is_top_level_channel) { + target_ = UniquePtr(grpc_channel_get_target(channel_)); + channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this); +} + +ChannelNode::~ChannelNode() { + ChannelzRegistry::UnregisterChannelNode(channel_uuid_); +} + +void ChannelNode::PopulateTarget(grpc_json* json) { + GPR_ASSERT(target_.get() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_.get(), + GRPC_JSON_STRING, false); +} + +grpc_json* ChannelNode::RenderJson() { + // We need to track these three json objects to build our object + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + // create and fill the ref child + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "channelId", channel_uuid_); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + PopulateConnectivityState(json); + PopulateTarget(json); + PopulateTrace(json); + PopulateCallData(json); + PopulateChildRefs(json); + return top_level_json; +} + RefCountedPtr ChannelNode::MakeChannelNode( grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel) { @@ -141,7 +148,8 @@ RefCountedPtr ChannelNode::MakeChannelNode( channel, channel_tracer_max_nodes, is_top_level_channel); } -SubchannelNode::SubchannelNode() { +SubchannelNode::SubchannelNode(size_t channel_tracer_max_nodes) + : CallCountingBase(channel_tracer_max_nodes) { subchannel_uuid_ = ChannelzRegistry::RegisterSubchannelNode(this); } @@ -149,5 +157,31 @@ SubchannelNode::~SubchannelNode() { ChannelzRegistry::UnregisterSubchannelNode(subchannel_uuid_); } +grpc_json* SubchannelNode::RenderJson() { + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "subchannelId", subchannel_uuid_); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + PopulateConnectivityState(json); + PopulateTarget(json); + PopulateTrace(json); + PopulateCallData(json); + PopulateChildRefs(json); + return top_level_json; +} + } // namespace channelz } // namespace grpc_core diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 07eb73d626..97e27c69fc 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -46,11 +46,44 @@ namespace testing { class ChannelNodePeer; } -class ChannelNode : public RefCounted { +// base class for all channelz entities +class ChannelzBaseNode : public RefCounted { public: - static RefCountedPtr MakeChannelNode( - grpc_channel* channel, size_t channel_tracer_max_nodes, - bool is_top_level_channel); + ChannelzBaseNode() {} + virtual ~ChannelzBaseNode() {} + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW +}; + +// Handles channelz bookkeeping for sockets +// TODO(ncteisen): implement in subsequent PR. +class SocketNode : public ChannelzBaseNode { + public: + SocketNode() : ChannelzBaseNode() {} + ~SocketNode() override {} + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW +}; + +// This class is the parent for the channelz entities that deal with Channels +// Subchannels, and Servers, since those have similar proto definitions. +// This class has the ability to: +// - track calls_{started,succeeded,failed} +// - track last_call_started_timestamp +// - hold the channel trace. +// - perform common rendering. +// +// This class also defines some fat interfaces so that its children can +// implement the functionality different. For example, querying the +// connectivity state looks different for channels and subchannels, and does +// not make sense for servers. So servers will not override, and channels and +// subchannels will override with their own way to query connectivity state. +class CallCountingBase : public ChannelzBaseNode { + public: + CallCountingBase(size_t channel_tracer_max_nodes); + ~CallCountingBase() override; void RecordCallStarted(); void RecordCallFailed() { @@ -59,66 +92,106 @@ class ChannelNode : public RefCounted { void RecordCallSucceeded() { gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1))); } + ChannelTrace* trace() { return trace_.get(); } + + // Fat interface for ConnectivityState. Default is to leave it out, however, + // things like Channel and Subchannel will override with their mechanism + // for querying connectivity state. + virtual void PopulateConnectivityState(grpc_json* json) {} + + // Fat interface for Targets. + virtual void PopulateTarget(grpc_json* json) {} + + // Fat interface for ChildRefs. Allows children to populate with whatever + // combination of child_refs, subchannel_refs, and socket_refs is correct. + virtual void PopulateChildRefs(grpc_json* json) {} - grpc_json* RenderJson(); + // All children must implement their custom JSON rendering. + virtual grpc_json* RenderJson() GRPC_ABSTRACT; + + // Common rendering of the channel trace. + void PopulateTrace(grpc_json* json); + + // Common rendering of the call count data and last_call_started_timestamp. + void PopulateCallData(grpc_json* json); + + // Common rendering of grpc_json from RenderJson() to allocated string. char* RenderJsonString(); - // helper for getting and populating connectivity state. It is virtual - // because it allows the client_channel specific code to live in ext/ - // instead of lib/ - virtual void PopulateConnectivityState(grpc_json* json); + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - virtual void PopulateChildRefs(grpc_json* json); + gpr_atm calls_started_ = 0; + gpr_atm calls_succeeded_ = 0; + gpr_atm calls_failed_ = 0; + gpr_atm last_call_started_millis_ = 0; + ManualConstructor trace_; +}; - ChannelTrace* trace() { return trace_.get(); } +// Handles channelz bookkeeping for servers +// TODO(ncteisen): implement in subsequent PR. +class ServerNode : public CallCountingBase { + public: + ServerNode(size_t channel_tracer_max_nodes) + : CallCountingBase(channel_tracer_max_nodes) {} + ~ServerNode() override {} + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW +}; + +// Overrides Channel specific functionality. +class ChannelNode : public CallCountingBase { + public: + static RefCountedPtr MakeChannelNode( + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); void MarkChannelDestroyed() { GPR_ASSERT(channel_ != nullptr); channel_ = nullptr; } + grpc_json* RenderJson() override; + + void PopulateTarget(grpc_json* json) override; + bool ChannelIsDestroyed() { return channel_ == nullptr; } intptr_t channel_uuid() { return channel_uuid_; } bool is_top_level_channel() { return is_top_level_channel_; } protected: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); - virtual ~ChannelNode(); + ~ChannelNode() override; private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + // testing peer friend. friend class testing::ChannelNodePeer; grpc_channel* channel_ = nullptr; UniquePtr target_; - gpr_atm calls_started_ = 0; - gpr_atm calls_succeeded_ = 0; - gpr_atm calls_failed_ = 0; - gpr_atm last_call_started_millis_ = 0; intptr_t channel_uuid_; bool is_top_level_channel_ = true; - ManualConstructor trace_; }; -// Placeholds channelz class for subchannels. All this can do now is track its -// uuid (this information is needed by the parent channelz class). -// TODO(ncteisen): build this out to support the GetSubchannel channelz request. -class SubchannelNode : public RefCounted { +// Overrides Subchannel specific functionality. +class SubchannelNode : public CallCountingBase { public: - SubchannelNode(); - virtual ~SubchannelNode(); - + SubchannelNode(size_t channel_tracer_max_nodes); + ~SubchannelNode() override; + grpc_json* RenderJson() override; intptr_t subchannel_uuid() { return subchannel_uuid_; } - protected: + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - - private: + intptr_t subchannel_uuid_; }; diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 38496b3d78..aeeb6958e4 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -142,3 +142,19 @@ char* grpc_channelz_get_channel(intptr_t channel_id) { grpc_json_destroy(top_level_json); return json_str; } + +char* grpc_channelz_get_subchannel(intptr_t subchannel_id) { + grpc_core::channelz::SubchannelNode* subchannel_node = + grpc_core::channelz::ChannelzRegistry::GetSubchannelNode(subchannel_id); + if (subchannel_node == nullptr) { + return nullptr; + } + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* subchannel_json = subchannel_node->RenderJson(); + subchannel_json->key = "subchannel"; + grpc_json_link_child(json, subchannel_json, nullptr); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 7cbd61adef..01caadaaba 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -417,6 +417,9 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) { static void destroy_channel(void* arg, grpc_error* error) { grpc_channel* channel = static_cast(arg); if (channel->channelz_channel != nullptr) { + channel->channelz_channel->trace()->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Channel destroyed")); channel->channelz_channel->MarkChannelDestroyed(); channel->channelz_channel.reset(); } diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index ad5f86d934..b8e65ebfb3 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -163,6 +163,14 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { gpr_free(core_api_json_str); } +void ValidateSubchannel(SubchannelNode* subchannel, + validate_channel_data_args args) { + char* json_str = subchannel->RenderJsonString(); + grpc::testing::ValidateSubchannelProtoJsonTranslation(json_str); + ValidateCounters(json_str, args); + gpr_free(json_str); +} + grpc_millis GetLastCallStartedMillis(ChannelNode* channel) { ChannelNodePeer peer(channel); return peer.last_call_started_millis(); @@ -275,8 +283,29 @@ TEST(ChannelzGetTopChannelsTest, InternalChannelTest) { grpc_channel_destroy(internal_channel); } +class ChannelzSubchannelTest : public ::testing::TestWithParam {}; + +TEST_P(ChannelzSubchannelTest, BasicTest) { + grpc_core::ExecCtx exec_ctx; + RefCountedPtr channelz_subchannel = + MakeRefCounted(GetParam()); + channelz_subchannel->RecordCallStarted(); + channelz_subchannel->RecordCallFailed(); + channelz_subchannel->RecordCallSucceeded(); + ValidateSubchannel(channelz_subchannel.get(), {1, 1, 1}); + channelz_subchannel->RecordCallStarted(); + channelz_subchannel->RecordCallFailed(); + channelz_subchannel->RecordCallSucceeded(); + channelz_subchannel->RecordCallStarted(); + channelz_subchannel->RecordCallFailed(); + channelz_subchannel->RecordCallSucceeded(); + ValidateSubchannel(channelz_subchannel.get(), {3, 3, 3}); +} + INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest, ::testing::Values(0, 1, 2, 6, 10, 15)); +INSTANTIATE_TEST_CASE_P(ChannelzSubchannelTestSweep, ChannelzSubchannelTest, + ::testing::Values(0, 1, 10, 15)); } // namespace testing } // namespace channelz diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index b4704bfe6a..e416a0375f 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -82,5 +82,9 @@ void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str) { json_c_str); } +void ValidateSubchannelProtoJsonTranslation(char* json_c_str) { + VaidateProtoJsonTranslation(json_c_str); +} + } // namespace testing } // namespace grpc diff --git a/test/cpp/util/channel_trace_proto_helper.h b/test/cpp/util/channel_trace_proto_helper.h index 18e3d54b6b..a1ebbcd110 100644 --- a/test/cpp/util/channel_trace_proto_helper.h +++ b/test/cpp/util/channel_trace_proto_helper.h @@ -26,6 +26,7 @@ void ValidateChannelTraceProtoJsonTranslation(char* json_c_str); void ValidateChannelProtoJsonTranslation(char* json_c_str); void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str); void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str); +void ValidateSubchannelProtoJsonTranslation(char* json_c_str); } // namespace testing } // namespace grpc -- cgit v1.2.3 From ca32a8a85286ae0c9c94c3eaeaee3100d0304f99 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Thu, 19 Jul 2018 16:59:50 -0700 Subject: reviewer feedback --- .../client_channel/client_channel_channelz.cc | 8 +++---- src/core/lib/channel/channelz.h | 25 ++++++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 5a0eec5d15..0688ee2abb 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -113,10 +113,10 @@ RefCountedPtr ClientChannelNode::MakeClientChannelNode( ClientChannelSubchannelNode::ClientChannelSubchannelNode( size_t channel_tracer_max_nodes, grpc_subchannel* subchannel) - : SubchannelNode(channel_tracer_max_nodes), subchannel_(subchannel) { - target_ = - UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_))); -} + : SubchannelNode(channel_tracer_max_nodes), + subchannel_(subchannel), + target_(UniquePtr( + gpr_strdup(grpc_subchannel_get_target(subchannel_)))) {} void ClientChannelSubchannelNode::PopulateTarget(grpc_json* json) { GPR_ASSERT(target_.get() != nullptr); diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 97e27c69fc..1cd55bab43 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -47,10 +47,11 @@ class ChannelNodePeer; } // base class for all channelz entities -class ChannelzBaseNode : public RefCounted { +class BaseNode : public RefCounted { public: - ChannelzBaseNode() {} - virtual ~ChannelzBaseNode() {} + BaseNode() {} + virtual ~BaseNode() {} + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW @@ -58,10 +59,11 @@ class ChannelzBaseNode : public RefCounted { // Handles channelz bookkeeping for sockets // TODO(ncteisen): implement in subsequent PR. -class SocketNode : public ChannelzBaseNode { +class SocketNode : public BaseNode { public: - SocketNode() : ChannelzBaseNode() {} + SocketNode() : BaseNode() {} ~SocketNode() override {} + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW @@ -76,11 +78,11 @@ class SocketNode : public ChannelzBaseNode { // - perform common rendering. // // This class also defines some fat interfaces so that its children can -// implement the functionality different. For example, querying the -// connectivity state looks different for channels and subchannels, and does -// not make sense for servers. So servers will not override, and channels and -// subchannels will override with their own way to query connectivity state. -class CallCountingBase : public ChannelzBaseNode { +// implement the functionality differently. For example, querying the +// connectivity state looks different for channels than for subchannels, and +// does not make sense for servers. So servers will not override, and channels +// and subchannels will override with their own way to query connectivity state. +class CallCountingBase : public BaseNode { public: CallCountingBase(size_t channel_tracer_max_nodes); ~CallCountingBase() override; @@ -136,6 +138,7 @@ class ServerNode : public CallCountingBase { ServerNode(size_t channel_tracer_max_nodes) : CallCountingBase(channel_tracer_max_nodes) {} ~ServerNode() override {} + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW @@ -191,7 +194,7 @@ class SubchannelNode : public CallCountingBase { private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - + intptr_t subchannel_uuid_; }; -- cgit v1.2.3 From 8cb2d0c64afd9c766ea6b4c41f3125879091d08a Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 20 Jul 2018 14:26:04 -0700 Subject: Restructure everything --- .../client_channel/client_channel_channelz.cc | 79 +++++++++++-- .../client_channel/client_channel_channelz.h | 37 +++---- src/core/ext/filters/client_channel/subchannel.cc | 8 +- src/core/lib/channel/channelz.cc | 89 +++++---------- src/core/lib/channel/channelz.h | 122 +++++++++------------ src/core/lib/channel/channelz_registry.cc | 51 +++++---- src/core/lib/channel/channelz_registry.h | 50 ++------- test/core/channel/channelz_registry_test.cc | 30 ++--- test/core/channel/channelz_test.cc | 42 ++----- 9 files changed, 223 insertions(+), 285 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 0688ee2abb..1d72b9c9d2 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -20,6 +20,7 @@ #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/client_channel_channelz.h" +#include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.h" @@ -97,6 +98,38 @@ void ClientChannelNode::PopulateChildRefs(grpc_json* json) { } } +grpc_json* ClientChannelNode::RenderJson() { + // We need to track these three json objects to build our object + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + // create and fill the ref child + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "channelId", channel_uuid()); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + PopulateConnectivityState(json); + // populate the target. + GPR_ASSERT(target_view() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_view(), + GRPC_JSON_STRING, false); + // as CallCountingAndTracingNode to populate trace and call count data. + PopulateTrace(json); + PopulateCallData(json); + PopulateChildRefs(json); + return top_level_json; +} + grpc_arg ClientChannelNode::CreateChannelArg() { return grpc_channel_arg_pointer_create( const_cast(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC), @@ -111,20 +144,21 @@ RefCountedPtr ClientChannelNode::MakeClientChannelNode( channel, channel_tracer_max_nodes, is_top_level_channel); } -ClientChannelSubchannelNode::ClientChannelSubchannelNode( - size_t channel_tracer_max_nodes, grpc_subchannel* subchannel) - : SubchannelNode(channel_tracer_max_nodes), +SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, + size_t channel_tracer_max_nodes) + : CallCountingAndTracingNode(EntityType::kSubchannel, + channel_tracer_max_nodes), subchannel_(subchannel), target_(UniquePtr( - gpr_strdup(grpc_subchannel_get_target(subchannel_)))) {} + gpr_strdup(grpc_subchannel_get_target(subchannel_)))) { + subchannel_uuid_ = ChannelzRegistry::Register(this); +} -void ClientChannelSubchannelNode::PopulateTarget(grpc_json* json) { - GPR_ASSERT(target_.get() != nullptr); - grpc_json_create_child(nullptr, json, "target", target_.get(), - GRPC_JSON_STRING, false); +SubchannelNode::~SubchannelNode() { + ChannelzRegistry::Unregister(subchannel_uuid_); } -void ClientChannelSubchannelNode::PopulateConnectivityState(grpc_json* json) { +void SubchannelNode::PopulateConnectivityState(grpc_json* json) { grpc_connectivity_state state; if (subchannel_ == nullptr) { state = GRPC_CHANNEL_SHUTDOWN; @@ -138,5 +172,32 @@ void ClientChannelSubchannelNode::PopulateConnectivityState(grpc_json* json) { false); } +grpc_json* SubchannelNode::RenderJson() { + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "subchannelId", subchannel_uuid_); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + PopulateConnectivityState(json); + GPR_ASSERT(target_.get() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_.get(), + GRPC_JSON_STRING, false); + PopulateTrace(json); + PopulateCallData(json); + return top_level_json; +} + } // namespace channelz } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index b1bd8db89e..73eea7cecf 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -45,12 +45,7 @@ class ClientChannelNode : public ChannelNode { grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); - // Override this functionality since client_channels have a notion of - // channel connectivity. - void PopulateConnectivityState(grpc_json* json) override; - - // Override this functionality since client_channels have subchannels - void PopulateChildRefs(grpc_json* json) override; + grpc_json* RenderJson() override; // Helper to create a channel arg to ensure this type of ChannelNode is // created. @@ -65,35 +60,35 @@ class ClientChannelNode : public ChannelNode { GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW grpc_channel_element* client_channel_; + + // helpers + void PopulateConnectivityState(grpc_json* json); + void PopulateChildRefs(grpc_json* json); }; -// Subtype of SubchannelNode that overrides and provides client_channel -// specific functionality like querying for connectivity_state and -// subchannel target. -class ClientChannelSubchannelNode : public SubchannelNode { +// Handles channelz bookkeeping for sockets +class SubchannelNode : public CallCountingAndTracingNode { public: - ClientChannelSubchannelNode(size_t channel_tracer_max_nodes, - grpc_subchannel* subchannel); - ~ClientChannelSubchannelNode() override {} - - // Override this functionality since subchannels have a notion of - // channel connectivity. - void PopulateConnectivityState(grpc_json* json) override; - - // Override this functionality since client_channels subchannels hold - // their own target. - void PopulateTarget(grpc_json* json) override; + SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes); + ~SubchannelNode() override; void MarkSubchannelDestroyed() { GPR_ASSERT(subchannel_ != nullptr); subchannel_ = nullptr; } + grpc_json* RenderJson() override; + + intptr_t subchannel_uuid() { return subchannel_uuid_; } + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + intptr_t subchannel_uuid_; grpc_subchannel* subchannel_; UniquePtr target_; + + void PopulateConnectivityState(grpc_json* json); }; } // namespace channelz diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 0c3313c5de..8dfbd33ffe 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -135,7 +135,7 @@ struct grpc_subchannel { /** our alarm */ grpc_timer alarm; - grpc_core::RefCountedPtr + grpc_core::RefCountedPtr channelz_subchannel; }; @@ -393,9 +393,9 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, size_t channel_tracer_max_nodes = (size_t)grpc_channel_arg_get_integer(arg, options); if (channelz_enabled) { - c->channelz_subchannel = grpc_core::MakeRefCounted< - grpc_core::channelz::ClientChannelSubchannelNode>( - channel_tracer_max_nodes, c); + c->channelz_subchannel = + grpc_core::MakeRefCounted( + c, channel_tracer_max_nodes); c->channelz_subchannel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel created")); diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 7fe086da3c..d7f2d6a9a2 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -41,21 +41,30 @@ namespace grpc_core { namespace channelz { -CallCountingBase::CallCountingBase(size_t channel_tracer_max_nodes) { +char* BaseNode::RenderJsonString() { + grpc_json* json = RenderJson(); + char* json_str = grpc_json_dump_to_string(json, 0); + grpc_json_destroy(json); + return json_str; +} + +CallCountingAndTracingNode::CallCountingAndTracingNode( + EntityType type, size_t channel_tracer_max_nodes) + : BaseNode(type) { trace_.Init(channel_tracer_max_nodes); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -CallCountingBase::~CallCountingBase() { trace_.Destroy(); } +CallCountingAndTracingNode::~CallCountingAndTracingNode() { trace_.Destroy(); } -void CallCountingBase::RecordCallStarted() { +void CallCountingAndTracingNode::RecordCallStarted() { gpr_atm_no_barrier_fetch_add(&calls_started_, (gpr_atm)1); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -void CallCountingBase::PopulateTrace(grpc_json* json) { +void CallCountingAndTracingNode::PopulateTrace(grpc_json* json) { // fill in the channel trace if applicable grpc_json* trace_json = trace_->RenderJson(); if (trace_json != nullptr) { @@ -66,7 +75,7 @@ void CallCountingBase::PopulateTrace(grpc_json* json) { } } -void CallCountingBase::PopulateCallData(grpc_json* json) { +void CallCountingAndTracingNode::PopulateCallData(grpc_json* json) { grpc_json* json_iterator = nullptr; if (calls_started_ != 0) { json_iterator = grpc_json_add_number_string_child( @@ -87,31 +96,18 @@ void CallCountingBase::PopulateCallData(grpc_json* json) { gpr_format_timespec(ts), GRPC_JSON_STRING, true); } -char* CallCountingBase::RenderJsonString() { - grpc_json* json = RenderJson(); - char* json_str = grpc_json_dump_to_string(json, 0); - grpc_json_destroy(json); - return json_str; -} - ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel) - : CallCountingBase(channel_tracer_max_nodes), + : CallCountingAndTracingNode(is_top_level_channel + ? EntityType::kTopLevelChannel + : EntityType::kInternalChannel, + channel_tracer_max_nodes), channel_(channel), - is_top_level_channel_(is_top_level_channel) { - target_ = UniquePtr(grpc_channel_get_target(channel_)); - channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this); + target_(UniquePtr(grpc_channel_get_target(channel_))) { + channel_uuid_ = ChannelzRegistry::Register(this); } -ChannelNode::~ChannelNode() { - ChannelzRegistry::UnregisterChannelNode(channel_uuid_); -} - -void ChannelNode::PopulateTarget(grpc_json* json) { - GPR_ASSERT(target_.get() != nullptr); - grpc_json_create_child(nullptr, json, "target", target_.get(), - GRPC_JSON_STRING, false); -} +ChannelNode::~ChannelNode() { ChannelzRegistry::Unregister(channel_uuid_); } grpc_json* ChannelNode::RenderJson() { // We need to track these three json objects to build our object @@ -133,11 +129,13 @@ grpc_json* ChannelNode::RenderJson() { GRPC_JSON_OBJECT, false); json = data; json_iterator = nullptr; - PopulateConnectivityState(json); - PopulateTarget(json); + // populate the target. + GPR_ASSERT(target_.get() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_.get(), + GRPC_JSON_STRING, false); + // as CallCountingAndTracingNode to populate trace and call count data. PopulateTrace(json); PopulateCallData(json); - PopulateChildRefs(json); return top_level_json; } @@ -148,40 +146,5 @@ RefCountedPtr ChannelNode::MakeChannelNode( channel, channel_tracer_max_nodes, is_top_level_channel); } -SubchannelNode::SubchannelNode(size_t channel_tracer_max_nodes) - : CallCountingBase(channel_tracer_max_nodes) { - subchannel_uuid_ = ChannelzRegistry::RegisterSubchannelNode(this); -} - -SubchannelNode::~SubchannelNode() { - ChannelzRegistry::UnregisterSubchannelNode(subchannel_uuid_); -} - -grpc_json* SubchannelNode::RenderJson() { - grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); - grpc_json* json = top_level_json; - grpc_json* json_iterator = nullptr; - json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, - GRPC_JSON_OBJECT, false); - json = json_iterator; - json_iterator = nullptr; - json_iterator = grpc_json_add_number_string_child( - json, json_iterator, "subchannelId", subchannel_uuid_); - // reset json iterators to top level object - json = top_level_json; - json_iterator = nullptr; - // create and fill the data child. - grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, - GRPC_JSON_OBJECT, false); - json = data; - json_iterator = nullptr; - PopulateConnectivityState(json); - PopulateTarget(json); - PopulateTrace(json); - PopulateCallData(json); - PopulateChildRefs(json); - return top_level_json; -} - } // namespace channelz } // namespace grpc_core diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 1cd55bab43..1273545663 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -43,30 +43,40 @@ namespace grpc_core { namespace channelz { namespace testing { -class ChannelNodePeer; +class CallCountingAndTracingNodePeer; } // base class for all channelz entities class BaseNode : public RefCounted { public: - BaseNode() {} + // There are only four high level channelz entities. However, to support + // GetTopChannelsRequest, we split the Channel entity into two different + // types. All children of BaseNode must be one of these types. + enum class EntityType { + kTopLevelChannel, + kInternalChannel, + kSubchannel, + kServer, + kSocket, + }; + + // we track is_top_level_channel to support GetTopChannels + BaseNode(EntityType type) : type_(type) {} virtual ~BaseNode() {} - private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW -}; + // All children must implement this function. + virtual grpc_json* RenderJson() GRPC_ABSTRACT; -// Handles channelz bookkeeping for sockets -// TODO(ncteisen): implement in subsequent PR. -class SocketNode : public BaseNode { - public: - SocketNode() : BaseNode() {} - ~SocketNode() override {} + // Renders the json and returns allocated string that must be freed by the + // caller. + char* RenderJsonString(); + + EntityType type() const { return type_; } private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + EntityType type_; }; // This class is the parent for the channelz entities that deal with Channels @@ -76,16 +86,10 @@ class SocketNode : public BaseNode { // - track last_call_started_timestamp // - hold the channel trace. // - perform common rendering. -// -// This class also defines some fat interfaces so that its children can -// implement the functionality differently. For example, querying the -// connectivity state looks different for channels than for subchannels, and -// does not make sense for servers. So servers will not override, and channels -// and subchannels will override with their own way to query connectivity state. -class CallCountingBase : public BaseNode { +class CallCountingAndTracingNode : public BaseNode { public: - CallCountingBase(size_t channel_tracer_max_nodes); - ~CallCountingBase() override; + CallCountingAndTracingNode(EntityType type, size_t channel_tracer_max_nodes); + ~CallCountingAndTracingNode() override; void RecordCallStarted(); void RecordCallFailed() { @@ -96,34 +100,19 @@ class CallCountingBase : public BaseNode { } ChannelTrace* trace() { return trace_.get(); } - // Fat interface for ConnectivityState. Default is to leave it out, however, - // things like Channel and Subchannel will override with their mechanism - // for querying connectivity state. - virtual void PopulateConnectivityState(grpc_json* json) {} - - // Fat interface for Targets. - virtual void PopulateTarget(grpc_json* json) {} - - // Fat interface for ChildRefs. Allows children to populate with whatever - // combination of child_refs, subchannel_refs, and socket_refs is correct. - virtual void PopulateChildRefs(grpc_json* json) {} - - // All children must implement their custom JSON rendering. - virtual grpc_json* RenderJson() GRPC_ABSTRACT; - // Common rendering of the channel trace. void PopulateTrace(grpc_json* json); // Common rendering of the call count data and last_call_started_timestamp. void PopulateCallData(grpc_json* json); - // Common rendering of grpc_json from RenderJson() to allocated string. - char* RenderJsonString(); - private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + // testing peer friend. + friend class testing::CallCountingAndTracingNodePeer; + gpr_atm calls_started_ = 0; gpr_atm calls_succeeded_ = 0; gpr_atm calls_failed_ = 0; @@ -131,71 +120,64 @@ class CallCountingBase : public BaseNode { ManualConstructor trace_; }; -// Handles channelz bookkeeping for servers -// TODO(ncteisen): implement in subsequent PR. -class ServerNode : public CallCountingBase { - public: - ServerNode(size_t channel_tracer_max_nodes) - : CallCountingBase(channel_tracer_max_nodes) {} - ~ServerNode() override {} - - private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW -}; - -// Overrides Channel specific functionality. -class ChannelNode : public CallCountingBase { +// Handles channelz bookkeeping for channels +class ChannelNode : public CallCountingAndTracingNode { public: static RefCountedPtr MakeChannelNode( grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); + grpc_json* RenderJson() override; + void MarkChannelDestroyed() { GPR_ASSERT(channel_ != nullptr); channel_ = nullptr; } - grpc_json* RenderJson() override; - - void PopulateTarget(grpc_json* json) override; - bool ChannelIsDestroyed() { return channel_ == nullptr; } intptr_t channel_uuid() { return channel_uuid_; } - bool is_top_level_channel() { return is_top_level_channel_; } protected: ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); ~ChannelNode() override; + // provides view of target for child. + char* target_view() { return target_.get(); } private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - // testing peer friend. - friend class testing::ChannelNodePeer; - grpc_channel* channel_ = nullptr; UniquePtr target_; intptr_t channel_uuid_; - bool is_top_level_channel_ = true; }; -// Overrides Subchannel specific functionality. -class SubchannelNode : public CallCountingBase { +// Handles channelz bookkeeping for servers +// TODO(ncteisen): implement in subsequent PR. +class ServerNode : public CallCountingAndTracingNode { public: - SubchannelNode(size_t channel_tracer_max_nodes); - ~SubchannelNode() override; - grpc_json* RenderJson() override; - intptr_t subchannel_uuid() { return subchannel_uuid_; } + ServerNode(size_t channel_tracer_max_nodes) + : CallCountingAndTracingNode(EntityType::kServer, + channel_tracer_max_nodes) {} + ~ServerNode() override {} private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW +}; - intptr_t subchannel_uuid_; +// Handles channelz bookkeeping for sockets +// TODO(ncteisen): implement in subsequent PR. +class SocketNode : public BaseNode { + public: + SocketNode() : BaseNode(EntityType::kSocket) {} + ~SocketNode() override {} + + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW }; // Creation functions diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index aeeb6958e4..7f70908989 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -52,54 +52,46 @@ ChannelzRegistry::ChannelzRegistry() { gpr_mu_init(&mu_); } ChannelzRegistry::~ChannelzRegistry() { gpr_mu_destroy(&mu_); } -intptr_t ChannelzRegistry::InternalRegisterEntry(const RegistryEntry& entry) { +intptr_t ChannelzRegistry::InternalRegister(BaseNode* node) { mu_guard guard(&mu_); - entities_.push_back(entry); + entities_.push_back(node); intptr_t uuid = entities_.size(); return uuid; } -void ChannelzRegistry::InternalUnregisterEntry(intptr_t uuid, EntityType type) { +void ChannelzRegistry::InternalUnregister(intptr_t uuid) { GPR_ASSERT(uuid >= 1); mu_guard guard(&mu_); GPR_ASSERT(static_cast(uuid) <= entities_.size()); - GPR_ASSERT(entities_[uuid - 1].type == type); - entities_[uuid - 1].object = nullptr; - entities_[uuid - 1].type = EntityType::kUnset; + entities_[uuid - 1] = nullptr; } -void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) { +BaseNode* ChannelzRegistry::InternalGet(intptr_t uuid) { mu_guard guard(&mu_); if (uuid < 1 || uuid > static_cast(entities_.size())) { return nullptr; } - if (entities_[uuid - 1].type == type) { - return entities_[uuid - 1].object; - } else { - return nullptr; - } + return entities_[uuid - 1]; } char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; grpc_json* json_iterator = nullptr; - InlinedVector top_level_channels; + InlinedVector top_level_channels; // 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_channel_id=0, which signifies "give me everything." Hence this // funky looking line below. size_t start_idx = start_channel_id == 0 ? 0 : start_channel_id - 1; for (size_t i = start_idx; i < entities_.size(); ++i) { - if (entities_[i].type == EntityType::kChannelNode) { - ChannelNode* channel_node = - static_cast(entities_[i].object); - if (channel_node->is_top_level_channel()) { - top_level_channels.push_back(channel_node); - } + if (entities_[i] != nullptr && + entities_[i]->type() == + grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel) { + top_level_channels.push_back(entities_[i]); } } - if (top_level_channels.size() > 0) { + if (!top_level_channels.empty()) { // create list of channels grpc_json* array_parent = grpc_json_create_child( nullptr, json, "channel", nullptr, GRPC_JSON_ARRAY, false); @@ -128,9 +120,14 @@ char* grpc_channelz_get_top_channels(intptr_t start_channel_id) { } char* grpc_channelz_get_channel(intptr_t channel_id) { - grpc_core::channelz::ChannelNode* channel_node = - grpc_core::channelz::ChannelzRegistry::GetChannelNode(channel_id); - if (channel_node == nullptr) { + grpc_core::channelz::BaseNode* channel_node = + grpc_core::channelz::ChannelzRegistry::Get(channel_id); + if (channel_node == nullptr || + + (channel_node->type() != + grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel && + channel_node->type() != + grpc_core::channelz::BaseNode::EntityType::kInternalChannel)) { return nullptr; } grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); @@ -144,9 +141,11 @@ char* grpc_channelz_get_channel(intptr_t channel_id) { } char* grpc_channelz_get_subchannel(intptr_t subchannel_id) { - grpc_core::channelz::SubchannelNode* subchannel_node = - grpc_core::channelz::ChannelzRegistry::GetSubchannelNode(subchannel_id); - if (subchannel_node == nullptr) { + grpc_core::channelz::BaseNode* subchannel_node = + grpc_core::channelz::ChannelzRegistry::Get(subchannel_id); + if (subchannel_node == nullptr || + subchannel_node->type() != + grpc_core::channelz::BaseNode::EntityType::kSubchannel) { return nullptr; } grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h index 5d7c936726..142c039220 100644 --- a/src/core/lib/channel/channelz_registry.h +++ b/src/core/lib/channel/channelz_registry.h @@ -40,32 +40,11 @@ class ChannelzRegistry { // To be called in grpc_shutdown(); static void Shutdown(); - // Register/Unregister/Get for ChannelNode - static intptr_t RegisterChannelNode(ChannelNode* channel_node) { - RegistryEntry entry(channel_node, EntityType::kChannelNode); - return Default()->InternalRegisterEntry(entry); - } - static void UnregisterChannelNode(intptr_t uuid) { - Default()->InternalUnregisterEntry(uuid, EntityType::kChannelNode); - } - static ChannelNode* GetChannelNode(intptr_t uuid) { - void* gotten = Default()->InternalGetEntry(uuid, EntityType::kChannelNode); - return gotten == nullptr ? nullptr : static_cast(gotten); - } - - // Register/Unregister/Get for SubchannelNode - static intptr_t RegisterSubchannelNode(SubchannelNode* channel_node) { - RegistryEntry entry(channel_node, EntityType::kSubchannelNode); - return Default()->InternalRegisterEntry(entry); - } - static void UnregisterSubchannelNode(intptr_t uuid) { - Default()->InternalUnregisterEntry(uuid, EntityType::kSubchannelNode); - } - static SubchannelNode* GetSubchannelNode(intptr_t uuid) { - void* gotten = - Default()->InternalGetEntry(uuid, EntityType::kSubchannelNode); - return gotten == nullptr ? nullptr : static_cast(gotten); + static intptr_t Register(BaseNode* node) { + return Default()->InternalRegister(node); } + static void Unregister(intptr_t uuid) { Default()->InternalUnregister(uuid); } + static BaseNode* Get(intptr_t uuid) { return Default()->InternalGet(uuid); } // Returns the allocated JSON string that represents the proto // GetTopChannelsResponse as per channelz.proto. @@ -74,19 +53,6 @@ class ChannelzRegistry { } private: - enum class EntityType { - kChannelNode, - kSubchannelNode, - kUnset, - }; - - struct RegistryEntry { - RegistryEntry(void* object_in, EntityType type_in) - : object(object_in), type(type_in) {} - void* object; - EntityType type; - }; - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE @@ -97,21 +63,21 @@ class ChannelzRegistry { static ChannelzRegistry* Default(); // globally registers an Entry. Returns its unique uuid - intptr_t InternalRegisterEntry(const RegistryEntry& entry); + intptr_t InternalRegister(BaseNode* node); // globally unregisters the object that is associated to uuid. Also does // sanity check that an object doesn't try to unregister the wrong type. - void InternalUnregisterEntry(intptr_t uuid, EntityType type); + void InternalUnregister(intptr_t uuid); // if object with uuid has previously been registered as the correct type, // returns the void* associated with that uuid. Else returns nullptr. - void* InternalGetEntry(intptr_t uuid, EntityType type); + BaseNode* InternalGet(intptr_t uuid); char* InternalGetTopChannels(intptr_t start_channel_id); // protects entities_ and uuid_ gpr_mu mu_; - InlinedVector entities_; + InlinedVector entities_; }; } // namespace channelz diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc index 581e867584..c02d525c81 100644 --- a/test/core/channel/channelz_registry_test.cc +++ b/test/core/channel/channelz_registry_test.cc @@ -44,22 +44,22 @@ namespace channelz { namespace testing { TEST(ChannelzRegistryTest, UuidStartsAboveZeroTest) { - ChannelNode* channelz_channel = nullptr; - intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); + BaseNode* channelz_channel = nullptr; + intptr_t uuid = ChannelzRegistry::Register(channelz_channel); EXPECT_GT(uuid, 0) << "First uuid chose must be greater than zero. Zero if " "reserved according to " "https://github.com/grpc/proposal/blob/master/" "A14-channelz.md"; - ChannelzRegistry::UnregisterChannelNode(uuid); + ChannelzRegistry::Unregister(uuid); } TEST(ChannelzRegistryTest, UuidsAreIncreasing) { - ChannelNode* channelz_channel = nullptr; + BaseNode* channelz_channel = nullptr; std::vector uuids; uuids.reserve(10); for (int i = 0; i < 10; ++i) { // reregister the same object. It's ok since we are just testing uuids - uuids.push_back(ChannelzRegistry::RegisterChannelNode(channelz_channel)); + uuids.push_back(ChannelzRegistry::Register(channelz_channel)); } for (size_t i = 1; i < uuids.size(); ++i) { EXPECT_LT(uuids[i - 1], uuids[i]) << "Uuids must always be increasing"; @@ -68,30 +68,30 @@ TEST(ChannelzRegistryTest, UuidsAreIncreasing) { TEST(ChannelzRegistryTest, RegisterGetTest) { // we hackily jam an intptr_t into this pointer to check for equality later - ChannelNode* channelz_channel = (ChannelNode*)42; - intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); - ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); + BaseNode* channelz_channel = (BaseNode*)42; + intptr_t uuid = ChannelzRegistry::Register(channelz_channel); + BaseNode* retrieved = ChannelzRegistry::Get(uuid); EXPECT_EQ(channelz_channel, retrieved); } TEST(ChannelzRegistryTest, RegisterManyItems) { // we hackily jam an intptr_t into this pointer to check for equality later - ChannelNode* channelz_channel = (ChannelNode*)42; + BaseNode* channelz_channel = (BaseNode*)42; for (int i = 0; i < 100; i++) { - intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); - ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); + intptr_t uuid = ChannelzRegistry::Register(channelz_channel); + BaseNode* retrieved = ChannelzRegistry::Get(uuid); EXPECT_EQ(channelz_channel, retrieved); } } TEST(ChannelzRegistryTest, NullIfNotPresentTest) { // we hackily jam an intptr_t into this pointer to check for equality later - ChannelNode* channelz_channel = (ChannelNode*)42; - intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); + BaseNode* channelz_channel = (BaseNode*)42; + intptr_t uuid = ChannelzRegistry::Register(channelz_channel); // try to pull out a uuid that does not exist. - ChannelNode* nonexistant = ChannelzRegistry::GetChannelNode(uuid + 1); + BaseNode* nonexistant = ChannelzRegistry::Get(uuid + 1); EXPECT_EQ(nonexistant, nullptr); - ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); + BaseNode* retrieved = ChannelzRegistry::Get(uuid); EXPECT_EQ(channelz_channel, retrieved); } diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index b8e65ebfb3..ec1c9f6faf 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -44,16 +44,17 @@ namespace channelz { namespace testing { // testing peer to access channel internals -class ChannelNodePeer { +class CallCountingAndTracingNodePeer { public: - ChannelNodePeer(ChannelNode* channel) : channel_(channel) {} + CallCountingAndTracingNodePeer(CallCountingAndTracingNode* node) + : node_(node) {} grpc_millis last_call_started_millis() { return (grpc_millis)gpr_atm_no_barrier_load( - &channel_->last_call_started_millis_); + &node_->last_call_started_millis_); } private: - ChannelNode* channel_; + CallCountingAndTracingNode* node_; }; namespace { @@ -163,16 +164,8 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { gpr_free(core_api_json_str); } -void ValidateSubchannel(SubchannelNode* subchannel, - validate_channel_data_args args) { - char* json_str = subchannel->RenderJsonString(); - grpc::testing::ValidateSubchannelProtoJsonTranslation(json_str); - ValidateCounters(json_str, args); - gpr_free(json_str); -} - -grpc_millis GetLastCallStartedMillis(ChannelNode* channel) { - ChannelNodePeer peer(channel); +grpc_millis GetLastCallStartedMillis(CallCountingAndTracingNode* channel) { + CallCountingAndTracingNodePeer peer(channel); return peer.last_call_started_millis(); } @@ -283,29 +276,8 @@ TEST(ChannelzGetTopChannelsTest, InternalChannelTest) { grpc_channel_destroy(internal_channel); } -class ChannelzSubchannelTest : public ::testing::TestWithParam {}; - -TEST_P(ChannelzSubchannelTest, BasicTest) { - grpc_core::ExecCtx exec_ctx; - RefCountedPtr channelz_subchannel = - MakeRefCounted(GetParam()); - channelz_subchannel->RecordCallStarted(); - channelz_subchannel->RecordCallFailed(); - channelz_subchannel->RecordCallSucceeded(); - ValidateSubchannel(channelz_subchannel.get(), {1, 1, 1}); - channelz_subchannel->RecordCallStarted(); - channelz_subchannel->RecordCallFailed(); - channelz_subchannel->RecordCallSucceeded(); - channelz_subchannel->RecordCallStarted(); - channelz_subchannel->RecordCallFailed(); - channelz_subchannel->RecordCallSucceeded(); - ValidateSubchannel(channelz_subchannel.get(), {3, 3, 3}); -} - INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest, ::testing::Values(0, 1, 2, 6, 10, 15)); -INSTANTIATE_TEST_CASE_P(ChannelzSubchannelTestSweep, ChannelzSubchannelTest, - ::testing::Values(0, 1, 10, 15)); } // namespace testing } // namespace channelz -- cgit v1.2.3 From 835dab6a464b3246f6bdc3b1bb0fe706551a0260 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 20 Jul 2018 16:17:48 -0700 Subject: Full subchannel support --- .../ext/filters/client_channel/client_channel.cc | 5 +++- .../client_channel/client_channel_channelz.cc | 2 ++ src/core/ext/filters/client_channel/subchannel.cc | 33 ++++++++++++++-------- src/core/ext/filters/client_channel/subchannel.h | 10 ++++++- src/core/lib/channel/channel_stack.h | 1 + src/core/lib/surface/call.cc | 22 ++++++++++++++- src/core/lib/surface/call.h | 13 +++++++++ test/core/channel/channel_stack_test.cc | 3 +- test/core/end2end/tests/channelz.cc | 4 +++ 9 files changed, 77 insertions(+), 16 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 024c9d737e..13a0b95511 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -892,6 +892,7 @@ typedef struct client_channel_call_data { grpc_millis deadline; gpr_arena* arena; grpc_call_stack* owning_call; + grpc_call* call; grpc_call_combiner* call_combiner; grpc_core::RefCountedPtr retry_throttle_data; @@ -2561,7 +2562,8 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) { calld->arena, // arena calld->pick.subchannel_call_context, // context calld->call_combiner, // call_combiner - parent_data_size // parent_data_size + parent_data_size, // parent_data_size + calld->call // call }; grpc_error* new_error = calld->pick.connected_subchannel->CreateCall( call_args, &calld->subchannel_call); @@ -3092,6 +3094,7 @@ static grpc_error* cc_init_call_elem(grpc_call_element* elem, calld->arena = args->arena; calld->owning_call = args->call_stack; calld->call_combiner = args->call_combiner; + calld->call = args->call; if (GPR_LIKELY(chand->deadline_checking_enabled)) { grpc_deadline_state_init(elem, args->call_stack, args->call_combiner, calld->deadline); diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 0db9799a65..a1ecbe75a2 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -126,6 +126,8 @@ grpc_json* ClientChannelNode::RenderJson() { // as CallCountingAndTracingNode to populate trace and call count data. PopulateTrace(json); PopulateCallData(json); + // reset to the top level + json = top_level_json; PopulateChildRefs(json); return top_level_json; } diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 8dfbd33ffe..a15cfd43c3 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -46,6 +46,7 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/transport/connectivity_state.h" @@ -640,8 +641,8 @@ static bool publish_transport_locked(grpc_subchannel* c) { } /* publish */ - c->connected_subchannel.reset( - grpc_core::New(stk)); + c->connected_subchannel.reset(grpc_core::New( + stk, c->channelz_subchannel.get())); gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p", c->connected_subchannel.get(), c); @@ -796,9 +797,12 @@ grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) { namespace grpc_core { -ConnectedSubchannel::ConnectedSubchannel(grpc_channel_stack* channel_stack) +ConnectedSubchannel::ConnectedSubchannel( + grpc_channel_stack* channel_stack, + channelz::SubchannelNode* channelz_subchannel) : RefCountedWithTracing(&grpc_trace_stream_refcount), - channel_stack_(channel_stack) {} + channel_stack_(channel_stack), + channelz_subchannel_(channelz_subchannel) {} ConnectedSubchannel::~ConnectedSubchannel() { GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); @@ -845,14 +849,15 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, connection.release(); // Ref is passed to the grpc_subchannel_call object. (*call)->connection = this; const grpc_call_element_args call_args = { - callstk, /* call_stack */ - nullptr, /* server_transport_data */ - args.context, /* context */ - args.path, /* path */ - args.start_time, /* start_time */ - args.deadline, /* deadline */ - args.arena, /* arena */ - args.call_combiner /* call_combiner */ + callstk, /* call_stack */ + nullptr, /* server_transport_data */ + args.context, /* context */ + args.path, /* path */ + args.start_time, /* start_time */ + args.deadline, /* deadline */ + args.arena, /* arena */ + args.call_combiner, /* call_combiner */ + args.call /* call */ }; grpc_error* error = grpc_call_stack_init( channel_stack_, 1, subchannel_call_destroy, *call, &call_args); @@ -861,6 +866,10 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, gpr_log(GPR_ERROR, "error: %s", error_string); return error; } + if (channelz_subchannel_ != nullptr) { + channelz_subchannel_->RecordCallStarted(); + grpc_call_set_channelz_subchannel(args.call, channelz_subchannel_); + } grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); return GRPC_ERROR_NONE; } diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index dd3a2d9621..d62348488e 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -83,9 +83,11 @@ class ConnectedSubchannel : public RefCountedWithTracing { grpc_call_context_element* context; grpc_call_combiner* call_combiner; size_t parent_data_size; + grpc_call* call; }; - explicit ConnectedSubchannel(grpc_channel_stack* channel_stack); + explicit ConnectedSubchannel(grpc_channel_stack* channel_stack, + channelz::SubchannelNode* channelz_subchannel); ~ConnectedSubchannel(); grpc_channel_stack* channel_stack() { return channel_stack_; } @@ -94,9 +96,15 @@ class ConnectedSubchannel : public RefCountedWithTracing { grpc_closure* closure); void Ping(grpc_closure* on_initiate, grpc_closure* on_ack); grpc_error* CreateCall(const CallArgs& args, grpc_subchannel_call** call); + channelz::SubchannelNode* channelz_subchannel() { + return channelz_subchannel_; + } private: grpc_channel_stack* channel_stack_; + // backpointer to the channelz node in this connected subchannel's + // owning subchannel. + channelz::SubchannelNode* channelz_subchannel_; }; } // namespace grpc_core diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index 7581f937b6..727f36a6f8 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -71,6 +71,7 @@ typedef struct { grpc_millis deadline; gpr_arena* arena; grpc_call_combiner* call_combiner; + grpc_call* call; } grpc_call_element_args; typedef struct { diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 88e015ce22..6545af8f72 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -170,6 +170,11 @@ struct grpc_call { /* parent_call* */ gpr_atm parent_call_atm; child_call* child; + // the call holds onto this so that once the call knows if the RPC was + // a success or failure, it can update the channelz bookkeeping for the + // subchannel that sent it. + grpc_core::channelz::CallCountingAndTracingNode* channelz_subchannel_; + /* client or server call */ bool is_client; /** has grpc_call_unref been called */ @@ -269,6 +274,11 @@ struct grpc_call { gpr_atm recv_state; }; +void grpc_call_set_channelz_subchannel( + grpc_call* call, grpc_core::channelz::CallCountingAndTracingNode* node) { + call->channelz_subchannel_ = node; +} + grpc_core::TraceFlag grpc_call_error_trace(false, "call_error"); grpc_core::TraceFlag grpc_compression_trace(false, "compression"); @@ -444,7 +454,8 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, call->start_time, send_deadline, call->arena, - &call->call_combiner}; + &call->call_combiner, + call}; add_init_error(&error, grpc_call_stack_init(channel_stack, 1, destroy_call, call, &call_args)); // Publish this call to parent only after the call stack has been initialized. @@ -1263,6 +1274,7 @@ static void post_batch_completion(batch_control* bctl) { get_final_status(call, set_cancelled_value, call->final_op.server.cancelled, nullptr, nullptr); } + // Record channelz data for the channel. grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { @@ -1272,6 +1284,14 @@ static void post_batch_completion(batch_control* bctl) { channelz_channel->RecordCallSucceeded(); } } + // Record channelz data for the subchannel. + if (call->channelz_subchannel_ != nullptr) { + if (*call->final_op.client.status != GRPC_STATUS_OK) { + call->channelz_subchannel_->RecordCallFailed(); + } else { + call->channelz_subchannel_->RecordCallSucceeded(); + } + } GRPC_ERROR_UNREF(error); error = GRPC_ERROR_NONE; } diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index b3b06059d4..200c840c61 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -110,6 +110,19 @@ size_t grpc_call_get_initial_size_estimate(); grpc_compression_algorithm grpc_call_compression_for_level( grpc_call* call, grpc_compression_level level); +namespace grpc_core { +namespace channelz { +class CallCountingAndTracingNode; +} // namespace channelz +} // namespace grpc_core + +// We need this so that a subchannel selected for a call can add itself to +// the call's data structure. This allows the call to trigger the correct +// channelz bookkeeping on the subchannel once the call knows if the RPC was +// successful or not. +void grpc_call_set_channelz_subchannel( + grpc_call* call, grpc_core::channelz::CallCountingAndTracingNode* node); + extern grpc_core::TraceFlag grpc_call_error_trace; extern grpc_core::TraceFlag grpc_compression_trace; diff --git a/test/core/channel/channel_stack_test.cc b/test/core/channel/channel_stack_test.cc index 2f5329a96d..4dc2ee3f55 100644 --- a/test/core/channel/channel_stack_test.cc +++ b/test/core/channel/channel_stack_test.cc @@ -124,7 +124,8 @@ static void test_create_channel_stack(void) { gpr_now(GPR_CLOCK_MONOTONIC), /* start_time */ GRPC_MILLIS_INF_FUTURE, /* deadline */ nullptr, /* arena */ - nullptr /* call_combiner */ + nullptr, /* call_combiner */ + nullptr /* call */ }; grpc_error* error = grpc_call_stack_init(channel_stack, 1, free_call, call_stack, &args); diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 533703a2be..754c3d3741 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -241,6 +241,10 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); + json = grpc_channelz_get_subchannel(2); + gpr_log(GPR_INFO, "%s", json); + gpr_free(json); + end_test(&f); config.tear_down_data(&f); } -- cgit v1.2.3 From f081cf67d16049dc07141420601272d9f5988b1c Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 20 Jul 2018 17:55:36 -0700 Subject: refactor --- .../client_channel/client_channel_channelz.cc | 16 ++-- .../client_channel/client_channel_channelz.h | 2 - .../client_channel/lb_policy/grpclb/grpclb.cc | 2 +- .../client_channel/lb_policy/subchannel_list.h | 2 +- src/core/lib/channel/channel_trace.cc | 42 ++++----- src/core/lib/channel/channel_trace.h | 26 +++--- src/core/lib/channel/channelz.cc | 14 +-- src/core/lib/channel/channelz.h | 10 +-- test/core/channel/channel_trace_test.cc | 100 +++++++++++---------- test/core/channel/channelz_test.cc | 2 +- 10 files changed, 102 insertions(+), 114 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index a1ecbe75a2..996a871f38 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -108,8 +108,8 @@ grpc_json* ClientChannelNode::RenderJson() { GRPC_JSON_OBJECT, false); json = json_iterator; json_iterator = nullptr; - json_iterator = grpc_json_add_number_string_child( - json, json_iterator, "channelId", channel_uuid()); + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "channelId", uuid()); // reset json iterators to top level object json = top_level_json; json_iterator = nullptr; @@ -152,13 +152,9 @@ SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, channel_tracer_max_nodes), subchannel_(subchannel), target_(UniquePtr( - gpr_strdup(grpc_subchannel_get_target(subchannel_)))) { - subchannel_uuid_ = ChannelzRegistry::Register(this); -} + gpr_strdup(grpc_subchannel_get_target(subchannel_)))) {} -SubchannelNode::~SubchannelNode() { - ChannelzRegistry::Unregister(subchannel_uuid_); -} +SubchannelNode::~SubchannelNode() {} void SubchannelNode::PopulateConnectivityState(grpc_json* json) { grpc_connectivity_state state; @@ -182,8 +178,8 @@ grpc_json* SubchannelNode::RenderJson() { GRPC_JSON_OBJECT, false); json = json_iterator; json_iterator = nullptr; - json_iterator = grpc_json_add_number_string_child( - json, json_iterator, "subchannelId", subchannel_uuid_); + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "subchannelId", uuid()); // reset json iterators to top level object json = top_level_json; json_iterator = nullptr; diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 73eea7cecf..45df756b91 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -79,8 +79,6 @@ class SubchannelNode : public CallCountingAndTracingNode { grpc_json* RenderJson() override; - intptr_t subchannel_uuid() { return subchannel_uuid_; } - private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 959c7441a3..dc475d3d68 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -1294,7 +1294,7 @@ void GrpcLb::FillChildRefsForChannelz(ChildRefsList* child_subchannels, grpc_core::channelz::ChannelNode* channel_node = grpc_channel_get_channelz_node(lb_channel_); if (channel_node != nullptr) { - child_channels->push_back(channel_node->channel_uuid()); + child_channels->push_back(channel_node->uuid()); } } } diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index 018ac3bb86..199b9a3c13 100644 --- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -196,7 +196,7 @@ class SubchannelList grpc_core::channelz::SubchannelNode* subchannel_node = grpc_subchannel_get_channelz_node(subchannels_[i].subchannel()); if (subchannel_node != nullptr) { - refs_list->push_back(subchannel_node->subchannel_uuid()); + refs_list->push_back(subchannel_node->uuid()); } } } diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index dd6fdeed54..ba2b3bcad6 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -41,16 +41,14 @@ namespace grpc_core { namespace channelz { -ChannelTrace::TraceEvent::TraceEvent( - Severity severity, grpc_slice data, - RefCountedPtr referenced_channel, ReferencedType type) +ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, + RefCountedPtr referenced_entity) : severity_(severity), data_(data), timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), GPR_CLOCK_REALTIME)), next_(nullptr), - referenced_channel_(std::move(referenced_channel)), - referenced_type_(type) {} + referenced_entity_(std::move(referenced_entity)) {} ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data) : severity_(severity), @@ -112,21 +110,11 @@ void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice data) { void ChannelTrace::AddTraceEventReferencingChannel( Severity severity, grpc_slice data, - RefCountedPtr referenced_channel) { - if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 - // create and fill up the new event - AddTraceEventHelper(New( - severity, data, std::move(referenced_channel), ReferencedType::Channel)); -} - -void ChannelTrace::AddTraceEventReferencingSubchannel( - Severity severity, grpc_slice data, - RefCountedPtr referenced_subchannel) { + RefCountedPtr referenced_entity) { if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 // create and fill up the new event - AddTraceEventHelper(New(severity, data, - std::move(referenced_subchannel), - ReferencedType::Subchannel)); + AddTraceEventHelper( + New(severity, data, std::move(referenced_entity))); } namespace { @@ -157,18 +145,24 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { json_iterator = grpc_json_create_child(json_iterator, json, "timestamp", gpr_format_timespec(timestamp_), GRPC_JSON_STRING, true); - if (referenced_channel_ != nullptr) { + if (referenced_entity_ != nullptr) { + GPR_ASSERT( + referenced_entity_->type() == BaseNode::EntityType::kSubchannel || + referenced_entity_->type() == BaseNode::EntityType::kTopLevelChannel || + referenced_entity_->type() == BaseNode::EntityType::kInternalChannel); char* uuid_str; - gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->channel_uuid()); + gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_entity_->uuid()); grpc_json* child_ref = grpc_json_create_child( json_iterator, json, - (referenced_type_ == ReferencedType::Channel) ? "channelRef" - : "subchannelRef", + (referenced_entity_->type() == BaseNode::EntityType::kSubchannel) + ? "subchannelRef" + : "channelRef", nullptr, GRPC_JSON_OBJECT, false); json_iterator = grpc_json_create_child( nullptr, child_ref, - (referenced_type_ == ReferencedType::Channel) ? "channelId" - : "subchannelId", + (referenced_entity_->type() == BaseNode::EntityType::kSubchannel) + ? "subchannelId" + : "channelId", uuid_str, GRPC_JSON_STRING, true); json_iterator = child_ref; } diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h index 596af7402f..cef8814d5f 100644 --- a/src/core/lib/channel/channel_trace.h +++ b/src/core/lib/channel/channel_trace.h @@ -30,7 +30,7 @@ namespace grpc_core { namespace channelz { -class ChannelNode; +class BaseNode; // Object used to hold live data for a channel. This data is exposed via the // channelz service: @@ -55,35 +55,32 @@ class ChannelTrace { void AddTraceEvent(Severity severity, grpc_slice data); // Adds a new trace event to the tracing object. This trace event refers to a - // an event on a child of the channel. For example, if this channel has - // created a new subchannel, then it would record that with a TraceEvent - // referencing the new subchannel. + // an event that concerns a different channelz entity. For example, if this + // channel has created a new subchannel, then it would record that with + // a TraceEvent referencing the new subchannel. // // TODO(ncteisen): as this call is used more and more throughout the gRPC // stack, determine if it makes more sense to accept a char* instead of a // slice. void AddTraceEventReferencingChannel( Severity severity, grpc_slice data, - RefCountedPtr referenced_channel); - void AddTraceEventReferencingSubchannel( - Severity severity, grpc_slice data, - RefCountedPtr referenced_subchannel); + RefCountedPtr referenced_entity); + // void AddTraceEventWithReference( + // Severity severity, grpc_slice data, + // RefCountedPtr referenced_entity); // Creates and returns the raw grpc_json object, so a parent channelz // object may incorporate the json before rendering. grpc_json* RenderJson() const; private: - // Types of objects that can be references by trace events. - enum class ReferencedType { Channel, Subchannel }; // Private class to encapsulate all the data and bookkeeping needed for a // a trace event. class TraceEvent { public: // Constructor for a TraceEvent that references a different channel. TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced_channel, - ReferencedType type); + RefCountedPtr referenced); // Constructor for a TraceEvent that does not reverence a different // channel. @@ -105,10 +102,7 @@ class ChannelTrace { gpr_timespec timestamp_; TraceEvent* next_; // the tracer object for the (sub)channel that this trace event refers to. - RefCountedPtr referenced_channel_; - // the type that the referenced tracer points to. Unused if this trace - // does not point to any channel or subchannel - ReferencedType referenced_type_; + RefCountedPtr referenced_entity_; }; // TraceEvent // Internal helper to add and link in a trace event diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index d7f2d6a9a2..eec2cd61b2 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -41,6 +41,12 @@ namespace grpc_core { namespace channelz { +BaseNode::BaseNode(EntityType type) : type_(type) { + uuid_ = ChannelzRegistry::Register(this); +} + +BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); } + char* BaseNode::RenderJsonString() { grpc_json* json = RenderJson(); char* json_str = grpc_json_dump_to_string(json, 0); @@ -103,11 +109,9 @@ ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, : EntityType::kInternalChannel, channel_tracer_max_nodes), channel_(channel), - target_(UniquePtr(grpc_channel_get_target(channel_))) { - channel_uuid_ = ChannelzRegistry::Register(this); -} + target_(UniquePtr(grpc_channel_get_target(channel_))) {} -ChannelNode::~ChannelNode() { ChannelzRegistry::Unregister(channel_uuid_); } +ChannelNode::~ChannelNode() {} grpc_json* ChannelNode::RenderJson() { // We need to track these three json objects to build our object @@ -120,7 +124,7 @@ grpc_json* ChannelNode::RenderJson() { json = json_iterator; json_iterator = nullptr; json_iterator = grpc_json_add_number_string_child(json, json_iterator, - "channelId", channel_uuid_); + "channelId", uuid()); // reset json iterators to top level object json = top_level_json; json_iterator = nullptr; diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 1273545663..67cd1fec2d 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -60,9 +60,8 @@ class BaseNode : public RefCounted { kSocket, }; - // we track is_top_level_channel to support GetTopChannels - BaseNode(EntityType type) : type_(type) {} - virtual ~BaseNode() {} + BaseNode(EntityType type); + virtual ~BaseNode(); // All children must implement this function. virtual grpc_json* RenderJson() GRPC_ABSTRACT; @@ -72,11 +71,14 @@ class BaseNode : public RefCounted { char* RenderJsonString(); EntityType type() const { return type_; } + intptr_t uuid() const { return uuid_; } private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + friend class ChannelTrace; EntityType type_; + intptr_t uuid_; }; // This class is the parent for the channelz entities that deal with Channels @@ -136,8 +138,6 @@ class ChannelNode : public CallCountingAndTracingNode { bool ChannelIsDestroyed() { return channel_ == nullptr; } - intptr_t channel_uuid() { return channel_uuid_; } - protected: ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 99d9a4847f..703a9e457f 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -156,7 +156,7 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = MakeRefCounted(channel1.channel(), GetParam(), true); - tracer.AddTraceEventReferencingSubchannel( + tracer.AddTraceEventReferencingChannel( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); @@ -177,7 +177,7 @@ TEST_P(ChannelTracerTest, ComplexTest) { tracer.AddTraceEventReferencingChannel( ChannelTrace::Severity::Info, grpc_slice_from_static_string("LB channel two created"), sc2); - tracer.AddTraceEventReferencingSubchannel( + tracer.AddTraceEventReferencingChannel( ChannelTrace::Severity::Warning, grpc_slice_from_static_string("subchannel one inactive"), sc1); ValidateChannelTrace(&tracer, 7, GetParam()); @@ -191,53 +191,55 @@ TEST_P(ChannelTracerTest, ComplexTest) { sc2.reset(nullptr); } -// Test a case in which the parent channel has subchannels and the subchannels -// have connections. Ensures that everything lives as long as it should then -// gets deleted. -TEST_P(ChannelTracerTest, TestNesting) { - grpc_core::ExecCtx exec_ctx; - ChannelTrace tracer(GetParam()); - AddSimpleTrace(&tracer); - AddSimpleTrace(&tracer); - ValidateChannelTrace(&tracer, 2, GetParam()); - ChannelFixture channel1(GetParam()); - RefCountedPtr sc1 = - MakeRefCounted(channel1.channel(), GetParam(), true); - tracer.AddTraceEventReferencingChannel( - ChannelTrace::Severity::Info, - grpc_slice_from_static_string("subchannel one created"), sc1); - ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->trace()); - ChannelFixture channel2(GetParam()); - RefCountedPtr conn1 = - MakeRefCounted(channel2.channel(), GetParam(), true); - // nesting one level deeper. - sc1->trace()->AddTraceEventReferencingSubchannel( - ChannelTrace::Severity::Info, - grpc_slice_from_static_string("connection one created"), conn1); - ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(conn1->trace()); - AddSimpleTrace(&tracer); - AddSimpleTrace(&tracer); - ValidateChannelTrace(&tracer, 5, GetParam()); - ValidateChannelTrace(conn1->trace(), 1, GetParam()); - ChannelFixture channel3(GetParam()); - RefCountedPtr sc2 = - MakeRefCounted(channel3.channel(), GetParam(), true); - tracer.AddTraceEventReferencingSubchannel( - ChannelTrace::Severity::Info, - grpc_slice_from_static_string("subchannel two created"), sc2); - // this trace should not get added to the parents children since it is already - // present in the tracer. - tracer.AddTraceEventReferencingChannel( - ChannelTrace::Severity::Warning, - grpc_slice_from_static_string("subchannel one inactive"), sc1); - AddSimpleTrace(&tracer); - ValidateChannelTrace(&tracer, 8, GetParam()); - sc1.reset(nullptr); - sc2.reset(nullptr); - conn1.reset(nullptr); -} +// // Test a case in which the parent channel has subchannels and the +// subchannels +// // have connections. Ensures that everything lives as long as it should then +// // gets deleted. +// TEST_P(ChannelTracerTest, TestNesting) { +// grpc_core::ExecCtx exec_ctx; +// ChannelTrace tracer(GetParam()); +// AddSimpleTrace(&tracer); +// AddSimpleTrace(&tracer); +// ValidateChannelTrace(&tracer, 2, GetParam()); +// ChannelFixture channel1(GetParam()); +// RefCountedPtr sc1 = +// MakeRefCounted(channel1.channel(), GetParam(), true); +// tracer.AddTraceEventReferencingChannel( +// ChannelTrace::Severity::Info, +// grpc_slice_from_static_string("subchannel one created"), sc1); +// ValidateChannelTrace(&tracer, 3, GetParam()); +// AddSimpleTrace(sc1->trace()); +// ChannelFixture channel2(GetParam()); +// RefCountedPtr conn1 = +// MakeRefCounted(channel2.channel(), GetParam(), true); +// // nesting one level deeper. +// sc1->trace()->AddTraceEventReferencingChannel( +// ChannelTrace::Severity::Info, +// grpc_slice_from_static_string("connection one created"), conn1); +// ValidateChannelTrace(&tracer, 3, GetParam()); +// AddSimpleTrace(conn1->trace()); +// AddSimpleTrace(&tracer); +// AddSimpleTrace(&tracer); +// ValidateChannelTrace(&tracer, 5, GetParam()); +// ValidateChannelTrace(conn1->trace(), 1, GetParam()); +// ChannelFixture channel3(GetParam()); +// RefCountedPtr sc2 = +// MakeRefCounted(channel3.channel(), GetParam(), true); +// tracer.AddTraceEventReferencingChannel( +// ChannelTrace::Severity::Info, +// grpc_slice_from_static_string("subchannel two created"), sc2); +// // this trace should not get added to the parents children since it is +// already +// // present in the tracer. +// tracer.AddTraceEventReferencingChannel( +// ChannelTrace::Severity::Warning, +// grpc_slice_from_static_string("subchannel one inactive"), sc1); +// AddSimpleTrace(&tracer); +// ValidateChannelTrace(&tracer, 8, GetParam()); +// sc1.reset(nullptr); +// sc2.reset(nullptr); +// conn1.reset(nullptr); +// } INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest, ::testing::Values(0, 1, 2, 6, 10, 15)); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index ec1c9f6faf..9f3756c182 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -158,7 +158,7 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { ValidateCounters(json_str, args); gpr_free(json_str); // also check that the core API formats this the correct way - char* core_api_json_str = grpc_channelz_get_channel(channel->channel_uuid()); + char* core_api_json_str = grpc_channelz_get_channel(channel->uuid()); grpc::testing::ValidateGetChannelResponseProtoJsonTranslation( core_api_json_str); gpr_free(core_api_json_str); -- cgit v1.2.3 From 1dc063c093745279452877861da2bacfcaaea95f Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 23 Jul 2018 19:05:27 -0700 Subject: Refactor ChannelTrace to compile --- src/core/lib/channel/channel_trace.cc | 63 +++++++++++++++++++++++------------ src/core/lib/channel/channel_trace.h | 20 +++++++---- src/core/lib/gprpp/ref_counted.h | 3 +- 3 files changed, 56 insertions(+), 30 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index ba2b3bcad6..7d8bb391f8 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -41,14 +41,25 @@ namespace grpc_core { namespace channelz { -ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced_entity) +ChannelTrace::TraceEvent::TraceEvent( + Severity severity, grpc_slice data, + RefCountedPtr referenced_channel) : severity_(severity), data_(data), timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), GPR_CLOCK_REALTIME)), next_(nullptr), - referenced_entity_(std::move(referenced_entity)) {} + referenced_channel_(std::move(referenced_channel)) {} + +// ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, +// RefCountedPtr +// referenced_subchannel) +// : severity_(severity), +// data_(data), +// timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), +// GPR_CLOCK_REALTIME)), +// next_(nullptr), +// referenced_subchannel_(std::move(referenced_subchannel)) {} ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data) : severity_(severity), @@ -110,13 +121,22 @@ void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice data) { void ChannelTrace::AddTraceEventReferencingChannel( Severity severity, grpc_slice data, - RefCountedPtr referenced_entity) { + RefCountedPtr referenced_channel) { if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 // create and fill up the new event AddTraceEventHelper( - New(severity, data, std::move(referenced_entity))); + New(severity, data, std::move(referenced_channel))); } +// void ChannelTrace::AddTraceEventReferencingSubchannel( +// Severity severity, grpc_slice data, +// RefCountedPtr referenced_subchannel) { +// if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 +// // create and fill up the new event +// AddTraceEventHelper( +// New(severity, data, std::move(referenced_subchannel))); +// } + namespace { const char* severity_string(ChannelTrace::Severity severity) { @@ -145,27 +165,26 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { json_iterator = grpc_json_create_child(json_iterator, json, "timestamp", gpr_format_timespec(timestamp_), GRPC_JSON_STRING, true); - if (referenced_entity_ != nullptr) { - GPR_ASSERT( - referenced_entity_->type() == BaseNode::EntityType::kSubchannel || - referenced_entity_->type() == BaseNode::EntityType::kTopLevelChannel || - referenced_entity_->type() == BaseNode::EntityType::kInternalChannel); + if (referenced_channel_ != nullptr) { char* uuid_str; - gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_entity_->uuid()); + gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->uuid()); grpc_json* child_ref = grpc_json_create_child( - json_iterator, json, - (referenced_entity_->type() == BaseNode::EntityType::kSubchannel) - ? "subchannelRef" - : "channelRef", - nullptr, GRPC_JSON_OBJECT, false); - json_iterator = grpc_json_create_child( - nullptr, child_ref, - (referenced_entity_->type() == BaseNode::EntityType::kSubchannel) - ? "subchannelId" - : "channelId", - uuid_str, GRPC_JSON_STRING, true); + json_iterator, json, "channelRef", nullptr, GRPC_JSON_OBJECT, false); + json_iterator = grpc_json_create_child(nullptr, child_ref, "channelId", + uuid_str, GRPC_JSON_STRING, true); json_iterator = child_ref; } + // else { + // char* uuid_str; + // gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_subchannel_->uuid()); + // grpc_json* child_ref = grpc_json_create_child( + // json_iterator, json, "subchannelRef", + // nullptr, GRPC_JSON_OBJECT, false); + // json_iterator = grpc_json_create_child( + // nullptr, child_ref, "subchannelId", + // uuid_str, GRPC_JSON_STRING, true); + // json_iterator = child_ref; + // } } grpc_json* ChannelTrace::RenderJson() const { diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h index cef8814d5f..543eabf13a 100644 --- a/src/core/lib/channel/channel_trace.h +++ b/src/core/lib/channel/channel_trace.h @@ -30,7 +30,8 @@ namespace grpc_core { namespace channelz { -class BaseNode; +class ChannelNode; +class SubchannelNode; // Object used to hold live data for a channel. This data is exposed via the // channelz service: @@ -64,10 +65,10 @@ class ChannelTrace { // slice. void AddTraceEventReferencingChannel( Severity severity, grpc_slice data, - RefCountedPtr referenced_entity); - // void AddTraceEventWithReference( + RefCountedPtr referenced_channel); + // void AddTraceEventReferencingSubchannel( // Severity severity, grpc_slice data, - // RefCountedPtr referenced_entity); + // RefCountedPtr referenced_subchannel); // Creates and returns the raw grpc_json object, so a parent channelz // object may incorporate the json before rendering. @@ -78,9 +79,13 @@ class ChannelTrace { // a trace event. class TraceEvent { public: - // Constructor for a TraceEvent that references a different channel. + // Constructor for a TraceEvent that references a channel. TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced); + RefCountedPtr referenced_channel); + + // Constructor for a TraceEvent that references a subchannel. + TraceEvent(Severity severity, grpc_slice data, + RefCountedPtr referenced_subchannel); // Constructor for a TraceEvent that does not reverence a different // channel. @@ -102,7 +107,8 @@ class ChannelTrace { gpr_timespec timestamp_; TraceEvent* next_; // the tracer object for the (sub)channel that this trace event refers to. - RefCountedPtr referenced_entity_; + RefCountedPtr referenced_channel_; + // RefCountedPtr referenced_subchannel_; }; // TraceEvent // Internal helper to add and link in a trace event diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h index ddac5bd475..3d6a32ddcf 100644 --- a/src/core/lib/gprpp/ref_counted.h +++ b/src/core/lib/gprpp/ref_counted.h @@ -73,7 +73,8 @@ class RefCounted { private: // Allow RefCountedPtr<> to access IncrementRefCount(). - friend class RefCountedPtr; + template + friend class RefCountedPtr; void IncrementRefCount() { gpr_ref(&refs_); } -- cgit v1.2.3 From a8d5c21b8864202e205fc210e369dc72abe606f2 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 24 Jul 2018 09:41:07 -0700 Subject: reviewer feedback --- .../client_channel/client_channel_channelz.h | 14 ++++--------- src/core/lib/channel/channelz.cc | 5 ++--- src/core/lib/channel/channelz.h | 24 +++++----------------- 3 files changed, 11 insertions(+), 32 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 45df756b91..1bc555448c 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -45,20 +45,17 @@ class ClientChannelNode : public ChannelNode { grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); + ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); + virtual ~ClientChannelNode() {} + grpc_json* RenderJson() override; // Helper to create a channel arg to ensure this type of ChannelNode is // created. static grpc_arg CreateChannelArg(); - protected: - ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, - bool is_top_level_channel); - virtual ~ClientChannelNode() {} - private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW grpc_channel_element* client_channel_; // helpers @@ -80,9 +77,6 @@ class SubchannelNode : public CallCountingAndTracingNode { grpc_json* RenderJson() override; private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - intptr_t subchannel_uuid_; grpc_subchannel* subchannel_; UniquePtr target_; diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index eec2cd61b2..4fbc441c0a 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -41,9 +41,8 @@ namespace grpc_core { namespace channelz { -BaseNode::BaseNode(EntityType type) : type_(type) { - uuid_ = ChannelzRegistry::Register(this); -} +BaseNode::BaseNode(EntityType type) + : type_(type), uuid_(ChannelzRegistry::Register(this)) {} BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 67cd1fec2d..5496163fb9 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -74,11 +74,9 @@ class BaseNode : public RefCounted { intptr_t uuid() const { return uuid_; } private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW friend class ChannelTrace; EntityType type_; - intptr_t uuid_; + const intptr_t uuid_; }; // This class is the parent for the channelz entities that deal with Channels @@ -109,9 +107,6 @@ class CallCountingAndTracingNode : public BaseNode { void PopulateCallData(grpc_json* json); private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - // testing peer friend. friend class testing::CallCountingAndTracingNodePeer; @@ -129,6 +124,10 @@ class ChannelNode : public CallCountingAndTracingNode { grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); + ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); + ~ChannelNode() override; + grpc_json* RenderJson() override; void MarkChannelDestroyed() { @@ -139,19 +138,12 @@ class ChannelNode : public CallCountingAndTracingNode { bool ChannelIsDestroyed() { return channel_ == nullptr; } protected: - ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, - bool is_top_level_channel); - ~ChannelNode() override; // provides view of target for child. char* target_view() { return target_.get(); } private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - grpc_channel* channel_ = nullptr; UniquePtr target_; - intptr_t channel_uuid_; }; // Handles channelz bookkeeping for servers @@ -162,10 +154,6 @@ class ServerNode : public CallCountingAndTracingNode { : CallCountingAndTracingNode(EntityType::kServer, channel_tracer_max_nodes) {} ~ServerNode() override {} - - private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW }; // Handles channelz bookkeeping for sockets @@ -176,8 +164,6 @@ class SocketNode : public BaseNode { ~SocketNode() override {} private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW }; // Creation functions -- cgit v1.2.3 From bfdfe9fefbc92f78da6247a85e7e7de4b30727b9 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 24 Jul 2018 10:13:52 -0700 Subject: Restructure heirarchy --- .../ext/filters/client_channel/client_channel.cc | 1 - .../client_channel/client_channel_channelz.cc | 16 +-- .../client_channel/client_channel_channelz.h | 7 +- src/core/ext/filters/client_channel/subchannel.cc | 9 +- src/core/lib/channel/channel_stack.h | 1 - src/core/lib/channel/channelz.cc | 16 ++- src/core/lib/channel/channelz.h | 21 ++-- src/core/lib/surface/call.cc | 27 +---- src/core/lib/surface/call.h | 13 --- src/core/lib/surface/channel.cc | 4 +- test/core/channel/channel_stack_test.cc | 1 - test/core/channel/channel_trace_test.cc | 112 ++++++++++----------- test/core/channel/channelz_test.cc | 38 +++---- 13 files changed, 116 insertions(+), 150 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 13a0b95511..683cb0e01d 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -3094,7 +3094,6 @@ static grpc_error* cc_init_call_elem(grpc_call_element* elem, calld->arena = args->arena; calld->owning_call = args->call_stack; calld->call_combiner = args->call_combiner; - calld->call = args->call; if (GPR_LIKELY(chand->deadline_checking_enabled)) { grpc_deadline_state_init(elem, args->call_stack, args->call_combiner, calld->deadline); diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 996a871f38..b209acc2ea 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -124,8 +124,8 @@ grpc_json* ClientChannelNode::RenderJson() { grpc_json_create_child(nullptr, json, "target", target_view(), GRPC_JSON_STRING, false); // as CallCountingAndTracingNode to populate trace and call count data. - PopulateTrace(json); - PopulateCallData(json); + counter_and_tracer()->PopulateTrace(json); + counter_and_tracer()->PopulateCallData(json); // reset to the top level json = top_level_json; PopulateChildRefs(json); @@ -148,11 +148,11 @@ RefCountedPtr ClientChannelNode::MakeClientChannelNode( SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes) - : CallCountingAndTracingNode(EntityType::kSubchannel, - channel_tracer_max_nodes), + : BaseNode(EntityType::kSubchannel), subchannel_(subchannel), - target_(UniquePtr( - gpr_strdup(grpc_subchannel_get_target(subchannel_)))) {} + target_( + UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_)))), + counter_and_tracer_(channel_tracer_max_nodes) {} SubchannelNode::~SubchannelNode() {} @@ -192,8 +192,8 @@ grpc_json* SubchannelNode::RenderJson() { GPR_ASSERT(target_.get() != nullptr); grpc_json_create_child(nullptr, json, "target", target_.get(), GRPC_JSON_STRING, false); - PopulateTrace(json); - PopulateCallData(json); + counter_and_tracer_.PopulateTrace(json); + counter_and_tracer_.PopulateCallData(json); return top_level_json; } diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 1bc555448c..f5344c049e 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -64,7 +64,7 @@ class ClientChannelNode : public ChannelNode { }; // Handles channelz bookkeeping for sockets -class SubchannelNode : public CallCountingAndTracingNode { +class SubchannelNode : public BaseNode { public: SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes); ~SubchannelNode() override; @@ -76,9 +76,14 @@ class SubchannelNode : public CallCountingAndTracingNode { grpc_json* RenderJson() override; + CallCountingAndTracingNode* counter_and_tracer() { + return &counter_and_tracer_; + } + private: grpc_subchannel* subchannel_; UniquePtr target_; + CallCountingAndTracingNode counter_and_tracer_; void PopulateConnectivityState(grpc_json* json); }; diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index a15cfd43c3..5894d52e6b 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -183,7 +183,7 @@ static void connection_destroy(void* arg, grpc_error* error) { static void subchannel_destroy(void* arg, grpc_error* error) { grpc_subchannel* c = static_cast(arg); if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel->trace()->AddTraceEvent( + c->channelz_subchannel->counter_and_tracer()->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel destroyed")); c->channelz_subchannel->MarkSubchannelDestroyed(); @@ -397,7 +397,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, c->channelz_subchannel = grpc_core::MakeRefCounted( c, channel_tracer_max_nodes); - c->channelz_subchannel->trace()->AddTraceEvent( + c->channelz_subchannel->counter_and_tracer()->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel created")); } @@ -857,7 +857,6 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, args.deadline, /* deadline */ args.arena, /* arena */ args.call_combiner, /* call_combiner */ - args.call /* call */ }; grpc_error* error = grpc_call_stack_init( channel_stack_, 1, subchannel_call_destroy, *call, &call_args); @@ -866,10 +865,6 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, gpr_log(GPR_ERROR, "error: %s", error_string); return error; } - if (channelz_subchannel_ != nullptr) { - channelz_subchannel_->RecordCallStarted(); - grpc_call_set_channelz_subchannel(args.call, channelz_subchannel_); - } grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); return GRPC_ERROR_NONE; } diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index 727f36a6f8..7581f937b6 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -71,7 +71,6 @@ typedef struct { grpc_millis deadline; gpr_arena* arena; grpc_call_combiner* call_combiner; - grpc_call* call; } grpc_call_element_args; typedef struct { diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 4fbc441c0a..ee1717ce9f 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -54,8 +54,7 @@ char* BaseNode::RenderJsonString() { } CallCountingAndTracingNode::CallCountingAndTracingNode( - EntityType type, size_t channel_tracer_max_nodes) - : BaseNode(type) { + size_t channel_tracer_max_nodes) { trace_.Init(channel_tracer_max_nodes); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); @@ -103,12 +102,11 @@ void CallCountingAndTracingNode::PopulateCallData(grpc_json* json) { ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel) - : CallCountingAndTracingNode(is_top_level_channel - ? EntityType::kTopLevelChannel - : EntityType::kInternalChannel, - channel_tracer_max_nodes), + : BaseNode(is_top_level_channel ? EntityType::kTopLevelChannel + : EntityType::kInternalChannel), channel_(channel), - target_(UniquePtr(grpc_channel_get_target(channel_))) {} + target_(UniquePtr(grpc_channel_get_target(channel_))), + counter_and_tracer_(channel_tracer_max_nodes) {} ChannelNode::~ChannelNode() {} @@ -137,8 +135,8 @@ grpc_json* ChannelNode::RenderJson() { grpc_json_create_child(nullptr, json, "target", target_.get(), GRPC_JSON_STRING, false); // as CallCountingAndTracingNode to populate trace and call count data. - PopulateTrace(json); - PopulateCallData(json); + counter_and_tracer_.PopulateTrace(json); + counter_and_tracer_.PopulateCallData(json); return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 5496163fb9..7bc4567ad2 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -86,10 +86,10 @@ class BaseNode : public RefCounted { // - track last_call_started_timestamp // - hold the channel trace. // - perform common rendering. -class CallCountingAndTracingNode : public BaseNode { +class CallCountingAndTracingNode { public: - CallCountingAndTracingNode(EntityType type, size_t channel_tracer_max_nodes); - ~CallCountingAndTracingNode() override; + CallCountingAndTracingNode(size_t channel_tracer_max_nodes); + ~CallCountingAndTracingNode(); void RecordCallStarted(); void RecordCallFailed() { @@ -118,7 +118,7 @@ class CallCountingAndTracingNode : public BaseNode { }; // Handles channelz bookkeeping for channels -class ChannelNode : public CallCountingAndTracingNode { +class ChannelNode : public BaseNode { public: static RefCountedPtr MakeChannelNode( grpc_channel* channel, size_t channel_tracer_max_nodes, @@ -137,6 +137,10 @@ class ChannelNode : public CallCountingAndTracingNode { bool ChannelIsDestroyed() { return channel_ == nullptr; } + CallCountingAndTracingNode* counter_and_tracer() { + return &counter_and_tracer_; + } + protected: // provides view of target for child. char* target_view() { return target_.get(); } @@ -144,15 +148,14 @@ class ChannelNode : public CallCountingAndTracingNode { private: grpc_channel* channel_ = nullptr; UniquePtr target_; + CallCountingAndTracingNode counter_and_tracer_; }; // Handles channelz bookkeeping for servers // TODO(ncteisen): implement in subsequent PR. -class ServerNode : public CallCountingAndTracingNode { +class ServerNode : public BaseNode { public: - ServerNode(size_t channel_tracer_max_nodes) - : CallCountingAndTracingNode(EntityType::kServer, - channel_tracer_max_nodes) {} + ServerNode(size_t channel_tracer_max_nodes) : BaseNode(EntityType::kServer) {} ~ServerNode() override {} }; @@ -162,8 +165,6 @@ class SocketNode : public BaseNode { public: SocketNode() : BaseNode(EntityType::kSocket) {} ~SocketNode() override {} - - private: }; // Creation functions diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 6545af8f72..b86ff048cf 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -170,11 +170,6 @@ struct grpc_call { /* parent_call* */ gpr_atm parent_call_atm; child_call* child; - // the call holds onto this so that once the call knows if the RPC was - // a success or failure, it can update the channelz bookkeeping for the - // subchannel that sent it. - grpc_core::channelz::CallCountingAndTracingNode* channelz_subchannel_; - /* client or server call */ bool is_client; /** has grpc_call_unref been called */ @@ -274,11 +269,6 @@ struct grpc_call { gpr_atm recv_state; }; -void grpc_call_set_channelz_subchannel( - grpc_call* call, grpc_core::channelz::CallCountingAndTracingNode* node) { - call->channelz_subchannel_ = node; -} - grpc_core::TraceFlag grpc_call_error_trace(false, "call_error"); grpc_core::TraceFlag grpc_compression_trace(false, "compression"); @@ -454,8 +444,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, call->start_time, send_deadline, call->arena, - &call->call_combiner, - call}; + &call->call_combiner}; add_init_error(&error, grpc_call_stack_init(channel_stack, 1, destroy_call, call, &call_args)); // Publish this call to parent only after the call stack has been initialized. @@ -500,7 +489,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { - channelz_channel->RecordCallStarted(); + channelz_channel->counter_and_tracer()->RecordCallStarted(); } grpc_slice_unref_internal(path); @@ -1279,17 +1268,9 @@ static void post_batch_completion(batch_control* bctl) { grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { if (*call->final_op.client.status != GRPC_STATUS_OK) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); - } - } - // Record channelz data for the subchannel. - if (call->channelz_subchannel_ != nullptr) { - if (*call->final_op.client.status != GRPC_STATUS_OK) { - call->channelz_subchannel_->RecordCallFailed(); + channelz_channel->counter_and_tracer()->RecordCallFailed(); } else { - call->channelz_subchannel_->RecordCallSucceeded(); + channelz_channel->counter_and_tracer()->RecordCallSucceeded(); } } GRPC_ERROR_UNREF(error); diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index 200c840c61..b3b06059d4 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -110,19 +110,6 @@ size_t grpc_call_get_initial_size_estimate(); grpc_compression_algorithm grpc_call_compression_for_level( grpc_call* call, grpc_compression_level level); -namespace grpc_core { -namespace channelz { -class CallCountingAndTracingNode; -} // namespace channelz -} // namespace grpc_core - -// We need this so that a subchannel selected for a call can add itself to -// the call's data structure. This allows the call to trigger the correct -// channelz bookkeeping on the subchannel once the call knows if the RPC was -// successful or not. -void grpc_call_set_channelz_subchannel( - grpc_call* call, grpc_core::channelz::CallCountingAndTracingNode* node); - extern grpc_core::TraceFlag grpc_call_error_trace; extern grpc_core::TraceFlag grpc_compression_trace; diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 01caadaaba..16d3322a9d 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -170,7 +170,7 @@ grpc_channel* grpc_channel_create_with_builder( bool is_top_level_channel = channel->is_client && !internal_channel; channel->channelz_channel = channel_node_create_func( channel, channel_tracer_max_nodes, is_top_level_channel); - channel->channelz_channel->trace()->AddTraceEvent( + channel->channelz_channel->counter_and_tracer()->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); } @@ -417,7 +417,7 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) { static void destroy_channel(void* arg, grpc_error* error) { grpc_channel* channel = static_cast(arg); if (channel->channelz_channel != nullptr) { - channel->channelz_channel->trace()->AddTraceEvent( + channel->channelz_channel->counter_and_tracer()->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel destroyed")); channel->channelz_channel->MarkChannelDestroyed(); diff --git a/test/core/channel/channel_stack_test.cc b/test/core/channel/channel_stack_test.cc index 4dc2ee3f55..6f0bfa06d2 100644 --- a/test/core/channel/channel_stack_test.cc +++ b/test/core/channel/channel_stack_test.cc @@ -125,7 +125,6 @@ static void test_create_channel_stack(void) { GRPC_MILLIS_INF_FUTURE, /* deadline */ nullptr, /* arena */ nullptr, /* call_combiner */ - nullptr /* call */ }; grpc_error* error = grpc_call_stack_init(channel_stack, 1, free_call, call_stack, &args); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 703a9e457f..3d6aff03eb 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -160,14 +160,14 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - ValidateChannelTrace(sc1->trace(), 3, GetParam()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - ValidateChannelTrace(sc1->trace(), 6, GetParam()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + ValidateChannelTrace(sc1->counter_and_tracer()->trace(), 3, GetParam()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + ValidateChannelTrace(sc1->counter_and_tracer()->trace(), 6, GetParam()); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 5, GetParam()); @@ -191,55 +191,53 @@ TEST_P(ChannelTracerTest, ComplexTest) { sc2.reset(nullptr); } -// // Test a case in which the parent channel has subchannels and the -// subchannels -// // have connections. Ensures that everything lives as long as it should then -// // gets deleted. -// TEST_P(ChannelTracerTest, TestNesting) { -// grpc_core::ExecCtx exec_ctx; -// ChannelTrace tracer(GetParam()); -// AddSimpleTrace(&tracer); -// AddSimpleTrace(&tracer); -// ValidateChannelTrace(&tracer, 2, GetParam()); -// ChannelFixture channel1(GetParam()); -// RefCountedPtr sc1 = -// MakeRefCounted(channel1.channel(), GetParam(), true); -// tracer.AddTraceEventReferencingChannel( -// ChannelTrace::Severity::Info, -// grpc_slice_from_static_string("subchannel one created"), sc1); -// ValidateChannelTrace(&tracer, 3, GetParam()); -// AddSimpleTrace(sc1->trace()); -// ChannelFixture channel2(GetParam()); -// RefCountedPtr conn1 = -// MakeRefCounted(channel2.channel(), GetParam(), true); -// // nesting one level deeper. -// sc1->trace()->AddTraceEventReferencingChannel( -// ChannelTrace::Severity::Info, -// grpc_slice_from_static_string("connection one created"), conn1); -// ValidateChannelTrace(&tracer, 3, GetParam()); -// AddSimpleTrace(conn1->trace()); -// AddSimpleTrace(&tracer); -// AddSimpleTrace(&tracer); -// ValidateChannelTrace(&tracer, 5, GetParam()); -// ValidateChannelTrace(conn1->trace(), 1, GetParam()); -// ChannelFixture channel3(GetParam()); -// RefCountedPtr sc2 = -// MakeRefCounted(channel3.channel(), GetParam(), true); -// tracer.AddTraceEventReferencingChannel( -// ChannelTrace::Severity::Info, -// grpc_slice_from_static_string("subchannel two created"), sc2); -// // this trace should not get added to the parents children since it is -// already -// // present in the tracer. -// tracer.AddTraceEventReferencingChannel( -// ChannelTrace::Severity::Warning, -// grpc_slice_from_static_string("subchannel one inactive"), sc1); -// AddSimpleTrace(&tracer); -// ValidateChannelTrace(&tracer, 8, GetParam()); -// sc1.reset(nullptr); -// sc2.reset(nullptr); -// conn1.reset(nullptr); -// } +// Test a case in which the parent channel has subchannels and the subchannels +// have connections. Ensures that everything lives as long as it should then +// gets deleted. +TEST_P(ChannelTracerTest, TestNesting) { + grpc_core::ExecCtx exec_ctx; + ChannelTrace tracer(GetParam()); + AddSimpleTrace(&tracer); + AddSimpleTrace(&tracer); + ValidateChannelTrace(&tracer, 2, GetParam()); + ChannelFixture channel1(GetParam()); + RefCountedPtr sc1 = + MakeRefCounted(channel1.channel(), GetParam(), true); + tracer.AddTraceEventReferencingChannel( + ChannelTrace::Severity::Info, + grpc_slice_from_static_string("subchannel one created"), sc1); + ValidateChannelTrace(&tracer, 3, GetParam()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + ChannelFixture channel2(GetParam()); + RefCountedPtr conn1 = + MakeRefCounted(channel2.channel(), GetParam(), true); + // nesting one level deeper. + sc1->counter_and_tracer()->trace()->AddTraceEventReferencingChannel( + ChannelTrace::Severity::Info, + grpc_slice_from_static_string("connection one created"), conn1); + ValidateChannelTrace(&tracer, 3, GetParam()); + AddSimpleTrace(conn1->counter_and_tracer()->trace()); + AddSimpleTrace(&tracer); + AddSimpleTrace(&tracer); + ValidateChannelTrace(&tracer, 5, GetParam()); + ValidateChannelTrace(conn1->counter_and_tracer()->trace(), 1, GetParam()); + ChannelFixture channel3(GetParam()); + RefCountedPtr sc2 = + MakeRefCounted(channel3.channel(), GetParam(), true); + tracer.AddTraceEventReferencingChannel( + ChannelTrace::Severity::Info, + grpc_slice_from_static_string("subchannel two created"), sc2); + // this trace should not get added to the parents children since it is already + // present in the tracer. + tracer.AddTraceEventReferencingChannel( + ChannelTrace::Severity::Warning, + grpc_slice_from_static_string("subchannel one inactive"), sc1); + AddSimpleTrace(&tracer); + ValidateChannelTrace(&tracer, 8, GetParam()); + sc1.reset(nullptr); + sc2.reset(nullptr); + conn1.reset(nullptr); +} INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest, ::testing::Values(0, 1, 2, 6, 10, 15)); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 9f3756c182..5e9a3f89a2 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -201,16 +201,16 @@ TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) { ChannelFixture channel(GetParam()); ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel.channel()); - channelz_channel->RecordCallStarted(); - channelz_channel->RecordCallFailed(); - channelz_channel->RecordCallSucceeded(); + channelz_channel->counter_and_tracer()->RecordCallStarted(); + channelz_channel->counter_and_tracer()->RecordCallFailed(); + channelz_channel->counter_and_tracer()->RecordCallSucceeded(); ValidateChannel(channelz_channel, {1, 1, 1}); - channelz_channel->RecordCallStarted(); - channelz_channel->RecordCallFailed(); - channelz_channel->RecordCallSucceeded(); - channelz_channel->RecordCallStarted(); - channelz_channel->RecordCallFailed(); - channelz_channel->RecordCallSucceeded(); + channelz_channel->counter_and_tracer()->RecordCallStarted(); + channelz_channel->counter_and_tracer()->RecordCallFailed(); + channelz_channel->counter_and_tracer()->RecordCallSucceeded(); + channelz_channel->counter_and_tracer()->RecordCallStarted(); + channelz_channel->counter_and_tracer()->RecordCallFailed(); + channelz_channel->counter_and_tracer()->RecordCallSucceeded(); ValidateChannel(channelz_channel, {3, 3, 3}); } @@ -220,23 +220,27 @@ TEST_P(ChannelzChannelTest, LastCallStartedMillis) { ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel.channel()); // start a call to set the last call started timestamp - channelz_channel->RecordCallStarted(); - grpc_millis millis1 = GetLastCallStartedMillis(channelz_channel); + channelz_channel->counter_and_tracer()->RecordCallStarted(); + grpc_millis millis1 = + GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); // time gone by should not affect the timestamp ChannelzSleep(100); - grpc_millis millis2 = GetLastCallStartedMillis(channelz_channel); + grpc_millis millis2 = + GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); EXPECT_EQ(millis1, millis2); // calls succeeded or failed should not affect the timestamp ChannelzSleep(100); - channelz_channel->RecordCallFailed(); - channelz_channel->RecordCallSucceeded(); - grpc_millis millis3 = GetLastCallStartedMillis(channelz_channel); + channelz_channel->counter_and_tracer()->RecordCallFailed(); + channelz_channel->counter_and_tracer()->RecordCallSucceeded(); + grpc_millis millis3 = + GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); EXPECT_EQ(millis1, millis3); // another call started should affect the timestamp // sleep for extra long to avoid flakes (since we cache Now()) ChannelzSleep(5000); - channelz_channel->RecordCallStarted(); - grpc_millis millis4 = GetLastCallStartedMillis(channelz_channel); + channelz_channel->counter_and_tracer()->RecordCallStarted(); + grpc_millis millis4 = + GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); EXPECT_NE(millis1, millis4); } -- cgit v1.2.3 From 37f7b5399dcf5b29e41ac1c0ff2a1c81c9933a93 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 24 Jul 2018 10:18:54 -0700 Subject: reviewer feedback --- src/core/lib/channel/channelz_registry.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 7f70908989..d2c403cc1b 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -123,7 +123,6 @@ char* grpc_channelz_get_channel(intptr_t channel_id) { grpc_core::channelz::BaseNode* channel_node = grpc_core::channelz::ChannelzRegistry::Get(channel_id); if (channel_node == nullptr || - (channel_node->type() != grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel && channel_node->type() != -- cgit v1.2.3 From a4e3bed5fb8f9203fa580f00a5cb1136415c1949 Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Tue, 24 Jul 2018 12:11:33 -0700 Subject: changes --- src/core/lib/surface/call.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index d9feb10850..c92172f278 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -532,7 +532,7 @@ static void destroy_call(void* call, grpc_error* error) { grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(c->status_error, c->send_deadline, &c->final_info.final_status, &slice, nullptr, - c->final_info.error_string); + &c->final_info.error_string); grpc_error* cancel_error = (grpc_error*)gpr_atm_no_barrier_load(&c->cancel_error); GRPC_ERROR_UNREF(cancel_error); @@ -1445,10 +1445,10 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready"); grpc_metadata_batch* md = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; recv_trailing_filter(call, md, GRPC_ERROR_REF(error)); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready"); finish_batch_step(bctl); } -- cgit v1.2.3 From 65007f624e3a7be460dda7c979ae939c89519cad Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Tue, 24 Jul 2018 14:50:16 -0700 Subject: Channelz fixes --- src/core/lib/surface/call.cc | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index c92172f278..f5abf1a1a6 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -509,26 +509,6 @@ static void destroy_call(void* call, grpc_error* error) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(c->channel); - if (c->is_client) { - if (channelz_channel != nullptr) { - if (*c->final_op.client.status != GRPC_STATUS_OK) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); - } - } - } else { - if (channelz_channel != nullptr) { - if (*c->final_op.server.cancelled || c->status_error != GRPC_ERROR_NONE) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); - } - } - } - grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(c->status_error, c->send_deadline, &c->final_info.final_status, &slice, nullptr, @@ -734,6 +714,15 @@ static void set_final_status(grpc_call* call, grpc_error* error) { error_string); *call->final_op.client.status = code; *call->final_op.client.status_details = grpc_slice_ref_internal(slice); + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); + if (channelz_channel != nullptr) { + if (code != GRPC_STATUS_OK) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } } else { *call->final_op.server.cancelled = error != GRPC_ERROR_NONE || call->status_error != GRPC_ERROR_NONE; @@ -1683,6 +1672,15 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, static_cast( op->data.send_status_from_server.status)); call->status_error = status_error; + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); + if (channelz_channel != nullptr) { + if (call->status_error != GRPC_ERROR_NONE) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } if (!prepare_application_metadata( call, static_cast( -- cgit v1.2.3 From 961fe4b523d8d097f32d6bb1df12ec8e0dcdaa4a Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Wed, 25 Jul 2018 10:49:48 -0700 Subject: Revert "Channelz fixes" This reverts commit 65007f624e3a7be460dda7c979ae939c89519cad. --- src/core/lib/surface/call.cc | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index f5abf1a1a6..c92172f278 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -509,6 +509,26 @@ static void destroy_call(void* call, grpc_error* error) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(c->channel); + if (c->is_client) { + if (channelz_channel != nullptr) { + if (*c->final_op.client.status != GRPC_STATUS_OK) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } + } else { + if (channelz_channel != nullptr) { + if (*c->final_op.server.cancelled || c->status_error != GRPC_ERROR_NONE) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } + } + grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(c->status_error, c->send_deadline, &c->final_info.final_status, &slice, nullptr, @@ -714,15 +734,6 @@ static void set_final_status(grpc_call* call, grpc_error* error) { error_string); *call->final_op.client.status = code; *call->final_op.client.status_details = grpc_slice_ref_internal(slice); - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(call->channel); - if (channelz_channel != nullptr) { - if (code != GRPC_STATUS_OK) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); - } - } } else { *call->final_op.server.cancelled = error != GRPC_ERROR_NONE || call->status_error != GRPC_ERROR_NONE; @@ -1672,15 +1683,6 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, static_cast( op->data.send_status_from_server.status)); call->status_error = status_error; - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(call->channel); - if (channelz_channel != nullptr) { - if (call->status_error != GRPC_ERROR_NONE) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); - } - } if (!prepare_application_metadata( call, static_cast( -- cgit v1.2.3 From ac4b2527850f966c8204dab091247b05489ad9d2 Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Wed, 25 Jul 2018 10:50:01 -0700 Subject: Revert "changes" This reverts commit a4e3bed5fb8f9203fa580f00a5cb1136415c1949. --- src/core/lib/surface/call.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index c92172f278..d9feb10850 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -532,7 +532,7 @@ static void destroy_call(void* call, grpc_error* error) { grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(c->status_error, c->send_deadline, &c->final_info.final_status, &slice, nullptr, - &c->final_info.error_string); + c->final_info.error_string); grpc_error* cancel_error = (grpc_error*)gpr_atm_no_barrier_load(&c->cancel_error); GRPC_ERROR_UNREF(cancel_error); @@ -1445,10 +1445,10 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready"); grpc_metadata_batch* md = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; recv_trailing_filter(call, md, GRPC_ERROR_REF(error)); - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready"); finish_batch_step(bctl); } -- cgit v1.2.3 From fa52bee77b34542566b40c8f368a90d2f12d8231 Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Wed, 25 Jul 2018 10:50:42 -0700 Subject: Revert "compile error fix" This reverts commit 5defb7354b620a67ef42cb2ad73bab7bdd512fa6. --- src/core/lib/surface/call.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index d9feb10850..ffba385605 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -301,7 +301,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, gpr_arena_alloc(arena, GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) + channel_stack->call_stack_size)); gpr_ref_init(&call->ext_ref, 1); - gpr_atm_no_barrier_store(&call->cancel_error, (gpr_atm)GRPC_ERROR_NONE); + gpr_atm_no_barrier_store(&call->cancel_error, GRPC_ERROR_NONE); call->arena = arena; grpc_call_combiner_init(&call->call_combiner); *out_call = call; -- cgit v1.2.3 From 1987e391bcdd572003fe9b6e1e27671203adebab Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Wed, 25 Jul 2018 10:50:59 -0700 Subject: Revert "Make error strings consistent" This reverts commit a135059ce7d2db3180045810f66dd69a8fc88284. --- src/core/lib/iomgr/error.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc index 93a5c20abb..90ed34da11 100644 --- a/src/core/lib/iomgr/error.cc +++ b/src/core/lib/iomgr/error.cc @@ -399,14 +399,14 @@ static grpc_error* copy_error_and_unref(grpc_error* in) { out = GRPC_ERROR_CREATE_FROM_STATIC_STRING("unknown"); if (in == GRPC_ERROR_NONE) { internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, - grpc_slice_from_static_string("No Error")); + grpc_slice_from_static_string("no error")); internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK); } else if (in == GRPC_ERROR_OOM) { internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, - grpc_slice_from_static_string("Out of memory")); + grpc_slice_from_static_string("oom")); } else if (in == GRPC_ERROR_CANCELLED) { internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION, - grpc_slice_from_static_string("Cancelled")); + grpc_slice_from_static_string("cancelled")); internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED); } } else if (gpr_ref_is_unique(&in->atomics.refs)) { -- cgit v1.2.3 From a7bd899970b01198a4ba66b7f9fa47e658e506aa Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Wed, 25 Jul 2018 10:51:18 -0700 Subject: Revert "Include cancellation error" This reverts commit 299c2c5e115b6a1204d67f3a4ae8de66c5386fe6. --- src/core/lib/surface/call.cc | 62 ++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 42 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index ffba385605..43dd795ce7 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -190,7 +190,7 @@ struct grpc_call { grpc_closure receiving_initial_metadata_ready; grpc_closure receiving_trailing_metadata_ready; uint32_t test_only_last_message_flags; - gpr_atm cancel_error; + gpr_atm cancelled; grpc_closure release_call; @@ -301,7 +301,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, gpr_arena_alloc(arena, GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) + channel_stack->call_stack_size)); gpr_ref_init(&call->ext_ref, 1); - gpr_atm_no_barrier_store(&call->cancel_error, GRPC_ERROR_NONE); + gpr_atm_no_barrier_store(&call->cancelled, 0); call->arena = arena; grpc_call_combiner_init(&call->call_combiner); *out_call = call; @@ -509,33 +509,10 @@ static void destroy_call(void* call, grpc_error* error) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(c->channel); - if (c->is_client) { - if (channelz_channel != nullptr) { - if (*c->final_op.client.status != GRPC_STATUS_OK) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); - } - } - } else { - if (channelz_channel != nullptr) { - if (*c->final_op.server.cancelled || c->status_error != GRPC_ERROR_NONE) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); - } - } - } - grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(c->status_error, c->send_deadline, &c->final_info.final_status, &slice, nullptr, c->final_info.error_string); - grpc_error* cancel_error = - (grpc_error*)gpr_atm_no_barrier_load(&c->cancel_error); - GRPC_ERROR_UNREF(cancel_error); GRPC_ERROR_UNREF(c->status_error); c->final_info.stats.latency = gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time); @@ -668,12 +645,10 @@ static void done_termination(void* arg, grpc_error* error) { } static void cancel_with_error(grpc_call* c, grpc_error* error) { - if (!gpr_atm_rel_cas(&c->cancel_error, (gpr_atm)GRPC_ERROR_NONE, - (gpr_atm)error)) { + if (!gpr_atm_rel_cas(&c->cancelled, 0, 1)) { GRPC_ERROR_UNREF(error); return; } - GRPC_ERROR_REF(error); GRPC_CALL_INTERNAL_REF(c, "termination"); // Inform the call combiner of the cancellation, so that it can cancel // any in-flight asynchronous actions that may be holding the call @@ -707,26 +682,14 @@ static void cancel_with_status(grpc_call* c, grpc_status_code status, cancel_with_error(c, error_from_status(status, description)); } -// The final status of a call is determined when the -// recv_trailing_metadata_ready callback is invoked. The status is determined -// based on the following (in order). -// 1. The first cancellation error that has occured prior to the callback. -// 2. The error passed to the recv_trailing_metadata_ready callback. -// 3. The status from the metadata on the call (grpc-status). static void set_final_status(grpc_call* call, grpc_error* error) { if (grpc_call_error_trace.enabled()) { gpr_log(GPR_DEBUG, "set_final_status %s", call->is_client ? "CLI" : "SVR"); gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); } - grpc_error* cancel_error = - (grpc_error*)gpr_atm_no_barrier_load(&call->cancel_error); - if (cancel_error != GRPC_ERROR_NONE && error == GRPC_ERROR_NONE) { - error = GRPC_ERROR_REF(cancel_error); - } else if (cancel_error != GRPC_ERROR_NONE && cancel_error != error) { - error = grpc_error_add_child(GRPC_ERROR_REF(cancel_error), error); - } + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); if (call->is_client) { - call->status_error = error; const char** error_string = call->final_op.client.error_string; grpc_status_code code; grpc_slice slice = grpc_empty_slice(); @@ -734,9 +697,24 @@ static void set_final_status(grpc_call* call, grpc_error* error) { error_string); *call->final_op.client.status = code; *call->final_op.client.status_details = grpc_slice_ref_internal(slice); + call->status_error = error; + if (channelz_channel != nullptr) { + if (*call->final_op.client.status != GRPC_STATUS_OK) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } } else { *call->final_op.server.cancelled = error != GRPC_ERROR_NONE || call->status_error != GRPC_ERROR_NONE; + if (channelz_channel != nullptr) { + if (*call->final_op.server.cancelled) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } GRPC_ERROR_UNREF(error); } } -- cgit v1.2.3 From aa8043b7c8df2182e57cc561f5477fc3a35c6d95 Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Wed, 25 Jul 2018 10:59:06 -0700 Subject: changes --- src/core/lib/surface/call.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 43dd795ce7..1ee3667a58 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -512,7 +512,7 @@ static void destroy_call(void* call, grpc_error* error) { grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(c->status_error, c->send_deadline, &c->final_info.final_status, &slice, nullptr, - c->final_info.error_string); + &c->final_info.error_string); GRPC_ERROR_UNREF(c->status_error); c->final_info.stats.latency = gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time); -- cgit v1.2.3 From 864e68e96d20c91ead272c17ff36c74422c7de3f Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 27 Jul 2018 02:27:58 -0700 Subject: Fix channel trace polymorphism --- grpc.def | 1 + src/core/lib/channel/channel_trace.cc | 58 +++++++------------------- src/core/lib/channel/channel_trace.h | 20 +++------ src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 + src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 ++ test/core/channel/channel_trace_test.cc | 15 +++---- test/core/surface/public_headers_must_be_c89.c | 1 + 7 files changed, 36 insertions(+), 64 deletions(-) (limited to 'src/core/lib') diff --git a/grpc.def b/grpc.def index 5b98792662..5d699e890a 100644 --- a/grpc.def +++ b/grpc.def @@ -71,6 +71,7 @@ EXPORTS grpc_resource_quota_arg_vtable grpc_channelz_get_top_channels grpc_channelz_get_channel + grpc_channelz_get_subchannel grpc_insecure_channel_create_from_fd grpc_server_add_insecure_channel_from_fd grpc_use_signal diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index 7d8bb391f8..cfb2faba51 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -41,25 +41,14 @@ namespace grpc_core { namespace channelz { -ChannelTrace::TraceEvent::TraceEvent( - Severity severity, grpc_slice data, - RefCountedPtr referenced_channel) +ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, + RefCountedPtr referenced_entity) : severity_(severity), data_(data), timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), GPR_CLOCK_REALTIME)), next_(nullptr), - referenced_channel_(std::move(referenced_channel)) {} - -// ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, -// RefCountedPtr -// referenced_subchannel) -// : severity_(severity), -// data_(data), -// timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), -// GPR_CLOCK_REALTIME)), -// next_(nullptr), -// referenced_subchannel_(std::move(referenced_subchannel)) {} + referenced_entity_(std::move(referenced_entity)) {} ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data) : severity_(severity), @@ -119,24 +108,15 @@ void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice data) { AddTraceEventHelper(New(severity, data)); } -void ChannelTrace::AddTraceEventReferencingChannel( +void ChannelTrace::AddTraceEventWithReference( Severity severity, grpc_slice data, - RefCountedPtr referenced_channel) { + RefCountedPtr referenced_entity) { if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 // create and fill up the new event AddTraceEventHelper( - New(severity, data, std::move(referenced_channel))); + New(severity, data, std::move(referenced_entity))); } -// void ChannelTrace::AddTraceEventReferencingSubchannel( -// Severity severity, grpc_slice data, -// RefCountedPtr referenced_subchannel) { -// if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 -// // create and fill up the new event -// AddTraceEventHelper( -// New(severity, data, std::move(referenced_subchannel))); -// } - namespace { const char* severity_string(ChannelTrace::Severity severity) { @@ -165,26 +145,20 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { json_iterator = grpc_json_create_child(json_iterator, json, "timestamp", gpr_format_timespec(timestamp_), GRPC_JSON_STRING, true); - if (referenced_channel_ != nullptr) { + if (referenced_entity_ != nullptr) { + const bool is_channel = + (referenced_entity_->type() == BaseNode::EntityType::kTopLevelChannel || + referenced_entity_->type() == BaseNode::EntityType::kInternalChannel); char* uuid_str; - gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->uuid()); + gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_entity_->uuid()); grpc_json* child_ref = grpc_json_create_child( - json_iterator, json, "channelRef", nullptr, GRPC_JSON_OBJECT, false); - json_iterator = grpc_json_create_child(nullptr, child_ref, "channelId", - uuid_str, GRPC_JSON_STRING, true); + json_iterator, json, is_channel ? "channelRef" : "subchannelRef", + nullptr, GRPC_JSON_OBJECT, false); + json_iterator = grpc_json_create_child( + nullptr, child_ref, is_channel ? "channelId" : "subchannelId", uuid_str, + GRPC_JSON_STRING, true); json_iterator = child_ref; } - // else { - // char* uuid_str; - // gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_subchannel_->uuid()); - // grpc_json* child_ref = grpc_json_create_child( - // json_iterator, json, "subchannelRef", - // nullptr, GRPC_JSON_OBJECT, false); - // json_iterator = grpc_json_create_child( - // nullptr, child_ref, "subchannelId", - // uuid_str, GRPC_JSON_STRING, true); - // json_iterator = child_ref; - // } } grpc_json* ChannelTrace::RenderJson() const { diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h index 543eabf13a..230faa483e 100644 --- a/src/core/lib/channel/channel_trace.h +++ b/src/core/lib/channel/channel_trace.h @@ -30,8 +30,7 @@ namespace grpc_core { namespace channelz { -class ChannelNode; -class SubchannelNode; +class BaseNode; // Object used to hold live data for a channel. This data is exposed via the // channelz service: @@ -63,12 +62,8 @@ class ChannelTrace { // TODO(ncteisen): as this call is used more and more throughout the gRPC // stack, determine if it makes more sense to accept a char* instead of a // slice. - void AddTraceEventReferencingChannel( - Severity severity, grpc_slice data, - RefCountedPtr referenced_channel); - // void AddTraceEventReferencingSubchannel( - // Severity severity, grpc_slice data, - // RefCountedPtr referenced_subchannel); + void AddTraceEventWithReference(Severity severity, grpc_slice data, + RefCountedPtr referenced_channel); // Creates and returns the raw grpc_json object, so a parent channelz // object may incorporate the json before rendering. @@ -81,11 +76,7 @@ class ChannelTrace { public: // Constructor for a TraceEvent that references a channel. TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced_channel); - - // Constructor for a TraceEvent that references a subchannel. - TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced_subchannel); + RefCountedPtr referenced_entity_); // Constructor for a TraceEvent that does not reverence a different // channel. @@ -107,8 +98,7 @@ class ChannelTrace { gpr_timespec timestamp_; TraceEvent* next_; // the tracer object for the (sub)channel that this trace event refers to. - RefCountedPtr referenced_channel_; - // RefCountedPtr referenced_subchannel_; + RefCountedPtr referenced_entity_; }; // TraceEvent // Internal helper to add and link in a trace event diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 2443532bb8..5018bbbfa1 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -94,6 +94,7 @@ grpc_resource_quota_resize_type grpc_resource_quota_resize_import; grpc_resource_quota_arg_vtable_type grpc_resource_quota_arg_vtable_import; grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import; grpc_channelz_get_channel_type grpc_channelz_get_channel_import; +grpc_channelz_get_subchannel_type grpc_channelz_get_subchannel_import; grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import; grpc_server_add_insecure_channel_from_fd_type grpc_server_add_insecure_channel_from_fd_import; grpc_use_signal_type grpc_use_signal_import; @@ -344,6 +345,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_resource_quota_arg_vtable_import = (grpc_resource_quota_arg_vtable_type) GetProcAddress(library, "grpc_resource_quota_arg_vtable"); grpc_channelz_get_top_channels_import = (grpc_channelz_get_top_channels_type) GetProcAddress(library, "grpc_channelz_get_top_channels"); grpc_channelz_get_channel_import = (grpc_channelz_get_channel_type) GetProcAddress(library, "grpc_channelz_get_channel"); + grpc_channelz_get_subchannel_import = (grpc_channelz_get_subchannel_type) GetProcAddress(library, "grpc_channelz_get_subchannel"); grpc_insecure_channel_create_from_fd_import = (grpc_insecure_channel_create_from_fd_type) GetProcAddress(library, "grpc_insecure_channel_create_from_fd"); grpc_server_add_insecure_channel_from_fd_import = (grpc_server_add_insecure_channel_from_fd_type) GetProcAddress(library, "grpc_server_add_insecure_channel_from_fd"); grpc_use_signal_import = (grpc_use_signal_type) GetProcAddress(library, "grpc_use_signal"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index b08a1f94f7..edb7e98605 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -257,6 +257,9 @@ extern grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import typedef char*(*grpc_channelz_get_channel_type)(intptr_t channel_id); extern grpc_channelz_get_channel_type grpc_channelz_get_channel_import; #define grpc_channelz_get_channel grpc_channelz_get_channel_import +typedef char*(*grpc_channelz_get_subchannel_type)(intptr_t subchannel_id); +extern grpc_channelz_get_subchannel_type grpc_channelz_get_subchannel_import; +#define grpc_channelz_get_subchannel grpc_channelz_get_subchannel_import typedef grpc_channel*(*grpc_insecure_channel_create_from_fd_type)(const char* target, int fd, const grpc_channel_args* args); extern grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import; #define grpc_insecure_channel_create_from_fd grpc_insecure_channel_create_from_fd_import diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index efa625bccf..9bc9dde8d6 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -89,6 +89,7 @@ void ValidateChannelTrace(ChannelTrace* tracer, grpc_json* json = tracer->RenderJson(); EXPECT_NE(json, nullptr); char* json_str = grpc_json_dump_to_string(json, 0); + gpr_log(GPR_ERROR, "%s", json_str); grpc_json_destroy(json); grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str); grpc_json* parsed_json = grpc_json_parse_string(json_str); @@ -156,7 +157,7 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = MakeRefCounted(channel1.channel(), GetParam(), true); - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); @@ -174,10 +175,10 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelFixture channel2(GetParam()); RefCountedPtr sc2 = MakeRefCounted(channel2.channel(), GetParam(), true); - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("LB channel two created"), sc2); - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Warning, grpc_slice_from_static_string("subchannel one inactive"), sc1); ValidateChannelTrace(&tracer, 7, GetParam()); @@ -203,7 +204,7 @@ TEST_P(ChannelTracerTest, TestNesting) { ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = MakeRefCounted(channel1.channel(), GetParam(), true); - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); @@ -212,7 +213,7 @@ TEST_P(ChannelTracerTest, TestNesting) { RefCountedPtr conn1 = MakeRefCounted(channel2.channel(), GetParam(), true); // nesting one level deeper. - sc1->counter_and_tracer()->trace()->AddTraceEventReferencingChannel( + sc1->counter_and_tracer()->trace()->AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("connection one created"), conn1); ValidateChannelTrace(&tracer, 3, GetParam()); @@ -224,12 +225,12 @@ TEST_P(ChannelTracerTest, TestNesting) { ChannelFixture channel3(GetParam()); RefCountedPtr sc2 = MakeRefCounted(channel3.channel(), GetParam(), true); - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel two created"), sc2); // this trace should not get added to the parents children since it is already // present in the tracer. - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Warning, grpc_slice_from_static_string("subchannel one inactive"), sc1); AddSimpleTrace(&tracer); diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 9f4ad2b4d7..d492685915 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -133,6 +133,7 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_resource_quota_arg_vtable); printf("%lx", (unsigned long) grpc_channelz_get_top_channels); printf("%lx", (unsigned long) grpc_channelz_get_channel); + printf("%lx", (unsigned long) grpc_channelz_get_subchannel); printf("%lx", (unsigned long) grpc_auth_property_iterator_next); printf("%lx", (unsigned long) grpc_auth_context_property_iterator); printf("%lx", (unsigned long) grpc_auth_context_peer_identity); -- cgit v1.2.3 From 1482d3f25c75d1773fd3ab7320403f93d173fc7f Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Fri, 27 Jul 2018 12:21:05 -0700 Subject: PR Feedback Changes --- .../ext/filters/http/server/http_server_filter.cc | 15 ++++--------- .../filters/message_size/message_size_filter.cc | 12 +---------- src/core/lib/iomgr/error.cc | 14 ++++++++++++ src/core/lib/iomgr/error.h | 7 ++++++ .../lib/security/transport/server_auth_filter.cc | 25 +++++++++++++++++++++- src/core/lib/surface/call.cc | 2 +- src/core/lib/surface/server.cc | 23 ++++++++++++++++++-- 7 files changed, 72 insertions(+), 26 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/http/server/http_server_filter.cc b/src/core/ext/filters/http/server/http_server_filter.cc index 01e5aa445e..c66f531a89 100644 --- a/src/core/ext/filters/http/server/http_server_filter.cc +++ b/src/core/ext/filters/http/server/http_server_filter.cc @@ -321,17 +321,8 @@ static void hs_recv_message_ready(void* user_data, grpc_error* err) { static void hs_recv_trailing_metadata_ready(void* user_data, grpc_error* err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); - if (calld->recv_initial_metadata_ready_error != GRPC_ERROR_NONE) { - if (err == GRPC_ERROR_NONE) { - err = GRPC_ERROR_REF(calld->recv_initial_metadata_ready_error); - } else if (err != calld->recv_initial_metadata_ready_error) { - err = grpc_error_add_child(err, calld->recv_initial_metadata_ready_error); - } else { - err = GRPC_ERROR_REF(err); - } - } else { - err = GRPC_ERROR_REF(err); - } + err = + grpc_error_maybe_add_child(err, calld->recv_initial_metadata_ready_error); GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err); } @@ -382,6 +373,8 @@ static grpc_error* hs_mutate_op(grpc_call_element* elem, if (op->recv_trailing_metadata) { calld->original_recv_trailing_metadata_ready = op->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready; } if (op->send_trailing_metadata) { diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc index deb5ae70ec..b5ca1be804 100644 --- a/src/core/ext/filters/message_size/message_size_filter.cc +++ b/src/core/ext/filters/message_size/message_size_filter.cc @@ -155,17 +155,7 @@ static void recv_message_ready(void* user_data, grpc_error* error) { static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); - if (calld->error != GRPC_ERROR_NONE) { - if (error == GRPC_ERROR_NONE) { - error = GRPC_ERROR_REF(calld->error); - } else if (error != calld->error) { - error = grpc_error_add_child(error, GRPC_ERROR_REF(calld->error)); - } else { - error = GRPC_ERROR_REF(error); - } - } else { - error = GRPC_ERROR_REF(error); - } + error = grpc_error_maybe_add_child(error, calld->error); // Invoke the next callback. GRPC_CLOSURE_RUN(calld->next_recv_trailing_metadata_ready, error); } diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc index 90ed34da11..226b44c46d 100644 --- a/src/core/lib/iomgr/error.cc +++ b/src/core/lib/iomgr/error.cc @@ -518,6 +518,20 @@ grpc_error* grpc_error_add_child(grpc_error* src, grpc_error* child) { return new_err; } +grpc_error* grpc_error_maybe_add_child(grpc_error* src, grpc_error* child) { + if (src != GRPC_ERROR_NONE) { + if (child == GRPC_ERROR_NONE) { + return GRPC_ERROR_REF(src); + } else if (child != src) { + return grpc_error_add_child(src, GRPC_ERROR_REF(child)); + } else { + return GRPC_ERROR_REF(src); + } + } else { + return GRPC_ERROR_REF(child); + } +} + static const char* no_error_string = "\"No Error\""; static const char* oom_error_string = "\"Out of memory\""; static const char* cancelled_error_string = "\"Cancelled\""; diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h index 27c4d22fd1..4f65c447fd 100644 --- a/src/core/lib/iomgr/error.h +++ b/src/core/lib/iomgr/error.h @@ -187,6 +187,13 @@ bool grpc_error_get_str(grpc_error* error, grpc_error_strs which, /// child error. grpc_error* grpc_error_add_child(grpc_error* src, grpc_error* child) GRPC_MUST_USE_RESULT; +/// Produce an error that is a combination of both src and child. +// If src or child, is GRPC_ERROR_NONE, a new reference to the other error is +// returned. Otherwise, a new error with src as the parent and child as the +// child is returned. +grpc_error* grpc_error_maybe_add_child(grpc_error* src, + grpc_error* child) GRPC_MUST_USE_RESULT; + grpc_error* grpc_os_error(const char* file, int line, int err, const char* call_name) GRPC_MUST_USE_RESULT; diff --git a/src/core/lib/security/transport/server_auth_filter.cc b/src/core/lib/security/transport/server_auth_filter.cc index 2dbefdf131..7732b695b3 100644 --- a/src/core/lib/security/transport/server_auth_filter.cc +++ b/src/core/lib/security/transport/server_auth_filter.cc @@ -41,6 +41,9 @@ struct call_data { grpc_transport_stream_op_batch* recv_initial_metadata_batch; grpc_closure* original_recv_initial_metadata_ready; grpc_closure recv_initial_metadata_ready; + grpc_error* error; + grpc_closure recv_trailing_metadata_ready; + grpc_closure* original_recv_trailing_metadata_ready; grpc_metadata_array md; const grpc_metadata* consumed_md; size_t num_consumed_md; @@ -111,6 +114,7 @@ static void on_md_processing_done_inner(grpc_call_element* elem, batch->payload->recv_initial_metadata.recv_initial_metadata, remove_consumed_md, elem, "Response metadata filtering error"); } + calld->error = GRPC_ERROR_REF(error); GRPC_CLOSURE_SCHED(calld->original_recv_initial_metadata_ready, error); } @@ -186,6 +190,13 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { GRPC_ERROR_REF(error)); } +static void recv_trailing_metadata_ready(void* user_data, grpc_error* err) { + grpc_call_element* elem = static_cast(user_data); + call_data* calld = static_cast(elem->call_data); + err = grpc_error_maybe_add_child(err, calld->error); + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err); +} + static void auth_start_transport_stream_op_batch( grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { call_data* calld = static_cast(elem->call_data); @@ -197,6 +208,12 @@ static void auth_start_transport_stream_op_batch( batch->payload->recv_initial_metadata.recv_initial_metadata_ready = &calld->recv_initial_metadata_ready; } + if (batch->recv_trailing_metadata) { + calld->original_recv_trailing_metadata_ready = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready; + } grpc_call_next_op(elem, batch); } @@ -210,6 +227,9 @@ static grpc_error* init_call_elem(grpc_call_element* elem, GRPC_CLOSURE_INIT(&calld->recv_initial_metadata_ready, recv_initial_metadata_ready, elem, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready, + recv_trailing_metadata_ready, elem, + grpc_schedule_on_exec_ctx); // Create server security context. Set its auth context from channel // data and save it in the call context. grpc_server_security_context* server_ctx = @@ -229,7 +249,10 @@ static grpc_error* init_call_elem(grpc_call_element* elem, /* Destructor for call_data */ static void destroy_call_elem(grpc_call_element* elem, const grpc_call_final_info* final_info, - grpc_closure* ignored) {} + grpc_closure* ignored) { + call_data* calld = static_cast(elem->call_data); + GRPC_ERROR_UNREF(calld->error); +} /* Constructor for channel_data */ static grpc_error* init_channel_elem(grpc_channel_element* elem, diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 1ee3667a58..151cf6c852 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -512,7 +512,7 @@ static void destroy_call(void* call, grpc_error* error) { grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(c->status_error, c->send_deadline, &c->final_info.final_status, &slice, nullptr, - &c->final_info.error_string); + &(c->final_info.error_string)); GRPC_ERROR_UNREF(c->status_error); c->final_info.stats.latency = gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time); diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index cb34def740..4403caf044 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -149,6 +149,9 @@ struct call_data { grpc_closure server_on_recv_initial_metadata; grpc_closure kill_zombie_closure; grpc_closure* on_done_recv_initial_metadata; + grpc_closure recv_trailing_metadata_ready; + grpc_error* error; + grpc_closure* original_recv_trailing_metadata_ready; grpc_closure publish; @@ -730,6 +733,14 @@ static void server_on_recv_initial_metadata(void* ptr, grpc_error* error) { GRPC_CLOSURE_RUN(calld->on_done_recv_initial_metadata, error); } +static void server_recv_trailing_metadata_ready(void* user_data, + grpc_error* err) { + grpc_call_element* elem = static_cast(user_data); + call_data* calld = static_cast(elem->call_data); + err = grpc_error_maybe_add_child(err, calld->error); + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err); +} + static void server_mutate_op(grpc_call_element* elem, grpc_transport_stream_op_batch* op) { call_data* calld = static_cast(elem->call_data); @@ -745,6 +756,12 @@ static void server_mutate_op(grpc_call_element* elem, op->payload->recv_initial_metadata.recv_flags = &calld->recv_initial_metadata_flags; } + if (op->recv_trailing_metadata) { + calld->original_recv_trailing_metadata_ready = + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + op->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready; + } } static void server_start_transport_stream_op_batch( @@ -828,7 +845,9 @@ static grpc_error* init_call_elem(grpc_call_element* elem, GRPC_CLOSURE_INIT(&calld->server_on_recv_initial_metadata, server_on_recv_initial_metadata, elem, grpc_schedule_on_exec_ctx); - + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready, + server_recv_trailing_metadata_ready, elem, + grpc_schedule_on_exec_ctx); server_ref(chand->server); return GRPC_ERROR_NONE; } @@ -840,7 +859,7 @@ static void destroy_call_elem(grpc_call_element* elem, call_data* calld = static_cast(elem->call_data); GPR_ASSERT(calld->state != PENDING); - + GRPC_ERROR_UNREF(calld->error); if (calld->host_set) { grpc_slice_unref_internal(calld->host); } -- cgit v1.2.3 From 58db94e5d9f3e55f14760f936a42e5e6ddb6bd5b Mon Sep 17 00:00:00 2001 From: ncteisen Date: Sun, 29 Jul 2018 20:30:05 -0700 Subject: reviewer comments --- .../client_channel/client_channel_channelz.cc | 30 ++++++++---- .../client_channel/client_channel_channelz.h | 11 +++-- src/core/ext/filters/client_channel/subchannel.cc | 4 +- src/core/lib/channel/channelz.cc | 39 +++++++--------- src/core/lib/channel/channelz.h | 41 ++++++++--------- src/core/lib/surface/call.cc | 6 +-- src/core/lib/surface/channel.cc | 4 +- test/core/channel/channel_trace_test.cc | 25 +++++----- test/core/channel/channelz_test.cc | 53 ++++++++++------------ 9 files changed, 106 insertions(+), 107 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index f797ef1b09..7120ec57f1 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -123,9 +123,14 @@ grpc_json* ClientChannelNode::RenderJson() { GPR_ASSERT(target_view() != nullptr); grpc_json_create_child(nullptr, json, "target", target_view(), GRPC_JSON_STRING, false); - // as CallCountingAndTracingNode to populate trace and call count data. - counter_and_tracer()->PopulateTrace(json); - counter_and_tracer()->PopulateCallData(json); + // fill in the channel trace if applicable + grpc_json* trace_json = trace()->RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter()->PopulateCallData(json); // reset to the top level json = top_level_json; PopulateChildRefs(json); @@ -150,11 +155,12 @@ SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes) : BaseNode(EntityType::kSubchannel), subchannel_(subchannel), - target_( - UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_)))), - counter_and_tracer_(channel_tracer_max_nodes) {} + target_(UniquePtr( + gpr_strdup(grpc_subchannel_get_target(subchannel_)))) { + trace_.Init(channel_tracer_max_nodes); +} -SubchannelNode::~SubchannelNode() {} +SubchannelNode::~SubchannelNode() { trace_.Destroy(); } void SubchannelNode::PopulateConnectivityState(grpc_json* json) { grpc_connectivity_state state; @@ -192,8 +198,14 @@ grpc_json* SubchannelNode::RenderJson() { GPR_ASSERT(target_.get() != nullptr); grpc_json_create_child(nullptr, json, "target", target_.get(), GRPC_JSON_STRING, false); - counter_and_tracer_.PopulateTrace(json); - counter_and_tracer_.PopulateCallData(json); + // fill in the channel trace if applicable + grpc_json* trace_json = trace_->RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter_.PopulateCallData(json); return top_level_json; } diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index f5344c049e..735ffacfd2 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -76,14 +76,17 @@ class SubchannelNode : public BaseNode { grpc_json* RenderJson() override; - CallCountingAndTracingNode* counter_and_tracer() { - return &counter_and_tracer_; - } + // proxy methods to composed classes. + ChannelTrace* trace() { return trace_.get(); } + void RecordCallStarted() { call_counter_.RecordCallStarted(); } + void RecordCallFailed() { call_counter_.RecordCallFailed(); } + void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } private: grpc_subchannel* subchannel_; UniquePtr target_; - CallCountingAndTracingNode counter_and_tracer_; + CallCountingHelper call_counter_; + ManualConstructor trace_; void PopulateConnectivityState(grpc_json* json); }; diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index d7b64a900f..f0f8d94ef4 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -183,7 +183,7 @@ static void connection_destroy(void* arg, grpc_error* error) { static void subchannel_destroy(void* arg, grpc_error* error) { grpc_subchannel* c = static_cast(arg); if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel->counter_and_tracer()->trace()->AddTraceEvent( + c->channelz_subchannel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel destroyed")); c->channelz_subchannel->MarkSubchannelDestroyed(); @@ -397,7 +397,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, c->channelz_subchannel = grpc_core::MakeRefCounted( c, channel_tracer_max_nodes); - c->channelz_subchannel->counter_and_tracer()->trace()->AddTraceEvent( + c->channelz_subchannel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel created")); } diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index ee1717ce9f..a75a05023a 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -53,33 +53,20 @@ char* BaseNode::RenderJsonString() { return json_str; } -CallCountingAndTracingNode::CallCountingAndTracingNode( - size_t channel_tracer_max_nodes) { - trace_.Init(channel_tracer_max_nodes); +CallCountingHelper::CallCountingHelper() { gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -CallCountingAndTracingNode::~CallCountingAndTracingNode() { trace_.Destroy(); } +CallCountingHelper::~CallCountingHelper() {} -void CallCountingAndTracingNode::RecordCallStarted() { +void CallCountingHelper::RecordCallStarted() { gpr_atm_no_barrier_fetch_add(&calls_started_, (gpr_atm)1); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -void CallCountingAndTracingNode::PopulateTrace(grpc_json* json) { - // fill in the channel trace if applicable - grpc_json* trace_json = trace_->RenderJson(); - if (trace_json != nullptr) { - // we manually link up and fill the child since it was created for us in - // ChannelTrace::RenderJson - trace_json->key = "trace"; // this object is named trace in channelz.proto - grpc_json_link_child(json, trace_json, nullptr); - } -} - -void CallCountingAndTracingNode::PopulateCallData(grpc_json* json) { +void CallCountingHelper::PopulateCallData(grpc_json* json) { grpc_json* json_iterator = nullptr; if (calls_started_ != 0) { json_iterator = grpc_json_add_number_string_child( @@ -105,10 +92,11 @@ ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, : BaseNode(is_top_level_channel ? EntityType::kTopLevelChannel : EntityType::kInternalChannel), channel_(channel), - target_(UniquePtr(grpc_channel_get_target(channel_))), - counter_and_tracer_(channel_tracer_max_nodes) {} + target_(UniquePtr(grpc_channel_get_target(channel_))) { + trace_.Init(channel_tracer_max_nodes); +} -ChannelNode::~ChannelNode() {} +ChannelNode::~ChannelNode() { trace_.Destroy(); } grpc_json* ChannelNode::RenderJson() { // We need to track these three json objects to build our object @@ -134,9 +122,14 @@ grpc_json* ChannelNode::RenderJson() { GPR_ASSERT(target_.get() != nullptr); grpc_json_create_child(nullptr, json, "target", target_.get(), GRPC_JSON_STRING, false); - // as CallCountingAndTracingNode to populate trace and call count data. - counter_and_tracer_.PopulateTrace(json); - counter_and_tracer_.PopulateCallData(json); + // fill in the channel trace if applicable + grpc_json* trace_json = trace_->RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter_.PopulateCallData(json); return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 7bc4567ad2..6e20f31b68 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -43,7 +43,7 @@ namespace grpc_core { namespace channelz { namespace testing { -class CallCountingAndTracingNodePeer; +class CallCountingHelperPeer; } // base class for all channelz entities @@ -60,7 +60,7 @@ class BaseNode : public RefCounted { kSocket, }; - BaseNode(EntityType type); + explicit BaseNode(EntityType type); virtual ~BaseNode(); // All children must implement this function. @@ -74,22 +74,20 @@ class BaseNode : public RefCounted { intptr_t uuid() const { return uuid_; } private: - friend class ChannelTrace; - EntityType type_; + const EntityType type_; const intptr_t uuid_; }; -// This class is the parent for the channelz entities that deal with Channels +// This class is a helper class for channelz entities that deal with Channels // Subchannels, and Servers, since those have similar proto definitions. // This class has the ability to: // - track calls_{started,succeeded,failed} // - track last_call_started_timestamp -// - hold the channel trace. -// - perform common rendering. -class CallCountingAndTracingNode { +// - perform rendering of the above items +class CallCountingHelper { public: - CallCountingAndTracingNode(size_t channel_tracer_max_nodes); - ~CallCountingAndTracingNode(); + CallCountingHelper(); + ~CallCountingHelper(); void RecordCallStarted(); void RecordCallFailed() { @@ -98,23 +96,18 @@ class CallCountingAndTracingNode { void RecordCallSucceeded() { gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1))); } - ChannelTrace* trace() { return trace_.get(); } - - // Common rendering of the channel trace. - void PopulateTrace(grpc_json* json); // Common rendering of the call count data and last_call_started_timestamp. void PopulateCallData(grpc_json* json); private: // testing peer friend. - friend class testing::CallCountingAndTracingNodePeer; + friend class testing::CallCountingHelperPeer; gpr_atm calls_started_ = 0; gpr_atm calls_succeeded_ = 0; gpr_atm calls_failed_ = 0; gpr_atm last_call_started_millis_ = 0; - ManualConstructor trace_; }; // Handles channelz bookkeeping for channels @@ -137,25 +130,31 @@ class ChannelNode : public BaseNode { bool ChannelIsDestroyed() { return channel_ == nullptr; } - CallCountingAndTracingNode* counter_and_tracer() { - return &counter_and_tracer_; - } + // proxy methods to composed classes. + ChannelTrace* trace() { return trace_.get(); } + void RecordCallStarted() { call_counter_.RecordCallStarted(); } + void RecordCallFailed() { call_counter_.RecordCallFailed(); } + void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } protected: // provides view of target for child. char* target_view() { return target_.get(); } + // provides access to call_counter_ for child. + CallCountingHelper* call_counter() { return &call_counter_; } private: grpc_channel* channel_ = nullptr; UniquePtr target_; - CallCountingAndTracingNode counter_and_tracer_; + CallCountingHelper call_counter_; + ManualConstructor trace_; }; // Handles channelz bookkeeping for servers // TODO(ncteisen): implement in subsequent PR. class ServerNode : public BaseNode { public: - ServerNode(size_t channel_tracer_max_nodes) : BaseNode(EntityType::kServer) {} + explicit ServerNode(size_t channel_tracer_max_nodes) + : BaseNode(EntityType::kServer) {} ~ServerNode() override {} }; diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 03b7cedcdb..a6d626e495 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -489,7 +489,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { - channelz_channel->counter_and_tracer()->RecordCallStarted(); + channelz_channel->RecordCallStarted(); } grpc_slice_unref_internal(path); @@ -1269,9 +1269,9 @@ static void post_batch_completion(batch_control* bctl) { grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { if (*call->final_op.client.status != GRPC_STATUS_OK) { - channelz_channel->counter_and_tracer()->RecordCallFailed(); + channelz_channel->RecordCallFailed(); } else { - channelz_channel->counter_and_tracer()->RecordCallSucceeded(); + channelz_channel->RecordCallSucceeded(); } } GRPC_ERROR_UNREF(error); diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 16d3322a9d..01caadaaba 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -170,7 +170,7 @@ grpc_channel* grpc_channel_create_with_builder( bool is_top_level_channel = channel->is_client && !internal_channel; channel->channelz_channel = channel_node_create_func( channel, channel_tracer_max_nodes, is_top_level_channel); - channel->channelz_channel->counter_and_tracer()->trace()->AddTraceEvent( + channel->channelz_channel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); } @@ -417,7 +417,7 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) { static void destroy_channel(void* arg, grpc_error* error) { grpc_channel* channel = static_cast(arg); if (channel->channelz_channel != nullptr) { - channel->channelz_channel->counter_and_tracer()->trace()->AddTraceEvent( + channel->channelz_channel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel destroyed")); channel->channelz_channel->MarkChannelDestroyed(); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 9bc9dde8d6..3f5aa85c8c 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -89,7 +89,6 @@ void ValidateChannelTrace(ChannelTrace* tracer, grpc_json* json = tracer->RenderJson(); EXPECT_NE(json, nullptr); char* json_str = grpc_json_dump_to_string(json, 0); - gpr_log(GPR_ERROR, "%s", json_str); grpc_json_destroy(json); grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str); grpc_json* parsed_json = grpc_json_parse_string(json_str); @@ -161,14 +160,14 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - ValidateChannelTrace(sc1->counter_and_tracer()->trace(), 3, GetParam()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - ValidateChannelTrace(sc1->counter_and_tracer()->trace(), 6, GetParam()); + AddSimpleTrace(sc1->trace()); + AddSimpleTrace(sc1->trace()); + AddSimpleTrace(sc1->trace()); + ValidateChannelTrace(sc1->trace(), 3, GetParam()); + AddSimpleTrace(sc1->trace()); + AddSimpleTrace(sc1->trace()); + AddSimpleTrace(sc1->trace()); + ValidateChannelTrace(sc1->trace(), 6, GetParam()); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 5, GetParam()); @@ -208,20 +207,20 @@ TEST_P(ChannelTracerTest, TestNesting) { ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); + AddSimpleTrace(sc1->trace()); ChannelFixture channel2(GetParam()); RefCountedPtr conn1 = MakeRefCounted(channel2.channel(), GetParam(), true); // nesting one level deeper. - sc1->counter_and_tracer()->trace()->AddTraceEventWithReference( + sc1->trace()->AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("connection one created"), conn1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(conn1->counter_and_tracer()->trace()); + AddSimpleTrace(conn1->trace()); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 5, GetParam()); - ValidateChannelTrace(conn1->counter_and_tracer()->trace(), 1, GetParam()); + ValidateChannelTrace(conn1->trace(), 1, GetParam()); ChannelFixture channel3(GetParam()); RefCountedPtr sc2 = MakeRefCounted(channel3.channel(), GetParam(), true); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 5e9a3f89a2..8fa46a18da 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -44,17 +44,16 @@ namespace channelz { namespace testing { // testing peer to access channel internals -class CallCountingAndTracingNodePeer { +class CallCountingHelperPeer { public: - CallCountingAndTracingNodePeer(CallCountingAndTracingNode* node) - : node_(node) {} + CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {} grpc_millis last_call_started_millis() { return (grpc_millis)gpr_atm_no_barrier_load( &node_->last_call_started_millis_); } private: - CallCountingAndTracingNode* node_; + CallCountingHelper* node_; }; namespace { @@ -164,8 +163,8 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { gpr_free(core_api_json_str); } -grpc_millis GetLastCallStartedMillis(CallCountingAndTracingNode* channel) { - CallCountingAndTracingNodePeer peer(channel); +grpc_millis GetLastCallStartedMillis(CallCountingHelper* channel) { + CallCountingHelperPeer peer(channel); return peer.last_call_started_millis(); } @@ -201,46 +200,40 @@ TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) { ChannelFixture channel(GetParam()); ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel.channel()); - channelz_channel->counter_and_tracer()->RecordCallStarted(); - channelz_channel->counter_and_tracer()->RecordCallFailed(); - channelz_channel->counter_and_tracer()->RecordCallSucceeded(); + channelz_channel->RecordCallStarted(); + channelz_channel->RecordCallFailed(); + channelz_channel->RecordCallSucceeded(); ValidateChannel(channelz_channel, {1, 1, 1}); - channelz_channel->counter_and_tracer()->RecordCallStarted(); - channelz_channel->counter_and_tracer()->RecordCallFailed(); - channelz_channel->counter_and_tracer()->RecordCallSucceeded(); - channelz_channel->counter_and_tracer()->RecordCallStarted(); - channelz_channel->counter_and_tracer()->RecordCallFailed(); - channelz_channel->counter_and_tracer()->RecordCallSucceeded(); + channelz_channel->RecordCallStarted(); + channelz_channel->RecordCallFailed(); + channelz_channel->RecordCallSucceeded(); + channelz_channel->RecordCallStarted(); + channelz_channel->RecordCallFailed(); + channelz_channel->RecordCallSucceeded(); ValidateChannel(channelz_channel, {3, 3, 3}); } TEST_P(ChannelzChannelTest, LastCallStartedMillis) { grpc_core::ExecCtx exec_ctx; - ChannelFixture channel(GetParam()); - ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(channel.channel()); + CallCountingHelper counter; // start a call to set the last call started timestamp - channelz_channel->counter_and_tracer()->RecordCallStarted(); - grpc_millis millis1 = - GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); + counter.RecordCallStarted(); + grpc_millis millis1 = GetLastCallStartedMillis(&counter); // time gone by should not affect the timestamp ChannelzSleep(100); - grpc_millis millis2 = - GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); + grpc_millis millis2 = GetLastCallStartedMillis(&counter); EXPECT_EQ(millis1, millis2); // calls succeeded or failed should not affect the timestamp ChannelzSleep(100); - channelz_channel->counter_and_tracer()->RecordCallFailed(); - channelz_channel->counter_and_tracer()->RecordCallSucceeded(); - grpc_millis millis3 = - GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); + counter.RecordCallFailed(); + counter.RecordCallSucceeded(); + grpc_millis millis3 = GetLastCallStartedMillis(&counter); EXPECT_EQ(millis1, millis3); // another call started should affect the timestamp // sleep for extra long to avoid flakes (since we cache Now()) ChannelzSleep(5000); - channelz_channel->counter_and_tracer()->RecordCallStarted(); - grpc_millis millis4 = - GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); + counter.RecordCallStarted(); + grpc_millis millis4 = GetLastCallStartedMillis(&counter); EXPECT_NE(millis1, millis4); } -- cgit v1.2.3 From e888e93293310259b9d4bbabff2baf312cdd8973 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 30 Jul 2018 22:29:47 -0700 Subject: reviewer feedback --- .../client_channel/client_channel_channelz.h | 9 ++++- src/core/ext/filters/client_channel/subchannel.cc | 4 +-- src/core/lib/channel/channelz.h | 16 +++++++-- src/core/lib/surface/channel.cc | 4 +-- test/core/channel/channel_trace_test.cc | 38 +++++++++++++++------- 5 files changed, 52 insertions(+), 19 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 735ffacfd2..5e01fdf2a3 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -77,7 +77,14 @@ class SubchannelNode : public BaseNode { grpc_json* RenderJson() override; // proxy methods to composed classes. - ChannelTrace* trace() { return trace_.get(); } + void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { + trace_->AddTraceEvent(severity, data); + } + void AddTraceEventWithReference(ChannelTrace::Severity severity, + grpc_slice data, + RefCountedPtr referenced_channel) { + trace_->AddTraceEventWithReference(severity, data, referenced_channel); + } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index b74a354e9e..639a5fe9db 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -183,7 +183,7 @@ static void connection_destroy(void* arg, grpc_error* error) { static void subchannel_destroy(void* arg, grpc_error* error) { grpc_subchannel* c = static_cast(arg); if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel->trace()->AddTraceEvent( + c->channelz_subchannel->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel destroyed")); c->channelz_subchannel->MarkSubchannelDestroyed(); @@ -397,7 +397,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, c->channelz_subchannel = grpc_core::MakeRefCounted( c, channel_tracer_max_nodes); - c->channelz_subchannel->trace()->AddTraceEvent( + c->channelz_subchannel->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel created")); } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 6e20f31b68..74b203af44 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -44,7 +44,8 @@ namespace channelz { namespace testing { class CallCountingHelperPeer; -} +class ChannelNodePeer; +} // namespace testing // base class for all channelz entities class BaseNode : public RefCounted { @@ -131,7 +132,14 @@ class ChannelNode : public BaseNode { bool ChannelIsDestroyed() { return channel_ == nullptr; } // proxy methods to composed classes. - ChannelTrace* trace() { return trace_.get(); } + void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { + trace_->AddTraceEvent(severity, data); + } + void AddTraceEventWithReference(ChannelTrace::Severity severity, + grpc_slice data, + RefCountedPtr referenced_channel) { + trace_->AddTraceEventWithReference(severity, data, referenced_channel); + } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } @@ -141,8 +149,12 @@ class ChannelNode : public BaseNode { char* target_view() { return target_.get(); } // provides access to call_counter_ for child. CallCountingHelper* call_counter() { return &call_counter_; } + // provides access to channel trace for child. + ChannelTrace* trace() { return trace_.get(); } private: + // to allow the channel trace test to access trace(); + friend class testing::ChannelNodePeer; grpc_channel* channel_ = nullptr; UniquePtr target_; CallCountingHelper call_counter_; diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 01caadaaba..0b3508e27c 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -170,7 +170,7 @@ grpc_channel* grpc_channel_create_with_builder( bool is_top_level_channel = channel->is_client && !internal_channel; channel->channelz_channel = channel_node_create_func( channel, channel_tracer_max_nodes, is_top_level_channel); - channel->channelz_channel->trace()->AddTraceEvent( + channel->channelz_channel->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); } @@ -417,7 +417,7 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) { static void destroy_channel(void* arg, grpc_error* error) { grpc_channel* channel = static_cast(arg); if (channel->channelz_channel != nullptr) { - channel->channelz_channel->trace()->AddTraceEvent( + channel->channelz_channel->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel destroyed")); channel->channelz_channel->MarkChannelDestroyed(); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 3f5aa85c8c..8a5ddc2723 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -40,6 +40,17 @@ namespace grpc_core { namespace channelz { namespace testing { + +// testing peer to access channel internals +class ChannelNodePeer { + public: + ChannelNodePeer(ChannelNode* node) : node_(node) {} + ChannelTrace* trace() { return node_->trace_.get(); } + + private: + ChannelNode* node_; +}; + namespace { grpc_json* GetJsonChild(grpc_json* parent, const char* key) { @@ -156,18 +167,19 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = MakeRefCounted(channel1.channel(), GetParam(), true); + ChannelNodePeer sc1_peer(sc1.get()); tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - ValidateChannelTrace(sc1->trace(), 3, GetParam()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - ValidateChannelTrace(sc1->trace(), 6, GetParam()); + AddSimpleTrace(sc1_peer.trace()); + AddSimpleTrace(sc1_peer.trace()); + AddSimpleTrace(sc1_peer.trace()); + ValidateChannelTrace(sc1_peer.trace(), 3, GetParam()); + AddSimpleTrace(sc1_peer.trace()); + AddSimpleTrace(sc1_peer.trace()); + AddSimpleTrace(sc1_peer.trace()); + ValidateChannelTrace(sc1_peer.trace(), 6, GetParam()); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 5, GetParam()); @@ -203,24 +215,26 @@ TEST_P(ChannelTracerTest, TestNesting) { ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = MakeRefCounted(channel1.channel(), GetParam(), true); + ChannelNodePeer sc1_peer(sc1.get()); tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->trace()); + AddSimpleTrace(sc1_peer.trace()); ChannelFixture channel2(GetParam()); RefCountedPtr conn1 = MakeRefCounted(channel2.channel(), GetParam(), true); + ChannelNodePeer conn1_peer(conn1.get()); // nesting one level deeper. - sc1->trace()->AddTraceEventWithReference( + sc1_peer.trace()->AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("connection one created"), conn1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(conn1->trace()); + AddSimpleTrace(conn1_peer.trace()); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 5, GetParam()); - ValidateChannelTrace(conn1->trace(), 1, GetParam()); + ValidateChannelTrace(conn1_peer.trace(), 1, GetParam()); ChannelFixture channel3(GetParam()); RefCountedPtr sc2 = MakeRefCounted(channel3.channel(), GetParam(), true); -- cgit v1.2.3 From 885c33da8bb363014e4231f8b5f3da024923f287 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 30 Jul 2018 22:36:25 -0700 Subject: reviewer feedback --- .../ext/filters/client_channel/client_channel_channelz.cc | 11 +++++------ src/core/ext/filters/client_channel/client_channel_channelz.h | 7 ++++--- src/core/lib/channel/channelz.cc | 9 ++++----- src/core/lib/channel/channelz.h | 8 ++++---- 4 files changed, 17 insertions(+), 18 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 7120ec57f1..d904fc28b2 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -155,12 +155,11 @@ SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes) : BaseNode(EntityType::kSubchannel), subchannel_(subchannel), - target_(UniquePtr( - gpr_strdup(grpc_subchannel_get_target(subchannel_)))) { - trace_.Init(channel_tracer_max_nodes); -} + target_( + UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_)))), + trace_(channel_tracer_max_nodes) {} -SubchannelNode::~SubchannelNode() { trace_.Destroy(); } +SubchannelNode::~SubchannelNode() {} void SubchannelNode::PopulateConnectivityState(grpc_json* json) { grpc_connectivity_state state; @@ -199,7 +198,7 @@ grpc_json* SubchannelNode::RenderJson() { grpc_json_create_child(nullptr, json, "target", target_.get(), GRPC_JSON_STRING, false); // fill in the channel trace if applicable - grpc_json* trace_json = trace_->RenderJson(); + grpc_json* trace_json = trace_.RenderJson(); if (trace_json != nullptr) { trace_json->key = "trace"; // this object is named trace in channelz.proto grpc_json_link_child(json, trace_json, nullptr); diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 5e01fdf2a3..9a3fc1d6f1 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -23,6 +23,7 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/channel_trace.h" #include "src/core/lib/channel/channelz.h" #include "src/core/lib/gprpp/inlined_vector.h" @@ -78,12 +79,12 @@ class SubchannelNode : public BaseNode { // proxy methods to composed classes. void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { - trace_->AddTraceEvent(severity, data); + trace_.AddTraceEvent(severity, data); } void AddTraceEventWithReference(ChannelTrace::Severity severity, grpc_slice data, RefCountedPtr referenced_channel) { - trace_->AddTraceEventWithReference(severity, data, referenced_channel); + trace_.AddTraceEventWithReference(severity, data, referenced_channel); } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } @@ -93,7 +94,7 @@ class SubchannelNode : public BaseNode { grpc_subchannel* subchannel_; UniquePtr target_; CallCountingHelper call_counter_; - ManualConstructor trace_; + ChannelTrace trace_; void PopulateConnectivityState(grpc_json* json); }; diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index a75a05023a..b908363b1b 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -92,11 +92,10 @@ ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, : BaseNode(is_top_level_channel ? EntityType::kTopLevelChannel : EntityType::kInternalChannel), channel_(channel), - target_(UniquePtr(grpc_channel_get_target(channel_))) { - trace_.Init(channel_tracer_max_nodes); -} + target_(UniquePtr(grpc_channel_get_target(channel_))), + trace_(channel_tracer_max_nodes) {} -ChannelNode::~ChannelNode() { trace_.Destroy(); } +ChannelNode::~ChannelNode() {} grpc_json* ChannelNode::RenderJson() { // We need to track these three json objects to build our object @@ -123,7 +122,7 @@ grpc_json* ChannelNode::RenderJson() { grpc_json_create_child(nullptr, json, "target", target_.get(), GRPC_JSON_STRING, false); // fill in the channel trace if applicable - grpc_json* trace_json = trace_->RenderJson(); + grpc_json* trace_json = trace_.RenderJson(); if (trace_json != nullptr) { trace_json->key = "trace"; // this object is named trace in channelz.proto grpc_json_link_child(json, trace_json, nullptr); diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 74b203af44..66753c96ee 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -133,12 +133,12 @@ class ChannelNode : public BaseNode { // proxy methods to composed classes. void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { - trace_->AddTraceEvent(severity, data); + trace_.AddTraceEvent(severity, data); } void AddTraceEventWithReference(ChannelTrace::Severity severity, grpc_slice data, RefCountedPtr referenced_channel) { - trace_->AddTraceEventWithReference(severity, data, referenced_channel); + trace_.AddTraceEventWithReference(severity, data, referenced_channel); } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } @@ -150,7 +150,7 @@ class ChannelNode : public BaseNode { // provides access to call_counter_ for child. CallCountingHelper* call_counter() { return &call_counter_; } // provides access to channel trace for child. - ChannelTrace* trace() { return trace_.get(); } + ChannelTrace* trace() { return &trace_; } private: // to allow the channel trace test to access trace(); @@ -158,7 +158,7 @@ class ChannelNode : public BaseNode { grpc_channel* channel_ = nullptr; UniquePtr target_; CallCountingHelper call_counter_; - ManualConstructor trace_; + ChannelTrace trace_; }; // Handles channelz bookkeeping for servers -- cgit v1.2.3 From 016a3354a5d9915dfd8a15822b0874eab6cbc7ba Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 30 Jul 2018 22:45:44 -0700 Subject: reviewer comments --- src/core/ext/filters/client_channel/client_channel.cc | 18 +++++++++++++----- .../filters/client_channel/client_channel_channelz.cc | 4 ++-- src/core/ext/filters/client_channel/subchannel.cc | 3 --- src/core/lib/channel/channelz.cc | 4 ++-- src/core/lib/channel/channelz.h | 2 +- 5 files changed, 18 insertions(+), 13 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 888a5efda3..b3c9268bd8 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -1942,11 +1942,14 @@ static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { grpc_mdelem* server_pushback_md = nullptr; get_call_status(batch_data, GRPC_ERROR_REF(error), &status, &server_pushback_md); - if (status == GRPC_STATUS_OK) { - calld->pick.connected_subchannel->channelz_subchannel() - ->RecordCallSucceeded(); - } else { - calld->pick.connected_subchannel->channelz_subchannel()->RecordCallFailed(); + grpc_core::channelz::SubchannelNode* channelz_subchannel = + calld->pick.connected_subchannel->channelz_subchannel(); + if (channelz_subchannel != nullptr) { + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); + } } if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: call finished, status=%s", chand, @@ -2581,6 +2584,11 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) { new_error = grpc_error_add_child(new_error, error); pending_batches_fail(elem, new_error, true /* yield_call_combiner */); } else { + grpc_core::channelz::SubchannelNode* channelz_subchannel = + calld->pick.connected_subchannel->channelz_subchannel(); + if (channelz_subchannel != nullptr) { + channelz_subchannel->RecordCallStarted(); + } if (parent_data_size > 0) { subchannel_call_retry_state* retry_state = static_cast( diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index d904fc28b2..06b4d2ab95 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -130,7 +130,7 @@ grpc_json* ClientChannelNode::RenderJson() { grpc_json_link_child(json, trace_json, nullptr); } // ask CallCountingHelper to populate trace and call count data. - call_counter()->PopulateCallData(json); + call_counter()->PopulateCallCounts(json); // reset to the top level json = top_level_json; PopulateChildRefs(json); @@ -204,7 +204,7 @@ grpc_json* SubchannelNode::RenderJson() { grpc_json_link_child(json, trace_json, nullptr); } // ask CallCountingHelper to populate trace and call count data. - call_counter_.PopulateCallData(json); + call_counter_.PopulateCallCounts(json); return top_level_json; } diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 639a5fe9db..a7df2ee6cc 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -865,9 +865,6 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, gpr_log(GPR_ERROR, "error: %s", error_string); return error; } - if (channelz_subchannel_ != nullptr) { - channelz_subchannel_->RecordCallStarted(); - } grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); return GRPC_ERROR_NONE; } diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index b908363b1b..1ac7bd3976 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -66,7 +66,7 @@ void CallCountingHelper::RecordCallStarted() { (gpr_atm)ExecCtx::Get()->Now()); } -void CallCountingHelper::PopulateCallData(grpc_json* json) { +void CallCountingHelper::PopulateCallCounts(grpc_json* json) { grpc_json* json_iterator = nullptr; if (calls_started_ != 0) { json_iterator = grpc_json_add_number_string_child( @@ -128,7 +128,7 @@ grpc_json* ChannelNode::RenderJson() { grpc_json_link_child(json, trace_json, nullptr); } // ask CallCountingHelper to populate trace and call count data. - call_counter_.PopulateCallData(json); + call_counter_.PopulateCallCounts(json); return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 66753c96ee..14edc75123 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -99,7 +99,7 @@ class CallCountingHelper { } // Common rendering of the call count data and last_call_started_timestamp. - void PopulateCallData(grpc_json* json); + void PopulateCallCounts(grpc_json* json); private: // testing peer friend. -- cgit v1.2.3 From fde951db9c6f87597faa7ae1b3d0f521ff1adb51 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Thu, 2 Aug 2018 20:55:00 -0700 Subject: Intecept recv_trailing in client_channel for channelz --- .../ext/filters/client_channel/client_channel.cc | 87 +++++++++++++++++++--- src/core/lib/channel/connected_channel.cc | 12 +-- src/core/lib/surface/call.cc | 10 ++- test/core/end2end/tests/channelz.cc | 3 + 4 files changed, 94 insertions(+), 18 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index f4d5596270..c3669189f4 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -923,6 +923,10 @@ typedef struct client_channel_call_data { grpc_closure pick_closure; grpc_closure pick_cancel_closure; + grpc_closure recv_trailing_metadata_ready_channelz; + grpc_closure* original_recv_trailing_metadata; + // metadata_batch recv_trailing_metadata_channelz; + grpc_polling_entity* pollent; bool pollent_added_to_interested_parties; @@ -984,6 +988,14 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem); static void on_complete(void* arg, grpc_error* error); static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored); static void start_pick_locked(void* arg, grpc_error* ignored); +template +static pending_batch* pending_batch_find(grpc_call_element* elem, + const char* log_message, + Predicate predicate); +static void get_call_status(grpc_call_element* elem, + grpc_metadata_batch* md_batch, grpc_error* error, + grpc_status_code* status, + grpc_mdelem** server_pushback_md); // // send op data caching @@ -1258,6 +1270,59 @@ static void resume_pending_batch_in_call_combiner(void* arg, grpc_subchannel_call_process_op(subchannel_call, batch); } +static void recv_trailing_metadata_ready_channelz(void* arg, + grpc_error* error) { + grpc_call_element* elem = static_cast(arg); + channel_data* chand = static_cast(elem->channel_data); + call_data* calld = static_cast(elem->call_data); + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: got recv_trailing_metadata_ready_channelz, " + "error=%s", + chand, calld, grpc_error_string(error)); + } + // find the right pending batch. + pending_batch* pending = pending_batch_find( + elem, "invoking recv_trailing_metadata_channelz for", + [](grpc_transport_stream_op_batch* batch) { + return batch->recv_trailing_metadata && + batch->payload->recv_trailing_metadata + .recv_trailing_metadata_ready != nullptr; + }); + grpc_status_code status = GRPC_STATUS_OK; + grpc_metadata_batch* md_batch = + pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata; + get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); + grpc_core::channelz::SubchannelNode* channelz_subchannel = + calld->pick.connected_subchannel->channelz_subchannel(); + GPR_ASSERT(channelz_subchannel != nullptr); + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); + } + pending->batch = nullptr; + GRPC_CLOSURE_SCHED(calld->original_recv_trailing_metadata, error); +} + +static bool maybe_intercept_recv_trailing_for_channelz( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { + call_data* calld = static_cast(elem->call_data); + // only add interceptor is channelz is enabled. + if (calld->pick.connected_subchannel->channelz_subchannel() != nullptr) { + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, + recv_trailing_metadata_ready_channelz, elem, + grpc_schedule_on_exec_ctx); + calld->original_recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready_channelz; + return true; + } else { + return false; + } +} + // This is called via the call combiner, so access to calld is synchronized. static void pending_batches_resume(grpc_call_element* elem) { channel_data* chand = static_cast(elem->channel_data); @@ -1282,13 +1347,17 @@ static void pending_batches_resume(grpc_call_element* elem) { pending_batch* pending = &calld->pending_batches[i]; grpc_transport_stream_op_batch* batch = pending->batch; if (batch != nullptr) { + bool intercepted = + maybe_intercept_recv_trailing_for_channelz(elem, batch); batch->handler_private.extra_arg = calld->subchannel_call; GRPC_CLOSURE_INIT(&batch->handler_private.closure, resume_pending_batch_in_call_combiner, batch, grpc_schedule_on_exec_ctx); closures.Add(&batch->handler_private.closure, GRPC_ERROR_NONE, "pending_batches_resume"); - pending_batch_clear(calld, pending); + if (!intercepted) { + pending_batch_clear(calld, pending); + } } } // Note: This will release the call combiner. @@ -1768,22 +1837,20 @@ static void recv_message_ready(void* arg, grpc_error* error) { // // Sets *status and *server_pushback_md based on batch_data and error. -static void get_call_status(subchannel_batch_data* batch_data, - grpc_error* error, grpc_status_code* status, +static void get_call_status(grpc_call_element* elem, + grpc_metadata_batch* md_batch, grpc_error* error, + grpc_status_code* status, grpc_mdelem** server_pushback_md) { - grpc_call_element* elem = batch_data->elem; call_data* calld = static_cast(elem->call_data); if (error != GRPC_ERROR_NONE) { grpc_error_get_status(error, calld->deadline, status, nullptr, nullptr, nullptr); } else { - grpc_metadata_batch* md_batch = - batch_data->batch.payload->recv_trailing_metadata - .recv_trailing_metadata; GPR_ASSERT(md_batch->idx.named.grpc_status != nullptr); *status = grpc_get_status_code_from_metadata(md_batch->idx.named.grpc_status->md); - if (md_batch->idx.named.grpc_retry_pushback_ms != nullptr) { + if (server_pushback_md != nullptr && + md_batch->idx.named.grpc_retry_pushback_ms != nullptr) { *server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md; } } @@ -1956,7 +2023,9 @@ static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { // Get the call's status and check for server pushback metadata. grpc_status_code status = GRPC_STATUS_OK; grpc_mdelem* server_pushback_md = nullptr; - get_call_status(batch_data, GRPC_ERROR_REF(error), &status, + grpc_metadata_batch* md_batch = + batch_data->batch.payload->recv_trailing_metadata.recv_trailing_metadata; + get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, &server_pushback_md); grpc_core::channelz::SubchannelNode* channelz_subchannel = calld->pick.connected_subchannel->channelz_subchannel(); diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc index e2ea334ded..90a0254663 100644 --- a/src/core/lib/channel/connected_channel.cc +++ b/src/core/lib/channel/connected_channel.cc @@ -104,18 +104,18 @@ static void con_start_transport_stream_op_batch( if (batch->recv_initial_metadata) { callback_state* state = &calld->recv_initial_metadata_ready; intercept_callback( - calld, state, false, "recv_initial_metadata_ready", + calld, state, false, "connected_recv_initial_metadata_ready", &batch->payload->recv_initial_metadata.recv_initial_metadata_ready); } if (batch->recv_message) { callback_state* state = &calld->recv_message_ready; - intercept_callback(calld, state, false, "recv_message_ready", + intercept_callback(calld, state, false, "connected_recv_message_ready", &batch->payload->recv_message.recv_message_ready); } if (batch->recv_trailing_metadata) { callback_state* state = &calld->recv_trailing_metadata_ready; intercept_callback( - calld, state, false, "recv_trailing_metadata_ready", + calld, state, false, "connected_recv_trailing_metadata_ready", &batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready); } if (batch->cancel_stream) { @@ -126,11 +126,13 @@ static void con_start_transport_stream_op_batch( // closure for each one. callback_state* state = static_cast(gpr_malloc(sizeof(*state))); - intercept_callback(calld, state, true, "on_complete (cancel_stream)", + intercept_callback(calld, state, true, + "connected_on_complete (cancel_stream)", &batch->on_complete); } else if (batch->on_complete != nullptr) { callback_state* state = get_state_for_batch(calld, batch); - intercept_callback(calld, state, false, "on_complete", &batch->on_complete); + intercept_callback(calld, state, false, "connected_on_complete", + &batch->on_complete); } grpc_transport_perform_stream_op( chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), batch); diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 26dd361e0d..859915affb 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1422,7 +1422,7 @@ static void receiving_stream_ready_in_call_combiner(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_message_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "call_recv_message_ready"); receiving_stream_ready(bctlp, error); } @@ -1507,7 +1507,8 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_initial_metadata_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, + "call_recv_initial_metadata_ready"); add_batch_error(bctl, GRPC_ERROR_REF(error), false); if (error == GRPC_ERROR_NONE) { @@ -1558,7 +1559,8 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, + "call_recv_trailing_metadata_ready"); add_batch_error(bctl, GRPC_ERROR_REF(error), false); grpc_metadata_batch* md = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; @@ -1569,7 +1571,7 @@ static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { static void finish_batch(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "call_on_complete"); add_batch_error(bctl, GRPC_ERROR_REF(error), false); finish_batch_step(bctl); } diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 754c3d3741..562822c537 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -243,6 +243,9 @@ static void test_channelz(grpc_end2end_test_config config) { json = grpc_channelz_get_subchannel(2); gpr_log(GPR_INFO, "%s", json); + GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); + GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); + GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); gpr_free(json); end_test(&f); -- cgit v1.2.3 From 0db2b830eb95c12975cb69b945f837194f38d96c Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 3 Aug 2018 11:24:18 -0400 Subject: Refactor rendering to use template method pattern --- .../client_channel/client_channel_channelz.cc | 39 ---------------------- .../client_channel/client_channel_channelz.h | 9 +++-- src/core/lib/channel/channelz.cc | 7 ++++ src/core/lib/channel/channelz.h | 20 ++++++----- 4 files changed, 23 insertions(+), 52 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 06b4d2ab95..7e8f59bcd3 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -98,45 +98,6 @@ void ClientChannelNode::PopulateChildRefs(grpc_json* json) { } } -grpc_json* ClientChannelNode::RenderJson() { - // We need to track these three json objects to build our object - grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); - grpc_json* json = top_level_json; - grpc_json* json_iterator = nullptr; - // create and fill the ref child - json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, - GRPC_JSON_OBJECT, false); - json = json_iterator; - json_iterator = nullptr; - json_iterator = grpc_json_add_number_string_child(json, json_iterator, - "channelId", uuid()); - // reset json iterators to top level object - json = top_level_json; - json_iterator = nullptr; - // create and fill the data child. - grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, - GRPC_JSON_OBJECT, false); - json = data; - json_iterator = nullptr; - PopulateConnectivityState(json); - // populate the target. - GPR_ASSERT(target_view() != nullptr); - grpc_json_create_child(nullptr, json, "target", target_view(), - GRPC_JSON_STRING, false); - // fill in the channel trace if applicable - grpc_json* trace_json = trace()->RenderJson(); - if (trace_json != nullptr) { - trace_json->key = "trace"; // this object is named trace in channelz.proto - grpc_json_link_child(json, trace_json, nullptr); - } - // ask CallCountingHelper to populate trace and call count data. - call_counter()->PopulateCallCounts(json); - // reset to the top level - json = top_level_json; - PopulateChildRefs(json); - return top_level_json; -} - grpc_arg ClientChannelNode::CreateChannelArg() { return grpc_channel_arg_pointer_create( const_cast(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC), diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 9a3fc1d6f1..a9e98deedb 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -50,7 +50,10 @@ class ClientChannelNode : public ChannelNode { bool is_top_level_channel); virtual ~ClientChannelNode() {} - grpc_json* RenderJson() override; + // Overriding template methods from ChannelNode to render information that + // only ClientChannelNode knows about. + void PopulateConnectivityState(grpc_json* json) override; + void PopulateChildRefs(grpc_json* json) override; // Helper to create a channel arg to ensure this type of ChannelNode is // created. @@ -58,10 +61,6 @@ class ClientChannelNode : public ChannelNode { private: grpc_channel_element* client_channel_; - - // helpers - void PopulateConnectivityState(grpc_json* json); - void PopulateChildRefs(grpc_json* json); }; // Handles channelz bookkeeping for sockets diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 1ac7bd3976..9f54850002 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -117,6 +117,9 @@ grpc_json* ChannelNode::RenderJson() { GRPC_JSON_OBJECT, false); json = data; json_iterator = nullptr; + // template method. Child classes may override this to add their specific + // functionality. + PopulateConnectivityState(json); // populate the target. GPR_ASSERT(target_.get() != nullptr); grpc_json_create_child(nullptr, json, "target", target_.get(), @@ -129,6 +132,10 @@ grpc_json* ChannelNode::RenderJson() { } // ask CallCountingHelper to populate trace and call count data. call_counter_.PopulateCallCounts(json); + json = top_level_json; + // template method. Child classes may override this to add their specific + // functionality. + PopulateChildRefs(json); return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 14edc75123..e2cef233e6 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -124,6 +124,18 @@ class ChannelNode : public BaseNode { grpc_json* RenderJson() override; + // template methods. RenderJSON uses these methods to render its JSON + // representation. These are virtual so that children classes may provide + // their specific mechanism for populating these parts of the channelz + // object. + // + // ChannelNode does not have a notion of connectivity state or child refs, + // so it leaves these implementations blank. + // + // This is utilizing the template method design pattern. + virtual void PopulateConnectivityState(grpc_json* json) {} + virtual void PopulateChildRefs(grpc_json* json) {} + void MarkChannelDestroyed() { GPR_ASSERT(channel_ != nullptr); channel_ = nullptr; @@ -144,14 +156,6 @@ class ChannelNode : public BaseNode { void RecordCallFailed() { call_counter_.RecordCallFailed(); } void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } - protected: - // provides view of target for child. - char* target_view() { return target_.get(); } - // provides access to call_counter_ for child. - CallCountingHelper* call_counter() { return &call_counter_; } - // provides access to channel trace for child. - ChannelTrace* trace() { return &trace_; } - private: // to allow the channel trace test to access trace(); friend class testing::ChannelNodePeer; -- cgit v1.2.3 From e2a87dac6975b3cbf6e434e1bb5112269043653e Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 3 Aug 2018 11:31:19 -0400 Subject: Add some comments --- src/core/ext/filters/client_channel/client_channel.cc | 8 ++++++-- src/core/ext/filters/client_channel/client_channel_channelz.h | 3 ++- src/core/lib/channel/channelz.h | 3 ++- test/core/end2end/tests/channelz.cc | 7 ------- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index c3669189f4..4263e791c4 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -925,7 +925,6 @@ typedef struct client_channel_call_data { grpc_closure recv_trailing_metadata_ready_channelz; grpc_closure* original_recv_trailing_metadata; - // metadata_batch recv_trailing_metadata_channelz; grpc_polling_entity* pollent; bool pollent_added_to_interested_parties; @@ -1305,6 +1304,9 @@ static void recv_trailing_metadata_ready_channelz(void* arg, GRPC_CLOSURE_SCHED(calld->original_recv_trailing_metadata, error); } +// If channelz is enabled, intercept recv_trailing so that we may check the +// status and associate it to a subchannel. +// Returns true if callback was intercepted, false otherwise. static bool maybe_intercept_recv_trailing_for_channelz( grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { call_data* calld = static_cast(elem->call_data); @@ -1355,6 +1357,7 @@ static void pending_batches_resume(grpc_call_element* elem) { grpc_schedule_on_exec_ctx); closures.Add(&batch->handler_private.closure, GRPC_ERROR_NONE, "pending_batches_resume"); + // Only clear if we haven't intercepted anything. if (!intercepted) { pending_batch_clear(calld, pending); } @@ -1836,7 +1839,8 @@ static void recv_message_ready(void* arg, grpc_error* error) { // recv_trailing_metadata handling // -// Sets *status and *server_pushback_md based on batch_data and error. +// Sets *status and *server_pushback_md based on md_batch and error. +// Only sets *server_pushback_md if server_pushback_md != nullptr. static void get_call_status(grpc_call_element* elem, grpc_metadata_batch* md_batch, grpc_error* error, grpc_status_code* status, diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index a9e98deedb..8ce331e529 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -83,7 +83,8 @@ class SubchannelNode : public BaseNode { void AddTraceEventWithReference(ChannelTrace::Severity severity, grpc_slice data, RefCountedPtr referenced_channel) { - trace_.AddTraceEventWithReference(severity, data, referenced_channel); + trace_.AddTraceEventWithReference(severity, data, + std::move(referenced_channel)); } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index e2cef233e6..bd2735929c 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -150,7 +150,8 @@ class ChannelNode : public BaseNode { void AddTraceEventWithReference(ChannelTrace::Severity severity, grpc_slice data, RefCountedPtr referenced_channel) { - trace_.AddTraceEventWithReference(severity, data, referenced_channel); + trace_.AddTraceEventWithReference(severity, data, + std::move(referenced_channel)); } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 562822c537..533703a2be 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -241,13 +241,6 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); - json = grpc_channelz_get_subchannel(2); - gpr_log(GPR_INFO, "%s", json); - GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); - GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); - GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); - gpr_free(json); - end_test(&f); config.tear_down_data(&f); } -- cgit v1.2.3 From 3aa987a29a02f59116f3e7d07cfa6a4835c211b4 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 13 Aug 2018 23:43:48 -0700 Subject: Add channelz server support --- include/grpc/grpc.h | 3 + src/core/lib/channel/channelz.cc | 41 +++++++++++++ src/core/lib/channel/channelz.h | 28 +++++++-- src/core/lib/channel/channelz_registry.cc | 40 +++++++++++++ src/core/lib/channel/channelz_registry.h | 7 +++ src/core/lib/surface/call.cc | 54 +++++++++++------ src/core/lib/surface/call.h | 1 + src/core/lib/surface/channel.cc | 7 ++- src/core/lib/surface/server.cc | 24 ++++++++ src/core/lib/surface/server.h | 4 ++ test/core/channel/channelz_test.cc | 90 ++++++++++++++++++++++++++++- test/core/end2end/tests/channelz.cc | 67 ++++++++++++++------- test/cpp/util/channel_trace_proto_helper.cc | 9 +++ test/cpp/util/channel_trace_proto_helper.h | 2 + 14 files changed, 331 insertions(+), 46 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 412778f7f7..cb32808c56 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -483,6 +483,9 @@ GRPCAPI const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void); The returned string is allocated and must be freed by the application. */ GRPCAPI char* grpc_channelz_get_top_channels(intptr_t start_channel_id); +/* Gets all servers that exist in the process. */ +GRPCAPI char* grpc_channelz_get_servers(intptr_t start_channel_id); + /* Returns a single Channel, or else a NOT_FOUND code. The returned string is allocated and must be freed by the application. */ GRPCAPI char* grpc_channelz_get_channel(intptr_t channel_id); diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 9f54850002..bb79005654 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -48,6 +48,7 @@ BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); } char* BaseNode::RenderJsonString() { grpc_json* json = RenderJson(); + GPR_ASSERT(json != nullptr); char* json_str = grpc_json_dump_to_string(json, 0); grpc_json_destroy(json); return json_str; @@ -146,5 +147,45 @@ RefCountedPtr ChannelNode::MakeChannelNode( channel, channel_tracer_max_nodes, is_top_level_channel); } +ServerNode::ServerNode(size_t channel_tracer_max_nodes) + : BaseNode(EntityType::kServer), trace_(channel_tracer_max_nodes) {} + +ServerNode::~ServerNode() {} + +grpc_json* ServerNode::RenderJson() { + // We need to track these three json objects to build our object + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + // create and fill the ref child + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "serverId", uuid()); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + // fill in the channel trace if applicable + grpc_json* trace_json = trace_.RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter_.PopulateCallCounts(json); + json = top_level_json; + // template method. Child classes may override this to add their specific + // functionality. + PopulateSockets(json); + return top_level_json; +} + } // namespace channelz } // namespace grpc_core diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index bd2735929c..9a448d3b38 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -167,12 +167,32 @@ class ChannelNode : public BaseNode { }; // Handles channelz bookkeeping for servers -// TODO(ncteisen): implement in subsequent PR. class ServerNode : public BaseNode { public: - explicit ServerNode(size_t channel_tracer_max_nodes) - : BaseNode(EntityType::kServer) {} - ~ServerNode() override {} + explicit ServerNode(size_t channel_tracer_max_nodes); + ~ServerNode() override; + + grpc_json* RenderJson() override; + + void PopulateSockets(grpc_json* json) {} + + // proxy methods to composed classes. + void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { + trace_.AddTraceEvent(severity, data); + } + void AddTraceEventWithReference(ChannelTrace::Severity severity, + grpc_slice data, + RefCountedPtr referenced_channel) { + trace_.AddTraceEventWithReference(severity, data, + std::move(referenced_channel)); + } + void RecordCallStarted() { call_counter_.RecordCallStarted(); } + void RecordCallFailed() { call_counter_.RecordCallFailed(); } + void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } + + private: + CallCountingHelper call_counter_; + ChannelTrace trace_; }; // Handles channelz bookkeeping for sockets diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index d2c403cc1b..285f641ba9 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -111,6 +111,42 @@ char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { return json_str; } +char* ChannelzRegistry::InternalGetServers(intptr_t start_server_id) { + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + InlinedVector servers; + // 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_server_id == 0 ? 0 : start_server_id - 1; + for (size_t i = start_idx; i < entities_.size(); ++i) { + if (entities_[i] != nullptr && + entities_[i]->type() == + grpc_core::channelz::BaseNode::EntityType::kServer) { + servers.push_back(entities_[i]); + } + } + if (!servers.empty()) { + // create list of servers + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "server", nullptr, GRPC_JSON_ARRAY, false); + for (size_t i = 0; i < servers.size(); ++i) { + grpc_json* server_json = servers[i]->RenderJson(); + json_iterator = + grpc_json_link_child(array_parent, server_json, json_iterator); + } + } + // 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); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} + } // namespace channelz } // namespace grpc_core @@ -119,6 +155,10 @@ char* grpc_channelz_get_top_channels(intptr_t start_channel_id) { start_channel_id); } +char* grpc_channelz_get_servers(intptr_t start_server_id) { + return grpc_core::channelz::ChannelzRegistry::GetServers(start_server_id); +} + char* grpc_channelz_get_channel(intptr_t channel_id) { grpc_core::channelz::BaseNode* channel_node = grpc_core::channelz::ChannelzRegistry::Get(channel_id); diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h index 142c039220..d0d660600d 100644 --- a/src/core/lib/channel/channelz_registry.h +++ b/src/core/lib/channel/channelz_registry.h @@ -52,6 +52,12 @@ class ChannelzRegistry { return Default()->InternalGetTopChannels(start_channel_id); } + // Returns the allocated JSON string that represents the proto + // GetServersResponse as per channelz.proto. + static char* GetServers(intptr_t start_server_id) { + return Default()->InternalGetServers(start_server_id); + } + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE @@ -74,6 +80,7 @@ class ChannelzRegistry { BaseNode* InternalGet(intptr_t uuid); char* InternalGetTopChannels(intptr_t start_channel_id); + char* InternalGetServers(intptr_t start_server_id); // protects entities_ and uuid_ gpr_mu mu_; diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index d81e33054a..d32281e076 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -48,6 +48,7 @@ #include "src/core/lib/surface/call_test_only.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/completion_queue.h" +#include "src/core/lib/surface/server.h" #include "src/core/lib/surface/validate_metadata.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/metadata.h" @@ -166,6 +167,8 @@ struct grpc_call { grpc_completion_queue* cq; grpc_polling_entity pollent; grpc_channel* channel; + // backpointer to owning server if this is a server side call. + grpc_server* server; gpr_timespec start_time; /* parent_call* */ gpr_atm parent_call_atm; child_call* child; @@ -362,14 +365,11 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, /* Always support no compression */ GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_MESSAGE_COMPRESS_NONE); call->is_client = args->server_transport_data == nullptr; - if (call->is_client) { - GRPC_STATS_INC_CLIENT_CALLS_CREATED(); - } else { - GRPC_STATS_INC_SERVER_CALLS_CREATED(); - } call->stream_op_payload.context = call->context; grpc_slice path = grpc_empty_slice(); if (call->is_client) { + GRPC_STATS_INC_CLIENT_CALLS_CREATED(); + call->server = nullptr; GPR_ASSERT(args->add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT); for (i = 0; i < args->add_initial_metadata_count; i++) { @@ -383,6 +383,8 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, call->send_extra_metadata_count = static_cast(args->add_initial_metadata_count); } else { + GRPC_STATS_INC_SERVER_CALLS_CREATED(); + call->server = args->server; GPR_ASSERT(args->add_initial_metadata_count == 0); call->send_extra_metadata_count = 0; } @@ -486,10 +488,18 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, &call->pollent); } - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(call->channel); - if (channelz_channel != nullptr) { - channelz_channel->RecordCallStarted(); + if (call->is_client) { + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); + if (channelz_channel != nullptr) { + channelz_channel->RecordCallStarted(); + } + } else { + grpc_core::channelz::ServerNode* channelz_server = + grpc_server_get_channelz_node(call->server); + if (channelz_server != nullptr) { + channelz_server->RecordCallStarted(); + } } grpc_slice_unref_internal(path); @@ -1263,18 +1273,26 @@ static void post_batch_completion(batch_control* bctl) { call->final_op.client.status, call->final_op.client.status_details, call->final_op.client.error_string); + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); + if (channelz_channel != nullptr) { + if (*call->final_op.client.status != GRPC_STATUS_OK) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } } else { get_final_status(call, set_cancelled_value, call->final_op.server.cancelled, nullptr, nullptr); - } - // Record channelz data for the channel. - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(call->channel); - if (channelz_channel != nullptr) { - if (*call->final_op.client.status != GRPC_STATUS_OK) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); + grpc_core::channelz::ServerNode* channelz_server = + grpc_server_get_channelz_node(call->server); + if (channelz_server != nullptr) { + if (*call->final_op.server.cancelled) { + channelz_server->RecordCallFailed(); + } else { + channelz_server->RecordCallSucceeded(); + } } } GRPC_ERROR_UNREF(error); diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index b3b06059d4..b34260505a 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -33,6 +33,7 @@ typedef void (*grpc_ioreq_completion_func)(grpc_call* call, int success, typedef struct grpc_call_create_args { grpc_channel* channel; + grpc_server* server; grpc_call* parent; uint32_t propagation_mask; diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 10d90e1406..815d302577 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -166,10 +166,11 @@ grpc_channel* grpc_channel_create_with_builder( } grpc_channel_args_destroy(args); - if (channelz_enabled) { - bool is_top_level_channel = channel->is_client && !internal_channel; + // only track client channels since server channels are held in the + // grpc_server channel. + if (channelz_enabled && channel->is_client) { channel->channelz_channel = channel_node_create_func( - channel, channel_tracer_max_nodes, is_top_level_channel); + channel, channel_tracer_max_nodes, !internal_channel); channel->channelz_channel->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index cb34def740..8e9d8ec98c 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -219,6 +219,8 @@ struct grpc_server { /** when did we print the last shutdown progress message */ gpr_timespec last_shutdown_message_time; + + grpc_core::RefCountedPtr channelz_server; }; #define SERVER_FROM_CALL_ELEM(elem) \ @@ -364,6 +366,7 @@ static void server_ref(grpc_server* server) { static void server_delete(grpc_server* server) { registered_method* rm; size_t i; + server->channelz_server.reset(); grpc_channel_args_destroy(server->channel_args); gpr_mu_destroy(&server->mu_global); gpr_mu_destroy(&server->mu_call); @@ -779,6 +782,7 @@ static void accept_stream(void* cd, grpc_transport* transport, args.channel = chand->channel; args.server_transport_data = transport_server_data; args.send_deadline = GRPC_MILLIS_INF_FUTURE; + args.server = chand->server; grpc_call* call; grpc_error* error = grpc_call_create(&args, &call); grpc_call_element* elem = @@ -941,6 +945,7 @@ void grpc_server_register_completion_queue(grpc_server* server, } grpc_server* grpc_server_create(const grpc_channel_args* args, void* reserved) { + grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved)); grpc_server* server = @@ -957,6 +962,20 @@ grpc_server* grpc_server_create(const grpc_channel_args* args, void* reserved) { server->channel_args = grpc_channel_args_copy(args); + const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_ENABLE_CHANNELZ); + if (grpc_channel_arg_get_bool(arg, false)) { + arg = grpc_channel_args_find(args, + GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE); + size_t trace_events_per_node = + grpc_channel_arg_get_integer(arg, {0, 0, INT_MAX}); + server->channelz_server = + grpc_core::MakeRefCounted( + trace_events_per_node); + server->channelz_server->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Server created")); + } + return server; } @@ -1459,3 +1478,8 @@ int grpc_server_has_open_connections(grpc_server* server) { gpr_mu_unlock(&server->mu_global); return r; } + +grpc_core::channelz::ServerNode* grpc_server_get_channelz_node( + grpc_server* server) { + return server->channelz_server.get(); +} diff --git a/src/core/lib/surface/server.h b/src/core/lib/surface/server.h index c617cc223e..0196743ff9 100644 --- a/src/core/lib/surface/server.h +++ b/src/core/lib/surface/server.h @@ -23,6 +23,7 @@ #include #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/transport/transport.h" @@ -46,6 +47,9 @@ void grpc_server_setup_transport(grpc_server* server, grpc_transport* transport, grpc_pollset* accepting_pollset, const grpc_channel_args* args); +grpc_core::channelz::ServerNode* grpc_server_get_channelz_node( + grpc_server* server); + const grpc_channel_args* grpc_server_get_channel_args(grpc_server* server); int grpc_server_has_open_connections(grpc_server* server); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 8fa46a18da..f947617d0f 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -31,6 +31,7 @@ #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/json/json.h" #include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" #include "test/core/util/test_config.h" #include "test/cpp/util/channel_trace_proto_helper.h" @@ -102,6 +103,25 @@ void ValidateGetTopChannels(size_t expected_channels) { gpr_free(core_api_json_str); } +void ValidateGetServers(size_t expected_servers) { + char* json_str = ChannelzRegistry::GetServers(0); + grpc::testing::ValidateGetServersResponseProtoJsonTranslation(json_str); + grpc_json* parsed_json = grpc_json_parse_string(json_str); + // This check will naturally have to change when we support pagination. + // tracked: https://github.com/grpc/grpc/issues/16019. + ValidateJsonArraySize(parsed_json, "server", expected_servers); + grpc_json* end = GetJsonChild(parsed_json, "end"); + ASSERT_NE(end, nullptr); + EXPECT_EQ(end->type, GRPC_JSON_TRUE); + grpc_json_destroy(parsed_json); + gpr_free(json_str); + // also check that the core API formats this correctly + char* core_api_json_str = grpc_channelz_get_servers(0); + grpc::testing::ValidateGetServersResponseProtoJsonTranslation( + core_api_json_str); + gpr_free(core_api_json_str); +} + class ChannelFixture { public: ChannelFixture(int max_trace_nodes = 0) { @@ -124,6 +144,27 @@ class ChannelFixture { grpc_channel* channel_; }; +class ServerFixture { + public: + ServerFixture(int max_trace_nodes = 0) { + grpc_arg server_a[2]; + server_a[0] = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE), + max_trace_nodes); + server_a[1] = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_CHANNELZ), true); + grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; + server_ = grpc_server_create(&server_args, nullptr); + } + + ~ServerFixture() { grpc_server_destroy(server_); } + + grpc_server* server() { return server_; } + + private: + grpc_server* server_; +}; + struct validate_channel_data_args { int64_t calls_started; int64_t calls_failed; @@ -163,6 +204,13 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { gpr_free(core_api_json_str); } +void ValidateServer(ServerNode* server, validate_channel_data_args args) { + char* json_str = server->RenderJsonString(); + grpc::testing::ValidateServerProtoJsonTranslation(json_str); + ValidateCounters(json_str, args); + gpr_free(json_str); +} + grpc_millis GetLastCallStartedMillis(CallCountingHelper* channel) { CallCountingHelperPeer peer(channel); return peer.last_call_started_millis(); @@ -237,7 +285,7 @@ TEST_P(ChannelzChannelTest, LastCallStartedMillis) { EXPECT_NE(millis1, millis4); } -TEST(ChannelzGetTopChannelsTest, BasicTest) { +TEST(ChannelzGetTopChannelsTest, BasicGetTopChannelsTest) { grpc_core::ExecCtx exec_ctx; ChannelFixture channel; ValidateGetTopChannels(1); @@ -273,9 +321,49 @@ TEST(ChannelzGetTopChannelsTest, InternalChannelTest) { grpc_channel_destroy(internal_channel); } +class ChannelzServerTest : public ::testing::TestWithParam {}; + +TEST_P(ChannelzServerTest, BasicServerAPIFunctionality) { + grpc_core::ExecCtx exec_ctx; + ServerFixture server(10); + ServerNode* channelz_server = grpc_server_get_channelz_node(server.server()); + channelz_server->RecordCallStarted(); + channelz_server->RecordCallFailed(); + channelz_server->RecordCallSucceeded(); + ValidateServer(channelz_server, {1, 1, 1}); + channelz_server->RecordCallStarted(); + channelz_server->RecordCallFailed(); + channelz_server->RecordCallSucceeded(); + channelz_server->RecordCallStarted(); + channelz_server->RecordCallFailed(); + channelz_server->RecordCallSucceeded(); + ValidateServer(channelz_server, {3, 3, 3}); +} + +TEST(ChannelzGetServersTest, BasicGetServersTest) { + grpc_core::ExecCtx exec_ctx; + ServerFixture server; + ValidateGetServers(1); +} + +TEST(ChannelzGetServersTest, NoServersTest) { + grpc_core::ExecCtx exec_ctx; + ValidateGetServers(0); +} + +TEST(ChannelzGetServersTest, ManyServersTest) { + grpc_core::ExecCtx exec_ctx; + ServerFixture servers[10]; + (void)servers; // suppress unused variable error + ValidateGetServers(10); +} + INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest, ::testing::Values(0, 1, 2, 6, 10, 15)); +INSTANTIATE_TEST_CASE_P(ChannelzServerTestSweep, ChannelzServerTest, + ::testing::Values(0, 1, 2, 6, 10, 15)); + } // namespace testing } // namespace channelz } // namespace grpc_core diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 533703a2be..f96c430b69 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -22,6 +22,7 @@ #include #include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" #include #include @@ -198,17 +199,21 @@ static void run_one_request(grpc_end2end_test_config config, static void test_channelz(grpc_end2end_test_config config) { grpc_end2end_test_fixture f; - grpc_arg client_a; - client_a.type = GRPC_ARG_INTEGER; - client_a.key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); - client_a.value.integer = true; - grpc_channel_args client_args = {1, &client_a}; + grpc_arg arg; + arg.type = GRPC_ARG_INTEGER; + arg.key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); + arg.value.integer = true; + grpc_channel_args args = {1, &arg}; - f = begin_test(config, "test_channelz", &client_args, nullptr); + f = begin_test(config, "test_channelz", &args, &args); grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(f.client); - GPR_ASSERT(channelz_channel != nullptr); + + grpc_core::channelz::ServerNode* channelz_server = + grpc_server_get_channelz_node(f.server); + GPR_ASSERT(channelz_server != nullptr); + char* json = channelz_channel->RenderJsonString(); GPR_ASSERT(json != nullptr); // nothing is present yet @@ -241,6 +246,18 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); + json = channelz_server->RenderJsonString(); + GPR_ASSERT(json != nullptr); + gpr_log(GPR_INFO, "%s", json); + GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); + GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); + GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); + // channel tracing is not enables, so these should not be preset. + GPR_ASSERT(nullptr == strstr(json, "\"trace\"")); + GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\"")); + GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); + gpr_free(json); + end_test(&f); config.tear_down_data(&f); } @@ -248,22 +265,24 @@ static void test_channelz(grpc_end2end_test_config config) { static void test_channelz_with_channel_trace(grpc_end2end_test_config config) { grpc_end2end_test_fixture f; - grpc_arg client_a[2]; - client_a[0].type = GRPC_ARG_INTEGER; - client_a[0].key = - const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE); - client_a[0].value.integer = 5; - client_a[1].type = GRPC_ARG_INTEGER; - client_a[1].key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); - client_a[1].value.integer = true; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; - - f = begin_test(config, "test_channelz_with_channel_trace", &client_args, - nullptr); + grpc_arg arg[2]; + arg[0].type = GRPC_ARG_INTEGER; + arg[0].key = const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE); + arg[0].value.integer = 5; + arg[1].type = GRPC_ARG_INTEGER; + arg[1].key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); + arg[1].value.integer = true; + grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; + + f = begin_test(config, "test_channelz_with_channel_trace", &args, &args); grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(f.client); - GPR_ASSERT(channelz_channel != nullptr); + + grpc_core::channelz::ServerNode* channelz_server = + grpc_server_get_channelz_node(f.server); + GPR_ASSERT(channelz_server != nullptr); + char* json = channelz_channel->RenderJsonString(); GPR_ASSERT(json != nullptr); gpr_log(GPR_INFO, "%s", json); @@ -272,6 +291,14 @@ static void test_channelz_with_channel_trace(grpc_end2end_test_config config) { GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); + json = channelz_server->RenderJsonString(); + GPR_ASSERT(json != nullptr); + gpr_log(GPR_INFO, "%s", json); + GPR_ASSERT(nullptr != strstr(json, "\"trace\"")); + GPR_ASSERT(nullptr != strstr(json, "\"description\":\"Server created\"")); + GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\"")); + gpr_free(json); + end_test(&f); config.tear_down_data(&f); } diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index e416a0375f..42a436d49b 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -86,5 +86,14 @@ void ValidateSubchannelProtoJsonTranslation(char* json_c_str) { VaidateProtoJsonTranslation(json_c_str); } +void ValidateServerProtoJsonTranslation(char* json_c_str) { + VaidateProtoJsonTranslation(json_c_str); +} + +void ValidateGetServersResponseProtoJsonTranslation(char* json_c_str) { + VaidateProtoJsonTranslation( + json_c_str); +} + } // namespace testing } // namespace grpc diff --git a/test/cpp/util/channel_trace_proto_helper.h b/test/cpp/util/channel_trace_proto_helper.h index a1ebbcd110..67c363e89b 100644 --- a/test/cpp/util/channel_trace_proto_helper.h +++ b/test/cpp/util/channel_trace_proto_helper.h @@ -27,6 +27,8 @@ void ValidateChannelProtoJsonTranslation(char* json_c_str); void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str); void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str); void ValidateSubchannelProtoJsonTranslation(char* json_c_str); +void ValidateServerProtoJsonTranslation(char* json_c_str); +void ValidateGetServersResponseProtoJsonTranslation(char* json_c_str); } // namespace testing } // namespace grpc -- cgit v1.2.3 From 85ff14dd16524b408bd30eb76d790be126aebb90 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 21 Aug 2018 10:11:53 -0700 Subject: Modify existing error child manipulation --- src/core/ext/filters/http/client/http_client_filter.cc | 9 ++------- src/core/ext/filters/http/server/http_server_filter.cc | 5 +++-- src/core/ext/filters/message_size/message_size_filter.cc | 3 ++- src/core/lib/iomgr/error.cc | 16 ++++++---------- src/core/lib/iomgr/error.h | 6 ------ src/core/lib/security/transport/server_auth_filter.cc | 2 +- src/core/lib/surface/call.cc | 4 +--- src/core/lib/surface/server.cc | 2 +- 8 files changed, 16 insertions(+), 31 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/http/client/http_client_filter.cc b/src/core/ext/filters/http/client/http_client_filter.cc index 04ac4ac947..f44dc032a7 100644 --- a/src/core/ext/filters/http/client/http_client_filter.cc +++ b/src/core/ext/filters/http/client/http_client_filter.cc @@ -164,13 +164,8 @@ static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) { } else { GRPC_ERROR_REF(error); } - if (calld->recv_initial_metadata_error != GRPC_ERROR_NONE) { - if (error == GRPC_ERROR_NONE) { - error = GRPC_ERROR_REF(calld->recv_initial_metadata_error); - } else if (error != calld->recv_initial_metadata_error) { - error = grpc_error_add_child(error, calld->recv_initial_metadata_error); - } - } + error = grpc_error_add_child( + error, GRPC_ERROR_REF(calld->recv_initial_metadata_error)); GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, error); } diff --git a/src/core/ext/filters/http/server/http_server_filter.cc b/src/core/ext/filters/http/server/http_server_filter.cc index c66f531a89..926afeec84 100644 --- a/src/core/ext/filters/http/server/http_server_filter.cc +++ b/src/core/ext/filters/http/server/http_server_filter.cc @@ -321,8 +321,9 @@ static void hs_recv_message_ready(void* user_data, grpc_error* err) { static void hs_recv_trailing_metadata_ready(void* user_data, grpc_error* err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); - err = - grpc_error_maybe_add_child(err, calld->recv_initial_metadata_ready_error); + err = grpc_error_add_child( + GRPC_ERROR_REF(err), + GRPC_ERROR_REF(calld->recv_initial_metadata_ready_error)); GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err); } diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc index b5ca1be804..a5f5f8e2ff 100644 --- a/src/core/ext/filters/message_size/message_size_filter.cc +++ b/src/core/ext/filters/message_size/message_size_filter.cc @@ -155,7 +155,8 @@ static void recv_message_ready(void* user_data, grpc_error* error) { static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); - error = grpc_error_maybe_add_child(error, calld->error); + error = + grpc_error_add_child(GRPC_ERROR_REF(error), GRPC_ERROR_REF(calld->error)); // Invoke the next callback. GRPC_CLOSURE_RUN(calld->next_recv_trailing_metadata_ready, error); } diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc index 226b44c46d..dfd063a695 100644 --- a/src/core/lib/iomgr/error.cc +++ b/src/core/lib/iomgr/error.cc @@ -513,22 +513,18 @@ bool grpc_error_get_str(grpc_error* err, grpc_error_strs which, grpc_error* grpc_error_add_child(grpc_error* src, grpc_error* child) { GPR_TIMER_SCOPE("grpc_error_add_child", 0); - grpc_error* new_err = copy_error_and_unref(src); - internal_add_error(&new_err, child); - return new_err; -} - -grpc_error* grpc_error_maybe_add_child(grpc_error* src, grpc_error* child) { if (src != GRPC_ERROR_NONE) { if (child == GRPC_ERROR_NONE) { - return GRPC_ERROR_REF(src); + return src; } else if (child != src) { - return grpc_error_add_child(src, GRPC_ERROR_REF(child)); + grpc_error* new_err = copy_error_and_unref(src); + internal_add_error(&new_err, child); + return new_err; } else { - return GRPC_ERROR_REF(src); + return src; } } else { - return GRPC_ERROR_REF(child); + return child; } } diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h index 4f65c447fd..e5369695c9 100644 --- a/src/core/lib/iomgr/error.h +++ b/src/core/lib/iomgr/error.h @@ -187,12 +187,6 @@ bool grpc_error_get_str(grpc_error* error, grpc_error_strs which, /// child error. grpc_error* grpc_error_add_child(grpc_error* src, grpc_error* child) GRPC_MUST_USE_RESULT; -/// Produce an error that is a combination of both src and child. -// If src or child, is GRPC_ERROR_NONE, a new reference to the other error is -// returned. Otherwise, a new error with src as the parent and child as the -// child is returned. -grpc_error* grpc_error_maybe_add_child(grpc_error* src, - grpc_error* child) GRPC_MUST_USE_RESULT; grpc_error* grpc_os_error(const char* file, int line, int err, const char* call_name) GRPC_MUST_USE_RESULT; diff --git a/src/core/lib/security/transport/server_auth_filter.cc b/src/core/lib/security/transport/server_auth_filter.cc index 5f2ad261d2..552e70130a 100644 --- a/src/core/lib/security/transport/server_auth_filter.cc +++ b/src/core/lib/security/transport/server_auth_filter.cc @@ -191,7 +191,7 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { static void recv_trailing_metadata_ready(void* user_data, grpc_error* err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); - err = grpc_error_maybe_add_child(err, calld->error); + err = grpc_error_add_child(GRPC_ERROR_REF(err), GRPC_ERROR_REF(calld->error)); GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err); } diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 56c4562952..d2c14571d3 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -686,6 +686,7 @@ static void cancel_with_status(grpc_call* c, grpc_status_code status, } static void set_final_status(grpc_call* call, grpc_error* error) { + gpr_log(GPR_INFO, "set final status"); if (grpc_call_error_trace.enabled()) { gpr_log(GPR_DEBUG, "set_final_status %s", call->is_client ? "CLI" : "SVR"); gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); @@ -1650,9 +1651,6 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, grpc_slice_ref_internal( *op->data.send_status_from_server.status_details)); call->send_extra_metadata_count++; - char* msg = grpc_slice_to_c_string( - GRPC_MDVALUE(call->send_extra_metadata[1].md)); - gpr_free(msg); } grpc_error* status_error = op->data.send_status_from_server.status == GRPC_STATUS_OK diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index 4403caf044..521825ca69 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -737,7 +737,7 @@ static void server_recv_trailing_metadata_ready(void* user_data, grpc_error* err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); - err = grpc_error_maybe_add_child(err, calld->error); + err = grpc_error_add_child(GRPC_ERROR_REF(err), GRPC_ERROR_REF(calld->error)); GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, err); } -- cgit v1.2.3 From 97ceb5962cc5317b262aa60b8863c7df7799f640 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 21 Aug 2018 10:42:22 -0700 Subject: Remove unwanted logs and also add status details to status error --- src/core/lib/surface/call.cc | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index d2c14571d3..d0f418220b 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -686,7 +686,6 @@ static void cancel_with_status(grpc_call* c, grpc_status_code status, } static void set_final_status(grpc_call* call, grpc_error* error) { - gpr_log(GPR_INFO, "set final status"); if (grpc_call_error_trace.enabled()) { gpr_log(GPR_DEBUG, "set_final_status %s", call->is_client ? "CLI" : "SVR"); gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); @@ -1645,13 +1644,6 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, call->send_extra_metadata_count = 1; call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem( call->channel, op->data.send_status_from_server.status); - if (op->data.send_status_from_server.status_details != nullptr) { - call->send_extra_metadata[1].md = grpc_mdelem_from_slices( - GRPC_MDSTR_GRPC_MESSAGE, - grpc_slice_ref_internal( - *op->data.send_status_from_server.status_details)); - call->send_extra_metadata_count++; - } grpc_error* status_error = op->data.send_status_from_server.status == GRPC_STATUS_OK ? GRPC_ERROR_NONE @@ -1661,6 +1653,22 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, GRPC_ERROR_INT_GRPC_STATUS, static_cast( op->data.send_status_from_server.status)); + if (op->data.send_status_from_server.status_details != nullptr) { + call->send_extra_metadata[1].md = grpc_mdelem_from_slices( + GRPC_MDSTR_GRPC_MESSAGE, + grpc_slice_ref_internal( + *op->data.send_status_from_server.status_details)); + call->send_extra_metadata_count++; + if (status_error != GRPC_ERROR_NONE) { + char* msg = grpc_slice_to_c_string( + GRPC_MDVALUE(call->send_extra_metadata[1].md)); + status_error = + grpc_error_set_str(status_error, GRPC_ERROR_STR_GRPC_MESSAGE, + grpc_slice_from_copied_string(msg)); + gpr_free(msg); + } + } + call->status_error = status_error; if (!prepare_application_metadata( call, -- cgit v1.2.3 From 1cfd81a604699d6ab8095c90e7da5fc588bb3048 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 21 Aug 2018 16:25:40 -0700 Subject: Explain the newer semantics of grpc_error_add_child --- src/core/lib/iomgr/error.cc | 5 +++++ src/core/lib/iomgr/error.h | 7 +++++++ test/core/iomgr/error_test.cc | 11 ----------- 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc index dfd063a695..13bc69ffb6 100644 --- a/src/core/lib/iomgr/error.cc +++ b/src/core/lib/iomgr/error.cc @@ -515,15 +515,20 @@ grpc_error* grpc_error_add_child(grpc_error* src, grpc_error* child) { GPR_TIMER_SCOPE("grpc_error_add_child", 0); if (src != GRPC_ERROR_NONE) { if (child == GRPC_ERROR_NONE) { + /* \a child is empty. Simply return the ref to \a src */ return src; } else if (child != src) { grpc_error* new_err = copy_error_and_unref(src); internal_add_error(&new_err, child); return new_err; } else { + /* \a src and \a child are the same. Drop one of the references and return + * the other */ + GRPC_ERROR_UNREF(child); return src; } } else { + /* \a src is empty. Simply return the ref to \a child */ return child; } } diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h index e5369695c9..49f4029bc2 100644 --- a/src/core/lib/iomgr/error.h +++ b/src/core/lib/iomgr/error.h @@ -185,6 +185,13 @@ bool grpc_error_get_str(grpc_error* error, grpc_error_strs which, /// error occurring. Allows root causing high level errors from lower level /// errors that contributed to them. The src error takes ownership of the /// child error. +/// +/// Edge Conditions - +/// 1) If either of \a src or \a child is GRPC_ERROR_NONE, returns a reference +/// to the other argument. 2) If both \a src and \a child are GRPC_ERROR_NONE, +/// returns GRPC_ERROR_NONE. 3) If \a src and \a child point to the same error, +/// returns a single reference. (Note that, 2 references should have been +/// received to the error in this case.) grpc_error* grpc_error_add_child(grpc_error* src, grpc_error* child) GRPC_MUST_USE_RESULT; diff --git a/test/core/iomgr/error_test.cc b/test/core/iomgr/error_test.cc index a1628a1f71..d78a8c2af3 100644 --- a/test/core/iomgr/error_test.cc +++ b/test/core/iomgr/error_test.cc @@ -187,16 +187,6 @@ static void test_os_error() { GRPC_ERROR_UNREF(error); } -static void test_special() { - grpc_error* error = GRPC_ERROR_NONE; - error = grpc_error_add_child( - error, GRPC_ERROR_CREATE_FROM_STATIC_STRING("test child")); - intptr_t i; - GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i)); - GPR_ASSERT(i == GRPC_STATUS_OK); - GRPC_ERROR_UNREF(error); -} - static void test_overflow() { grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Overflow"); @@ -235,7 +225,6 @@ int main(int argc, char** argv) { test_os_error(); test_create_referencing(); test_create_referencing_many(); - test_special(); test_overflow(); grpc_shutdown(); -- cgit v1.2.3 From 986fa0ed58661e13b71e04fd9c6a62f9d84493f3 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 21 Aug 2018 18:55:05 -0700 Subject: reviewer comments --- src/core/lib/surface/call.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index d0f418220b..fb3161aeaa 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -693,12 +693,10 @@ static void set_final_status(grpc_call* call, grpc_error* error) { grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(call->channel); if (call->is_client) { - const char** error_string = call->final_op.client.error_string; - grpc_status_code code; grpc_slice slice = grpc_empty_slice(); - grpc_error_get_status(error, call->send_deadline, &code, &slice, nullptr, - error_string); - *call->final_op.client.status = code; + grpc_error_get_status(error, call->send_deadline, + call->final_op.client.status, &slice, nullptr, + call->final_op.client.error_string); *call->final_op.client.status_details = grpc_slice_ref_internal(slice); call->status_error = error; if (channelz_channel != nullptr) { -- cgit v1.2.3 From 497532027dca770da60ac23e44f60ecf619cc2c5 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 23 Aug 2018 14:00:49 -0700 Subject: Reviewer comments --- src/core/lib/surface/call.cc | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index fb3161aeaa..0b86a74340 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -510,9 +510,8 @@ static void destroy_call(void* call, grpc_error* error) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } - grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(c->status_error, c->send_deadline, - &c->final_info.final_status, &slice, nullptr, + &c->final_info.final_status, nullptr, nullptr, &(c->final_info.error_string)); GRPC_ERROR_UNREF(c->status_error); c->final_info.stats.latency = @@ -690,8 +689,6 @@ static void set_final_status(grpc_call* call, grpc_error* error) { gpr_log(GPR_DEBUG, "set_final_status %s", call->is_client ? "CLI" : "SVR"); gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); } - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(call->channel); if (call->is_client) { grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(error, call->send_deadline, @@ -699,6 +696,8 @@ static void set_final_status(grpc_call* call, grpc_error* error) { call->final_op.client.error_string); *call->final_op.client.status_details = grpc_slice_ref_internal(slice); call->status_error = error; + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { if (*call->final_op.client.status != GRPC_STATUS_OK) { channelz_channel->RecordCallFailed(); @@ -709,13 +708,14 @@ static void set_final_status(grpc_call* call, grpc_error* error) { } else { *call->final_op.server.cancelled = error != GRPC_ERROR_NONE || call->status_error != GRPC_ERROR_NONE; - if (channelz_channel != nullptr) { + /* TODO(ncteisen) : Update channelz handling for server + if (channelz_channel != nullptr) { if (*call->final_op.server.cancelled) { channelz_channel->RecordCallFailed(); } else { channelz_channel->RecordCallSucceeded(); } - } + } */ GRPC_ERROR_UNREF(error); } } @@ -992,7 +992,7 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b, grpc_error* batch_error) { grpc_call* call = static_cast(args); if (batch_error != GRPC_ERROR_NONE) { - set_final_status(call, GRPC_ERROR_REF(batch_error)); + set_final_status(call, batch_error); } else if (b->idx.named.grpc_status != nullptr) { grpc_status_code status_code = grpc_get_status_code_from_metadata(b->idx.named.grpc_status->md); @@ -1025,7 +1025,6 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNKNOWN)); } publish_app_metadata(call, b, true); - GRPC_ERROR_UNREF(batch_error); } gpr_arena* grpc_call_get_arena(grpc_call* call) { return call->arena; } -- cgit v1.2.3 From d60a4b0f6b0d0d92944385bc9b629bb12aea24af Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 24 Aug 2018 09:44:37 -0700 Subject: Reviewer comments --- src/core/lib/surface/call.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 0b86a74340..e568ff3db4 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -690,11 +690,12 @@ static void set_final_status(grpc_call* call, grpc_error* error) { gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); } if (call->is_client) { - grpc_slice slice = grpc_empty_slice(); grpc_error_get_status(error, call->send_deadline, - call->final_op.client.status, &slice, nullptr, + call->final_op.client.status, + call->final_op.client.status_details, nullptr, call->final_op.client.error_string); - *call->final_op.client.status_details = grpc_slice_ref_internal(slice); + // explicitly take a ref + grpc_slice_ref_internal(*call->final_op.client.status_details); call->status_error = error; grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(call->channel); -- cgit v1.2.3 From ffdcad5e0699f36b5b1a45aa5a8a8e2733d592f1 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 24 Aug 2018 16:07:49 -0700 Subject: Redefine constants from errqueue.h. Some header files lag behind the kernel version --- src/core/lib/iomgr/internal_errqueue.h | 21 +++++++++++++++++++++ src/core/lib/iomgr/tcp_posix.cc | 3 ++- test/core/iomgr/buffer_list_test.cc | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/internal_errqueue.h b/src/core/lib/iomgr/internal_errqueue.h index fc11be9a6d..9d122808f9 100644 --- a/src/core/lib/iomgr/internal_errqueue.h +++ b/src/core/lib/iomgr/internal_errqueue.h @@ -43,6 +43,27 @@ namespace grpc_core { #ifdef GRPC_LINUX_ERRQUEUE + +/* Redefining scm_timestamping in the same way that defines + * it, so that code compiles on systems that don't have it. */ +struct scm_timestamping { + struct timespec ts[3]; +}; +/* Also redefine timestamp types */ +/* The timestamp type for when the driver passed skb to NIC, or HW. */ +constexpr int SCM_TSTAMP_SND = 0; +/* The timestamp type for when data entered the packet scheduler. */ +constexpr int SCM_TSTAMP_SCHED = 1; +/* The timestamp type for when data acknowledged by peer. */ +constexpr int SCM_TSTAMP_ACK = 2; +/* Redefine required constants from */ +constexpr uint32_t SOF_TIMESTAMPING_TX_SOFTWARE = 1u << 1; +constexpr uint32_t SOF_TIMESTAMPING_SOFTWARE = 1u << 4; +constexpr uint32_t SOF_TIMESTAMPING_OPT_ID = 1u << 7; +constexpr uint32_t SOF_TIMESTAMPING_TX_SCHED = 1u << 8; +constexpr uint32_t SOF_TIMESTAMPING_TX_ACK = 1u << 9; +constexpr uint32_t SOF_TIMESTAMPING_OPT_TSONLY = 1u << 11; + constexpr uint32_t kTimestampingSocketOptions = SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_OPT_TSONLY; diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 1db2790265..ac1e919acb 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -646,7 +646,8 @@ struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg, return cmsg; } - auto tss = reinterpret_cast(CMSG_DATA(cmsg)); + auto tss = + reinterpret_cast(CMSG_DATA(cmsg)); auto serr = reinterpret_cast(CMSG_DATA(next_cmsg)); if (serr->ee_errno != ENOMSG || serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) { diff --git a/test/core/iomgr/buffer_list_test.cc b/test/core/iomgr/buffer_list_test.cc index f1773580bd..9cdeee7a1a 100644 --- a/test/core/iomgr/buffer_list_test.cc +++ b/test/core/iomgr/buffer_list_test.cc @@ -76,7 +76,7 @@ static void TestVerifierCalledOnAck() { struct sock_extended_err serr; serr.ee_data = 213; serr.ee_info = SCM_TSTAMP_ACK; - struct scm_timestamping tss; + struct grpc_core::scm_timestamping tss; tss.ts[0].tv_sec = 123; tss.ts[0].tv_nsec = 456; grpc_core::grpc_tcp_set_write_timestamps_callback( -- cgit v1.2.3 From 8ceb27a324b5efaf2ed096a7bbdf241295272bf5 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Mon, 27 Aug 2018 14:27:55 -0700 Subject: Regenerate projects --- CMakeLists.txt | 2 +- Makefile | 4 ++-- gRPC-C++.podspec | 4 ++-- gRPC-Core.podspec | 2 +- gRPC-ProtoRPC.podspec | 2 +- gRPC-RxLibrary.podspec | 2 +- gRPC.podspec | 2 +- package.xml | 4 ++-- src/core/lib/surface/version.cc | 2 +- src/cpp/common/version_cc.cc | 2 +- src/csharp/Grpc.Core/Version.csproj.include | 2 +- src/csharp/Grpc.Core/VersionInfo.cs | 4 ++-- src/csharp/build_packages_dotnetcli.bat | 2 +- src/csharp/build_unitypackage.bat | 2 +- src/objective-c/!ProtoCompiler-gRPCPlugin.podspec | 2 +- src/objective-c/GRPCClient/private/version.h | 2 +- src/objective-c/tests/version.h | 2 +- src/php/composer.json | 2 +- src/php/ext/grpc/version.h | 2 +- src/python/grpcio/grpc/_grpcio_metadata.py | 2 +- src/python/grpcio/grpc_version.py | 2 +- src/python/grpcio_health_checking/grpc_version.py | 2 +- src/python/grpcio_reflection/grpc_version.py | 2 +- src/python/grpcio_testing/grpc_version.py | 2 +- src/python/grpcio_tests/grpc_version.py | 2 +- src/ruby/lib/grpc/version.rb | 2 +- src/ruby/tools/version.rb | 2 +- tools/distrib/python/grpcio_tools/grpc_version.py | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- 30 files changed, 34 insertions(+), 34 deletions(-) (limited to 'src/core/lib') diff --git a/CMakeLists.txt b/CMakeLists.txt index a330fefc27..7672e26c44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "grpc") -set(PACKAGE_VERSION "1.15.0-dev") +set(PACKAGE_VERSION "1.16.0-dev") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") diff --git a/Makefile b/Makefile index e9a9486a3c..2609441a95 100644 --- a/Makefile +++ b/Makefile @@ -437,8 +437,8 @@ Q = @ endif CORE_VERSION = 6.0.0-dev -CPP_VERSION = 1.15.0-dev -CSHARP_VERSION = 1.15.0-dev +CPP_VERSION = 1.16.0-dev +CSHARP_VERSION = 1.16.0-dev CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 207d7baa8f..d5f275318b 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-C++' # TODO (mxyan): use version that match gRPC version when pod is stabilized - # version = '1.15.0-dev' + # version = '1.16.0-dev' version = '0.0.3' s.version = version s.summary = 'gRPC C++ library' @@ -31,7 +31,7 @@ Pod::Spec.new do |s| s.license = 'Apache License, Version 2.0' s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } - grpc_version = '1.15.0-dev' + grpc_version = '1.16.0-dev' s.source = { :git => 'https://github.com/grpc/grpc.git', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index f1a9bce7f2..0b4f79ac8b 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.15.0-dev' + version = '1.16.0-dev' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'https://grpc.io' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 79ec679e3a..75fd592e75 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.15.0-dev' + version = '1.16.0-dev' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'https://grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index 7a461e270f..ecd786e7b3 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.15.0-dev' + version = '1.16.0-dev' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'https://grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index bf3f56bd54..9164b2169a 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.15.0-dev' + version = '1.16.0-dev' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'https://grpc.io' diff --git a/package.xml b/package.xml index 1bdf127c36..cb1978e2ab 100644 --- a/package.xml +++ b/package.xml @@ -13,8 +13,8 @@ 2018-01-19 - 1.15.0dev - 1.15.0dev + 1.16.0dev + 1.16.0dev beta diff --git a/src/core/lib/surface/version.cc b/src/core/lib/surface/version.cc index e92fe2c5a1..a44f9acdc3 100644 --- a/src/core/lib/surface/version.cc +++ b/src/core/lib/surface/version.cc @@ -25,4 +25,4 @@ const char* grpc_version_string(void) { return "6.0.0-dev"; } -const char* grpc_g_stands_for(void) { return "glider"; } +const char* grpc_g_stands_for(void) { return "gao"; } diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index b8fca9a6ee..cc797f1546 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -22,5 +22,5 @@ #include namespace grpc { -grpc::string Version() { return "1.15.0-dev"; } +grpc::string Version() { return "1.16.0-dev"; } } // namespace grpc diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include index 45bd8ebd85..18515ea1e8 100755 --- a/src/csharp/Grpc.Core/Version.csproj.include +++ b/src/csharp/Grpc.Core/Version.csproj.include @@ -1,7 +1,7 @@ - 1.15.0-dev + 1.16.0-dev 3.6.1 diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index 295e0f2577..55d09dda7a 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -33,11 +33,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "1.15.0.0"; + public const string CurrentAssemblyFileVersion = "1.16.0.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "1.15.0-dev"; + public const string CurrentVersion = "1.16.0-dev"; } } diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index 8f38f0aa20..24d016104c 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.15.0-dev +set VERSION=1.16.0-dev @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/csharp/build_unitypackage.bat b/src/csharp/build_unitypackage.bat index 9c53114b84..4e7ac4e414 100644 --- a/src/csharp/build_unitypackage.bat +++ b/src/csharp/build_unitypackage.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.15.0-dev +set VERSION=1.16.0-dev @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 5e9a9a4513..200cee5b7b 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.15.0-dev' + v = '1.16.0-dev' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index 52fe0dd050..38862e102a 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -22,4 +22,4 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.15.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.16.0-dev" diff --git a/src/objective-c/tests/version.h b/src/objective-c/tests/version.h index d532eed245..82833102ad 100644 --- a/src/objective-c/tests/version.h +++ b/src/objective-c/tests/version.h @@ -22,5 +22,5 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.15.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.16.0-dev" #define GRPC_C_VERSION_STRING @"6.0.0-dev" diff --git a/src/php/composer.json b/src/php/composer.json index 91913d73d2..f31423f8c0 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "Apache-2.0", - "version": "1.15.0", + "version": "1.16.0", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.3.0" diff --git a/src/php/ext/grpc/version.h b/src/php/ext/grpc/version.h index 99dd9d68f0..469a48e782 100644 --- a/src/php/ext/grpc/version.h +++ b/src/php/ext/grpc/version.h @@ -20,6 +20,6 @@ #ifndef VERSION_H #define VERSION_H -#define PHP_GRPC_VERSION "1.15.0dev" +#define PHP_GRPC_VERSION "1.16.0dev" #endif /* VERSION_H */ diff --git a/src/python/grpcio/grpc/_grpcio_metadata.py b/src/python/grpcio/grpc/_grpcio_metadata.py index c33911ebc1..24e1557578 100644 --- a/src/python/grpcio/grpc/_grpcio_metadata.py +++ b/src/python/grpcio/grpc/_grpcio_metadata.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!! -__version__ = """1.15.0.dev0""" +__version__ = """1.16.0.dev0""" diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 9337800a33..6ffe1eb827 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION = '1.15.0.dev0' +VERSION = '1.16.0.dev0' diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index 3b84f7a4c5..e080bf2cbc 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION = '1.15.0.dev0' +VERSION = '1.16.0.dev0' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index 7b0e48ea23..4b3b95fee9 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION = '1.15.0.dev0' +VERSION = '1.16.0.dev0' diff --git a/src/python/grpcio_testing/grpc_version.py b/src/python/grpcio_testing/grpc_version.py index df9953fa25..c12aa153a4 100644 --- a/src/python/grpcio_testing/grpc_version.py +++ b/src/python/grpcio_testing/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!! -VERSION = '1.15.0.dev0' +VERSION = '1.16.0.dev0' diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index b2cf129e4f..f4b8a34a46 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION = '1.15.0.dev0' +VERSION = '1.16.0.dev0' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 5c21a5b168..0c3e1ef734 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -14,5 +14,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '1.15.0.dev' + VERSION = '1.16.0.dev' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 1b5e2c362b..03d977c064 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -14,6 +14,6 @@ module GRPC module Tools - VERSION = '1.15.0.dev' + VERSION = '1.16.0.dev' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index ccb69a8ebc..581dab3b4e 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION = '1.15.0.dev0' +VERSION = '1.16.0.dev0' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 688c271fea..9a97ee84f2 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.15.0-dev +PROJECT_NUMBER = 1.16.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 43ebf8cad9..de1f48d369 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.15.0-dev +PROJECT_NUMBER = 1.16.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a -- cgit v1.2.3 From 8d47cd4992c3c3546bef23568fde5fe132144666 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 27 Aug 2018 14:56:01 -0700 Subject: Revert "Revert "Fathom tcp changes"" --- BUILD | 4 + CMakeLists.txt | 46 +++ Makefile | 48 ++++ build.yaml | 18 ++ config.m4 | 2 + config.w32 | 2 + gRPC-C++.podspec | 4 + gRPC-Core.podspec | 6 + grpc.gemspec | 4 + grpc.gyp | 8 + package.xml | 4 + .../client_channel/http_connect_handshaker.cc | 2 +- .../chttp2/client/insecure/channel_create_posix.cc | 2 +- .../chttp2/server/insecure/server_chttp2_posix.cc | 2 +- .../transport/chttp2/transport/chttp2_transport.cc | 3 +- src/core/lib/http/httpcli.cc | 2 +- src/core/lib/iomgr/buffer_list.cc | 134 +++++++++ src/core/lib/iomgr/buffer_list.h | 96 +++++++ src/core/lib/iomgr/endpoint.cc | 4 +- src/core/lib/iomgr/endpoint.h | 8 +- src/core/lib/iomgr/endpoint_cfstream.cc | 2 +- src/core/lib/iomgr/endpoint_pair_posix.cc | 4 +- src/core/lib/iomgr/ev_posix.cc | 9 +- src/core/lib/iomgr/internal_errqueue.cc | 40 +++ src/core/lib/iomgr/internal_errqueue.h | 62 ++++ src/core/lib/iomgr/port.h | 6 + src/core/lib/iomgr/tcp_client_posix.cc | 2 +- src/core/lib/iomgr/tcp_custom.cc | 2 +- src/core/lib/iomgr/tcp_posix.cc | 311 ++++++++++++++++++++- src/core/lib/iomgr/tcp_posix.h | 3 + src/core/lib/iomgr/tcp_server_posix.cc | 4 +- .../lib/iomgr/tcp_server_utils_posix_common.cc | 2 +- src/core/lib/iomgr/tcp_windows.cc | 2 +- src/core/lib/iomgr/udp_server.cc | 2 +- src/core/lib/security/transport/secure_endpoint.cc | 4 +- .../lib/security/transport/security_handshaker.cc | 2 +- src/python/grpcio/grpc_core_dependencies.py | 2 + test/core/bad_client/bad_client.cc | 2 +- test/core/end2end/bad_server_response_test.cc | 2 +- test/core/end2end/fixtures/http_proxy_fixture.cc | 10 +- test/core/iomgr/BUILD | 13 + test/core/iomgr/buffer_list_test.cc | 111 ++++++++ test/core/iomgr/endpoint_tests.cc | 7 +- test/core/iomgr/tcp_posix_test.cc | 109 ++++++-- test/core/util/mock_endpoint.cc | 2 +- test/core/util/passthru_endpoint.cc | 2 +- test/core/util/trickle_endpoint.cc | 5 +- test/cpp/microbenchmarks/bm_chttp2_transport.cc | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 + tools/doxygen/Doxyfile.core.internal | 4 + tools/run_tests/generated/sources_and_headers.json | 23 ++ tools/run_tests/generated/tests.json | 20 ++ 52 files changed, 1104 insertions(+), 68 deletions(-) create mode 100644 src/core/lib/iomgr/buffer_list.cc create mode 100644 src/core/lib/iomgr/buffer_list.h create mode 100644 src/core/lib/iomgr/internal_errqueue.cc create mode 100644 src/core/lib/iomgr/internal_errqueue.h create mode 100644 test/core/iomgr/buffer_list_test.cc (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index e1b00a5cf0..c01b971281 100644 --- a/BUILD +++ b/BUILD @@ -696,6 +696,7 @@ grpc_cc_library( "src/core/lib/http/format_request.cc", "src/core/lib/http/httpcli.cc", "src/core/lib/http/parser.cc", + "src/core/lib/iomgr/buffer_list.cc", "src/core/lib/iomgr/call_combiner.cc", "src/core/lib/iomgr/combiner.cc", "src/core/lib/iomgr/endpoint.cc", @@ -716,6 +717,7 @@ grpc_cc_library( "src/core/lib/iomgr/gethostname_fallback.cc", "src/core/lib/iomgr/gethostname_host_name_max.cc", "src/core/lib/iomgr/gethostname_sysconf.cc", + "src/core/lib/iomgr/internal_errqueue.cc", "src/core/lib/iomgr/iocp_windows.cc", "src/core/lib/iomgr/iomgr.cc", "src/core/lib/iomgr/iomgr_custom.cc", @@ -845,6 +847,7 @@ grpc_cc_library( "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", + "src/core/lib/iomgr/buffer_list.h", "src/core/lib/iomgr/block_annotate.h", "src/core/lib/iomgr/call_combiner.h", "src/core/lib/iomgr/closure.h", @@ -862,6 +865,7 @@ grpc_cc_library( "src/core/lib/iomgr/executor.h", "src/core/lib/iomgr/gethostname.h", "src/core/lib/iomgr/gevent_util.h", + "src/core/lib/iomgr/internal_errqueue.h", "src/core/lib/iomgr/iocp_windows.h", "src/core/lib/iomgr/iomgr.h", "src/core/lib/iomgr/iomgr_custom.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index a330fefc27..3895d4c0f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,6 +230,9 @@ add_dependencies(buildtests_c avl_test) add_dependencies(buildtests_c bad_server_response_test) add_dependencies(buildtests_c bin_decoder_test) add_dependencies(buildtests_c bin_encoder_test) +if(_gRPC_PLATFORM_LINUX) +add_dependencies(buildtests_c buffer_list_test) +endif() add_dependencies(buildtests_c channel_create_test) add_dependencies(buildtests_c chttp2_hpack_encoder_test) add_dependencies(buildtests_c chttp2_stream_map_test) @@ -959,6 +962,7 @@ add_library(grpc src/core/lib/http/format_request.cc src/core/lib/http/httpcli.cc src/core/lib/http/parser.cc + src/core/lib/iomgr/buffer_list.cc src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/endpoint.cc @@ -979,6 +983,7 @@ add_library(grpc src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr_custom.cc @@ -1365,6 +1370,7 @@ add_library(grpc_cronet src/core/lib/http/format_request.cc src/core/lib/http/httpcli.cc src/core/lib/http/parser.cc + src/core/lib/iomgr/buffer_list.cc src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/endpoint.cc @@ -1385,6 +1391,7 @@ add_library(grpc_cronet src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr_custom.cc @@ -1757,6 +1764,7 @@ add_library(grpc_test_util src/core/lib/http/format_request.cc src/core/lib/http/httpcli.cc src/core/lib/http/parser.cc + src/core/lib/iomgr/buffer_list.cc src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/endpoint.cc @@ -1777,6 +1785,7 @@ add_library(grpc_test_util src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr_custom.cc @@ -2065,6 +2074,7 @@ add_library(grpc_test_util_unsecure src/core/lib/http/format_request.cc src/core/lib/http/httpcli.cc src/core/lib/http/parser.cc + src/core/lib/iomgr/buffer_list.cc src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/endpoint.cc @@ -2085,6 +2095,7 @@ add_library(grpc_test_util_unsecure src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr_custom.cc @@ -2352,6 +2363,7 @@ add_library(grpc_unsecure src/core/lib/http/format_request.cc src/core/lib/http/httpcli.cc src/core/lib/http/parser.cc + src/core/lib/iomgr/buffer_list.cc src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/endpoint.cc @@ -2372,6 +2384,7 @@ add_library(grpc_unsecure src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr_custom.cc @@ -3192,6 +3205,7 @@ add_library(grpc++_cronet src/core/lib/http/format_request.cc src/core/lib/http/httpcli.cc src/core/lib/http/parser.cc + src/core/lib/iomgr/buffer_list.cc src/core/lib/iomgr/call_combiner.cc src/core/lib/iomgr/combiner.cc src/core/lib/iomgr/endpoint.cc @@ -3212,6 +3226,7 @@ add_library(grpc++_cronet src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc src/core/lib/iomgr/iomgr_custom.cc @@ -5835,6 +5850,37 @@ target_link_libraries(bin_encoder_test grpc ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX) + +add_executable(buffer_list_test + test/core/iomgr/buffer_list_test.cc +) + + +target_include_directories(buffer_list_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} +) + +target_link_libraries(buffer_list_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr +) + +endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index e9a9486a3c..7caf585ee9 100644 --- a/Makefile +++ b/Makefile @@ -978,6 +978,7 @@ avl_test: $(BINDIR)/$(CONFIG)/avl_test bad_server_response_test: $(BINDIR)/$(CONFIG)/bad_server_response_test bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test +buffer_list_test: $(BINDIR)/$(CONFIG)/buffer_list_test channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test check_epollexclusive: $(BINDIR)/$(CONFIG)/check_epollexclusive chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test @@ -1434,6 +1435,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/bad_server_response_test \ $(BINDIR)/$(CONFIG)/bin_decoder_test \ $(BINDIR)/$(CONFIG)/bin_encoder_test \ + $(BINDIR)/$(CONFIG)/buffer_list_test \ $(BINDIR)/$(CONFIG)/channel_create_test \ $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \ $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \ @@ -1950,6 +1952,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/bin_decoder_test || ( echo test bin_decoder_test failed ; exit 1 ) $(E) "[RUN] Testing bin_encoder_test" $(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 ) + $(E) "[RUN] Testing buffer_list_test" + $(Q) $(BINDIR)/$(CONFIG)/buffer_list_test || ( echo test buffer_list_test failed ; exit 1 ) $(E) "[RUN] Testing channel_create_test" $(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_hpack_encoder_test" @@ -3460,6 +3464,7 @@ LIBGRPC_SRC = \ src/core/lib/http/format_request.cc \ src/core/lib/http/httpcli.cc \ src/core/lib/http/parser.cc \ + src/core/lib/iomgr/buffer_list.cc \ src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/endpoint.cc \ @@ -3480,6 +3485,7 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr_custom.cc \ @@ -3865,6 +3871,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/http/format_request.cc \ src/core/lib/http/httpcli.cc \ src/core/lib/http/parser.cc \ + src/core/lib/iomgr/buffer_list.cc \ src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/endpoint.cc \ @@ -3885,6 +3892,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr_custom.cc \ @@ -4255,6 +4263,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/http/format_request.cc \ src/core/lib/http/httpcli.cc \ src/core/lib/http/parser.cc \ + src/core/lib/iomgr/buffer_list.cc \ src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/endpoint.cc \ @@ -4275,6 +4284,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr_custom.cc \ @@ -4554,6 +4564,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \ src/core/lib/http/format_request.cc \ src/core/lib/http/httpcli.cc \ src/core/lib/http/parser.cc \ + src/core/lib/iomgr/buffer_list.cc \ src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/endpoint.cc \ @@ -4574,6 +4585,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr_custom.cc \ @@ -4819,6 +4831,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/http/format_request.cc \ src/core/lib/http/httpcli.cc \ src/core/lib/http/parser.cc \ + src/core/lib/iomgr/buffer_list.cc \ src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/endpoint.cc \ @@ -4839,6 +4852,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr_custom.cc \ @@ -5647,6 +5661,7 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/http/format_request.cc \ src/core/lib/http/httpcli.cc \ src/core/lib/http/parser.cc \ + src/core/lib/iomgr/buffer_list.cc \ src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/endpoint.cc \ @@ -5667,6 +5682,7 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr_custom.cc \ @@ -10701,6 +10717,38 @@ endif endif +BUFFER_LIST_TEST_SRC = \ + test/core/iomgr/buffer_list_test.cc \ + +BUFFER_LIST_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BUFFER_LIST_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/buffer_list_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/buffer_list_test: $(BUFFER_LIST_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(BUFFER_LIST_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/buffer_list_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/buffer_list_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_buffer_list_test: $(BUFFER_LIST_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(BUFFER_LIST_TEST_OBJS:.o=.dep) +endif +endif + + CHANNEL_CREATE_TEST_SRC = \ test/core/surface/channel_create_test.cc \ diff --git a/build.yaml b/build.yaml index ce21068c31..a7ebee7572 100644 --- a/build.yaml +++ b/build.yaml @@ -256,6 +256,7 @@ filegroups: - src/core/lib/http/format_request.cc - src/core/lib/http/httpcli.cc - src/core/lib/http/parser.cc + - src/core/lib/iomgr/buffer_list.cc - src/core/lib/iomgr/call_combiner.cc - src/core/lib/iomgr/combiner.cc - src/core/lib/iomgr/endpoint.cc @@ -276,6 +277,7 @@ filegroups: - src/core/lib/iomgr/gethostname_fallback.cc - src/core/lib/iomgr/gethostname_host_name_max.cc - src/core/lib/iomgr/gethostname_sysconf.cc + - src/core/lib/iomgr/internal_errqueue.cc - src/core/lib/iomgr/iocp_windows.cc - src/core/lib/iomgr/iomgr.cc - src/core/lib/iomgr/iomgr_custom.cc @@ -434,6 +436,7 @@ filegroups: - src/core/lib/http/httpcli.h - src/core/lib/http/parser.h - src/core/lib/iomgr/block_annotate.h + - src/core/lib/iomgr/buffer_list.h - src/core/lib/iomgr/call_combiner.h - src/core/lib/iomgr/closure.h - src/core/lib/iomgr/combiner.h @@ -449,6 +452,7 @@ filegroups: - src/core/lib/iomgr/exec_ctx.h - src/core/lib/iomgr/executor.h - src/core/lib/iomgr/gethostname.h + - src/core/lib/iomgr/internal_errqueue.h - src/core/lib/iomgr/iocp_windows.h - src/core/lib/iomgr/iomgr.h - src/core/lib/iomgr/iomgr_custom.h @@ -2139,6 +2143,20 @@ targets: - grpc_test_util - grpc uses_polling: false +- name: buffer_list_test + build: test + language: c + src: + - test/core/iomgr/buffer_list_test.cc + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + exclude_iomgrs: + - uv + platforms: + - linux - name: channel_create_test build: test language: c diff --git a/config.m4 b/config.m4 index 7825274eea..af3624cdd1 100644 --- a/config.m4 +++ b/config.m4 @@ -108,6 +108,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/http/format_request.cc \ src/core/lib/http/httpcli.cc \ src/core/lib/http/parser.cc \ + src/core/lib/iomgr/buffer_list.cc \ src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/combiner.cc \ src/core/lib/iomgr/endpoint.cc \ @@ -128,6 +129,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ src/core/lib/iomgr/iomgr_custom.cc \ diff --git a/config.w32 b/config.w32 index a9d1e6c9d0..ad91ee40bd 100644 --- a/config.w32 +++ b/config.w32 @@ -83,6 +83,7 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\http\\format_request.cc " + "src\\core\\lib\\http\\httpcli.cc " + "src\\core\\lib\\http\\parser.cc " + + "src\\core\\lib\\iomgr\\buffer_list.cc " + "src\\core\\lib\\iomgr\\call_combiner.cc " + "src\\core\\lib\\iomgr\\combiner.cc " + "src\\core\\lib\\iomgr\\endpoint.cc " + @@ -103,6 +104,7 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\iomgr\\gethostname_fallback.cc " + "src\\core\\lib\\iomgr\\gethostname_host_name_max.cc " + "src\\core\\lib\\iomgr\\gethostname_sysconf.cc " + + "src\\core\\lib\\iomgr\\internal_errqueue.cc " + "src\\core\\lib\\iomgr\\iocp_windows.cc " + "src\\core\\lib\\iomgr\\iomgr.cc " + "src\\core\\lib\\iomgr\\iomgr_custom.cc " + diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 207d7baa8f..a387794f57 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -382,6 +382,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', 'src/core/lib/iomgr/block_annotate.h', + 'src/core/lib/iomgr/buffer_list.h', 'src/core/lib/iomgr/call_combiner.h', 'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/combiner.h', @@ -397,6 +398,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/gethostname.h', + 'src/core/lib/iomgr/internal_errqueue.h', 'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr_custom.h', @@ -570,6 +572,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', 'src/core/lib/iomgr/block_annotate.h', + 'src/core/lib/iomgr/buffer_list.h', 'src/core/lib/iomgr/call_combiner.h', 'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/combiner.h', @@ -585,6 +588,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/gethostname.h', + 'src/core/lib/iomgr/internal_errqueue.h', 'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr_custom.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index f1a9bce7f2..9832283e5c 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -394,6 +394,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', 'src/core/lib/iomgr/block_annotate.h', + 'src/core/lib/iomgr/buffer_list.h', 'src/core/lib/iomgr/call_combiner.h', 'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/combiner.h', @@ -409,6 +410,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/gethostname.h', + 'src/core/lib/iomgr/internal_errqueue.h', 'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr_custom.h', @@ -538,6 +540,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/format_request.cc', 'src/core/lib/http/httpcli.cc', 'src/core/lib/http/parser.cc', + 'src/core/lib/iomgr/buffer_list.cc', 'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/endpoint.cc', @@ -558,6 +561,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr_custom.cc', @@ -993,6 +997,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', 'src/core/lib/iomgr/block_annotate.h', + 'src/core/lib/iomgr/buffer_list.h', 'src/core/lib/iomgr/call_combiner.h', 'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/combiner.h', @@ -1008,6 +1013,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/gethostname.h', + 'src/core/lib/iomgr/internal_errqueue.h', 'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr_custom.h', diff --git a/grpc.gemspec b/grpc.gemspec index 5c38071d15..c8e58faec9 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -330,6 +330,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/http/httpcli.h ) s.files += %w( src/core/lib/http/parser.h ) s.files += %w( src/core/lib/iomgr/block_annotate.h ) + s.files += %w( src/core/lib/iomgr/buffer_list.h ) s.files += %w( src/core/lib/iomgr/call_combiner.h ) s.files += %w( src/core/lib/iomgr/closure.h ) s.files += %w( src/core/lib/iomgr/combiner.h ) @@ -345,6 +346,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/exec_ctx.h ) s.files += %w( src/core/lib/iomgr/executor.h ) s.files += %w( src/core/lib/iomgr/gethostname.h ) + s.files += %w( src/core/lib/iomgr/internal_errqueue.h ) s.files += %w( src/core/lib/iomgr/iocp_windows.h ) s.files += %w( src/core/lib/iomgr/iomgr.h ) s.files += %w( src/core/lib/iomgr/iomgr_custom.h ) @@ -474,6 +476,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/http/format_request.cc ) s.files += %w( src/core/lib/http/httpcli.cc ) s.files += %w( src/core/lib/http/parser.cc ) + s.files += %w( src/core/lib/iomgr/buffer_list.cc ) s.files += %w( src/core/lib/iomgr/call_combiner.cc ) s.files += %w( src/core/lib/iomgr/combiner.cc ) s.files += %w( src/core/lib/iomgr/endpoint.cc ) @@ -494,6 +497,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/gethostname_fallback.cc ) s.files += %w( src/core/lib/iomgr/gethostname_host_name_max.cc ) s.files += %w( src/core/lib/iomgr/gethostname_sysconf.cc ) + s.files += %w( src/core/lib/iomgr/internal_errqueue.cc ) s.files += %w( src/core/lib/iomgr/iocp_windows.cc ) s.files += %w( src/core/lib/iomgr/iomgr.cc ) s.files += %w( src/core/lib/iomgr/iomgr_custom.cc ) diff --git a/grpc.gyp b/grpc.gyp index a36998bcb3..654a531092 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -300,6 +300,7 @@ 'src/core/lib/http/format_request.cc', 'src/core/lib/http/httpcli.cc', 'src/core/lib/http/parser.cc', + 'src/core/lib/iomgr/buffer_list.cc', 'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/endpoint.cc', @@ -320,6 +321,7 @@ 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr_custom.cc', @@ -660,6 +662,7 @@ 'src/core/lib/http/format_request.cc', 'src/core/lib/http/httpcli.cc', 'src/core/lib/http/parser.cc', + 'src/core/lib/iomgr/buffer_list.cc', 'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/endpoint.cc', @@ -680,6 +683,7 @@ 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr_custom.cc', @@ -893,6 +897,7 @@ 'src/core/lib/http/format_request.cc', 'src/core/lib/http/httpcli.cc', 'src/core/lib/http/parser.cc', + 'src/core/lib/iomgr/buffer_list.cc', 'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/endpoint.cc', @@ -913,6 +918,7 @@ 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr_custom.cc', @@ -1104,6 +1110,7 @@ 'src/core/lib/http/format_request.cc', 'src/core/lib/http/httpcli.cc', 'src/core/lib/http/parser.cc', + 'src/core/lib/iomgr/buffer_list.cc', 'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/endpoint.cc', @@ -1124,6 +1131,7 @@ 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr_custom.cc', diff --git a/package.xml b/package.xml index 1bdf127c36..537c5404e7 100644 --- a/package.xml +++ b/package.xml @@ -335,6 +335,7 @@ + @@ -350,6 +351,7 @@ + @@ -479,6 +481,7 @@ + @@ -499,6 +502,7 @@ + diff --git a/src/core/ext/filters/client_channel/http_connect_handshaker.cc b/src/core/ext/filters/client_channel/http_connect_handshaker.cc index 4e8b8b71db..7ce8da8c00 100644 --- a/src/core/ext/filters/client_channel/http_connect_handshaker.cc +++ b/src/core/ext/filters/client_channel/http_connect_handshaker.cc @@ -320,7 +320,7 @@ static void http_connect_handshaker_do_handshake( // Take a new ref to be held by the write callback. gpr_ref(&handshaker->refcount); grpc_endpoint_write(args->endpoint, &handshaker->write_buffer, - &handshaker->request_done_closure); + &handshaker->request_done_closure, nullptr); gpr_mu_unlock(&handshaker->mu); } diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc b/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc index dfed824cd5..5bdcb387c9 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc @@ -50,7 +50,7 @@ grpc_channel* grpc_insecure_channel_create_from_fd( GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); grpc_endpoint* client = grpc_tcp_client_create_from_fd( - grpc_fd_create(fd, "client", false), args, "fd-client"); + grpc_fd_create(fd, "client", true), args, "fd-client"); grpc_transport* transport = grpc_create_chttp2_transport(final_args, client, true); diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc b/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc index a0228785ee..e4bd91d07b 100644 --- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc @@ -44,7 +44,7 @@ void grpc_server_add_insecure_channel_from_fd(grpc_server* server, gpr_asprintf(&name, "fd:%d", fd); grpc_endpoint* server_endpoint = - grpc_tcp_create(grpc_fd_create(fd, name, false), + grpc_tcp_create(grpc_fd_create(fd, name, true), grpc_server_get_channel_args(server), name); gpr_free(name); diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 36511fa608..027a57d606 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -1029,7 +1029,8 @@ static void write_action(void* gt, grpc_error* error) { grpc_endpoint_write( t->ep, &t->outbuf, GRPC_CLOSURE_INIT(&t->write_action_end_locked, write_action_end_locked, t, - grpc_combiner_scheduler(t->combiner))); + grpc_combiner_scheduler(t->combiner)), + nullptr); } /* Callback from the grpc_endpoint after bytes have been written by calling diff --git a/src/core/lib/http/httpcli.cc b/src/core/lib/http/httpcli.cc index 12060074c5..3bd7a2ce59 100644 --- a/src/core/lib/http/httpcli.cc +++ b/src/core/lib/http/httpcli.cc @@ -163,7 +163,7 @@ static void done_write(void* arg, grpc_error* error) { static void start_write(internal_request* req) { grpc_slice_ref_internal(req->request_text); grpc_slice_buffer_add(&req->outgoing, req->request_text); - grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write); + grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write, nullptr); } static void on_handshake_done(void* arg, grpc_endpoint* ep) { diff --git a/src/core/lib/iomgr/buffer_list.cc b/src/core/lib/iomgr/buffer_list.cc new file mode 100644 index 0000000000..6ada23db1c --- /dev/null +++ b/src/core/lib/iomgr/buffer_list.cc @@ -0,0 +1,134 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/buffer_list.h" +#include "src/core/lib/iomgr/port.h" + +#include + +#ifdef GRPC_LINUX_ERRQUEUE +#include + +#include "src/core/lib/gprpp/memory.h" + +namespace grpc_core { +void TracedBuffer::AddNewEntry(TracedBuffer** head, uint32_t seq_no, + void* arg) { + GPR_DEBUG_ASSERT(head != nullptr); + TracedBuffer* new_elem = New(seq_no, arg); + /* Store the current time as the sendmsg time. */ + new_elem->ts_.sendmsg_time = gpr_now(GPR_CLOCK_REALTIME); + if (*head == nullptr) { + *head = new_elem; + return; + } + /* Append at the end. */ + TracedBuffer* ptr = *head; + while (ptr->next_ != nullptr) { + ptr = ptr->next_; + } + ptr->next_ = new_elem; +} + +namespace { +/** Fills gpr_timespec gts based on values from timespec ts */ +void fill_gpr_from_timestamp(gpr_timespec* gts, const struct timespec* ts) { + gts->tv_sec = ts->tv_sec; + gts->tv_nsec = static_cast(ts->tv_nsec); + gts->clock_type = GPR_CLOCK_REALTIME; +} + +/** The saved callback function that will be invoked when we get all the + * timestamps that we are going to get for a TracedBuffer. */ +void (*timestamps_callback)(void*, grpc_core::Timestamps*, + grpc_error* shutdown_err); +} /* namespace */ + +void TracedBuffer::ProcessTimestamp(TracedBuffer** head, + struct sock_extended_err* serr, + struct scm_timestamping* tss) { + GPR_DEBUG_ASSERT(head != nullptr); + TracedBuffer* elem = *head; + TracedBuffer* next = nullptr; + while (elem != nullptr) { + /* The byte number refers to the sequence number of the last byte which this + * timestamp relates to. */ + if (serr->ee_data >= elem->seq_no_) { + switch (serr->ee_info) { + case SCM_TSTAMP_SCHED: + fill_gpr_from_timestamp(&(elem->ts_.scheduled_time), &(tss->ts[0])); + elem = elem->next_; + break; + case SCM_TSTAMP_SND: + fill_gpr_from_timestamp(&(elem->ts_.sent_time), &(tss->ts[0])); + elem = elem->next_; + break; + case SCM_TSTAMP_ACK: + fill_gpr_from_timestamp(&(elem->ts_.acked_time), &(tss->ts[0])); + /* Got all timestamps. Do the callback and free this TracedBuffer. + * The thing below can be passed by value if we don't want the + * restriction on the lifetime. */ + timestamps_callback(elem->arg_, &(elem->ts_), GRPC_ERROR_NONE); + next = elem->next_; + Delete(elem); + *head = elem = next; + break; + default: + abort(); + } + } else { + break; + } + } +} + +void TracedBuffer::Shutdown(TracedBuffer** head, grpc_error* shutdown_err) { + GPR_DEBUG_ASSERT(head != nullptr); + TracedBuffer* elem = *head; + while (elem != nullptr) { + if (timestamps_callback) { + timestamps_callback(elem->arg_, &(elem->ts_), shutdown_err); + } + auto* next = elem->next_; + Delete(elem); + elem = next; + } + *head = nullptr; + GRPC_ERROR_UNREF(shutdown_err); +} + +void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*, + grpc_core::Timestamps*, + grpc_error* error)) { + timestamps_callback = fn; +} +} /* namespace grpc_core */ + +#else /* GRPC_LINUX_ERRQUEUE */ + +namespace grpc_core { +void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*, + grpc_core::Timestamps*, + grpc_error* error)) { + gpr_log(GPR_DEBUG, "Timestamps callback is not enabled for this platform"); +} +} /* namespace grpc_core */ + +#endif /* GRPC_LINUX_ERRQUEUE */ diff --git a/src/core/lib/iomgr/buffer_list.h b/src/core/lib/iomgr/buffer_list.h new file mode 100644 index 0000000000..cbbf50a657 --- /dev/null +++ b/src/core/lib/iomgr/buffer_list.h @@ -0,0 +1,96 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_BUFFER_LIST_H +#define GRPC_CORE_LIB_IOMGR_BUFFER_LIST_H + +#include + +#include "src/core/lib/iomgr/port.h" + +#include + +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/internal_errqueue.h" + +namespace grpc_core { +struct Timestamps { + /* TODO(yashykt): This would also need to store OPTSTAT once support is added + */ + gpr_timespec sendmsg_time; + gpr_timespec scheduled_time; + gpr_timespec sent_time; + gpr_timespec acked_time; +}; + +/** TracedBuffer is a class to keep track of timestamps for a specific buffer in + * the TCP layer. We are only tracking timestamps for Linux kernels and hence + * this class would only be used by Linux platforms. For all other platforms, + * TracedBuffer would be an empty class. + * + * The timestamps collected are according to grpc_core::Timestamps declared + * above. + * + * A TracedBuffer list is kept track of using the head element of the list. If + * the head element of the list is nullptr, then the list is empty. + */ +#ifdef GRPC_LINUX_ERRQUEUE +class TracedBuffer { + public: + /** Add a new entry in the TracedBuffer list pointed to by head. Also saves + * sendmsg_time with the current timestamp. */ + static void AddNewEntry(grpc_core::TracedBuffer** head, uint32_t seq_no, + void* arg); + + /** Processes a received timestamp based on sock_extended_err and + * scm_timestamping structures. It will invoke the timestamps callback if the + * timestamp type is SCM_TSTAMP_ACK. */ + static void ProcessTimestamp(grpc_core::TracedBuffer** head, + struct sock_extended_err* serr, + struct scm_timestamping* tss); + + /** Cleans the list by calling the callback for each traced buffer in the list + * with timestamps that it has. */ + static void Shutdown(grpc_core::TracedBuffer** head, + grpc_error* shutdown_err); + + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + + TracedBuffer(int seq_no, void* arg) + : seq_no_(seq_no), arg_(arg), next_(nullptr) {} + + uint32_t seq_no_; /* The sequence number for the last byte in the buffer */ + void* arg_; /* The arg to pass to timestamps_callback */ + grpc_core::Timestamps ts_; /* The timestamps corresponding to this buffer */ + grpc_core::TracedBuffer* next_; /* The next TracedBuffer in the list */ +}; +#else /* GRPC_LINUX_ERRQUEUE */ +class TracedBuffer {}; +#endif /* GRPC_LINUX_ERRQUEUE */ + +/** Sets the callback function to call when timestamps for a write are + * collected. The callback does not own a reference to error. */ +void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*, + grpc_core::Timestamps*, + grpc_error* error)); + +}; /* namespace grpc_core */ + +#endif /* GRPC_CORE_LIB_IOMGR_BUFFER_LIST_H */ diff --git a/src/core/lib/iomgr/endpoint.cc b/src/core/lib/iomgr/endpoint.cc index 92e7930111..44fb47e19d 100644 --- a/src/core/lib/iomgr/endpoint.cc +++ b/src/core/lib/iomgr/endpoint.cc @@ -28,8 +28,8 @@ void grpc_endpoint_read(grpc_endpoint* ep, grpc_slice_buffer* slices, } void grpc_endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb) { - ep->vtable->write(ep, slices, cb); + grpc_closure* cb, void* arg) { + ep->vtable->write(ep, slices, cb, arg); } void grpc_endpoint_add_to_pollset(grpc_endpoint* ep, grpc_pollset* pollset) { diff --git a/src/core/lib/iomgr/endpoint.h b/src/core/lib/iomgr/endpoint.h index 15db1649fa..1f590a80ca 100644 --- a/src/core/lib/iomgr/endpoint.h +++ b/src/core/lib/iomgr/endpoint.h @@ -33,10 +33,12 @@ typedef struct grpc_endpoint grpc_endpoint; typedef struct grpc_endpoint_vtable grpc_endpoint_vtable; +class Timestamps; struct grpc_endpoint_vtable { void (*read)(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb); - void (*write)(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb); + void (*write)(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb, + void* arg); void (*add_to_pollset)(grpc_endpoint* ep, grpc_pollset* pollset); void (*add_to_pollset_set)(grpc_endpoint* ep, grpc_pollset_set* pollset); void (*delete_from_pollset_set)(grpc_endpoint* ep, grpc_pollset_set* pollset); @@ -70,9 +72,11 @@ int grpc_endpoint_get_fd(grpc_endpoint* ep); \a slices may be mutated at will by the endpoint until cb is called. No guarantee is made to the content of slices after a write EXCEPT that it is a valid slice buffer. + \a arg is platform specific. It is currently only used by TCP on linux + platforms as an argument that would be forwarded to the timestamps callback. */ void grpc_endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb); + grpc_closure* cb, void* arg); /* Causes any pending and future read/write callbacks to run immediately with success==0 */ diff --git a/src/core/lib/iomgr/endpoint_cfstream.cc b/src/core/lib/iomgr/endpoint_cfstream.cc index c3bc0cc8fd..df2cf508c8 100644 --- a/src/core/lib/iomgr/endpoint_cfstream.cc +++ b/src/core/lib/iomgr/endpoint_cfstream.cc @@ -268,7 +268,7 @@ static void CFStreamRead(grpc_endpoint* ep, grpc_slice_buffer* slices, } static void CFStreamWrite(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { CFStreamEndpoint* ep_impl = reinterpret_cast(ep); if (grpc_tcp_trace.enabled()) { gpr_log(GPR_DEBUG, "CFStream endpoint:%p write (%p, %p) length:%zu", diff --git a/src/core/lib/iomgr/endpoint_pair_posix.cc b/src/core/lib/iomgr/endpoint_pair_posix.cc index 5c5c246f99..3afbfd7254 100644 --- a/src/core/lib/iomgr/endpoint_pair_posix.cc +++ b/src/core/lib/iomgr/endpoint_pair_posix.cc @@ -59,11 +59,11 @@ grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char* name, grpc_core::ExecCtx exec_ctx; gpr_asprintf(&final_name, "%s:client", name); - p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name, false), args, + p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name, true), args, "socketpair-server"); gpr_free(final_name); gpr_asprintf(&final_name, "%s:server", name); - p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name, false), args, + p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name, true), args, "socketpair-client"); gpr_free(final_name); diff --git a/src/core/lib/iomgr/ev_posix.cc b/src/core/lib/iomgr/ev_posix.cc index 0205363d5c..d4377e2d50 100644 --- a/src/core/lib/iomgr/ev_posix.cc +++ b/src/core/lib/iomgr/ev_posix.cc @@ -237,14 +237,19 @@ void grpc_event_engine_shutdown(void) { } bool grpc_event_engine_can_track_errors(void) { +/* Only track errors if platform supports errqueue. */ +#ifdef GRPC_LINUX_ERRQUEUE return g_event_engine->can_track_err; +#else + return false; +#endif /* GRPC_LINUX_ERRQUEUE */ } grpc_fd* grpc_fd_create(int fd, const char* name, bool track_err) { GRPC_POLLING_API_TRACE("fd_create(%d, %s, %d)", fd, name, track_err); GRPC_FD_TRACE("fd_create(%d, %s, %d)", fd, name, track_err); - GPR_DEBUG_ASSERT(!track_err || g_event_engine->can_track_err); - return g_event_engine->fd_create(fd, name, track_err); + return g_event_engine->fd_create(fd, name, + track_err && g_event_engine->can_track_err); } int grpc_fd_wrapped_fd(grpc_fd* fd) { diff --git a/src/core/lib/iomgr/internal_errqueue.cc b/src/core/lib/iomgr/internal_errqueue.cc new file mode 100644 index 0000000000..8823737e49 --- /dev/null +++ b/src/core/lib/iomgr/internal_errqueue.cc @@ -0,0 +1,40 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/port.h" + +#include "src/core/lib/iomgr/internal_errqueue.h" + +#ifdef GRPC_POSIX_SOCKET_TCP + +#ifdef GPR_LINUX +#include +#endif /* GPR_LINUX */ + +bool kernel_supports_errqueue() { +#ifdef LINUX_VERSION_CODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) + return true; +#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(4, 0, 0) */ +#endif /* LINUX_VERSION_CODE */ + return false; +} + +#endif /* GRPC_POSIX_SOCKET_TCP */ diff --git a/src/core/lib/iomgr/internal_errqueue.h b/src/core/lib/iomgr/internal_errqueue.h new file mode 100644 index 0000000000..fc11be9a6d --- /dev/null +++ b/src/core/lib/iomgr/internal_errqueue.h @@ -0,0 +1,62 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* This file contains constants defined in and + * so as to allow collecting network timestamps in the + * kernel. This file allows tcp_posix.cc to compile on platforms that do not + * have and . + */ + +#ifndef GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H +#define GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H + +#include + +#include "src/core/lib/iomgr/port.h" + +#ifdef GRPC_POSIX_SOCKET_TCP + +#include +#include + +#ifdef GRPC_LINUX_ERRQUEUE +#include +#include +#include +#endif /* GRPC_LINUX_ERRQUEUE */ + +namespace grpc_core { + +#ifdef GRPC_LINUX_ERRQUEUE +constexpr uint32_t kTimestampingSocketOptions = SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_OPT_ID | + SOF_TIMESTAMPING_OPT_TSONLY; +constexpr uint32_t kTimestampingRecordingOptions = + SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_TX_ACK; +#endif /* GRPC_LINUX_ERRQUEUE */ + +/* Returns true if kernel is capable of supporting errqueue and timestamping. + * Currently allowing only linux kernels above 4.0.0 + */ +bool kernel_supports_errqueue(); +} // namespace grpc_core + +#endif /* GRPC_POSIX_SOCKET_TCP */ + +#endif /* GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H */ diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index 066417b93c..a4688fd0ef 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -60,6 +60,12 @@ #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 #define GRPC_HAVE_UNIX_SOCKET 1 +#include +#ifdef LINUX_VERSION_CODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) +#define GRPC_LINUX_ERRQUEUE 1 +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */ +#endif /* LINUX_VERSION_CODE */ #define GRPC_LINUX_MULTIPOLL_WITH_EPOLL 1 #define GRPC_POSIX_FORK 1 #define GRPC_POSIX_HOST_NAME_MAX 1 diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc index 296ee74311..9c989b7dfe 100644 --- a/src/core/lib/iomgr/tcp_client_posix.cc +++ b/src/core/lib/iomgr/tcp_client_posix.cc @@ -279,7 +279,7 @@ grpc_error* grpc_tcp_client_prepare_fd(const grpc_channel_args* channel_args, } addr_str = grpc_sockaddr_to_uri(mapped_addr); gpr_asprintf(&name, "tcp-client:%s", addr_str); - *fdobj = grpc_fd_create(fd, name, false); + *fdobj = grpc_fd_create(fd, name, true); gpr_free(name); gpr_free(addr_str); return GRPC_ERROR_NONE; diff --git a/src/core/lib/iomgr/tcp_custom.cc b/src/core/lib/iomgr/tcp_custom.cc index 990e8d632b..e02a1898f2 100644 --- a/src/core/lib/iomgr/tcp_custom.cc +++ b/src/core/lib/iomgr/tcp_custom.cc @@ -221,7 +221,7 @@ static void custom_write_callback(grpc_custom_socket* socket, } static void endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* write_slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)ep; GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index b53ffbf01c..1db2790265 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -27,7 +27,9 @@ #include #include +#include #include +#include #include #include #include @@ -46,6 +48,7 @@ #include "src/core/lib/debug/trace.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/useful.h" +#include "src/core/lib/iomgr/buffer_list.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/profiling/timers.h" @@ -97,17 +100,42 @@ struct grpc_tcp { grpc_closure read_done_closure; grpc_closure write_done_closure; + grpc_closure error_closure; char* peer_string; grpc_resource_user* resource_user; grpc_resource_user_slice_allocator slice_allocator; + + grpc_core::TracedBuffer* tb_head; /* List of traced buffers */ + gpr_mu tb_mu; /* Lock for access to list of traced buffers */ + + /* grpc_endpoint_write takes an argument which if non-null means that the + * transport layer wants the TCP layer to collect timestamps for this write. + * This arg is forwarded to the timestamps callback function when the ACK + * timestamp is received from the kernel. This arg is a (void *) which allows + * users of this API to pass in a pointer to any kind of structure. This + * structure could actually be a tag or any book-keeping object that the user + * can use to distinguish between different traced writes. The only + * requirement from the TCP endpoint layer is that this arg should be non-null + * if the user wants timestamps for the write. */ + void* outgoing_buffer_arg; + /* A counter which starts at 0. It is initialized the first time the socket + * options for collecting timestamps are set, and is incremented with each + * byte sent. */ + int bytes_counter; + bool socket_ts_enabled; /* True if timestamping options are set on the socket + */ + gpr_atm + stop_error_notification; /* Set to 1 if we do not want to be notified on + errors anymore */ }; struct backup_poller { gpr_mu* pollset_mu; grpc_closure run_poller; }; + } // namespace #define BACKUP_POLLER_POLLSET(b) ((grpc_pollset*)((b) + 1)) @@ -302,6 +330,7 @@ static void tcp_free(grpc_tcp* tcp) { grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer); grpc_resource_user_unref(tcp->resource_user); gpr_free(tcp->peer_string); + gpr_mu_destroy(&tcp->tb_mu); gpr_free(tcp); } @@ -347,6 +376,10 @@ static void tcp_destroy(grpc_endpoint* ep) { grpc_network_status_unregister_endpoint(ep); grpc_tcp* tcp = reinterpret_cast(ep); grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); + if (grpc_event_engine_can_track_errors()) { + gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); + grpc_fd_set_error(tcp->em_fd); + } TCP_UNREF(tcp, "destroy"); } @@ -513,6 +546,234 @@ static void tcp_read(grpc_endpoint* ep, grpc_slice_buffer* incoming_buffer, } } +/* A wrapper around sendmsg. It sends \a msg over \a fd and returns the number + * of bytes sent. */ +ssize_t tcp_send(int fd, const struct msghdr* msg) { + GPR_TIMER_SCOPE("sendmsg", 1); + ssize_t sent_length; + do { + /* TODO(klempner): Cork if this is a partial write */ + GRPC_STATS_INC_SYSCALL_WRITE(); + sent_length = sendmsg(fd, msg, SENDMSG_FLAGS); + } while (sent_length < 0 && errno == EINTR); + return sent_length; +} + +/** This is to be called if outgoing_buffer_arg is not null. On linux platforms, + * this will call sendmsg with socket options set to collect timestamps inside + * the kernel. On return, sent_length is set to the return value of the sendmsg + * call. Returns false if setting the socket options failed. This is not + * implemented for non-linux platforms currently, and crashes out. + */ +static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, + size_t sending_length, + ssize_t* sent_length, grpc_error** error); + +/** The callback function to be invoked when we get an error on the socket. */ +static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error); + +#ifdef GRPC_LINUX_ERRQUEUE +static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, + size_t sending_length, + ssize_t* sent_length, + grpc_error** error) { + if (!tcp->socket_ts_enabled) { + uint32_t opt = grpc_core::kTimestampingSocketOptions; + if (setsockopt(tcp->fd, SOL_SOCKET, SO_TIMESTAMPING, + static_cast(&opt), sizeof(opt)) != 0) { + *error = tcp_annotate_error(GRPC_OS_ERROR(errno, "setsockopt"), tcp); + grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer); + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_ERROR, "Failed to set timestamping options on the socket."); + } + return false; + } + tcp->bytes_counter = -1; + tcp->socket_ts_enabled = true; + } + /* Set control message to indicate that you want timestamps. */ + union { + char cmsg_buf[CMSG_SPACE(sizeof(uint32_t))]; + struct cmsghdr align; + } u; + cmsghdr* cmsg = reinterpret_cast(u.cmsg_buf); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMPING; + cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); + *reinterpret_cast(CMSG_DATA(cmsg)) = + grpc_core::kTimestampingRecordingOptions; + msg->msg_control = u.cmsg_buf; + msg->msg_controllen = CMSG_SPACE(sizeof(uint32_t)); + + /* If there was an error on sendmsg the logic in tcp_flush will handle it. */ + ssize_t length = tcp_send(tcp->fd, msg); + *sent_length = length; + /* Only save timestamps if all the bytes were taken by sendmsg. */ + if (sending_length == static_cast(length)) { + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::AddNewEntry( + &tcp->tb_head, static_cast(tcp->bytes_counter + length), + tcp->outgoing_buffer_arg); + gpr_mu_unlock(&tcp->tb_mu); + tcp->outgoing_buffer_arg = nullptr; + } + return true; +} + +/** Reads \a cmsg to derive timestamps from the control messages. If a valid + * timestamp is found, the traced buffer list is updated with this timestamp. + * The caller of this function should be looping on the control messages found + * in \a msg. \a cmsg should point to the control message that the caller wants + * processed. + * On return, a pointer to a control message is returned. On the next iteration, + * CMSG_NXTHDR(msg, ret_val) should be passed as \a cmsg. */ +struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg, + struct cmsghdr* cmsg) { + auto next_cmsg = CMSG_NXTHDR(msg, cmsg); + if (next_cmsg == nullptr) { + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_ERROR, "Received timestamp without extended error"); + } + return cmsg; + } + + if (!(next_cmsg->cmsg_level == SOL_IP || next_cmsg->cmsg_level == SOL_IPV6) || + !(next_cmsg->cmsg_type == IP_RECVERR || + next_cmsg->cmsg_type == IPV6_RECVERR)) { + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_ERROR, "Unexpected control message"); + } + return cmsg; + } + + auto tss = reinterpret_cast(CMSG_DATA(cmsg)); + auto serr = reinterpret_cast(CMSG_DATA(next_cmsg)); + if (serr->ee_errno != ENOMSG || + serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) { + gpr_log(GPR_ERROR, "Unexpected control message"); + return cmsg; + } + /* The error handling can potentially be done on another thread so we need + * to protect the traced buffer list. A lock free list might be better. Using + * a simple mutex for now. */ + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::ProcessTimestamp(&tcp->tb_head, serr, tss); + gpr_mu_unlock(&tcp->tb_mu); + return next_cmsg; +} + +/** For linux platforms, reads the socket's error queue and processes error + * messages from the queue. Returns true if all the errors processed were + * timestamps. Returns false if any of the errors were not timestamps. For + * non-linux platforms, error processing is not used/enabled currently. + */ +static bool process_errors(grpc_tcp* tcp) { + while (true) { + struct iovec iov; + iov.iov_base = nullptr; + iov.iov_len = 0; + struct msghdr msg; + msg.msg_name = nullptr; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 0; + msg.msg_flags = 0; + + union { + char rbuf[1024 /*CMSG_SPACE(sizeof(scm_timestamping)) + + CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in))*/]; + struct cmsghdr align; + } aligned_buf; + memset(&aligned_buf, 0, sizeof(aligned_buf)); + + msg.msg_control = aligned_buf.rbuf; + msg.msg_controllen = sizeof(aligned_buf.rbuf); + + int r, saved_errno; + do { + r = recvmsg(tcp->fd, &msg, MSG_ERRQUEUE); + saved_errno = errno; + } while (r < 0 && saved_errno == EINTR); + + if (r == -1 && saved_errno == EAGAIN) { + return true; /* No more errors to process */ + } + if (r == -1) { + return false; + } + if (grpc_tcp_trace.enabled()) { + if ((msg.msg_flags & MSG_CTRUNC) == 1) { + gpr_log(GPR_INFO, "Error message was truncated."); + } + } + + if (msg.msg_controllen == 0) { + /* There was no control message found. It was probably spurious. */ + return true; + } + for (auto cmsg = CMSG_FIRSTHDR(&msg); cmsg && cmsg->cmsg_len; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_TIMESTAMPING) { + /* Got a control message that is not a timestamp. Don't know how to + * handle this. */ + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, + "unknown control message cmsg_level:%d cmsg_type:%d", + cmsg->cmsg_level, cmsg->cmsg_type); + } + return false; + } + process_timestamp(tcp, &msg, cmsg); + } + } +} + +static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) { + grpc_tcp* tcp = static_cast(arg); + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP:%p got_error: %s", tcp, grpc_error_string(error)); + } + + if (error != GRPC_ERROR_NONE || + static_cast(gpr_atm_acq_load(&tcp->stop_error_notification))) { + /* We aren't going to register to hear on error anymore, so it is safe to + * unref. */ + grpc_core::TracedBuffer::Shutdown(&tcp->tb_head, GRPC_ERROR_REF(error)); + TCP_UNREF(tcp, "error-tracking"); + return; + } + + /* We are still interested in collecting timestamps, so let's try reading + * them. */ + if (!process_errors(tcp)) { + /* This was not a timestamps error. This was an actual error. Set the + * read and write closures to be ready. + */ + grpc_fd_set_readable(tcp->em_fd); + grpc_fd_set_writable(tcp->em_fd); + } + GRPC_CLOSURE_INIT(&tcp->error_closure, tcp_handle_error, tcp, + grpc_schedule_on_exec_ctx); + grpc_fd_notify_on_error(tcp->em_fd, &tcp->error_closure); +} + +#else /* GRPC_LINUX_ERRQUEUE */ +static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, + size_t sending_length, + ssize_t* sent_length, + grpc_error** error) { + gpr_log(GPR_ERROR, "Write with timestamps not supported for this platform"); + GPR_ASSERT(0); + return false; +} + +static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) { + gpr_log(GPR_ERROR, "Error handling is not supported for this platform"); + GPR_ASSERT(0); +} +#endif /* GRPC_LINUX_ERRQUEUE */ + /* returns true if done, false if pending; if returning true, *error is set */ #if defined(IOV_MAX) && IOV_MAX < 1000 #define MAX_WRITE_IOVEC IOV_MAX @@ -557,19 +818,20 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = iov_size; - msg.msg_control = nullptr; - msg.msg_controllen = 0; msg.msg_flags = 0; + if (tcp->outgoing_buffer_arg != nullptr) { + if (!tcp_write_with_timestamps(tcp, &msg, sending_length, &sent_length, + error)) + return true; /* something went wrong with timestamps */ + } else { + msg.msg_control = nullptr; + msg.msg_controllen = 0; - GRPC_STATS_INC_TCP_WRITE_SIZE(sending_length); - GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(iov_size); + GRPC_STATS_INC_TCP_WRITE_SIZE(sending_length); + GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(iov_size); - GPR_TIMER_SCOPE("sendmsg", 1); - do { - /* TODO(klempner): Cork if this is a partial write */ - GRPC_STATS_INC_SYSCALL_WRITE(); - sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS); - } while (sent_length < 0 && errno == EINTR); + sent_length = tcp_send(tcp->fd, &msg); + } if (sent_length < 0) { if (errno == EAGAIN) { @@ -593,6 +855,7 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { } GPR_ASSERT(tcp->outgoing_byte_idx == 0); + tcp->bytes_counter += sent_length; trailing = sending_length - static_cast(sent_length); while (trailing > 0) { size_t slice_length; @@ -607,7 +870,6 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { trailing -= slice_length; } } - if (outgoing_slice_idx == tcp->outgoing_buffer->count) { *error = GRPC_ERROR_NONE; grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer); @@ -640,14 +902,13 @@ static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error) { const char* str = grpc_error_string(error); gpr_log(GPR_INFO, "write: %s", str); } - GRPC_CLOSURE_SCHED(cb, error); TCP_UNREF(tcp, "write"); } } static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { GPR_TIMER_SCOPE("tcp_write", 0); grpc_tcp* tcp = reinterpret_cast(ep); grpc_error* error = GRPC_ERROR_NONE; @@ -675,6 +936,10 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, } tcp->outgoing_buffer = buf; tcp->outgoing_byte_idx = 0; + tcp->outgoing_buffer_arg = arg; + if (arg) { + GPR_ASSERT(grpc_event_engine_can_track_errors()); + } if (!tcp_flush(tcp, &error)) { TCP_REF(tcp, "write"); @@ -792,6 +1057,8 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd, tcp->bytes_read_this_round = 0; /* Will be set to false by the very first endpoint read function */ tcp->is_first_read = true; + tcp->bytes_counter = -1; + tcp->socket_ts_enabled = false; /* paired with unref in grpc_tcp_destroy */ gpr_ref_init(&tcp->refcount, 1); gpr_atm_no_barrier_store(&tcp->shutdown_count, 0); @@ -803,6 +1070,19 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd, /* Tell network status tracker about new endpoint */ grpc_network_status_register_endpoint(&tcp->base); grpc_resource_quota_unref_internal(resource_quota); + gpr_mu_init(&tcp->tb_mu); + tcp->tb_head = nullptr; + /* Start being notified on errors if event engine can track errors. */ + if (grpc_event_engine_can_track_errors()) { + /* Grab a ref to tcp so that we can safely access the tcp struct when + * processing errors. We unref when we no longer want to track errors + * separately. */ + TCP_REF(tcp, "error-tracking"); + gpr_atm_rel_store(&tcp->stop_error_notification, 0); + GRPC_CLOSURE_INIT(&tcp->error_closure, tcp_handle_error, tcp, + grpc_schedule_on_exec_ctx); + grpc_fd_notify_on_error(tcp->em_fd, &tcp->error_closure); + } return &tcp->base; } @@ -821,6 +1101,11 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd, tcp->release_fd = fd; tcp->release_fd_cb = done; grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); + if (grpc_event_engine_can_track_errors()) { + /* Stop errors notification. */ + gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); + grpc_fd_set_error(tcp->em_fd); + } TCP_UNREF(tcp, "destroy"); } diff --git a/src/core/lib/iomgr/tcp_posix.h b/src/core/lib/iomgr/tcp_posix.h index af89bd24db..eff825cb92 100644 --- a/src/core/lib/iomgr/tcp_posix.h +++ b/src/core/lib/iomgr/tcp_posix.h @@ -31,7 +31,10 @@ #include +#include "src/core/lib/iomgr/port.h" + #include "src/core/lib/debug/trace.h" +#include "src/core/lib/iomgr/buffer_list.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/ev_posix.h" diff --git a/src/core/lib/iomgr/tcp_server_posix.cc b/src/core/lib/iomgr/tcp_server_posix.cc index 8ddf684fea..824db07fbf 100644 --- a/src/core/lib/iomgr/tcp_server_posix.cc +++ b/src/core/lib/iomgr/tcp_server_posix.cc @@ -226,7 +226,7 @@ static void on_read(void* arg, grpc_error* err) { gpr_log(GPR_INFO, "SERVER_CONNECT: incoming connection: %s", addr_str); } - grpc_fd* fdobj = grpc_fd_create(fd, name, false); + grpc_fd* fdobj = grpc_fd_create(fd, name, true); read_notifier_pollset = sp->server->pollsets[static_cast(gpr_atm_no_barrier_fetch_add( @@ -362,7 +362,7 @@ static grpc_error* clone_port(grpc_tcp_listener* listener, unsigned count) { listener->sibling = sp; sp->server = listener->server; sp->fd = fd; - sp->emfd = grpc_fd_create(fd, name, false); + sp->emfd = grpc_fd_create(fd, name, true); memcpy(&sp->addr, &listener->addr, sizeof(grpc_resolved_address)); sp->port = port; sp->port_index = listener->port_index; diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc index b9f8145572..9595c028ce 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc @@ -105,7 +105,7 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, int fd, s->tail = sp; sp->server = s; sp->fd = fd; - sp->emfd = grpc_fd_create(fd, name, false); + sp->emfd = grpc_fd_create(fd, name, true); memcpy(&sp->addr, addr, sizeof(grpc_resolved_address)); sp->port = port; sp->port_index = port_index; diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc index b3cb442f18..64c4a56ae9 100644 --- a/src/core/lib/iomgr/tcp_windows.cc +++ b/src/core/lib/iomgr/tcp_windows.cc @@ -296,7 +296,7 @@ static void on_write(void* tcpp, grpc_error* error) { /* Initiates a write. */ static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { grpc_tcp* tcp = (grpc_tcp*)ep; grpc_winsocket* socket = tcp->socket; grpc_winsocket_callback_info* info = &socket->write_info; diff --git a/src/core/lib/iomgr/udp_server.cc b/src/core/lib/iomgr/udp_server.cc index bdb2d0e764..3dd7cab855 100644 --- a/src/core/lib/iomgr/udp_server.cc +++ b/src/core/lib/iomgr/udp_server.cc @@ -152,7 +152,7 @@ GrpcUdpListener::GrpcUdpListener(grpc_udp_server* server, int fd, grpc_sockaddr_to_string(&addr_str, addr, 1); gpr_asprintf(&name, "udp-server-listener:%s", addr_str); gpr_free(addr_str); - emfd_ = grpc_fd_create(fd, name, false); + emfd_ = grpc_fd_create(fd, name, true); memcpy(&addr_, addr, sizeof(grpc_resolved_address)); GPR_ASSERT(emfd_); gpr_free(name); diff --git a/src/core/lib/security/transport/secure_endpoint.cc b/src/core/lib/security/transport/secure_endpoint.cc index 840b2e73bc..f40f969bb7 100644 --- a/src/core/lib/security/transport/secure_endpoint.cc +++ b/src/core/lib/security/transport/secure_endpoint.cc @@ -254,7 +254,7 @@ static void flush_write_staging_buffer(secure_endpoint* ep, uint8_t** cur, } static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { GPR_TIMER_SCOPE("secure_endpoint.endpoint_write", 0); unsigned i; @@ -342,7 +342,7 @@ static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices, return; } - grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb); + grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb, arg); } static void endpoint_shutdown(grpc_endpoint* secure_ep, grpc_error* why) { diff --git a/src/core/lib/security/transport/security_handshaker.cc b/src/core/lib/security/transport/security_handshaker.cc index aff723ed04..d76d582638 100644 --- a/src/core/lib/security/transport/security_handshaker.cc +++ b/src/core/lib/security/transport/security_handshaker.cc @@ -259,7 +259,7 @@ static grpc_error* on_handshake_next_done_locked( grpc_slice_buffer_reset_and_unref_internal(&h->outgoing); grpc_slice_buffer_add(&h->outgoing, to_send); grpc_endpoint_write(h->args->endpoint, &h->outgoing, - &h->on_handshake_data_sent_to_peer); + &h->on_handshake_data_sent_to_peer, nullptr); } else if (handshaker_result == nullptr) { // There is nothing to send, but need to read from peer. grpc_endpoint_read(h->args->endpoint, h->args->read_buffer, diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 6e6d756eec..0f68e823d7 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -82,6 +82,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/http/format_request.cc', 'src/core/lib/http/httpcli.cc', 'src/core/lib/http/parser.cc', + 'src/core/lib/iomgr/buffer_list.cc', 'src/core/lib/iomgr/call_combiner.cc', 'src/core/lib/iomgr/combiner.cc', 'src/core/lib/iomgr/endpoint.cc', @@ -102,6 +103,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', 'src/core/lib/iomgr/iomgr_custom.cc', diff --git a/test/core/bad_client/bad_client.cc b/test/core/bad_client/bad_client.cc index c03ebcf409..ade23133c5 100644 --- a/test/core/bad_client/bad_client.cc +++ b/test/core/bad_client/bad_client.cc @@ -115,7 +115,7 @@ void grpc_run_client_side_validator(grpc_bad_client_arg* arg, uint32_t flags, grpc_schedule_on_exec_ctx); /* Write data */ - grpc_endpoint_write(sfd->client, &outgoing, &done_write_closure); + grpc_endpoint_write(sfd->client, &outgoing, &done_write_closure, nullptr); grpc_core::ExecCtx::Get()->Flush(); /* Await completion, unless the request is large and write may not finish diff --git a/test/core/end2end/bad_server_response_test.cc b/test/core/end2end/bad_server_response_test.cc index 3d133cfc18..f7396a1684 100644 --- a/test/core/end2end/bad_server_response_test.cc +++ b/test/core/end2end/bad_server_response_test.cc @@ -104,7 +104,7 @@ static void handle_write() { grpc_slice_buffer_reset_and_unref(&state.outgoing_buffer); grpc_slice_buffer_add(&state.outgoing_buffer, slice); - grpc_endpoint_write(state.tcp, &state.outgoing_buffer, &on_write); + grpc_endpoint_write(state.tcp, &state.outgoing_buffer, &on_write, nullptr); } static void handle_read(void* arg, grpc_error* error) { diff --git a/test/core/end2end/fixtures/http_proxy_fixture.cc b/test/core/end2end/fixtures/http_proxy_fixture.cc index f02fa9d998..ea9c000efb 100644 --- a/test/core/end2end/fixtures/http_proxy_fixture.cc +++ b/test/core/end2end/fixtures/http_proxy_fixture.cc @@ -201,7 +201,7 @@ static void on_client_write_done(void* arg, grpc_error* error) { &conn->client_write_buffer); conn->client_is_writing = true; grpc_endpoint_write(conn->client_endpoint, &conn->client_write_buffer, - &conn->on_client_write_done); + &conn->on_client_write_done, nullptr); } else { // No more writes. Unref the connection. proxy_connection_unref(conn, "write_done"); @@ -226,7 +226,7 @@ static void on_server_write_done(void* arg, grpc_error* error) { &conn->server_write_buffer); conn->server_is_writing = true; grpc_endpoint_write(conn->server_endpoint, &conn->server_write_buffer, - &conn->on_server_write_done); + &conn->on_server_write_done, nullptr); } else { // No more writes. Unref the connection. proxy_connection_unref(conn, "server_write"); @@ -257,7 +257,7 @@ static void on_client_read_done(void* arg, grpc_error* error) { proxy_connection_ref(conn, "client_read"); conn->server_is_writing = true; grpc_endpoint_write(conn->server_endpoint, &conn->server_write_buffer, - &conn->on_server_write_done); + &conn->on_server_write_done, nullptr); } // Read more data. grpc_endpoint_read(conn->client_endpoint, &conn->client_read_buffer, @@ -288,7 +288,7 @@ static void on_server_read_done(void* arg, grpc_error* error) { proxy_connection_ref(conn, "server_read"); conn->client_is_writing = true; grpc_endpoint_write(conn->client_endpoint, &conn->client_write_buffer, - &conn->on_client_write_done); + &conn->on_client_write_done, nullptr); } // Read more data. grpc_endpoint_read(conn->server_endpoint, &conn->server_read_buffer, @@ -340,7 +340,7 @@ static void on_server_connect_done(void* arg, grpc_error* error) { grpc_slice_buffer_add(&conn->client_write_buffer, slice); conn->client_is_writing = true; grpc_endpoint_write(conn->client_endpoint, &conn->client_write_buffer, - &conn->on_write_response_done); + &conn->on_write_response_done, nullptr); } /** diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index 002671a5fa..675d9e6278 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -246,6 +246,19 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "buffer_list_test", + srcs = ["buffer_list_test.cc"], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + + grpc_cc_test( name = "tcp_server_posix_test", srcs = ["tcp_server_posix_test.cc"], diff --git a/test/core/iomgr/buffer_list_test.cc b/test/core/iomgr/buffer_list_test.cc new file mode 100644 index 0000000000..f1773580bd --- /dev/null +++ b/test/core/iomgr/buffer_list_test.cc @@ -0,0 +1,111 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/iomgr/port.h" + +#include "src/core/lib/iomgr/buffer_list.h" + +#include + +#include "test/core/util/test_config.h" + +#ifdef GRPC_LINUX_ERRQUEUE + +static void TestShutdownFlushesListVerifier(void* arg, + grpc_core::Timestamps* ts, + grpc_error* error) { + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(arg != nullptr); + gpr_atm* done = reinterpret_cast(arg); + gpr_atm_rel_store(done, static_cast(1)); +} + +/** Tests that all TracedBuffer elements in the list are flushed out on + * shutdown. + * Also tests that arg is passed correctly. + */ +static void TestShutdownFlushesList() { + grpc_core::grpc_tcp_set_write_timestamps_callback( + TestShutdownFlushesListVerifier); + grpc_core::TracedBuffer* list = nullptr; +#define NUM_ELEM 5 + gpr_atm verifier_called[NUM_ELEM]; + for (auto i = 0; i < NUM_ELEM; i++) { + gpr_atm_rel_store(&verifier_called[i], static_cast(0)); + grpc_core::TracedBuffer::AddNewEntry( + &list, i, static_cast(&verifier_called[i])); + } + grpc_core::TracedBuffer::Shutdown(&list, GRPC_ERROR_NONE); + GPR_ASSERT(list == nullptr); + for (auto i = 0; i < NUM_ELEM; i++) { + GPR_ASSERT(gpr_atm_acq_load(&verifier_called[i]) == + static_cast(1)); + } +} + +static void TestVerifierCalledOnAckVerifier(void* arg, + grpc_core::Timestamps* ts, + grpc_error* error) { + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(arg != nullptr); + GPR_ASSERT(ts->acked_time.clock_type == GPR_CLOCK_REALTIME); + GPR_ASSERT(ts->acked_time.tv_sec == 123); + GPR_ASSERT(ts->acked_time.tv_nsec == 456); + gpr_atm* done = reinterpret_cast(arg); + gpr_atm_rel_store(done, static_cast(1)); +} + +/** Tests that the timestamp verifier is called on an ACK timestamp. + */ +static void TestVerifierCalledOnAck() { + struct sock_extended_err serr; + serr.ee_data = 213; + serr.ee_info = SCM_TSTAMP_ACK; + struct scm_timestamping tss; + tss.ts[0].tv_sec = 123; + tss.ts[0].tv_nsec = 456; + grpc_core::grpc_tcp_set_write_timestamps_callback( + TestVerifierCalledOnAckVerifier); + grpc_core::TracedBuffer* list = nullptr; + gpr_atm verifier_called; + gpr_atm_rel_store(&verifier_called, static_cast(0)); + grpc_core::TracedBuffer::AddNewEntry(&list, 213, &verifier_called); + grpc_core::TracedBuffer::ProcessTimestamp(&list, &serr, &tss); + GPR_ASSERT(gpr_atm_acq_load(&verifier_called) == static_cast(1)); + GPR_ASSERT(list == nullptr); + grpc_core::TracedBuffer::Shutdown(&list, GRPC_ERROR_NONE); +} + +static void TestTcpBufferList() { + TestVerifierCalledOnAck(); + TestShutdownFlushesList(); +} + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + grpc_init(); + TestTcpBufferList(); + grpc_shutdown(); + return 0; +} + +#else /* GRPC_LINUX_ERRQUEUE */ + +int main(int argc, char** argv) { return 0; } + +#endif /* GRPC_LINUX_ERRQUEUE */ diff --git a/test/core/iomgr/endpoint_tests.cc b/test/core/iomgr/endpoint_tests.cc index 8db8ac5ed6..a9e8ba86c5 100644 --- a/test/core/iomgr/endpoint_tests.cc +++ b/test/core/iomgr/endpoint_tests.cc @@ -150,8 +150,8 @@ static void read_and_write_test_write_handler(void* data, grpc_error* error) { &state->current_write_data); grpc_slice_buffer_reset_and_unref(&state->outgoing); grpc_slice_buffer_addn(&state->outgoing, slices, nslices); - grpc_endpoint_write(state->write_ep, &state->outgoing, - &state->done_write); + grpc_endpoint_write(state->write_ep, &state->outgoing, &state->done_write, + nullptr); gpr_free(slices); return; } @@ -294,7 +294,8 @@ static void multiple_shutdown_test(grpc_endpoint_test_config config) { grpc_slice_buffer_add(&slice_buffer, grpc_slice_from_copied_string("a")); grpc_endpoint_write(f.client_ep, &slice_buffer, GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, - grpc_schedule_on_exec_ctx)); + grpc_schedule_on_exec_ctx), + nullptr); wait_for_fail_count(&fail_count, 3); grpc_endpoint_shutdown(f.client_ep, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); diff --git a/test/core/iomgr/tcp_posix_test.cc b/test/core/iomgr/tcp_posix_test.cc index 3e87831e44..6447cc234d 100644 --- a/test/core/iomgr/tcp_posix_test.cc +++ b/test/core/iomgr/tcp_posix_test.cc @@ -36,6 +36,9 @@ #include #include "src/core/lib/gpr/useful.h" +#include "src/core/lib/iomgr/buffer_list.h" +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/sockaddr_posix.h" #include "src/core/lib/slice/slice_internal.h" #include "test/core/iomgr/endpoint_tests.h" #include "test/core/util/test_config.h" @@ -68,6 +71,43 @@ static void create_sockets(int sv[2]) { GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); } +static void create_inet_sockets(int sv[2]) { + /* Prepare listening socket */ + struct sockaddr_in addr; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + int sock = socket(AF_INET, SOCK_STREAM, 0); + GPR_ASSERT(sock); + GPR_ASSERT(bind(sock, (sockaddr*)&addr, sizeof(sockaddr_in)) == 0); + listen(sock, 1); + + /* Prepare client socket and connect to server */ + socklen_t len = sizeof(sockaddr_in); + GPR_ASSERT(getsockname(sock, (sockaddr*)&addr, &len) == 0); + + int client = socket(AF_INET, SOCK_STREAM, 0); + GPR_ASSERT(client); + int ret; + do { + ret = connect(client, (sockaddr*)&addr, sizeof(sockaddr_in)); + } while (ret == -1 && errno == EINTR); + + /* Accept client connection */ + len = sizeof(socklen_t); + int server; + do { + server = accept(sock, (sockaddr*)&addr, (socklen_t*)&len); + } while (server == -1 && errno == EINTR); + GPR_ASSERT(server != -1); + + sv[0] = server; + sv[1] = client; + int flags = fcntl(sv[0], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); + flags = fcntl(sv[1], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); +} + static ssize_t fill_socket(int fd) { ssize_t write_bytes; ssize_t total_bytes = 0; @@ -289,11 +329,10 @@ static grpc_slice* allocate_blocks(size_t num_bytes, size_t slice_size, static void write_done(void* user_data /* write_socket_state */, grpc_error* error) { + GPR_ASSERT(error == GRPC_ERROR_NONE); struct write_socket_state* state = static_cast(user_data); - gpr_log(GPR_INFO, "Write done callback called"); gpr_mu_lock(g_mu); - gpr_log(GPR_INFO, "Signalling write done"); state->write_done = 1; GPR_ASSERT( GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, nullptr))); @@ -340,10 +379,24 @@ void drain_socket_blocking(int fd, size_t num_bytes, size_t read_size) { gpr_free(buf); } +/* Verifier for timestamps callback for write_test */ +void timestamps_verifier(void* arg, grpc_core::Timestamps* ts, + grpc_error* error) { + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(arg != nullptr); + GPR_ASSERT(ts->sendmsg_time.clock_type == GPR_CLOCK_REALTIME); + GPR_ASSERT(ts->scheduled_time.clock_type == GPR_CLOCK_REALTIME); + GPR_ASSERT(ts->acked_time.clock_type == GPR_CLOCK_REALTIME); + gpr_atm* done_timestamps = (gpr_atm*)arg; + gpr_atm_rel_store(done_timestamps, static_cast(1)); +} + /* Write to a socket using the grpc_tcp API, then drain it directly. Note that if the write does not complete immediately we need to drain the - socket in parallel with the read. */ -static void write_test(size_t num_bytes, size_t slice_size) { + socket in parallel with the read. If collect_timestamps is true, it will + try to get timestamps for the write. */ +static void write_test(size_t num_bytes, size_t slice_size, + bool collect_timestamps) { int sv[2]; grpc_endpoint* ep; struct write_socket_state state; @@ -356,19 +409,27 @@ static void write_test(size_t num_bytes, size_t slice_size) { grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(20)); grpc_core::ExecCtx exec_ctx; + if (collect_timestamps && !grpc_event_engine_can_track_errors()) { + return; + } + gpr_log(GPR_INFO, "Start write test with %" PRIuPTR " bytes, slice size %" PRIuPTR, num_bytes, slice_size); - create_sockets(sv); + if (collect_timestamps) { + create_inet_sockets(sv); + } else { + create_sockets(sv); + } grpc_arg a[1]; a[0].key = const_cast(GRPC_ARG_TCP_READ_CHUNK_SIZE); a[0].type = GRPC_ARG_INTEGER, a[0].value.integer = static_cast(slice_size); grpc_channel_args args = {GPR_ARRAY_SIZE(a), a}; - ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_test", false), &args, - "test"); + ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_test", collect_timestamps), + &args, "test"); grpc_endpoint_add_to_pollset(ep, g_pollset); state.ep = ep; @@ -381,18 +442,26 @@ static void write_test(size_t num_bytes, size_t slice_size) { GRPC_CLOSURE_INIT(&write_done_closure, write_done, &state, grpc_schedule_on_exec_ctx); - grpc_endpoint_write(ep, &outgoing, &write_done_closure); + gpr_atm done_timestamps; + gpr_atm_rel_store(&done_timestamps, static_cast(0)); + grpc_endpoint_write(ep, &outgoing, &write_done_closure, + grpc_event_engine_can_track_errors() && collect_timestamps + ? (void*)&done_timestamps + : nullptr); drain_socket_blocking(sv[0], num_bytes, num_bytes); + exec_ctx.Flush(); gpr_mu_lock(g_mu); for (;;) { grpc_pollset_worker* worker = nullptr; - if (state.write_done) { + if (state.write_done && + (!(grpc_event_engine_can_track_errors() && collect_timestamps) || + gpr_atm_acq_load(&done_timestamps) == static_cast(1))) { break; } GPR_ASSERT(GRPC_LOG_IF_ERROR( "pollset_work", grpc_pollset_work(g_pollset, &worker, deadline))); gpr_mu_unlock(g_mu); - + exec_ctx.Flush(); gpr_mu_lock(g_mu); } gpr_mu_unlock(g_mu); @@ -497,14 +566,21 @@ void run_tests(void) { large_read_test(8192); large_read_test(1); - write_test(100, 8192); - write_test(100, 1); - write_test(100000, 8192); - write_test(100000, 1); - write_test(100000, 137); + write_test(100, 8192, false); + write_test(100, 1, false); + write_test(100000, 8192, false); + write_test(100000, 1, false); + write_test(100000, 137, false); + + write_test(100, 8192, true); + write_test(100, 1, true); + write_test(100000, 8192, true); + write_test(100000, 1, true); + write_test(100, 137, true); for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { - write_test(40320, i); + write_test(40320, i, false); + write_test(40320, i, true); } release_fd_test(100, 8192); @@ -549,6 +625,7 @@ int main(int argc, char** argv) { grpc_closure destroyed; grpc_test_init(argc, argv); grpc_init(); + grpc_core::grpc_tcp_set_write_timestamps_callback(timestamps_verifier); { grpc_core::ExecCtx exec_ctx; g_pollset = static_cast(gpr_zalloc(grpc_pollset_size())); diff --git a/test/core/util/mock_endpoint.cc b/test/core/util/mock_endpoint.cc index 1156cd5fc5..ef6fd62b51 100644 --- a/test/core/util/mock_endpoint.cc +++ b/test/core/util/mock_endpoint.cc @@ -55,7 +55,7 @@ static void me_read(grpc_endpoint* ep, grpc_slice_buffer* slices, } static void me_write(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { mock_endpoint* m = reinterpret_cast(ep); for (size_t i = 0; i < slices->count; i++) { m->on_write(slices->slices[i]); diff --git a/test/core/util/passthru_endpoint.cc b/test/core/util/passthru_endpoint.cc index 5958216747..3cc8ad6fe1 100644 --- a/test/core/util/passthru_endpoint.cc +++ b/test/core/util/passthru_endpoint.cc @@ -76,7 +76,7 @@ static half* other_half(half* h) { } static void me_write(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { half* m = other_half(reinterpret_cast(ep)); gpr_mu_lock(&m->parent->mu); grpc_error* error = GRPC_ERROR_NONE; diff --git a/test/core/util/trickle_endpoint.cc b/test/core/util/trickle_endpoint.cc index f2efb049b4..62ed72a629 100644 --- a/test/core/util/trickle_endpoint.cc +++ b/test/core/util/trickle_endpoint.cc @@ -62,7 +62,7 @@ static void maybe_call_write_cb_locked(trickle_endpoint* te) { } static void te_write(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { trickle_endpoint* te = reinterpret_cast(ep); gpr_mu_lock(&te->mu); GPR_ASSERT(te->write_cb == nullptr); @@ -186,7 +186,8 @@ size_t grpc_trickle_endpoint_trickle(grpc_endpoint* ep) { te->last_write = now; grpc_endpoint_write( te->wrapped, &te->writing_buffer, - GRPC_CLOSURE_CREATE(te_finish_write, te, grpc_schedule_on_exec_ctx)); + GRPC_CLOSURE_CREATE(te_finish_write, te, grpc_schedule_on_exec_ctx), + nullptr); maybe_call_write_cb_locked(te); } } diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc index 1e9bd273aa..189923a841 100644 --- a/test/cpp/microbenchmarks/bm_chttp2_transport.cc +++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc @@ -96,7 +96,7 @@ class DummyEndpoint : public grpc_endpoint { } static void write(grpc_endpoint* ep, grpc_slice_buffer* slices, - grpc_closure* cb) { + grpc_closure* cb, void* arg) { GRPC_CLOSURE_SCHED(cb, GRPC_ERROR_NONE); } diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 43ebf8cad9..e6d4b1d98f 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1067,6 +1067,7 @@ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ src/core/lib/http/parser.h \ src/core/lib/iomgr/block_annotate.h \ +src/core/lib/iomgr/buffer_list.h \ src/core/lib/iomgr/call_combiner.h \ src/core/lib/iomgr/closure.h \ src/core/lib/iomgr/combiner.h \ @@ -1082,6 +1083,7 @@ src/core/lib/iomgr/ev_posix.h \ src/core/lib/iomgr/exec_ctx.h \ src/core/lib/iomgr/executor.h \ src/core/lib/iomgr/gethostname.h \ +src/core/lib/iomgr/internal_errqueue.h \ src/core/lib/iomgr/iocp_windows.h \ src/core/lib/iomgr/iomgr.h \ src/core/lib/iomgr/iomgr_custom.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index c1706fd070..7cd1dc7bf3 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1159,6 +1159,8 @@ src/core/lib/http/parser.cc \ src/core/lib/http/parser.h \ src/core/lib/iomgr/README.md \ src/core/lib/iomgr/block_annotate.h \ +src/core/lib/iomgr/buffer_list.cc \ +src/core/lib/iomgr/buffer_list.h \ src/core/lib/iomgr/call_combiner.cc \ src/core/lib/iomgr/call_combiner.h \ src/core/lib/iomgr/closure.h \ @@ -1194,6 +1196,8 @@ src/core/lib/iomgr/gethostname.h \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ +src/core/lib/iomgr/internal_errqueue.cc \ +src/core/lib/iomgr/internal_errqueue.h \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iocp_windows.h \ src/core/lib/iomgr/iomgr.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 5014aea9cd..8ea5126fde 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -163,6 +163,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "buffer_list_test", + "src": [ + "test/core/iomgr/buffer_list_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -9488,6 +9505,7 @@ "src/core/lib/http/format_request.cc", "src/core/lib/http/httpcli.cc", "src/core/lib/http/parser.cc", + "src/core/lib/iomgr/buffer_list.cc", "src/core/lib/iomgr/call_combiner.cc", "src/core/lib/iomgr/combiner.cc", "src/core/lib/iomgr/endpoint.cc", @@ -9508,6 +9526,7 @@ "src/core/lib/iomgr/gethostname_fallback.cc", "src/core/lib/iomgr/gethostname_host_name_max.cc", "src/core/lib/iomgr/gethostname_sysconf.cc", + "src/core/lib/iomgr/internal_errqueue.cc", "src/core/lib/iomgr/iocp_windows.cc", "src/core/lib/iomgr/iomgr.cc", "src/core/lib/iomgr/iomgr_custom.cc", @@ -9667,6 +9686,7 @@ "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/block_annotate.h", + "src/core/lib/iomgr/buffer_list.h", "src/core/lib/iomgr/call_combiner.h", "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/combiner.h", @@ -9682,6 +9702,7 @@ "src/core/lib/iomgr/exec_ctx.h", "src/core/lib/iomgr/executor.h", "src/core/lib/iomgr/gethostname.h", + "src/core/lib/iomgr/internal_errqueue.h", "src/core/lib/iomgr/iocp_windows.h", "src/core/lib/iomgr/iomgr.h", "src/core/lib/iomgr/iomgr_custom.h", @@ -9817,6 +9838,7 @@ "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/block_annotate.h", + "src/core/lib/iomgr/buffer_list.h", "src/core/lib/iomgr/call_combiner.h", "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/combiner.h", @@ -9832,6 +9854,7 @@ "src/core/lib/iomgr/exec_ctx.h", "src/core/lib/iomgr/executor.h", "src/core/lib/iomgr/gethostname.h", + "src/core/lib/iomgr/internal_errqueue.h", "src/core/lib/iomgr/iocp_windows.h", "src/core/lib/iomgr/iomgr.h", "src/core/lib/iomgr/iomgr_custom.h", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 51c7b57d8a..fba76d69d1 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -195,6 +195,26 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "gtest": false, + "language": "c", + "name": "buffer_list_test", + "platforms": [ + "linux" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, -- cgit v1.2.3 From 0cb982974f12ead39b6a8969949f2fbbe59cf3cf Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 27 Aug 2018 15:10:25 -0700 Subject: Remove linux/version.h include from port.h --- src/core/lib/iomgr/internal_errqueue.cc | 4 ---- src/core/lib/iomgr/port.h | 1 - 2 files changed, 5 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/internal_errqueue.cc b/src/core/lib/iomgr/internal_errqueue.cc index 8823737e49..99c22e9055 100644 --- a/src/core/lib/iomgr/internal_errqueue.cc +++ b/src/core/lib/iomgr/internal_errqueue.cc @@ -24,10 +24,6 @@ #ifdef GRPC_POSIX_SOCKET_TCP -#ifdef GPR_LINUX -#include -#endif /* GPR_LINUX */ - bool kernel_supports_errqueue() { #ifdef LINUX_VERSION_CODE #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index a4688fd0ef..abf96662f5 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -60,7 +60,6 @@ #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 #define GRPC_HAVE_UNIX_SOCKET 1 -#include #ifdef LINUX_VERSION_CODE #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) #define GRPC_LINUX_ERRQUEUE 1 -- cgit v1.2.3 From f8a4aae1197e586d5c34f1acff450eac4d764c4b Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 1 Aug 2018 08:36:03 -0700 Subject: Fix all instances of bugprone-undefined-memory-manipulation --- .clang-tidy | 4 ++-- src/core/ext/filters/client_channel/client_channel.cc | 1 - src/core/lib/surface/channel.cc | 1 - src/core/tsi/alts_transport_security.cc | 4 +++- test/.clang-tidy | 6 ++++++ test/core/end2end/fixtures/http_proxy_fixture.cc | 18 ++++++++++++------ test/core/end2end/fixtures/proxy.cc | 17 +++++++++++++---- test/cpp/util/.clang-tidy | 6 ------ 8 files changed, 36 insertions(+), 21 deletions(-) create mode 100644 test/.clang-tidy delete mode 100644 test/cpp/util/.clang-tidy (limited to 'src/core/lib') diff --git a/.clang-tidy b/.clang-tidy index fbf0b6541e..d217441792 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,6 @@ --- -Checks: 'modernize-use-nullptr,google-build-namespaces,google-build-explicit-make-pair,readability-function-size,performance-*' -WarningsAsErrors: 'modernize-use-nullptr,google-build-namespaces,google-build-explicit-make-pair,readability-function-size,performance-*' +Checks: 'modernize-use-nullptr,google-build-namespaces,google-build-explicit-make-pair,readability-function-size,performance-*,bugprone-*' +WarningsAsErrors: 'modernize-use-nullptr,google-build-namespaces,google-build-explicit-make-pair,readability-function-size,performance-*,bugprone-*' CheckOptions: - key: readability-function-size.StatementThreshold value: '450' diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index b06f09d8c7..b2275441e5 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -457,7 +457,6 @@ get_service_config_from_resolver_result_locked(channel_data* chand) { grpc_uri* uri = grpc_uri_parse(server_uri, true); GPR_ASSERT(uri->path[0] != '\0'); service_config_parsing_state parsing_state; - memset(&parsing_state, 0, sizeof(parsing_state)); parsing_state.server_name = uri->path[0] == '/' ? uri->path + 1 : uri->path; service_config->ParseGlobalParams(parse_retry_throttle_params, diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 82635d3c21..e3dde51d69 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -100,7 +100,6 @@ grpc_channel* grpc_channel_create_with_builder( return channel; } - memset(channel, 0, sizeof(*channel)); channel->target = target; channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type); size_t channel_tracer_max_nodes = 0; // default to off diff --git a/src/core/tsi/alts_transport_security.cc b/src/core/tsi/alts_transport_security.cc index 2fd408103b..dac23bbf7a 100644 --- a/src/core/tsi/alts_transport_security.cc +++ b/src/core/tsi/alts_transport_security.cc @@ -45,7 +45,9 @@ void grpc_tsi_alts_signal_for_cq_destroy() { } void grpc_tsi_alts_init() { - memset(&g_alts_resource, 0, sizeof(alts_shared_resource)); + g_alts_resource.channel = nullptr; + g_alts_resource.cq = nullptr; + g_alts_resource.is_cq_drained = false; gpr_mu_init(&g_alts_resource.mu); gpr_cv_init(&g_alts_resource.cv); } diff --git a/test/.clang-tidy b/test/.clang-tidy new file mode 100644 index 0000000000..f951ee5fea --- /dev/null +++ b/test/.clang-tidy @@ -0,0 +1,6 @@ +--- +Checks: 'modernize-use-nullptr,google-build-namespaces,google-build-explicit-make-pair,readability-function-size,performance-*,-performance-unnecessary-copy-initialization' +WarningsAsErrors: 'modernize-use-nullptr,google-build-namespaces,google-build-explicit-make-pair,readability-function-size,performance-*,-performance-unnecessary-copy-initialization' +CheckOptions: + - key: readability-function-size.StatementThreshold + value: '450' diff --git a/test/core/end2end/fixtures/http_proxy_fixture.cc b/test/core/end2end/fixtures/http_proxy_fixture.cc index f02fa9d998..6f444bf66a 100644 --- a/test/core/end2end/fixtures/http_proxy_fixture.cc +++ b/test/core/end2end/fixtures/http_proxy_fixture.cc @@ -52,6 +52,16 @@ #include "test/core/util/port.h" struct grpc_end2end_http_proxy { + grpc_end2end_http_proxy() + : proxy_name(nullptr), + server(nullptr), + channel_args(nullptr), + mu(nullptr), + pollset(nullptr), + combiner(nullptr) { + gpr_ref_init(&users, 1); + combiner = grpc_combiner_create(); + } char* proxy_name; grpc_core::Thread thd; grpc_tcp_server* server; @@ -519,11 +529,7 @@ static void thread_main(void* arg) { grpc_end2end_http_proxy* grpc_end2end_http_proxy_create( grpc_channel_args* args) { grpc_core::ExecCtx exec_ctx; - grpc_end2end_http_proxy* proxy = - static_cast(gpr_malloc(sizeof(*proxy))); - memset(proxy, 0, sizeof(*proxy)); - proxy->combiner = grpc_combiner_create(); - gpr_ref_init(&proxy->users, 1); + grpc_end2end_http_proxy* proxy = grpc_core::New(); // Construct proxy address. const int proxy_port = grpc_pick_unused_port_or_die(); gpr_join_host_port(&proxy->proxy_name, "localhost", proxy_port); @@ -573,7 +579,7 @@ void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) { GRPC_CLOSURE_CREATE(destroy_pollset, proxy->pollset, grpc_schedule_on_exec_ctx)); GRPC_COMBINER_UNREF(proxy->combiner, "test"); - gpr_free(proxy); + grpc_core::Delete(proxy); } const char* grpc_end2end_http_proxy_get_proxy_name( diff --git a/test/core/end2end/fixtures/proxy.cc b/test/core/end2end/fixtures/proxy.cc index 042c858b4c..869b6e846d 100644 --- a/test/core/end2end/fixtures/proxy.cc +++ b/test/core/end2end/fixtures/proxy.cc @@ -30,6 +30,17 @@ #include "test/core/util/port.h" struct grpc_end2end_proxy { + grpc_end2end_proxy() + : proxy_port(nullptr), + server_port(nullptr), + cq(nullptr), + server(nullptr), + client(nullptr), + shutdown(false), + new_call(nullptr) { + memset(&new_call_details, 0, sizeof(new_call_details)); + memset(&new_call_metadata, 0, sizeof(new_call_metadata)); + } grpc_core::Thread thd; char* proxy_port; char* server_port; @@ -79,9 +90,7 @@ grpc_end2end_proxy* grpc_end2end_proxy_create(const grpc_end2end_proxy_def* def, int proxy_port = grpc_pick_unused_port_or_die(); int server_port = grpc_pick_unused_port_or_die(); - grpc_end2end_proxy* proxy = - static_cast(gpr_malloc(sizeof(*proxy))); - memset(proxy, 0, sizeof(*proxy)); + grpc_end2end_proxy* proxy = grpc_core::New(); gpr_join_host_port(&proxy->proxy_port, "localhost", proxy_port); gpr_join_host_port(&proxy->server_port, "localhost", server_port); @@ -128,7 +137,7 @@ void grpc_end2end_proxy_destroy(grpc_end2end_proxy* proxy) { grpc_channel_destroy(proxy->client); grpc_completion_queue_destroy(proxy->cq); grpc_call_details_destroy(&proxy->new_call_details); - gpr_free(proxy); + grpc_core::Delete(proxy); } static void unrefpc(proxy_call* pc, const char* reason) { diff --git a/test/cpp/util/.clang-tidy b/test/cpp/util/.clang-tidy deleted file mode 100644 index f951ee5fea..0000000000 --- a/test/cpp/util/.clang-tidy +++ /dev/null @@ -1,6 +0,0 @@ ---- -Checks: 'modernize-use-nullptr,google-build-namespaces,google-build-explicit-make-pair,readability-function-size,performance-*,-performance-unnecessary-copy-initialization' -WarningsAsErrors: 'modernize-use-nullptr,google-build-namespaces,google-build-explicit-make-pair,readability-function-size,performance-*,-performance-unnecessary-copy-initialization' -CheckOptions: - - key: readability-function-size.StatementThreshold - value: '450' -- cgit v1.2.3 From 8bf52535d1008a3f38e70d1387846f0e942761b5 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 21 Aug 2018 14:32:13 -0700 Subject: Provide a generic client-side unary callback API --- BUILD | 4 + CMakeLists.txt | 57 ++++++++++ Makefile | 64 +++++++++++ build.yaml | 18 +++ gRPC-C++.podspec | 4 + grpc.gyp | 2 + include/grpcpp/channel.h | 5 + include/grpcpp/generic/generic_stub.h | 23 ++++ include/grpcpp/impl/codegen/call.h | 10 +- include/grpcpp/impl/codegen/callback_common.h | 79 +++++++++++++ include/grpcpp/impl/codegen/channel_interface.h | 14 +++ include/grpcpp/impl/codegen/client_callback.h | 92 +++++++++++++++ include/grpcpp/impl/codegen/client_context.h | 4 + include/grpcpp/impl/codegen/completion_queue.h | 3 + include/grpcpp/support/client_callback.h | 24 ++++ src/core/lib/surface/completion_queue.cc | 4 +- src/cpp/client/channel_cc.cc | 41 ++++++- src/cpp/client/generic_stub.cc | 14 ++- src/cpp/common/callback_common.cc | 109 ++++++++++++++++++ src/cpp/server/server_cc.cc | 3 +- src/cpp/server/server_context.cc | 3 + test/cpp/end2end/BUILD | 19 ++++ test/cpp/end2end/client_callback_end2end_test.cc | 126 +++++++++++++++++++++ tools/doxygen/Doxyfile.c++ | 3 + tools/doxygen/Doxyfile.c++.internal | 4 + tools/run_tests/generated/sources_and_headers.json | 26 +++++ tools/run_tests/generated/tests.json | 24 ++++ 27 files changed, 772 insertions(+), 7 deletions(-) create mode 100644 include/grpcpp/impl/codegen/callback_common.h create mode 100644 include/grpcpp/impl/codegen/client_callback.h create mode 100644 include/grpcpp/support/client_callback.h create mode 100644 src/cpp/common/callback_common.cc create mode 100644 test/cpp/end2end/client_callback_end2end_test.cc (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index 925e277cf7..271e57e36c 100644 --- a/BUILD +++ b/BUILD @@ -119,6 +119,7 @@ GRPCXX_SRCS = [ "src/cpp/client/credentials_cc.cc", "src/cpp/client/generic_stub.cc", "src/cpp/common/alarm.cc", + "src/cpp/common/callback_common.cc", "src/cpp/common/channel_arguments.cc", "src/cpp/common/channel_filter.cc", "src/cpp/common/completion_queue_cc.cc", @@ -243,6 +244,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", "include/grpcpp/support/channel_arguments.h", + "include/grpcpp/support/client_callback.h", "include/grpcpp/support/config.h", "include/grpcpp/support/proto_buffer_reader.h", "include/grpcpp/support/proto_buffer_writer.h", @@ -1979,7 +1981,9 @@ grpc_cc_library( "include/grpcpp/impl/codegen/byte_buffer.h", "include/grpcpp/impl/codegen/call.h", "include/grpcpp/impl/codegen/call_hook.h", + "include/grpcpp/impl/codegen/callback_common.h", "include/grpcpp/impl/codegen/channel_interface.h", + "include/grpcpp/impl/codegen/client_callback.h", "include/grpcpp/impl/codegen/client_context.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index a21bb8b5fa..8679c5b4e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -564,6 +564,7 @@ add_dependencies(buildtests_cxx check_gcp_environment_linux_test) add_dependencies(buildtests_cxx check_gcp_environment_windows_test) add_dependencies(buildtests_cxx chttp2_settings_timeout_test) add_dependencies(buildtests_cxx cli_call_test) +add_dependencies(buildtests_cxx client_callback_end2end_test) add_dependencies(buildtests_cxx client_channel_stress_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx client_crash_test) @@ -2771,6 +2772,7 @@ add_library(grpc++ src/cpp/client/credentials_cc.cc src/cpp/client/generic_stub.cc src/cpp/common/alarm.cc + src/cpp/common/callback_common.cc src/cpp/common/channel_arguments.cc src/cpp/common/channel_filter.cc src/cpp/common/completion_queue_cc.cc @@ -2917,6 +2919,7 @@ foreach(_hdr include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h include/grpcpp/support/channel_arguments.h + include/grpcpp/support/client_callback.h include/grpcpp/support/config.h include/grpcpp/support/proto_buffer_reader.h include/grpcpp/support/proto_buffer_writer.h @@ -3014,7 +3017,9 @@ foreach(_hdr include/grpcpp/impl/codegen/byte_buffer.h include/grpcpp/impl/codegen/call.h include/grpcpp/impl/codegen/call_hook.h + include/grpcpp/impl/codegen/callback_common.h include/grpcpp/impl/codegen/channel_interface.h + include/grpcpp/impl/codegen/client_callback.h include/grpcpp/impl/codegen/client_context.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h @@ -3129,6 +3134,7 @@ add_library(grpc++_cronet src/cpp/client/credentials_cc.cc src/cpp/client/generic_stub.cc src/cpp/common/alarm.cc + src/cpp/common/callback_common.cc src/cpp/common/channel_arguments.cc src/cpp/common/channel_filter.cc src/cpp/common/completion_queue_cc.cc @@ -3486,6 +3492,7 @@ foreach(_hdr include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h include/grpcpp/support/channel_arguments.h + include/grpcpp/support/client_callback.h include/grpcpp/support/config.h include/grpcpp/support/proto_buffer_reader.h include/grpcpp/support/proto_buffer_writer.h @@ -3583,7 +3590,9 @@ foreach(_hdr include/grpcpp/impl/codegen/byte_buffer.h include/grpcpp/impl/codegen/call.h include/grpcpp/impl/codegen/call_hook.h + include/grpcpp/impl/codegen/callback_common.h include/grpcpp/impl/codegen/channel_interface.h + include/grpcpp/impl/codegen/client_callback.h include/grpcpp/impl/codegen/client_context.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h @@ -3993,7 +4002,9 @@ foreach(_hdr include/grpcpp/impl/codegen/byte_buffer.h include/grpcpp/impl/codegen/call.h include/grpcpp/impl/codegen/call_hook.h + include/grpcpp/impl/codegen/callback_common.h include/grpcpp/impl/codegen/channel_interface.h + include/grpcpp/impl/codegen/client_callback.h include/grpcpp/impl/codegen/client_context.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h @@ -4171,7 +4182,9 @@ foreach(_hdr include/grpcpp/impl/codegen/byte_buffer.h include/grpcpp/impl/codegen/call.h include/grpcpp/impl/codegen/call_hook.h + include/grpcpp/impl/codegen/callback_common.h include/grpcpp/impl/codegen/channel_interface.h + include/grpcpp/impl/codegen/client_callback.h include/grpcpp/impl/codegen/client_context.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h @@ -4247,6 +4260,7 @@ add_library(grpc++_unsecure src/cpp/client/credentials_cc.cc src/cpp/client/generic_stub.cc src/cpp/common/alarm.cc + src/cpp/common/callback_common.cc src/cpp/common/channel_arguments.cc src/cpp/common/channel_filter.cc src/cpp/common/completion_queue_cc.cc @@ -4392,6 +4406,7 @@ foreach(_hdr include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h include/grpcpp/support/channel_arguments.h + include/grpcpp/support/client_callback.h include/grpcpp/support/config.h include/grpcpp/support/proto_buffer_reader.h include/grpcpp/support/proto_buffer_writer.h @@ -4489,7 +4504,9 @@ foreach(_hdr include/grpcpp/impl/codegen/byte_buffer.h include/grpcpp/impl/codegen/call.h include/grpcpp/impl/codegen/call_hook.h + include/grpcpp/impl/codegen/callback_common.h include/grpcpp/impl/codegen/channel_interface.h + include/grpcpp/impl/codegen/client_callback.h include/grpcpp/impl/codegen/client_context.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h @@ -11297,6 +11314,46 @@ target_link_libraries(cli_call_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(client_callback_end2end_test + test/cpp/end2end/client_callback_end2end_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(client_callback_end2end_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(client_callback_end2end_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test_util + grpc_test_util + grpc++ + grpc + gpr_test_util + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(client_channel_stress_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc diff --git a/Makefile b/Makefile index 96ea890bcb..33ec3d93e7 100644 --- a/Makefile +++ b/Makefile @@ -1160,6 +1160,7 @@ check_gcp_environment_linux_test: $(BINDIR)/$(CONFIG)/check_gcp_environment_linu check_gcp_environment_windows_test: $(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test chttp2_settings_timeout_test: $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test +client_callback_end2end_test: $(BINDIR)/$(CONFIG)/client_callback_end2end_test client_channel_stress_test: $(BINDIR)/$(CONFIG)/client_channel_stress_test client_crash_test: $(BINDIR)/$(CONFIG)/client_crash_test client_crash_test_server: $(BINDIR)/$(CONFIG)/client_crash_test_server @@ -1665,6 +1666,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test \ $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test \ $(BINDIR)/$(CONFIG)/cli_call_test \ + $(BINDIR)/$(CONFIG)/client_callback_end2end_test \ $(BINDIR)/$(CONFIG)/client_channel_stress_test \ $(BINDIR)/$(CONFIG)/client_crash_test \ $(BINDIR)/$(CONFIG)/client_crash_test_server \ @@ -1845,6 +1847,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test \ $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test \ $(BINDIR)/$(CONFIG)/cli_call_test \ + $(BINDIR)/$(CONFIG)/client_callback_end2end_test \ $(BINDIR)/$(CONFIG)/client_channel_stress_test \ $(BINDIR)/$(CONFIG)/client_crash_test \ $(BINDIR)/$(CONFIG)/client_crash_test_server \ @@ -2302,6 +2305,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test || ( echo test chttp2_settings_timeout_test failed ; exit 1 ) $(E) "[RUN] Testing cli_call_test" $(Q) $(BINDIR)/$(CONFIG)/cli_call_test || ( echo test cli_call_test failed ; exit 1 ) + $(E) "[RUN] Testing client_callback_end2end_test" + $(Q) $(BINDIR)/$(CONFIG)/client_callback_end2end_test || ( echo test client_callback_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing client_channel_stress_test" $(Q) $(BINDIR)/$(CONFIG)/client_channel_stress_test || ( echo test client_channel_stress_test failed ; exit 1 ) $(E) "[RUN] Testing client_crash_test" @@ -5219,6 +5224,7 @@ LIBGRPC++_SRC = \ src/cpp/client/credentials_cc.cc \ src/cpp/client/generic_stub.cc \ src/cpp/common/alarm.cc \ + src/cpp/common/callback_common.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/completion_queue_cc.cc \ @@ -5329,6 +5335,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ + include/grpcpp/support/client_callback.h \ include/grpcpp/support/config.h \ include/grpcpp/support/proto_buffer_reader.h \ include/grpcpp/support/proto_buffer_writer.h \ @@ -5426,7 +5433,9 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ + include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ + include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -5585,6 +5594,7 @@ LIBGRPC++_CRONET_SRC = \ src/cpp/client/credentials_cc.cc \ src/cpp/client/generic_stub.cc \ src/cpp/common/alarm.cc \ + src/cpp/common/callback_common.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/completion_queue_cc.cc \ @@ -5905,6 +5915,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ + include/grpcpp/support/client_callback.h \ include/grpcpp/support/config.h \ include/grpcpp/support/proto_buffer_reader.h \ include/grpcpp/support/proto_buffer_writer.h \ @@ -6002,7 +6013,9 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ + include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ + include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -6392,7 +6405,9 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ + include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ + include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -6546,7 +6561,9 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ + include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ + include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -6661,6 +6678,7 @@ LIBGRPC++_UNSECURE_SRC = \ src/cpp/client/credentials_cc.cc \ src/cpp/client/generic_stub.cc \ src/cpp/common/alarm.cc \ + src/cpp/common/callback_common.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/completion_queue_cc.cc \ @@ -6771,6 +6789,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ + include/grpcpp/support/client_callback.h \ include/grpcpp/support/config.h \ include/grpcpp/support/proto_buffer_reader.h \ include/grpcpp/support/proto_buffer_writer.h \ @@ -6868,7 +6887,9 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ + include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ + include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -17076,6 +17097,49 @@ endif endif +CLIENT_CALLBACK_END2END_TEST_SRC = \ + test/cpp/end2end/client_callback_end2end_test.cc \ + +CLIENT_CALLBACK_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_CALLBACK_END2END_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/client_callback_end2end_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/client_callback_end2end_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/client_callback_end2end_test: $(PROTOBUF_DEP) $(CLIENT_CALLBACK_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(CLIENT_CALLBACK_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/client_callback_end2end_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/end2end/client_callback_end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_client_callback_end2end_test: $(CLIENT_CALLBACK_END2END_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CLIENT_CALLBACK_END2END_TEST_OBJS:.o=.dep) +endif +endif + + CLIENT_CHANNEL_STRESS_TEST_SRC = \ $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \ test/cpp/client/client_channel_stress_test.cc \ diff --git a/build.yaml b/build.yaml index a50a0a4ab6..b775773e42 100644 --- a/build.yaml +++ b/build.yaml @@ -1169,7 +1169,9 @@ filegroups: - include/grpcpp/impl/codegen/byte_buffer.h - include/grpcpp/impl/codegen/call.h - include/grpcpp/impl/codegen/call_hook.h + - include/grpcpp/impl/codegen/callback_common.h - include/grpcpp/impl/codegen/channel_interface.h + - include/grpcpp/impl/codegen/client_callback.h - include/grpcpp/impl/codegen/client_context.h - include/grpcpp/impl/codegen/client_unary_call.h - include/grpcpp/impl/codegen/completion_queue.h @@ -1297,6 +1299,7 @@ filegroups: - include/grpcpp/support/async_unary_call.h - include/grpcpp/support/byte_buffer.h - include/grpcpp/support/channel_arguments.h + - include/grpcpp/support/client_callback.h - include/grpcpp/support/config.h - include/grpcpp/support/proto_buffer_reader.h - include/grpcpp/support/proto_buffer_writer.h @@ -1324,6 +1327,7 @@ filegroups: - src/cpp/client/credentials_cc.cc - src/cpp/client/generic_stub.cc - src/cpp/common/alarm.cc + - src/cpp/common/callback_common.cc - src/cpp/common/channel_arguments.cc - src/cpp/common/channel_filter.cc - src/cpp/common/completion_queue_cc.cc @@ -4465,6 +4469,20 @@ targets: - grpc - gpr_test_util - gpr +- name: client_callback_end2end_test + gtest: true + cpu_cost: 0.5 + build: test + language: c++ + src: + - test/cpp/end2end/client_callback_end2end_test.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - gpr_test_util + - gpr - name: client_channel_stress_test gtest: false build: test diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 581b9246bc..03ec223279 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -111,6 +111,7 @@ Pod::Spec.new do |s| 'include/grpcpp/support/async_unary_call.h', 'include/grpcpp/support/byte_buffer.h', 'include/grpcpp/support/channel_arguments.h', + 'include/grpcpp/support/client_callback.h', 'include/grpcpp/support/config.h', 'include/grpcpp/support/proto_buffer_reader.h', 'include/grpcpp/support/proto_buffer_writer.h', @@ -127,7 +128,9 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/codegen/byte_buffer.h', 'include/grpcpp/impl/codegen/call.h', 'include/grpcpp/impl/codegen/call_hook.h', + 'include/grpcpp/impl/codegen/callback_common.h', 'include/grpcpp/impl/codegen/channel_interface.h', + 'include/grpcpp/impl/codegen/client_callback.h', 'include/grpcpp/impl/codegen/client_context.h', 'include/grpcpp/impl/codegen/client_unary_call.h', 'include/grpcpp/impl/codegen/completion_queue.h', @@ -187,6 +190,7 @@ Pod::Spec.new do |s| 'src/cpp/client/credentials_cc.cc', 'src/cpp/client/generic_stub.cc', 'src/cpp/common/alarm.cc', + 'src/cpp/common/callback_common.cc', 'src/cpp/common/channel_arguments.cc', 'src/cpp/common/channel_filter.cc', 'src/cpp/common/completion_queue_cc.cc', diff --git a/grpc.gyp b/grpc.gyp index 654a531092..b8aae44de3 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -1381,6 +1381,7 @@ 'src/cpp/client/credentials_cc.cc', 'src/cpp/client/generic_stub.cc', 'src/cpp/common/alarm.cc', + 'src/cpp/common/callback_common.cc', 'src/cpp/common/channel_arguments.cc', 'src/cpp/common/channel_filter.cc', 'src/cpp/common/completion_queue_cc.cc', @@ -1528,6 +1529,7 @@ 'src/cpp/client/credentials_cc.cc', 'src/cpp/client/generic_stub.cc', 'src/cpp/common/alarm.cc', + 'src/cpp/common/callback_common.cc', 'src/cpp/common/channel_arguments.cc', 'src/cpp/common/channel_filter.cc', 'src/cpp/common/completion_queue_cc.cc', diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h index fed02bf7bc..58a6f51664 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -78,8 +78,13 @@ class Channel final : public ChannelInterface, bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) override; + CompletionQueue* CallbackCQ() override; + const grpc::string host_; grpc_channel* const c_channel_; // owned + + CompletionQueue* callback_cq_ = nullptr; + std::mutex mu_; }; } // namespace grpc diff --git a/include/grpcpp/generic/generic_stub.h b/include/grpcpp/generic/generic_stub.h index 92405a43fa..d509d9a520 100644 --- a/include/grpcpp/generic/generic_stub.h +++ b/include/grpcpp/generic/generic_stub.h @@ -19,9 +19,12 @@ #ifndef GRPCPP_GENERIC_GENERIC_STUB_H #define GRPCPP_GENERIC_GENERIC_STUB_H +#include + #include #include #include +#include namespace grpc { @@ -62,6 +65,26 @@ class GenericStub final { ClientContext* context, const grpc::string& method, CompletionQueue* cq, void* tag); + /// NOTE: class experimental_type is not part of the public API of this class + /// TODO(vjpai): Move these contents to the public API of GenericStub when + /// they are no longer experimental + class experimental_type { + public: + explicit experimental_type(GenericStub* stub) : stub_(stub) {} + + void UnaryCall(ClientContext* context, const grpc::string& method, + const ByteBuffer* request, ByteBuffer* response, + std::function on_completion); + + private: + GenericStub* stub_; + }; + + /// NOTE: The function experimental() is not stable public API. It is a view + /// to the experimental components of this class. It may be changed or removed + /// at any time. + experimental_type experimental() { return experimental_type(this); } + private: std::shared_ptr channel_; }; diff --git a/include/grpcpp/impl/codegen/call.h b/include/grpcpp/impl/codegen/call.h index a5e930aaa5..7bd03b6b1b 100644 --- a/include/grpcpp/impl/codegen/call.h +++ b/include/grpcpp/impl/codegen/call.h @@ -608,6 +608,9 @@ class CallOpSetInterface : public CompletionQueueTag { /// Fills in grpc_op, starting from ops[*nops] and moving /// upwards. virtual void FillOps(grpc_call* call, grpc_op* ops, size_t* nops) = 0; + + /// Get the tag to be used at the CQ + virtual void* cq_tag() = 0; }; /// Primary implementation of CallOpSetInterface. @@ -627,7 +630,7 @@ class CallOpSet : public CallOpSetInterface, public Op5, public Op6 { public: - CallOpSet() : return_tag_(this), call_(nullptr) {} + CallOpSet() : cq_tag_(this), return_tag_(this), call_(nullptr) {} void FillOps(grpc_call* call, grpc_op* ops, size_t* nops) override { this->Op1::AddOp(ops, nops); this->Op2::AddOp(ops, nops); @@ -654,7 +657,12 @@ class CallOpSet : public CallOpSetInterface, void set_output_tag(void* return_tag) { return_tag_ = return_tag; } + void* cq_tag() override { return cq_tag_; } + + void set_cq_tag(void* cq_tag) { cq_tag_ = cq_tag; } + private: + void* cq_tag_; void* return_tag_; grpc_call* call_; }; diff --git a/include/grpcpp/impl/codegen/callback_common.h b/include/grpcpp/impl/codegen/callback_common.h new file mode 100644 index 0000000000..5e1530a310 --- /dev/null +++ b/include/grpcpp/impl/codegen/callback_common.h @@ -0,0 +1,79 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_IMPL_CODEGEN_CALLBACK_COMMON_H +#define GRPCPP_IMPL_CODEGEN_CALLBACK_COMMON_H + +#include + +#include +#include +#include +#include +#include + +// Forward declarations +namespace grpc_core { +class CQCallbackInterface; +}; + +namespace grpc { +namespace internal { + +class CallbackWithStatusTag { + public: + // TODO(vjpai): make impl and ops part of this structure to avoid allocation, + // ownership transfer, and delete + CallbackWithStatusTag(std::function f, bool self_delete, + CompletionQueueTag* ops); + ~CallbackWithStatusTag() { delete ops_; } + void* tag() { return static_cast(impl_); } + Status* status_ptr() { return status_; } + CompletionQueueTag* ops() { return ops_; } + + // force_run can only be performed on a tag before it can ever be active + void force_run(Status s); + + private: + grpc_core::CQCallbackInterface* impl_; + Status* status_; + CompletionQueueTag* ops_; +}; + +class CallbackWithSuccessTag { + public: + // TODO(vjpai): make impl and ops part of this structure to avoid allocation, + // ownership transfer, and delete + CallbackWithSuccessTag(std::function f, bool self_delete, + CompletionQueueTag* ops); + ~CallbackWithSuccessTag() { delete ops_; } + void* tag() { return static_cast(impl_); } + CompletionQueueTag* ops() { return ops_; } + + // force_run can only be performed on a tag before it can ever be active + void force_run(bool ok); + + private: + grpc_core::CQCallbackInterface* impl_; + CompletionQueueTag* ops_; +}; + +} // namespace internal +} // namespace grpc + +#endif // GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H diff --git a/include/grpcpp/impl/codegen/channel_interface.h b/include/grpcpp/impl/codegen/channel_interface.h index ec1c6c25d8..b257acc1ab 100644 --- a/include/grpcpp/impl/codegen/channel_interface.h +++ b/include/grpcpp/impl/codegen/channel_interface.h @@ -41,6 +41,8 @@ class CallOpSetInterface; class RpcMethod; template class BlockingUnaryCallImpl; +template +class CallbackUnaryCallImpl; template class ClientAsyncReaderFactory; template @@ -103,6 +105,8 @@ class ChannelInterface { friend class ::grpc::internal::ClientAsyncResponseReaderFactory; template friend class ::grpc::internal::BlockingUnaryCallImpl; + template + friend class ::grpc::internal::CallbackUnaryCallImpl; friend class ::grpc::internal::RpcMethod; virtual internal::Call CreateCall(const internal::RpcMethod& method, ClientContext* context, @@ -115,6 +119,16 @@ class ChannelInterface { CompletionQueue* cq, void* tag) = 0; virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) = 0; + + // EXPERIMENTAL + // A method to get the callbackable completion queue associated with this + // channel. If the return value is nullptr, this channel doesn't support + // callback operations. + // TODO(vjpai): Consider a better default like using a global CQ + // Returns nullptr (rather than being pure) since this is a new method + // and adding a new pure method to an interface would be a breaking change + // (even though this is private and non-API) + virtual CompletionQueue* CallbackCQ() { return nullptr; } }; } // namespace grpc diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h new file mode 100644 index 0000000000..419933f85c --- /dev/null +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -0,0 +1,92 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H +#define GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H + +#include + +#include +#include +#include +#include +#include +#include + +namespace grpc { + +class Channel; +class ClientContext; +class CompletionQueue; + +namespace internal { +class RpcMethod; + +/// Perform a callback-based unary call +/// TODO(vjpai): Combine as much as possible with the blocking unary call code +template +void CallbackUnaryCall(ChannelInterface* channel, const RpcMethod& method, + ClientContext* context, const InputMessage* request, + OutputMessage* result, + std::function on_completion) { + CallbackUnaryCallImpl x( + channel, method, context, request, result, on_completion); +} + +template +class CallbackUnaryCallImpl { + public: + CallbackUnaryCallImpl(ChannelInterface* channel, const RpcMethod& method, + ClientContext* context, const InputMessage* request, + OutputMessage* result, + std::function on_completion) { + CompletionQueue* cq = channel->CallbackCQ(); + GPR_CODEGEN_ASSERT(cq != nullptr); + + // TODO(vjpai): Allocate this as part of the tag's arena + auto* ops = new CallOpSet, + CallOpClientSendClose, CallOpClientRecvStatus>; + + // TODO(vjpai): Move to using pre-allocated tags rather than new/self-delete + auto* tag = new CallbackWithStatusTag(on_completion, true, ops); + + // TODO(vjpai): Unify code with sync API as much as possible + Call call(channel->CreateCall(method, context, cq)); + Status s = ops->SendMessage(*request); + if (!s.ok()) { + tag->force_run(s); + return; + } + ops->SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); + ops->RecvInitialMetadata(context); + ops->RecvMessage(result); + ops->AllowNoMessage(); + ops->ClientSendClose(); + ops->ClientRecvStatus(context, tag->status_ptr()); + ops->set_cq_tag(tag->tag()); + call.PerformOps(ops); + } +}; + +} // namespace internal +} // namespace grpc + +#endif // GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 9dda4c7fac..7db31fcbcf 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -68,6 +68,8 @@ class CallOpClientRecvStatus; class CallOpRecvInitialMetadata; template class BlockingUnaryCallImpl; +template +class CallbackUnaryCallImpl; } // namespace internal template @@ -389,6 +391,8 @@ class ClientContext { friend class ::grpc::ClientAsyncResponseReader; template friend class ::grpc::internal::BlockingUnaryCallImpl; + template + friend class ::grpc::internal::CallbackUnaryCallImpl; // Used by friend class CallOpClientRecvStatus void set_debug_error_string(const grpc::string& debug_error_string) { diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 3f7d4fb765..f52f9a53be 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -274,6 +274,9 @@ class CompletionQueue : private GrpcLibraryCodegen { template friend class ::grpc::internal::BlockingUnaryCallImpl; + // Friends that need access to constructor for callback CQ + friend class ::grpc::Channel; + /// EXPERIMENTAL /// Creates a Thread Local cache to store the first event /// On this completion queue queued from this thread. Once diff --git a/include/grpcpp/support/client_callback.h b/include/grpcpp/support/client_callback.h new file mode 100644 index 0000000000..03a7e1400c --- /dev/null +++ b/include/grpcpp/support/client_callback.h @@ -0,0 +1,24 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SUPPORT_CLIENT_CALLBACK_H +#define GRPCPP_SUPPORT_CLIENT_CALLBACK_H + +#include + +#endif // GRPCPP_SUPPORT_CLIENT_CALLBACK_H diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc index 0769d9e4f6..c2cf450e94 100644 --- a/src/core/lib/surface/completion_queue.cc +++ b/src/core/lib/surface/completion_queue.cc @@ -1364,9 +1364,11 @@ static void cq_shutdown_callback(grpc_completion_queue* cq) { } cqd->shutdown_called = true; if (gpr_atm_full_fetch_add(&cqd->pending_events, -1) == 1) { + gpr_mu_unlock(cq->mu); cq_finish_shutdown_callback(cq); + } else { + gpr_mu_unlock(cq->mu); } - gpr_mu_unlock(cq->mu); GRPC_CQ_INTERNAL_UNREF(cq, "shutting_down (callback cq)"); } diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index 39b891c2e1..2a961e6e27 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -42,8 +42,10 @@ #include #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/surface/completion_queue.h" namespace grpc { @@ -53,7 +55,12 @@ Channel::Channel(const grpc::string& host, grpc_channel* channel) g_gli_initializer.summon(); } -Channel::~Channel() { grpc_channel_destroy(c_channel_); } +Channel::~Channel() { + grpc_channel_destroy(c_channel_); + if (callback_cq_ != nullptr) { + callback_cq_->Shutdown(); + } +} namespace { @@ -135,8 +142,8 @@ void Channel::PerformOpsOnCall(internal::CallOpSetInterface* ops, size_t nops = 0; grpc_op cops[MAX_OPS]; ops->FillOps(call->call(), cops, &nops); - GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_batch(call->call(), cops, nops, ops, nullptr)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call->call(), cops, nops, + ops->cq_tag(), nullptr)); } void* Channel::RegisterMethod(const char* method) { @@ -185,4 +192,32 @@ bool Channel::WaitForStateChangeImpl(grpc_connectivity_state last_observed, return ok; } +namespace { +class ShutdownCallback : public grpc_core::CQCallbackInterface { + public: + void TakeCQ(CompletionQueue* cq) { cq_ = cq; } + void Run(bool) override { + delete cq_; + grpc_core::Delete(this); + } + + private: + CompletionQueue* cq_ = nullptr; +}; +} // namespace + +CompletionQueue* Channel::CallbackCQ() { + // TODO(vjpai): Consider using a single global CQ for the default CQ + // if there is no explicit per-channel CQ registered + std::lock_guard l(mu_); + if (callback_cq_ == nullptr) { + auto* shutdown_callback = grpc_core::New(); + callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ + GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING, + shutdown_callback}); + shutdown_callback->TakeCQ(callback_cq_); + } + return callback_cq_; +} + } // namespace grpc diff --git a/src/cpp/client/generic_stub.cc b/src/cpp/client/generic_stub.cc index 67ef46bebe..07c34c8878 100644 --- a/src/cpp/client/generic_stub.cc +++ b/src/cpp/client/generic_stub.cc @@ -16,9 +16,11 @@ * */ -#include +#include +#include #include +#include namespace grpc { @@ -60,4 +62,14 @@ std::unique_ptr GenericStub::PrepareUnaryCall( context, request, false)); } +void GenericStub::experimental_type::UnaryCall( + ClientContext* context, const grpc::string& method, + const ByteBuffer* request, ByteBuffer* response, + std::function on_completion) { + internal::CallbackUnaryCall( + stub_->channel_.get(), + internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC), + context, request, response, on_completion); +} + } // namespace grpc diff --git a/src/cpp/common/callback_common.cc b/src/cpp/common/callback_common.cc new file mode 100644 index 0000000000..2598d37e27 --- /dev/null +++ b/src/cpp/common/callback_common.cc @@ -0,0 +1,109 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/surface/completion_queue.h" + +namespace grpc { +namespace internal { + +namespace { +class CallbackWithSuccessImpl : public grpc_core::CQCallbackInterface { + public: + CallbackWithSuccessImpl(CallbackWithSuccessTag* parent, + std::function f, bool self_delete) + : parent_(parent), func_(f), self_delete_(self_delete) {} + + void Run(bool ok) override { + void* ignored = parent_->ops(); + bool new_ok = ok; + GPR_ASSERT(parent_->ops()->FinalizeResult(&ignored, &new_ok)); + GPR_ASSERT(ignored == parent_->ops()); + func_(ok); + if (self_delete_) { + delete parent_; + // Must use grpc_core::Delete since base is GRPC_ABSTRACT + grpc_core::Delete(this); + } + } + + private: + CallbackWithSuccessTag* parent_; + std::function func_; + bool self_delete_; +}; + +class CallbackWithStatusImpl : public grpc_core::CQCallbackInterface { + public: + CallbackWithStatusImpl(CallbackWithStatusTag* parent, + std::function f, bool self_delete) + : parent_(parent), func_(f), status_(), self_delete_(self_delete) {} + + void Run(bool ok) override { + void* ignored = parent_->ops(); + + GPR_ASSERT(parent_->ops()->FinalizeResult(&ignored, &ok)); + GPR_ASSERT(ignored == parent_->ops()); + + func_(status_); + if (self_delete_) { + delete parent_; + // Must use grpc_core::Delete since base is GRPC_ABSTRACT + grpc_core::Delete(this); + } + } + Status* status_ptr() { return &status_; } + + private: + CallbackWithStatusTag* parent_; + std::function func_; + Status status_; + bool self_delete_; +}; + +} // namespace + +CallbackWithSuccessTag::CallbackWithSuccessTag(std::function f, + bool self_delete, + CompletionQueueTag* ops) + : impl_(grpc_core::New(this, f, self_delete)), + ops_(ops) {} + +void CallbackWithSuccessTag::force_run(bool ok) { impl_->Run(ok); } + +CallbackWithStatusTag::CallbackWithStatusTag(std::function f, + bool self_delete, + CompletionQueueTag* ops) + : ops_(ops) { + auto* impl = grpc_core::New(this, f, self_delete); + impl_ = impl; + status_ = impl->status_ptr(); +} + +void CallbackWithStatusTag::force_run(Status s) { + *status_ = s; + impl_->Run(true); +} + +} // namespace internal +} // namespace grpc diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 36c709eb45..f271825cba 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -657,7 +657,8 @@ void Server::PerformOpsOnCall(internal::CallOpSetInterface* ops, size_t nops = 0; grpc_op cops[MAX_OPS]; ops->FillOps(call->call(), cops, &nops); - auto result = grpc_call_start_batch(call->call(), cops, nops, ops, nullptr); + auto result = + grpc_call_start_batch(call->call(), cops, nops, ops->cq_tag(), nullptr); if (result != GRPC_CALL_OK) { gpr_log(GPR_ERROR, "Fatal: grpc_call_start_batch returned %d", result); grpc_call_log_batch(__FILE__, __LINE__, GPR_LOG_SEVERITY_ERROR, diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 6f5bde0d9f..f76f64e3da 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -61,6 +61,9 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { tag_ = tag; } + /// TODO(vjpai): Allow override of cq_tag if appropriate for callback API + void* cq_tag() override { return this; } + void Unref(); private: diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 75dec56a60..0415efc1ef 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -98,6 +98,25 @@ grpc_cc_binary( ], ) +grpc_cc_test( + name = "client_callback_end2end_test", + srcs = ["client_callback_end2end_test.cc"], + external_deps = [ + "gtest", + ], + deps = [ + ":test_service_impl", + "//:gpr", + "//:grpc", + "//:grpc++", + "//src/proto/grpc/testing:echo_messages_proto", + "//src/proto/grpc/testing:echo_proto", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) + grpc_cc_library( name = "end2end_test_lib", testonly = True, diff --git a/test/cpp/end2end/client_callback_end2end_test.cc b/test/cpp/end2end/client_callback_end2end_test.cc new file mode 100644 index 0000000000..be732a0ca6 --- /dev/null +++ b/test/cpp/end2end/client_callback_end2end_test.cc @@ -0,0 +1,126 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" + +#include + +namespace grpc { +namespace testing { +namespace { + +class ClientCallbackEnd2endTest : public ::testing::Test { + protected: + ClientCallbackEnd2endTest() {} + + void SetUp() override { + ServerBuilder builder; + builder.RegisterService(&service_); + + server_ = builder.BuildAndStart(); + is_server_started_ = true; + } + + void ResetStub() { + ChannelArguments args; + channel_ = server_->InProcessChannel(args); + stub_.reset(new GenericStub(channel_)); + } + + void TearDown() override { + if (is_server_started_) { + server_->Shutdown(); + } + } + + void SendRpcs(int num_rpcs) { + const grpc::string kMethodName("/grpc.testing.EchoTestService/Echo"); + grpc::string test_string(""); + for (int i = 0; i < num_rpcs; i++) { + EchoRequest request; + std::unique_ptr send_buf; + ByteBuffer recv_buf; + ClientContext cli_ctx; + + test_string += "Hello world. "; + request.set_message(test_string); + send_buf = SerializeToByteBuffer(&request); + + std::mutex mu; + std::condition_variable cv; + bool done; + stub_->experimental().UnaryCall( + &cli_ctx, kMethodName, send_buf.get(), &recv_buf, + [&request, &recv_buf, &done, &mu, &cv](Status s) { + GPR_ASSERT(s.ok()); + + EchoResponse response; + EXPECT_TRUE(ParseFromByteBuffer(&recv_buf, &response)); + EXPECT_EQ(request.message(), response.message()); + std::lock_guard l(mu); + done = true; + cv.notify_one(); + }); + std::unique_lock l(mu); + while (!done) { + cv.wait(l); + } + } + } + bool is_server_started_; + std::shared_ptr channel_; + std::unique_ptr stub_; + TestServiceImpl service_; + std::unique_ptr server_; +}; + +TEST_F(ClientCallbackEnd2endTest, SimpleRpc) { + ResetStub(); + SendRpcs(1); +} + +TEST_F(ClientCallbackEnd2endTest, SequentialRpcs) { + ResetStub(); + SendRpcs(10); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9a97ee84f2..3b7fd1fa8e 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -945,7 +945,9 @@ include/grpcpp/impl/codegen/async_unary_call.h \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ +include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ +include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -997,6 +999,7 @@ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ +include/grpcpp/support/client_callback.h \ include/grpcpp/support/config.h \ include/grpcpp/support/proto_buffer_reader.h \ include/grpcpp/support/proto_buffer_writer.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 0cd4cfd647..a72390d9f8 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -946,7 +946,9 @@ include/grpcpp/impl/codegen/async_unary_call.h \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ +include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ +include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -999,6 +1001,7 @@ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ +include/grpcpp/support/client_callback.h \ include/grpcpp/support/config.h \ include/grpcpp/support/proto_buffer_reader.h \ include/grpcpp/support/proto_buffer_writer.h \ @@ -1187,6 +1190,7 @@ src/cpp/client/secure_credentials.h \ src/cpp/codegen/codegen_init.cc \ src/cpp/common/alarm.cc \ src/cpp/common/auth_property_iterator.cc \ +src/cpp/common/callback_common.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/channel_filter.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8ea5126fde..9637fa8787 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -3302,6 +3302,25 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc++", + "grpc++_test_util", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "client_callback_end2end_test", + "src": [ + "test/cpp/end2end/client_callback_end2end_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -11081,7 +11100,9 @@ "include/grpcpp/impl/codegen/byte_buffer.h", "include/grpcpp/impl/codegen/call.h", "include/grpcpp/impl/codegen/call_hook.h", + "include/grpcpp/impl/codegen/callback_common.h", "include/grpcpp/impl/codegen/channel_interface.h", + "include/grpcpp/impl/codegen/client_callback.h", "include/grpcpp/impl/codegen/client_context.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", @@ -11147,7 +11168,9 @@ "include/grpcpp/impl/codegen/byte_buffer.h", "include/grpcpp/impl/codegen/call.h", "include/grpcpp/impl/codegen/call_hook.h", + "include/grpcpp/impl/codegen/callback_common.h", "include/grpcpp/impl/codegen/channel_interface.h", + "include/grpcpp/impl/codegen/client_callback.h", "include/grpcpp/impl/codegen/client_context.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", @@ -11305,6 +11328,7 @@ "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", "include/grpcpp/support/channel_arguments.h", + "include/grpcpp/support/client_callback.h", "include/grpcpp/support/config.h", "include/grpcpp/support/proto_buffer_reader.h", "include/grpcpp/support/proto_buffer_writer.h", @@ -11409,6 +11433,7 @@ "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", "include/grpcpp/support/channel_arguments.h", + "include/grpcpp/support/client_callback.h", "include/grpcpp/support/config.h", "include/grpcpp/support/proto_buffer_reader.h", "include/grpcpp/support/proto_buffer_writer.h", @@ -11428,6 +11453,7 @@ "src/cpp/client/credentials_cc.cc", "src/cpp/client/generic_stub.cc", "src/cpp/common/alarm.cc", + "src/cpp/common/callback_common.cc", "src/cpp/common/channel_arguments.cc", "src/cpp/common/channel_filter.cc", "src/cpp/common/channel_filter.h", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index fba76d69d1..a48b9c60da 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -3945,6 +3945,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 0.5, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "client_callback_end2end_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, -- cgit v1.2.3 From e361d0f6910db66e081d125e45e58b96e22d3e11 Mon Sep 17 00:00:00 2001 From: jiangtaoli2016 Date: Fri, 31 Aug 2018 11:30:28 -0700 Subject: Turn loading system root certificate as default --- .../lib/security/security_connector/security_connector.cc | 14 +++++++------- test/core/security/linux_system_roots_test.cc | 6 ------ test/core/security/security_connector_test.cc | 1 + 3 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc index 04b4c87c71..6246613e7b 100644 --- a/src/core/lib/security/security_connector/security_connector.cc +++ b/src/core/lib/security/security_connector/security_connector.cc @@ -59,8 +59,8 @@ static const char* installed_roots_path = /** Environment variable used as a flag to enable/disable loading system root certificates from the OS trust store. */ -#ifndef GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR -#define GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR "GRPC_USE_SYSTEM_SSL_ROOTS" +#ifndef GRPC_NOT_USE_SYSTEM_SSL_ROOTS_ENV_VAR +#define GRPC_NOT_USE_SYSTEM_SSL_ROOTS_ENV_VAR "GRPC_NOT_USE_SYSTEM_SSL_ROOTS" #endif #ifndef TSI_OPENSSL_ALPN_SUPPORT @@ -1192,10 +1192,10 @@ const char* DefaultSslRootStore::GetPemRootCerts() { grpc_slice DefaultSslRootStore::ComputePemRootCerts() { grpc_slice result = grpc_empty_slice(); - char* use_system_roots_env_value = - gpr_getenv(GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR); - const bool use_system_roots = gpr_is_true(use_system_roots_env_value); - gpr_free(use_system_roots_env_value); + char* not_use_system_roots_env_value = + gpr_getenv(GRPC_NOT_USE_SYSTEM_SSL_ROOTS_ENV_VAR); + const bool not_use_system_roots = gpr_is_true(not_use_system_roots_env_value); + gpr_free(not_use_system_roots_env_value); // First try to load the roots from the environment. char* default_root_certs_path = gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); @@ -1218,7 +1218,7 @@ grpc_slice DefaultSslRootStore::ComputePemRootCerts() { gpr_free(pem_root_certs); } // Try loading roots from OS trust store if flag is enabled. - if (GRPC_SLICE_IS_EMPTY(result) && use_system_roots) { + if (GRPC_SLICE_IS_EMPTY(result) && !not_use_system_roots) { result = LoadSystemRootCerts(); } // Fallback to roots manually shipped with gRPC. diff --git a/test/core/security/linux_system_roots_test.cc b/test/core/security/linux_system_roots_test.cc index fce9c8dcc5..24d446de35 100644 --- a/test/core/security/linux_system_roots_test.cc +++ b/test/core/security/linux_system_roots_test.cc @@ -41,10 +41,6 @@ #include "gtest/gtest.h" -#ifndef GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR -#define GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR "GRPC_USE_SYSTEM_SSL_ROOTS" -#endif - namespace grpc { namespace { @@ -68,7 +64,6 @@ TEST(CreateRootCertsBundleTest, ReturnsEmpty) { } TEST(CreateRootCertsBundleTest, BundlesCorrectly) { - gpr_setenv(GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR, "true"); // Test that CreateRootCertsBundle returns a correct slice. grpc_slice roots_bundle = grpc_empty_slice(); GRPC_LOG_IF_ERROR( @@ -81,7 +76,6 @@ TEST(CreateRootCertsBundleTest, BundlesCorrectly) { char* bundle_str = grpc_slice_to_c_string(roots_bundle); EXPECT_STREQ(result_str, bundle_str); // Clean up. - unsetenv(GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR); gpr_free(result_str); gpr_free(bundle_str); grpc_slice_unref(roots_bundle); diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc index 82d77eef8b..9dd37b975b 100644 --- a/test/core/security/security_connector_test.cc +++ b/test/core/security/security_connector_test.cc @@ -415,6 +415,7 @@ static void test_default_ssl_roots(void) { /* Now setup a permanent failure for the overridden roots and we should get an empty slice. */ + gpr_setenv("GRPC_NOT_USE_SYSTEM_SSL_ROOTS", "true"); grpc_set_ssl_roots_override_callback(override_roots_permanent_failure); roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting(); GPR_ASSERT(GRPC_SLICE_IS_EMPTY(roots)); -- cgit v1.2.3 From be8844bcdb704cff6a70507f5093e4bb26320ea3 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 7 Sep 2018 15:44:59 -0700 Subject: reviewer feedback --- .../ext/filters/client_channel/client_channel.cc | 133 ++++++++++----------- src/core/lib/channel/channelz.h | 7 +- src/core/lib/channel/connected_channel.cc | 6 +- src/core/lib/surface/call.cc | 8 +- test/core/channel/channel_trace_test.cc | 4 +- test/core/channel/channelz_test.cc | 4 +- 6 files changed, 78 insertions(+), 84 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index d015ceb335..000cf82c6c 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -937,7 +937,7 @@ typedef struct client_channel_call_data { // state needed to support channelz interception of recv trailing metadata. grpc_closure recv_trailing_metadata_ready_channelz; grpc_closure* original_recv_trailing_metadata; - grpc_transport_stream_op_batch* recv_trailing_metadata_batch; + grpc_metadata_batch* recv_trailing_metadata_batch; grpc_polling_entity* pollent; bool pollent_added_to_interested_parties; @@ -1000,14 +1000,8 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem); static void on_complete(void* arg, grpc_error* error); static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored); static void start_pick_locked(void* arg, grpc_error* ignored); -template -static pending_batch* pending_batch_find(grpc_call_element* elem, - const char* log_message, - Predicate predicate); -static void get_call_status(grpc_call_element* elem, - grpc_metadata_batch* md_batch, grpc_error* error, - grpc_status_code* status, - grpc_mdelem** server_pushback_md); +static void maybe_intercept_metadata_for_channelz( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch); // // send op data caching @@ -1282,66 +1276,6 @@ static void resume_pending_batch_in_call_combiner(void* arg, grpc_subchannel_call_process_op(subchannel_call, batch); } -static void recv_trailing_metadata_ready_channelz(void* arg, - grpc_error* error) { - grpc_call_element* elem = static_cast(arg); - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: got recv_trailing_metadata_ready_channelz, " - "error=%s", - chand, calld, grpc_error_string(error)); - } - GPR_ASSERT(calld->recv_trailing_metadata_batch != nullptr); - grpc_status_code status = GRPC_STATUS_OK; - grpc_metadata_batch* md_batch = - calld->recv_trailing_metadata_batch->payload->recv_trailing_metadata - .recv_trailing_metadata; - get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); - grpc_core::channelz::SubchannelNode* channelz_subchannel = - calld->pick.connected_subchannel->channelz_subchannel(); - GPR_ASSERT(channelz_subchannel != nullptr); - if (status == GRPC_STATUS_OK) { - channelz_subchannel->RecordCallSucceeded(); - } else { - channelz_subchannel->RecordCallFailed(); - } - calld->recv_trailing_metadata_batch = nullptr; - GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata, error); -} - -// If channelz is enabled, intercept recv_trailing so that we may check the -// status and associate it to a subchannel. -// Returns true if callback was intercepted, false otherwise. -static void maybe_intercept_recv_trailing_for_channelz( - grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { - call_data* calld = static_cast(elem->call_data); - // only intercept payloads with recv trailing. - if (!batch->recv_trailing_metadata) { - return; - } - // only add interceptor is channelz is enabled. - if (calld->pick.connected_subchannel->channelz_subchannel() == nullptr) { - return; - } - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "calld=%p batch=%p: intercepting recv trailing for channelz", calld, - batch); - } - GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, - recv_trailing_metadata_ready_channelz, elem, - grpc_schedule_on_exec_ctx); - // save some state needed for the interception callback. - GPR_ASSERT(calld->recv_trailing_metadata_batch == nullptr); - calld->recv_trailing_metadata_batch = batch; - calld->original_recv_trailing_metadata = - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - &calld->recv_trailing_metadata_ready_channelz; -} - // This is called via the call combiner, so access to calld is synchronized. static void pending_batches_resume(grpc_call_element* elem) { channel_data* chand = static_cast(elem->channel_data); @@ -1366,7 +1300,7 @@ static void pending_batches_resume(grpc_call_element* elem) { pending_batch* pending = &calld->pending_batches[i]; grpc_transport_stream_op_batch* batch = pending->batch; if (batch != nullptr) { - maybe_intercept_recv_trailing_for_channelz(elem, batch); + maybe_intercept_metadata_for_channelz(elem, batch); batch->handler_private.extra_arg = calld->subchannel_call; GRPC_CLOSURE_INIT(&batch->handler_private.closure, resume_pending_batch_in_call_combiner, batch, @@ -2736,6 +2670,65 @@ static void pick_done(void* arg, grpc_error* error) { } } +static void recv_trailing_metadata_ready_channelz(void* arg, + grpc_error* error) { + grpc_call_element* elem = static_cast(arg); + channel_data* chand = static_cast(elem->channel_data); + call_data* calld = static_cast(elem->call_data); + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: got recv_trailing_metadata_ready_channelz, " + "error=%s", + chand, calld, grpc_error_string(error)); + } + GPR_ASSERT(calld->recv_trailing_metadata_batch != nullptr); + grpc_status_code status = GRPC_STATUS_OK; + grpc_metadata_batch* md_batch = calld->recv_trailing_metadata_batch; + get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); + grpc_core::channelz::SubchannelNode* channelz_subchannel = + calld->pick.connected_subchannel->channelz_subchannel(); + GPR_ASSERT(channelz_subchannel != nullptr); + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); + } + calld->recv_trailing_metadata_batch = nullptr; + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata, error); +} + +// If channelz is enabled, intercept recv_trailing so that we may check the +// status and associate it to a subchannel. +// Returns true if callback was intercepted, false otherwise. +static void maybe_intercept_metadata_for_channelz( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { + call_data* calld = static_cast(elem->call_data); + // only intercept payloads with recv trailing. + if (!batch->recv_trailing_metadata) { + return; + } + // only add interceptor is channelz is enabled. + if (calld->pick.connected_subchannel->channelz_subchannel() == nullptr) { + return; + } + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "calld=%p batch=%p: intercepting recv trailing for channelz", calld, + batch); + } + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, + recv_trailing_metadata_ready_channelz, elem, + grpc_schedule_on_exec_ctx); + // save some state needed for the interception callback. + GPR_ASSERT(calld->recv_trailing_metadata_batch == nullptr); + calld->recv_trailing_metadata_batch = + batch->payload->recv_trailing_metadata.recv_trailing_metadata; + calld->original_recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready_channelz; +} + static void maybe_add_call_to_channel_interested_parties_locked( grpc_call_element* elem) { channel_data* chand = static_cast(elem->channel_data); diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index bd2735929c..db5d05140d 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -79,7 +79,7 @@ class BaseNode : public RefCounted { const intptr_t uuid_; }; -// This class is a helper class for channelz entities that deal with Channels +// This class is a helper class for channelz entities that deal with Channels, // Subchannels, and Servers, since those have similar proto definitions. // This class has the ability to: // - track calls_{started,succeeded,failed} @@ -133,6 +133,9 @@ class ChannelNode : public BaseNode { // so it leaves these implementations blank. // // This is utilizing the template method design pattern. + // + // TODO(ncteisen): remove these template methods in favor of manual traversal + // and mutation of the grpc_json object. virtual void PopulateConnectivityState(grpc_json* json) {} virtual void PopulateChildRefs(grpc_json* json) {} @@ -158,7 +161,7 @@ class ChannelNode : public BaseNode { void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } private: - // to allow the channel trace test to access trace(); + // to allow the channel trace test to access trace_. friend class testing::ChannelNodePeer; grpc_channel* channel_ = nullptr; UniquePtr target_; diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc index 90a0254663..4a4f0e49d0 100644 --- a/src/core/lib/channel/connected_channel.cc +++ b/src/core/lib/channel/connected_channel.cc @@ -104,18 +104,18 @@ static void con_start_transport_stream_op_batch( if (batch->recv_initial_metadata) { callback_state* state = &calld->recv_initial_metadata_ready; intercept_callback( - calld, state, false, "connected_recv_initial_metadata_ready", + calld, state, false, "recv_initial_metadata_ready", &batch->payload->recv_initial_metadata.recv_initial_metadata_ready); } if (batch->recv_message) { callback_state* state = &calld->recv_message_ready; - intercept_callback(calld, state, false, "connected_recv_message_ready", + intercept_callback(calld, state, false, "recv_message_ready", &batch->payload->recv_message.recv_message_ready); } if (batch->recv_trailing_metadata) { callback_state* state = &calld->recv_trailing_metadata_ready; intercept_callback( - calld, state, false, "connected_recv_trailing_metadata_ready", + calld, state, false, "recv_trailing_metadata_ready", &batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready); } if (batch->cancel_stream) { diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 3d69db4f83..eb7e67233b 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1425,7 +1425,7 @@ static void receiving_stream_ready_in_call_combiner(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "call_recv_message_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_message_ready"); receiving_stream_ready(bctlp, error); } @@ -1510,8 +1510,7 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, - "call_recv_initial_metadata_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_initial_metadata_ready"); add_batch_error(bctl, GRPC_ERROR_REF(error), false); if (error == GRPC_ERROR_NONE) { @@ -1562,8 +1561,7 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, - "call_recv_trailing_metadata_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready"); add_batch_error(bctl, GRPC_ERROR_REF(error), false); grpc_metadata_batch* md = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index e33277753b..d594445bfb 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -44,8 +44,8 @@ namespace testing { // testing peer to access channel internals class ChannelNodePeer { public: - ChannelNodePeer(ChannelNode* node) : node_(node) {} - ChannelTrace* trace() { return &node_->trace_; } + explicit ChannelNodePeer(ChannelNode* node) : node_(node) {} + ChannelTrace* trace() const { return &node_->trace_; } private: ChannelNode* node_; diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 8fa46a18da..09189fa36d 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -46,8 +46,8 @@ namespace testing { // testing peer to access channel internals class CallCountingHelperPeer { public: - CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {} - grpc_millis last_call_started_millis() { + explicit CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {} + grpc_millis last_call_started_millis() const { return (grpc_millis)gpr_atm_no_barrier_load( &node_->last_call_started_millis_); } -- cgit v1.2.3 From fe1f7f58139a3ccafb7b8e8ca92d5d209880a3e5 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 7 Sep 2018 15:58:22 -0700 Subject: reviewer feedback --- src/core/lib/channel/channelz.cc | 3 --- src/core/lib/channel/channelz.h | 2 -- src/core/lib/surface/call.cc | 11 +++++------ src/core/lib/surface/channel.cc | 4 ++-- test/core/channel/channelz_test.cc | 17 +++++++++-------- test/core/end2end/tests/channelz.cc | 4 ++-- 6 files changed, 18 insertions(+), 23 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index bb79005654..375cf25cc6 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -181,9 +181,6 @@ grpc_json* ServerNode::RenderJson() { // ask CallCountingHelper to populate trace and call count data. call_counter_.PopulateCallCounts(json); json = top_level_json; - // template method. Child classes may override this to add their specific - // functionality. - PopulateSockets(json); return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 9a448d3b38..603ec0b473 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -174,8 +174,6 @@ class ServerNode : public BaseNode { grpc_json* RenderJson() override; - void PopulateSockets(grpc_json* json) {} - // proxy methods to composed classes. void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { trace_.AddTraceEvent(severity, data); diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 826c0fb834..bff3ec379f 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -167,8 +167,6 @@ struct grpc_call { grpc_completion_queue* cq; grpc_polling_entity pollent; grpc_channel* channel; - // backpointer to owning server if this is a server side call. - grpc_server* server; gpr_timespec start_time; /* parent_call* */ gpr_atm parent_call_atm; child_call* child; @@ -250,6 +248,8 @@ struct grpc_call { } client; struct { int* cancelled; + // backpointer to owning server if this is a server side call. + grpc_server* server; } server; } final_op; @@ -369,7 +369,6 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, grpc_slice path = grpc_empty_slice(); if (call->is_client) { GRPC_STATS_INC_CLIENT_CALLS_CREATED(); - call->server = nullptr; GPR_ASSERT(args->add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT); for (i = 0; i < args->add_initial_metadata_count; i++) { @@ -384,7 +383,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, static_cast(args->add_initial_metadata_count); } else { GRPC_STATS_INC_SERVER_CALLS_CREATED(); - call->server = args->server; + call->final_op.server.server = args->server; GPR_ASSERT(args->add_initial_metadata_count == 0); call->send_extra_metadata_count = 0; } @@ -496,7 +495,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, } } else { grpc_core::channelz::ServerNode* channelz_server = - grpc_server_get_channelz_node(call->server); + grpc_server_get_channelz_node(call->final_op.server.server); if (channelz_server != nullptr) { channelz_server->RecordCallStarted(); } @@ -1286,7 +1285,7 @@ static void post_batch_completion(batch_control* bctl) { get_final_status(call, set_cancelled_value, call->final_op.server.cancelled, nullptr, nullptr); grpc_core::channelz::ServerNode* channelz_server = - grpc_server_get_channelz_node(call->server); + grpc_server_get_channelz_node(call->final_op.server.server); if (channelz_server != nullptr) { if (*call->final_op.server.cancelled) { channelz_server->RecordCallFailed(); diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 815d302577..52056b8671 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -166,8 +166,8 @@ grpc_channel* grpc_channel_create_with_builder( } grpc_channel_args_destroy(args); - // only track client channels since server channels are held in the - // grpc_server channel. + // we only need to do the channelz bookkeeping for clients here. The channelz + // bookkeeping for server channels occurs in src/core/lib/surface/server.cc if (channelz_enabled && channel->is_client) { channel->channelz_channel = channel_node_create_func( channel, channel_tracer_max_nodes, !internal_channel); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index f947617d0f..4bfab4e2ee 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -146,20 +146,21 @@ class ChannelFixture { class ServerFixture { public: - ServerFixture(int max_trace_nodes = 0) { - grpc_arg server_a[2]; - server_a[0] = grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE), - max_trace_nodes); - server_a[1] = grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ENABLE_CHANNELZ), true); + explicit ServerFixture(int max_trace_nodes = 0) { + grpc_arg server_a[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE), + max_trace_nodes), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_CHANNELZ), true), + }; grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; server_ = grpc_server_create(&server_args, nullptr); } ~ServerFixture() { grpc_server_destroy(server_); } - grpc_server* server() { return server_; } + grpc_server* server() const { return server_; } private: grpc_server* server_; diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index f96c430b69..40a0370f0e 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -240,7 +240,7 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); - // channel tracing is not enables, so these should not be preset. + // channel tracing is not enabled, so these should not be preset. GPR_ASSERT(nullptr == strstr(json, "\"trace\"")); GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\"")); GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); @@ -252,7 +252,7 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); - // channel tracing is not enables, so these should not be preset. + // channel tracing is not enabled, so these should not be preset. GPR_ASSERT(nullptr == strstr(json, "\"trace\"")); GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\"")); GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); -- cgit v1.2.3 From 2ff5be8c08c75a2c2c0152694788aa1e5ed3d50d Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 10 Sep 2018 10:14:05 -0700 Subject: reveiwer comments --- .../ext/filters/client_channel/client_channel.cc | 128 +++++++++++---------- src/core/lib/channel/connected_channel.cc | 6 +- 2 files changed, 68 insertions(+), 66 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 4691aa1c97..388736b60a 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -936,7 +936,7 @@ typedef struct client_channel_call_data { // state needed to support channelz interception of recv trailing metadata. grpc_closure recv_trailing_metadata_ready_channelz; grpc_closure* original_recv_trailing_metadata; - grpc_metadata_batch* recv_trailing_metadata_batch; + grpc_metadata_batch* recv_trailing_metadata; grpc_polling_entity* pollent; bool pollent_added_to_interested_parties; @@ -999,7 +999,7 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem); static void on_complete(void* arg, grpc_error* error); static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored); static void start_pick_locked(void* arg, grpc_error* ignored); -static void maybe_intercept_metadata_for_channelz( +static void maybe_intercept_recv_trailing_metadata_for_channelz( grpc_call_element* elem, grpc_transport_stream_op_batch* batch); // @@ -1299,7 +1299,7 @@ static void pending_batches_resume(grpc_call_element* elem) { pending_batch* pending = &calld->pending_batches[i]; grpc_transport_stream_op_batch* batch = pending->batch; if (batch != nullptr) { - maybe_intercept_metadata_for_channelz(elem, batch); + maybe_intercept_recv_trailing_metadata_for_channelz(elem, batch); batch->handler_private.extra_arg = calld->subchannel_call; GRPC_CLOSURE_INIT(&batch->handler_private.closure, resume_pending_batch_in_call_combiner, batch, @@ -2589,6 +2589,69 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) { closures.RunClosures(calld->call_combiner); } +// +// Channelz +// + +static void recv_trailing_metadata_ready_channelz(void* arg, + grpc_error* error) { + grpc_call_element* elem = static_cast(arg); + channel_data* chand = static_cast(elem->channel_data); + call_data* calld = static_cast(elem->call_data); + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: got recv_trailing_metadata_ready_channelz, " + "error=%s", + chand, calld, grpc_error_string(error)); + } + GPR_ASSERT(calld->recv_trailing_metadata != nullptr); + grpc_status_code status = GRPC_STATUS_OK; + grpc_metadata_batch* md_batch = calld->recv_trailing_metadata; + get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); + grpc_core::channelz::SubchannelNode* channelz_subchannel = + calld->pick.connected_subchannel->channelz_subchannel(); + GPR_ASSERT(channelz_subchannel != nullptr); + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); + } + calld->recv_trailing_metadata = nullptr; + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata, error); +} + +// If channelz is enabled, intercept recv_trailing so that we may check the +// status and associate it to a subchannel. +// Returns true if callback was intercepted, false otherwise. +static void maybe_intercept_recv_trailing_metadata_for_channelz( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { + call_data* calld = static_cast(elem->call_data); + // only intercept payloads with recv trailing. + if (!batch->recv_trailing_metadata) { + return; + } + // only add interceptor is channelz is enabled. + if (calld->pick.connected_subchannel->channelz_subchannel() == nullptr) { + return; + } + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "calld=%p batch=%p: intercepting recv trailing for channelz", calld, + batch); + } + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, + recv_trailing_metadata_ready_channelz, elem, + grpc_schedule_on_exec_ctx); + // save some state needed for the interception callback. + GPR_ASSERT(calld->recv_trailing_metadata == nullptr); + calld->recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata; + calld->original_recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready_channelz; +} + // // LB pick // @@ -2669,65 +2732,6 @@ static void pick_done(void* arg, grpc_error* error) { } } -static void recv_trailing_metadata_ready_channelz(void* arg, - grpc_error* error) { - grpc_call_element* elem = static_cast(arg); - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: got recv_trailing_metadata_ready_channelz, " - "error=%s", - chand, calld, grpc_error_string(error)); - } - GPR_ASSERT(calld->recv_trailing_metadata_batch != nullptr); - grpc_status_code status = GRPC_STATUS_OK; - grpc_metadata_batch* md_batch = calld->recv_trailing_metadata_batch; - get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); - grpc_core::channelz::SubchannelNode* channelz_subchannel = - calld->pick.connected_subchannel->channelz_subchannel(); - GPR_ASSERT(channelz_subchannel != nullptr); - if (status == GRPC_STATUS_OK) { - channelz_subchannel->RecordCallSucceeded(); - } else { - channelz_subchannel->RecordCallFailed(); - } - calld->recv_trailing_metadata_batch = nullptr; - GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata, error); -} - -// If channelz is enabled, intercept recv_trailing so that we may check the -// status and associate it to a subchannel. -// Returns true if callback was intercepted, false otherwise. -static void maybe_intercept_metadata_for_channelz( - grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { - call_data* calld = static_cast(elem->call_data); - // only intercept payloads with recv trailing. - if (!batch->recv_trailing_metadata) { - return; - } - // only add interceptor is channelz is enabled. - if (calld->pick.connected_subchannel->channelz_subchannel() == nullptr) { - return; - } - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "calld=%p batch=%p: intercepting recv trailing for channelz", calld, - batch); - } - GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, - recv_trailing_metadata_ready_channelz, elem, - grpc_schedule_on_exec_ctx); - // save some state needed for the interception callback. - GPR_ASSERT(calld->recv_trailing_metadata_batch == nullptr); - calld->recv_trailing_metadata_batch = - batch->payload->recv_trailing_metadata.recv_trailing_metadata; - calld->original_recv_trailing_metadata = - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - &calld->recv_trailing_metadata_ready_channelz; -} - static void maybe_add_call_to_channel_interested_parties_locked( grpc_call_element* elem) { channel_data* chand = static_cast(elem->channel_data); diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc index 4a4f0e49d0..e2ea334ded 100644 --- a/src/core/lib/channel/connected_channel.cc +++ b/src/core/lib/channel/connected_channel.cc @@ -126,13 +126,11 @@ static void con_start_transport_stream_op_batch( // closure for each one. callback_state* state = static_cast(gpr_malloc(sizeof(*state))); - intercept_callback(calld, state, true, - "connected_on_complete (cancel_stream)", + intercept_callback(calld, state, true, "on_complete (cancel_stream)", &batch->on_complete); } else if (batch->on_complete != nullptr) { callback_state* state = get_state_for_batch(calld, batch); - intercept_callback(calld, state, false, "connected_on_complete", - &batch->on_complete); + intercept_callback(calld, state, false, "on_complete", &batch->on_complete); } grpc_transport_perform_stream_op( chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), batch); -- cgit v1.2.3 From 11d3309130c7ed657fecf77b981a57cc48173753 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 10 Sep 2018 11:53:18 -0700 Subject: Make batch_error an atomic to avoid data races --- src/core/lib/surface/call.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index b07c4d6c10..90d812dad6 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -95,7 +95,7 @@ typedef struct batch_control { grpc_closure start_batch; grpc_closure finish_batch; gpr_refcount steps_to_complete; - grpc_error* batch_error; + gpr_atm batch_error; grpc_transport_stream_op_batch op; } batch_control; @@ -1106,14 +1106,16 @@ static void finish_batch_completion(void* user_data, } static void reset_batch_errors(batch_control* bctl) { - GRPC_ERROR_UNREF(bctl->batch_error); - bctl->batch_error = GRPC_ERROR_NONE; + GRPC_ERROR_UNREF( + reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error))); + gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_NONE); } static void post_batch_completion(batch_control* bctl) { grpc_call* next_child_call; grpc_call* call = bctl->call; - grpc_error* error = GRPC_ERROR_REF(bctl->batch_error); + grpc_error* error = GRPC_ERROR_REF( + reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error))); if (bctl->op.send_initial_metadata) { grpc_metadata_batch_destroy( @@ -1277,8 +1279,9 @@ static void receiving_stream_ready(void* bctlp, grpc_error* error) { grpc_call* call = bctl->call; if (error != GRPC_ERROR_NONE) { call->receiving_stream.reset(); - if (bctl->batch_error == GRPC_ERROR_NONE) { - bctl->batch_error = GRPC_ERROR_REF(error); + if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == + GRPC_ERROR_NONE) { + gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); } cancel_with_error(call, GRPC_ERROR_REF(error)); } @@ -1384,8 +1387,9 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { call->send_deadline = md->deadline; } } else { - if (bctl->batch_error == GRPC_ERROR_NONE) { - bctl->batch_error = GRPC_ERROR_REF(error); + if (reinterpret_cast gpr_atm_acq_load(&bctl->batch_error) == + GRPC_ERROR_NONE) { + gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); } cancel_with_error(call, GRPC_ERROR_REF(error)); } @@ -1435,8 +1439,9 @@ static void finish_batch(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete"); - if (bctl->batch_error == GRPC_ERROR_NONE) { - bctl->batch_error = GRPC_ERROR_REF(error); + if (reinterpret_cast gpr_atm_acq_load(&bctl->batch_error) == + GRPC_ERROR_NONE) { + gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); } if (error != GRPC_ERROR_NONE) { cancel_with_error(call, GRPC_ERROR_REF(error)); -- cgit v1.2.3 From b6bb49dbf73805e4998ad6f4ac7adc94550e8d97 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 10 Sep 2018 14:20:01 -0700 Subject: reinterpret casts for compiler checks --- src/core/lib/surface/call.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 90d812dad6..ee7c15381a 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1108,7 +1108,8 @@ static void finish_batch_completion(void* user_data, static void reset_batch_errors(batch_control* bctl) { GRPC_ERROR_UNREF( reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error))); - gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_NONE); + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_NONE)); } static void post_batch_completion(batch_control* bctl) { @@ -1281,7 +1282,8 @@ static void receiving_stream_ready(void* bctlp, grpc_error* error) { call->receiving_stream.reset(); if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) { - gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_REF(error))); } cancel_with_error(call, GRPC_ERROR_REF(error)); } @@ -1387,9 +1389,10 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { call->send_deadline = md->deadline; } } else { - if (reinterpret_cast gpr_atm_acq_load(&bctl->batch_error) == + if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) { - gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_REF(error))); } cancel_with_error(call, GRPC_ERROR_REF(error)); } @@ -1439,9 +1442,10 @@ static void finish_batch(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete"); - if (reinterpret_cast gpr_atm_acq_load(&bctl->batch_error) == + if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) { - gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_REF(error))); } if (error != GRPC_ERROR_NONE) { cancel_with_error(call, GRPC_ERROR_REF(error)); -- cgit v1.2.3 From b9a174ab1507306fed5fa4ee70416e2489ef8fcb Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Sep 2018 12:42:01 -0700 Subject: Add check on server for channelz accessor --- src/core/lib/surface/server.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index c0fae0f140..5fa58ffdec 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -1500,5 +1500,8 @@ int grpc_server_has_open_connections(grpc_server* server) { grpc_core::channelz::ServerNode* grpc_server_get_channelz_node( grpc_server* server) { + if (server == nullptr) { + return nullptr; + } return server->channelz_server.get(); } -- cgit v1.2.3 From 157e7fa03e600a4156a2913f8f645c5af4270408 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Sep 2018 14:33:40 -0700 Subject: fix clang tidy --- include/grpc/grpc.h | 2 +- src/core/lib/channel/channel_trace.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index ce421e93bd..3ef95ff462 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -500,7 +500,7 @@ GRPCAPI const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void); GRPCAPI char* grpc_channelz_get_top_channels(intptr_t start_channel_id); /* Gets all servers that exist in the process. */ -GRPCAPI char* grpc_channelz_get_servers(intptr_t start_channel_id); +GRPCAPI char* grpc_channelz_get_servers(intptr_t start_server_id); /* 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/channel_trace.h b/src/core/lib/channel/channel_trace.h index 230faa483e..94fea20b45 100644 --- a/src/core/lib/channel/channel_trace.h +++ b/src/core/lib/channel/channel_trace.h @@ -63,7 +63,7 @@ class ChannelTrace { // stack, determine if it makes more sense to accept a char* instead of a // slice. void AddTraceEventWithReference(Severity severity, grpc_slice data, - RefCountedPtr referenced_channel); + RefCountedPtr referenced_entity); // Creates and returns the raw grpc_json object, so a parent channelz // object may incorporate the json before rendering. -- cgit v1.2.3