diff options
author | Mark D. Roth <roth@google.com> | 2016-08-02 10:05:17 -0700 |
---|---|---|
committer | Mark D. Roth <roth@google.com> | 2016-08-02 10:05:17 -0700 |
commit | 6e26952db4fc3eef2c764d1202281d8cdbb1975a (patch) | |
tree | 10ad005176bbca463c2f7afd90e25448247127ad /src/core/ext/load_reporting | |
parent | 9fd00425c50800906f4deb2c5aafa9b64217b54c (diff) | |
parent | 1e3fdbe7fd7831fe31b05a3da8044872564c4351 (diff) |
Merge remote-tracking branch 'upstream/master' into filter_call_init_failure
Diffstat (limited to 'src/core/ext/load_reporting')
-rw-r--r-- | src/core/ext/load_reporting/load_reporting.c | 60 | ||||
-rw-r--r-- | src/core/ext/load_reporting/load_reporting.h | 61 | ||||
-rw-r--r-- | src/core/ext/load_reporting/load_reporting_filter.c | 154 | ||||
-rw-r--r-- | src/core/ext/load_reporting/load_reporting_filter.h | 1 |
4 files changed, 157 insertions, 119 deletions
diff --git a/src/core/ext/load_reporting/load_reporting.c b/src/core/ext/load_reporting/load_reporting.c index 9e4d32676f..df1ea0ec9a 100644 --- a/src/core/ext/load_reporting/load_reporting.c +++ b/src/core/ext/load_reporting/load_reporting.c @@ -42,42 +42,12 @@ #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/surface/channel_init.h" -struct grpc_load_reporting_config { - grpc_load_reporting_fn fn; - void *user_data; -}; - -grpc_load_reporting_config *grpc_load_reporting_config_create( - grpc_load_reporting_fn fn, void *user_data) { - GPR_ASSERT(fn != NULL); - grpc_load_reporting_config *lrc = - gpr_malloc(sizeof(grpc_load_reporting_config)); - lrc->fn = fn; - lrc->user_data = user_data; - return lrc; -} - -grpc_load_reporting_config *grpc_load_reporting_config_copy( - grpc_load_reporting_config *src) { - return grpc_load_reporting_config_create(src->fn, src->user_data); -} - -void grpc_load_reporting_config_destroy(grpc_load_reporting_config *lrc) { - gpr_free(lrc); -} - -void grpc_load_reporting_config_call( - grpc_load_reporting_config *lrc, - const grpc_load_reporting_call_data *call_data) { - lrc->fn(call_data, lrc->user_data); -} - static bool is_load_reporting_enabled(const grpc_channel_args *a) { if (a == NULL) return false; for (size_t i = 0; i < a->num_args; i++) { if (0 == strcmp(a->args[i].key, GRPC_ARG_ENABLE_LOAD_REPORTING)) { - return a->args[i].type == GRPC_ARG_POINTER && - a->args[i].value.pointer.p != NULL; + return a->args[i].type == GRPC_ARG_INTEGER && + a->args[i].value.integer != 0; } } return false; @@ -94,37 +64,17 @@ static bool maybe_add_load_reporting_filter(grpc_channel_stack_builder *builder, return true; } -static void lrd_arg_destroy(void *p) { grpc_load_reporting_config_destroy(p); } - -static void *lrd_arg_copy(void *p) { - return grpc_load_reporting_config_copy(p); -} - -static int lrd_arg_cmp(void *a, void *b) { - grpc_load_reporting_config *lhs = a; - grpc_load_reporting_config *rhs = b; - return !(lhs->fn == rhs->fn && lhs->user_data == rhs->user_data); -} - -static const grpc_arg_pointer_vtable lrd_ptr_vtable = { - lrd_arg_copy, lrd_arg_destroy, lrd_arg_cmp}; - -grpc_arg grpc_load_reporting_config_create_arg( - grpc_load_reporting_config *lrc) { +grpc_arg grpc_load_reporting_enable_arg() { grpc_arg arg; - arg.type = GRPC_ARG_POINTER; + arg.type = GRPC_ARG_INTEGER; arg.key = GRPC_ARG_ENABLE_LOAD_REPORTING; - arg.value.pointer.p = lrc; - arg.value.pointer.vtable = &lrd_ptr_vtable; + arg.value.integer = 1; return arg; } /* Plugin registration */ void grpc_load_reporting_plugin_init(void) { - grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, - maybe_add_load_reporting_filter, - (void *)&grpc_load_reporting_filter); grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, maybe_add_load_reporting_filter, (void *)&grpc_load_reporting_filter); diff --git a/src/core/ext/load_reporting/load_reporting.h b/src/core/ext/load_reporting/load_reporting.h index 316cd89bd7..e37817d8c2 100644 --- a/src/core/ext/load_reporting/load_reporting.h +++ b/src/core/ext/load_reporting/load_reporting.h @@ -34,42 +34,47 @@ #ifndef GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H #define GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H -#include "src/core/lib/iomgr/closure.h" -#include "src/core/lib/surface/call.h" +#include <grpc/impl/codegen/grpc_types.h> +#include "src/core/lib/channel/channel_stack.h" -typedef struct grpc_load_reporting_config grpc_load_reporting_config; +/** Metadata key for initial metadata coming from clients */ +/* TODO(dgq): change to the final value TBD */ +#define GRPC_LOAD_REPORTING_INITIAL_MD_KEY "load-reporting-initial" -/** Call information to be passed to the provided load reporting function upon - * completion of the call */ -typedef struct grpc_load_reporting_call_data { - const grpc_call_stats *stats; /**< Stats for the call */ - const char *trailing_md_string; /**< LR trailing metadata info */ -} grpc_load_reporting_call_data; +/** Metadata key for trailing metadata from servers */ +/* TODO(dgq): change to the final value TBD */ +#define GRPC_LOAD_REPORTING_TRAILING_MD_KEY "load-reporting-trailing" -/** Custom function to be called by the load reporting filter. */ -typedef void (*grpc_load_reporting_fn)( - const grpc_load_reporting_call_data *call_data, void *user_data); +/** Identifiers for the invocation point of the users LR callback */ +typedef enum grpc_load_reporting_source { + GRPC_LR_POINT_UNKNOWN = 0, + GRPC_LR_POINT_CHANNEL_CREATION, + GRPC_LR_POINT_CHANNEL_DESTRUCTION, + GRPC_LR_POINT_CALL_CREATION, + GRPC_LR_POINT_CALL_DESTRUCTION +} grpc_load_reporting_source; -/** Register \a fn as the function to be invoked by the load reporting filter. - * \a fn will be invoked at the beginning and at the end of the call. - * - * For the first invocation, \a fn's first argument - * (grpc_load_reporting_call_data*) will be NULL. \a user_data is always passed - * as-is. */ -grpc_load_reporting_config *grpc_load_reporting_config_create( - grpc_load_reporting_fn fn, void *user_data); +/** Call information to be passed to the provided LR callback. */ +typedef struct grpc_load_reporting_call_data { + const grpc_load_reporting_source source; /**< point of last data update. */ + + /** Unique identifier for the channel associated with the data */ + intptr_t channel_id; -grpc_load_reporting_config *grpc_load_reporting_config_copy( - grpc_load_reporting_config *src); + /** Unique identifier for the call associated with the data. If the call + * hasn't been created yet, it'll have a value of zero. */ + intptr_t call_id; -void grpc_load_reporting_config_destroy(grpc_load_reporting_config *lrc); + /** Only valid when \a source is \a GRPC_LR_POINT_CALL_DESTRUCTION, that is, + * once the call has completed */ + const grpc_call_final_info *final_info; -/** Invoke the function registered by \a grpc_load_reporting_init. */ -void grpc_load_reporting_config_call( - grpc_load_reporting_config *lrc, - const grpc_load_reporting_call_data *call_data); + const char *initial_md_string; /**< value string for LR's initial md key */ + const char *trailing_md_string; /**< value string for LR's trailing md key */ + const char *method_name; /**< Corresponds to :path header */ +} grpc_load_reporting_call_data; /** Return a \a grpc_arg enabling load reporting */ -grpc_arg grpc_load_reporting_config_create_arg(grpc_load_reporting_config *lrc); +grpc_arg grpc_load_reporting_enable_arg(); #endif /* GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H */ diff --git a/src/core/ext/load_reporting/load_reporting_filter.c b/src/core/ext/load_reporting/load_reporting_filter.c index b584e31c5d..394f0cb832 100644 --- a/src/core/ext/load_reporting/load_reporting_filter.c +++ b/src/core/ext/load_reporting/load_reporting_filter.c @@ -31,6 +31,7 @@ * */ +#include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> #include <grpc/support/sync.h> @@ -42,17 +43,67 @@ #include "src/core/lib/profiling/timers.h" #include "src/core/lib/transport/static_metadata.h" -typedef struct call_data { const char *trailing_md_string; } call_data; +typedef struct call_data { + intptr_t id; /**< an id unique to the call */ + char *trailing_md_string; + char *initial_md_string; + const char *service_method; + + /* stores the recv_initial_metadata op's ready closure, which we wrap with our + * own (on_initial_md_ready) in order to capture the incoming initial metadata + * */ + grpc_closure *ops_recv_initial_metadata_ready; + + /* to get notified of the availability of the incoming initial metadata. */ + grpc_closure on_initial_md_ready; + grpc_metadata_batch *recv_initial_metadata; +} call_data; + typedef struct channel_data { - gpr_mu mu; - grpc_load_reporting_config *lrc; + intptr_t id; /**< an id unique to the channel */ } channel_data; -static void invoke_lr_fn_locked(grpc_load_reporting_config *lrc, - grpc_load_reporting_call_data *lr_call_data) { - GPR_TIMER_BEGIN("load_reporting_config_fn", 0); - grpc_load_reporting_config_call(lrc, lr_call_data); - GPR_TIMER_END("load_reporting_config_fn", 0); +typedef struct { + grpc_call_element *elem; + grpc_exec_ctx *exec_ctx; +} recv_md_filter_args; + +static grpc_mdelem *recv_md_filter(void *user_data, grpc_mdelem *md) { + recv_md_filter_args *a = user_data; + grpc_call_element *elem = a->elem; + call_data *calld = elem->call_data; + + if (md->key == GRPC_MDSTR_PATH) { + calld->service_method = grpc_mdstr_as_c_string(md->value); + } else if (md->key == GRPC_MDSTR_LOAD_REPORTING_INITIAL) { + calld->initial_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value)); + return NULL; + } + + return md; +} + +static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_error *err) { + grpc_call_element *elem = user_data; + call_data *calld = elem->call_data; + + if (err == GRPC_ERROR_NONE) { + recv_md_filter_args a; + a.elem = elem; + a.exec_ctx = exec_ctx; + grpc_metadata_batch_filter(calld->recv_initial_metadata, recv_md_filter, + &a); + if (calld->service_method == NULL) { + err = + grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :path header")); + } + } else { + GRPC_ERROR_REF(err); + } + calld->ops_recv_initial_metadata_ready->cb( + exec_ctx, calld->ops_recv_initial_metadata_ready->cb_arg, err); + GRPC_ERROR_UNREF(err); } /* Constructor for call_data */ @@ -61,21 +112,43 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element_args *args) { call_data *calld = elem->call_data; memset(calld, 0, sizeof(call_data)); + + calld->id = (intptr_t)args->call_stack; + grpc_closure_init(&calld->on_initial_md_ready, on_initial_md_ready, elem); + + /* TODO(dgq): do something with the data + channel_data *chand = elem->channel_data; + grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_CREATION, + (intptr_t)chand->id, + (intptr_t)calld->id, + NULL, + NULL, + NULL, + NULL}; + */ + return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, void *ignored) { - channel_data *chand = elem->channel_data; + const grpc_call_final_info *final_info, + void *ignored) { call_data *calld = elem->call_data; - grpc_load_reporting_call_data lr_call_data = {stats, - calld->trailing_md_string}; - - gpr_mu_lock(&chand->mu); - invoke_lr_fn_locked(chand->lrc, &lr_call_data); - gpr_mu_unlock(&chand->mu); + /* TODO(dgq): do something with the data + channel_data *chand = elem->channel_data; + grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_DESTRUCTION, + (intptr_t)chand->id, + (intptr_t)calld->id, + final_info, + calld->initial_md_string, + calld->trailing_md_string, + calld->service_method}; + */ + + gpr_free(calld->initial_md_string); + gpr_free(calld->trailing_md_string); } /* Constructor for channel_data */ @@ -87,37 +160,40 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx, channel_data *chand = elem->channel_data; memset(chand, 0, sizeof(channel_data)); - gpr_mu_init(&chand->mu); - for (size_t i = 0; i < args->channel_args->num_args; i++) { - if (0 == strcmp(args->channel_args->args[i].key, - GRPC_ARG_ENABLE_LOAD_REPORTING)) { - grpc_load_reporting_config *arg_lrc = - args->channel_args->args[i].value.pointer.p; - chand->lrc = grpc_load_reporting_config_copy(arg_lrc); - GPR_ASSERT(chand->lrc != NULL); - break; - } - } - GPR_ASSERT(chand->lrc != NULL); /* arg actually found */ - - gpr_mu_lock(&chand->mu); - invoke_lr_fn_locked(chand->lrc, NULL); - gpr_mu_unlock(&chand->mu); + chand->id = (intptr_t)args->channel_stack; + + /* TODO(dgq): do something with the data + grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CHANNEL_CREATION, + (intptr_t)chand, + 0, + NULL, + NULL, + NULL, + NULL}; + */ } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { + /* TODO(dgq): do something with the data channel_data *chand = elem->channel_data; - gpr_mu_destroy(&chand->mu); - grpc_load_reporting_config_destroy(chand->lrc); + grpc_load_reporting_call_data lr_call_data = { + GRPC_LR_POINT_CHANNEL_DESTRUCTION, + (intptr_t)chand->id, + 0, + NULL, + NULL, + NULL, + NULL}; + */ } static grpc_mdelem *lr_trailing_md_filter(void *user_data, grpc_mdelem *md) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; - if (md->key == GRPC_MDSTR_LOAD_REPORTING) { + if (md->key == GRPC_MDSTR_LOAD_REPORTING_TRAILING) { calld->trailing_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value)); return NULL; } @@ -129,8 +205,14 @@ static void lr_start_transport_stream_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op *op) { GPR_TIMER_BEGIN("lr_start_transport_stream_op", 0); + call_data *calld = elem->call_data; - if (op->send_trailing_metadata) { + if (op->recv_initial_metadata) { + calld->recv_initial_metadata = op->recv_initial_metadata; + /* substitute our callback for the higher callback */ + calld->ops_recv_initial_metadata_ready = op->recv_initial_metadata_ready; + op->recv_initial_metadata_ready = &calld->on_initial_md_ready; + } else if (op->send_trailing_metadata) { grpc_metadata_batch_filter(op->send_trailing_metadata, lr_trailing_md_filter, elem); } diff --git a/src/core/ext/load_reporting/load_reporting_filter.h b/src/core/ext/load_reporting/load_reporting_filter.h index f69cd6fdc6..160ed32af9 100644 --- a/src/core/ext/load_reporting/load_reporting_filter.h +++ b/src/core/ext/load_reporting/load_reporting_filter.h @@ -34,6 +34,7 @@ #ifndef GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_FILTER_H #define GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_FILTER_H +#include "src/core/ext/load_reporting/load_reporting.h" #include "src/core/lib/channel/channel_stack.h" extern const grpc_channel_filter grpc_load_reporting_filter; |