Failover cron function, checks coordinated failover state. * * Implementation note: The current implementation calls replicationSetMaster() * to start the failover request, this has some unintended side effects if the * failover doesn't work like blocked clients will be unblocked and replicas will * be disconnected. This could be optimized further. */
| 3726 | * be disconnected. This could be optimized further. |
| 3727 | */ |
| 3728 | void updateFailoverStatus(void) { |
| 3729 | if (server.failover_state != FAILOVER_WAIT_FOR_SYNC) return; |
| 3730 | mstime_t now = server.mstime; |
| 3731 | |
| 3732 | /* Check if failover operation has timed out */ |
| 3733 | if (server.failover_end_time && server.failover_end_time <= now) { |
| 3734 | if (server.force_failover) { |
| 3735 | serverLog(LL_NOTICE, |
| 3736 | "FAILOVER to %s:%d time out exceeded, failing over.", |
| 3737 | server.target_replica_host, server.target_replica_port); |
| 3738 | server.failover_state = FAILOVER_IN_PROGRESS; |
| 3739 | /* If timeout has expired force a failover if requested. */ |
| 3740 | replicationSetMaster(server.target_replica_host, |
| 3741 | server.target_replica_port); |
| 3742 | return; |
| 3743 | } else { |
| 3744 | /* Force was not requested, so timeout. */ |
| 3745 | abortFailover("Replica never caught up before timeout"); |
| 3746 | return; |
| 3747 | } |
| 3748 | } |
| 3749 | |
| 3750 | /* Check to see if the replica has caught up so failover can start */ |
| 3751 | client *replica = NULL; |
| 3752 | if (server.target_replica_host) { |
| 3753 | replica = findReplica(server.target_replica_host, |
| 3754 | server.target_replica_port); |
| 3755 | } else { |
| 3756 | listIter li; |
| 3757 | listNode *ln; |
| 3758 | |
| 3759 | listRewind(server.slaves,&li); |
| 3760 | /* Find any replica that has matched our repl_offset */ |
| 3761 | while((ln = listNext(&li))) { |
| 3762 | replica = ln->value; |
| 3763 | if (replica->repl_ack_off == server.master_repl_offset) { |
| 3764 | char ip[NET_IP_STR_LEN], *replicaaddr = replica->slave_addr; |
| 3765 | |
| 3766 | if (!replicaaddr) { |
| 3767 | if (connPeerToString(replica->conn,ip,sizeof(ip),NULL) == -1) |
| 3768 | continue; |
| 3769 | replicaaddr = ip; |
| 3770 | } |
| 3771 | |
| 3772 | /* We are now failing over to this specific node */ |
| 3773 | server.target_replica_host = zstrdup(replicaaddr); |
| 3774 | server.target_replica_port = replica->slave_listening_port; |
| 3775 | break; |
| 3776 | } |
| 3777 | } |
| 3778 | } |
| 3779 | |
| 3780 | /* We've found a replica that is caught up */ |
| 3781 | if (replica && (replica->repl_ack_off == server.master_repl_offset)) { |
| 3782 | server.failover_state = FAILOVER_IN_PROGRESS; |
| 3783 | serverLog(LL_NOTICE, |
| 3784 | "Failover target %s:%d is synced, failing over.", |
| 3785 | server.target_replica_host, server.target_replica_port); |
no test coverage detected