From: Yunkai Zhang <[email protected]>

1) In previous code, sheep calls client_incref() in alloc_request(), but
free_request() does not call client_desref() in it, as a result it's difficult
to keep ci->refcnt with correct value, so I simplify client_decref() and move
it into free_request().

2) A bug in put_request(): before calling client_decref(), we should do some
clear actions like client_handler().

3) ci->refcnt should only be increased by alloc_request(), let's initialize
   it with 0 in create_client().

Now I add a helper named clear_client() to do clear works and try to destroy
connection when ci->refcnt is 0.

Signed-off-by: Yunkai Zhang <[email protected]>
---
 sheep/sdnet.c |   35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/sheep/sdnet.c b/sheep/sdnet.c
index c13cdb0..c9abc25 100644
--- a/sheep/sdnet.c
+++ b/sheep/sdnet.c
@@ -370,6 +370,7 @@ static void requeue_request(struct request *req)
 
 static void client_incref(struct client_info *ci);
 static void client_decref(struct client_info *ci);
+static void clear_client(struct client_info *ci);
 
 static struct request *alloc_local_request(void *data, int data_length)
 {
@@ -453,6 +454,7 @@ static void free_request(struct request *req)
        sys->nr_outstanding_reqs--;
        sys->outstanding_data_size -= req->data_length;
 
+       client_decref(req->ci);
        put_vnode_info(req->vnodes);
        free(req->data);
        free(req);
@@ -473,11 +475,10 @@ void put_request(struct request *req)
                if (conn_tx_on(&ci->conn)) {
                        dprintf("connection seems to be dead\n");
                        free_request(req);
+                       clear_client(ci);
                } else {
                        list_add(&req->request_list, &ci->done_reqs);
                }
-
-               client_decref(ci);
        }
 }
 
@@ -653,6 +654,23 @@ static void destroy_client(struct client_info *ci)
        free(ci);
 }
 
+static void clear_client(struct client_info *ci)
+{
+       if (!list_empty(&ci->conn.blocking_siblings))
+               list_del_init(&ci->conn.blocking_siblings);
+
+       unregister_event(ci->conn.fd);
+
+       dprintf("refcnt:%d, fd:%d, %s:%d\n",
+               ci->refcnt, ci->conn.fd,
+               ci->conn.ipstr, ci->conn.port);
+
+       if (ci->refcnt)
+               return;
+
+       destroy_client(ci);
+}
+
 static void client_incref(struct client_info *ci)
 {
        if (ci)
@@ -661,8 +679,8 @@ static void client_incref(struct client_info *ci)
 
 static void client_decref(struct client_info *ci)
 {
-       if (ci && --ci->refcnt == 0)
-               destroy_client(ci);
+       if (ci)
+               ci->refcnt--;
 }
 
 static struct client_info *create_client(int fd, struct cluster_info *cluster)
@@ -693,7 +711,7 @@ static struct client_info *create_client(int fd, struct 
cluster_info *cluster)
 
        ci->conn.fd = fd;
        ci->conn.events = EPOLLIN;
-       ci->refcnt = 1;
+       ci->refcnt = 0;
 
        INIT_LIST_HEAD(&ci->done_reqs);
        INIT_LIST_HEAD(&ci->conn.blocking_siblings);
@@ -720,12 +738,7 @@ static void client_handler(int fd, int events, void *data)
 err:
                dprintf("closed connection %d, %s:%d\n", fd,
                        ci->conn.ipstr, ci->conn.port);
-
-               if (!list_empty(&ci->conn.blocking_siblings))
-                       list_del_init(&ci->conn.blocking_siblings);
-
-               unregister_event(fd);
-               client_decref(ci);
+               clear_client(ci);
        }
 }
 
-- 
1.7.10.4

-- 
sheepdog mailing list
[email protected]
http://lists.wpkg.org/mailman/listinfo/sheepdog

Reply via email to