about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-06-27 00:18:08 +0000
committerEric Wong <normalperson@yhbt.net>2013-07-10 00:55:54 +0000
commit331e7a1300ae59a052763ffecc77b45a56e2deb3 (patch)
tree6687bb899c5932e6f0fa0907b9ecc3fd2fcf5e4e
parentd9486d154f69be2bbe44dbc8ea74efce1d0195ad (diff)
downloadcmogstored-331e7a1300ae59a052763ffecc77b45a56e2deb3.tar.gz
We'll be allowing the migration of buffers between threads
and from waiting clients back to thread-local storage.
-rw-r--r--mgmt.c21
-rw-r--r--test/mgmt.rb10
2 files changed, 22 insertions, 9 deletions
diff --git a/mgmt.c b/mgmt.c
index 16ec4c0..5d52a3e 100644
--- a/mgmt.c
+++ b/mgmt.c
@@ -133,7 +133,7 @@ mgmt_defer_rbuf(struct mog_mgmt *mgmt, struct mog_rbuf *rbuf, size_t buf_len)
         char *src = rbuf->rptr + mgmt->buf_off;
 
         assert(mgmt->buf_off >= 0 && "mgmt->buf_off negative");
-        assert(defer_bytes <= MOG_RBUF_BASE_SIZE && "defer bytes overflow");
+        assert(defer_bytes <= MOG_RBUF_MAX_SIZE && "defer bytes overflow");
 
         if (defer_bytes == 0) {
                 mog_rbuf_free_and_null(&mgmt->rbuf);
@@ -142,7 +142,7 @@ mgmt_defer_rbuf(struct mog_mgmt *mgmt, struct mog_rbuf *rbuf, size_t buf_len)
                 memmove(old->rptr, src, defer_bytes);
                 old->rsize = defer_bytes;
         } else {
-                mgmt->rbuf = mog_rbuf_new(MOG_RBUF_BASE_SIZE);
+                mgmt->rbuf = mog_rbuf_new(defer_bytes);
                 memcpy(mgmt->rbuf->rptr, src, defer_bytes);
                 mgmt->rbuf->rsize = defer_bytes;
         }
@@ -191,14 +191,14 @@ static enum mog_next __mgmt_queue_step(struct mog_fd *mfd)
         buf = rbuf->rptr;
         off = mgmt->buf_off;
         assert(off >= 0 && "offset is negative");
-        assert(off < MOG_RBUF_BASE_SIZE && "offset is too big");
+        assert(off < rbuf->rcapa && "offset is too big");
         if (mgmt->rbuf && off == 0) {
                 /* request got "pipelined", resuming now */
                 buf_len = mgmt->rbuf->rsize;
                 goto parse;
         }
 reread:
-        r = read(mfd->fd, buf + off, MOG_RBUF_BASE_SIZE - off);
+        r = read(mfd->fd, buf + off, rbuf->rcapa - off);
         if (r > 0) {
                 buf_len = r + off;
 parse:
@@ -212,11 +212,12 @@ parse:
                 case MOG_PARSER_CONTINUE:
                         assert(mgmt->wbuf == NULL &&
                                "tried to write (and failed) with partial req");
-                        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;
+                        if (mgmt->buf_off >= rbuf->rcapa) {
+                                rbuf->rsize = buf_len;
+                                mgmt->rbuf = rbuf = mog_rbuf_grow(rbuf);
+                                if (!rbuf)
+                                        goto too_large;
+                                buf = rbuf->rptr;
                         }
                         off = mgmt->buf_off;
                         goto reread;
@@ -259,6 +260,8 @@ parse:
         }
 
         assert(0 && "compiler bug?");
+too_large:
+        syslog(LOG_ERR, "mgmt request too large");
         return MOG_NEXT_CLOSE;
 }
 
diff --git a/test/mgmt.rb b/test/mgmt.rb
index 7101245..7a7c432 100644
--- a/test/mgmt.rb
+++ b/test/mgmt.rb
@@ -371,4 +371,14 @@ class TestMgmt < Test::Unit::TestCase
       fp.write('.')
     end
   end
+
+  def test_gigantic_path
+    @client.write("MD5 /foo ")
+    (1..50000).each do |i|
+      @client.write((i % 10).to_s)
+    end
+    @client.write("\r\n")
+    output = @client.gets
+    assert_equal "/foo MD5=-1\r\n", output
+  end
 end