diff options
author | Salvatore Sanfilippo <antirez@gmail.com> | 2018-11-22 11:12:36 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-22 11:12:36 +0100 |
commit | 97192e2d884ac7a6d683479c6dd804773c7582f5 (patch) | |
tree | 118173a7e0e7058cfa35d359c636ed2e5bd48ec1 | |
parent | 54b17f985d55b9e0bd8d0c98eff467f0eff22d07 (diff) | |
parent | 1908aba73d88346ecbdd44fe5322c61813520c54 (diff) | |
download | redis-97192e2d884ac7a6d683479c6dd804773c7582f5.tar.gz |
Merge pull request #5569 from maximebedard/backport-4497
Backport #4497 to redis 4
-rw-r--r-- | src/networking.c | 20 | ||||
-rw-r--r-- | src/replication.c | 2 | ||||
-rw-r--r-- | src/server.h | 2 |
3 files changed, 19 insertions, 5 deletions
diff --git a/src/networking.c b/src/networking.c index 2cab29d40..82c763c95 100644 --- a/src/networking.c +++ b/src/networking.c @@ -67,6 +67,16 @@ int listMatchObjects(void *a, void *b) { return equalStringObjects(a,b); } +/* This function links the client to the global linked list of clients. + * unlinkClient() does the opposite, among other things. */ +void linkClient(client *c) { + listAddNodeTail(server.clients,c); + /* Note that we remember the linked list node where the client is stored, + * this way removing the client in unlinkClient() will not require + * a linear scan, but just a constant time operation. */ + c->client_list_node = listLast(server.clients); +} + client *createClient(int fd) { client *c = zmalloc(sizeof(client)); @@ -133,9 +143,10 @@ client *createClient(int fd) { c->pubsub_channels = dictCreate(&objectKeyPointerValueDictType,NULL); c->pubsub_patterns = listCreate(); c->peerid = NULL; + c->client_list_node = NULL; listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid); listSetMatchMethod(c->pubsub_patterns,listMatchObjects); - if (fd != -1) listAddNodeTail(server.clients,c); + if (fd != -1) linkClient(c); initClientMultiState(c); return c; } @@ -752,9 +763,10 @@ void unlinkClient(client *c) { * fd is already set to -1. */ if (c->fd != -1) { /* Remove from the list of active clients. */ - ln = listSearchKey(server.clients,c); - serverAssert(ln != NULL); - listDelNode(server.clients,ln); + if (c->client_list_node) { + listDelNode(server.clients,c->client_list_node); + c->client_list_node = NULL; + } /* Unregister async I/O handlers and close the socket. */ aeDeleteFileEvent(server.el,c->fd,AE_READABLE); diff --git a/src/replication.c b/src/replication.c index fa0047041..2c0c47a27 100644 --- a/src/replication.c +++ b/src/replication.c @@ -2226,7 +2226,7 @@ void replicationResurrectCachedMaster(int newfd) { server.repl_down_since = 0; /* Re-add to the list of clients. */ - listAddNodeTail(server.clients,server.master); + linkClient(server.master); if (aeCreateFileEvent(server.el, newfd, AE_READABLE, readQueryFromClient, server.master)) { serverLog(LL_WARNING,"Error resurrecting the cached master, impossible to add the readable handler: %s", strerror(errno)); diff --git a/src/server.h b/src/server.h index 5abb8bdca..7b0d22eaf 100644 --- a/src/server.h +++ b/src/server.h @@ -723,6 +723,7 @@ typedef struct client { dict *pubsub_channels; /* channels a client is interested in (SUBSCRIBE) */ list *pubsub_patterns; /* patterns a client is interested in (SUBSCRIBE) */ sds peerid; /* Cached peer ID. */ + listNode *client_list_node; /* list node in client list */ /* Response buffer */ int bufpos; @@ -1393,6 +1394,7 @@ int handleClientsWithPendingWrites(void); int clientHasPendingReplies(client *c); void unlinkClient(client *c); int writeToClient(int fd, client *c, int handler_installed); +void linkClient(client *c); #ifdef __GNUC__ void addReplyErrorFormat(client *c, const char *fmt, ...) |