// File: /workspace/github_c_makefile_star2_O1/zhou-yuxin[P]redis-aof-no-cow/src/cluster.c
// Function: clusterSendFailoverAuthIfNeeded
void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) {
    clusterNode *master = node->slaveof;
    uint64_t requestCurrentEpoch = ntohu64(request->currentEpoch);
    uint64_t requestConfigEpoch = ntohu64(request->configEpoch);
    unsigned char *claimed_slots = request->myslots;
    int force_ack = request->mflags[0] & CLUSTERMSG_FLAG0_FORCEACK;
    int j;

    /* IF we are not a master serving at least 1 slot, we don't have the
     * right to vote, as the cluster size in Redis Cluster is the number
     * of masters serving at least one slot, and quorum is the cluster
     * size + 1 */
    if (nodeIsSlave(myself) || myself->numslots == 0) return;

    /* Request epoch must be >= our currentEpoch.
     * Note that it is impossible for it to actually be greater since
     * our currentEpoch was updated as a side effect of receiving this
     * request, if the request epoch was greater. */
    if (requestCurrentEpoch < server.cluster->currentEpoch) {
        serverLog(LL_WARNING,
            "Failover auth denied to %.40s: reqEpoch (%llu) < curEpoch(%llu)",
            node->name,
            (unsigned long long) requestCurrentEpoch,
            (unsigned long long) server.cluster->currentEpoch);
        return;
    }

    /* I already voted for this epoch? Return ASAP. */
    if (server.cluster->lastVoteEpoch == server.cluster->currentEpoch) {
        serverLog(LL_WARNING,
                "Failover auth denied to %.40s: already voted for epoch %llu",
                node->name,
                (unsigned long long) server.cluster->currentEpoch);
        return;
    }

    /* Node must be a slave and its master down.
     * The master can be non failing if the request is flagged
     * with CLUSTERMSG_FLAG0_FORCEACK (manual failover). */
    if (nodeIsMaster(node) || master == NULL ||
        (!nodeFailed(master) && !force_ack))
    {
        if (nodeIsMaster(node)) {
            serverLog(LL_WARNING,
                    "Failover auth denied to %.40s: it is a master node",
                    node->name);
        } else if (master == NULL) {
            serverLog(LL_WARNING,
                    "Failover auth denied to %.40s: I don't know its master",
                    node->name);
        } else if (!nodeFailed(master)) {
            serverLog(LL_WARNING,
                    "Failover auth denied to %.40s: its master is up",
                    node->name);
        }
        return;
    }

    /* We did not voted for a slave about this master for two
     * times the node timeout. This is not strictly needed for correctness
     * of the algorithm but makes the base case more linear. */
    if (mstime() - node->slaveof->voted_time < server.cluster_node_timeout * 2)
    {
        serverLog(LL_WARNING,
                "Failover auth denied to %.40s: "
                "can't vote about this master before %lld milliseconds",
                node->name,
                (long long) ((server.cluster_node_timeout*2)-
                             (mstime() - node->slaveof->voted_time)));
        return;
    }

    /* The slave requesting the vote must have a configEpoch for the claimed
     * slots that is >= the one of the masters currently serving the same
     * slots in the current configuration. */
    for (j = 0; j < CLUSTER_SLOTS; j++) {
        if (bitmapTestBit(claimed_slots, j) == 0) continue;
        if (server.cluster->slots[j] == NULL ||
            server.cluster->slots[j]->configEpoch <= requestConfigEpoch)
        {
            continue;
        }
        /* If we reached this point we found a slot that in our current slots
         * is served by a master with a greater configEpoch than the one claimed
         * by the slave requesting our vote. Refuse to vote for this slave. */
        serverLog(LL_WARNING,
                "Failover auth denied to %.40s: "
                "slot %d epoch (%llu) > reqEpoch (%llu)",
                node->name, j,
                (unsigned long long) server.cluster->slots[j]->configEpoch,
                (unsigned long long) requestConfigEpoch);
        return;
    }

    /* We can vote for this slave. */
    clusterSendFailoverAuth(node);
    server.cluster->lastVoteEpoch = server.cluster->currentEpoch;
    node->slaveof->voted_time = mstime();
    serverLog(LL_WARNING, "Failover auth granted to %.40s for epoch %llu",
        node->name, (unsigned long long) server.cluster->currentEpoch);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movq 0x850(%rdi), %rbp
movq 0x10(%rsi), %rdi
callq 0x70c51
movq %rax, %r12
movq 0x18(%r14), %rdi
callq 0x70c51
movq %rax, %r15
movq 0xaef7d(%rip), %rax     # 0x11b1d0
testb $0x2, 0x30(%rax)
jne 0x6c322
cmpl $0x0, 0x840(%rax)
je 0x6c322
leaq 0x9a5e7(%rip), %r13     # 0x106858
movq 0x9a0(%r13), %rax
movq 0x8(%rax), %r8
cmpq %r8, %r12
jae 0x6c2ac
addq $0x8, %rbx
leaq 0x5ed5e(%rip), %rsi     # 0xcafea
movl $0x3, %edi
movq %rbx, %rdx
movq %r12, %rcx
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x32ea6
cmpq %r8, 0x60078(%rax)
jne 0x6c2e0
addq $0x8, %rbx
leaq 0x5ed6a(%rip), %rsi     # 0xcb02a
movl $0x3, %edi
movq %rbx, %rdx
movq %r8, %rcx
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x32ea6
movl 0x30(%rbx), %eax
testq %rbp, %rbp
sete %cl
orb %al, %cl
testb $0x1, %cl
jne 0x6c302
testb $0x8, 0x30(%rbp)
jne 0x6c33e
movb 0x89d(%r14), %cl
andb $0x2, %cl
jne 0x6c33e
testb $0x1, %al
jne 0x6c331
testq %rbp, %rbp
je 0x6c391
testb $0x8, 0x30(%rbp)
jne 0x6c322
addq $0x8, %rbx
leaq 0x5edb0(%rip), %rsi     # 0xcb0d0
jmp 0x6c39c
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
addq $0x8, %rbx
leaq 0x5ed2a(%rip), %rsi     # 0xcb066
jmp 0x6c39c
callq 0x330c8
movq 0x850(%rbx), %rcx
subq 0x870(%rcx), %rax
movq 0x990(%r13), %r12
addq %r12, %r12
cmpq %r12, %rax
jge 0x6c3b9
leaq 0x8(%rbx), %r14
callq 0x330c8
movq 0x850(%rbx), %rcx
subq %rax, %r12
addq 0x870(%rcx), %r12
leaq 0x5ed7f(%rip), %rsi     # 0xcb100
movl $0x3, %edi
movq %r14, %rdx
movq %r12, %rcx
jmp 0x6c2cb
addq $0x8, %rbx
leaq 0x5ecfd(%rip), %rsi     # 0xcb099
movl $0x3, %edi
movq %rbx, %rdx
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x32ea6
movq 0x9a0(%r13), %rax
xorl %ecx, %ecx
movl %ecx, %edx
shrl $0x3, %edx
movzbl 0x50(%r14,%rdx), %edx
movl %ecx, %esi
andl $0x7, %esi
btl %esi, %edx
jae 0x6c3ed
movq 0x40028(%rax,%rcx,8), %rdx
testq %rdx, %rdx
je 0x6c3ed
movq 0x38(%rdx), %r8
cmpq %r15, %r8
ja 0x6c449
incq %rcx
cmpq $0x4000, %rcx           # imm = 0x4000
jne 0x6c3c2
movq %rbx, %rdi
callq 0x6cb4f
movq 0x9a0(%r13), %rax
movq 0x8(%rax), %rcx
movq %rcx, 0x60078(%rax)
callq 0x330c8
movq 0x850(%rbx), %rcx
movq %rax, 0x870(%rcx)
addq $0x8, %rbx
movq 0x9a0(%r13), %rax
movq 0x8(%rax), %rcx
leaq 0x5ed5f(%rip), %rsi     # 0xcb19b
movl $0x3, %edi
movq %rbx, %rdx
jmp 0x6c2cb
addq $0x8, %rbx
leaq 0x5ed01(%rip), %rsi     # 0xcb155
movl $0x3, %edi
movq %rbx, %rdx
movq %r15, %r9
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x32ea6