LLM4Binary/decompile-bench-makefile huggingface dataset:
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/intset.c
// Function: intsetSearch
static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) {
    int min = 0, max = intrev32ifbe(is->length)-1, mid = -1;
    int64_t cur = -1;

    /* The value can never be found when the set is empty */
    // 处理 is 为空时的情况
    if (intrev32ifbe(is->length) == 0) {
        if (pos) *pos = 0;
        return 0;
    } else {
        /* Check for the case where we know we cannot find the value,
         * but do know the insert position. */
        // 因为底层数组是有序的，如果 value 比数组中最后一个值都要大
        // 那么 value 肯定不存在于集合中，
        // 并且应该将 value 添加到底层数组的最末端
        if (value > _intsetGet(is,intrev32ifbe(is->length)-1)) {
            if (pos) *pos = intrev32ifbe(is->length);
            return 0;
        // 因为底层数组是有序的，如果 value 比数组中最前一个值都要小
        // 那么 value 肯定不存在于集合中，
        // 并且应该将它添加到底层数组的最前端
        } else if (value < _intsetGet(is,0)) {
            if (pos) *pos = 0;
            return 0;
        }
    }

    // 在有序数组中进行二分查找
    // T = O(log N)
    while(max >= min) {
        mid = (min+max)/2;
        cur = _intsetGet(is,mid);
        if (value > cur) {
            min = mid+1;
        } else if (value < cur) {
            max = mid-1;
        } else {
            break;
        }
    }

    // 检查是否已经找到了 value
    if (value == cur) {
        if (pos) *pos = mid;
        return 1;
    } else {
        if (pos) *pos = min;
        return 0;
    }
}

