This handler fires when the non blocking connect was able to * establish a connection with the master. */
| 3426 | /* This handler fires when the non blocking connect was able to |
| 3427 | * establish a connection with the master. */ |
| 3428 | void syncWithMaster(connection *conn) { |
| 3429 | serverAssert(GlobalLocksAcquired()); |
| 3430 | char tmpfile[256] = {0}, *err = NULL; |
| 3431 | int dfd = -1, maxtries = 5; |
| 3432 | int psync_result; |
| 3433 | |
| 3434 | redisMaster *mi = (redisMaster*)connGetPrivateData(conn); |
| 3435 | if (mi == nullptr) { |
| 3436 | // We're about to be closed, bail |
| 3437 | return; |
| 3438 | } |
| 3439 | |
| 3440 | /* If this event fired after the user turned the instance into a master |
| 3441 | * with SLAVEOF NO ONE we must just return ASAP. */ |
| 3442 | if (mi->repl_state == REPL_STATE_NONE) { |
| 3443 | connClose(conn); |
| 3444 | return; |
| 3445 | } |
| 3446 | |
| 3447 | /* Check for errors in the socket: after a non blocking connect() we |
| 3448 | * may find that the socket is in error state. */ |
| 3449 | if (connGetState(conn) != CONN_STATE_CONNECTED) { |
| 3450 | serverLog(LL_WARNING,"Error condition on socket for SYNC: %s", |
| 3451 | connGetLastError(conn)); |
| 3452 | goto error; |
| 3453 | } |
| 3454 | |
| 3455 | retry_connect: |
| 3456 | /* Send a PING to check the master is able to reply without errors. */ |
| 3457 | if (mi->repl_state == REPL_STATE_CONNECTING || mi->repl_state == REPL_STATE_RETRY_NOREPLPING) { |
| 3458 | serverLog(LL_NOTICE,"Non blocking connect for SYNC fired the event."); |
| 3459 | /* Delete the writable event so that the readable event remains |
| 3460 | * registered and we can wait for the PONG reply. */ |
| 3461 | connSetReadHandler(conn, syncWithMaster); |
| 3462 | connSetWriteHandler(conn, NULL); |
| 3463 | /* Send the PING, don't check for errors at all, we have the timeout |
| 3464 | * that will take care about this. */ |
| 3465 | err = sendCommand(conn,mi->repl_state == REPL_STATE_RETRY_NOREPLPING ? "PING" : "REPLPING",NULL); |
| 3466 | if (err) goto write_error; |
| 3467 | mi->repl_state = REPL_STATE_RECEIVE_PING_REPLY; |
| 3468 | return; |
| 3469 | } |
| 3470 | |
| 3471 | /* Receive the PONG command. */ |
| 3472 | if (mi->repl_state == REPL_STATE_RECEIVE_PING_REPLY) { |
| 3473 | err = receiveSynchronousResponse(mi, conn); |
| 3474 | |
| 3475 | /* We accept only two replies as valid, a positive +PONG reply |
| 3476 | * (we just check for "+") or an authentication error. |
| 3477 | * Note that older versions of Redis replied with "operation not |
| 3478 | * permitted" instead of using a proper error code, so we test |
| 3479 | * both. */ |
| 3480 | if (strncmp(err,"-ERR unknown command",20) == 0) { |
| 3481 | serverLog(LL_NOTICE,"Master does not support REPLPING, sending PING instead..."); |
| 3482 | mi->repl_state = REPL_STATE_RETRY_NOREPLPING; |
| 3483 | sdsfree(err); |
| 3484 | err = NULL; |
| 3485 | goto retry_connect; |
nothing calls this directly
no test coverage detected