// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/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. */
    // 请求的配置纪元必须大于等于当前节点的配置纪元
    if (requestCurrentEpoch < server.cluster->currentEpoch) return;

    /* I already voted for this epoch? Return ASAP. */
    // 已经投过票了
    if (server.cluster->lastVoteEpoch == 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)) 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)
        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 < REDIS_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. */
        return;
    }

    /* We can vote for this slave. */
    // 为节点投票
    clusterSendFailoverAuth(node);
    // 更新时间值
    server.cluster->lastVoteEpoch = server.cluster->currentEpoch;
    node->slaveof->voted_time = mstime();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq 0x850(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x724a0
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x724a0
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
addq $0x50, %rax
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movzbl 0x89d(%rax), %eax
andl $0x2, %eax
movl %eax, -0x34(%rbp)
movq 0xbb623(%rip), %rax     # 0x127f78
movl 0x30(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
jne 0x6c970
movq 0xbb611(%rip), %rax     # 0x127f78
cmpl $0x0, 0x840(%rax)
jne 0x6c975
jmp 0x6cadf
movq -0x20(%rbp), %rax
leaq 0xa6f78(%rip), %rcx     # 0x1138f8
movq 0x7d0(%rcx), %rcx
cmpq 0x8(%rcx), %rax
jae 0x6c992
jmp 0x6cadf
leaq 0xa6f5f(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
movq 0x60070(%rax), %rax
leaq 0xa6f4a(%rip), %rcx     # 0x1138f8
movq 0x7d0(%rcx), %rcx
cmpq 0x8(%rcx), %rax
jne 0x6c9c0
jmp 0x6cadf
movq -0x8(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x6c9eb
cmpq $0x0, -0x18(%rbp)
je 0x6c9eb
movq -0x18(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
jne 0x6c9f0
cmpl $0x0, -0x34(%rbp)
jne 0x6c9f0
jmp 0x6cadf
callq 0x252e0
movq -0x8(%rbp), %rcx
movq 0x850(%rcx), %rcx
subq 0x870(%rcx), %rax
leaq 0xa6eea(%rip), %rcx     # 0x1138f8
movq 0x7c0(%rcx), %rcx
shlq %rcx
cmpq %rcx, %rax
jge 0x6ca22
jmp 0x6cadf
movl $0x0, -0x38(%rbp)
cmpl $0x4000, -0x38(%rbp)    # imm = 0x4000
jge 0x6ca95
movq -0x30(%rbp), %rdi
movl -0x38(%rbp), %esi
callq 0x6b310
cmpl $0x0, %eax
jne 0x6ca45
jmp 0x6ca8a
leaq 0xa6eac(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
movslq -0x38(%rbp), %rcx
cmpq $0x0, 0x40028(%rax,%rcx,8)
je 0x6ca86
leaq 0xa6e8f(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
movslq -0x38(%rbp), %rcx
movq 0x40028(%rax,%rcx,8), %rax
movq 0x38(%rax), %rax
cmpq -0x28(%rbp), %rax
ja 0x6ca88
jmp 0x6ca8a
jmp 0x6cadf
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x6ca29
movq -0x8(%rbp), %rdi
callq 0x6d430
leaq 0xa6e53(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
movq 0x8(%rax), %rcx
leaq 0xa6e41(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
movq %rcx, 0x60070(%rax)
callq 0x252e0
movq %rax, %rcx
movq -0x8(%rbp), %rax
movq 0x850(%rax), %rax
movq %rcx, 0x870(%rax)
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)