From 1e27328de27d192a40d73e1f013fcfffd1f3b04f Mon Sep 17 00:00:00 2001
From: klempner <klempner@google.com>
Date: Wed, 10 Dec 2014 13:55:41 -0800
Subject: [PATCH] Move status 200 setting into http_server_filter and keep a
 fixed mdelem for it rather than allocating a separate one for each rpc. 
 Change on 2014/12/10 by klempner <klempner@google.com> ------------- Created
 by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=81814150

---
 src/core/channel/http_server_filter.c | 24 +++++++++++++++++++-----
 src/core/surface/server.c             |  6 ------
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c
index 7322ff5b46..9c6dd45206 100644
--- a/src/core/channel/http_server_filter.c
+++ b/src/core/channel/http_server_filter.c
@@ -34,11 +34,12 @@
 #include "src/core/channel/http_server_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_status; } call_data;
 
-typedef struct channel_data { grpc_mdelem *te_trailers; } channel_data;
+typedef struct channel_data {
+  grpc_mdelem *te_trailers;
+  grpc_mdelem *status_md;
+} channel_data;
 
 /* used to silence 'variable not used' warnings */
 static void ignore_unused(void *ignored) {}
@@ -76,6 +77,17 @@ static void call_op(grpc_call_element *elem, grpc_call_op *op) {
         grpc_call_next_op(elem, op);
       }
       break;
+    case GRPC_SEND_START:
+    case GRPC_SEND_METADATA:
+      /* If we haven't sent status 200 yet, we need to so so because it needs to
+         come before any non : prefixed metadata. */
+      if (!calld->sent_status) {
+        calld->sent_status = 1;
+        /* status_md is reffed by grpc_call_element_send_metadata */
+        grpc_call_element_send_metadata(elem, channeld->status_md);
+      }
+      grpc_call_next_op(elem, op);
+      break;
     default:
       /* pass control up or down the stack depending on op->dir */
       grpc_call_next_op(elem, op);
@@ -109,7 +121,7 @@ static void init_call_elem(grpc_call_element *elem,
   ignore_unused(channeld);
 
   /* initialize members */
-  calld->unused = 0;
+  calld->sent_status = 0;
 }
 
 /* Destructor for call_data */
@@ -137,6 +149,7 @@ static void init_channel_elem(grpc_channel_element *elem,
 
   /* initialize members */
   channeld->te_trailers = grpc_mdelem_from_strings(mdctx, "te", "trailers");
+  channeld->status_md = grpc_mdelem_from_strings(mdctx, ":status", "200");
 }
 
 /* Destructor for channel data */
@@ -145,6 +158,7 @@ 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->status_md);
 }
 
 const grpc_channel_filter grpc_http_server_filter = {
diff --git a/src/core/surface/server.c b/src/core/surface/server.c
index 2c859060eb..cfff6631f3 100644
--- a/src/core/surface/server.c
+++ b/src/core/surface/server.c
@@ -216,7 +216,6 @@ static void queue_new_rpc(grpc_server *server, call_data *calld, void *tag) {
   const char *host = NULL;
   const char *method = NULL;
   size_t i;
-  grpc_metadata status_md;
 
   for (i = 0; i < count; i++) {
     if (0 == strcmp(elements[i].key, ":authority")) {
@@ -226,11 +225,6 @@ static void queue_new_rpc(grpc_server *server, call_data *calld, void *tag) {
     }
   }
 
-  status_md.key = ":status";
-  status_md.value = "200";
-  status_md.value_length = 3;
-  grpc_call_add_metadata(call, &status_md, GRPC_WRITE_BUFFER_HINT);
-
   grpc_call_internal_ref(call);
   grpc_cq_end_new_rpc(server->cq, tag, call,
                       grpc_metadata_buffer_cleanup_elements, elements, method,
-- 
GitLab