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. */
| 3132 | * 3) Perform the failover informing all the other nodes. |
| 3133 | */ |
| 3134 | void clusterHandleSlaveFailover(void) { |
| 3135 | mstime_t data_age; |
| 3136 | mstime_t auth_age = mstime() - server.cluster->failover_auth_time; |
| 3137 | int needed_quorum = (server.cluster->size / 2) + 1; |
| 3138 | int manual_failover = server.cluster->mf_end != 0 && |
| 3139 | server.cluster->mf_can_start; |
| 3140 | mstime_t auth_timeout, auth_retry_time; |
| 3141 | |
| 3142 | server.cluster->todo_before_sleep &= ~CLUSTER_TODO_HANDLE_FAILOVER; |
| 3143 | |
| 3144 | /* Compute the failover timeout (the max time we have to send votes |
| 3145 | * and wait for replies), and the failover retry time (the time to wait |
| 3146 | * before trying to get voted again). |
| 3147 | * |
| 3148 | * Timeout is MAX(NODE_TIMEOUT*2,2000) milliseconds. |
| 3149 | * Retry is two times the Timeout. |
| 3150 | */ |
| 3151 | auth_timeout = server.cluster_node_timeout*2; |
| 3152 | if (auth_timeout < 2000) auth_timeout = 2000; |
| 3153 | auth_retry_time = auth_timeout*2; |
| 3154 | |
| 3155 | /* Pre conditions to run the function, that must be met both in case |
| 3156 | * of an automatic or manual failover: |
| 3157 | * 1) We are a slave. |
| 3158 | * 2) Our master is flagged as FAIL, or this is a manual failover. |
| 3159 | * 3) We don't have the no failover configuration set, and this is |
| 3160 | * not a manual failover. |
| 3161 | * 4) It is serving slots. */ |
| 3162 | if (nodeIsMaster(myself) || |
| 3163 | myself->slaveof == NULL || |
| 3164 | (!nodeFailed(myself->slaveof) && !manual_failover) || |
| 3165 | (server.cluster_slave_no_failover && !manual_failover) || |
| 3166 | myself->slaveof->numslots == 0) |
| 3167 | { |
| 3168 | /* There are no reasons to failover, so we set the reason why we |
| 3169 | * are returning without failing over to NONE. */ |
| 3170 | server.cluster->cant_failover_reason = CLUSTER_CANT_FAILOVER_NONE; |
| 3171 | return; |
| 3172 | } |
| 3173 | |
| 3174 | /* Set data_age to the number of milliseconds we are disconnected from |
| 3175 | * the master. */ |
| 3176 | if (server.repl_state == REPL_STATE_CONNECTED) { |
| 3177 | data_age = (mstime_t)(server.unixtime - server.master->lastinteraction) |
| 3178 | * 1000; |
| 3179 | } else { |
| 3180 | data_age = (mstime_t)(server.unixtime - server.repl_down_since) * 1000; |
| 3181 | } |
| 3182 | |
| 3183 | /* Remove the node timeout from the data age as it is fine that we are |
| 3184 | * disconnected from our master at least for the time it was down to be |
| 3185 | * flagged as FAIL, that's the baseline. */ |
| 3186 | if (data_age > server.cluster_node_timeout) |
| 3187 | data_age -= server.cluster_node_timeout; |
| 3188 | |
| 3189 | /* Check if our data is recent enough according to the slave validity |
| 3190 | * factor configured by the user. |
| 3191 | * |
no test coverage detected