// File: /workspace/github_c_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movl %esi, %ebp
movq %rdi, %rbx
leaq 0x9953f(%rip), %r15     # 0x1018a8
movq 0x9b0(%r15), %rax
movq 0x18(%rax), %rax
movq 0x48(%rax), %rcx
addq 0x28(%rax), %rcx
movabsq $-0x3333333333333333, %rdx # imm = 0xCCCCCCCCCCCCCCCD
movq %rcx, %rax
mulq %rdx
leal -0x2(%rcx), %eax
shrq $0x3, %rdx
cmpl $0x4, %edx
movl $0x3, %ecx
cmovgel %edx, %ecx
cmpl %eax, %ecx
movl %eax, %r14d
cmovgel %eax, %ecx
movq %rcx, 0x30(%rsp)
imull $0x68, %ecx, %eax
addl $0x8a0, %eax            # imm = 0x8A0
cmpl $0x10d1, %eax           # imm = 0x10D1
movl $0x10d0, %edi           # imm = 0x10D0
cmovgel %eax, %edi
callq 0x38323
movq %rax, %r12
testl %ebp, %ebp
jne 0x683e3
cmpq $0x0, 0x20(%rbx)
je 0x683e3
callq 0x2ffce
movq 0x20(%rbx), %rcx
movq %rax, 0x858(%rcx)
movq %r12, %rdi
movl %ebp, %esi
callq 0x68b27
testl %r14d, %r14d
jle 0x685b5
movl %r14d, %ebp
movq 0x30(%rsp), %rax
leal (%rax,%rax,2), %r14d
addl %eax, %eax
movl %eax, 0x14(%rsp)
movq %r12, %rax
addq $0x8a0, %rax            # imm = 0x8A0
movq %rax, 0x28(%rsp)
xorl %edx, %edx
movq %rbx, 0x20(%rsp)
movq %r12, 0x18(%rsp)
subl $0x1, %r14d
jb 0x685b7
movq %rdx, 0x8(%rsp)
movq 0x9b0(%r15), %rax
movq 0x18(%rax), %rdi
callq 0x2f141
movq 0x8(%rax), %r13
cmpq 0xadde4(%rip), %r13     # 0x116230
je 0x685a0
movl 0x30(%r13), %eax
cmpl 0x14(%rsp), %r14d
movq 0x8(%rsp), %rdx
jle 0x6846d
movl %eax, %ecx
andl $0xc, %ecx
je 0x685a5
testb $0x60, %al
je 0x68478
decl %ebp
jmp 0x685a5
cmpq $0x0, 0x8c8(%r13)
jne 0x6848c
cmpl $0x0, 0x840(%r13)
je 0x68471
movl %ebp, 0x10(%rsp)
testl %edx, %edx
jle 0x684c3
leaq 0x8(%r13), %r15
movl %edx, %ebp
movq 0x28(%rsp), %r12
xorl %ebx, %ebx
movl $0x28, %edx
movq %r12, %rdi
movq %r15, %rsi
callq 0x266f0
testl %eax, %eax
je 0x684c7
incq %rbx
addq $0x68, %r12
cmpq %rbx, %rbp
jne 0x684a1
jmp 0x684d4
xorl %ebx, %ebx
jmp 0x684cc
movq 0x8(%rsp), %rdx
cmpl %edx, %ebx
jne 0x6858b
movl 0x10(%rsp), %ebp
decl %ebp
movq 0x8(%rsp), %rdx
movslq %edx, %rax
imulq $0x68, %rax, %rax
movq 0x28(%r13), %rcx
movq 0x28(%rsp), %rsi
movq %rcx, 0x20(%rsi,%rax)
movups 0x8(%r13), %xmm0
movups 0x18(%r13), %xmm1
movups %xmm1, 0x10(%rsi,%rax)
movups %xmm0, (%rsi,%rax)
movl 0x858(%r13), %ecx
bswapl %ecx
movl %ecx, 0x28(%rsi,%rax)
movl 0x860(%r13), %ecx
bswapl %ecx
movl %ecx, 0x2c(%rsi,%rax)
movups 0x890(%r13), %xmm0
movups 0x8a0(%r13), %xmm1
movups 0x8ae(%r13), %xmm2
movups %xmm0, 0x30(%rsi,%rax)
movups %xmm1, 0x40(%rsi,%rax)
movups %xmm2, 0x4e(%rsi,%rax)
movzwl 0x8c0(%r13), %ecx
rolw $0x8, %cx
movw %cx, 0x5e(%rsi,%rax)
movzwl 0x30(%r13), %ecx
rolw $0x8, %cx
movw %cx, 0x60(%rsi,%rax)
movw $0x0, 0x62(%rsi,%rax)
movl $0x0, 0x64(%rsi,%rax)
incl %edx
movq 0x20(%rsp), %rbx
leaq 0x99324(%rip), %r15     # 0x1018a8
movq 0x18(%rsp), %r12
jmp 0x685a5
movq 0x20(%rsp), %rbx
leaq 0x99311(%rip), %r15     # 0x1018a8
movq 0x18(%rsp), %r12
movl 0x10(%rsp), %ebp
movq 0x8(%rsp), %rdx
testl %ebp, %ebp
jle 0x685b7
cmpl 0x30(%rsp), %edx
jl 0x68422
jmp 0x685b7
xorl %edx, %edx
imull $0x68, %edx, %eax
addl $0x8a0, %eax            # imm = 0x8A0
rolw $0x8, %dx
movw %dx, 0xe(%r12)
movslq %eax, %rdx
bswapl %eax
movl %eax, 0x4(%r12)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x68a1a
movq %r12, %rdi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x38413