// File: /workspace/github_c_makefile_star2_O0/gplessis[P]dotdeb-redis/src/cluster.c
// Function: clusterSendPing
void clusterSendPing(clusterLink *link, int type) {
    unsigned char *buf;
    clusterMsg *hdr;
    int gossipcount = 0; /* Number of gossip sections added so far. */
    int wanted; /* Number of gossip sections we want to append if possible. */
    int totlen; /* Total packet length. */
    /* freshnodes is the max number of nodes we can hope to append at all:
     * nodes available minus two (ourself and the node we are sending the
     * message to). However practically there may be less valid nodes since
     * nodes in handshake state, disconnected, are not considered. */
    int freshnodes = dictSize(server.cluster->nodes)-2;

    /* How many gossip sections we want to add? 1/10 of the number of nodes
     * and anyway at least 3. Why 1/10?
     *
     * If we have N masters, with N/10 entries, and we consider that in
     * node_timeout we exchange with each other node at least 4 packets
     * (we ping in the worst case in node_timeout/2 time, and we also
     * receive two pings from the host), we have a total of 8 packets
     * in the node_timeout*2 falure reports validity time. So we have
     * that, for a single PFAIL node, we can expect to receive the following
     * number of failure reports (in the specified window of time):
     *
     * PROB * GOSSIP_ENTRIES_PER_PACKET * TOTAL_PACKETS:
     *
     * PROB = probability of being featured in a single gossip entry,
     *        which is 1 / NUM_OF_NODES.
     * ENTRIES = 10.
     * TOTAL_PACKETS = 2 * 4 * NUM_OF_MASTERS.
     *
     * If we assume we have just masters (so num of nodes and num of masters
     * is the same), with 1/10 we always get over the majority, and specifically
     * 80% of the number of nodes, to account for many masters failing at the
     * same time.
     *
     * Since we have non-voting slaves that lower the probability of an entry
     * to feature our node, we set the number of entires per packet as
     * 10% of the total nodes we have. */
    wanted = floor(dictSize(server.cluster->nodes)/10);
    if (wanted < 3) wanted = 3;
    if (wanted > freshnodes) wanted = freshnodes;

    /* Compute the maxium totlen to allocate our buffer. We'll fix the totlen
     * later according to the number of gossip sections we really were able
     * to put inside the packet. */
    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);
    totlen += (sizeof(clusterMsgDataGossip)*wanted);
    /* Note: clusterBuildMessageHdr() expects the buffer to be always at least
     * sizeof(clusterMsg) or more. */
    if (totlen < (int)sizeof(clusterMsg)) totlen = sizeof(clusterMsg);
    buf = zcalloc(totlen);
    hdr = (clusterMsg*) buf;

    /* Populate the header. */
    if (link->node && type == CLUSTERMSG_TYPE_PING)
        link->node->ping_sent = mstime();
    clusterBuildMessageHdr(hdr,type);

    /* Populate the gossip fields */
    int maxiterations = wanted*3;
    while(freshnodes > 0 && gossipcount < wanted && maxiterations--) {
        dictEntry *de = dictGetRandomKey(server.cluster->nodes);
        clusterNode *this = dictGetVal(de);
        clusterMsgDataGossip *gossip;
        int j;

        /* Don't include this node: the whole packet header is about us
         * already, so we just gossip about other nodes. */
        if (this == myself) continue;

        /* Give a bias to FAIL/PFAIL nodes. */
        if (maxiterations > wanted*2 &&
            !(this->flags & (CLUSTER_NODE_PFAIL|CLUSTER_NODE_FAIL)))
            continue;

        /* In the gossip section don't include:
         * 1) Nodes in HANDSHAKE state.
         * 3) Nodes with the NOADDR flag set.
         * 4) Disconnected nodes if they don't have configured slots.
         */
        if (this->flags & (CLUSTER_NODE_HANDSHAKE|CLUSTER_NODE_NOADDR) ||
            (this->link == NULL && this->numslots == 0))
        {
            freshnodes--; /* Tecnically not correct, but saves CPU. */
            continue;
        }

        /* Check if we already added this node */
        for (j = 0; j < gossipcount; j++) {
            if (memcmp(hdr->data.ping.gossip[j].nodename,this->name,
                    CLUSTER_NAMELEN) == 0) break;
        }
        if (j != gossipcount) continue;

        /* Add it */
        freshnodes--;
        gossip = &(hdr->data.ping.gossip[gossipcount]);
        memcpy(gossip->nodename,this->name,CLUSTER_NAMELEN);
        gossip->ping_sent = htonl(this->ping_sent);
        gossip->pong_received = htonl(this->pong_received);
        memcpy(gossip->ip,this->ip,sizeof(this->ip));
        gossip->port = htons(this->port);
        gossip->flags = htons(this->flags);
        gossip->notused1 = 0;
        gossip->notused2 = 0;
        gossipcount++;
    }

    /* Ready to send... fix the totlen fiend and queue the message in the
     * output buffer. */
    totlen = sizeof(clusterMsg)-sizeof(union clusterMsgData);
    totlen += (sizeof(clusterMsgDataGossip)*gossipcount);
    hdr->count = htons(gossipcount);
    hdr->totlen = htonl(totlen);
    clusterSendMessage(link,buf,totlen);
    zfree(buf);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl $0x0, -0x24(%rbp)
