summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2018-06-27 13:52:46 +0200
committerantirez <antirez@gmail.com>2018-06-27 13:52:46 +0200
commitaed54849e57271718783609570cb7a34c15797b7 (patch)
treeb16cdcedb8a631b530e9af3dd6824eff1c3e93f8
parent65afcf24cb458154874102f2accfb48bce81fc41 (diff)
downloadredis-client-unblock.tar.gz
CLIENT UNBLOCK implemented.client-unblock
-rw-r--r--src/networking.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/src/networking.c b/src/networking.c
index cbbad5419..fe8a78ec5 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -868,6 +868,15 @@ void freeClientsInAsyncFreeQueue(void) {
}
}
+/* Return a client by ID, or NULL if the client ID is not in the set
+ * of registered clients. Note that "fake clients", created with -1 as FD,
+ * are not registered clients. */
+client *lookupClientByID(uint64_t id) {
+ id = htonu64(id);
+ client *c = raxFind(server.clients_index,(unsigned char*)&id,sizeof(id));
+ return (c == raxNotFound) ? NULL : c;
+}
+
/* Write data in output buffers to client. Return C_OK if the client
* is still valid after the call, C_ERR if it was freed. */
int writeToClient(int fd, client *c, int handler_installed) {
@@ -1679,6 +1688,19 @@ NULL
/* If this client has to be closed, flag it as CLOSE_AFTER_REPLY
* only after we queued the reply to its output buffers. */
if (close_this_client) c->flags |= CLIENT_CLOSE_AFTER_REPLY;
+ } else if (!strcasecmp(c->argv[1]->ptr,"unblock") && c->argc == 3) {
+ /* CLIENT UNBLOCK <id> */
+ long long id;
+ if (getLongLongFromObjectOrReply(c,c->argv[2],&id,NULL)
+ != C_OK) return;
+ struct client *target = lookupClientByID(id);
+ if (target && target->flags & CLIENT_BLOCKED) {
+ replyToBlockedClientTimedOut(target);
+ unblockClient(target);
+ addReply(c,shared.cone);
+ } else {
+ addReply(c,shared.czero);
+ }
} else if (!strcasecmp(c->argv[1]->ptr,"setname") && c->argc == 3) {
int j, len = sdslen(c->argv[2]->ptr);
char *p = c->argv[2]->ptr;