// File: /workspace/github_c_makefile_star2_O0/gplessis[P]dotdeb-redis/src/cluster.c
// Function: clusterHandleSlaveFailover
void clusterHandleSlaveFailover(void) {
    mstime_t data_age;
    mstime_t auth_age = mstime() - server.cluster->failover_auth_time;
    int needed_quorum = (server.cluster->size / 2) + 1;
    int manual_failover = server.cluster->mf_end != 0 &&
                          server.cluster->mf_can_start;
    mstime_t auth_timeout, auth_retry_time;

    server.cluster->todo_before_sleep &= ~CLUSTER_TODO_HANDLE_FAILOVER;

    /* Compute the failover timeout (the max time we have to send votes
     * and wait for replies), and the failover retry time (the time to wait
     * before trying to get voted again).
     *
     * Timeout is MIN(NODE_TIMEOUT*2,2000) milliseconds.
     * Retry is two times the Timeout.
     */
    auth_timeout = server.cluster_node_timeout*2;
    if (auth_timeout < 2000) auth_timeout = 2000;
    auth_retry_time = auth_timeout*2;

    /* Pre conditions to run the function, that must be met both in case
     * of an automatic or manual failover:
     * 1) We are a slave.
     * 2) Our master is flagged as FAIL, or this is a manual failover.
     * 3) It is serving slots. */
    if (nodeIsMaster(myself) ||
        myself->slaveof == NULL ||
        (!nodeFailed(myself->slaveof) && !manual_failover) ||
        myself->slaveof->numslots == 0)
    {
        /* There are no reasons to failover, so we set the reason why we
         * are returning without failing over to NONE. */
        server.cluster->cant_failover_reason = CLUSTER_CANT_FAILOVER_NONE;
        return;
    }

    /* Set data_age to the number of seconds we are disconnected from
     * the master. */
    if (server.repl_state == REPL_STATE_CONNECTED) {
        data_age = (mstime_t)(server.unixtime - server.master->lastinteraction)
                   * 1000;
    } else {
        data_age = (mstime_t)(server.unixtime - server.repl_down_since) * 1000;
    }

    /* Remove the node timeout from the data age as it is fine that we are
     * disconnected from our master at least for the time it was down to be
     * flagged as FAIL, that's the baseline. */
    if (data_age > server.cluster_node_timeout)
        data_age -= server.cluster_node_timeout;

    /* Check if our data is recent enough according to the slave validity
     * factor configured by the user.
     *
     * Check bypassed for manual failovers. */
    if (server.cluster_slave_validity_factor &&
        data_age >
        (((mstime_t)server.repl_ping_slave_period * 1000) +
         (server.cluster_node_timeout * server.cluster_slave_validity_factor)))
    {
        if (!manual_failover) {
            clusterLogCantFailover(CLUSTER_CANT_FAILOVER_DATA_AGE);
            return;
        }
    }

    /* If the previous failover attempt timedout and the retry time has
     * elapsed, we can setup a new one. */
    if (auth_age > auth_retry_time) {
        server.cluster->failover_auth_time = mstime() +
            500 + /* Fixed delay of 500 milliseconds, let FAIL msg propagate. */
            random() % 500; /* Random delay between 0 and 500 milliseconds. */
        server.cluster->failover_auth_count = 0;
        server.cluster->failover_auth_sent = 0;
        server.cluster->failover_auth_rank = clusterGetSlaveRank();
        /* We add another delay that is proportional to the slave rank.
         * Specifically 1 second * rank. This way slaves that have a probably
         * less updated replication offset, are penalized. */
        server.cluster->failover_auth_time +=
            server.cluster->failover_auth_rank * 1000;
        /* However if this is a manual failover, no delay is needed. */
        if (server.cluster->mf_end) {
            server.cluster->failover_auth_time = mstime();
            server.cluster->failover_auth_rank = 0;
        }
        serverLog(LL_WARNING,
            "Start of election delayed for %lld milliseconds "
            "(rank #%d, offset %lld).",
            server.cluster->failover_auth_time - mstime(),
            server.cluster->failover_auth_rank,
            replicationGetSlaveOffset());
        /* Now that we have a scheduled election, broadcast our offset
         * to all the other slaves so that they'll updated their offsets
         * if our offset is better. */
        clusterBroadcastPong(CLUSTER_BROADCAST_LOCAL_SLAVES);
        return;
    }

    /* It is possible that we received more updated offsets from other
     * slaves for the same master since we computed our election delay.
     * Update the delay if our rank changed.
     *
     * Not performed if this is a manual failover. */
    if (server.cluster->failover_auth_sent == 0 &&
        server.cluster->mf_end == 0)
    {
        int newrank = clusterGetSlaveRank();
        if (newrank > server.cluster->failover_auth_rank) {
            long long added_delay =
                (newrank - server.cluster->failover_auth_rank) * 1000;
            server.cluster->failover_auth_time += added_delay;
            server.cluster->failover_auth_rank = newrank;
            serverLog(LL_WARNING,
                "Slave rank updated to #%d, added %lld milliseconds of delay.",
                newrank, added_delay);
        }
    }

    /* Return ASAP if we can't still start the election. */
    if (mstime() < server.cluster->failover_auth_time) {
        clusterLogCantFailover(CLUSTER_CANT_FAILOVER_WAITING_DELAY);
        return;
    }

    /* Return ASAP if the election is too old to be valid. */
    if (auth_age > auth_timeout) {
        clusterLogCantFailover(CLUSTER_CANT_FAILOVER_EXPIRED);
        return;
    }

    /* Ask for votes if needed. */
    if (server.cluster->failover_auth_sent == 0) {
        server.cluster->currentEpoch++;
        server.cluster->failover_auth_epoch = server.cluster->currentEpoch;
        serverLog(LL_WARNING,"Starting a failover election for epoch %llu.",
            (unsigned long long) server.cluster->currentEpoch);
        clusterRequestFailoverAuth();
        server.cluster->failover_auth_sent = 1;
        clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|
                             CLUSTER_TODO_UPDATE_STATE|
                             CLUSTER_TODO_FSYNC_CONFIG);
        return; /* Wait for replies. */
    }

    /* Check if we reached the quorum. */
    if (server.cluster->failover_auth_count >= needed_quorum) {
        /* We have the quorum, we can finally failover the master. */

        serverLog(LL_WARNING,
            "Failover election won: I'm the new master.");

        /* Update my configEpoch to the epoch of the election. */
        if (myself->configEpoch < server.cluster->failover_auth_epoch) {
            myself->configEpoch = server.cluster->failover_auth_epoch;
            serverLog(LL_WARNING,
                "configEpoch set to %llu after successful failover",
                (unsigned long long) myself->configEpoch);
        }

        /* Take responsability for the cluster slots. */
        clusterFailoverReplaceYourMaster();
    } else {
        clusterLogCantFailover(CLUSTER_CANT_FAILOVER_WAITING_VOTES);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
callq 0x2ff70
leaq 0xf61e4(%rip), %rcx     # 0x1781d8
movq 0x9b0(%rcx), %rcx
subq 0x60030(%rcx), %rax
movq %rax, -0x10(%rbp)
leaq 0xf61cb(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl 0x14(%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
addl $0x1, %eax
movl %eax, -0x14(%rbp)
leaq 0xf61ac(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rcx
xorl %eax, %eax
cmpq $0x0, 0x60058(%rcx)
movb %al, -0x39(%rbp)
je 0x8205d
leaq 0xf618f(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
cmpl $0x0, 0x60070(%rax)
setne %al
movb %al, -0x39(%rbp)
movb -0x39(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x18(%rbp)
leaq 0xf6169(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl 0x60080(%rax), %ecx
andl $-0x2, %ecx
movl %ecx, 0x60080(%rax)
leaq 0xf614c(%rip), %rax     # 0x1781d8
movq 0x9a0(%rax), %rax
shlq %rax
movq %rax, -0x20(%rbp)
cmpq $0x7d0, -0x20(%rbp)     # imm = 0x7D0
jge 0x820ac
movq $0x7d0, -0x20(%rbp)     # imm = 0x7D0
movq -0x20(%rbp), %rax
shlq %rax
movq %rax, -0x28(%rbp)
movq 0x10aaa2(%rip), %rax    # 0x18cb60
movl 0x30(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x82110
movq 0x10aa90(%rip), %rax    # 0x18cb60
cmpq $0x0, 0x850(%rax)
je 0x82110
movq 0x10aa7f(%rip), %rax    # 0x18cb60
movq 0x850(%rax), %rax
movl 0x30(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
jne 0x820f9
cmpl $0x0, -0x18(%rbp)
je 0x82110
movq 0x10aa60(%rip), %rax    # 0x18cb60
movq 0x850(%rax), %rax
cmpl $0x0, 0x840(%rax)
jne 0x8212d
leaq 0xf60c1(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl $0x0, 0x60050(%rax)
jmp 0x82610
leaq 0xf60a4(%rip), %rax     # 0x1781d8
cmpl $0xf, 0x84c(%rax)
jne 0x8216d
leaq 0xf6094(%rip), %rax     # 0x1781d8
movq 0x978(%rax), %rax
leaq 0xf6086(%rip), %rcx     # 0x1781d8
movq 0x838(%rcx), %rcx
subq 0x88(%rcx), %rax
imulq $0x3e8, %rax, %rax      # imm = 0x3E8
movq %rax, -0x8(%rbp)
jmp 0x82194
leaq 0xf6064(%rip), %rax     # 0x1781d8
movq 0x978(%rax), %rax
leaq 0xf6056(%rip), %rcx     # 0x1781d8
subq 0x888(%rcx), %rax
imulq $0x3e8, %rax, %rax      # imm = 0x3E8
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
leaq 0xf6039(%rip), %rcx     # 0x1781d8
cmpq 0x9a0(%rcx), %rax
jle 0x821c1
leaq 0xf6029(%rip), %rax     # 0x1781d8
movq 0x9a0(%rax), %rcx
movq -0x8(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x8(%rbp)
leaq 0xf6010(%rip), %rax     # 0x1781d8
cmpl $0x0, 0x9bc(%rax)
je 0x82229
movq -0x8(%rbp), %rax
leaq 0xf5ffc(%rip), %rcx     # 0x1781d8
movslq 0x7c8(%rcx), %rcx
imulq $0x3e8, %rcx, %rcx      # imm = 0x3E8
leaq 0xf5fe7(%rip), %rdx     # 0x1781d8
movq 0x9a0(%rdx), %rdx
leaq 0xf5fd9(%rip), %rsi     # 0x1781d8
movslq 0x9bc(%rsi), %rsi
imulq %rsi, %rdx
addq %rdx, %rcx
cmpq %rcx, %rax
jle 0x82229
cmpl $0x0, -0x18(%rbp)
jne 0x82227
movl $0x1, %edi
callq 0x81b00
jmp 0x82610
jmp 0x82229
movq -0x10(%rbp), %rax
cmpq -0x28(%rbp), %rax
jle 0x823b4
callq 0x2ff70
addq $0x1f4, %rax            # imm = 0x1F4
movq %rax, -0x48(%rbp)
callq 0x26a30
movq -0x48(%rbp), %rcx
movl $0x1f4, %esi            # imm = 0x1F4
cqto
idivq %rsi
addq %rdx, %rcx
leaq 0xf5f75(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movq %rcx, 0x60030(%rax)
leaq 0xf5f60(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl $0x0, 0x60038(%rax)
leaq 0xf5f48(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl $0x0, 0x6003c(%rax)
callq 0x81a10
movl %eax, %ecx
leaq 0xf5f29(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl %ecx, 0x60040(%rax)
leaq 0xf5f15(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
imull $0x3e8, 0x60040(%rax), %eax # imm = 0x3E8
movslq %eax, %rcx
leaq 0xf5efa(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
addq 0x60030(%rax), %rcx
movq %rcx, 0x60030(%rax)
leaq 0xf5ede(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
cmpq $0x0, 0x60058(%rax)
je 0x82340
callq 0x2ff70
movq %rax, %rcx
leaq 0xf5ebe(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movq %rcx, 0x60030(%rax)
leaq 0xf5ea9(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl $0x0, 0x60040(%rax)
leaq 0xf5e91(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movq 0x60030(%rax), %rax
movq %rax, -0x60(%rbp)
callq 0x2ff70
movq %rax, %rcx
movq -0x60(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x58(%rbp)
leaq 0xf5e65(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl 0x60040(%rax), %eax
movl %eax, -0x4c(%rbp)
callq 0x523d0
movq -0x58(%rbp), %rdx
movl -0x4c(%rbp), %ecx
movq %rax, %r8
movl $0x3, %edi
leaq 0xc0079(%rip), %rsi     # 0x142417
movb $0x0, %al
callq 0x2fc60
movl $0x1, %edi
callq 0x81480
jmp 0x82610
leaq 0xf5e1d(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
cmpl $0x0, 0x6003c(%rax)
jne 0x82482
leaq 0xf5e02(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
cmpq $0x0, 0x60058(%rax)
jne 0x82482
callq 0x81a10
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
leaq 0xf5ddb(%rip), %rcx     # 0x1781d8
movq 0x9b0(%rcx), %rcx
cmpl 0x60040(%rcx), %eax
jle 0x82480
movl -0x2c(%rbp), %eax
leaq 0xf5dc2(%rip), %rcx     # 0x1781d8
movq 0x9b0(%rcx), %rcx
subl 0x60040(%rcx), %eax
imull $0x3e8, %eax, %eax      # imm = 0x3E8
cltq
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rcx
leaq 0xf5d9e(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
addq 0x60030(%rax), %rcx
movq %rcx, 0x60030(%rax)
movl -0x2c(%rbp), %ecx
leaq 0xf5d7f(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl %ecx, 0x60040(%rax)
movl -0x2c(%rbp), %edx
movq -0x38(%rbp), %rcx
movl $0x3, %edi
leaq 0xbffe7(%rip), %rsi     # 0x142460
movb $0x0, %al
callq 0x2fc60
jmp 0x82482
callq 0x2ff70
leaq 0xf5d4a(%rip), %rcx     # 0x1781d8
movq 0x9b0(%rcx), %rcx
cmpq 0x60030(%rcx), %rax
jge 0x824ad
movl $0x2, %edi
callq 0x81b00
jmp 0x82610
movq -0x10(%rbp), %rax
cmpq -0x20(%rbp), %rax
jle 0x824c6
movl $0x3, %edi
callq 0x81b00
jmp 0x82610
leaq 0xf5d0b(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
cmpl $0x0, 0x6003c(%rax)
jne 0x82573
leaq 0xf5cf0(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movq 0x8(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x8(%rax)
leaq 0xf5cd6(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movq 0x8(%rax), %rcx
leaq 0xf5cc4(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movq %rcx, 0x60048(%rax)
leaq 0xf5caf(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movq 0x8(%rax), %rdx
movl $0x3, %edi
leaq 0xbff5d(%rip), %rsi     # 0x14249d
movb $0x0, %al
callq 0x2fc60
callq 0x81850
leaq 0xf5c85(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl $0x1, 0x6003c(%rax)
movl $0xe, %edi
callq 0x7db50
jmp 0x82610
leaq 0xf5c5e(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movl 0x60038(%rax), %eax
cmpl -0x14(%rbp), %eax
jl 0x82606
movl $0x3, %edi
leaq 0xbff32(%rip), %rsi     # 0x1424ca
movb $0x0, %al
callq 0x2fc60
movq 0x10a5ba(%rip), %rax    # 0x18cb60
movq 0x38(%rax), %rax
leaq 0xf5c27(%rip), %rcx     # 0x1781d8
movq 0x9b0(%rcx), %rcx
cmpq 0x60048(%rcx), %rax
jae 0x825ff
leaq 0xf5c10(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movq 0x60048(%rax), %rcx
movq 0x10a583(%rip), %rax    # 0x18cb60
movq %rcx, 0x38(%rax)
movq 0x10a578(%rip), %rax    # 0x18cb60
movq 0x38(%rax), %rdx
movl $0x3, %edi
leaq 0xbfefd(%rip), %rsi     # 0x1424f5
movb $0x0, %al
callq 0x2fc60
callq 0x81c50
jmp 0x82610
movl $0x4, %edi
callq 0x81b00
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)