From 3cd12b568776fcee3284ca692ad25e4ddce93c95 Mon Sep 17 00:00:00 2001 From: antirez <antirez@gmail.com> Date: Thu, 21 Apr 2011 15:38:02 +0200 Subject: [PATCH] CLIENT LIST implemented --- src/anet.c | 10 ++++++++++ src/anet.h | 1 + src/networking.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/redis-cli.c | 5 ++++- src/redis.c | 3 ++- src/redis.h | 1 + 6 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/anet.c b/src/anet.c index 4e16f2e4..692cef19 100644 --- a/src/anet.c +++ b/src/anet.c @@ -345,3 +345,13 @@ int anetUnixAccept(char *err, int s) { return fd; } + +int anetPeerToString(int fd, char *ip, int *port) { + struct sockaddr_in sa; + socklen_t salen = sizeof(sa); + + if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) return -1; + if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); + if (port) *port = ntohs(sa.sin_port); + return 0; +} diff --git a/src/anet.h b/src/anet.h index 118b4dda..2b2dea45 100644 --- a/src/anet.h +++ b/src/anet.h @@ -53,5 +53,6 @@ int anetWrite(int fd, char *buf, int count); int anetNonBlock(char *err, int fd); int anetTcpNoDelay(char *err, int fd); int anetTcpKeepAlive(char *err, int fd); +int anetPeerToString(int fd, char *ip, int *port); #endif diff --git a/src/networking.c b/src/networking.c index 995b910c..8949c948 100644 --- a/src/networking.c +++ b/src/networking.c @@ -869,3 +869,49 @@ void getClientsMaxBuffers(unsigned long *longest_output_list, *biggest_input_buffer = bib; } +void clientCommand(redisClient *c) { + if (!strcasecmp(c->argv[1]->ptr,"list") && c->argc == 2) { + listNode *ln; + listIter li; + sds o = sdsempty(); + time_t now = time(NULL); + + listRewind(server.clients,&li); + while ((ln = listNext(&li)) != NULL) { + redisClient *client; + char ip[32], flags[16], *p; + int port; + + client = listNodeValue(ln); + if (anetPeerToString(client->fd,ip,&port) == -1) continue; + p = flags; + if (client->flags & REDIS_SLAVE) { + if (client->flags & REDIS_MONITOR) + *p++ = 'O'; + else + *p++ = 'S'; + } + if (client->flags & REDIS_MASTER) *p++ = 'M'; + if (p == flags) *p++ = 'N'; + if (client->flags & REDIS_MULTI) *p++ = 'x'; + if (client->flags & REDIS_BLOCKED) *p++ = 'b'; + if (client->flags & REDIS_IO_WAIT) *p++ = 'i'; + if (client->flags & REDIS_DIRTY_CAS) *p++ = 'd'; + if (client->flags & REDIS_CLOSE_AFTER_REPLY) *p++ = 'c'; + if (client->flags & REDIS_UNBLOCKED) *p++ = 'u'; + *p++ = '\0'; + o = sdscatprintf(o, + "addr=%s:%d fd=%d idle=%ld flags=%s db=%d sub=%d psub=%d\n", + ip,port,client->fd, + (long)(now - client->lastinteraction), + flags, + client->db->id, + (int) dictSize(client->pubsub_channels), + (int) listLength(client->pubsub_patterns)); + } + addReplyBulkCBuffer(c,o,sdslen(o)); + sdsfree(o); + } else { + addReplyError(c, "Syntax error, try CLIENT (LIST | KILL ip:port)"); + } +} diff --git a/src/redis-cli.c b/src/redis-cli.c index 1b23c0b1..b53a4c82 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -471,7 +471,10 @@ static int cliSendCommand(int argc, char **argv, int repeat) { if (!strcasecmp(command,"info") || (argc == 2 && !strcasecmp(command,"cluster") && (!strcasecmp(argv[1],"nodes") || - !strcasecmp(argv[1],"info")))) + !strcasecmp(argv[1],"info"))) || + (argc == 2 && !strcasecmp(command,"client") && + !strcasecmp(argv[1],"list"))) + { output_raw = 1; } diff --git a/src/redis.c b/src/redis.c index b19ee891..b164fdd1 100644 --- a/src/redis.c +++ b/src/redis.c @@ -192,7 +192,8 @@ struct redisCommand redisCommandTable[] = { {"restore",restoreCommand,4,0,NULL,0,0,0,0,0}, {"migrate",migrateCommand,6,0,NULL,0,0,0,0,0}, {"dump",dumpCommand,2,0,NULL,0,0,0,0,0}, - {"object",objectCommand,-2,0,NULL,0,0,0,0,0} + {"object",objectCommand,-2,0,NULL,0,0,0,0,0}, + {"client",clientCommand,-2,0,NULL,0,0,0,0,0} }; /*============================ Utility functions ============================ */ diff --git a/src/redis.h b/src/redis.h index 19d2ddd1..952fcbf6 100644 --- a/src/redis.h +++ b/src/redis.h @@ -1200,6 +1200,7 @@ void restoreCommand(redisClient *c); void migrateCommand(redisClient *c); void dumpCommand(redisClient *c); void objectCommand(redisClient *c); +void clientCommand(redisClient *c); #if defined(__GNUC__) void *calloc(size_t count, size_t size) __attribute__ ((deprecated)); -- 2.45.2