diff options
Diffstat (limited to 'src/networking.c')
-rw-r--r-- | src/networking.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/src/networking.c b/src/networking.c index 3b4f3b0fe..761645cb2 100644 --- a/src/networking.c +++ b/src/networking.c @@ -135,23 +135,49 @@ redisClient *createClient(int fd) { * returns REDIS_OK, and make sure to install the write handler in our event * loop so that when the socket is writable new data gets written. * - * If the client should not receive new data, because it is a fake client, - * a master, a slave not yet online, or because the setup of the write handler - * failed, the function returns REDIS_ERR. + * If the client should not receive new data, because it is a fake client + * (used to load AOF in memory), a master or because the setup of the write + * handler failed, the function returns REDIS_ERR. + * + * The function may return REDIS_OK without actually installing the write + * event handler in the following cases: + * + * 1) The event handler should already be installed since the output buffer + * already contained something. + * 2) The client is a slave but not yet online, so we want to just accumulate + * writes in the buffer but not actually sending them yet. * * Typically gets called every time a reply is built, before adding more * data to the clients output buffers. If the function returns REDIS_ERR no * data should be appended to the output buffers. */ int prepareClientToWrite(redisClient *c) { + /* If it's the Lua client we always return ok without installing any + * handler since there is no socket at all. */ if (c->flags & REDIS_LUA_CLIENT) return REDIS_OK; + + /* Masters don't receive replies, unless REDIS_MASTER_FORCE_REPLY flag + * is set. */ if ((c->flags & REDIS_MASTER) && !(c->flags & REDIS_MASTER_FORCE_REPLY)) return REDIS_ERR; - if (c->fd <= 0) return REDIS_ERR; /* Fake client */ + + if (c->fd <= 0) return REDIS_ERR; /* Fake client for AOF loading. */ + + /* Only install the handler if not already installed and, in case of + * slaves, if the client can actually receive writes. */ if (c->bufpos == 0 && listLength(c->reply) == 0 && (c->replstate == REDIS_REPL_NONE || - c->replstate == REDIS_REPL_ONLINE) && !c->repl_put_online_on_ack && - aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, - sendReplyToClient, c) == AE_ERR) return REDIS_ERR; + (c->replstate == REDIS_REPL_ONLINE && !c->repl_put_online_on_ack))) + { + /* Try to install the write handler. */ + if (aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, + sendReplyToClient, c) == AE_ERR) + { + freeClientAsync(c); + return REDIS_ERR; + } + } + + /* Authorize the caller to queue in the output buffer of this client. */ return REDIS_OK; } |