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
