Pre allocate client side strings per channel for method, scheme, path, and

authority.

For method and scheme, move these from channel to http_client_filter.
	Change on 2014/12/19 by klempner <klempner@google.com>
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=82536909
pull/1/merge
klempner 10 years ago committed by Craig Tiller
parent 186cdab82e
commit c463f746c9
  1. 39
      src/core/channel/http_client_filter.c
  2. 33
      src/core/surface/call.c
  3. 3
      src/core/surface/call.h
  4. 36
      src/core/surface/channel.c

@ -34,11 +34,14 @@
#include "src/core/channel/http_client_filter.h"
#include <grpc/support/log.h>
typedef struct call_data {
int unused; /* C89 requires at least one struct element */
} call_data;
typedef struct call_data { int sent_headers; } call_data;
typedef struct channel_data { grpc_mdelem *te_trailers; } channel_data;
typedef struct channel_data {
grpc_mdelem *te_trailers;
grpc_mdelem *method;
grpc_mdelem *scheme;
grpc_mdelem *content_type;
} channel_data;
/* used to silence 'variable not used' warnings */
static void ignore_unused(void *ignored) {}
@ -58,9 +61,26 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
ignore_unused(calld);
switch (op->type) {
case GRPC_SEND_METADATA:
if (!calld->sent_headers) {
/* Send : prefixed headers, which have to be before any application
* layer headers. */
calld->sent_headers = 1;
grpc_call_element_send_metadata(elem, channeld->method);
grpc_call_element_send_metadata(elem, channeld->scheme);
}
grpc_call_next_op(elem, op);
break;
case GRPC_SEND_START:
/* just prior to starting, add a te: trailers header */
if (!calld->sent_headers) {
/* Send : prefixed headers, if we haven't already */
calld->sent_headers = 1;
grpc_call_element_send_metadata(elem, channeld->method);
grpc_call_element_send_metadata(elem, channeld->scheme);
}
/* Send non : prefixed headers */
grpc_call_element_send_metadata(elem, channeld->te_trailers);
grpc_call_element_send_metadata(elem, channeld->content_type);
grpc_call_next_op(elem, op);
break;
default:
@ -97,7 +117,7 @@ static void init_call_elem(grpc_call_element *elem,
ignore_unused(channeld);
/* initialize members */
calld->unused = 0;
calld->sent_headers = 0;
}
/* Destructor for call_data */
@ -125,6 +145,10 @@ static void init_channel_elem(grpc_channel_element *elem,
/* initialize members */
channeld->te_trailers = grpc_mdelem_from_strings(mdctx, "te", "trailers");
channeld->method = grpc_mdelem_from_strings(mdctx, ":method", "POST");
channeld->scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "grpc");
channeld->content_type =
grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc");
}
/* Destructor for channel data */
@ -133,6 +157,9 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
channel_data *channeld = elem->channel_data;
grpc_mdelem_unref(channeld->te_trailers);
grpc_mdelem_unref(channeld->method);
grpc_mdelem_unref(channeld->scheme);
grpc_mdelem_unref(channeld->content_type);
}
const grpc_channel_filter grpc_http_client_filter = {

@ -291,11 +291,28 @@ void grpc_call_execute_op(grpc_call *call, grpc_call_op *op) {
elem->filter->call_op(elem, NULL, op);
}
grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata,
gpr_uint32 flags) {
void grpc_call_add_mdelem(grpc_call *call, grpc_mdelem *mdelem,
gpr_uint32 flags) {
grpc_call_element *elem;
grpc_call_op op;
GPR_ASSERT(call->state < CALL_FINISHED);
op.type = GRPC_SEND_METADATA;
op.dir = GRPC_CALL_DOWN;
op.flags = flags;
op.done_cb = do_nothing;
op.user_data = NULL;
op.data.metadata = mdelem;
elem = CALL_ELEM_FROM_CALL(call, 0);
elem->filter->call_op(elem, NULL, &op);
}
grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata,
gpr_uint32 flags) {
grpc_mdelem *mdelem;
if (call->is_client) {
if (call->state >= CALL_STARTED) {
return GRPC_CALL_ERROR_ALREADY_INVOKED;
@ -306,18 +323,10 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata,
}
}
op.type = GRPC_SEND_METADATA;
op.dir = GRPC_CALL_DOWN;
op.flags = flags;
op.done_cb = do_nothing;
op.user_data = NULL;
op.data.metadata = grpc_mdelem_from_string_and_buffer(
mdelem = grpc_mdelem_from_string_and_buffer(
call->metadata_context, metadata->key, (gpr_uint8 *)metadata->value,
metadata->value_length);
elem = CALL_ELEM_FROM_CALL(call, 0);
elem->filter->call_op(elem, NULL, &op);
grpc_call_add_mdelem(call, mdelem, flags);
return GRPC_CALL_OK;
}

@ -70,4 +70,7 @@ grpc_call *grpc_call_from_top_element(grpc_call_element *surface_element);
/* Get the metadata buffer. */
grpc_metadata_buffer *grpc_call_get_metadata_buffer(grpc_call *call);
void grpc_call_add_mdelem(grpc_call *call, grpc_mdelem *mdelem,
gpr_uint32 flags);
#endif /* __GRPC_INTERNAL_SURFACE_CALL_H__ */

@ -47,6 +47,8 @@ struct grpc_channel {
grpc_mdctx *metadata_context;
grpc_mdstr *grpc_status_string;
grpc_mdstr *grpc_message_string;
grpc_mdstr *path_string;
grpc_mdstr *authority_string;
};
#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c)+1))
@ -63,6 +65,8 @@ grpc_channel *grpc_channel_create_from_filters(
channel->metadata_context = mdctx;
channel->grpc_status_string = grpc_mdstr_from_string(mdctx, "grpc-status");
channel->grpc_message_string = grpc_mdstr_from_string(mdctx, "grpc-message");
channel->path_string = grpc_mdstr_from_string(mdctx, ":path");
channel->authority_string = grpc_mdstr_from_string(mdctx, ":authority");
grpc_channel_stack_init(filters, num_filters, args, channel->metadata_context,
CHANNEL_STACK_FROM_CHANNEL(channel));
return channel;
@ -74,7 +78,8 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel, const char *method,
const char *host,
gpr_timespec absolute_deadline) {
grpc_call *call;
grpc_metadata md;
grpc_mdelem *path_mdelem;
grpc_mdelem *authority_mdelem;
if (!channel->is_client) {
gpr_log(GPR_ERROR, "Cannot create a call on the server.");
@ -83,18 +88,21 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel, const char *method,
call = grpc_call_create(channel, NULL);
#define ADDMD(k, v) \
do { \
md.key = (k); \
md.value = (char *)(v); \
md.value_length = strlen((v)); \
grpc_call_add_metadata(call, &md, 0); \
} while (0)
ADDMD(":method", "POST");
ADDMD(":scheme", "grpc");
ADDMD(":path", method);
ADDMD(":authority", host);
ADDMD("content-type", "application/grpc");
/* Add :path and :authority headers. */
/* TODO(klempner): Consider optimizing this by stashing mdelems for common
values of method and host. */
grpc_mdstr_ref(channel->path_string);
path_mdelem = grpc_mdelem_from_metadata_strings(
channel->metadata_context, channel->path_string,
grpc_mdstr_from_string(channel->metadata_context, method));
grpc_call_add_mdelem(call, path_mdelem, 0);
grpc_mdstr_ref(channel->authority_string);
authority_mdelem = grpc_mdelem_from_metadata_strings(
channel->metadata_context, channel->authority_string,
grpc_mdstr_from_string(channel->metadata_context, host));
grpc_call_add_mdelem(call, authority_mdelem, 0);
if (0 != gpr_time_cmp(absolute_deadline, gpr_inf_future)) {
grpc_call_op op;
op.type = GRPC_SEND_DEADLINE;
@ -118,6 +126,8 @@ void grpc_channel_internal_unref(grpc_channel *channel) {
grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel));
grpc_mdstr_unref(channel->grpc_status_string);
grpc_mdstr_unref(channel->grpc_message_string);
grpc_mdstr_unref(channel->path_string);
grpc_mdstr_unref(channel->authority_string);
grpc_mdctx_orphan(channel->metadata_context);
gpr_free(channel);
}

Loading…
Cancel
Save