about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-07-12 20:49:46 +0000
committerEric Wong <normalperson@yhbt.net>2013-07-12 21:47:29 +0000
commit4244fd63ef360a1b5a201d82e323c54842f0db55 (patch)
treeb84d070ef14fab2cffc0ce257e01d98352c749ee
parent86c7628b01130559c53dffe1d799f2031a020918 (diff)
downloadcmogstored-4244fd63ef360a1b5a201d82e323c54842f0db55.tar.gz
We don't want drop in-flight pipelined requests when disabling
persistent connections.  Disabling persistent connections will
always be potentially racy, but hopefully this makes the race
small enough that lower-level latencies are the only thing
which affect that.
-rw-r--r--cmogstored.h5
-rw-r--r--http_parser.rl16
2 files changed, 16 insertions, 5 deletions
diff --git a/cmogstored.h b/cmogstored.h
index 5b4493b..2dffbb2 100644
--- a/cmogstored.h
+++ b/cmogstored.h
@@ -197,15 +197,16 @@ enum mog_chunk_state {
 struct mog_http {
         int cs;
         struct {
-                /* only needs 4 bits, but we use 8 for alignment */
-                enum mog_http_method http_method:8;
+                enum mog_http_method http_method:4;
                 unsigned persistent:1;
+                unsigned persist_client_at_start:1;
                 unsigned chunked:1;
                 unsigned has_md5:1;
                 unsigned has_content_range:1; /* for PUT */
                 unsigned has_range:1;         /* for GET */
                 unsigned skip_rbuf_defer:1;
                 enum mog_chunk_state chunk_state:2;
+                unsigned unused_padding:3;
                 uint8_t path_tip;
                 uint8_t path_end;
                 uint16_t line_end;
diff --git a/http_parser.rl b/http_parser.rl
index ef854ba..fc4bfd5 100644
--- a/http_parser.rl
+++ b/http_parser.rl
@@ -125,6 +125,16 @@ void mog_http_reset_parser(struct mog_http *http)
         http->cs = cs;
         memset(&http->_p, 0, sizeof(http->_p));
 
+        if (http->rbuf) /* already pipelined */
+                http->_p.persist_client_at_start = 1;
+        else
+                /*
+                 * we need to know persist_client when we start reading
+                 * the request because we do not want to break pipelined
+                 * requests
+                 */
+                http->_p.persist_client_at_start = http->svc->persist_client;
+
         /* these should probably be in mog_http_init */
         http->forward = NULL;
         http->wbuf = NULL;
@@ -132,9 +142,9 @@ void mog_http_reset_parser(struct mog_http *http)
 
 void mog_http_init(struct mog_http *http, struct mog_svc *svc)
 {
-        mog_http_reset_parser(http);
-        http->rbuf = NULL;
         http->svc = svc;
+        http->rbuf = NULL;
+        mog_http_reset_parser(http);
 }
 
 enum mog_parser_state
@@ -171,7 +181,7 @@ mog_http_parse(struct mog_http *http, char *buf, size_t len)
         assert(http->_p.buf_off <= len && "offset longer than len");
 
         if (http->cs == http_parser_first_final) {
-                http->_p.persistent &= http->svc->persist_client;
+                http->_p.persistent &= http->_p.persist_client_at_start;
                 return MOG_PARSER_DONE;
         }
         return MOG_PARSER_CONTINUE;