This function is called if we are a slave node and our master serving * a non-zero amount of hash slots is in FAIL state. * * The goal of this function is: * 1) To check if we are able to perform a failover, is our data updated? * 2) Try to get elected by masters. * 3) Perform the failover informing all the other nodes. */
| 3190 | * 3) Perform the failover informing all the other nodes. |
| 3191 | */ |
| 3192 | void clusterHandleSlaveFailover(void) { |
| 3193 | mstime_t data_age; |
| 3194 | mstime_t auth_age = mstime() - g_pserver->cluster->failover_auth_time; |
| 3195 | int needed_quorum = (g_pserver->cluster->size / 2) + 1; |
| 3196 | int manual_failover = g_pserver->cluster->mf_end != 0 && |
| 3197 | g_pserver->cluster->mf_can_start; |
| 3198 | mstime_t auth_timeout, auth_retry_time; |
| 3199 | |
| 3200 | g_pserver->cluster->todo_before_sleep &= ~CLUSTER_TODO_HANDLE_FAILOVER; |
| 3201 | |
| 3202 | /* Compute the failover timeout (the max time we have to send votes |
| 3203 | * and wait for replies), and the failover retry time (the time to wait |
| 3204 | * before trying to get voted again). |
| 3205 | * |
| 3206 | * Timeout is MAX(NODE_TIMEOUT*2,2000) milliseconds. |
| 3207 | * Retry is two times the Timeout. |
| 3208 | */ |
| 3209 | auth_timeout = g_pserver->cluster_node_timeout*2; |
| 3210 | if (auth_timeout < 2000) auth_timeout = 2000; |
| 3211 | auth_retry_time = auth_timeout*2; |
| 3212 | |
| 3213 | /* Pre conditions to run the function, that must be met both in case |
| 3214 | * of an automatic or manual failover: |
| 3215 | * 1) We are a slave. |
| 3216 | * 2) Our master is flagged as FAIL, or this is a manual failover. |
| 3217 | * 3) We don't have the no failover configuration set, and this is |
| 3218 | * not a manual failover. |
| 3219 | * 4) It is serving slots. */ |
| 3220 | if (nodeIsMaster(myself) || |
| 3221 | myself->slaveof == NULL || |
| 3222 | (!nodeFailed(myself->slaveof) && !manual_failover) || |
| 3223 | (g_pserver->cluster_slave_no_failover && !manual_failover) || |
| 3224 | myself->slaveof->numslots == 0) |
| 3225 | { |
| 3226 | /* There are no reasons to failover, so we set the reason why we |
| 3227 | * are returning without failing over to NONE. */ |
| 3228 | g_pserver->cluster->cant_failover_reason = CLUSTER_CANT_FAILOVER_NONE; |
| 3229 | return; |
| 3230 | } |
| 3231 | |
| 3232 | /* Set data_age to the number of milliseconds we are disconnected from |
| 3233 | * the master. */ |
| 3234 | if (getFirstMaster()->repl_state == REPL_STATE_CONNECTED) { |
| 3235 | data_age = (mstime_t)(g_pserver->unixtime - getFirstMaster()->master->lastinteraction) |
| 3236 | * 1000; |
| 3237 | } else { |
| 3238 | data_age = (mstime_t)(g_pserver->unixtime - getFirstMaster()->repl_down_since) * 1000; |
| 3239 | } |
| 3240 | |
| 3241 | /* Remove the node timeout from the data age as it is fine that we are |
| 3242 | * disconnected from our master at least for the time it was down to be |
| 3243 | * flagged as FAIL, that's the baseline. */ |
| 3244 | if (data_age > g_pserver->cluster_node_timeout) |
| 3245 | data_age -= g_pserver->cluster_node_timeout; |
| 3246 | |
| 3247 | /* Check if our data is recent enough according to the slave validity |
| 3248 | * factor configured by the user. |
| 3249 | * |
no test coverage detected