]> git.saurik.com Git - redis.git/commitdiff
Return OK on QUIT
authorPieter Noordhuis <pcnoordhuis@gmail.com>
Wed, 13 Oct 2010 09:25:40 +0000 (11:25 +0200)
committerPieter Noordhuis <pcnoordhuis@gmail.com>
Wed, 13 Oct 2010 09:25:40 +0000 (11:25 +0200)
src/networking.c
src/redis.c
src/redis.h
tests/support/redis.tcl
tests/support/server.tcl
tests/test_helper.tcl

index 632fd04769dca5a3c464b26b982d8a9a064a4faa..a1d8f564421ec9bd8f574959bdad679cc5c40247 100644 (file)
@@ -546,6 +546,9 @@ void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) {
     if (listLength(c->reply) == 0) {
         c->sentlen = 0;
         aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);
+
+        /* Close connection after entire reply has been sent. */
+        if (c->flags & REDIS_QUIT) freeClient(c);
     }
 }
 
@@ -675,6 +678,10 @@ again:
      * will try to reiterate. The following line will make it return asap. */
     if (c->flags & REDIS_BLOCKED || c->flags & REDIS_IO_WAIT) return;
 
+    /* Never continue to process the input buffer after QUIT. After the output
+     * buffer is flushed (with the OK), the connection will be dropped. */
+    if (c->flags & REDIS_QUIT) return;
+
     if (seeknewline && c->bulklen == -1) c->newline = strchr(c->querybuf,'\n');
     seeknewline = 1;
     if (c->bulklen == -1) {
index 27a855d97a0d0f6d4ff5c7f5328af250f6bc7c91..a1ac2a15098db32476805d0b4a5ebd085edfde33 100644 (file)
@@ -962,10 +962,14 @@ int processCommand(redisClient *c) {
     }
     /* -- end of multi bulk commands processing -- */
 
-    /* The QUIT command is handled as a special case. Normal command
-     * procs are unable to close the client connection safely */
+    /* The QUIT command is handled separately. Normal command procs will
+     * go through checking for replication and QUIT will cause trouble
+     * when FORCE_REPLICATION is enabled and would be implemented in
+     * a regular command proc. */
+    redisAssert(!(c->flags & REDIS_QUIT));
     if (!strcasecmp(c->argv[0]->ptr,"quit")) {
-        freeClient(c);
+        c->flags |= REDIS_QUIT;
+        addReply(c,shared.ok);
         return 0;
     }
 
index 3e9fc2369cdfacf9f3f3536be582b22c34791fba..e525a99b09623794c50864801bcf5a7e2eb0c891 100644 (file)
 #define REDIS_BLOCKED 16    /* The client is waiting in a blocking operation */
 #define REDIS_IO_WAIT 32    /* The client is waiting for Virtual Memory I/O */
 #define REDIS_DIRTY_CAS 64  /* Watched keys modified. EXEC will fail. */
+#define REDIS_QUIT 128      /* Client will be disconnected after reply is sent */
 
 /* Slave replication state - slave side */
 #define REDIS_REPL_NONE 0   /* No active replication */
index 7c7c65c6564f2cb1847d695b53d35a0f78c685f5..98cf86f093d7fa1be246c57b1cc9738bac8474c9 100644 (file)
@@ -123,6 +123,14 @@ proc ::redis::__method__read {id fd} {
     ::redis::redis_read_reply $fd
 }
 
+proc ::redis::__method__write {id fd buf} {
+    ::redis::redis_write $fd $buf
+}
+
+proc ::redis::__method__flush {id fd} {
+    flush $fd
+}
+
 proc ::redis::__method__close {id fd} {
     catch {close $fd}
     catch {unset ::redis::fd($id)}
index e5ca6c6cd69ffb664990c314bbcde90211c0d794..1507088e002e68d4d70e1627177a1a3b529b8f89 100644 (file)
@@ -215,7 +215,8 @@ proc start_server {options {code undefined}} {
     if {[dict exists $config port]} { set port [dict get $config port] }
 
     # setup config dict
-    dict set srv "config" $config_file
+    dict set srv "config_file" $config_file
+    dict set srv "config" $config
     dict set srv "pid" $pid
     dict set srv "host" $host
     dict set srv "port" $port
@@ -238,17 +239,12 @@ proc start_server {options {code undefined}} {
             after 10
         }
 
-        set client [redis $host $port]
-        dict set srv "client" $client
-
-        # select the right db when we don't have to authenticate
-        if {![dict exists $config requirepass]} {
-            $client select 9
-        }
-
         # append the server to the stack
         lappend ::servers $srv
-        
+
+        # connect client (after server dict is put on the stack)
+        reconnect
+
         # execute provided block
         set curnum $::testnum
         if {![catch { uplevel 1 $code } err]} {
index f427fabce053c20b8bb6d69ed56642b4e37cdf27..a6c3e83355c01fa60c1db0e01910d47ecca0e872 100644 (file)
@@ -50,6 +50,28 @@ proc r {args} {
     [srv $level "client"] {*}$args
 }
 
+proc reconnect {args} {
+    set level [lindex $args 0]
+    if {[string length $level] == 0 || ![string is integer $level]} {
+        set level 0
+    }
+
+    set srv [lindex $::servers end+$level]
+    set host [dict get $srv "host"]
+    set port [dict get $srv "port"]
+    set config [dict get $srv "config"]
+    set client [redis $host $port]
+    dict set srv "client" $client
+
+    # select the right db when we don't have to authenticate
+    if {![dict exists $config "requirepass"]} {
+        $client select 9
+    }
+
+    # re-set $srv in the servers list
+    set ::servers [lreplace $::servers end+$level 1 $srv]
+}
+
 proc redis_deferring_client {args} {
     set level 0
     if {[llength $args] > 0 && [string is integer [lindex $args 0]]} {