// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterCron
void clusterCron(void) {
    dictIterator *di;
    dictEntry *de;
    int update_state = 0;
    int orphaned_masters; /* How many masters there are without ok slaves. */
    int max_slaves; /* Max number of ok slaves for a single master. */
    int this_slaves; /* Number of ok slaves for our master (if we are slave). */
    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 节点没有在 handshake timeout 内
    // 转换成普通节点（normal node），
    // 那么节点会从 nodes 表中移除这个 handshake 节点
    // 一般来说 handshake timeout 的值总是等于 NODE_TIMEOUT
    // 不过如果 NODE_TIMEOUT 太少的话，程序会将值设为 1 秒钟
    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 & (REDIS_NODE_MYSELF|REDIS_NODE_NOADDR)) continue;

        /* A Node in HANDSHAKE state has a limited lifespan equal to the
         * configured node timeout. */
        // 如果 handshake 节点已超时，释放它
        if (nodeInHandshake(node) && now - node->ctime > handshake_timeout) {
            freeClusterNode(node);
            continue;
        }

        // 为未创建连接的节点创建连接
        if (node->link == NULL) {
            int fd;
            mstime_t old_ping_sent;
            clusterLink *link;

            fd = anetTcpNonBlockBindConnect(server.neterr, node->ip,
                node->port+REDIS_CLUSTER_PORT_INCR,
                    server.bindaddr_count ? server.bindaddr[0] : NULL);
            if (fd == -1) {
                redisLog(REDIS_DEBUG, "Unable to connect to "
                    "Cluster Node [%s]:%d -> %s", node->ip,
                    node->port+REDIS_CLUSTER_PORT_INCR,
                    server.neterr);
                continue;
            }
            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. */
            // 向新连接的节点发送 PING 命令，防止节点被识进入下线
            // 如果节点被标记为 MEET ，那么发送 MEET 命令，否则发送 PING 命令
            old_ping_sent = node->ping_sent;
            clusterSendPing(link, node->flags & REDIS_NODE_MEET ?
                    CLUSTERMSG_TYPE_MEET : CLUSTERMSG_TYPE_PING);

            // 这不是第一次发送 PING 信息，所以可以还原这个时间
            // 等 clusterSendPing() 函数来更新它
            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.
             *
             * 在发送 MEET 信息之后，清除节点的 MEET 标识。
             *
             * 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. 
             *
             * 如果当前节点（发送者）没能收到 MEET 信息的回复，
             * 那么它将不再向目标节点发送命令。
             *
             * 如果接收到回复的话，那么节点将不再处于 HANDSHAKE 状态，
             * 并继续向目标节点发送普通 PING 命令。
             */
            node->flags &= ~REDIS_NODE_MEET;

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

    /* Ping some random node 1 time every 10 iterations, so that we usually ping
     * one random node every second. */
    // clusterCron() 每执行 10 次（至少间隔一秒钟），就向一个随机节点发送 gossip 信息
    if (!(iteration % 10)) {
        int j;

        /* Check a few random nodes and ping the one with the oldest
         * pong_received time. */
        // 随机 5 个节点，选出其中一个
        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. */
            // 不要 PING 连接断开的节点，也不要 PING 最近已经 PING 过的节点
            if (this->link == NULL || this->ping_sent != 0) continue;

            if (this->flags & (REDIS_NODE_MYSELF|REDIS_NODE_HANDSHAKE))
                continue;

            // 选出 5 个随机节点中最近一次接收 PONG 回复距离现在最旧的节点
            if (min_pong_node == NULL || min_pong > this->pong_received) {
                min_pong_node = this;
                min_pong = this->pong_received;
            }
        }

        // 向最久没有收到 PONG 回复的节点发送 PING 命令
        if (min_pong_node) {
            redisLog(REDIS_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. */
    orphaned_masters = 0;
    max_slaves = 0;
    this_slaves = 0;
    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;

        // 跳过节点本身、无地址节点、HANDSHAKE 状态的节点
        if (node->flags &
            (REDIS_NODE_MYSELF|REDIS_NODE_NOADDR|REDIS_NODE_HANDSHAKE))
                continue;

        /* Orphaned master check, useful only if the current instance
         * is a slave that may migrate to another master. */
        if (nodeIsSlave(myself) && nodeIsMaster(node) && !nodeFailed(node)) {
            int okslaves = clusterCountNonFailingSlaves(node);

            if (okslaves == 0 && node->numslots > 0) orphaned_masters++;
            if (okslaves > max_slaves) max_slaves = okslaves;
            if (nodeIsSlave(myself) && myself->slaveof == node)
                this_slaves = okslaves;
        }

        /* 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. */
        // 如果等到 PONG 到达的时间超过了 node timeout 一半的连接
        // 因为尽管节点依然正常，但连接可能已经出问题了
        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. */
            // 释放连接，下次 clusterCron() 会自动重连
            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. */
        // 如果目前没有在 PING 节点
        // 并且已经有 node timeout 一半的时间没有从节点那里收到 PONG 回复
        // 那么向节点发送一个 PING ，确保节点的信息不会太旧
        // （因为一部分节点可能一直没有被随机中）
        if (node->link &&
            node->ping_sent == 0 &&
            (now - node->pong_received) > server.cluster_node_timeout/2)
        {
            clusterSendPing(node->link, CLUSTERMSG_TYPE_PING);
            continue;
        }

        /* If we are a master and one of the slaves requested a manual
         * failover, ping it continuously. */
        // 如果这是一个主节点，并且有一个从服务器请求进行手动故障转移
        // 那么向从服务器发送 PING 。
        if (server.cluster->mf_end &&
            nodeIsMaster(myself) &&
            server.cluster->mf_slave == node &&
            node->link)
        {
            clusterSendPing(node->link, CLUSTERMSG_TYPE_PING);
            continue;
        }

        /* Check only if we have an active ping for this instance. */
        // 以下代码只在节点发送了 PING 命令的情况下执行
        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. */
        // 计算等待 PONG 回复的时长
        delay = now - node->ping_sent;

        // 等待 PONG 回复的时长超过了限制值，将目标节点标记为 PFAIL （疑似下线）
        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 & (REDIS_NODE_PFAIL|REDIS_NODE_FAIL))) {
                redisLog(REDIS_DEBUG,"*** NODE %.40s possibly failing",
                    node->name);
                // 打开疑似下线标记
                node->flags |= REDIS_NODE_PFAIL;
                update_state = 1;
            }
        }
    }
    dictReleaseIterator(di);

    /* If we are a slave node but the replication is still turned off,
     * enable it if we know the address of our master and it appears to
     * be up. */
    // 如果从节点没有在复制主节点，那么对从节点进行设置
    if (nodeIsSlave(myself) &&
        server.masterhost == NULL &&
        myself->slaveof &&
        nodeHasAddr(myself->slaveof))
    {
        replicationSetMaster(myself->slaveof->ip, myself->slaveof->port);
    }

    /* Abourt a manual failover if the timeout is reached. */
    manualFailoverCheckTimeout();

    if (nodeIsSlave(myself)) {
        clusterHandleManualFailover();
        clusterHandleSlaveFailover();
        /* If there are orphaned slaves, and we are a slave among the masters
         * with the max number of non-failing slaves, consider migrating to
         * the orphaned masters. Note that it does not make sense to try
         * a migration if there is no master with at least *two* working
         * slaves. */
        if (orphaned_masters && max_slaves >= 2 && this_slaves == max_slaves)
            clusterHandleSlaveMigration(max_slaves);
    }

    // 更新集群状态
    if (update_state || server.cluster->state == REDIS_CLUSTER_FAIL)
        clusterUpdateState();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movl $0x0, -0x14(%rbp)
