// File: /workspace/github_c_makefile_star2_O0/erikdubbelboer[P]discnt/src/cluster.c
// Function: clusterCron
void clusterCron(void) {
    dictIterator *di;
    dictEntry *de;
    int update_state = 0;
    mstime_t min_pong = 0, now = mstime();
    clusterNode *min_pong_node = NULL;
    static unsigned long long iteration = 0;
    mstime_t handshake_timeout;

    iteration++; /* Number of times this function was called so far. */

    /* The handshake timeout is the time after which a handshake node that was
     * not turned into a normal node is removed from the nodes. Usually it is
     * just the NODE_TIMEOUT value, but when NODE_TIMEOUT is too small we use
     * the value of 1 second. */
    handshake_timeout = server.cluster_node_timeout;
    if (handshake_timeout < 1000) handshake_timeout = 1000;

    /* Check if we have disconnected nodes and re-establish the connection. */
    di = dictGetSafeIterator(server.cluster->nodes);
    while((de = dictNext(di)) != NULL) {
        clusterNode *node = dictGetVal(de);

        if (node->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_NOADDR)) continue;

        /* A Node in HANDSHAKE state has a limited lifespan equal to the
         * configured node timeout. */
        if (nodeInHandshake(node) && now - node->ctime > handshake_timeout) {
            clusterDelNode(node);
            continue;
        }

        if (node->link == NULL) {
            int fd;
            mstime_t old_ping_sent;
            clusterLink *link;

            fd = anetTcpNonBlockBindConnect(server.neterr, node->ip,
                node->port+CLUSTER_PORT_INCR, NET_FIRST_BIND_ADDR);
            if (fd == -1) {
                /* We got a synchronous error from connect before
                 * clusterSendPing() had a chance to be called.
                 * If node->ping_sent is zero, failure detection can't work,
                 * so we claim we actually sent a ping now (that will
                 * be really sent as soon as the link is obtained). */
                if (node->ping_sent == 0) node->ping_sent = mstime();
                serverLog(LL_DEBUG, "Unable to connect to "
                    "Cluster Node [%s]:%d -> %s", node->ip,
                    node->port+CLUSTER_PORT_INCR,
                    server.neterr);
                continue;
            }
            anetEnableTcpNoDelay(NULL,fd);
            link = createClusterLink(node);
            link->fd = fd;
            node->link = link;
            aeCreateFileEvent(server.el,link->fd,AE_READABLE,
                    clusterReadHandler,link);
            /* Queue a PING in the new connection ASAP: this is crucial
             * to avoid false positives in failure detection.
             *
             * If the node is flagged as MEET, we send a MEET message instead
             * of a PING one, to force the receiver to add us in its node
             * table. */
            old_ping_sent = node->ping_sent;
            clusterSendPing(link, node->flags & CLUSTER_NODE_MEET ?
                    CLUSTERMSG_TYPE_MEET : CLUSTERMSG_TYPE_PING);
            if (old_ping_sent) {
                /* If there was an active ping before the link was
                 * disconnected, we want to restore the ping time, otherwise
                 * replaced by the clusterSendPing() call. */
                node->ping_sent = old_ping_sent;
            }
            /* We can clear the flag after the first packet is sent.
             * If we'll never receive a PONG, we'll never send new packets
             * to this node. Instead after the PONG is received and we
             * are no longer in meet/handshake status, we want to send
             * normal PING packets. */
            node->flags &= ~CLUSTER_NODE_MEET;

            serverLog(LL_DEBUG,"Connecting with Node %.40s at %s:%d",
                    node->name, node->ip, node->port+CLUSTER_PORT_INCR);
        }
    }
    dictReleaseIterator(di);

    /* Ping some random node 1 time every 10 iterations, so that we usually ping
     * one random node every second. */
    if (!(iteration % 10)) {
        int j;

        /* Check a few random nodes and ping the one with the oldest
         * pong_received time. */
        for (j = 0; j < 5; j++) {
            de = dictGetRandomKey(server.cluster->nodes);
            clusterNode *this = dictGetVal(de);

            /* Don't ping nodes disconnected or with a ping currently active. */
            if (this->link == NULL || this->ping_sent != 0) continue;
            if (this->flags & (CLUSTER_NODE_MYSELF|CLUSTER_NODE_HANDSHAKE))
                continue;
            if (min_pong_node == NULL || min_pong > this->pong_received) {
                min_pong_node = this;
                min_pong = this->pong_received;
            }
        }
        if (min_pong_node) {
            /*serverLog(LL_DEBUG,"Pinging node %.40s", min_pong_node->name);*/
            clusterSendPing(min_pong_node->link, CLUSTERMSG_TYPE_PING);
        }
    }

    /* Iterate nodes to check if we need to flag something as failing.
     * This loop is also responsible to:
     * 1) Check if there are orphaned masters (masters without non failing
     *    slaves).
     * 2) Count the max number of non failing slaves for a single master.
     * 3) Count the number of slaves for our master, if we are a slave. */
    di = dictGetSafeIterator(server.cluster->nodes);
    while((de = dictNext(di)) != NULL) {
        clusterNode *node = dictGetVal(de);
        now = mstime(); /* Use an updated time at every iteration. */
        mstime_t delay;

        if (node->flags &
            (CLUSTER_NODE_MYSELF|CLUSTER_NODE_NOADDR|CLUSTER_NODE_HANDSHAKE))
                continue;

        /* If we are waiting for the PONG more than half the cluster
         * timeout, reconnect the link: maybe there is a connection
         * issue even if the node is alive. */
        if (node->link && /* is connected */
            now - node->link->ctime >
            server.cluster_node_timeout && /* was not already reconnected */
            node->ping_sent && /* we already sent a ping */
            node->pong_received < node->ping_sent && /* still waiting pong */
            /* and we are waiting for the pong more than timeout/2 */
            now - node->ping_sent > server.cluster_node_timeout/2)
        {
            /* Disconnect the link, it will be reconnected automatically. */
            freeClusterLink(node->link);
        }

        /* If we have currently no active ping in this instance, and the
         * received PONG is older than half the cluster timeout, send
         * a new ping now, to ensure all the nodes are pinged without
         * a too big delay. */
        if (node->link &&
            node->ping_sent == 0 &&
            (now - node->pong_received) > server.cluster_node_timeout/2)
        {
            clusterSendPing(node->link, CLUSTERMSG_TYPE_PING);
            continue;
        }

        /* Check only if we have an active ping for this instance. */
        if (node->ping_sent == 0) continue;

        /* Compute the delay of the PONG. Note that if we already received
         * the PONG, then node->ping_sent is zero, so can't reach this
         * code at all. */
        delay = now - node->ping_sent;

        if (delay > server.cluster_node_timeout) {
            /* Timeout reached. Set the node as possibly failing if it is
             * not already in this state. */
            if (!(node->flags & (CLUSTER_NODE_PFAIL|CLUSTER_NODE_FAIL))) {
                serverLog(LL_DEBUG,"*** NODE %.40s possibly failing",
                    node->name);
                node->flags |= CLUSTER_NODE_PFAIL;
                update_state = 1;
            }
        }
    }
    dictReleaseIterator(di);

    if (update_state || server.cluster->state == CLUSTER_FAIL)
        clusterUpdateState();

    clusterUpdateReachableNodes();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movl $0x0, -0x14(%rbp)
