From c28b42acd9b32c8888d7265adc528ded7a787919 Mon Sep 17 00:00:00 2001
From: antirez <antirez@gmail.com>
Date: Wed, 18 Nov 2009 20:32:03 +0100
Subject: [PATCH] more experiments with long replies, glue output buffer, and
 writev.

---
 benchmark.c    |  4 ++++
 redis.c        | 37 +++++++++++++++++--------------------
 test-redis.tcl |  4 ++++
 3 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/benchmark.c b/benchmark.c
index a933eba9..6b4fb2ff 100644
--- a/benchmark.c
+++ b/benchmark.c
@@ -486,6 +486,7 @@ int main(int argc, char **argv) {
     }
 
     do {
+#if 0
         prepareForBenchmark();
         c = createClient();
         if (!c) exit(1);
@@ -547,6 +548,7 @@ int main(int argc, char **argv) {
         aeMain(config.el);
         endBenchmark("PING");
 
+#endif
         prepareForBenchmark();
         c = createClient();
         if (!c) exit(1);
@@ -556,6 +558,7 @@ int main(int argc, char **argv) {
         aeMain(config.el);
         endBenchmark("LPUSH (again, in order to bench LRANGE)");
 
+#if 0
         prepareForBenchmark();
         c = createClient();
         if (!c) exit(1);
@@ -582,6 +585,7 @@ int main(int argc, char **argv) {
         createMissingClients(c);
         aeMain(config.el);
         endBenchmark("LRANGE (first 450 elements)");
+#endif
 
         prepareForBenchmark();
         c = createClient();
diff --git a/redis.c b/redis.c
index 52143e56..daf2c9bc 100644
--- a/redis.c
+++ b/redis.c
@@ -1351,33 +1351,29 @@ static void freeClient(redisClient *c) {
 
 #define GLUEREPLY_UP_TO (1024)
 static void glueReplyBuffersIfNeeded(redisClient *c) {
-    int totlen = 0;
+    int copylen = 0;
+    char buf[GLUEREPLY_UP_TO];
     listNode *ln;
     robj *o;
 
     listRewind(c->reply);
     while((ln = listYield(c->reply))) {
-        o = ln->value;
-        totlen += sdslen(o->ptr);
-        /* This optimization makes more sense if we don't have to copy
-         * too much data */
-        if (totlen > GLUEREPLY_UP_TO) return;
-    }
-    if (totlen > 0) {
-        char buf[GLUEREPLY_UP_TO];
-        int copylen = 0;
+        int objlen;
 
-        listRewind(c->reply);
-        while((ln = listYield(c->reply))) {
-            o = ln->value;
-            memcpy(buf+copylen,o->ptr,sdslen(o->ptr));
-            copylen += sdslen(o->ptr);
+        o = ln->value;
+        objlen = sdslen(o->ptr);
+        if (copylen + objlen <= GLUEREPLY_UP_TO) {
+            memcpy(buf+copylen,o->ptr,objlen);
+            copylen += objlen;
             listDelNode(c->reply,ln);
+        } else {
+            if (copylen == 0) return;
+            break;
         }
-        /* Now the output buffer is empty, add the new single element */
-        o = createObject(REDIS_STRING,sdsnewlen(buf,totlen));
-        listAddNodeTail(c->reply,o);
     }
+    /* Now the output buffer is empty, add the new single element */
+    o = createObject(REDIS_STRING,sdsnewlen(buf,copylen));
+    listAddNodeHead(c->reply,o);
 }
 
 static void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) {
@@ -1387,8 +1383,6 @@ static void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask)
     REDIS_NOTUSED(el);
     REDIS_NOTUSED(mask);
 
-    if (server.glueoutputbuf && listLength(c->reply) > 1)
-        glueReplyBuffersIfNeeded(c);
 
     /* Use writev() if we have enough buffers to send */
 #if 0
@@ -1401,6 +1395,9 @@ static void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask)
 #endif
 
     while(listLength(c->reply)) {
+        if (server.glueoutputbuf && listLength(c->reply) > 1)
+            glueReplyBuffersIfNeeded(c);
+
         o = listNodeValue(listFirst(c->reply));
         objlen = sdslen(o->ptr);
 
diff --git a/test-redis.tcl b/test-redis.tcl
index 1ca5e21a..400b0db5 100644
--- a/test-redis.tcl
+++ b/test-redis.tcl
@@ -912,6 +912,10 @@ proc main {server port} {
         lappend aux [$r dbsize]
     } {0 0}
 
+    test {Perform a final SAVE to leave a clean DB on disk} {
+        $r save
+    } {OK}
+
     puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed"
     if {$::failed > 0} {
         puts "\n*** WARNING!!! $::failed FAILED TESTS ***\n"