about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-06-21 03:34:14 +0000
committerEric Wong <normalperson@yhbt.net>2013-06-25 21:25:28 +0000
commit89f0cf089b9e68730948ce652b42efaf26b98fd2 (patch)
tree674f2c0172f3612bf4e52422418ce6a3722dec6b
parent2376ed3c3da3bd2c9e8326e7dd75be2188fffc35 (diff)
downloadcmogstored-89f0cf089b9e68730948ce652b42efaf26b98fd2.tar.gz
This will allow us to do lookups for IO queues/semaphores before
we attempt to fstatat/stat a path.
-rw-r--r--Makefile.am5
-rw-r--r--chunk_parser.rl8
-rw-r--r--cmogstored.h6
-rw-r--r--http.c23
-rw-r--r--http_parser.rl9
-rw-r--r--http_put.c42
-rw-r--r--mgmt.c14
-rw-r--r--mgmt_parser.rl13
-rw-r--r--path_parser.h14
-rw-r--r--path_parser.rl21
-rw-r--r--test/chunk-parser-1.c14
-rw-r--r--test/http-parser-1.c21
12 files changed, 120 insertions, 70 deletions
diff --git a/Makefile.am b/Makefile.am
index 499def1..e57d2cf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -103,11 +103,12 @@ RAGEL = ragel
 RL_MAIN = cfg_parser.rl iostat_parser.rl listen_parser.rl mgmt_parser.rl \
           valid_path.rl http_parser.rl chunk_parser.rl valid_put_path.rl
 RL_CGEN = $(RL_MAIN:.rl=.c)
-RL_ALL = listen_parser_common.rl http_common.rl $(RL_MAIN)
+RL_ALL = listen_parser_common.rl http_common.rl path_parser.rl $(RL_MAIN)
 
 cfg_parser.c: cfg_parser.rl listen_parser_common.rl
 listen_parser.c: listen_parser.rl listen_parser_common.rl
-http_parser.c: http_parser.rl http_common.rl
+http_parser.c: http_parser.rl http_common.rl path_parser.rl
+mgmt_parser.c: path_parser.rl
 chunk_parser.c: chunk_parser.rl http_common.rl
 .rl.c:
         $(AM_V_GEN)$(RAGEL) $< -C $(RLFLAGS) -o $@
diff --git a/chunk_parser.rl b/chunk_parser.rl
index 926db26..e339a87 100644
--- a/chunk_parser.rl
+++ b/chunk_parser.rl
@@ -104,7 +104,7 @@ void mog_chunk_init(struct mog_http *http)
         http->cs = cs;
         http->_p.line_end = 0;
         http->_p.content_len = 0;
-        http->_p.offset = 0;
+        http->_p.buf_off = 0;
         http->_p.chunk_state = MOG_CHUNK_STATE_SIZE;
 }
 
@@ -114,7 +114,7 @@ mog_chunk_parse(struct mog_http *http, char *buf, size_t len)
         char *p, *pe, *eof = NULL;
         int cs = http->cs;
         int really_done = 0;
-        size_t off = http->_p.offset;
+        size_t off = http->_p.buf_off;
 
         assert(http->wbuf == NULL && "unwritten data in buffer");
         assert(off <= len && "http offset past end of buffer");
@@ -132,13 +132,13 @@ mog_chunk_parse(struct mog_http *http, char *buf, size_t len)
                 cs = chunk_parser_first_final;
 
         http->cs = cs;
-        http->_p.offset = p - buf;
+        http->_p.buf_off = p - buf;
 
         if (cs == chunk_parser_error || errno)
                 return MOG_PARSER_ERROR;
 
         assert(p <= pe && "buffer overflow after chunk parse");
-        assert(http->_p.offset <= len && "offset longer than len");
+        assert(http->_p.buf_off <= len && "offset longer than len");
 
         if (http->cs == chunk_parser_first_final) return MOG_PARSER_DONE;
         return MOG_PARSER_CONTINUE;
