summaryrefslogtreecommitdiff
path: root/src/networking.c
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2013-01-30 18:33:16 +0100
committerantirez <antirez@gmail.com>2013-02-12 12:52:21 +0100
commit078882025ea50e0ed888713fba8ce28299de626a (patch)
treec88e4bbde92c4ff9c6f9a51d002cbfb9456893d0 /src/networking.c
parente34a35a51194650ce7ef7df1047012c7eaad2957 (diff)
downloadredis-078882025ea50e0ed888713fba8ce28299de626a.tar.gz
PSYNC: work in progress, preview #2, rebased to unstable.
Diffstat (limited to 'src/networking.c')
-rw-r--r--src/networking.c68
1 files changed, 50 insertions, 18 deletions
diff --git a/src/networking.c b/src/networking.c
index 66a2702c5..b90936011 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -87,6 +87,7 @@ redisClient *createClient(int fd) {
c->ctime = c->lastinteraction = server.unixtime;
c->authenticated = 0;
c->replstate = REDIS_REPL_NONE;
+ c->reploff = 0;
c->slave_listening_port = 0;
c->reply = listCreate();
c->reply_bytes = 0;
@@ -595,12 +596,42 @@ void disconnectSlaves(void) {
}
}
+/* This function is called when the slave lose the connection with the
+ * master into an unexpected way. */
+void replicationHandleMasterDisconnection(void) {
+ server.master = NULL;
+ server.repl_state = REDIS_REPL_CONNECT;
+ server.repl_down_since = server.unixtime;
+ /* We lost connection with our master, force our slaves to resync
+ * with us as well to load the new data set.
+ *
+ * If server.masterhost is NULL the user called SLAVEOF NO ONE so
+ * slave resync is not needed. */
+ if (server.masterhost != NULL) disconnectSlaves();
+}
+
void freeClient(redisClient *c) {
listNode *ln;
/* If this is marked as current client unset it */
if (server.current_client == c) server.current_client = NULL;
+ /* If it is our master that's beging disconnected we should make sure
+ * to cache the state to try a partial resynchronization later.
+ *
+ * Note that before doing this we make sure that the client is not in
+ * some unexpected state, by checking its flags. */
+ if (server.master &&
+ (c->flags & REDIS_MASTER) &&
+ !(c->flags & (REDIS_CLOSE_AFTER_REPLY|
+ REDIS_CLOSE_ASAP|
+ REDIS_BLOCKED|
+ REDIS_UNBLOCKED)))
+ {
+ replicationCacheMaster(c);
+ return;
+ }
+
/* Note that if the client we are freeing is blocked into a blocking
* call, we have to set querybuf to NULL *before* to call
* unblockClientWaitingData() to avoid processInputBuffer() will get
@@ -620,16 +651,21 @@ void freeClient(redisClient *c) {
pubsubUnsubscribeAllPatterns(c,0);
dictRelease(c->pubsub_channels);
listRelease(c->pubsub_patterns);
- /* Obvious cleanup */
- aeDeleteFileEvent(server.el,c->fd,AE_READABLE);
- aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);
+ /* Close socket, unregister events, and remove list of replies and
+ * accumulated arguments. */
+ if (c->fd != -1) {
+ aeDeleteFileEvent(server.el,c->fd,AE_READABLE);
+ aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);
+ close(c->fd);
+ }
listRelease(c->reply);
freeClientArgv(c);
- close(c->fd);
/* Remove from the list of clients */
- ln = listSearchKey(server.clients,c);
- redisAssert(ln != NULL);
- listDelNode(server.clients,ln);
+ if (c->fd != -1) {
+ ln = listSearchKey(server.clients,c);
+ redisAssert(ln != NULL);
+ listDelNode(server.clients,ln);
+ }
/* When client was just unblocked because of a blocking operation,
* remove it from the list with unblocked clients. */
if (c->flags & REDIS_UNBLOCKED) {
@@ -647,20 +683,15 @@ void freeClient(redisClient *c) {
ln = listSearchKey(l,c);
redisAssert(ln != NULL);
listDelNode(l,ln);
+ /* We need to remember the time when we started to have zero
+ * attached slaves, as after some time we'll free the replication
+ * backlog. */
+ if (c->flags & REDIS_SLAVE && listLength(server.slaves) == 0)
+ server.repl_no_slaves_since = server.unixtime;
}
/* Case 2: we lost the connection with the master. */
- if (c->flags & REDIS_MASTER) {
- server.master = NULL;
- server.repl_state = REDIS_REPL_CONNECT;
- server.repl_down_since = server.unixtime;
- /* We lost connection with our master, force our slaves to resync
- * with us as well to load the new data set.
- *
- * If server.masterhost is NULL the user called SLAVEOF NO ONE so
- * slave resync is not needed. */
- if (server.masterhost != NULL) disconnectSlaves();
- }
+ if (c->flags & REDIS_MASTER) replicationHandleMasterDisconnection();
/* If this client was scheduled for async freeing we need to remove it
* from the queue. */
@@ -1059,6 +1090,7 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
if (nread) {
sdsIncrLen(c->querybuf,nread);
c->lastinteraction = server.unixtime;
+ if (c->flags & REDIS_MASTER) c->reploff += nread;
} else {
server.current_client = NULL;
return;