diff --git a/src/replication.cpp b/src/replication.cpp index f29cdb184..dd82aa637 100644 --- a/src/replication.cpp +++ b/src/replication.cpp @@ -2759,18 +2759,19 @@ void syncWithMaster(connection *conn) { goto error; } +retry_connect: /* Send a PING to check the master is able to reply without errors. */ - if (mi->repl_state == REPL_STATE_CONNECTING) { + if (mi->repl_state == REPL_STATE_CONNECTING || mi->repl_state == REPL_STATE_RETRY_NOREPLPING) { serverLog(LL_NOTICE,"Non blocking connect for SYNC fired the event."); /* Delete the writable event so that the readable event remains * registered and we can wait for the PONG reply. */ connSetReadHandler(conn, syncWithMaster); connSetWriteHandler(conn, NULL); - mi->repl_state = REPL_STATE_RECEIVE_PING_REPLY; /* Send the PING, don't check for errors at all, we have the timeout * that will take care about this. */ - err = sendCommand(conn,"PING",NULL); + err = sendCommand(conn,mi->repl_state == REPL_STATE_RETRY_NOREPLPING ? "PING" : "REPLPING",NULL); if (err) goto write_error; + mi->repl_state = REPL_STATE_RECEIVE_PING_REPLY; return; } @@ -2783,7 +2784,13 @@ void syncWithMaster(connection *conn) { * Note that older versions of Redis replied with "operation not * permitted" instead of using a proper error code, so we test * both. */ - if (err[0] != '+' && + if (strncmp(err,"-ERR unknown command",20) == 0) { + serverLog(LL_NOTICE,"Master does not support REPLPING, sending PING instead..."); + mi->repl_state = REPL_STATE_RETRY_NOREPLPING; + sdsfree(err); + err = NULL; + goto retry_connect; + } else if (err[0] != '+' && strncmp(err,"-NOAUTH",7) != 0 && strncmp(err,"-NOPERM",7) != 0 && strncmp(err,"-ERR operation not permitted",28) != 0) diff --git a/src/server.cpp b/src/server.cpp index 234f22173..e95268373 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -753,6 +753,10 @@ struct redisCommand redisCommandTable[] = { "ok-stale ok-loading fast @connection @replication", 0,NULL,0,0,0,0,0,0}, + {"replping",pingCommand,-1, + "ok-stale fast @connection @replication", + 0,NULL,0,0,0,0,0,0}, + {"echo",echoCommand,2, "fast @connection", 0,NULL,0,0,0,0,0,0}, @@ -2768,6 +2772,7 @@ void createSharedObjects(void) { shared.lastid = makeObjectShared("LASTID",6); shared.default_username = makeObjectShared("default",7); shared.ping = makeObjectShared("ping",4); + shared.replping = makeObjectShared("replping", 8); shared.setid = makeObjectShared("SETID",5); shared.keepttl = makeObjectShared("KEEPTTL",7); shared.load = makeObjectShared("LOAD",4); diff --git a/src/server.h b/src/server.h index e5275e816..a5252a478 100644 --- a/src/server.h +++ b/src/server.h @@ -505,6 +505,7 @@ typedef enum { REPL_STATE_NONE = 0, /* No active replication */ REPL_STATE_CONNECT, /* Must connect to master */ REPL_STATE_CONNECTING, /* Connecting to master */ + REPL_STATE_RETRY_NOREPLPING, /* Master does not support REPLPING, retry with PING */ /* --- Handshake states, must be ordered --- */ REPL_STATE_RECEIVE_PING_REPLY, /* Wait for PING reply */ REPL_STATE_SEND_HANDSHAKE, /* Send handshake sequance to master */ @@ -1283,7 +1284,7 @@ struct sharedObjectsStruct { *emptyscan, *multi, *exec, *left, *right, *hset, *srem, *xgroup, *xclaim, *script, *replconf, *eval, *persist, *set, *pexpireat, *pexpire, *time, *pxat, *px, *retrycount, *force, *justid, - *lastid, *ping, *setid, *keepttl, *load, *createconsumer, + *lastid, *ping, *replping, *setid, *keepttl, *load, *createconsumer, *getack, *special_asterick, *special_equals, *default_username, *hdel, *zrem, *mvccrestore, *pexpirememberat, *select[PROTO_SHARED_SELECT_CMDS],