movq $0x0, -0x20(%rbp)
callq 0x18e20
movq %rax, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movq 0x9ea96(%rip), %rax     # 0xd3608
addq $0x1, %rax
movq %rax, 0x9ea8b(%rip)     # 0xd3608
leaq 0x8a564(%rip), %rax     # 0xbf0e8
movq 0x658(%rax), %rax
movq %rax, -0x38(%rbp)
cmpq $0x3e8, -0x38(%rbp)     # imm = 0x3E8
jge 0x34ba1
movq $0x3e8, -0x38(%rbp)     # imm = 0x3E8
leaq 0x8a540(%rip), %rax     # 0xbf0e8
movq 0x668(%rax), %rax
movq 0x10(%rax), %rdi
callq 0x17370
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rdi
callq 0x173a0
movq %rax, -0x10(%rbp)
cmpq $0x0, %rax
je 0x34ddc
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x14, %eax
cmpl $0x0, %eax
je 0x34bf0
jmp 0x34bbc
movq -0x40(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x34c1c
movq -0x28(%rbp), %rax
movq -0x40(%rbp), %rcx
subq 0x28(%rcx), %rax
cmpq -0x38(%rbp), %rax
jle 0x34c1c
movq -0x40(%rbp), %rdi
callq 0x32a20
jmp 0x34bbc
movq -0x40(%rbp), %rax
cmpq $0x0, 0x88(%rax)
jne 0x34dd7
movq -0x40(%rbp), %rax
addq $0x50, %rax
movq %rax, -0x88(%rbp)
movq -0x40(%rbp), %rax
movl 0x80(%rax), %eax
addl $0x2710, %eax           # imm = 0x2710
movl %eax, -0x7c(%rbp)
leaq 0x8a492(%rip), %rax     # 0xbf0e8
cmpl $0x0, 0x140(%rax)
je 0x34c76
leaq 0x8a482(%rip), %rax     # 0xbf0e8
movq 0xc0(%rax), %rax
movq %rax, -0x90(%rbp)
jmp 0x34c81
xorl %eax, %eax
movq %rax, -0x90(%rbp)
jmp 0x34c81
movl -0x7c(%rbp), %edx
movq -0x88(%rbp), %rsi
movq -0x90(%rbp), %rcx
leaq 0x8a44f(%rip), %rdi     # 0xbf0e8
addq $0x218, %rdi            # imm = 0x218
callq 0x15110
movl %eax, -0x44(%rbp)
cmpl $-0x1, -0x44(%rbp)
jne 0x34d04
movq -0x40(%rbp), %rax
cmpq $0x0, 0x38(%rax)
jne 0x34cc9
callq 0x18e20
movq %rax, %rcx
movq -0x40(%rbp), %rax
movq %rcx, 0x38(%rax)
movq -0x40(%rbp), %rdx
addq $0x50, %rdx
movq -0x40(%rbp), %rax
movl 0x80(%rax), %ecx
addl $0x2710, %ecx           # imm = 0x2710
xorl %edi, %edi
leaq 0x72bf8(%rip), %rsi     # 0xa78e2
leaq 0x8a3f7(%rip), %r8      # 0xbf0e8
addq $0x218, %r8             # imm = 0x218
movb $0x0, %al
callq 0x18b10
jmp 0x34bbc
movl -0x44(%rbp), %esi
xorl %eax, %eax
movl %eax, %edi
callq 0x14950
movq -0x40(%rbp), %rdi
callq 0x32ac0
movq %rax, -0x58(%rbp)
movl -0x44(%rbp), %ecx
movq -0x58(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x58(%rbp), %rcx
movq -0x40(%rbp), %rax
movq %rcx, 0x88(%rax)
leaq 0x8a3ab(%rip), %rax     # 0xbf0e8
movq 0x38(%rax), %rdi
movq -0x58(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x58(%rbp), %r8
movl $0x1, %edx
leaq -0x2178(%rip), %rcx     # 0x32be0
callq 0x137d0
movq -0x40(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x58(%rbp), %rdi
movq -0x40(%rbp), %rax
movl 0x30(%rax), %ecx
andl $0x20, %ecx
xorl %esi, %esi
movl $0x2, %eax
cmpl $0x0, %ecx
cmovnel %eax, %esi
callq 0x34230
cmpq $0x0, -0x50(%rbp)
je 0x34d9c
movq -0x50(%rbp), %rcx
movq -0x40(%rbp), %rax
movq %rcx, 0x38(%rax)
movq -0x40(%rbp), %rax
movl 0x30(%rax), %ecx
andl $-0x21, %ecx
movl %ecx, 0x30(%rax)
movq -0x40(%rbp), %rdx
movq -0x40(%rbp), %rcx
addq $0x50, %rcx
movq -0x40(%rbp), %rax
movl 0x80(%rax), %r8d
addl $0x2710, %r8d           # imm = 0x2710
xorl %edi, %edi
leaq 0x72b42(%rip), %rsi     # 0xa7912
movb $0x0, %al
callq 0x18b10
jmp 0x34bbc
movq -0x8(%rbp), %rdi
callq 0x17510
movq 0x9e81c(%rip), %rax     # 0xd3608
movl $0xa, %ecx
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
jne 0x34eb8
movl $0x0, -0x5c(%rbp)
cmpl $0x5, -0x5c(%rbp)
jge 0x34e9d
leaq 0x8a2d0(%rip), %rax     # 0xbf0e8
movq 0x668(%rax), %rax
movq 0x10(%rax), %rdi
callq 0x175b0
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
cmpq $0x0, 0x88(%rax)
je 0x34e51
movq -0x68(%rbp), %rax
cmpq $0x0, 0x38(%rax)
je 0x34e53
jmp 0x34e8f
movq -0x68(%rbp), %rax
movl 0x30(%rax), %eax
andl $0xc, %eax
cmpl $0x0, %eax
je 0x34e64
jmp 0x34e8f
cmpq $0x0, -0x30(%rbp)
je 0x34e79
movq -0x20(%rbp), %rax
movq -0x68(%rbp), %rcx
cmpq 0x40(%rcx), %rax
jle 0x34e8d
movq -0x68(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x68(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x20(%rbp)
jmp 0x34e8f
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x34e07
cmpq $0x0, -0x30(%rbp)
je 0x34eb6
movq -0x30(%rbp), %rax
movq 0x88(%rax), %rdi
xorl %esi, %esi
callq 0x34230
jmp 0x34eb8
leaq 0x8a229(%rip), %rax     # 0xbf0e8
movq 0x668(%rax), %rax
movq 0x10(%rax), %rdi
callq 0x17370
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rdi
callq 0x173a0
movq %rax, -0x10(%rbp)
cmpq $0x0, %rax
je 0x35087
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x70(%rbp)
callq 0x18e20
movq %rax, -0x28(%rbp)
movq -0x70(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x1c, %eax
cmpl $0x0, %eax
je 0x34f10
jmp 0x34ed3
movq -0x70(%rbp), %rax
cmpq $0x0, 0x88(%rax)
je 0x34fab
movq -0x28(%rbp), %rax
movq -0x70(%rbp), %rcx
movq 0x88(%rcx), %rcx
subq (%rcx), %rax
leaq 0x8a1ad(%rip), %rcx     # 0xbf0e8
cmpq 0x658(%rcx), %rax
jle 0x34fab
movq -0x70(%rbp), %rax
cmpq $0x0, 0x38(%rax)
je 0x34fab
movq -0x70(%rbp), %rax
movq 0x40(%rax), %rax
movq -0x70(%rbp), %rcx
cmpq 0x38(%rcx), %rax
jge 0x34fab
movq -0x28(%rbp), %rax
movq -0x70(%rbp), %rcx
subq 0x38(%rcx), %rax
movq %rax, -0x98(%rbp)
leaq 0x8a16d(%rip), %rax     # 0xbf0e8
movq 0x658(%rax), %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0x98(%rbp), %rax
cmpq %rcx, %rax
jle 0x34fab
movq -0x70(%rbp), %rax
movq 0x88(%rax), %rdi
callq 0x32b30
movq -0x70(%rbp), %rax
cmpq $0x0, 0x88(%rax)
je 0x35015
movq -0x70(%rbp), %rax
cmpq $0x0, 0x38(%rax)
jne 0x35015
movq -0x28(%rbp), %rax
movq -0x70(%rbp), %rcx
subq 0x40(%rcx), %rax
movq %rax, -0xa0(%rbp)
leaq 0x8a10a(%rip), %rax     # 0xbf0e8
movq 0x658(%rax), %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0xa0(%rbp), %rax
cmpq %rcx, %rax
jle 0x35015
movq -0x70(%rbp), %rax
movq 0x88(%rax), %rdi
xorl %esi, %esi
callq 0x34230
jmp 0x34ed3
movq -0x70(%rbp), %rax
cmpq $0x0, 0x38(%rax)
jne 0x35025
jmp 0x34ed3
movq -0x28(%rbp), %rax
movq -0x70(%rbp), %rcx
subq 0x38(%rcx), %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
leaq 0x8a0a8(%rip), %rcx     # 0xbf0e8
cmpq 0x658(%rcx), %rax
jle 0x35082
movq -0x70(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x3, %eax
cmpl $0x0, %eax
jne 0x35080
movq -0x70(%rbp), %rdx
xorl %edi, %edi
leaq 0x728d1(%rip), %rsi     # 0xa7936
movb $0x0, %al
callq 0x18b10
movq -0x70(%rbp), %rax
movl 0x30(%rax), %ecx
orl $0x1, %ecx
movl %ecx, 0x30(%rax)
movl $0x1, -0x14(%rbp)
jmp 0x35082
jmp 0x34ed3
movq -0x8(%rbp), %rdi
callq 0x17510
cmpl $0x0, -0x14(%rbp)
jne 0x350aa
leaq 0x8a04b(%rip), %rax     # 0xbf0e8
movq 0x668(%rax), %rax
cmpl $0x1, 0x8(%rax)
jne 0x350af
callq 0x32740
callq 0x327f0
addq $0xa0, %rsp
popq %rbp
retq
nopl (%rax)