diff --git a/cmogstored.h b/cmogstored.h
index 6bbd786..2937049 100644
--- a/cmogstored.h
+++ b/cmogstored.h
@@ -123,7 +123,8 @@ struct mog_mgmt {
         int cs;
         enum mog_prio prio;
         struct mog_fd *forward;
-        size_t offset;
+        uint32_t buf_off;
+        uint32_t mog_devid;
         size_t mark[2];
         struct mog_rbuf *rbuf;
         struct mog_wbuf *wbuf; /* uncommonly needed */
@@ -185,7 +186,8 @@ struct mog_http {
                 uint8_t path_end;
                 uint16_t line_end;
                 uint16_t tmp_tip;
-                size_t offset;
+                uint32_t buf_off;
+                uint32_t mog_devid;
                 off_t range_beg;
                 off_t range_end;
                 off_t content_len;
diff --git a/http.c b/http.c
index 5fa34bc..3f20f60 100644
--- a/http.c
+++ b/http.c
@@ -34,15 +34,15 @@ static void
 http_defer_rbuf(struct mog_http *http, struct mog_rbuf *rbuf, size_t buf_len)
 {
         struct mog_rbuf *old = http->rbuf;
-        size_t defer_bytes = buf_len - http->_p.offset;
-        char *src = rbuf->rptr + http->_p.offset;
+        size_t defer_bytes = buf_len - http->_p.buf_off;
+        char *src = rbuf->rptr + http->_p.buf_off;
 
         if (http->_p.skip_rbuf_defer) {
                 http->_p.skip_rbuf_defer = 0;
                 return;
         }
 
-        assert(http->_p.offset >= 0 && "http->_p.offset negative");
+        assert(http->_p.buf_off >= 0 && "http->_p.buf_off negative");
         assert(defer_bytes <= MOG_RBUF_MAX_SIZE && "defer bytes overflow");
 
         if (defer_bytes == 0) {
@@ -56,7 +56,7 @@ http_defer_rbuf(struct mog_http *http, struct mog_rbuf *rbuf, size_t buf_len)
                 memcpy(http->rbuf->rptr, src, defer_bytes);
                 http->rbuf->rsize = defer_bytes;
         }
-        http->_p.offset = 0;
+        http->_p.buf_off = 0;
 }
 
 static void
@@ -106,7 +106,7 @@ static enum mog_next http_wbuf_in_progress(struct mog_http *http)
                 if (!http->_p.persistent) return MOG_NEXT_CLOSE;
                 if (http->forward == NULL)
                         mog_http_reset(http);
-                assert(http->_p.offset == 0 && "bad offset");
+                assert(http->_p.buf_off == 0 && "bad offset");
                 return MOG_NEXT_ACTIVE;
         case MOG_WRSTATE_BUSY:
                 /* unlikely, we never put anything big in wbuf */
@@ -134,7 +134,7 @@ static enum mog_next http_queue_step(struct mog_fd *mfd)
         struct mog_rbuf *rbuf;
         char *buf;
         ssize_t r;
-        off_t off;
+        uint32_t off;
         size_t buf_len = 0;
         enum mog_parser_state state;
 
@@ -146,16 +146,15 @@ static enum mog_next http_queue_step(struct mog_fd *mfd)
         /* we may have pipelined data in http->rbuf */
         rbuf = http->rbuf ? http->rbuf : mog_rbuf_get(MOG_RBUF_BASE_SIZE);
         buf = rbuf->rptr;
-        off = http->_p.offset;
-        assert(off >= 0 && "offset is negative");
+        off = http->_p.buf_off;
         assert(off < rbuf->rcapa && "offset is too big");
         if (http->rbuf) {
                 /* request got pipelined, resuming now */
                 buf_len = http->rbuf->rsize;
-                assert(http->_p.offset <= buf_len
+                assert(http->_p.buf_off <= buf_len
                         && "bad offset from pipelining");
                 assert(buf_len <= http->rbuf->rcapa && "bad rsize stashed");
-                if (http->_p.offset < buf_len)
+                if (http->_p.buf_off < buf_len)
                         goto parse;
         }
 reread:
@@ -174,14 +173,14 @@ parse:
                 case MOG_PARSER_CONTINUE:
                         assert(http->wbuf == NULL &&
                                "tried to write (and failed) with partial req");
-                        if (http->_p.offset >= rbuf->rcapa) {
+                        if (http->_p.buf_off >= rbuf->rcapa) {
                                 rbuf->rsize = buf_len;
                                 http->rbuf = rbuf = mog_rbuf_grow(rbuf);
                                 if (!rbuf)
                                         goto err400;
                                 buf = rbuf->rptr;
                         }
-                        off = http->_p.offset;
+                        off = http->_p.buf_off;
                         goto reread;
                 case MOG_PARSER_DONE:
                         http_process_client(mfd, buf, buf_len);
diff --git a/http_parser.rl b/http_parser.rl
index 364a984..0622d62 100644
--- a/http_parser.rl
+++ b/http_parser.rl
@@ -24,12 +24,12 @@ static bool length_incr(off_t *len, unsigned c)
 %%{
         machine http_parser;
         include http_common "http_common.rl";
+        include path_parser "path_parser.rl";
 
         ignored_header := header_name ':' sep header_value eor @ {
                 fgoto more_headers;
         };
 
-        mog_path = '/'[a-zA-Z0-9/\.\-]{0,36}; # only stuff MogileFS will use
         GET = "GET "> { http->_p.http_method = MOG_HTTP_METHOD_GET; };
         HEAD = "HEAD "> { http->_p.http_method = MOG_HTTP_METHOD_HEAD; };
         PUT = "PUT "> { http->_p.http_method = MOG_HTTP_METHOD_PUT; };
@@ -143,7 +143,8 @@ mog_http_parse(struct mog_http *http, char *buf, size_t len)
         char *p, *pe, *eof = NULL;
         int cs = http->cs;
         int really_done = 0;
-        size_t off = http->_p.offset;
+        size_t off = http->_p.buf_off;
+        uint32_t *mog_devid = &http->_p.mog_devid;
 
         assert(http->wbuf == NULL && "unwritten data in buffer");
         assert(off <= len && "http offset past end of buffer");
@@ -161,13 +162,13 @@ mog_http_parse(struct mog_http *http, char *buf, size_t len)
                 cs = http_parser_first_final;
 
         http->cs = cs;
-        http->_p.offset = p - buf;
+        http->_p.buf_off = p - buf;
 
         if (cs == http_parser_error || errno)
                 return MOG_PARSER_ERROR;
 
         assert(p <= pe && "buffer overflow after http parse");
-        assert(http->_p.offset <= len && "offset longer than len");
+        assert(http->_p.buf_off <= len && "offset longer than len");
 
         if (http->cs == http_parser_first_final) return MOG_PARSER_DONE;
         return MOG_PARSER_CONTINUE;
diff --git a/http_put.c b/http_put.c
index 360c46e..999d3a7 100644
--- a/http_put.c
+++ b/http_put.c
@@ -185,20 +185,20 @@ static void stash_advance_rbuf(struct mog_http *http, char *buf, size_t buf_len)
         size_t end = http->_p.line_end + 1;
 
         if (http->_p.line_end == 0 || buf_len <= end) {
-                http->_p.offset = 0;
+                http->_p.buf_off = 0;
                 mog_rbuf_free_and_null(&http->rbuf);
                 return;
         }
 
         assert(buf[http->_p.line_end] == '\n' && "line_end is not LF");
         assert(buf_len <= MOG_RBUF_MAX_SIZE && "bad rbuf size");
-        assert(end <= http->_p.offset && "invalid line end");
+        assert(end <= http->_p.buf_off && "invalid line end");
         if (rbuf == NULL)
                 http->rbuf = rbuf = mog_rbuf_new(MOG_RBUF_BASE_SIZE);
 
         memmove(rbuf->rptr, buf + end, buf_len - end);
         rbuf->rsize = buf_len - end;
-        http->_p.offset -= end;
+        http->_p.buf_off -= end;
         if (http->_p.tmp_tip >= end)
                 http->_p.tmp_tip -= end;
         http->_p.line_end = 0;
@@ -207,10 +207,10 @@ static void stash_advance_rbuf(struct mog_http *http, char *buf, size_t buf_len)
 static void
 chunked_body_after_header(struct mog_http *http, char *buf, size_t buf_len)
 {
-        size_t tmpoff = http->_p.offset;
+        size_t tmpoff = http->_p.buf_off;
 
         mog_chunk_init(http);
-        http->_p.offset = tmpoff;
+        http->_p.buf_off = tmpoff;
 
         switch (mog_chunk_parse(http, buf, buf_len)) {
         case MOG_PARSER_ERROR:
@@ -222,23 +222,23 @@ chunked_body_after_header(struct mog_http *http, char *buf, size_t buf_len)
         case MOG_PARSER_DONE:
                 switch (http->_p.chunk_state) {
                 case MOG_CHUNK_STATE_SIZE:
-                        assert(http->_p.offset == buf_len
+                        assert(http->_p.buf_off == buf_len
                                && "HTTP chunk parser didn't finish size");
                         return;
                 case MOG_CHUNK_STATE_DATA:
-                        assert(http->_p.offset == buf_len
+                        assert(http->_p.buf_off == buf_len
                                && "HTTP chunk parser didn't finish data");
                         return;
                 case MOG_CHUNK_STATE_TRAILER:
-                        assert(http->_p.offset > 0 &&
-                               "http->_p.offset unset while in trailer");
+                        assert(http->_p.buf_off > 0 &&
+                               "http->_p.buf_off unset while in trailer");
                         stash_advance_rbuf(http, buf, buf_len);
                         http->_p.skip_rbuf_defer = 1;
                         return;
                 case MOG_CHUNK_STATE_DONE:
                         put_commit_resp(http);
-                        assert(http->_p.offset > 0 &&
-                               "http->_p.offset unset after chunk body done");
+                        assert(http->_p.buf_off > 0 &&
+                               "http->_p.buf_off unset after chunk body done");
                         stash_advance_rbuf(http, buf, buf_len);
                         http->_p.skip_rbuf_defer = 1;
                 }
@@ -248,14 +248,14 @@ chunked_body_after_header(struct mog_http *http, char *buf, size_t buf_len)
 static void
 identity_body_after_header(struct mog_http *http, char *buf, size_t buf_len)
 {
-        size_t body_len = buf_len - http->_p.offset;
-        char *body_ptr = buf + http->_p.offset;
+        size_t body_len = buf_len - http->_p.buf_off;
+        char *body_ptr = buf + http->_p.buf_off;
 
         if (http->_p.content_len < body_len)
                 body_len = http->_p.content_len;
         if (body_len == 0)
                 return;
-        http->_p.offset += body_len;
+        http->_p.buf_off += body_len;
         if (!mog_http_write_full(http->forward, body_ptr, body_len))
                 (void)write_err(http, NULL);
 }
@@ -388,12 +388,12 @@ void mog_http_put(struct mog_fd *mfd, char *buf, size_t buf_len)
         if (file == NULL)
                 goto err;
 
-        if (buf_len == http->_p.offset) {
+        if (buf_len == http->_p.buf_off) {
                 /* we got the HTTP header in one read() */
                 if (http->_p.chunked) {
                         mog_rbuf_free_and_null(&http->rbuf);
                         mog_chunk_init(http);
-                        http->_p.offset = buf_len;
+                        http->_p.buf_off = buf_len;
                 }
                 return;
         }
@@ -401,8 +401,8 @@ void mog_http_put(struct mog_fd *mfd, char *buf, size_t buf_len)
          * otherwise we got part of the request body with the header,
          * write partially read body
          */
-        assert(buf_len > http->_p.offset && http->_p.offset > 0
-               && "http->_p.offset is wrong");
+        assert(buf_len > http->_p.buf_off && http->_p.buf_off > 0
+               && "http->_p.buf_off is wrong");
 
         if (http->_p.chunked)
                 chunked_body_after_header(http, buf, buf_len);
@@ -535,7 +535,7 @@ again:
                 assert(http->rbuf == NULL && "unexpected http->rbuf");
                 if (http->_p.content_len == 0) { /* final chunk */
                         http->_p.chunk_state = MOG_CHUNK_STATE_TRAILER;
-                        http->_p.offset = 0;
+                        http->_p.buf_off = 0;
                         goto chunk_state_trailer;
                 }
                 assert(http->_p.content_len > 0 && "bad chunk length");
@@ -599,7 +599,7 @@ chunk_state_trailer:
                                         assert(0 && "bad chunk state: size");
                                 /* client is trickling chunk size :< */
                                 mog_rbuf_free_and_null(&http->rbuf);
-                                http->_p.offset = 0;
+                                http->_p.buf_off = 0;
                                 goto again;
                         case MOG_CHUNK_STATE_DATA:
                                 if (in_trailer)
@@ -616,7 +616,7 @@ chunk_state_trailer:
                                 /* pipelined HTTP request after trailers! */
                                 if (http->rbuf)
                                         assert(http->rbuf->rsize > 0
-                                               && http->_p.offset == 0
+                                               && http->_p.buf_off == 0
                                                && "bad rbuf");
                                 return http_put_commit(http);
                         }
diff --git a/mgmt.c b/mgmt.c
index 839a919..503398d 100644
--- a/mgmt.c
+++ b/mgmt.c
@@ -122,10 +122,10 @@ static void
 mgmt_defer_rbuf(struct mog_mgmt *mgmt, struct mog_rbuf *rbuf, size_t buf_len)
 {
         struct mog_rbuf *old = mgmt->rbuf;
-        size_t defer_bytes = buf_len - mgmt->offset;
-        char *src = rbuf->rptr + mgmt->offset;
+        size_t defer_bytes = buf_len - mgmt->buf_off;
+        char *src = rbuf->rptr + mgmt->buf_off;
 
-        assert(mgmt->offset >= 0 && "mgmt->offset negative");
+        assert(mgmt->buf_off >= 0 && "mgmt->buf_off negative");
         assert(defer_bytes <= MOG_RBUF_BASE_SIZE && "defer bytes overflow");
 
         if (defer_bytes == 0) {
@@ -139,7 +139,7 @@ mgmt_defer_rbuf(struct mog_mgmt *mgmt, struct mog_rbuf *rbuf, size_t buf_len)
                 memcpy(mgmt->rbuf->rptr, src, defer_bytes);
                 mgmt->rbuf->rsize = defer_bytes;
         }
-        mgmt->offset = 0;
+        mgmt->buf_off = 0;
 }
 
 /*
@@ -164,7 +164,7 @@ static enum mog_next mgmt_queue_step(struct mog_fd *mfd)
         /* we may have pipelined data in mgmt->rbuf */
         rbuf = mgmt->rbuf ? mgmt->rbuf : mog_rbuf_get(MOG_RBUF_BASE_SIZE);
         buf = rbuf->rptr;
-        off = mgmt->offset;
+        off = mgmt->buf_off;
         assert(off >= 0 && "offset is negative");
         assert(off < MOG_RBUF_BASE_SIZE && "offset is too big");
         if (mgmt->rbuf && off == 0) {
@@ -187,13 +187,13 @@ parse:
                 case MOG_PARSER_CONTINUE:
                         assert(mgmt->wbuf == NULL &&
                                "tried to write (and failed) with partial req");
-                        if (mgmt->offset == MOG_RBUF_BASE_SIZE) {
+                        if (mgmt->buf_off == MOG_RBUF_BASE_SIZE) {
                                 assert(buf_len == MOG_RBUF_BASE_SIZE &&
                                        "bad rbuf");
                                 syslog(LOG_ERR, "mgmt request too large");
                                 return MOG_NEXT_CLOSE;
                         }
-                        off = mgmt->offset;
+                        off = mgmt->buf_off;
                         goto reread;
                 case MOG_PARSER_DONE:
                         if (mgmt->forward == MOG_IOSTAT)
diff --git a/mgmt_parser.rl b/mgmt_parser.rl
index ead5d8c..d8342a1 100644
--- a/mgmt_parser.rl
+++ b/mgmt_parser.rl
@@ -17,9 +17,9 @@ static void set_prio_fsck(struct mog_mgmt *mgmt)
 
 %%{
         machine mgmt_parser;
+        include path_parser "path_parser.rl";
 
         eor = '\r'?'\n';
-        path = "/"[a-zA-Z0-9/\.\-]*;
         reason = ' '("fsck" @ { set_prio_fsck(mgmt); } | [a-zA-Z0-9_]+);
         invalid_line := (
                 [ \t]*
@@ -32,7 +32,7 @@ static void set_prio_fsck(struct mog_mgmt *mgmt)
                 fbreak;
         };
         size = (
-                "size "(path) > { mgmt->mark[0] = fpc - buf; }
+                "size "(mog_path) > { mgmt->mark[0] = fpc - buf; }
                 eor > { mgmt->mark[1] = fpc - buf; }
                 @ { mog_mgmt_fn_size(mgmt, buf); fbreak; }
         );
@@ -43,7 +43,7 @@ static void set_prio_fsck(struct mog_mgmt *mgmt)
                         "SHA-1" @ { mgmt->alg = GC_SHA1; }
                 )
                 " "
-                (path) > { mgmt->mark[0] = fpc - buf; }
+                (mog_path) > { mgmt->mark[0] = fpc - buf; }
                 ( reason? eor) > { mgmt->mark[1] = fpc - buf; }
                 @ { mog_mgmt_fn_digest(mgmt, buf); fbreak; }
         );
@@ -99,7 +99,8 @@ mog_mgmt_parse(struct mog_mgmt *mgmt, char *buf, size_t len)
         char *p, *pe, *eof = NULL;
         int cs = mgmt->cs;
         int really_done = 0;
-        size_t off = mgmt->offset;
+        size_t off = mgmt->buf_off;
+        uint32_t *mog_devid = &mgmt->mog_devid;
 
         assert(mgmt->wbuf == NULL && "unwritten data in buffer");
         assert(off <= len && "mgmt offset past end of buffer");
@@ -116,13 +117,13 @@ mog_mgmt_parse(struct mog_mgmt *mgmt, char *buf, size_t len)
                 cs = mgmt_parser_first_final;
 
         mgmt->cs = cs;
-        mgmt->offset = p - buf;
+        mgmt->buf_off = p - buf;
 
         if (cs == mgmt_parser_error)
                 return MOG_PARSER_ERROR;
 
         assert(p <= pe && "buffer overflow after mgmt parse");
-        assert(mgmt->offset <= len && "offset longer than len");
+        assert(mgmt->buf_off <= len && "offset longer than len");
 
         if (mgmt->cs == mgmt_parser_first_final) return MOG_PARSER_DONE;
         return MOG_PARSER_CONTINUE;
diff --git a/path_parser.h b/path_parser.h
new file mode 100644
index 0000000..8be9a4d
--- /dev/null
+++ b/path_parser.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
+ * License: GPLv3 or later (see COPYING for details)
+ */
+#include "config.h"
+#include <stdint.h>
+
+static void mog_devid_incr(uint32_t *mog_devid, unsigned c)
+{
+        *mog_devid *= 10;
+        *mog_devid += c - '0';
+
+        /* no overflow checking here */
+}
diff --git a/path_parser.rl b/path_parser.rl
new file mode 100644
index 0000000..fc77c98
--- /dev/null
+++ b/path_parser.rl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
+ * License: GPLv3 or later (see COPYING for details)
+ */
+
+/*
+ * caller needs to setup: uint32_t *mog_devid = ...
+ */
+%%{
+        machine path_parser;
+
+        devid = "dev"
+                (digit+) $ {
+                        /* no overflow checking here, no need */
+                        *mog_devid *= 10;
+                        *mog_devid += fc - '0';
+                }
+                '/';
+        # only stuff MogileFS will use
+        mog_path = '/' (devid)? [a-zA-Z0-9/\.\-]{0,36};
+}%%
diff --git a/test/chunk-parser-1.c b/test/chunk-parser-1.c
index d9d2b5d..fd1de49 100644
--- a/test/chunk-parser-1.c
+++ b/test/chunk-parser-1.c
@@ -91,7 +91,7 @@ int main(void)
                 assert(http->_p.chunk_state == MOG_CHUNK_STATE_SIZE);
                 assert(sizeof(tmp) == pread(tmpfd, tmp, sizeof(tmp), 0));
                 assert(0 == memcmp(tmp, "abcde", sizeof(tmp)));
-                assert(http->_p.offset == len);
+                assert(http->_p.buf_off == len);
         }
         if ("multiple chunks with end") {
                 char tmp[8];
@@ -101,7 +101,7 @@ int main(void)
                 assert(http->_p.chunk_state == MOG_CHUNK_STATE_DONE);
                 assert(sizeof(tmp) == pread(tmpfd, tmp, sizeof(tmp), 0));
                 assert(0 == memcmp(tmp, "abcde123", sizeof(tmp)));
-                assert(http->_p.offset == len);
+                assert(http->_p.buf_off == len);
         }
 
         if ("multiple chunks with trailer") {
@@ -113,7 +113,7 @@ int main(void)
                 assert(http->_p.content_len == 0);
                 assert(sizeof(tmp) == pread(tmpfd, tmp, sizeof(tmp), 0));
                 assert(0 == memcmp(tmp, "abcde123", sizeof(tmp)));
-                assert(http->_p.offset == len);
+                assert(http->_p.buf_off == len);
         }
 
         if ("multiple chunks with almost end") {
@@ -125,7 +125,7 @@ int main(void)
                 assert(http->_p.content_len == 0);
                 assert(sizeof(tmp) == pread(tmpfd, tmp, sizeof(tmp), 0));
                 assert(0 == memcmp(tmp, "abcde123", sizeof(tmp)));
-                assert(http->_p.offset == len);
+                assert(http->_p.buf_off == len);
         }
 
         if ("multiple chunks with almost end (more)") {
@@ -137,7 +137,7 @@ int main(void)
                 assert(http->_p.content_len == 0);
                 assert(sizeof(tmp) == pread(tmpfd, tmp, sizeof(tmp), 0));
                 assert(0 == memcmp(tmp, "abcde123", sizeof(tmp)));
-                assert(http->_p.offset == len);
+                assert(http->_p.buf_off == len);
         }
 
         if ("multiple chunks with incomplete") {
@@ -149,7 +149,7 @@ int main(void)
                 assert(http->_p.content_len == 1);
                 assert(sizeof(tmp) == pread(tmpfd, tmp, sizeof(tmp), 0));
                 assert(0 == memcmp(tmp, "abcde12", sizeof(tmp)));
-                assert(http->_p.offset == len);
+                assert(http->_p.buf_off == len);
         }
 
         if ("incomplete data") {
@@ -161,7 +161,7 @@ int main(void)
                 assert(http->_p.content_len == (0x666 - sizeof(tmp)));
                 assert(sizeof(tmp) == pread(tmpfd, tmp, sizeof(tmp), 0));
                 assert(0 == memcmp(tmp, "abc", sizeof(tmp)));
-                assert(http->_p.offset == len);
+                assert(http->_p.buf_off == len);
         }
 
         reset();
diff --git a/test/http-parser-1.c b/test/http-parser-1.c
index 66fd3d5..053237a 100644
--- a/test/http-parser-1.c
+++ b/test/http-parser-1.c
@@ -119,8 +119,8 @@ int main(void)
                 assert(http->_p.persistent == 1 && "should be persistent");
                 assert(state == MOG_PARSER_DONE && "parser not done");
                 assert_path_equal("/foo");
-                assert(strcmp(buf + http->_p.offset, "partial body request") == 0
-                       && "buffer repositioned to body start");
+                assert(strcmp(buf + http->_p.buf_off, "partial body request")
+                       == 0 && "buffer repositioned to body start");
         }
 
         if ("HTTP/1.1 PUT chunked request header") {
@@ -137,7 +137,7 @@ int main(void)
                 assert(http->_p.persistent == 1 && "should be persistent");
                 assert(state == MOG_PARSER_DONE && "parser not done");
                 assert_path_equal("/foo");
-                assert(strcmp(buf + http->_p.offset, "16\r\npartial...") == 0
+                assert(strcmp(buf + http->_p.buf_off, "16\r\npartial...") == 0
                        && "buffer repositioned to body start");
         }
 
@@ -158,7 +158,7 @@ int main(void)
                 assert(http->_p.persistent == 1 && "should be persistent");
                 assert(state == MOG_PARSER_DONE && "parser not done");
                 assert_path_equal("/foo");
-                assert(strcmp(buf + http->_p.offset, "16\r\npartial...") == 0
+                assert(strcmp(buf + http->_p.buf_off, "16\r\npartial...") == 0
                        && "buffer repositioned to body start");
         }
 
@@ -177,7 +177,7 @@ int main(void)
                 assert(http->_p.persistent == 1 && "should be persistent");
                 assert(state == MOG_PARSER_DONE && "parser not done");
                 assert_path_equal("/foo");
-                assert(strcmp(buf + http->_p.offset, "16\r\npartial...") == 0
+                assert(strcmp(buf + http->_p.buf_off, "16\r\npartial...") == 0
                        && "buffer repositioned to body start");
         }
 
@@ -257,6 +257,17 @@ int main(void)
                 assert_path_equal("/foo");
         }
 
+        if ("HTTP/1.1 devid parse") {
+                buf_set("GET /dev666/0/1.fid HTTP/1.0\r\n"
+                        "\r\n");
+                state = mog_http_parse(http, buf, len);
+                assert(http->_p.http_method == MOG_HTTP_METHOD_GET
+                       && "http_method should be GET");
+                assert(http->_p.mog_devid == 666 && "dev666 set");
+                assert(state == MOG_PARSER_DONE && "parser not done");
+                assert_path_equal("/dev666/0/1.fid");
+        }
+
         reset();
         return 0;
 }