leaq 0xf7a8b(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rcx
movq 0x18(%rcx), %rcx
movl 0x28(%rcx), %esi
movl 0x48(%rcx), %ecx
movl %ecx, %edx
movl %esi, %ecx
leal -0x2(%rcx,%rdx), %ecx
movl %ecx, -0x30(%rbp)
movq 0x9b0(%rax), %rax
movq 0x18(%rax), %rcx
movq 0x28(%rcx), %rax
movq 0x48(%rcx), %rcx
addq %rcx, %rax
movabsq $-0x3333333333333333, %rcx # imm = 0xCCCCCCCCCCCCCCCD
mulq %rcx
shrq $0x3, %rdx
cvtsi2sd %rdx, %xmm0
callq 0x26b60
cvttsd2si %xmm0, %eax
movl %eax, -0x28(%rbp)
cmpl $0x3, -0x28(%rbp)
jge 0x807ae
movl $0x3, -0x28(%rbp)
movl -0x28(%rbp), %eax
cmpl -0x30(%rbp), %eax
jle 0x807bc
movl -0x30(%rbp), %eax
movl %eax, -0x28(%rbp)
movl $0x8a0, -0x2c(%rbp)     # imm = 0x8A0
movslq -0x28(%rbp), %rax
imulq $0x68, %rax, %rcx
movslq -0x2c(%rbp), %rax
addq %rcx, %rax
movl %eax, -0x2c(%rbp)
cmpl $0x10d0, -0x2c(%rbp)    # imm = 0x10D0
jge 0x807e5
movl $0x10d0, -0x2c(%rbp)    # imm = 0x10D0
movslq -0x2c(%rbp), %rdi
callq 0x3ad80
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rax
cmpq $0x0, 0x20(%rax)
je 0x80822
cmpl $0x0, -0xc(%rbp)
jne 0x80822
callq 0x2ff70
movq %rax, %rcx
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq %rcx, 0x858(%rax)
movq -0x20(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0x811d0
imull $0x3, -0x28(%rbp), %eax
movl %eax, -0x34(%rbp)
xorl %eax, %eax
cmpl $0x0, -0x30(%rbp)
movb %al, -0x55(%rbp)
jle 0x80861
movl -0x24(%rbp), %ecx
xorl %eax, %eax
cmpl -0x28(%rbp), %ecx
movb %al, -0x55(%rbp)
jge 0x80861
movl -0x34(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x34(%rbp)
cmpl $0x0, %eax
setne %al
movb %al, -0x55(%rbp)
movb -0x55(%rbp), %al
testb $0x1, %al
jne 0x8086d
jmp 0x80a38
leaq 0xf7964(%rip), %rax     # 0x1781d8
movq 0x9b0(%rax), %rax
movq 0x18(%rax), %rdi
callq 0x2e6a0
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
cmpq 0x10c2c1(%rip), %rax    # 0x18cb60
jne 0x808a3
jmp 0x80835
movl -0x34(%rbp), %eax
movl -0x28(%rbp), %ecx
shll %ecx
cmpl %ecx, %eax
jle 0x808c3
movq -0x48(%rbp), %rax
movl 0x30(%rax), %eax
andl $0xc, %eax
cmpl $0x0, %eax
jne 0x808c3
jmp 0x80835
movq -0x48(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x60, %eax
cmpl $0x0, %eax
jne 0x808ed
movq -0x48(%rbp), %rax
cmpq $0x0, 0x8c8(%rax)
jne 0x808fb
movq -0x48(%rbp), %rax
cmpl $0x0, 0x840(%rax)
jne 0x808fb
movl -0x30(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x80835
movl $0x0, -0x54(%rbp)
movl -0x54(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x80946
movq -0x20(%rbp), %rdi
addq $0x8a0, %rdi            # imm = 0x8A0
movslq -0x54(%rbp), %rax
imulq $0x68, %rax, %rax
addq %rax, %rdi
movq -0x48(%rbp), %rsi
addq $0x8, %rsi
movl $0x28, %edx
callq 0x269b0
cmpl $0x0, %eax
jne 0x80939
jmp 0x80946
jmp 0x8093b
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x80902
movl -0x54(%rbp), %eax
cmpl -0x24(%rbp), %eax
je 0x80953
jmp 0x80835
movl -0x30(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x30(%rbp)
movq -0x20(%rbp), %rax
addq $0x8a0, %rax            # imm = 0x8A0
movslq -0x24(%rbp), %rcx
imulq $0x68, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq $0x8, %rsi
movl $0x28, %edx
callq 0x26c60
movq -0x48(%rbp), %rax
movq 0x858(%rax), %rax
movl %eax, %edi
callq 0x26b20
movl %eax, %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x28(%rax)
movq -0x48(%rbp), %rax
movq 0x860(%rax), %rax
movl %eax, %edi
callq 0x26b20
movl %eax, %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x2c(%rax)
movq -0x50(%rbp), %rdi
addq $0x30, %rdi
movq -0x48(%rbp), %rsi
addq $0x890, %rsi            # imm = 0x890
movl $0x2e, %edx
callq 0x26c60
movq -0x48(%rbp), %rax
movl 0x8c0(%rax), %eax
movzwl %ax, %edi
callq 0x26280
movw %ax, %cx
movq -0x50(%rbp), %rax
movw %cx, 0x5e(%rax)
movq -0x48(%rbp), %rax
movl 0x30(%rax), %eax
movzwl %ax, %edi
callq 0x26280
movw %ax, %cx
movq -0x50(%rbp), %rax
movw %cx, 0x60(%rax)
movq -0x50(%rbp), %rax
movw $0x0, 0x62(%rax)
movq -0x50(%rbp), %rax
movl $0x0, 0x64(%rax)
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x80835
movl $0x8a0, -0x2c(%rbp)     # imm = 0x8A0
movslq -0x24(%rbp), %rax
imulq $0x68, %rax, %rcx
movslq -0x2c(%rbp), %rax
addq %rcx, %rax
movl %eax, -0x2c(%rbp)
movl -0x24(%rbp), %eax
movzwl %ax, %edi
callq 0x26280
movw %ax, %cx
movq -0x20(%rbp), %rax
movw %cx, 0xe(%rax)
movl -0x2c(%rbp), %edi
callq 0x26b20
movl %eax, %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
movslq -0x2c(%rbp), %rdx
callq 0x81090
movq -0x18(%rbp), %rdi
callq 0x3afa0
addq $0x60, %rsp
popq %rbp
retq
nopl (%rax,%rax)