// Assembly:
movl 0x4(%rdi), %ecx
movl %ecx, %eax
subl $0x1, %eax
jae 0x4f7d6
xorl %ecx, %ecx
movl $0x0, %eax
jmp 0x4f88c
movzbl (%rdi), %r8d
movslq %eax, %r9
cmpl $0x4, %r8d
je 0x4f7f0
cmpl $0x8, %r8d
jne 0x4f7f7
movq 0x8(%rdi,%r9,8), %r9
jmp 0x4f7fd
movslq 0x8(%rdi,%r9,4), %r9
jmp 0x4f7fd
movswq 0x8(%rdi,%r9,2), %r9
cmpq %rsi, %r9
jge 0x4f809
xorl %eax, %eax
jmp 0x4f88c
movzbl %r8b, %r9d
cmpb $0x4, %r9b
je 0x4f81f
cmpl $0x8, %r9d
jne 0x4f825
movq 0x8(%rdi), %rcx
jmp 0x4f82a
movslq 0x8(%rdi), %rcx
jmp 0x4f82a
movswq 0x8(%rdi), %rcx
cmpq %rsi, %rcx
jg 0x4f7ca
testl %eax, %eax
js 0x4f873
xorl %ecx, %ecx
leal (%rax,%rcx), %r10d
shrl %r10d
cmpb $0x4, %r8b
je 0x4f84f
cmpl $0x8, %r9d
jne 0x4f856
movq 0x8(%rdi,%r10,8), %r11
jmp 0x4f85c
movslq 0x8(%rdi,%r10,4), %r11
jmp 0x4f85c
movswq 0x8(%rdi,%r10,2), %r11
cmpq %rsi, %r11
jge 0x4f867
leal 0x1(%r10), %ecx
jmp 0x4f86d
jle 0x4f882
leal -0x1(%r10), %eax
cmpl %ecx, %eax
jge 0x4f835
jmp 0x4f882
movq $-0x1, %r11
movl $0xffffffff, %r10d      # imm = 0xFFFFFFFF
xorl %ecx, %ecx
cmpq %rsi, %r11
sete %al
cmovel %r10d, %ecx
testq %rdx, %rdx
je 0x4f893
movl %ecx, (%rdx)
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/intset.c
// Function: intsetRemove
intset *intsetRemove(intset *is, int64_t value, int *success) {

    // 计算 value 的编码方式
    uint8_t valenc = _intsetValueEncoding(value);
    uint32_t pos;

    // 默认设置标识值为删除失败
    if (success) *success = 0;

    // 当 value 的编码大小小于或等于集合的当前编码方式（说明 value 有可能存在于集合）
    // 并且 intsetSearch 的结果为真，那么执行删除
    // T = O(log N)
    if (valenc <= intrev32ifbe(is->encoding) && intsetSearch(is,value,&pos)) {

        // 取出集合当前的元素数量
        uint32_t len = intrev32ifbe(is->length);

        /* We know we can delete */
        // 设置标识值为删除成功
        if (success) *success = 1;

        /* Overwrite value with tail and update length */
        // 如果 value 不是位于数组的末尾
        // 那么需要对原本位于 value 之后的元素进行移动
        //
        // 举个例子，如果数组表示如下，而 b 为删除的目标
        // | a | b | c | d |
        // 那么 intsetMoveTail 将 b 之后的所有数据向前移动一个元素的空间，
        // 覆盖 b 原来的数据
        // | a | c | d | d |
        // 之后 intsetResize 缩小内存大小时，
        // 数组末尾多出来的一个元素的空间将被移除
        // | a | c | d |
        if (pos < (len-1)) intsetMoveTail(is,pos+1,pos);
        // 缩小数组的大小，移除被删除元素占用的空间
        // T = O(N)
        is = intsetResize(is,len-1);
        // 更新集合的元素数量
        is->length = intrev32ifbe(len-1);
    }

    return is;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rdx, %r14
movq %rdi, %rbx
leaq -0x80000000(%rsi), %rax
movswq %si, %rcx
xorl %edx, %edx
cmpq %rsi, %rcx
setne %dl
leal 0x2(,%rdx,2), %ecx
testq %r14, %r14
je 0x4f8c8
movl $0x0, (%r14)
movabsq $-0x100000000, %rdx     # imm = 0xFFFFFFFF00000000
cmpq %rdx, %rax
movl $0x8, %eax
cmovbl %eax, %ecx
cmpl %ecx, (%rbx)
jb 0x4f970
leaq 0xc(%rsp), %rdx
movq %rbx, %rdi
callq 0x4f7c0
testb %al, %al
je 0x4f970
movl 0x4(%rbx), %ebp
testq %r14, %r14
je 0x4f905
movl $0x1, (%r14)
movl 0xc(%rsp), %eax
decl %ebp
cmpl %ebp, %eax
jae 0x4f959
leal 0x1(%rax), %ecx
movl (%rbx), %esi
movl 0x4(%rbx), %edx
subl %ecx, %edx
leaq 0x8(%rbx), %rdi
cmpl $0x4, %esi
je 0x4f936
cmpl $0x8, %esi
jne 0x4f945
leaq (%rdi,%rcx,8), %rsi
leaq (%rdi,%rax,8), %rdi
movl $0x3, %ecx
jmp 0x4f952
leaq (%rdi,%rcx,4), %rsi
leaq (%rdi,%rax,4), %rdi
movl $0x2, %ecx
jmp 0x4f952
leaq (%rdi,%rcx,2), %rsi
leaq (%rdi,%rax,2), %rdi
movl $0x1, %ecx
shll %cl, %edx
callq 0x1f780
movl (%rbx), %esi
imull %ebp, %esi
addq $0x8, %rsi
movq %rbx, %rdi
callq 0x297b5
movq %rax, %rbx
movl %ebp, 0x4(%rax)
movq %rbx, %rax
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/intset.c
// Function: intsetRandom
int64_t intsetRandom(intset *is) {
    // intrev32ifbe(is->length) 取出集合的元素数量
    // 而 rand() % intrev32ifbe(is->length) 根据元素数量计算一个随机索引
    // 然后 _intsetGet 负责根据随机索引来查找值
    return _intsetGet(is,rand()%intrev32ifbe(is->length));
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
callq 0x1faf0
xorl %edx, %edx
divl 0x4(%rbx)
movzbl (%rbx), %ecx
movslq %edx, %rax
cmpl $0x4, %ecx
je 0x4f9cd
cmpl $0x8, %ecx
jne 0x4f9d4
movq 0x8(%rbx,%rax,8), %rax
jmp 0x4f9da
movslq 0x8(%rbx,%rax,4), %rax
jmp 0x4f9da
movswq 0x8(%rbx,%rax,2), %rax
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/intset.c
// Function: intsetGet
uint8_t intsetGet(intset *is, uint32_t pos, int64_t *value) {

    // pos < intrev32ifbe(is->length) 
    // 检查 pos 是否符合数组的范围
    if (pos < intrev32ifbe(is->length)) {

        // 保存值到指针
        *value = _intsetGet(is,pos);

        // 返回成功指示值
        return 1;
    }

    // 超出索引范围
    return 0;
}

// Assembly:
cmpl %esi, 0x4(%rdi)
jbe 0x4f9f8
movzbl (%rdi), %ecx
movslq %esi, %rax
cmpl $0x4, %ecx
je 0x4f9fb
cmpl $0x8, %ecx
jne 0x4fa02
movq 0x8(%rdi,%rax,8), %rax
jmp 0x4fa08
xorl %eax, %eax
retq
movslq 0x8(%rdi,%rax,4), %rax
jmp 0x4fa08
movswq 0x8(%rdi,%rax,2), %rax
movq %rax, (%rdx)
movb $0x1, %al
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterGetMaxEpoch
uint64_t clusterGetMaxEpoch(void) {
    uint64_t max = 0;
    dictIterator *di;
    dictEntry *de;

    // 选出节点中的最大纪元
    di = dictGetSafeIterator(server.cluster->nodes);
    while((de = dictNext(di)) != NULL) {
        clusterNode *node = dictGetVal(de);
        if (node->configEpoch > max) max = node->configEpoch;
    }
    dictReleaseIterator(di);
    if (max < server.cluster->currentEpoch) max = server.cluster->currentEpoch;
    return max;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
leaq 0x7a334(%rip), %r14     # 0xc9fa8
movq 0x7d0(%r14), %rax
movq 0x18(%rax), %rdi
callq 0x228e4
movq %rax, %rbx
movq %rax, %rdi
callq 0x22913
xorl %r15d, %r15d
testq %rax, %rax
je 0x4fcb0
movq 0x8(%rax), %rax
movq 0x38(%rax), %rax
cmpq %r15, %rax
cmovaq %rax, %r15
movq %rbx, %rdi
callq 0x22913
jmp 0x4fc92
movq %rbx, %rdi
callq 0x229b9
movq 0x7d0(%r14), %rax
movq 0x8(%rax), %rax
cmpq %rax, %r15
cmovaq %r15, %rax
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterLookupNode
clusterNode *clusterLookupNode(char *name) {
    sds s = sdsnewlen(name, REDIS_CLUSTER_NAMELEN);
    dictEntry *de;

    de = dictFind(server.cluster->nodes,s);
    sdsfree(s);
    if (de == NULL) return NULL;
    return dictGetVal(de);
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movl $0x28, %esi
callq 0x28148
movq %rax, %r14
leaq 0x79bfc(%rip), %rax     # 0xc9fa8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %rdi
movq %r14, %rsi
callq 0x224dc
movq %rax, %rbx
movq %r14, %rdi
callq 0x28204
testq %rbx, %rbx
je 0x503d5
movq 0x8(%rbx), %rax
jmp 0x503d7
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: createClusterNode
clusterNode *createClusterNode(char *nodename, int flags) {
    clusterNode *node = zmalloc(sizeof(*node));

    // 设置名字
    if (nodename)
        memcpy(node->name, nodename, REDIS_CLUSTER_NAMELEN);
    else
        getRandomHexChars(node->name, REDIS_CLUSTER_NAMELEN);

    // 初始化属性
    node->ctime = mstime();
    node->configEpoch = 0;
    node->flags = flags;
    memset(node->slots,0,sizeof(node->slots));
    node->numslots = 0;
    node->numslaves = 0;
    node->slaves = NULL;
    node->slaveof = NULL;
    node->ping_sent = node->pong_received = 0;
    node->fail_time = 0;
    node->link = NULL;
    memset(node->ip,0,sizeof(node->ip));
    node->port = 0;
    node->fail_reports = listCreate();
    node->voted_time = 0;
    node->repl_offset_time = 0;
    node->repl_offset = 0;
    listSetFreeMethod(node->fail_reports,zfree);

    return node;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
movl %esi, %ebp
movq %rdi, %r14
movl $0x8d0, %edi            # imm = 0x8D0
callq 0x29709
movq %rax, %rbx
leaq 0x8(%rax), %rdi
testq %r14, %r14
je 0x50418
movq 0x20(%r14), %rax
movq %rax, 0x20(%rdi)
movups (%r14), %xmm0
movups 0x10(%r14), %xmm1
movups %xmm1, 0x10(%rdi)
movups %xmm0, (%rdi)
jmp 0x50422
movl $0x28, %esi
callq 0x30096
callq 0x232a3
movq %rax, (%rbx)
xorl %r14d, %r14d
movq %r14, 0x38(%rbx)
movl %ebp, 0x30(%rbx)
movq %rbx, %rdi
addq $0x40, %rdi
movq %r14, 0x8c0(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x888(%rbx)
movups %xmm0, 0x898(%rbx)
movups %xmm0, 0x8a6(%rbx)
movl $0x0, 0x8b8(%rbx)
movl $0x830, %edx            # imm = 0x830
xorl %esi, %esi
callq 0x1f110
callq 0x2038c
movq %rax, 0x8c8(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x870(%rbx)
movq %r14, 0x880(%rbx)
leaq -0x26c49(%rip), %rcx    # 0x2984b
movq %rcx, 0x18(%rax)
movq %rbx, %rax
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterAddNode
int clusterAddNode(clusterNode *node) {
    int retval;
    // 将 node 添加到当前节点的 nodes 表中
    // 这样接下来当前节点就会创建连向 node 的节点
    retval = dictAdd(server.cluster->nodes,
            sdsnewlen(node->name,REDIS_CLUSTER_NAMELEN), node);
    return (retval == DICT_OK) ? REDIS_OK : REDIS_ERR;
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
leaq 0x79afa(%rip), %rax     # 0xc9fa8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %r14
addq $0x8, %rdi
movl $0x28, %esi
callq 0x28148
movq %r14, %rdi
movq %rax, %rsi
movq %rbx, %rdx
callq 0x222b6
xorl %ecx, %ecx
negl %eax
sbbl %ecx, %ecx
movl %ecx, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterNodeAddSlave
int clusterNodeAddSlave(clusterNode *master, clusterNode *slave) {
    int j;

    /* If it's already a slave, don't add it again. */
    // 如果 slave 已经存在，那么不做操作
    for (j = 0; j < master->numslaves; j++)
        if (master->slaves[j] == slave) return REDIS_ERR;

    // 将 slave 添加到 slaves 数组里面
    master->slaves = zrealloc(master->slaves,
        sizeof(clusterNode*)*(master->numslaves+1));
    master->slaves[master->numslaves] = slave;
    master->numslaves++;

    return REDIS_OK;
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movslq 0x844(%rdi), %rax
testq %rax, %rax
jle 0x50512
movq 0x848(%rbx), %rcx
xorl %edx, %edx
cmpq %r14, (%rcx,%rdx,8)
je 0x50545
incq %rdx
cmpq %rdx, %rax
jne 0x50504
movq 0x848(%rbx), %rdi
leaq 0x8(,%rax,8), %rsi
callq 0x297b5
movq %rax, 0x848(%rbx)
movslq 0x844(%rbx), %rcx
movq %r14, (%rax,%rcx,8)
leal 0x1(%rcx), %eax
movl %eax, 0x844(%rbx)
xorl %eax, %eax
jmp 0x5054a
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterAddSlot
int clusterAddSlot(clusterNode *n, int slot) {

    // 槽 slot 已经是节点 n 处理的了
    if (server.cluster->slots[slot]) return REDIS_ERR;

    // 设置 bitmap
    clusterNodeSetSlotBit(n,slot);

    // 更新集群状态
    server.cluster->slots[slot] = n;

    return REDIS_OK;
}

// Assembly:
leaq 0x79a4f(%rip), %rcx     # 0xc9fa8
movq 0x7d0(%rcx), %r8
movslq %esi, %rdx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpq $0x0, 0x40028(%r8,%rdx,8)
je 0x50574
retq
leal 0x7(%rsi), %eax
testl %esi, %esi
cmovnsl %esi, %eax
sarl $0x3, %eax
cltq
movzbl 0x40(%rdi,%rax), %r8d
movl %esi, %r9d
andb $0x7, %r9b
movl %r8d, %r10d
btsl %r9d, %r10d
movb %r10b, 0x40(%rdi,%rax)
andl $0x7, %esi
btl %esi, %r8d
jb 0x505a9
incl 0x840(%rdi)
movq 0x7d0(%rcx), %rax
movq %rdi, 0x40028(%rax,%rdx,8)
xorl %eax, %eax
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterSaveConfig
int clusterSaveConfig(int do_fsync) {
    sds ci;
    size_t content_size;
    struct stat sb;
    int fd;

    server.cluster->todo_before_sleep &= ~CLUSTER_TODO_SAVE_CONFIG;

    /* Get the nodes description and concatenate our "vars" directive to
     * save currentEpoch and lastVoteEpoch. */
    ci = clusterGenNodesDescription(REDIS_NODE_HANDSHAKE);
    ci = sdscatprintf(ci,"vars currentEpoch %llu lastVoteEpoch %llu\n",
        (unsigned long long) server.cluster->currentEpoch,
        (unsigned long long) server.cluster->lastVoteEpoch);
    content_size = sdslen(ci);

    if ((fd = open(server.cluster_configfile,O_WRONLY|O_CREAT,0644))
        == -1) goto err;

    /* Pad the new payload if the existing file length is greater. */
    if (fstat(fd,&sb) != -1) {
        if (sb.st_size > content_size) {
            ci = sdsgrowzero(ci,sb.st_size);
            memset(ci+content_size,'\n',sb.st_size-content_size);
        }
    }
    if (write(fd,ci,sdslen(ci)) != (ssize_t)sdslen(ci)) goto err;
    if (do_fsync) {
        server.cluster->todo_before_sleep &= ~CLUSTER_TODO_FSYNC_CONFIG;
        fsync(fd);
    }

    /* Truncate the file if needed to remove the final \n padding that
     * is just garbage. */
    if (content_size != sdslen(ci) && ftruncate(fd,content_size) == -1) {
        /* ftruncate() failing is not a critical error. */
    }
    close(fd);
    sdsfree(ci);
    return 0;

err:
    if (fd != -1) close(fd);
    sdsfree(ci);
    return -1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movl %edi, %r14d
leaq 0x799d2(%rip), %r13     # 0xc9fa8
movq 0x7d0(%r13), %rax
andl $-0x5, 0x60078(%rax)
movl $0x20, %edi
callq 0x506ea
movq 0x7d0(%r13), %rcx
movq 0x8(%rcx), %rdx
movq 0x60070(%rcx), %rcx
leaq 0x4b748(%rip), %rsi     # 0x9bd4f
movq %rax, %rdi
xorl %eax, %eax
callq 0x28760
movq %rax, %rbx
movslq -0x8(%rax), %r15
movq 0x7c8(%r13), %rdi
movl $0x41, %esi
movl $0x1a4, %edx            # imm = 0x1A4
xorl %eax, %eax
callq 0x1f640
movl %eax, %ebp
cmpl $-0x1, %eax
je 0x506bb
leaq 0x8(%rsp), %rsi
movl %ebp, %edi
callq 0x1f690
cmpl $-0x1, %eax
je 0x50675
movq 0x38(%rsp), %rsi
movq %rsi, %r12
subq %r15, %r12
jbe 0x50675
movq %rbx, %rdi
callq 0x28320
movq %rax, %rbx
leaq (%rax,%r15), %rdi
movl $0xa, %esi
movq %r12, %rdx
callq 0x1f110
movslq -0x8(%rbx), %rdx
movl %ebp, %edi
movq %rbx, %rsi
callq 0x1fb30
movslq -0x8(%rbx), %rcx
cmpq %rcx, %rax
jne 0x506bb
testl %r14d, %r14d
je 0x506a6
movq 0x7d0(%r13), %rax
andl $-0x9, 0x60078(%rax)
movl %ebp, %edi
callq 0x1f5d0
xorl %r14d, %r14d
cmpl -0x8(%rbx), %r15d
je 0x506c6
movl %ebp, %edi
movq %r15, %rsi
callq 0x1f6e0
jmp 0x506c6
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
cmpl $-0x1, %ebp
je 0x506cd
movl %ebp, %edi
callq 0x1f170
movq %rbx, %rdi
callq 0x28204
movl %r14d, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterLockConfig
int clusterLockConfig(char *filename) {
    /* To lock it, we need to open the file in a way it is created if
     * it does not exist, otherwise there is a race condition with other
     * processes. */
    int fd = open(filename,O_WRONLY|O_CREAT,0644);
    if (fd == -1) {
        redisLog(REDIS_WARNING,
            "Can't open %s in order to acquire a lock: %s",
            filename, strerror(errno));
        return REDIS_ERR;
    }

    if (flock(fd,LOCK_EX|LOCK_NB) == -1) {
        if (errno == EWOULDBLOCK) {
            redisLog(REDIS_WARNING,
                 "Sorry, the cluster configuration file %s is already used "
                 "by a different Redis Cluster node. Please make sure that "
                 "different nodes use different cluster configuration "
                 "files.", filename);
        } else {
            redisLog(REDIS_WARNING,
                "Impossible to lock %s: %s", filename, strerror(errno));
        }
        close(fd);
        return REDIS_ERR;
    }
    /* Lock acquired: leak the 'fd' by not closing it, so that we'll retain the
     * lock to the file as long as the process exists. */
    return REDIS_OK;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
movq %rdi, %rbx
xorl %r14d, %r14d
movl $0x41, %esi
movl $0x1a4, %edx            # imm = 0x1A4
xorl %eax, %eax
callq 0x1f640
cmpl $-0x1, %eax
je 0x50808
movl %eax, %ebp
movl %eax, %edi
movl $0x6, %esi
callq 0x1f610
cmpl $-0x1, %eax
jne 0x5085a
callq 0x1f810
movl (%rax), %edi
cmpl $0xb, %edi
jne 0x5082f
leaq 0x4b5d9(%rip), %rsi     # 0x9bdd0
movl $0x3, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x23064
jmp 0x5084d
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x4b588(%rip), %rsi     # 0x9bda3
movl $0x3, %edi
movq %rbx, %rdx
movq %rax, %rcx
xorl %eax, %eax
callq 0x23064
jmp 0x50854
callq 0x1f630
leaq 0x4b642(%rip), %rsi     # 0x9be7d
movl $0x3, %edi
movq %rbx, %rdx
movq %rax, %rcx
xorl %eax, %eax
callq 0x23064
movl %ebp, %edi
callq 0x1f170
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
movl %r14d, %eax
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterAcceptHandler
void clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
    int cport, cfd;
    int max = MAX_CLUSTER_ACCEPTS_PER_CALL;
    char cip[REDIS_IP_STR_LEN];
    clusterLink *link;
    REDIS_NOTUSED(el);
    REDIS_NOTUSED(mask);
    REDIS_NOTUSED(privdata);

    /* If the server is starting up, don't accept cluster connections:
     * UPDATE messages may interact with the database content. */
    if (server.masterhost == NULL && server.loading) return;

    while(max--) {
        cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);
        if (cfd == ANET_ERR) {
            if (errno != EWOULDBLOCK)
                redisLog(REDIS_VERBOSE,
                    "Accepting cluster node: %s", server.neterr);
            return;
        }
        anetNonBlock(NULL,cfd);
        anetEnableTcpNoDelay(NULL,cfd);

        /* Use non-blocking I/O for cluster messages. */
        redisLog(REDIS_VERBOSE,"Accepted cluster node %s:%d", cip, cport);
        /* Create a link object we use to handle the connection.
         * It gets passed to the readable handler when data is available.
         * Initiallly the link->node pointer is set to NULL as we don't know
         * which node is, but the right node is references once we know the
         * node identity. */
        link = createClusterLink(NULL);
        link->fd = cfd;
        aeCreateFileEvent(server.el,cfd,AE_READABLE,clusterReadHandler,link);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movl %esi, %ebx
leaq 0x794b1(%rip), %r12     # 0xc9fa8
cmpq $0x0, 0x650(%r12)
jne 0x50b11
cmpl $0x0, 0x2f0(%r12)
jne 0x50bca
movl $0xfffffc18, %ebp       # imm = 0xFFFFFC18
movl $0x1e8, %r14d           # imm = 0x1E8
addq 0x75495(%rip), %r14     # 0xc5fb8
leaq 0x10(%rsp), %r15
movl $0x2e, %ecx
movq %r14, %rdi
movl %ebx, %esi
movq %r15, %rdx
leaq 0xc(%rsp), %r8
callq 0x21bff
cmpl $-0x1, %eax
je 0x50ba1
movl %eax, %r13d
xorl %edi, %edi
movl %eax, %esi
callq 0x21120
xorl %edi, %edi
movl %r13d, %esi
callq 0x2134b
movl 0xc(%rsp), %ecx
movl $0x1, %edi
leaq 0x4b44a(%rip), %rsi     # 0x9bfb4
movq %r15, %rdx
xorl %eax, %eax
callq 0x23064
xorl %edi, %edi
callq 0x50fcf
movl %r13d, 0x8(%rax)
movq 0x28(%r12), %rdi
movl %r13d, %esi
movl $0x1, %edx
leaq 0x4f3(%rip), %rcx       # 0x51086
movq %rax, %r8
callq 0x209d7
incl %ebp
jne 0x50b28
jmp 0x50bca
callq 0x1f810
cmpl $0xb, (%rax)
je 0x50bca
movl $0x1e8, %edx            # imm = 0x1E8
addq 0x75401(%rip), %rdx     # 0xc5fb8
leaq 0x4b3db(%rip), %rsi     # 0x9bf99
movl $0x1, %edi
xorl %eax, %eax
callq 0x23064
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: resetManualFailover
void resetManualFailover(void) {
    if (server.cluster->mf_end && clientsArePaused()) {
        server.clients_pause_end_time = 0;
        clientsArePaused(); /* Just use the side effect of the function. */
    }
    server.cluster->mf_end = 0; /* No manual failover in progress. */
    server.cluster->mf_can_start = 0;
    server.cluster->mf_slave = NULL;
    server.cluster->mf_master_offset = 0;
}

// Assembly:
pushq %rbx
leaq 0x793c7(%rip), %rbx     # 0xc9fa8
movq 0x7d0(%rbx), %rax
cmpq $0x0, 0x60050(%rax)
je 0x50c0b
callq 0x2ed93
testl %eax, %eax
je 0x50c0b
movq $0x0, 0x1e0(%rbx)
callq 0x2ed93
movq 0x7d0(%rbx), %rax
xorps %xmm0, %xmm0
movups %xmm0, 0x6005c(%rax)
movups %xmm0, 0x60050(%rax)
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O1/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:
testb $0x1, 0x30(%rdi)
jne 0x50e14
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x850(%rdi), %r14
testq %r14, %r14
je 0x50de2
movslq 0x844(%r14), %rax
testq %rax, %rax
jle 0x50de2
movq 0x848(%r14), %rdx
xorl %ecx, %ecx
cmpq %rbx, (%rdx,%rcx,8)
je 0x50dc3
incq %rcx
cmpq %rcx, %rax
jne 0x50db3
jmp 0x50de2
leaq (%rdx,%rcx,8), %rdi
leaq (%rdx,%rcx,8), %rsi
addq $0x8, %rsi
notl %ecx
addl %eax, %ecx
movslq %ecx, %rdx
callq 0x1f780
decl 0x844(%r14)
movl 0x30(%rbx), %eax
andl $-0x4, %eax
incl %eax
movl %eax, 0x30(%rbx)
movq $0x0, 0x850(%rbx)
leaq 0x791a9(%rip), %rax     # 0xc9fa8
movq 0x7d0(%rax), %rax
orl $0x6, 0x60078(%rax)
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O1/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:
leaq 0x7918c(%rip), %rax     # 0xc9fa8
movq 0x7d0(%rax), %rcx
movslq %edi, %rdx
movq 0x40028(%rcx,%rdx,8), %rsi
testq %rsi, %rsi
je 0x50e85
leal 0x7(%rdi), %ecx
testl %edi, %edi
cmovnsl %edi, %ecx
sarl $0x3, %ecx
movslq %ecx, %r8
movzbl 0x40(%rsi,%r8), %r9d
movl %edi, %ecx
andb $0x7, %cl
movl $0x1, %r10d
shll %cl, %r10d
notb %r10b
andb %r9b, %r10b
movb %r10b, 0x40(%rsi,%r8)
andl $0x7, %edi
btl %edi, %r9d
jae 0x50e8b
decl 0x840(%rsi)
movq 0x7d0(%rax), %rax
movq $0x0, 0x40028(%rax,%rdx,8)
xorl %eax, %eax
retq
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
retq
pushq %rax
leaq 0x4b8f1(%rip), %rdi     # 0x9c784
leaq 0x4ade3(%rip), %rsi     # 0x9bc7d
movl $0xfaa, %edx            # imm = 0xFAA
callq 0x4d037
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/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 0x790e8(%rip), %r15     # 0xc9fa8
movq 0x7d0(%r15), %rax
cmpq %rbx, 0x20028(%rax,%r14,8)
jne 0x50edd
movq $0x0, 0x20028(%rax,%r14,8)
movq 0x7d0(%r15), %rax
cmpq %rbx, 0x28(%rax,%r14,8)
jne 0x50ef4
movq $0x0, 0x28(%rax,%r14,8)
movq 0x7d0(%r15), %rax
cmpq %rbx, 0x40028(%rax,%r14,8)
jne 0x50f0d
movl %r14d, %edi
callq 0x50e15
incq %r14
cmpq $0x4000, %r14           # imm = 0x4000
jne 0x50ec0
movq 0x7d0(%r15), %rax
movq 0x18(%rax), %rdi
callq 0x228e4
movq %rax, %r14
movq %rax, %rdi
callq 0x22913
testq %rax, %rax
je 0x50f4f
movq 0x8(%rax), %rdi
cmpq %rbx, %rdi
je 0x50f4a
movq %rbx, %rsi
callq 0x5132f
movq %r14, %rdi
jmp 0x50f2f
movq %r14, %rdi
callq 0x229b9
testb $0x2, 0x30(%rbx)
je 0x50fad
movq 0x850(%rbx), %r14
testq %r14, %r14
je 0x50fad
movslq 0x844(%r14), %rax
testq %rax, %rax
jle 0x50fad
movq 0x848(%r14), %rdx
xorl %ecx, %ecx
cmpq %rbx, (%rdx,%rcx,8)
je 0x50f8e
incq %rcx
cmpq %rcx, %rax
jne 0x50f7e
jmp 0x50fad
leaq (%rdx,%rcx,8), %rdi
leaq (%rdx,%rcx,8), %rsi
addq $0x8, %rsi
notl %ecx
addl %eax, %ecx
movslq %ecx, %rdx
callq 0x1f780
decl 0x844(%r14)
movq %rbx, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x51457
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: keyHashSlot
unsigned int keyHashSlot(char *key, int keylen) {
    int s, e; /* start-end indexes of { and } */

    for (s = 0; s < keylen; s++)
        if (key[s] == '{') break;

    /* No '{' ? Hash the whole key. This is the base case. */
    if (s == keylen) return crc16(key,keylen) & 0x3FFF;

    /* '{' found? Check if we have the corresponding '}'. */
    for (e = s+1; e < keylen; e++)
        if (key[e] == '}') break;

    /* No '}' or nothing betweeen {} ? Hash the whole key. */
    if (e == keylen || e == s+1) return crc16(key,keylen) & 0x3FFF;

    /* If we are here there is both a { and a } on its right. Hash
     * what is in the middle between { and }. */
    return crc16(key+s+1,e-s-1) & 0x3FFF;
}

// Assembly:
pushq %rax
testl %esi, %esi
jle 0x511dd
movl %esi, %eax
xorl %ecx, %ecx
cmpb $0x7b, (%rdi,%rcx)
je 0x511df
incq %rcx
cmpq %rcx, %rax
jne 0x511cb
movl %eax, %ecx
jmp 0x511df
xorl %ecx, %ecx
cmpl %esi, %ecx
je 0x51223
leal 0x1(%rcx), %edx
movl %edx, %eax
cmpl %esi, %edx
jge 0x51205
movl %edx, %r8d
addq %rdi, %r8
movl %edx, %eax
cmpb $0x7d, (%r8)
je 0x51205
incl %eax
incq %r8
cmpl %esi, %eax
jl 0x511f4
movl %esi, %eax
cmpl %esi, %eax
setne %r8b
cmpl %edx, %eax
setne %dl
testb %dl, %r8b
je 0x51223
movl %ecx, %edx
addq %rdx, %rdi
incq %rdi
notl %ecx
addl %ecx, %eax
movl %eax, %esi
callq 0x5663c
andl $0x3fff, %eax           # imm = 0x3FFF
popq %rcx
retq
// File: /workspace/github_c_makefile_star2_O1/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:
movslq 0x844(%rdi), %rcx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
testq %rcx, %rcx
jle 0x513f9
pushq %rbx
movq %rdi, %rbx
movq 0x848(%rdi), %r8
xorl %edx, %edx
cmpq %rsi, (%r8,%rdx,8)
je 0x513d8
incq %rdx
cmpq %rdx, %rcx
jne 0x513c8
jmp 0x513f8
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_O1/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterCountNonFailingSlaves
int clusterCountNonFailingSlaves(clusterNode *n) {
    int j, okslaves = 0;

    for (j = 0; j < n->numslaves; j++)
        if (!nodeFailed(n->slaves[j])) okslaves++;
    return okslaves;
}

// Assembly:
movslq 0x844(%rdi), %rcx
testq %rcx, %rcx
jle 0x51454
movq 0x848(%rdi), %rdx
xorl %esi, %esi
xorl %eax, %eax
movq (%rdx,%rsi,8), %rdi
movb 0x30(%rdi), %dil
andb $0x8, %dil
cmpb $0x1, %dil
adcl $0x0, %eax
incq %rsi
cmpq %rsi, %rcx
jne 0x51438
retq
xorl %eax, %eax
retq
// File: /workspace/github_c_makefile_star2_O1/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
movl $0x28, %esi
callq 0x28148
movq %rax, %r14
leaq 0x78b32(%rip), %rax     # 0xc9fa8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %rdi
movq %r14, %rsi
callq 0x225d3
testl %eax, %eax
jne 0x51515
movq %r14, %rdi
callq 0x28204
movq 0x850(%rbx), %r14
testq %r14, %r14
je 0x514e9
movslq 0x844(%r14), %rax
testq %rax, %rax
jle 0x514e9
movq 0x848(%r14), %rdx
xorl %ecx, %ecx
cmpq %rbx, (%rdx,%rcx,8)
je 0x514ca
incq %rcx
cmpq %rcx, %rax
jne 0x514ba
jmp 0x514e9
leaq (%rdx,%rcx,8), %rdi
leaq (%rdx,%rcx,8), %rsi
addq $0x8, %rsi
notl %ecx
addl %eax, %ecx
movslq %ecx, %rdx
callq 0x1f780
decl 0x844(%r14)
movq 0x8c0(%rbx), %rdi
testq %rdi, %rdi
je 0x514fa
callq 0x51014
movq 0x8c8(%rbx), %rdi
callq 0x203b0
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x2984b
leaq 0x4aab4(%rip), %rdi     # 0x9bfd0
leaq 0x4a75a(%rip), %rsi     # 0x9bc7d
movl $0x3cb, %edx            # imm = 0x3CB
callq 0x4d037
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/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 %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r15
movq %rdi, %rbx
leaq 0x8(%rdi), %r14
movl $0x28, %esi
movq %r14, %rdi
callq 0x28148
movq %rax, %r12
leaq 0x4aaa3(%rip), %rsi     # 0x9c006
xorl %edi, %edi
movq %r14, %rdx
movq %r15, %rcx
xorl %eax, %eax
callq 0x23064
leaq 0x78a2f(%rip), %r13     # 0xc9fa8
movq 0x7d0(%r13), %rax
movq 0x18(%rax), %rdi
movq %r12, %rsi
callq 0x225d3
movl %eax, %ebp
movq %r12, %rdi
callq 0x28204
testl %ebp, %ebp
jne 0x515e8
movq 0x20(%r15), %rax
movq %rax, 0x20(%r14)
movups (%r15), %xmm0
movups 0x10(%r15), %xmm1
movups %xmm1, 0x10(%r14)
movups %xmm0, (%r14)
movq 0x7d0(%r13), %rax
movq 0x18(%rax), %r15
movl $0x28, %esi
movq %r14, %rdi
callq 0x28148
movq %r15, %rdi
movq %rax, %rsi
movq %rbx, %rdx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x222b6
leaq 0x471f7(%rip), %rdi     # 0x987e6
leaq 0x4a687(%rip), %rsi     # 0x9bc7d
movl $0x43b, %edx            # imm = 0x43B
callq 0x4d037
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/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
movl $0x28, %esi
callq 0x28148
movq %rax, %rbx
callq 0x5160a
leaq 0x7891e(%rip), %r14     # 0xc9fa8
movq 0x7d0(%r14), %rax
movq 0x20(%rax), %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x222b6
testl %eax, %eax
jne 0x516ae
movq %rbx, %rdi
callq 0x281fb
movq %rax, %rbx
movq 0x7d0(%r14), %rax
movq 0x20(%rax), %rdi
movq %rbx, %rsi
callq 0x224dc
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 0x28204
// File: /workspace/github_c_makefile_star2_O1/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
movl $0x28, %esi
callq 0x28148
movq %rax, %rbx
callq 0x5160a
leaq 0x788aa(%rip), %rax     # 0xc9fa8
movq 0x7d0(%rax), %rax
movq 0x20(%rax), %rdi
movq %rbx, %rsi
callq 0x224dc
xorl %ebp, %ebp
testq %rax, %rax
setne %bpl
movq %rbx, %rdi
callq 0x28204
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/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 0x51821
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x10d8, %rsp           # imm = 0x10D8
movq %rdi, %rbx
leaq 0x78857(%rip), %r15     # 0xc9fa8
movq 0x7d0(%r15), %rax
movl 0x14(%rax), %eax
movl %eax, %ebp
shrl $0x1f, %ebp
addl %eax, %ebp
sarl %ebp
callq 0x512ae
movq 0x8c8(%rbx), %rax
movq 0x8ceb1(%rip), %rcx     # 0xde628
movl 0x30(%rcx), %ecx
andl $0x1, %ecx
addl 0x28(%rax), %ecx
cmpl %ebp, %ecx
jle 0x51814
leaq 0x8(%rbx), %r14
leaq 0x4a892(%rip), %rsi     # 0x9c025
movl $0x2, %edi
movq %r14, %rdx
xorl %eax, %eax
callq 0x23064
movl 0x30(%rbx), %eax
andl $-0xd, %eax
orl $0x8, %eax
movl %eax, 0x30(%rbx)
callq 0x232a3
movq %rax, 0x868(%rbx)
movq 0x8ce67(%rip), %rax     # 0xde628
testb $0x1, 0x30(%rax)
je 0x51806
movq %rsp, %rbx
movq %rbx, %rdi
movl $0x3, %esi
callq 0x53105
movq 0x20(%r14), %rax
movq %rax, 0x8c0(%rbx)
movups (%r14), %xmm0
movups 0x10(%r14), %xmm1
movaps %xmm1, 0x8b0(%rbx)
movaps %xmm0, 0x8a0(%rbx)
movl 0x4(%rbx), %esi
bswapl %esi
movq %rbx, %rdi
callq 0x530a0
movq 0x7d0(%r15), %rax
orl $0x6, 0x60078(%rax)
addq $0x10d8, %rsp           # imm = 0x10D8
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/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
movq %r14, %rdi
movl $0x3, %esi
callq 0x53105
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 0x530a0
addq $0x10d8, %rsp           # imm = 0x10D8
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O1/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 0x232a3
movq %rax, %r14
movl 0x30(%rbx), %eax
testb $0x8, %al
je 0x5193d
testb $0x2, %al
jne 0x518ab
cmpl $0x0, 0x840(%rbx)
jne 0x518e2
leaq 0x4a7f5(%rip), %rcx     # 0x9c09e
jmp 0x518b2
leaq 0x4b588(%rip), %rcx     # 0x9ce3a
leaq 0x8(%rbx), %rdx
leaq 0x4a7a9(%rip), %rsi     # 0x9c066
movl $0x2, %edi
xorl %eax, %eax
callq 0x23064
andb $-0x9, 0x30(%rbx)
leaq 0x786d4(%rip), %rax     # 0xc9fa8
movq 0x7d0(%rax), %rax
orl $0x6, 0x60078(%rax)
testb $0x1, 0x30(%rbx)
je 0x51937
cmpl $0x0, 0x840(%rbx)
jle 0x51937
subq 0x868(%rbx), %r14
leaq 0x786a9(%rip), %r15     # 0xc9fa8
movq 0x7c0(%r15), %rax
addq %rax, %rax
cmpq %rax, %r14
jle 0x51937
leaq 0x8(%rbx), %rdx
leaq 0x4a79a(%rip), %rsi     # 0x9c0b3
movl $0x2, %edi
xorl %eax, %eax
callq 0x23064
andb $-0x9, 0x30(%rbx)
movq 0x7d0(%r15), %rax
orl $0x6, 0x60078(%rax)
popq %rbx
popq %r14
popq %r15
retq
leaq 0x4a711(%rip), %rdi     # 0x9c055
leaq 0x4a332(%rip), %rsi     # 0x9bc7d
movl $0x511, %edx            # imm = 0x511
callq 0x4d037
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/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 %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0xb8, %rsp
movl %esi, %ebx
movq %rdi, %r15
leaq 0x3c(%rsp), %r14
movl $0x2, %edi
movq %r15, %rsi
movq %r14, %rdx
callq 0x1f150
movl %eax, %ebp
movw $0x2, %cx
testl %eax, %eax
jne 0x51a29
leaq 0x40(%rsp), %rdx
movl $0xa, %edi
movq %r15, %rsi
callq 0x1f150
movw $0xa, %cx
testl %eax, %eax
je 0x51a3a
movw %cx, 0x38(%rsp)
movl $0xffff2710, %eax       # imm = 0xFFFF2710
leal (%rbx,%rax), %ecx
cmpl %eax, %ecx
ja 0x51a47
callq 0x1f810
movl $0x16, (%rax)
jmp 0x51a88
testl %ebp, %ebp
je 0x51a58
movq %rsp, %rdx
movl $0x2, %edi
movq %r14, %rsi
jmp 0x51a65
leaq 0x40(%rsp), %rsi
movq %rsp, %rdx
movl $0xa, %edi
movl $0x2e, %ecx
callq 0x1fbc0
movq %rsp, %rdi
movl %ebx, %esi
callq 0x5195f
testl %eax, %eax
je 0x51a98
callq 0x1f810
movl $0xb, (%rax)
xorl %eax, %eax
addq $0xb8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
xorl %edi, %edi
movl $0xa0, %esi
callq 0x503df
movq %rax, %r14
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)
leaq 0x784d1(%rip), %rax     # 0xc9fa8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %rbx
leaq 0x8(%r14), %rdi
movl $0x28, %esi
callq 0x28148
movq %rbx, %rdi
movq %rax, %rsi
movq %r14, %rdx
callq 0x222b6
movl $0x1, %eax
jmp 0x51a8a
// File: /workspace/github_c_makefile_star2_O1/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
cmpq %rsi, 0x8c0(%rdi)
je 0x51e5f
movl %edx, %ebp
movq %rdi, %rbx
movl 0x8(%rsi), %edi
xorl %r14d, %r14d
movq %rsp, %rsi
movl $0x2e, %edx
xorl %ecx, %ecx
callq 0x21d05
cmpl %ebp, 0x8b8(%rbx)
jne 0x51dd1
leaq 0x888(%rbx), %rsi
movq %rsp, %rdi
callq 0x1f880
testl %eax, %eax
je 0x51e62
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 0x51e12
callq 0x51014
leaq 0x8(%rbx), %rdx
movl 0x8b8(%rbx), %r8d
leaq 0x4a3aa(%rip), %rsi     # 0x9c1ce
movl $0x3, %edi
movq %r15, %rcx
xorl %eax, %eax
callq 0x23064
movq 0x8c7ee(%rip), %rax     # 0xde628
movl $0x1, %r14d
testb $0x2, 0x30(%rax)
je 0x51e62
cmpq %rbx, 0x850(%rax)
jne 0x51e62
movl 0x8b8(%rbx), %esi
movq %r15, %rdi
callq 0x35339
jmp 0x51e62
xorl %r14d, %r14d
movl %r14d, %eax
addq $0x38, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq