LLM4Binary/decompile-bench-makefile huggingface dataset:
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterSetNodeAsMaster
void clusterSetNodeAsMaster(clusterNode *n) {

    // 已经是主节点了。
    if (nodeIsMaster(n)) return;

    // 移除 slaveof
    if (n->slaveof) clusterNodeRemoveSlave(n->slaveof,n);

    // 关闭 SLAVE 标识
    n->flags &= ~REDIS_NODE_SLAVE;

    // 打开 MASTER 标识
    n->flags |= REDIS_NODE_MASTER;

    // 清零 slaveof 属性
    n->slaveof = NULL;

    /* Update config and state. */
    clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|
                         CLUSTER_TODO_UPDATE_STATE);
}

// Assembly:
movl 0x30(%rdi), %eax
testb $0x1, %al
jne 0x4c7f7
pushq %rbx
movq %rdi, %rbx
movq 0x850(%rdi), %rdi
testq %rdi, %rdi
je 0x4c7d1
movq %rbx, %rsi
callq 0x4ccfb
movl 0x30(%rbx), %eax
andl $-0x4, %eax
incl %eax
movl %eax, 0x30(%rbx)
andq $0x0, 0x850(%rbx)
leaq 0x7a7c0(%rip), %rax     # 0xc6fa8
movq 0x7d0(%rax), %rax
orl $0x6, 0x60078(%rax)
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterDelSlot
int clusterDelSlot(int slot) {

    // 获取当前处理槽 slot 的节点 n
    clusterNode *n = server.cluster->slots[slot];

    if (!n) return REDIS_ERR;

    // 清除位图
    redisAssert(clusterNodeClearSlotBit(n,slot) == 1);

    // 清空负责处理槽的节点
    server.cluster->slots[slot] = NULL;

    return REDIS_OK;
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movl %edi, %esi
leaq 0x7a7a3(%rip), %rbx     # 0xc6fa8
movq 0x7d0(%rbx), %rax
movslq %edi, %r14
movq 0x40028(%rax,%r14,8), %rdi
testq %rdi, %rdi
je 0x4c839
callq 0x4fa4f
testl %eax, %eax
je 0x4c844
movq 0x7d0(%rbx), %rax
andq $0x0, 0x40028(%rax,%r14,8)
xorl %eax, %eax
jmp 0x4c83c
pushq $-0x1
popq %rax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
leaq 0x45f39(%rip), %rdi     # 0x92784
leaq 0x4542b(%rip), %rsi     # 0x91c7d
movl $0xfaa, %edx            # imm = 0xFAA
callq 0x4906b
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterDelNode
void clusterDelNode(clusterNode *delnode) {
    int j;
    dictIterator *di;
    dictEntry *de;

    /* 1) Mark slots as unassigned. */
    for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) {
        // 取消向该节点接收槽的计划
        if (server.cluster->importing_slots_from[j] == delnode)
            server.cluster->importing_slots_from[j] = NULL;
        // 取消向该节点移交槽的计划
        if (server.cluster->migrating_slots_to[j] == delnode)
            server.cluster->migrating_slots_to[j] = NULL;
        // 将所有由该节点负责的槽设置为未分配
        if (server.cluster->slots[j] == delnode)
            clusterDelSlot(j);
    }

    /* 2) Remove failure reports. */
    // 移除所有由该节点发送的下线报告
    di = dictGetSafeIterator(server.cluster->nodes);
    while((de = dictNext(di)) != NULL) {
        clusterNode *node = dictGetVal(de);

        if (node == delnode) continue;
        clusterNodeDelFailureReport(node,delnode);
    }
    dictReleaseIterator(di);

    /* 3) Remove this node from its master's slaves if needed. */
    // 将节点从它的主节点的从节点列表中移除
    if (nodeIsSlave(delnode) && delnode->slaveof)
        clusterNodeRemoveSlave(delnode->slaveof,delnode);

    /* 4) Free the node, unlinking it from the cluster. */
    // 释放节点
    freeClusterNode(delnode);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdi, %rbx
xorl %r14d, %r14d
leaq 0x7a732(%rip), %r15     # 0xc6fa8
movq 0x7d0(%r15), %rax
cmpq $0x4000, %r14           # imm = 0x4000
je 0x4c8cb
cmpq %rbx, 0x20028(%rax,%r14,8)
jne 0x4c8a0
andq $0x0, 0x20028(%rax,%r14,8)
movq 0x7d0(%r15), %rax
cmpq %rbx, 0x28(%rax,%r14,8)
jne 0x4c8b4
andq $0x0, 0x28(%rax,%r14,8)
movq 0x7d0(%r15), %rax
cmpq %rbx, 0x40028(%rax,%r14,8)
jne 0x4c8c6
movl %r14d, %edi
callq 0x4c7f8
incq %r14
jmp 0x4c876
movq 0x18(%rax), %rdi
callq 0x21f20
movq %rax, %r14
movq %r14, %rdi
callq 0x21f2f
testq %rax, %rax
je 0x4c8f7
movq 0x8(%rax), %rdi
cmpq %rbx, %rdi
je 0x4c8d7
movq %rbx, %rsi
callq 0x4cc82
jmp 0x4c8d7
movq %r14, %rdi
callq 0x21fe6
testb $0x2, 0x30(%rbx)
je 0x4c919
movq 0x850(%rbx), %rdi
testq %rdi, %rdi
je 0x4c919
movq %rbx, %rsi
callq 0x4ccfb
movq %rbx, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x4cda2
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterNodeRemoveSlave
int clusterNodeRemoveSlave(clusterNode *master, clusterNode *slave) {
    int j;

    // 在 slaves 数组中找到从节点 slave 所属的主节点，
    // 将主节点中的 slave 信息移除
    for (j = 0; j < master->numslaves; j++) {
        if (master->slaves[j] == slave) {
            memmove(master->slaves+j,master->slaves+(j+1),
                (master->numslaves-1)-j);
            master->numslaves--;
            return REDIS_OK;
        }
    }
    return REDIS_ERR;
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
movl 0x844(%rdi), %ecx
xorl %edx, %edx
testl %ecx, %ecx
movl $0x0, %edi
cmovgl %ecx, %edi
pushq $-0x1
popq %rax
cmpq %rdx, %rdi
je 0x4cd4b
movq 0x848(%rbx), %r8
cmpq %rsi, (%r8,%rdx,8)
je 0x4cd2b
incq %rdx
jmp 0x4cd14
leaq (%r8,%rdx,8), %rdi
leaq (%r8,%rdx,8), %rsi
addq $0x8, %rsi
notl %edx
addl %ecx, %edx
movslq %edx, %rdx
callq 0x1f780
decl 0x844(%rbx)
xorl %eax, %eax
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: freeClusterNode
void freeClusterNode(clusterNode *n) {
    sds nodename;

    nodename = sdsnewlen(n->name, REDIS_CLUSTER_NAMELEN);

    // 从 nodes 表中删除节点
    redisAssert(dictDelete(server.cluster->nodes,nodename) == DICT_OK);
    sdsfree(nodename);

    // 移除从节点
    if (n->slaveof) clusterNodeRemoveSlave(n->slaveof, n);

    // 释放连接
    if (n->link) freeClusterLink(n->link);
    
    // 释放失败报告
    listRelease(n->fail_reports);

    // 释放节点结构
    zfree(n);
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
addq $0x8, %rdi
pushq $0x28
popq %rsi
callq 0x27158
movq %rax, %r14
leaq 0x7a1e9(%rip), %rax     # 0xc6fa8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %rdi
movq %r14, %rsi
callq 0x21c36
testl %eax, %eax
jne 0x4ce1e
movq %r14, %rdi
callq 0x271f7
movq 0x850(%rbx), %rdi
testq %rdi, %rdi
je 0x4cdf2
movq %rbx, %rsi
callq 0x4ccfb
movq 0x8c0(%rbx), %rdi
testq %rdi, %rdi
je 0x4ce03
callq 0x4c97b
movq 0x8c8(%rbx), %rdi
callq 0x1fdaa
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x283cd
leaq 0x451ab(%rip), %rdi     # 0x91fd0
leaq 0x44e51(%rip), %rsi     # 0x91c7d
movl $0x3cb, %edx            # imm = 0x3CB
callq 0x4906b
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterRenameNode
void clusterRenameNode(clusterNode *node, char *newname) {
    int retval;
    sds s = sdsnewlen(node->name, REDIS_CLUSTER_NAMELEN);

    redisLog(REDIS_DEBUG,"Renaming node %.40s into %.40s",
        node->name, newname);
    retval = dictDelete(server.cluster->nodes, s);
    sdsfree(s);
    redisAssert(retval == DICT_OK);
    memcpy(node->name, newname, REDIS_CLUSTER_NAMELEN);
    clusterAddNode(node);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movq %rsi, %r15
movq %rdi, %rbx
leaq 0x8(%rdi), %r14
pushq $0x28
popq %rsi
movq %r14, %rdi
callq 0x27158
movq %rax, %r12
leaq 0x451a1(%rip), %rsi     # 0x92006
xorl %edi, %edi
movq %r14, %rdx
movq %r15, %rcx
xorl %eax, %eax
callq 0x22613
leaq 0x7a12d(%rip), %rax     # 0xc6fa8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %rdi
movq %r12, %rsi
callq 0x21c36
movl %eax, %ebp
movq %r12, %rdi
callq 0x271f7
testl %ebp, %ebp
jne 0x4cec6
movq 0x20(%r15), %rax
movq %rax, 0x20(%r14)
movups (%r15), %xmm0
movups 0x10(%r15), %xmm1
movups %xmm1, 0x10(%r14)
movups %xmm0, (%r14)
movq %rbx, %rdi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x4bf5b
leaq 0x4194d(%rip), %rdi     # 0x8e81a
leaq 0x44da9(%rip), %rsi     # 0x91c7d
movl $0x43b, %edx            # imm = 0x43B
callq 0x4906b
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterBlacklistAddNode
void clusterBlacklistAddNode(clusterNode *node) {
    dictEntry *de;
    sds id = sdsnewlen(node->name,REDIS_CLUSTER_NAMELEN);

    // 先清理过期名单
    clusterBlacklistCleanup();

    // 添加节点
    if (dictAdd(server.cluster->nodes_black_list,id,NULL) == DICT_OK) {
        /* If the key was added, duplicate the sds string representation of
         * the key for the next lookup. We'll free it at the end. */
        id = sdsdup(id);
    }
    // 设置过期时间
    de = dictFind(server.cluster->nodes_black_list,id);
    dictSetUnsignedIntegerVal(de,time(NULL)+REDIS_CLUSTER_BLACKLIST_TTL);
    sdsfree(id);
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
addq $0x8, %rdi
pushq $0x28
popq %rsi
callq 0x27158
movq %rax, %rbx
callq 0x4cee6
leaq 0x7a047(%rip), %r14     # 0xc6fa8
movq 0x7d0(%r14), %rax
movq 0x20(%rax), %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x21956
testl %eax, %eax
jne 0x4cf85
movq %rbx, %rdi
callq 0x271ee
movq %rax, %rbx
movq 0x7d0(%r14), %rax
movq 0x20(%rax), %rdi
movq %rbx, %rsi
callq 0x21b64
movq %rax, %r14
xorl %edi, %edi
callq 0x1fc50
addq $0x3c, %rax
movq %rax, 0x8(%r14)
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x271f7
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterBlacklistExists
int clusterBlacklistExists(char *nodeid) {

    // 构建 SDS 表示的节点名
    sds id = sdsnewlen(nodeid,REDIS_CLUSTER_NAMELEN);
    int retval;

    // 清除过期黑名单
    clusterBlacklistCleanup();

    // 检查节点是否存在
    retval = dictFind(server.cluster->nodes_black_list,id) != NULL;
    sdsfree(id);

    return retval;
}

// Assembly:
pushq %rbp
pushq %rbx
pushq %rax
pushq $0x28
popq %rsi
callq 0x27158
movq %rax, %rbx
callq 0x4cee6
leaq 0x79fd5(%rip), %rax     # 0xc6fa8
movq 0x7d0(%rax), %rax
movq 0x20(%rax), %rdi
movq %rbx, %rsi
callq 0x21b64
xorl %ebp, %ebp
testq %rax, %rax
setne %bpl
movq %rbx, %rdi
callq 0x271f7
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: markNodeAsFailingIfNeeded
void markNodeAsFailingIfNeeded(clusterNode *node) {
    int failures;

    // 标记为 FAIL 所需的节点数量，需要超过集群节点数量的一半
    int needed_quorum = (server.cluster->size / 2) + 1;

    if (!nodeTimedOut(node)) return; /* We can reach it. */
    if (nodeFailed(node)) return; /* Already FAILing. */

    // 统计将 node 标记为 PFAIL 或者 FAIL 的节点数量（不包括当前节点）
    failures = clusterNodeFailureReportsCount(node);

    /* Also count myself as a voter if I'm a master. */
    // 如果当前节点是主节点，那么将当前节点也算在 failures 之内
    if (nodeIsMaster(myself)) failures++;
    // 报告下线节点的数量不足节点总数的一半，不能将节点判断为 FAIL ，返回
    if (failures < needed_quorum) return; /* No weak agreement from masters. */

    redisLog(REDIS_NOTICE,
        "Marking node %.40s as failing (quorum reached).", node->name);

    /* Mark the node as failing. */
    // 将 node 标记为 FAIL
    node->flags &= ~REDIS_NODE_PFAIL;
    node->flags |= REDIS_NODE_FAIL;
    node->fail_time = mstime();

    /* Broadcast the failing node name to everybody, forcing all the other
     * reachable nodes to flag the node as FAIL. */
    // 如果当前节点是主节点的话，那么向其他节点发送报告 node 的 FAIL 信息
    // 让其他节点也将 node 标记为 FAIL
    if (nodeIsMaster(myself)) clusterSendFail(node->name);
    clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);
}

// Assembly:
movl 0x30(%rdi), %eax
andl $0xc, %eax
cmpl $0x4, %eax
jne 0x4d0a7
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
leaq 0x79f88(%rip), %r15     # 0xc6fa8
movq 0x7d0(%r15), %rax
movl 0x14(%rax), %eax
pushq $0x2
popq %rcx
cltd
idivl %ecx
movl %eax, %ebp
callq 0x4cce6
movq 0x8e5ea(%rip), %rcx     # 0xdb628
movl 0x30(%rcx), %ecx
andl $0x1, %ecx
addl %eax, %ecx
cmpl %ebp, %ecx
jle 0x4d09d
leaq 0x8(%rbx), %r14
leaq 0x44fd0(%rip), %rsi     # 0x92025
pushq $0x2
popq %rdi
movq %r14, %rdx
xorl %eax, %eax
callq 0x22613
movl 0x30(%rbx), %eax
andl $-0xd, %eax
orl $0x8, %eax
movl %eax, 0x30(%rbx)
callq 0x22843
movq %rax, 0x868(%rbx)
movq 0x8e5a7(%rip), %rax     # 0xdb628
testb $0x1, 0x30(%rax)
je 0x4d08f
movq %r14, %rdi
callq 0x4d0a8
movq 0x7d0(%r15), %rax
orl $0x6, 0x60078(%rax)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterSendFail
void clusterSendFail(char *nodename) {
    unsigned char buf[sizeof(clusterMsg)];
    clusterMsg *hdr = (clusterMsg*) buf;

    // 创建下线消息
    clusterBuildMessageHdr(hdr,CLUSTERMSG_TYPE_FAIL);

    // 记录命令
    memcpy(hdr->data.fail.about.nodename,nodename,REDIS_CLUSTER_NAMELEN);

    // 广播消息
    clusterBroadcastMessage(buf,ntohl(hdr->totlen));
}

// Assembly:
pushq %r14
pushq %rbx
subq $0x10d8, %rsp           # imm = 0x10D8
movq %rdi, %rbx
movq %rsp, %r14
pushq $0x3
popq %rsi
movq %r14, %rdi
callq 0x4e8b1
movq 0x20(%rbx), %rax
movq %rax, 0x8c0(%r14)
movups (%rbx), %xmm0
movups 0x10(%rbx), %xmm1
movaps %xmm1, 0x8b0(%r14)
movaps %xmm0, 0x8a0(%r14)
movl 0x4(%r14), %esi
bswapl %esi
movq %r14, %rdi
callq 0x4e84f
addq $0x10d8, %rsp           # imm = 0x10D8
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clearNodeFailureIfNeeded
void clearNodeFailureIfNeeded(clusterNode *node) {
    mstime_t now = mstime();

    redisAssert(nodeFailed(node));

    /* For slaves we always clear the FAIL flag if we can contact the
     * node again. */
    // 如果 FAIL 的是从节点，那么当前节点会直接移除该节点的 FAIL
    if (nodeIsSlave(node) || node->numslots == 0) {
        redisLog(REDIS_NOTICE,
            "Clear FAIL state for node %.40s: %s is reachable again.",
                node->name,
                nodeIsSlave(node) ? "slave" : "master without slots");
        // 移除
        node->flags &= ~REDIS_NODE_FAIL;

        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);
    }

    /* If it is a master and...
     *
     * 如果 FAIL 的是一个主节点，并且：
     *
     * 1) The FAIL state is old enough.
     *    节点被标记为 FAIL 状态已经有一段时间了
     *
     * 2) It is yet serving slots from our point of view (not failed over).
     *    从当前节点的视角来看，这个节点还有负责处理的槽
     *
     * Apparently no one is going to fix these slots, clear the FAIL flag. 
     *
     * 那么说明 FAIL 节点仍然有槽没有迁移完，那么当前节点移除该节点的 FAIL 标识。
     */
    if (nodeIsMaster(node) && node->numslots > 0 &&
        (now - node->fail_time) >
        (server.cluster_node_timeout * REDIS_CLUSTER_FAIL_UNDO_TIME_MULT))
    {
        redisLog(REDIS_NOTICE,
            "Clear FAIL state for node %.40s: is reachable again and nobody is serving its slots after some time.",
                node->name);

        // 撤销 FAIL 状态
        node->flags &= ~REDIS_NODE_FAIL;

        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdi, %rbx
callq 0x22843
movq %rax, %r14
movl 0x30(%rbx), %eax
testb $0x8, %al
je 0x4d1c0
testb $0x2, %al
jne 0x4d12f
cmpl $0x0, 0x840(%rbx)
jne 0x4d169
leaq 0x44f71(%rip), %rcx     # 0x9209e
jmp 0x4d136
leaq 0x45d04(%rip), %rcx     # 0x92e3a
leaq 0x8(%rbx), %rdx
leaq 0x44f25(%rip), %rsi     # 0x92066
pushq $0x2
popq %rdi
xorl %eax, %eax
callq 0x22613
movl 0x30(%rbx), %eax
andl $-0x9, %eax
movl %eax, 0x30(%rbx)
leaq 0x79e4d(%rip), %rcx     # 0xc6fa8
movq 0x7d0(%rcx), %rcx
orl $0x6, 0x60078(%rcx)
testb $0x1, %al
je 0x4d1ba
cmpl $0x0, 0x840(%rbx)
jle 0x4d1ba
subq 0x868(%rbx), %r14
leaq 0x79e24(%rip), %r15     # 0xc6fa8
movq 0x7c0(%r15), %rax
addq %rax, %rax
cmpq %rax, %r14
jle 0x4d1ba
leaq 0x8(%rbx), %rdx
leaq 0x44f15(%rip), %rsi     # 0x920b3
pushq $0x2
popq %rdi
xorl %eax, %eax
callq 0x22613
andb $-0x9, 0x30(%rbx)
movq 0x7d0(%r15), %rax
orl $0x6, 0x60078(%rax)
popq %rbx
popq %r14
popq %r15
retq
leaq 0x44e8e(%rip), %rdi     # 0x92055
leaq 0x44aaf(%rip), %rsi     # 0x91c7d
movl $0x511, %edx            # imm = 0x511
callq 0x4906b
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterStartHandshake
int clusterStartHandshake(char *ip, int port) {
    clusterNode *n;
    char norm_ip[REDIS_IP_STR_LEN];
    struct sockaddr_storage sa;

    /* IP sanity check */
    // ip 合法性检查
    if (inet_pton(AF_INET,ip,
            &(((struct sockaddr_in *)&sa)->sin_addr)))
    {
        sa.ss_family = AF_INET;
    } else if (inet_pton(AF_INET6,ip,
            &(((struct sockaddr_in6 *)&sa)->sin6_addr)))
    {
        sa.ss_family = AF_INET6;
    } else {
        errno = EINVAL;
        return 0;
    }

    /* Port sanity check */
    // port 合法性检查
    if (port <= 0 || port > (65535-REDIS_CLUSTER_PORT_INCR)) {
        errno = EINVAL;
        return 0;
    }

    /* Set norm_ip as the normalized string representation of the node
     * IP address. */
    if (sa.ss_family == AF_INET)
        inet_ntop(AF_INET,
            (void*)&(((struct sockaddr_in *)&sa)->sin_addr),
            norm_ip,REDIS_IP_STR_LEN);
    else
        inet_ntop(AF_INET6,
            (void*)&(((struct sockaddr_in6 *)&sa)->sin6_addr),
            norm_ip,REDIS_IP_STR_LEN);

    // 检查节点是否已经发送握手请求，如果是的话，那么直接返回，防止出现重复握手
    if (clusterHandshakeInProgress(norm_ip,port)) {
        errno = EAGAIN;
        return 0;
    }

    /* Add the node with a random address (NULL as first argument to
     * createClusterNode()). Everything will be fixed during the
     * handskake. */
    // 对给定地址的节点设置一个随机名字
    // 当 HANDSHAKE 完成时，当前节点会取得给定地址节点的真正名字
    // 到时会用真名替换随机名
    n = createClusterNode(NULL,REDIS_NODE_HANDSHAKE|REDIS_NODE_MEET);
    memcpy(n->ip,norm_ip,sizeof(n->ip));
    n->port = port;

    // 将节点添加到集群当中
    clusterAddNode(n);

    return 1;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0xb0, %rsp
movl %esi, %ebx
movq %rdi, %r15
leaq 0x34(%rsp), %r14
pushq $0x2
popq %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x1f150
testl %eax, %eax
je 0x4d2a5
movw $0x2, 0x30(%rsp)
movl $0xffff2710, %eax       # imm = 0xFFFF2710
leal (%rbx,%rax), %ecx
cmpl %eax, %ecx
jbe 0x4d2cd
pushq $0x2
popq %rdi
movq %rsp, %rdx
pushq $0x2e
popq %rcx
movq %r14, %rsi
jmp 0x4d2e8
leaq 0x38(%rsp), %rdx
pushq $0xa
popq %rdi
movq %r15, %rsi
callq 0x1f150
testl %eax, %eax
je 0x4d2cd
movw $0xa, 0x30(%rsp)
leal -0xd8f0(%rbx), %eax
cmpl $0xffff2711, %eax       # imm = 0xFFFF2711
jae 0x4d2da
callq 0x1f810
movl $0x16, (%rax)
jmp 0x4d306
leaq 0x38(%rsp), %rsi
pushq $0xa
popq %rdi
movq %rsp, %rdx
pushq $0x2e
popq %rcx
callq 0x1fbc0
movq %rsp, %rdi
movl %ebx, %esi
callq 0x4d1e0
testl %eax, %eax
je 0x4d315
callq 0x1f810
movl $0xb, (%rax)
xorl %eax, %eax
addq $0xb0, %rsp
popq %rbx
popq %r14
popq %r15
retq
xorl %edi, %edi
movl $0xa0, %esi
callq 0x4be9f
movaps (%rsp), %xmm0
movaps 0x10(%rsp), %xmm1
movups %xmm0, 0x888(%rax)
movups %xmm1, 0x898(%rax)
movups 0x1e(%rsp), %xmm0
movups %xmm0, 0x8a6(%rax)
movl %ebx, 0x8b8(%rax)
movq %rax, %rdi
callq 0x4bf5b
pushq $0x1
popq %rax
jmp 0x4d308
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: nodeUpdateAddressIfNeeded
int nodeUpdateAddressIfNeeded(clusterNode *node, clusterLink *link, int port) {
    char ip[REDIS_IP_STR_LEN];

    /* We don't proceed if the link is the same as the sender link, as this
     * function is designed to see if the node link is consistent with the
     * symmetric link that is used to receive PINGs from the node.
     *
     * As a side effect this function never frees the passed 'link', so
     * it is safe to call during packet processing. */
    // 连接不变，直接返回
    if (link == node->link) return 0;

    // 获取字符串格式的 ip 地址
    nodeIp2String(ip,link);
    // 获取端口号
    if (node->port == port && strcmp(ip,node->ip) == 0) return 0;

    /* IP / port is different, update it. */
    memcpy(node->ip,ip,sizeof(ip));
    node->port = port;

    // 释放旧连接（新连接会在之后自动创建）
    if (node->link) freeClusterLink(node->link);

    redisLog(REDIS_WARNING,"Address updated for node %.40s, now %s:%d",
        node->name, node->ip, node->port);

    /* Check if this is our master and we have to change the
     * replication target as well. */
    // 如果连接来自当前节点（从节点）的主节点，那么根据新地址设置复制对象
    if (nodeIsSlave(myself) && myself->slaveof == node)
        replicationSetMaster(node->ip, node->port);
    return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x38, %rsp
xorl %r14d, %r14d
cmpq %rsi, 0x8c0(%rdi)
je 0x4d6ad
movl %edx, %ebp
movq %rdi, %rbx
movq %rsp, %rdi
callq 0x4d5ca
cmpl %ebp, 0x8b8(%rbx)
jne 0x4d623
leaq 0x888(%rbx), %rsi
movq %rsp, %rdi
callq 0x1f880
testl %eax, %eax
je 0x4d6ad
leaq 0x888(%rbx), %r15
movups 0x1e(%rsp), %xmm0
movups %xmm0, 0x8a6(%rbx)
movaps (%rsp), %xmm0
movaps 0x10(%rsp), %xmm1
movups %xmm1, 0x898(%rbx)
movups %xmm0, 0x888(%rbx)
movl %ebp, 0x8b8(%rbx)
movq 0x8c0(%rbx), %rdi
testq %rdi, %rdi
je 0x4d66a
callq 0x4c97b
movl 0x8b8(%rbx), %ebp
leaq 0x8(%rbx), %rdx
leaq 0x44b59(%rip), %rsi     # 0x921ce
pushq $0x3
popq %rdi
movq %r15, %rcx
movl %ebp, %r8d
xorl %eax, %eax
callq 0x22613
movq 0x8df9c(%rip), %rax     # 0xdb628
pushq $0x1
popq %r14
testb $0x2, 0x30(%rax)
je 0x4d6ad
cmpq %rbx, 0x850(%rax)
jne 0x4d6ad
movl 0x8b8(%rbx), %esi
movq %r15, %rdi
callq 0x334df
movl %r14d, %eax
addq $0x38, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterSetMaster
void clusterSetMaster(clusterNode *n) {
    redisAssert(n != myself);
    redisAssert(myself->numslots == 0);

    if (nodeIsMaster(myself)) {
        myself->flags &= ~REDIS_NODE_MASTER;
        myself->flags |= REDIS_NODE_SLAVE;
        clusterCloseAllSlots();
    } else {
        if (myself->slaveof)
            clusterNodeRemoveSlave(myself->slaveof,myself);
    }

    // 将 slaveof 属性指向主节点
    myself->slaveof = n;

    // 设置主节点的 IP 和地址，开始对它进行复制
    clusterNodeAddSlave(n,myself);
    replicationSetMaster(n->ip, n->port);
    resetManualFailover();
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq 0x8dda3(%rip), %r14     # 0xdb628
cmpq %rdi, %r14
je 0x4d935
cmpl $0x0, 0x840(%r14)
jne 0x4d94a
movq %rdi, %rbx
movl 0x30(%r14), %eax
testb $0x1, %al
jne 0x4d8c4
movq 0x850(%r14), %rdi
testq %rdi, %rdi
je 0x4d904
movq %r14, %rsi
callq 0x4ccfb
movq 0x8dd66(%rip), %r14     # 0xdb628
jmp 0x4d904
andl $-0x4, %eax
orl $0x2, %eax
movl %eax, 0x30(%r14)
leaq 0x796d3(%rip), %r15     # 0xc6fa8
movq 0x7d0(%r15), %rdi
addq $0x28, %rdi
movl $0x20000, %edx          # imm = 0x20000
xorl %esi, %esi
callq 0x1f110
movl $0x20028, %edi          # imm = 0x20028
addq 0x7d0(%r15), %rdi
movl $0x20000, %edx          # imm = 0x20000
xorl %esi, %esi
callq 0x1f110
movq %rbx, 0x850(%r14)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x4bf9e
movl 0x8b8(%rbx), %esi
addq $0x888, %rbx            # imm = 0x888
movq %rbx, %rdi
callq 0x334df
popq %rbx
popq %r14
popq %r15
jmp 0x4c634
leaq 0x44f36(%rip), %rdi     # 0x92872
leaq 0x4433a(%rip), %rsi     # 0x91c7d
movl $0x109a, %edx           # imm = 0x109A
jmp 0x4d95d
leaq 0x44f2d(%rip), %rdi     # 0x9287e
leaq 0x44325(%rip), %rsi     # 0x91c7d
movl $0x109b, %edx           # imm = 0x109B
callq 0x4906b
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterHandleConfigEpochCollision
void clusterHandleConfigEpochCollision(clusterNode *sender) {
    /* Prerequisites: nodes have the same configEpoch and are both masters. */
    if (sender->configEpoch != myself->configEpoch ||
        !nodeIsMaster(sender) || !nodeIsMaster(myself)) return;
    /* Don't act if the colliding node has a smaller Node ID. */
    if (memcmp(sender->name,myself->name,REDIS_CLUSTER_NAMELEN) <= 0) return;
    /* Get the next ID available at the best of this node knowledge. */
    server.cluster->currentEpoch++;
    myself->configEpoch = server.cluster->currentEpoch;
    clusterSaveConfigOrDie(1);
    redisLog(REDIS_VERBOSE,
        "WARNING: configEpoch collision with node %.40s."
        " Updating my configEpoch to %llu",
        sender->name,
        (unsigned long long) myself->configEpoch);
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
movq 0x38(%rdi), %rax
movq 0x8dcaf(%rip), %r14     # 0xdb628
cmpq 0x38(%r14), %rax
jne 0x4d9a6
movq %rdi, %rbx
testb $0x1, 0x30(%rdi)
je 0x4d9a6
testb $0x1, 0x30(%r14)
je 0x4d9a6
addq $0x8, %rbx
leaq 0x8(%r14), %rsi
pushq $0x28
popq %rdx
movq %rbx, %rdi
callq 0x1f940
testl %eax, %eax
jg 0x4d9ab
popq %rbx
popq %r14
popq %rbp
retq
leaq 0x795f6(%rip), %rax     # 0xc6fa8
movq 0x7d0(%rax), %rax
movq 0x8(%rax), %rcx
incq %rcx
movq %rcx, 0x8(%rax)
movq %rcx, 0x38(%r14)
pushq $0x1
popq %rbp
movl %ebp, %edi
callq 0x4c218
movq 0x8dc4f(%rip), %rax     # 0xdb628
movq 0x38(%rax), %rcx
leaq 0x44886(%rip), %rsi     # 0x9226a
movl %ebp, %edi
movq %rbx, %rdx
xorl %eax, %eax
popq %rbx
popq %r14
popq %rbp
jmp 0x22613
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterDelNodeSlots
int clusterDelNodeSlots(clusterNode *node) {
    int deleted = 0, j;

    for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) {
        // 如果这个槽由该节点负责，那么删除它
        if (clusterNodeGetSlotBit(node,j)) clusterDelSlot(j);
        deleted++;
    }
    return deleted;
}

// Assembly:
pushq %rbp
pushq %rbx
pushq %rax
movq %rdi, %rbx
xorl %ebp, %ebp
cmpl $0x4000, %ebp           # imm = 0x4000
je 0x4e594
movl %ebp, %eax
shrl $0x3, %eax
movzbl 0x40(%rbx,%rax), %eax
movl %ebp, %ecx
andl $0x7, %ecx
btl %ecx, %eax
jae 0x4e590
movl %ebp, %edi
callq 0x4c7f8
incl %ebp
jmp 0x4e56d
movl $0x4000, %eax           # imm = 0x4000
addq $0x8, %rsp
popq %rbx
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterWriteHandler
void clusterWriteHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
    clusterLink *link = (clusterLink*) privdata;
    ssize_t nwritten;
    REDIS_NOTUSED(el);
    REDIS_NOTUSED(mask);

    // 写入信息
    nwritten = write(fd, link->sndbuf, sdslen(link->sndbuf));

    // 写入错误
    if (nwritten <= 0) {
        redisLog(REDIS_DEBUG,"I/O error writing to node link: %s",
            strerror(errno));
        handleLinkIOError(link);
        return;
    }

    // 删除已写入的部分
    sdsrange(link->sndbuf,nwritten,-1);

    // 如果所有当前节点输出缓冲区里面的所有内容都已经写入完毕
    // （缓冲区为空）
    // 那么删除写事件处理器
    if (sdslen(link->sndbuf) == 0)
        aeDeleteFileEvent(server.el, link->fd, AE_WRITABLE);
}

// Assembly:
pushq %rbx
movq %rdx, %rbx
movl %esi, %edi
movq 0x10(%rdx), %rsi
movslq -0x8(%rsi), %rdx
callq 0x1fb30
testq %rax, %rax
jle 0x4e7a5
movq 0x10(%rbx), %rdi
pushq $-0x1
popq %rdx
movl %eax, %esi
callq 0x27a3e
movq 0x10(%rbx), %rax
cmpl $0x0, -0x8(%rax)
je 0x4e7cd
popq %rbx
retq
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x43d37(%rip), %rsi     # 0x924ef
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0x22613
movq %rbx, %rdi
popq %rbx
jmp 0x4c97b
leaq 0x787d4(%rip), %rax     # 0xc6fa8
movq 0x28(%rax), %rdi
movl 0x8(%rbx), %esi
pushq $0x2
popq %rdx
popq %rbx
jmp 0x203cd
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterBroadcastMessage
void clusterBroadcastMessage(void *buf, size_t len) {
    dictIterator *di;
    dictEntry *de;

    // 遍历所有已知节点
    di = dictGetSafeIterator(server.cluster->nodes);
    while((de = dictNext(di)) != NULL) {
        clusterNode *node = dictGetVal(de);

        // 不向未连接节点发送信息
        if (!node->link) continue;

        // 不向节点自身或者 HANDSHAKE 状态的节点发送信息
        if (node->flags & (REDIS_NODE_MYSELF|REDIS_NODE_HANDSHAKE))
            continue;

        // 发送信息
        clusterSendMessage(node->link,buf,len);
    }
    dictReleaseIterator(di);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x78747(%rip), %rax     # 0xc6fa8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %rdi
callq 0x21f20
movq %rax, %r15
movq %r15, %rdi
callq 0x21f2f
testq %rax, %rax
je 0x4e8a4
movq 0x8(%rax), %rax
movq 0x8c0(%rax), %rdi
testq %rdi, %rdi
je 0x4e874
testb $0x30, 0x30(%rax)
jne 0x4e874
movq %r14, %rsi
movq %rbx, %rdx
callq 0x4e7e4
jmp 0x4e874
movq %r15, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x21fe6
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterHandleManualFailover
void clusterHandleManualFailover(void) {
    /* Return ASAP if no manual failover is in progress. */
    if (server.cluster->mf_end == 0) return;

    /* If mf_can_start is non-zero, the failover was alrady triggered so the
     * next steps are performed by clusterHandleSlaveFailover(). */
    if (server.cluster->mf_can_start) return;

    if (server.cluster->mf_master_offset == 0) return; /* Wait for offset... */

    if (server.cluster->mf_master_offset == replicationGetSlaveOffset()) {
        /* Our replication offset matches the master replication offset
         * announced after clients were paused. We can start the failover. */
        server.cluster->mf_can_start = 1;
        redisLog(REDIS_WARNING,
            "All master replication stream processed, "
            "manual failover can start.");
    }
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
leaq 0x77b81(%rip), %rbx     # 0xc6fa8
movq 0x7d0(%rbx), %rax
cmpq $0x0, 0x60050(%rax)
je 0x4f441
cmpl $0x0, 0x60068(%rax)
je 0x4f449
addq $0x8, %rsp
popq %rbx
popq %r14
retq
movq 0x60060(%rax), %r14
testq %r14, %r14
je 0x4f441
callq 0x33b20
cmpq %rax, %r14
jne 0x4f441
movq 0x7d0(%rbx), %rax
movl $0x1, 0x60068(%rax)
leaq 0x43242(%rip), %rsi     # 0x926b9
pushq $0x3
popq %rdi
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x22613
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterNodeSetSlotBit
int clusterNodeSetSlotBit(clusterNode *n, int slot) {
    int old = bitmapTestBit(n->slots,slot);
    bitmapSetBit(n->slots,slot);
    if (!old) n->numslots++;
    return old;
}

// Assembly:
pushq $0x8
popq %rcx
movl %esi, %eax
cltd
idivl %ecx
movslq %eax, %rcx
movzbl 0x40(%rdi,%rcx), %edx
andb $0x7, %sil
movl %edx, %r8d
btsl %esi, %r8d
movzbl %sil, %esi
xorl %eax, %eax
btl %esi, %edx
setb %al
movb %r8b, 0x40(%rdi,%rcx)
jb 0x4fa4e
incl 0x840(%rdi)
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: createDumpPayload
void createDumpPayload(rio *payload, robj *o) {
    unsigned char buf[2];
    uint64_t crc;

    /* Serialize the object in a RDB-like format. It consist of an object type
     * byte followed by the serialized object. This is understood by RESTORE. */
    // 将对象序列化为一个 RDB 格式对象
    // 序列化对象以对象类型为首，后跟序列化后的对象
    // 如图
    //
    // |<-- RDB payload  -->|
    //      序列化数据
    // +-------------+------+
    // | 1 byte type | obj  |
    // +-------------+------+
    rioInitWithBuffer(payload,sdsempty());
    redisAssert(rdbSaveObjectType(payload,o));
    redisAssert(rdbSaveObject(payload,o));

    /* Write the footer, this is how it looks like:
     * ----------------+---------------------+---------------+
     * ... RDB payload | 2 bytes RDB version | 8 bytes CRC64 |
     * ----------------+---------------------+---------------+
     * RDB version and CRC are both in little endian.
     */

    /* RDB version */
    // 写入 RDB 版本
    buf[0] = REDIS_RDB_VERSION & 0xff;
    buf[1] = (REDIS_RDB_VERSION >> 8) & 0xff;
    payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,buf,2);

    /* CRC64 */
    // 写入 CRC 校验和
    crc = crc64(0,(unsigned char*)payload->io.buffer.ptr,
                sdslen(payload->io.buffer.ptr));
    memrev64ifbe(&crc);
    payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,&crc,8);

    // 整个数据的结构:
    //
    // | <--- 序列化数据 -->|
    // +-------------+------+---------------------+---------------+
    // | 1 byte type | obj  | 2 bytes RDB version | 8 bytes CRC64 |
    // +-------------+------+---------------------+---------------+

}

// Assembly:
pushq %r14
pushq %rbx
subq $0x18, %rsp
movq %rsi, %r14
movq %rdi, %rbx
callq 0x271bf
movq %rbx, %rdi
movq %rax, %rsi
callq 0x5421f
movq %rbx, %rdi
movq %r14, %rsi
callq 0x34810
testl %eax, %eax
je 0x50cb3
movq %rbx, %rdi
movq %r14, %rsi
callq 0x34922
testl %eax, %eax
je 0x50cc8
leaq 0xe(%rsp), %rsi
movw $0x6, (%rsi)
movq 0x38(%rbx), %rdi
pushq $0x2
popq %rdx
callq 0x2736d
movq %rax, 0x38(%rbx)
movslq -0x8(%rax), %rdx
xorl %edi, %edi
movq %rax, %rsi
callq 0x54c94
leaq 0x10(%rsp), %rsi
movq %rax, (%rsi)
movq 0x38(%rbx), %rdi
pushq $0x8
popq %rdx
callq 0x2736d
movq %rax, 0x38(%rbx)
addq $0x18, %rsp
popq %rbx
popq %r14
retq
leaq 0x42319(%rip), %rdi     # 0x92fd3
leaq 0x40fbc(%rip), %rsi     # 0x91c7d
movl $0x13ab, %edx           # imm = 0x13AB
jmp 0x50cdb
leaq 0x42321(%rip), %rdi     # 0x92ff0
leaq 0x40fa7(%rip), %rsi     # 0x91c7d
movl $0x13ac, %edx           # imm = 0x13AC
callq 0x4906b
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: dumpCommand
void dumpCommand(redisClient *c) {
    robj *o, *dumpobj;
    rio payload;

    /* Check if the key is here. */
    // 取出给定键的值
    if ((o = lookupKeyRead(c->db,c->argv[1])) == NULL) {
        addReply(c,shared.nullbulk);
        return;
    }

    /* Create the DUMP encoded representation. */
    // 创建给定值的一个 DUMP 编码表示
    createDumpPayload(&payload,o);

    /* Transfer to the client */
    // 将编码后的键值对数据返回给客户端
    dumpobj = createObject(REDIS_STRING,payload.io.buffer.ptr);
    addReplyBulk(c,dumpobj);
    decrRefCount(dumpobj);

    return;
}

// Assembly:
pushq %r14
pushq %rbx
subq $0x58, %rsp
movq %rdi, %rbx
movq 0x8(%rdi), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x2f89e
testq %rax, %rax
je 0x50d85
leaq 0x8(%rsp), %r14
movq %r14, %rdi
movq %rax, %rsi
callq 0x50c30
movq 0x38(%r14), %rsi
xorl %edi, %edi
callq 0x2e9b4
movq %rax, %r14
movq %rbx, %rdi
movq %rax, %rsi
callq 0x2c84a
movq %r14, %rdi
callq 0x2ee1f
addq $0x58, %rsp
popq %rbx
popq %r14
retq
leaq 0x76a74(%rip), %rax     # 0xc7800
movq 0x50(%rax), %rsi
movq %rbx, %rdi
addq $0x58, %rsp
popq %rbx
popq %r14
jmp 0x2c10d
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: readonlyCommand
void readonlyCommand(redisClient *c) {
    if (server.cluster_enabled == 0) {
        addReplyError(c,"This instance has cluster support disabled");
        return;
    }
    c->flags |= REDIS_READONLY;
    addReply(c,shared.ok);
}

// Assembly:
leaq 0x75704(%rip), %rax     # 0xc6fa8
cmpl $0x0, 0x7bc(%rax)
je 0x518c4
orb $0x2, 0x92(%rdi)
leaq 0x75f45(%rip), %rax     # 0xc7800
movq 0x8(%rax), %rsi
jmp 0x2c10d
leaq 0x4103f(%rip), %rsi     # 0x9290a
jmp 0x2c2da
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/scripting.c
// Function: luaPushError
void luaPushError(lua_State *lua, char *error) {
    lua_Debug dbg;

    lua_newtable(lua);
    lua_pushstring(lua,"err");

    /* Attempt to figure out where this function was called, if possible */
    if(lua_getstack(lua, 1, &dbg) && lua_getinfo(lua, "nSl", &dbg)) {
        sds msg = sdscatprintf(sdsempty(), "%s: %d: %s",
            dbg.source, dbg.currentline, error);
        lua_pushstring(lua, msg);
        sdsfree(msg);
    } else {
        lua_pushstring(lua, error);
    }
    lua_settable(lua,-3);
}

// Assembly:
pushq %r14
pushq %rbx
subq $0x78, %rsp
movq %rsi, %r14
movq %rdi, %rbx
xorl %esi, %esi
xorl %edx, %edx
callq 0x610a7
leaq 0x395b0(%rip), %rsi     # 0x8b92d
movq %rbx, %rdi
callq 0x60db8
pushq $0x1
popq %rsi
movq %rsp, %rdx
movq %rbx, %rdi
callq 0x61947
testl %eax, %eax
je 0x523e7
leaq 0x4126a(%rip), %rsi     # 0x93608
movq %rsp, %rdx
movq %rbx, %rdi
callq 0x61ab4
testl %eax, %eax
je 0x523e7
callq 0x271bf
movq 0x20(%rsp), %rdx
movl 0x28(%rsp), %ecx
leaq 0x4124a(%rip), %rsi     # 0x9360c
movq %rax, %rdi
movq %r14, %r8
xorl %eax, %eax
callq 0x2763d
movq %rax, %r14
movq %rbx, %rdi
movq %rax, %rsi
callq 0x60db8
movq %r14, %rdi
callq 0x271f7
jmp 0x523f2
movq %rbx, %rdi
movq %r14, %rsi
callq 0x60db8
pushq $-0x3
popq %rsi
movq %rbx, %rdi
callq 0x6119f
addq $0x78, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/scripting.c
// Function: luaLogCommand
int luaLogCommand(lua_State *lua) {
    int j, argc = lua_gettop(lua);
    int level;
    sds log;

    if (argc < 2) {
        luaPushError(lua, "redis.log() requires two arguments or more.");
        return 1;
    } else if (!lua_isnumber(lua,-argc)) {
        luaPushError(lua, "First argument must be a number (log level).");
        return 1;
    }
    level = lua_tonumber(lua,-argc);
    if (level < REDIS_DEBUG || level > REDIS_WARNING) {
        luaPushError(lua, "Invalid debug level.");
        return 1;
    }

    /* Glue together all the arguments */
    log = sdsempty();
    for (j = 1; j < argc; j++) {
        size_t len;
        char *s;

        s = (char*)lua_tolstring(lua,(-argc)+j,&len);
        if (s) {
            if (j != 1) log = sdscatlen(log," ",1);
            log = sdscatlen(log,s,len);
        }
    }
    redisLogRaw(level,log);
    sdsfree(log);
    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
callq 0x60737
cmpl $0x1, %eax
jg 0x52b19
leaq 0x40c7d(%rip), %rsi     # 0x93794
jmp 0x52b51
movl %eax, %r15d
movl %eax, %ebp
negl %ebp
movq %rbx, %rdi
movl %ebp, %esi
callq 0x609db
testl %eax, %eax
je 0x52b4a
movq %rbx, %rdi
movl %ebp, %esi
callq 0x60b2b
cvttsd2si %xmm0, %eax
cmpl $0x4, %eax
jb 0x52b6b
leaq 0x40ca5(%rip), %rsi     # 0x937ed
jmp 0x52b51
leaq 0x40c6f(%rip), %rsi     # 0x937c0
movq %rbx, %rdi
callq 0x52360
pushq $0x1
popq %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %eax, 0xc(%rsp)
callq 0x271bf
movq %rax, %r14
pushq $0x1
popq %r12
subl %r15d, %r12d
xorl %r13d, %r13d
leaq 0x10(%rsp), %r15
movl %r12d, %esi
addl %r13d, %esi
je 0x52bd3
movq %rbx, %rdi
movq %r15, %rdx
callq 0x60bad
testq %rax, %rax
je 0x52bce
movq %rax, %rbp
testl %r13d, %r13d
je 0x52bbb
movq %r14, %rdi
leaq 0x3d823(%rip), %rsi     # 0x903d3
pushq $0x1
popq %rdx
callq 0x2736d
movq %rax, %r14
movq 0x10(%rsp), %rdx
movq %r14, %rdi
movq %rbp, %rsi
callq 0x2736d
movq %rax, %r14
incl %r13d
jmp 0x52b86
movl 0xc(%rsp), %edi
movq %r14, %rsi
callq 0x224d3
movq %r14, %rdi
callq 0x271f7
xorl %eax, %eax
jmp 0x52b5c
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/scripting.c
// Function: luaMaskCountHook
void luaMaskCountHook(lua_State *lua, lua_Debug *ar) {
    long long elapsed;
    REDIS_NOTUSED(ar);
    REDIS_NOTUSED(lua);

    // 计算已执行时间
    elapsed = mstime() - server.lua_time_start;
    // 执行已超时
    if (elapsed >= server.lua_time_limit && server.lua_timedout == 0) {

        // 打印 LOG
        redisLog(REDIS_WARNING,"Lua slow script detected: still in execution after %lld milliseconds. You can try killing the script using the SCRIPT KILL command.",elapsed);

        // 设置状态
        server.lua_timedout = 1;

        /* Once the script timeouts we reenter the event loop to permit others
         * to call SCRIPT KILL or SHUTDOWN NOSAVE if needed. For this reason
         * we need to mask the client executing the script from the event loop.
         * If we don't do that the client may disconnect and could no longer be
         * here when the EVAL command will return. */
         // 当脚本运行超时时，将正在执行的客户端从读事件中移除
         // 并允许其他客户端执行 SCRIPT KILL 或者 SHUTDOWN NOSAVE
         aeDeleteFileEvent(server.el, server.lua_caller->fd, AE_READABLE);
    }

    // 在脚本上下文中，启动文件事件处理（等待 SCRIPT KILL 或 SHUTDOWN NOSAVE）
    if (server.lua_timedout) processEventsWhileBlocked();
    // 如果接到 SCRIPT KILL ，那么杀死脚本
    if (server.lua_kill) {
        redisLog(REDIS_WARNING,"Lua script killed by user with SCRIPT KILL.");
        lua_pushstring(lua,"Script killed by user with SCRIPT KILL...");
        lua_error(lua);
    }
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
callq 0x22843
leaq 0x743a7(%rip), %r14     # 0xc6fa8
subq 0x808(%r14), %rax
cmpq 0x800(%r14), %rax
setge %dl
movl 0x818(%r14), %ecx
testl %ecx, %ecx
sete %sil
andb %dl, %sil
cmpb $0x1, %sil
jne 0x52c63
leaq 0x40bd3(%rip), %rsi     # 0x93802
pushq $0x3
popq %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x22613
movl $0x1, 0x818(%r14)
movq 0x28(%r14), %rdi
movq 0x7f0(%r14), %rax
movl (%rax), %esi
pushq $0x1
popq %rdx
callq 0x203cd
movl 0x818(%r14), %ecx
testl %ecx, %ecx
je 0x52c6c
callq 0x2e0b2
cmpl $0x0, 0x81c(%r14)
je 0x52ca5
leaq 0x40c09(%rip), %rsi     # 0x93886
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x22613
leaq 0x40c24(%rip), %rsi     # 0x938b2
movq %rbx, %rdi
callq 0x60db8
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x616b3
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/scripting.c
// Function: luaLoadLibraries
void luaLoadLibraries(lua_State *lua) {

    // 基础库
    luaLoadLib(lua, "", luaopen_base);

    // table 库
    luaLoadLib(lua, LUA_TABLIBNAME, luaopen_table);

    // 字符串库
    luaLoadLib(lua, LUA_STRLIBNAME, luaopen_string);

    // 数学库
    luaLoadLib(lua, LUA_MATHLIBNAME, luaopen_math);

    // debug 库
    luaLoadLib(lua, LUA_DBLIBNAME, luaopen_debug); 

    // cjson 库
    luaLoadLib(lua, "cjson", luaopen_cjson);

    // struct 库
    luaLoadLib(lua, "struct", luaopen_struct);

    // cmsgpack 库
    luaLoadLib(lua, "cmsgpack", luaopen_cmsgpack);

#if 0 /* Stuff that we don't load currently, for sandboxing concerns. */
    luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package);
    luaLoadLib(lua, LUA_OSLIBNAME, luaopen_os);
#endif
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
leaq 0x3a626(%rip), %rsi     # 0x8d311
leaq 0x18bf6(%rip), %rdx     # 0x6b8e8
callq 0x52cad
leaq 0x44d77(%rip), %rsi     # 0x97a75
leaq 0x1b167(%rip), %rdx     # 0x6de6c
movq %rbx, %rdi
callq 0x52cad
leaq 0x44cb4(%rip), %rsi     # 0x979c8
leaq 0x1ba19(%rip), %rdx     # 0x6e734
movq %rbx, %rdi
callq 0x52cad
leaq 0x40bb2(%rip), %rsi     # 0x938dc
leaq 0x1aa9f(%rip), %rdx     # 0x6d7d0
movq %rbx, %rdi
callq 0x52cad
leaq 0x46af9(%rip), %rsi     # 0x99839
leaq 0x19db1(%rip), %rdx     # 0x6caf8
movq %rbx, %rdi
callq 0x52cad
leaq 0x40b8b(%rip), %rsi     # 0x938e1
leaq 0x1d433(%rip), %rdx     # 0x70190
movq %rbx, %rdi
callq 0x52cad
leaq 0x40b7b(%rip), %rsi     # 0x938e7
leaq 0x1e92d(%rip), %rdx     # 0x716a0
movq %rbx, %rdi
callq 0x52cad
leaq 0x40b6c(%rip), %rsi     # 0x938ee
leaq 0x1f7e5(%rip), %rdx     # 0x7256e
movq %rbx, %rdi
popq %rbx
jmp 0x52cad
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/scripting.c
// Function: scriptingEnableGlobalsProtection
void scriptingEnableGlobalsProtection(lua_State *lua) {
    char *s[32];
    sds code = sdsempty();
    int j = 0;

    /* strict.lua from: http://metalua.luaforge.net/src/lib/strict.lua.html.
     * Modified to be adapted to Redis. */
    s[j++]="local mt = {}\n";
    s[j++]="setmetatable(_G, mt)\n";
    s[j++]="mt.__newindex = function (t, n, v)\n";
    s[j++]="  if debug.getinfo(2) then\n";
    s[j++]="    local w = debug.getinfo(2, \"S\").what\n";
    s[j++]="    if w ~= \"main\" and w ~= \"C\" then\n";
    s[j++]="      error(\"Script attempted to create global variable '\"..tostring(n)..\"'\", 2)\n";
    s[j++]="    end\n";
    s[j++]="  end\n";
    s[j++]="  rawset(t, n, v)\n";
    s[j++]="end\n";
    s[j++]="mt.__index = function (t, n)\n";
    s[j++]="  if debug.getinfo(2) and debug.getinfo(2, \"S\").what ~= \"C\" then\n";
    s[j++]="    error(\"Script attempted to access unexisting global variable '\"..tostring(n)..\"'\", 2)\n";
    s[j++]="  end\n";
    s[j++]="  return rawget(t, n)\n";
    s[j++]="end\n";
    s[j++]=NULL;

    for (j = 0; s[j] != NULL; j++) code = sdscatlen(code,s[j],strlen(s[j]));
    luaL_loadbuffer(lua,code,sdslen(code),"@enable_strict_lua");
    lua_pcall(lua,0,0,0);
    sdsfree(code);
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x108, %rsp            # imm = 0x108
movq %rdi, %rbx
callq 0x271bf
movq %rax, %r14
leaq 0x40b30(%rip), %r15     # 0x93900
leaq 0x8(%rsp), %r12
movq %r15, -0x8(%r12)
leaq 0x40b2e(%rip), %rax     # 0x9390f
movq %rax, (%r12)
leaq 0x40b39(%rip), %rax     # 0x93925
movq %rax, 0x8(%r12)
leaq 0x40b51(%rip), %rax     # 0x93949
movq %rax, 0x10(%r12)
leaq 0x40b61(%rip), %rax     # 0x93965
movq %rax, 0x18(%r12)
leaq 0x40b7f(%rip), %rax     # 0x9398f
movq %rax, 0x20(%r12)
leaq 0x40b99(%rip), %rax     # 0x939b5
movq %rax, 0x28(%r12)
leaq 0x40bdf(%rip), %rax     # 0x93a07
movq %rax, 0x30(%r12)
leaq 0x40bd5(%rip), %rax     # 0x93a09
movq %rax, 0x38(%r12)
leaq 0x40bd0(%rip), %rcx     # 0x93a10
movq %rcx, 0x40(%r12)
leaq 0x40d88(%rip), %rcx     # 0x93bd4
movq %rcx, 0x48(%r12)
leaq 0x40bcb(%rip), %rdx     # 0x93a23
movq %rdx, 0x50(%r12)
leaq 0x40bdd(%rip), %rdx     # 0x93a41
movq %rdx, 0x58(%r12)
leaq 0x40c13(%rip), %rdx     # 0x93a83
movq %rdx, 0x60(%r12)
movq %rax, 0x68(%r12)
leaq 0x40c5d(%rip), %rax     # 0x93ade
movq %rax, 0x70(%r12)
movq %rcx, 0x78(%r12)
andq $0x0, 0x80(%r12)
testq %r15, %r15
je 0x52ebc
movq %r15, %rdi
callq 0x1f4f0
movq %r14, %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x2736d
movq %rax, %r14
movq (%r12), %r15
addq $0x8, %r12
jmp 0x52e94
movslq -0x8(%r14), %rdx
leaq 0x40c2e(%rip), %rcx     # 0x93af5
movq %rbx, %rdi
movq %r14, %rsi
callq 0x6b810
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x61434
movq %r14, %rdi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x271f7
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/bio.c
// Function: bioInit
void bioInit(void) {
    pthread_attr_t attr;
    pthread_t thread;
    size_t stacksize;
    int j;

    /* Initialization of state vars and objects 
     *
     * 初始化 job 队列，以及线程状态
     */
    for (j = 0; j < REDIS_BIO_NUM_OPS; j++) {
        pthread_mutex_init(&bio_mutex[j],NULL);
        pthread_cond_init(&bio_condvar[j],NULL);
        bio_jobs[j] = listCreate();
        bio_pending[j] = 0;
    }

    /* Set the stack size as by default it may be small in some system 
     *
     * 设置栈大小
     */
    pthread_attr_init(&attr);
    pthread_attr_getstacksize(&attr,&stacksize);
    if (!stacksize) stacksize = 1; /* The world is full of Solaris Fixes */
    while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2;
    pthread_attr_setstacksize(&attr, stacksize);

    /* Ready to spawn our threads. We use the single argument the thread
     * function accepts in order to pass the job ID the thread is
     * responsible of. 
     *
     * 创建线程
     */
    for (j = 0; j < REDIS_BIO_NUM_OPS; j++) {
        void *arg = (void*)(unsigned long) j;
        if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,arg) != 0) {
            redisLog(REDIS_WARNING,"Fatal: Can't initialize Background Jobs.");
            exit(1);
        }
        bio_threads[j] = thread;
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x50, %rsp
leaq 0x879dc(%rip), %rbx     # 0xdb840
leaq 0x87985(%rip), %r14     # 0xdb7f0
xorl %r15d, %r15d
leaq 0x87a2b(%rip), %r12     # 0xdb8a0
leaq 0x87a34(%rip), %r13     # 0xdb8b0
cmpq $0x10, %r15
je 0x53eb2
movq %r14, %rdi
xorl %esi, %esi
callq 0x1f420
movq %rbx, %rdi
xorl %esi, %esi
callq 0x1f510
callq 0x1fd8c
andq $0x0, (%r15,%r13)
movq %rax, (%r15,%r12)
addq $0x8, %r15
addq $0x30, %rbx
addq $0x28, %r14
jmp 0x53e7c
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x1f9e0
leaq 0x8(%rsp), %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1f870
movq (%r14), %rsi
testq %rsi, %rsi
jne 0x53eed
movq $0x1, 0x8(%rsp)
pushq $0x1
popq %rsi
jmp 0x53eed
addq %rsi, %rsi
movq %rsi, 0x8(%rsp)
cmpq $0x3fffff, %rsi         # imm = 0x3FFFFF
jbe 0x53ee5
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x1f760
leaq 0x879b6(%rip), %r13     # 0xdb8c0
xorl %r14d, %r14d
leaq 0x59(%rip), %r15        # 0x53f6d
leaq 0x10(%rsp), %r12
cmpq $0x2, %r14
je 0x53f46
movq %r12, %rdi
movq %rbx, %rsi
movq %r15, %rdx
movq %r14, %rcx
callq 0x1f490
testl %eax, %eax
jne 0x53f54
movq 0x10(%rsp), %rax
movq %rax, (%r13)
incq %r14
addq $0x8, %r13
jmp 0x53f19
addq $0x50, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
leaq 0x3ffef(%rip), %rsi     # 0x93f4a
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x22613
pushq $0x1
popq %rdi
callq 0x1f2b0