LLM4Binary/decompile-bench-makefile huggingface dataset:
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/pubsub.c
// Function: pubsubSubscribeChannel
int pubsubSubscribeChannel(redisClient *c, robj *channel) {
    dictEntry *de;
    list *clients = NULL;
    int retval = 0;

    /* Add the channel to the client -> channels hash table */
    // 将 channels 填接到 c->pubsub_channels 的集合中（值为 NULL 的字典视为集合）
    if (dictAdd(c->pubsub_channels,channel,NULL) == DICT_OK) {
        retval = 1;
        incrRefCount(channel);

        // 关联示意图
        // {
        //  频道名        订阅频道的客户端
        //  'channel-a' : [c1, c2, c3],
        //  'channel-b' : [c5, c2, c1],
        //  'channel-c' : [c10, c2, c1]
        // }
        /* Add the client to the channel -> list of clients hash table */
        // 从 pubsub_channels 字典中取出保存着所有订阅了 channel 的客户端的链表
        // 如果 channel 不存在于字典，那么添加进去
        de = dictFind(server.pubsub_channels,channel);
        if (de == NULL) {
            clients = listCreate();
            dictAdd(server.pubsub_channels,channel,clients);
            incrRefCount(channel);
        } else {
            clients = dictGetVal(de);
        }

        // before:
        // 'channel' : [c1, c2]
        // after:
        // 'channel' : [c1, c2, c3]
        // 将客户端添加到链表的末尾
        listAddNodeTail(clients,c);
    }

    /* Notify the client */
    // 回复客户端。
    // 示例：
    // redis 127.0.0.1:6379> SUBSCRIBE xxx
    // Reading messages... (press Ctrl-C to quit)
    // 1) "subscribe"
    // 2) "xxx"
    // 3) (integer) 1
    addReply(c,shared.mbulkhdr[3]);
    // "subscribe\n" 字符串
    addReply(c,shared.subscribebulk);
    // 被订阅的客户端
    addReplyBulk(c,channel);
    // 客户端订阅的频道和模式总数
    addReplyLongLong(c,dictSize(c->pubsub_channels)+listLength(c->pubsub_patterns));

    return retval;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movq 0x158(%rdi), %rdi
xorl %r15d, %r15d
xorl %edx, %edx
callq 0x21956
testl %eax, %eax
jne 0x47a58
movq %r14, %rdi
callq 0x2eacc
leaq 0x7f59d(%rip), %r12     # 0xc6fa8
movq 0x7a8(%r12), %rdi
movq %r14, %rsi
callq 0x21b64
testq %rax, %rax
je 0x47a26
movq 0x8(%rax), %r15
jmp 0x47a49
callq 0x1fd8c
movq %rax, %r15
movq 0x7a8(%r12), %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x21956
movq %r14, %rdi
callq 0x2eacc
movq %r15, %rdi
movq %rbx, %rsi
callq 0x1fe4c
pushq $0x1
popq %r15
leaq 0x7fda1(%rip), %r12     # 0xc7800
movq 0x13a48(%r12), %rsi
movq %rbx, %rdi
callq 0x2c10d
movq 0x108(%r12), %rsi
movq %rbx, %rdi
callq 0x2c10d
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2c84a
movq 0x158(%rbx), %rax
movq 0x160(%rbx), %rcx
movq 0x48(%rax), %rsi
addq 0x28(%rax), %rsi
addq 0x28(%rcx), %rsi
movq %rbx, %rdi
callq 0x2c794
movl %r15d, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/pubsub.c
// Function: pubsubSubscribePattern
int pubsubSubscribePattern(redisClient *c, robj *pattern) {
    int retval = 0;

    // 在链表中查找模式，看客户端是否已经订阅了这个模式
    // 这里为什么不像 channel 那样，用字典来进行检测呢？
    // 虽然 pattern 的数量一般来说并不多
    if (listSearchKey(c->pubsub_patterns,pattern) == NULL) {
        
        // 如果没有的话，执行以下代码

        retval = 1;

        pubsubPattern *pat;

        // 将 pattern 添加到 c->pubsub_patterns 链表中
        listAddNodeTail(c->pubsub_patterns,pattern);

        incrRefCount(pattern);

        // 创建并设置新的 pubsubPattern 结构
        pat = zmalloc(sizeof(*pat));
        pat->pattern = getDecodedObject(pattern);
        pat->client = c;

        // 添加到末尾
        listAddNodeTail(server.pubsub_patterns,pat);
    }

    /* Notify the client */
    // 回复客户端。
    // 示例：
    // redis 127.0.0.1:6379> PSUBSCRIBE xxx*
    // Reading messages... (press Ctrl-C to quit)
    // 1) "psubscribe"
    // 2) "xxx*"
    // 3) (integer) 1
    addReply(c,shared.mbulkhdr[3]);
    // 回复 "psubscribe" 字符串
    addReply(c,shared.psubscribebulk);
    // 回复被订阅的模式
    addReplyBulk(c,pattern);
    // 回复客户端订阅的频道和模式的总数
    addReplyLongLong(c,dictSize(c->pubsub_channels)+listLength(c->pubsub_patterns));

    return retval;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movq 0x160(%rdi), %rdi
callq 0x20066
xorl %ebp, %ebp
testq %rax, %rax
jne 0x47c66
movq 0x160(%rbx), %rdi
movq %r14, %rsi
callq 0x1fe4c
movq %r14, %rdi
callq 0x2eacc
pushq $0x10
popq %rdi
callq 0x2828d
movq %rax, %r15
movq %r14, %rdi
callq 0x2f087
movq %rax, 0x8(%r15)
movq %rbx, (%r15)
leaq 0x7f354(%rip), %rax     # 0xc6fa8
movq 0x7b0(%rax), %rdi
movq %r15, %rsi
callq 0x1fe4c
pushq $0x1
popq %rbp
leaq 0x7fb93(%rip), %r15     # 0xc7800
movq 0x13a48(%r15), %rsi
movq %rbx, %rdi
callq 0x2c10d
movq 0x118(%r15), %rsi
movq %rbx, %rdi
callq 0x2c10d
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2c84a
movq 0x158(%rbx), %rax
movq 0x160(%rbx), %rcx
movq 0x48(%rax), %rsi
addq 0x28(%rax), %rsi
addq 0x28(%rcx), %rsi
movq %rbx, %rdi
callq 0x2c794
movl %ebp, %eax
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/pubsub.c
// Function: pubsubUnsubscribePattern
int pubsubUnsubscribePattern(redisClient *c, robj *pattern, int notify) {
    listNode *ln;
    pubsubPattern pat;
    int retval = 0;

    incrRefCount(pattern); /* Protect the object. May be the same we remove */

    // 先确认一下，客户端是否订阅了这个模式
    if ((ln = listSearchKey(c->pubsub_patterns,pattern)) != NULL) {

        retval = 1;

        // 将模式从客户端的订阅列表中删除
        listDelNode(c->pubsub_patterns,ln);

        // 设置 pubsubPattern 结构
        pat.client = c;
        pat.pattern = pattern;

        // 在服务器中查找
        ln = listSearchKey(server.pubsub_patterns,&pat);
        listDelNode(server.pubsub_patterns,ln);
    }

    /* Notify the client */
    // 回复客户端
    if (notify) {
        addReply(c,shared.mbulkhdr[3]);
        // "punsubscribe" 字符串
        addReply(c,shared.punsubscribebulk);
        // 被退订的模式
        addReplyBulk(c,pattern);
        // 退订频道之后客户端仍在订阅的频道和模式的总数
        addReplyLongLong(c,dictSize(c->pubsub_channels)+
                       listLength(c->pubsub_patterns));
    }

    decrRefCount(pattern);

    return retval;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x10, %rsp
movl %edx, %ebp
movq %rsi, %rbx
movq %rdi, %r14
movq %rsi, %rdi
callq 0x2eacc
movq 0x160(%r14), %rdi
movq %rbx, %rsi
callq 0x20066
testq %rax, %rax
je 0x47d36
movq 0x160(%r14), %rdi
movq %rax, %rsi
callq 0x1ff28
movq %rsp, %rsi
movq %r14, (%rsi)
movq %rbx, 0x8(%rsi)
leaq 0x7f293(%rip), %r15     # 0xc6fa8
movq 0x7b0(%r15), %rdi
callq 0x20066
movq 0x7b0(%r15), %rdi
movq %rax, %rsi
callq 0x1ff28
pushq $0x1
popq %r15
jmp 0x47d39
xorl %r15d, %r15d
testl %ebp, %ebp
je 0x47d91
leaq 0x7fabc(%rip), %r12     # 0xc7800
movq 0x13a48(%r12), %rsi
movq %r14, %rdi
callq 0x2c10d
movq 0x120(%r12), %rsi
movq %r14, %rdi
callq 0x2c10d
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2c84a
movq 0x158(%r14), %rax
movq 0x160(%r14), %rcx
movq 0x48(%rax), %rsi
addq 0x28(%rax), %rsi
addq 0x28(%rcx), %rsi
movq %r14, %rdi
callq 0x2c794
movq %rbx, %rdi
callq 0x2ee1f
movl %r15d, %eax
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/pubsub.c
// Function: unsubscribeCommand
void unsubscribeCommand(redisClient *c) {
    if (c->argc == 1) {
        pubsubUnsubscribeAllChannels(c,1);
    } else {
        int j;

        for (j = 1; j < c->argc; j++)
            pubsubUnsubscribeChannel(c,c->argv[j],1);
    }
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
movq %rdi, %rbx
movl 0x30(%rdi), %eax
cmpl $0x1, %eax
jne 0x480b5
pushq $0x1
popq %rsi
movq %rbx, %rdi
popq %rbx
popq %r14
popq %rbp
jmp 0x47da9
pushq $0x1
popq %r14
pushq $0x1
popq %rbp
cltq
cmpq %rax, %r14
jge 0x480dd
movq 0x38(%rbx), %rax
movq (%rax,%r14,8), %rsi
movq %rbx, %rdi
movl %ebp, %edx
callq 0x47abb
incq %r14
movl 0x30(%rbx), %eax
jmp 0x480bc
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/pubsub.c
// Function: punsubscribeCommand
void punsubscribeCommand(redisClient *c) {
    if (c->argc == 1) {
        pubsubUnsubscribeAllPatterns(c,1);
    } else {
        int j;

        for (j = 1; j < c->argc; j++)
            pubsubUnsubscribePattern(c,c->argv[j],1);
    }
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
movq %rdi, %rbx
movl 0x30(%rdi), %eax
cmpl $0x1, %eax
jne 0x48131
pushq $0x1
popq %rsi
movq %rbx, %rdi
popq %rbx
popq %r14
popq %rbp
jmp 0x47e56
pushq $0x1
popq %r14
pushq $0x1
popq %rbp
cltq
cmpq %rax, %r14
jge 0x48159
movq 0x38(%rbx), %rax
movq (%rax,%r14,8), %rsi
movq %rbx, %rdi
movl %ebp, %edx
callq 0x47cc5
incq %r14
movl 0x30(%rbx), %eax
jmp 0x48138
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/pubsub.c
// Function: publishCommand
void publishCommand(redisClient *c) {

    int receivers = pubsubPublishMessage(c->argv[1],c->argv[2]);
    if (server.cluster_enabled)
        clusterPropagatePublish(c->argv[1],c->argv[2]);
    else
        forceCommandPropagation(c,REDIS_PROPAGATE_REPL);
    addReplyLongLong(c,receivers);
}

// Assembly:
pushq %rbp
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x38(%rdi), %rax
movq 0x8(%rax), %rdi
movq 0x10(%rax), %rsi
callq 0x47f05
movl %eax, %ebp
leaq 0x7ee2a(%rip), %rax     # 0xc6fa8
cmpl $0x0, 0x7bc(%rax)
je 0x4819a
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rdi
movq 0x10(%rax), %rsi
callq 0x4ebec
jmp 0x481a5
pushq $0x2
popq %rsi
movq %rbx, %rdi
callq 0x24c79
movslq %ebp, %rsi
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x2c794
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/multi.c
// Function: freeClientMultiState
void freeClientMultiState(redisClient *c) {
    int j;

    // 遍历事务队列
    for (j = 0; j < c->mstate.count; j++) {
        int i;
        multiCmd *mc = c->mstate.commands+j;

        // 释放所有命令参数
        for (i = 0; i < mc->argc; i++)
            decrRefCount(mc->argv[i]);

        // 释放参数数组本身
        zfree(mc->argv);
    }

    // 释放事务队列
    zfree(c->mstate.commands);
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
xorl %r15d, %r15d
movslq 0x108(%rbx), %rax
movq 0x100(%rbx), %r14
cmpq %rax, %r15
jge 0x483e7
imulq $0x18, %r15, %rax
addq %rax, %r14
xorl %r12d, %r12d
movslq 0x8(%r14), %rax
movq (%r14), %rdi
cmpq %rax, %r12
jge 0x483dd
movq (%rdi,%r12,8), %rdi
callq 0x2ee1f
incq %r12
jmp 0x483c3
callq 0x283cd
incq %r15
jmp 0x483a6
movq %r14, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x283cd
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/multi.c
// Function: discardCommand
void discardCommand(redisClient *c) {

    // 不能在客户端未进行事务状态之前使用
    if (!(c->flags & REDIS_MULTI)) {
        addReplyError(c,"DISCARD without MULTI");
        return;
    }

    discardTransaction(c);

    addReply(c,shared.ok);
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
testb $0x8, 0x90(%rdi)
jne 0x48603
leaq 0x48a98(%rip), %rsi     # 0x91092
movq %rbx, %rdi
popq %rbx
jmp 0x2c2da
movq %rbx, %rdi
callq 0x4849b
leaq 0x7f1ee(%rip), %rax     # 0xc7800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
popq %rbx
jmp 0x2c10d
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/multi.c
// Function: execCommandPropagateMulti
void execCommandPropagateMulti(redisClient *c) {
    robj *multistring = createStringObject("MULTI",5);

    propagate(server.multiCommand,c->db->id,&multistring,1,
              REDIS_PROPAGATE_AOF|REDIS_PROPAGATE_REPL);

    decrRefCount(multistring);
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
leaq 0x48a88(%rip), %rdi     # 0x910b5
pushq $0x5
popq %rsi
callq 0x2ea81
movq %rsp, %r14
movq %rax, (%r14)
leaq 0x7e966(%rip), %rax     # 0xc6fa8
movq 0x320(%rax), %rdi
movq 0x8(%rbx), %rax
movl 0x30(%rax), %esi
pushq $0x1
popq %rcx
pushq $0x3
popq %r8
movq %r14, %rdx
callq 0x24c05
movq (%r14), %rdi
callq 0x2ee1f
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/multi.c
// Function: touchWatchedKey
void touchWatchedKey(redisDb *db, robj *key) {
    list *clients;
    listIter li;
    listNode *ln;

    // 字典为空，没有任何键被监视
    if (dictSize(db->watched_keys) == 0) return;

    // 获取所有监视这个键的客户端
    clients = dictFetchValue(db->watched_keys, key);
    if (!clients) return;

    /* Mark all the clients watching this key as REDIS_DIRTY_CAS */
    /* Check if we are already watching for this key */
    // 遍历所有客户端，打开他们的 REDIS_DIRTY_CAS 标识
    listRewind(clients,&li);
    while((ln = listNext(&li))) {
        redisClient *c = listNodeValue(ln);

        c->flags |= REDIS_DIRTY_CAS;
    }
}

// Assembly:
pushq %rbx
subq $0x10, %rsp
movq 0x20(%rdi), %rdi
movq 0x28(%rdi), %rax
addq 0x48(%rdi), %rax
je 0x4891c
callq 0x21e57
testq %rax, %rax
je 0x4891c
movq %rsp, %rbx
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1ffac
movq %rbx, %rdi
callq 0x1ffc6
testq %rax, %rax
je 0x4891c
movq 0x10(%rax), %rax
orl $0x20, 0x90(%rax)
jmp 0x48902
addq $0x10, %rsp
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/multi.c
// Function: touchWatchedKeysOnFlush
void touchWatchedKeysOnFlush(int dbid) {
    listIter li1, li2;
    listNode *ln;

    // 这里的思路挺有趣的，不是遍历数据库的所有 key 来让客户端变为 DIRTY
    // 而是遍历所有客户端，然后遍历客户端监视的键，再让相应的客户端变为 DIRTY
    // 后者要比前者高效很多

    /* For every client, check all the waited keys */
    // 遍历所有客户端
    listRewind(server.clients,&li1);
    while((ln = listNext(&li1))) {

        redisClient *c = listNodeValue(ln);

        // 遍历客户端监视的键
        listRewind(c->watched_keys,&li2);
        while((ln = listNext(&li2))) {

            // 取出监视的键和键的数据库
            watchedKey *wk = listNodeValue(ln);

            /* For every watched key matching the specified DB, if the
             * key exists, mark the client as dirty, as the key will be
             * removed. */
            // 如果数据库号码相同，或者执行的命令为 FLUSHALL
            // 那么将客户端设置为 REDIS_DIRTY_CAS
            if (dbid == -1 || wk->db->id == dbid) {
                if (dictFind(wk->db->dict, wk->key->ptr) != NULL)
                    c->flags |= REDIS_DIRTY_CAS;
            }
        }
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %edi, %ebx
leaq 0x7e672(%rip), %rax     # 0xc6fa8
movq 0x1b0(%rax), %rdi
leaq 0x18(%rsp), %r14
movq %r14, %rsi
callq 0x1ffac
leaq 0x8(%rsp), %r15
movq %r14, %rdi
callq 0x1ffc6
testq %rax, %rax
je 0x489ae
movq 0x10(%rax), %r12
movq 0x150(%r12), %rdi
movq %r15, %rsi
callq 0x1ffac
movq %r15, %rdi
callq 0x1ffc6
testq %rax, %rax
je 0x4894f
movq 0x10(%rax), %rax
movq 0x8(%rax), %rcx
cmpl $-0x1, %ebx
je 0x4898f
cmpl %ebx, 0x30(%rcx)
jne 0x48970
movq (%rcx), %rdi
movq (%rax), %rax
movq 0x8(%rax), %rsi
callq 0x21b64
testq %rax, %rax
je 0x48970
orb $0x20, 0x90(%r12)
jmp 0x48970
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/multi.c
// Function: watchCommand
void watchCommand(redisClient *c) {
    int j;

    // 不能在事务开始后执行
    if (c->flags & REDIS_MULTI) {
        addReplyError(c,"WATCH inside MULTI is not allowed");
        return;
    }

    // 监视输入的任意个键
    for (j = 1; j < c->argc; j++)
        watchForKey(c,c->argv[j]);

    addReply(c,shared.ok);
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
testb $0x8, 0x90(%rdi)
jne 0x48a06
pushq $0x1
popq %r14
movslq 0x30(%rbx), %rax
cmpq %rax, %r14
jge 0x489ec
movq 0x38(%rbx), %rax
movq (%rax,%r14,8), %rsi
movq %rbx, %rdi
callq 0x4880d
incq %r14
jmp 0x489ce
leaq 0x7ee0d(%rip), %rax     # 0xc7800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x2c10d
leaq 0x486c6(%rip), %rsi     # 0x910d3
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x2c2da
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/multi.c
// Function: unwatchCommand
void unwatchCommand(redisClient *c) {

    // 取消客户端对所有键的监视
    unwatchAllKeys(c);
    
    // 重置状态
    c->flags &= (~REDIS_DIRTY_CAS);

    addReply(c,shared.ok);
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
callq 0x484c6
andb $-0x21, 0x90(%rbx)
leaq 0x7edcd(%rip), %rax     # 0xc7800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
popq %rbx
jmp 0x2c10d
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/debug.c
// Function: redisAssert
void _redisAssert(char *estr, char *file, int line) {
    bugReportStart();
    redisLog(REDIS_WARNING,"=== ASSERTION FAILED ===");
    redisLog(REDIS_WARNING,"==> %s:%d '%s' is not true",file,line,estr);
#ifdef HAVE_BACKTRACE
    server.assert_failed = estr;
    server.assert_file = file;
    server.assert_line = line;
    redisLog(REDIS_WARNING,"(forcing SIGSEGV to print the bug report.)");
#endif
    *((char*)-1) = 'x';
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movl %edx, %ebx
movq %rsi, %r14
movq %rdi, %r15
callq 0x4984f
leaq 0x482dd(%rip), %rsi     # 0x91363
pushq $0x3
popq %rbp
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
leaq 0x482e3(%rip), %rsi     # 0x9137c
movl %ebp, %edi
movq %r14, %rdx
movl %ebx, %ecx
movq %r15, %r8
xorl %eax, %eax
callq 0x22613
leaq 0x7def7(%rip), %rax     # 0xc6fa8
movq %r15, 0x820(%rax)
movq %r14, 0x828(%rax)
movl %ebx, 0x830(%rax)
leaq 0x482cb(%rip), %rsi     # 0x91397
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
movb $0x78, -0x1
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/debug.c
// Function: redisPanic
void _redisPanic(char *msg, char *file, int line) {
    bugReportStart();
    redisLog(REDIS_WARNING,"------------------------------------------------");
    redisLog(REDIS_WARNING,"!!! Software Failure. Press left mouse button to continue");
    redisLog(REDIS_WARNING,"Guru Meditation: %s #%s:%d",msg,file,line);
#ifdef HAVE_BACKTRACE
    redisLog(REDIS_WARNING,"(forcing SIGSEGV in order to print the stack trace)");
#endif
    redisLog(REDIS_WARNING,"------------------------------------------------");
    *((char*)-1) = 'x';
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movl %edx, %r14d
movq %rsi, %r15
movq %rdi, %r12
callq 0x4984f
leaq 0x4844a(%rip), %rbx     # 0x9154f
pushq $0x3
popq %rbp
movl %ebp, %edi
movq %rbx, %rsi
xorl %eax, %eax
callq 0x22613
leaq 0x48465(%rip), %rsi     # 0x91580
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
leaq 0x4848f(%rip), %rsi     # 0x915ba
movl %ebp, %edi
movq %r12, %rdx
movq %r15, %rcx
movl %r14d, %r8d
xorl %eax, %eax
callq 0x22613
leaq 0x48491(%rip), %rsi     # 0x915d5
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
movl %ebp, %edi
movq %rbx, %rsi
xorl %eax, %eax
callq 0x22613
movb $0x78, -0x1
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/debug.c
// Function: bugReportStart
void bugReportStart(void) {
    if (server.bug_report_start == 0) {
        redisLog(REDIS_WARNING,
            "\n\n=== REDIS BUG REPORT START: Cut & paste starting from here ===");
        server.bug_report_start = 1;
    }
}

// Assembly:
pushq %rbx
leaq 0x7d751(%rip), %rbx     # 0xc6fa8
cmpl $0x0, 0x834(%rbx)
jne 0x4987b
leaq 0x47da2(%rip), %rsi     # 0x91609
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x22613
movl $0x1, 0x834(%rbx)
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/debug.c
// Function: redisAssertPrintClientInfo
void _redisAssertPrintClientInfo(redisClient *c) {
    int j;

    bugReportStart();
    redisLog(REDIS_WARNING,"=== ASSERTION FAILED CLIENT CONTEXT ===");
    redisLog(REDIS_WARNING,"client->flags = %d", c->flags);
    redisLog(REDIS_WARNING,"client->fd = %d", c->fd);
    redisLog(REDIS_WARNING,"client->argc = %d", c->argc);
    for (j=0; j < c->argc; j++) {
        char buf[128];
        char *arg;

        if (c->argv[j]->type == REDIS_STRING && sdsEncodedObject(c->argv[j])) {
            arg = (char*) c->argv[j]->ptr;
        } else {
            snprintf(buf,sizeof(buf),"Object type: %d, encoding: %d",
                c->argv[j]->type, c->argv[j]->encoding);
            arg = buf;
        }
        redisLog(REDIS_WARNING,"client->argv[%d] = \"%s\" (refcount: %d)",
            j, arg, c->argv[j]->refcount);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rdi, %rbx
callq 0x4984f
leaq 0x47b25(%rip), %rsi     # 0x913c2
pushq $0x3
popq %rbp
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
movl 0x90(%rbx), %edx
leaq 0x47b34(%rip), %rsi     # 0x913ea
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
movl (%rbx), %edx
leaq 0x47b35(%rip), %rsi     # 0x913fd
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
movl 0x30(%rbx), %edx
leaq 0x47b32(%rip), %rsi     # 0x9140d
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
leaq 0x47b52(%rip), %r14     # 0x9143d
leaq 0x47b2d(%rip), %r15     # 0x9141f
movq %rsp, %r12
xorl %r13d, %r13d
movslq 0x30(%rbx), %rax
cmpq %rax, %r13
jge 0x4995c
movq 0x38(%rbx), %rax
movq (%rax,%r13,8), %rax
movl (%rax), %ecx
movl %ecx, %r8d
shrl $0x4, %r8d
andl $0xf, %r8d
andl $0xf, %ecx
je 0x4993a
movl $0x80, %esi
movq %r12, %rdi
movq %r15, %rdx
xorl %eax, %eax
callq 0x1f120
movq 0x38(%rbx), %rax
movq (%rax,%r13,8), %rax
movq %r12, %rcx
jmp 0x49944
testb $0x7, %r8b
jne 0x4991b
movq 0x8(%rax), %rcx
movl 0x4(%rax), %r8d
movl %ebp, %edi
movq %r14, %rsi
movl %r13d, %edx
xorl %eax, %eax
callq 0x22613
incq %r13
jmp 0x498f8
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/debug.c
// Function: redisLogObjectDebugInfo
void redisLogObjectDebugInfo(robj *o) {
    redisLog(REDIS_WARNING,"Object type: %d", o->type);
    redisLog(REDIS_WARNING,"Object encoding: %d", o->encoding);
    redisLog(REDIS_WARNING,"Object refcount: %d", o->refcount);
    if (o->type == REDIS_STRING && sdsEncodedObject(o)) {
        redisLog(REDIS_WARNING,"Object raw string len: %zu", sdslen(o->ptr));
        if (sdslen(o->ptr) < 4096) {
            sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr));
            redisLog(REDIS_WARNING,"Object raw string content: %s", repr);
            sdsfree(repr);
        }
    } else if (o->type == REDIS_LIST) {
        redisLog(REDIS_WARNING,"List length: %d", (int) listTypeLength(o));
    } else if (o->type == REDIS_SET) {
        redisLog(REDIS_WARNING,"Set size: %d", (int) setTypeSize(o));
    } else if (o->type == REDIS_HASH) {
        redisLog(REDIS_WARNING,"Hash size: %d", (int) hashTypeLength(o));
    } else if (o->type == REDIS_ZSET) {
        redisLog(REDIS_WARNING,"Sorted set size: %d", (int) zsetLength(o));
        if (o->encoding == REDIS_ENCODING_SKIPLIST)
            redisLog(REDIS_WARNING,"Skiplist level: %d", (int) ((zset*)o->ptr)->zsl->level);
    }
}

// Assembly:
pushq %rbp
pushq %rbx
pushq %rax
movq %rdi, %rbx
movl (%rdi), %edx
andl $0xf, %edx
leaq 0x47ae4(%rip), %rsi     # 0x91464
pushq $0x3
popq %rbp
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
movl (%rbx), %edx
shrl $0x4, %edx
andl $0xf, %edx
leaq 0x47ad9(%rip), %rsi     # 0x91474
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
movl 0x4(%rbx), %edx
leaq 0x47ada(%rip), %rsi     # 0x91488
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
movl (%rbx), %eax
movl %eax, %ecx
andl $0xf, %ecx
cmpl $0x4, %ecx
ja 0x49aa6
leaq 0x4773e(%rip), %rdx     # 0x9110c
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
shrl $0x4, %eax
testb $0x7, %al
jne 0x49aa6
movq 0x8(%rbx), %rax
movslq -0x8(%rax), %rdx
leaq 0x47aab(%rip), %rsi     # 0x9149c
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x22613
movq 0x8(%rbx), %rax
cmpl $0xfff, -0x8(%rax)      # imm = 0xFFF
ja 0x49aa6
callq 0x271bf
movq 0x8(%rbx), %rsi
movslq -0x8(%rsi), %rdx
movq %rax, %rdi
callq 0x27d51
movq %rax, %rbx
leaq 0x47a8c(%rip), %rsi     # 0x914b7
pushq $0x3
popq %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x22613
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x271f7
movq %rbx, %rdi
callq 0x3f488
leaq 0x47a9d(%rip), %rsi     # 0x914f2
jmp 0x49abc
movq %rbx, %rdi
callq 0x3917b
leaq 0x47a7f(%rip), %rsi     # 0x914e5
jmp 0x49abc
movq %rbx, %rdi
callq 0x3bc1e
leaq 0x47a89(%rip), %rsi     # 0x91500
pushq $0x3
popq %rdi
movl %eax, %edx
xorl %eax, %eax
callq 0x22613
movl $0xf0, %eax
andl (%rbx), %eax
cmpl $0x70, %eax
jne 0x49aa6
movq 0x8(%rbx), %rax
movq 0x8(%rax), %rax
movl 0x18(%rax), %edx
leaq 0x47a73(%rip), %rsi     # 0x91514
pushq $0x3
popq %rdi
jmp 0x49ac1
addq $0x8, %rsp
popq %rbx
popq %rbp
retq
movq %rbx, %rdi
callq 0x3700e
leaq 0x47a19(%rip), %rsi     # 0x914d5
pushq $0x3
popq %rdi
movl %eax, %edx
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x22613
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/debug.c
// Function: logStackContent
void logStackContent(void **sp) {
    int i;
    for (i = 15; i >= 0; i--) {
        unsigned long addr = (unsigned long) sp+i;
        unsigned long val = (unsigned long) sp[i];

        if (sizeof(long) == 4)
            redisLog(REDIS_WARNING, "(%08lx) -> %08lx", addr, val);
        else
            redisLog(REDIS_WARNING, "(%016lx) -> %016lx", addr, val);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
pushq $0xf
popq %r15
leaq 0x47b44(%rip), %r14     # 0x9164a
pushq $0x3
popq %rbp
testl %r15d, %r15d
js 0x49b29
movl %r15d, %edx
movq (%rbx,%rdx,8), %rcx
addq %rbx, %rdx
movl %ebp, %edi
movq %r14, %rsi
xorl %eax, %eax
callq 0x22613
decl %r15d
jmp 0x49b09
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/debug.c
// Function: logCurrentClient
void logCurrentClient(void) {
    if (server.current_client == NULL) return;

    redisClient *cc = server.current_client;
    sds client;
    int j;

    redisLog(REDIS_WARNING, "--- CURRENT CLIENT INFO");
    client = catClientInfoString(sdsempty(),cc);
    redisLog(REDIS_WARNING,"client: %s", client);
    sdsfree(client);
    for (j = 0; j < cc->argc; j++) {
        robj *decoded;

        decoded = getDecodedObject(cc->argv[j]);
        redisLog(REDIS_WARNING,"argv[%d]: '%s'", j, (char*)decoded->ptr);
        decrRefCount(decoded);
    }
    /* Check if the first argument, usually a key, is found inside the
     * selected DB, and if so print info about the associated object. */
    if (cc->argc >= 1) {
        robj *val, *key;
        dictEntry *de;

        key = getDecodedObject(cc->argv[1]);
        de = dictFind(cc->db->dict, key->ptr);
        if (de) {
            val = dictGetVal(de);
            redisLog(REDIS_WARNING,"key '%s' found in DB containing the following object:", (char*)key->ptr);
            redisLogObjectDebugInfo(val);
        }
        decrRefCount(key);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
leaq 0x7d2b9(%rip), %rax     # 0xc6fa8
movq 0x1d0(%rax), %rbx
testq %rbx, %rbx
je 0x49ddd
leaq 0x47a3a(%rip), %rsi     # 0x91740
pushq $0x3
popq %rbp
movl %ebp, %edi
xorl %eax, %eax
callq 0x22613
callq 0x271bf
movq %rax, %rdi
movq %rbx, %rsi
callq 0x2d623
movq %rax, %r14
leaq 0x432bd(%rip), %rsi     # 0x8cfe9
movl %ebp, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0x22613
movq %r14, %rdi
callq 0x271f7
leaq 0x47a11(%rip), %r14     # 0x91758
xorl %r15d, %r15d
movslq 0x30(%rbx), %rax
cmpq %rax, %r15
jge 0x49d83
movq 0x38(%rbx), %rax
movq (%rax,%r15,8), %rdi
callq 0x2f087
movq %rax, %r12
movq 0x8(%rax), %rcx
movl %ebp, %edi
movq %r14, %rsi
movl %r15d, %edx
xorl %eax, %eax
callq 0x22613
movq %r12, %rdi
callq 0x2ee1f
incq %r15
jmp 0x49d4a
testl %eax, %eax
jle 0x49ddd
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rdi
callq 0x2f087
movq %rax, %r14
movq 0x8(%rbx), %rax
movq (%rax), %rdi
movq 0x8(%r14), %rsi
callq 0x21b64
testq %rax, %rax
je 0x49dcd
movq 0x8(%rax), %rbx
movq 0x8(%r14), %rdx
leaq 0x479ac(%rip), %rsi     # 0x91767
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x22613
movq %rbx, %rdi
callq 0x4996e
movq %r14, %rdi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x2ee1f
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/debug.c
// Function: redisLogHexDump
void redisLogHexDump(int level, char *descr, void *value, size_t len) {
    char buf[65], *b;
    unsigned char *v = value;
    char charset[] = "0123456789abcdef";

    redisLog(level,"%s (hexdump):", descr);
    b = buf;
    while(len) {
        b[0] = charset[(*v)>>4];
        b[1] = charset[(*v)&0xf];
        b[2] = '\0';
        b += 2;
        len--;
        v++;
        if (b-buf == 64 || len == 0) {
            redisLogRaw(level|REDIS_LOG_RAW,buf);
            b = buf;
        }
    }
    redisLogRaw(level|REDIS_LOG_RAW,"\n");
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rcx, %r14
movq %rdx, %r15
movq %rsi, %rdx
movl %edi, %ebx
leaq 0x477e1(%rip), %rsi     # 0x91a2b
xorl %r13d, %r13d
xorl %eax, %eax
callq 0x22613
orl $0x400, %ebx            # imm = 0x400
movl %ebx, 0x4(%rsp)
leaq -0x1(%r14), %rbp
leaq 0x10(%rsp), %r12
leaq 0x47802(%rip), %rbx     # 0x91a70
movq %r12, %rcx
negq %rcx
movq %rcx, 0x8(%rsp)
cmpq %r13, %r14
je 0x4a2d6
movzbl (%r15,%r13), %ecx
shrl $0x4, %ecx
movb (%rcx,%rbx), %cl
movb %cl, (%r12)
movzbl (%r15,%r13), %ecx
andl $0xf, %ecx
movb (%rcx,%rbx), %cl
movb %cl, 0x1(%r12)
movb $0x0, 0x2(%r12)
cmpq %r13, %rbp
je 0x4a2c0
movq 0x8(%rsp), %rcx
addq %r12, %rcx
addq $0x2, %rcx
cmpq $0x40, %rcx
je 0x4a2c0
addq $0x2, %r12
jmp 0x4a2d1
movl 0x4(%rsp), %edi
leaq 0x10(%rsp), %r12
movq %r12, %rsi
callq 0x224d3
incq %r13
jmp 0x4a279
leaq 0x42474(%rip), %rsi     # 0x8c751
movl 0x4(%rsp), %edi
callq 0x224d3
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/debug.c
// Function: watchdogSignalHandler
void watchdogSignalHandler(int sig, siginfo_t *info, void *secret) {
#ifdef HAVE_BACKTRACE
    ucontext_t *uc = (ucontext_t*) secret;
#endif
    REDIS_NOTUSED(info);
    REDIS_NOTUSED(sig);

    redisLogFromHandler(REDIS_WARNING,"\n--- WATCHDOG TIMER EXPIRED ---");
#ifdef HAVE_BACKTRACE
    logStackTrace(uc);
#else
    redisLogFromHandler(REDIS_WARNING,"Sorry: no support for backtrace().");
#endif
    redisLogFromHandler(REDIS_WARNING,"--------\n");
}

// Assembly:
pushq %rbp
pushq %rbx
pushq %rax
movq %rdx, %rbx
leaq 0x47737(%rip), %rsi     # 0x91a39
pushq $0x3
popq %rbp
movl %ebp, %edi
callq 0x226ce
movq %rbx, %rdi
callq 0x49c5f
leaq 0x4773e(%rip), %rsi     # 0x91a59
movl %ebp, %edi
addq $0x8, %rsp
popq %rbx
popq %rbp
jmp 0x226ce
// File: /workspace/github_c_makefile_star2_O2/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdx, %rbx
movl 0x4(%rdi), %ebp
movl %ebp, %r12d
subl $0x1, %r12d
jae 0x4b415
xorl %ebp, %ebp
movl $0x0, %eax
jmp 0x4b478
movq %rsi, %r14
movq %rdi, %r15
movl %r12d, %esi
callq 0x4b5e5
cmpq %r14, %rax
jge 0x4b42c
xorl %eax, %eax
jmp 0x4b478
xorl %ebp, %ebp
movq %r15, %rdi
xorl %esi, %esi
callq 0x4b5e5
cmpq %r14, %rax
jg 0x4b40c
pushq $-0x1
popq %rax
pushq $-0x1
popq %r13
cmpl %ebp, %r12d
jl 0x4b46e
leal (%r12,%rbp), %r13d
shrl %r13d
movq %r15, %rdi
movl %r13d, %esi
callq 0x4b5e5
cmpq %r14, %rax
jl 0x4b468
jle 0x4b46e
leal -0x1(%r13), %r12d
jmp 0x4b444
leal 0x1(%r13), %ebp
jmp 0x4b444
cmpq %r14, %rax
sete %al
cmovel %r13d, %ebp
testq %rbx, %rbx
je 0x4b47f
movl %ebp, (%rbx)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/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 0x4b53d
andl $0x0, (%r14)
movabsq $-0x100000000, %rdx     # imm = 0xFFFFFFFF00000000
cmpq %rdx, %rax
pushq $0x8
popq %rax
cmovbl %eax, %ecx
cmpl %ecx, (%rbx)
jb 0x4b599
leaq 0xc(%rsp), %rdx
movq %rbx, %rdi
callq 0x4b3f2
testb %al, %al
je 0x4b599
movl 0x4(%rbx), %ebp
testq %r14, %r14
je 0x4b574
movl $0x1, (%r14)
movl 0xc(%rsp), %edx
decl %ebp
cmpl %ebp, %edx
jae 0x4b589
leal 0x1(%rdx), %esi
movq %rbx, %rdi
callq 0x4b49a
movq %rbx, %rdi
movl %ebp, %esi
callq 0x4b48e
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_O2/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
pushq $0x28
popq %rsi
callq 0x27158
movq %rax, %r14
leaq 0x7b13c(%rip), %rax     # 0xc6fa8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %rdi
movq %r14, %rsi
callq 0x21b64
movq %rax, %rbx
movq %r14, %rdi
callq 0x271f7
testq %rbx, %rbx
je 0x4be95
movq 0x8(%rbx), %rax
jmp 0x4be97
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O2/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 0x2828d
movq %rax, %rbx
leaq 0x8(%rax), %rdi
testq %r14, %r14
je 0x4bed8
movq 0x20(%r14), %rax
movq %rax, 0x20(%rdi)
movups (%r14), %xmm0
movups 0x10(%r14), %xmm1
movups %xmm1, 0x10(%rdi)
movups %xmm0, (%rdi)
jmp 0x4bee0
pushq $0x28
popq %rsi
callq 0x2e796
callq 0x22843
movq %rax, (%rbx)
andq $0x0, 0x38(%rbx)
movl %ebp, 0x30(%rbx)
movq %rbx, %rdi
andq $0x0, 0x8c0(%rbx)
addq $0x40, %rdi
xorps %xmm0, %xmm0
movups %xmm0, 0x888(%rbx)
movups %xmm0, 0x898(%rbx)
movups %xmm0, 0x8a6(%rbx)
andl $0x0, 0x8b8(%rbx)
movl $0x830, %edx            # imm = 0x830
xorl %esi, %esi
callq 0x1f110
callq 0x1fd8c
movq %rax, 0x8c8(%rbx)
andq $0x0, 0x880(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x870(%rbx)
leaq -0x23b82(%rip), %rcx    # 0x283cd
movq %rcx, 0x18(%rax)
movq %rbx, %rax
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/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 0x7b03f(%rip), %rax     # 0xc6fa8
movq 0x7d0(%rax), %rax
movq 0x18(%rax), %r14
addq $0x8, %rdi
pushq $0x28
popq %rsi
callq 0x27158
movq %r14, %rdi
movq %rax, %rsi
movq %rbx, %rdx
callq 0x21956
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_O2/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), %rcx
xorl %edx, %edx
testl %ecx, %ecx
movl $0x0, %esi
cmovgl %ecx, %esi
movq 0x848(%rdi), %rdi
pushq $-0x1
popq %rax
cmpq %rdx, %rsi
je 0x4bfd9
leaq 0x1(%rdx), %r8
cmpq %r14, (%rdi,%rdx,8)
movq %r8, %rdx
jne 0x4bfc5
jmp 0x4c003
leaq 0x8(,%rcx,8), %rsi
callq 0x28337
movq %rax, 0x848(%rbx)
movslq 0x844(%rbx), %rcx
movq %r14, (%rax,%rcx,8)
leal 0x1(%rcx), %eax
movl %eax, 0x844(%rbx)
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O2/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:
pushq %r15
pushq %r14
pushq %rbx
leaq 0x7af91(%rip), %r15     # 0xc6fa8
movq 0x7d0(%r15), %rax
movslq %esi, %r14
cmpq $0x0, 0x40028(%rax,%r14,8)
je 0x4c031
pushq $-0x1
popq %rax
jmp 0x4c04d
movq %rdi, %rbx
movl %r14d, %esi
callq 0x4fa1a
movq 0x7d0(%r15), %rax
movq %rbx, 0x40028(%rax,%r14,8)
xorl %eax, %eax
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O2/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
pushq $0x41
popq %rsi
movl $0x1a4, %edx            # imm = 0x1A4
xorl %eax, %eax
callq 0x1f640
cmpl $-0x1, %eax
je 0x4c28f
movl %eax, %ebp
pushq $0x6
popq %rsi
movl %eax, %edi
callq 0x1f610
cmpl $-0x1, %eax
jne 0x4c2db
callq 0x1f810
movl (%rax), %edi
cmpl $0xb, %edi
jne 0x4c2b4
leaq 0x45b50(%rip), %rsi     # 0x91dd0
pushq $0x3
popq %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x22613
jmp 0x4c2d0
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x45b01(%rip), %rsi     # 0x91da3
pushq $0x3
popq %rdi
movq %rbx, %rdx
movq %rax, %rcx
xorl %eax, %eax
callq 0x22613
jmp 0x4c2d7
callq 0x1f630
leaq 0x45bbd(%rip), %rsi     # 0x91e7d
pushq $0x3
popq %rdi
movq %rbx, %rdx
movq %rax, %rcx
xorl %eax, %eax
callq 0x22613
movl %ebp, %edi
callq 0x1f170
pushq $-0x1
popq %r14
movl %r14d, %eax
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/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 0x7aa63(%rip), %rax     # 0xc6fa8
cmpq $0x0, 0x650(%rax)
jne 0x4c56e
leaq 0x7aa52(%rip), %rax     # 0xc6fa8
cmpl $0x0, 0x2f0(%rax)
je 0x4c56e
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0xfffffc18, %ebp       # imm = 0xFFFFFC18
movl $0x1e8, %r14d           # imm = 0x1E8
addq 0x76a38(%rip), %r14     # 0xc2fb8
leaq 0x10(%rsp), %r15
pushq $0x1
popq %r12
testl %ebp, %ebp
je 0x4c55f
movq %r14, %rdi
movl %ebx, %esi
movq %r15, %rdx
pushq $0x2e
popq %rcx
leaq 0xc(%rsp), %r8
callq 0x21389
cmpl $-0x1, %eax
je 0x4c604
movl %eax, %r13d
xorl %edi, %edi
movl %eax, %esi
callq 0x209a0
xorl %edi, %edi
movl %r13d, %esi
callq 0x20b95
movl 0xc(%rsp), %ecx
movl %r12d, %edi
leaq 0x459e9(%rip), %rsi     # 0x91fb4
movq %r15, %rdx
xorl %eax, %eax
callq 0x22613
xorl %edi, %edi
callq 0x4c93b
movl %r13d, 0x8(%rax)
leaq 0x7a9c1(%rip), %rcx     # 0xc6fa8
movq 0x28(%rcx), %rdi
movl %r13d, %esi
movl %r12d, %edx
leaq 0x3ee(%rip), %rcx       # 0x4c9e6
movq %rax, %r8
callq 0x2030c
incl %ebp
jmp 0x4c589
callq 0x1f810
cmpl $0xb, (%rax)
je 0x4c55f
movl $0x1e8, %edx            # imm = 0x1E8
addq 0x7699a(%rip), %rdx     # 0xc2fb8
leaq 0x45974(%rip), %rsi     # 0x91f99
pushq $0x1
popq %rdi
xorl %eax, %eax
callq 0x22613
jmp 0x4c55f
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/cluster.c
// Function: clusterReset
void clusterReset(int hard) {
    dictIterator *di;
    dictEntry *de;
    int j;

    /* Turn into master. */
    if (nodeIsSlave(myself)) {
        clusterSetNodeAsMaster(myself);
        replicationUnsetMaster();
    }

    /* Close slots, reset manual failover state. */
    clusterCloseAllSlots();
    resetManualFailover();

    /* Unassign all the slots. */
    for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) clusterDelSlot(j);

    /* Forget all the nodes, but myself. */
    di = dictGetSafeIterator(server.cluster->nodes);
    while((de = dictNext(di)) != NULL) {
        clusterNode *node = dictGetVal(de);

        if (node == myself) continue;
        clusterDelNode(node);
    }
    dictReleaseIterator(di);

    /* Hard reset only: set epochs to 0, change node ID. */
    if (hard) {
        sds oldname;

        server.cluster->currentEpoch = 0;
        server.cluster->lastVoteEpoch = 0;
        myself->configEpoch = 0;

        /* To change the Node ID we need to remove the old name from the
         * nodes table, change the ID, and re-add back with new name. */
        oldname = sdsnewlen(myself->name, REDIS_CLUSTER_NAMELEN);
        dictDelete(server.cluster->nodes,oldname);
        sdsfree(oldname);
        getRandomHexChars(myself->name, REDIS_CLUSTER_NAMELEN);
        clusterAddNode(myself);
    }

    /* Make sure to persist the new config and update the state. */
    clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|
                         CLUSTER_TODO_UPDATE_STATE|
                         CLUSTER_TODO_FSYNC_CONFIG);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movl %edi, %ebx
movq 0x8ef9b(%rip), %rdi     # 0xdb628
testb $0x2, 0x30(%rdi)
je 0x4c69d
callq 0x4c7af
callq 0x33558
leaq 0x7a904(%rip), %r15     # 0xc6fa8
movq 0x7d0(%r15), %rdi
addq $0x28, %rdi
xorl %ebp, %ebp
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
callq 0x4c634
cmpl $0x4000, %ebp           # imm = 0x4000
je 0x4c6ed
movl %ebp, %edi
callq 0x4c7f8
incl %ebp
jmp 0x4c6da
movq 0x7d0(%r15), %rax
movq 0x18(%rax), %rdi
callq 0x21f20
movq %rax, %r14
movq %r14, %rdi
callq 0x21f2f
testq %rax, %rax
je 0x4c721
movq 0x8(%rax), %rdi
cmpq 0x8ef10(%rip), %rdi     # 0xdb628
je 0x4c700
callq 0x4c864
jmp 0x4c700
movq %r14, %rdi
callq 0x21fe6
testl %ebx, %ebx
je 0x4c796
movq 0x7d0(%r15), %rax
andq $0x0, 0x8(%rax)
andq $0x0, 0x60070(%rax)
movq 0x8eee0(%rip), %rdi     # 0xdb628
andq $0x0, 0x38(%rdi)
addq $0x8, %rdi
pushq $0x28
popq %rsi
callq 0x27158
movq %rax, %rbx
movq 0x7d0(%r15), %rax
movq 0x18(%rax), %rdi
movq %rbx, %rsi
callq 0x21c36
movq %rbx, %rdi
callq 0x271f7
movq 0x8eeaa(%rip), %rdi     # 0xdb628
addq $0x8, %rdi
pushq $0x28
popq %rsi
callq 0x2e796
movq 0x8ee97(%rip), %rdi     # 0xdb628
callq 0x4bf5b
movq 0x7d0(%r15), %rax
orl $0xe, 0x60078(%rax)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq