summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSalvatore Sanfilippo <antirez@gmail.com>2018-11-22 11:12:36 +0100
committerGitHub <noreply@github.com>2018-11-22 11:12:36 +0100
commit97192e2d884ac7a6d683479c6dd804773c7582f5 (patch)
tree118173a7e0e7058cfa35d359c636ed2e5bd48ec1
parent54b17f985d55b9e0bd8d0c98eff467f0eff22d07 (diff)
parent1908aba73d88346ecbdd44fe5322c61813520c54 (diff)
downloadredis-97192e2d884ac7a6d683479c6dd804773c7582f5.tar.gz
Merge pull request #5569 from maximebedard/backport-4497
Backport #4497 to redis 4
-rw-r--r--src/networking.c20
-rw-r--r--src/replication.c2
-rw-r--r--src/server.h2
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, ...)