summaryrefslogtreecommitdiff
path: root/src/networking.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/networking.c')
-rw-r--r--src/networking.c40
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;
}