movq $0x0, -0x28(%rbp)
callq 0x252e0
movq %rax, -0x30(%rbp)
movq $0x0, -0x38(%rbp)
movq 0xb9cde(%rip), %rax     # 0x127f80
addq $0x1, %rax
movq %rax, 0xb9cd3(%rip)     # 0x127f80
leaq 0xa5644(%rip), %rax     # 0x1138f8
movq 0x7c0(%rax), %rax
movq %rax, -0x40(%rbp)
cmpq $0x3e8, -0x40(%rbp)     # imm = 0x3E8
jge 0x6e2d1
movq $0x3e8, -0x40(%rbp)     # imm = 0x3E8
leaq 0xa5620(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %rdi
callq 0x24240
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rdi
callq 0x24270
movq %rax, -0x10(%rbp)
cmpq $0x0, %rax
je 0x6e502
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x50, %eax
cmpl $0x0, %eax
je 0x6e320
jmp 0x6e2ec
movq -0x48(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x20, %eax
cmpl $0x0, %eax
je 0x6e34b
movq -0x30(%rbp), %rax
movq -0x48(%rbp), %rcx
subq (%rcx), %rax
cmpq -0x40(%rbp), %rax
jle 0x6e34b
movq -0x48(%rbp), %rdi
callq 0x6a350
jmp 0x6e2ec
movq -0x48(%rbp), %rax
cmpq $0x0, 0x8c0(%rax)
jne 0x6e4fd
movq -0x48(%rbp), %rax
addq $0x888, %rax            # imm = 0x888
movq %rax, -0x90(%rbp)
movq -0x48(%rbp), %rax
movl 0x8b8(%rax), %eax
addl $0x2710, %eax           # imm = 0x2710
movl %eax, -0x88(%rbp)
leaq 0xa556e(%rip), %rax     # 0x1138f8
cmpl $0x0, 0x110(%rax)
je 0x6e3aa
leaq 0xa555e(%rip), %rax     # 0x1138f8
movq 0x90(%rax), %rax
movq %rax, -0x98(%rbp)
jmp 0x6e3b5
xorl %eax, %eax
movq %rax, -0x98(%rbp)
jmp 0x6e3b5
movl -0x88(%rbp), %edx
movq -0x90(%rbp), %rsi
movq -0x98(%rbp), %rcx
leaq 0xa5528(%rip), %rdi     # 0x1138f8
addq $0x1e8, %rdi            # imm = 0x1E8
callq 0x222b0
movl %eax, -0x4c(%rbp)
cmpl $-0x1, -0x4c(%rbp)
jne 0x6e423
movq -0x48(%rbp), %rdx
addq $0x888, %rdx            # imm = 0x888
movq -0x48(%rbp), %rax
movl 0x8b8(%rax), %ecx
addl $0x2710, %ecx           # imm = 0x2710
xorl %edi, %edi
leaq 0x7831c(%rip), %rsi     # 0xe6725
leaq 0xa54e8(%rip), %r8      # 0x1138f8
addq $0x1e8, %r8             # imm = 0x1E8
movb $0x0, %al
callq 0x24fb0
jmp 0x6e2ec
movq -0x48(%rbp), %rdi
callq 0x69b30
movq %rax, -0x60(%rbp)
movl -0x4c(%rbp), %ecx
movq -0x60(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x60(%rbp), %rcx
movq -0x48(%rbp), %rax
movq %rcx, 0x8c0(%rax)
leaq 0xa54a8(%rip), %rax     # 0x1138f8
movq 0x28(%rax), %rdi
movq -0x60(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x60(%rbp), %r8
movl $0x1, %edx
leaq -0x481b(%rip), %rcx     # 0x69c50
callq 0x20a80
movq -0x48(%rbp), %rax
movq 0x858(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x60(%rbp), %rdi
movq -0x48(%rbp), %rax
movl 0x30(%rax), %ecx
andl $0x80, %ecx
xorl %esi, %esi
movl $0x2, %eax
cmpl $0x0, %ecx
cmovnel %eax, %esi
callq 0x6c450
cmpq $0x0, -0x58(%rbp)
je 0x6e4b8
movq -0x58(%rbp), %rcx
movq -0x48(%rbp), %rax
movq %rcx, 0x858(%rax)
movq -0x48(%rbp), %rax
movl 0x30(%rax), %ecx
andl $0xffffff7f, %ecx       # imm = 0xFFFFFF7F
movl %ecx, 0x30(%rax)
movq -0x48(%rbp), %rdx
addq $0x8, %rdx
movq -0x48(%rbp), %rcx
addq $0x888, %rcx            # imm = 0x888
movq -0x48(%rbp), %rax
movl 0x8b8(%rax), %r8d
addl $0x2710, %r8d           # imm = 0x2710
xorl %edi, %edi
leaq 0x7825f(%rip), %rsi     # 0xe6755
movb $0x0, %al
callq 0x24fb0
jmp 0x6e2ec
movq -0x8(%rbp), %rdi
callq 0x243d0
movq 0xb9a6e(%rip), %rax     # 0x127f80
movl $0xa, %ecx
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
jne 0x6e5ff
movl $0x0, -0x64(%rbp)
cmpl $0x5, -0x64(%rbp)
jge 0x6e5cc
leaq 0xa53ba(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %rdi
callq 0x24470
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
cmpq $0x0, 0x8c0(%rax)
je 0x6e57a
movq -0x70(%rbp), %rax
cmpq $0x0, 0x858(%rax)
je 0x6e57c
jmp 0x6e5be
movq -0x70(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x30, %eax
cmpl $0x0, %eax
je 0x6e58d
jmp 0x6e5be
cmpq $0x0, -0x38(%rbp)
je 0x6e5a5
movq -0x28(%rbp), %rax
movq -0x70(%rbp), %rcx
cmpq 0x860(%rcx), %rax
jle 0x6e5bc
movq -0x70(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x70(%rbp), %rax
movq 0x860(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x6e5be
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x6e52d
cmpq $0x0, -0x38(%rbp)
je 0x6e5fd
movq -0x38(%rbp), %rdx
addq $0x8, %rdx
xorl %edi, %edi
leaq 0x78195(%rip), %rsi     # 0xe6779
movb $0x0, %al
callq 0x24fb0
movq -0x38(%rbp), %rax
movq 0x8c0(%rax), %rdi
xorl %esi, %esi
callq 0x6c450
jmp 0x6e5ff
movl $0x0, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
movl $0x0, -0x20(%rbp)
leaq 0xa52dd(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %rdi
callq 0x24240
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rdi
callq 0x24270
movq %rax, -0x10(%rbp)
cmpq $0x0, %rax
je 0x6e914
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x78(%rbp)
callq 0x252e0
movq %rax, -0x30(%rbp)
movq -0x78(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x70, %eax
cmpl $0x0, %eax
je 0x6e66c
jmp 0x6e62f
movq 0xb9905(%rip), %rax     # 0x127f78
movl 0x30(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x6e717
movq -0x78(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x6e717
movq -0x78(%rbp), %rax
movl 0x30(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
jne 0x6e717
movq -0x78(%rbp), %rdi
callq 0x6a2f0
movl %eax, -0x84(%rbp)
cmpl $0x0, -0x84(%rbp)
jne 0x6e6d2
movq -0x78(%rbp), %rax
cmpl $0x0, 0x840(%rax)
jle 0x6e6d2
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movl -0x84(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jle 0x6e6e6
movl -0x84(%rbp), %eax
movl %eax, -0x1c(%rbp)
movq 0xb988b(%rip), %rax     # 0x127f78
movl 0x30(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x6e715
movq 0xb9879(%rip), %rax     # 0x127f78
movq 0x850(%rax), %rax
cmpq -0x78(%rbp), %rax
jne 0x6e715
movl -0x84(%rbp), %eax
movl %eax, -0x20(%rbp)
jmp 0x6e717
movq -0x78(%rbp), %rax
cmpq $0x0, 0x8c0(%rax)
je 0x6e7be
movq -0x30(%rbp), %rax
movq -0x78(%rbp), %rcx
movq 0x8c0(%rcx), %rcx
subq (%rcx), %rax
leaq 0xa51b6(%rip), %rcx     # 0x1138f8
cmpq 0x7c0(%rcx), %rax
jle 0x6e7be
movq -0x78(%rbp), %rax
cmpq $0x0, 0x858(%rax)
je 0x6e7be
movq -0x78(%rbp), %rax
movq 0x860(%rax), %rax
movq -0x78(%rbp), %rcx
cmpq 0x858(%rcx), %rax
jge 0x6e7be
movq -0x30(%rbp), %rax
movq -0x78(%rbp), %rcx
subq 0x858(%rcx), %rax
movq %rax, -0xa0(%rbp)
leaq 0xa516a(%rip), %rax     # 0x1138f8
movq 0x7c0(%rax), %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0xa0(%rbp), %rax
cmpq %rcx, %rax
jle 0x6e7be
movq -0x78(%rbp), %rax
movq 0x8c0(%rax), %rdi
callq 0x69ba0
movq -0x78(%rbp), %rax
cmpq $0x0, 0x8c0(%rax)
je 0x6e82e
movq -0x78(%rbp), %rax
cmpq $0x0, 0x858(%rax)
jne 0x6e82e
movq -0x30(%rbp), %rax
movq -0x78(%rbp), %rcx
subq 0x860(%rcx), %rax
movq %rax, -0xa8(%rbp)
leaq 0xa5101(%rip), %rax     # 0x1138f8
movq 0x7c0(%rax), %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0xa8(%rbp), %rax
cmpq %rcx, %rax
jle 0x6e82e
movq -0x78(%rbp), %rax
movq 0x8c0(%rax), %rdi
xorl %esi, %esi
callq 0x6c450
jmp 0x6e62f
leaq 0xa50c3(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
cmpq $0x0, 0x60050(%rax)
je 0x6e898
movq 0xb972b(%rip), %rax     # 0x127f78
movl 0x30(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x6e898
leaq 0xa5099(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
movq 0x60058(%rax), %rax
cmpq -0x78(%rbp), %rax
jne 0x6e898
movq -0x78(%rbp), %rax
cmpq $0x0, 0x8c0(%rax)
je 0x6e898
movq -0x78(%rbp), %rax
movq 0x8c0(%rax), %rdi
xorl %esi, %esi
callq 0x6c450
jmp 0x6e62f
movq -0x78(%rbp), %rax
cmpq $0x0, 0x858(%rax)
jne 0x6e8ab
jmp 0x6e62f
movq -0x30(%rbp), %rax
movq -0x78(%rbp), %rcx
subq 0x858(%rcx), %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
leaq 0xa502f(%rip), %rcx     # 0x1138f8
cmpq 0x7c0(%rcx), %rax
jle 0x6e90f
movq -0x78(%rbp), %rax
movl 0x30(%rax), %eax
andl $0xc, %eax
cmpl $0x0, %eax
jne 0x6e90d
movq -0x78(%rbp), %rdx
addq $0x8, %rdx
xorl %edi, %edi
leaq 0x77e9a(%rip), %rsi     # 0xe678c
movb $0x0, %al
callq 0x24fb0
movq -0x78(%rbp), %rax
movl 0x30(%rax), %ecx
orl $0x4, %ecx
movl %ecx, 0x30(%rax)
movl $0x1, -0x14(%rbp)
jmp 0x6e90f
jmp 0x6e62f
movq -0x8(%rbp), %rdi
callq 0x243d0
movq 0xb9654(%rip), %rax     # 0x127f78
movl 0x30(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x6e998
leaq 0xa4fc2(%rip), %rax     # 0x1138f8
cmpq $0x0, 0x650(%rax)
jne 0x6e998
movq 0xb9631(%rip), %rax     # 0x127f78
cmpq $0x0, 0x850(%rax)
je 0x6e998
movq 0xb9620(%rip), %rax     # 0x127f78
movq 0x850(%rax), %rax
movl 0x30(%rax), %eax
andl $0x40, %eax
cmpl $0x0, %eax
jne 0x6e998
movq 0xb9607(%rip), %rax     # 0x127f78
movq 0x850(%rax), %rdi
addq $0x888, %rdi            # imm = 0x888
movq 0xb95f2(%rip), %rax     # 0x127f78
movq 0x850(%rax), %rax
movl 0x8b8(%rax), %esi
callq 0x42000
callq 0x6e140
movq 0xb95d4(%rip), %rax     # 0x127f78
movl 0x30(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x6e9d7
callq 0x6e1b0
callq 0x6d640
cmpl $0x0, -0x18(%rbp)
je 0x6e9d5
cmpl $0x2, -0x1c(%rbp)
jl 0x6e9d5
movl -0x20(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jne 0x6e9d5
movl -0x1c(%rbp), %edi
callq 0x6df10
jmp 0x6e9d7
cmpl $0x0, -0x14(%rbp)
jne 0x6e9f1
leaq 0xa4f14(%rip), %rax     # 0x1138f8
movq 0x7d0(%rax), %rax
cmpl $0x1, 0x10(%rax)
jne 0x6e9f6
callq 0x6dc90
addq $0xb0, %rsp
popq %rbp
retq
nop