LLM4Binary/decompile-bench-makefile huggingface dataset:
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: expireIfNeeded
int expireIfNeeded(redisDb *db, robj *key) {

    // 取出键的过期时间
    mstime_t when = getExpire(db,key);
    mstime_t now;

    // 没有过期时间
    if (when < 0) return 0; /* No expire for this key */

    /* Don't expire anything while loading. It will be done later. */
    // 如果服务器正在进行载入，那么不进行任何过期检查
    if (server.loading) return 0;

    /* If we are in the context of a Lua script, we claim that time is
     * blocked to when the Lua script started. This way a key can expire
     * only the first time it is accessed and not in the middle of the
     * script execution, making propagation to slaves / AOF consistent.
     * See issue #1525 on Github for more information. */
    now = server.lua_caller ? server.lua_time_start : mstime();

    /* If we are running in the context of a slave, return ASAP:
     * the slave key expiration is controlled by the master that will
     * send us synthesized DEL operations for expired keys.
     *
     * Still we try to return the right information to the caller, 
     * that is, 0 if we think the key should be still valid, 1 if
     * we think the key is expired at this time. */
    // 当服务器运行在 replication 模式时
    // 附属节点并不主动删除 key
    // 它只返回一个逻辑上正确的返回值
    // 真正的删除操作要等待主节点发来删除命令时才执行
    // 从而保证数据的同步
    if (server.masterhost != NULL) return now > when;

    // 运行到这里，表示键带有过期时间，并且服务器为主节点

    /* Return when this key has not expired */
    // 如果未过期，返回 0
    if (now <= when) return 0;

    /* Delete the key */
    server.stat_expiredkeys++;

    // 向 AOF 文件和附属节点传播过期信息
    propagateExpire(db,key);

    // 发送事件通知
    notifyKeyspaceEvent(REDIS_NOTIFY_EXPIRED,
        "expired",key,db->id);

    // 将过期键从数据库中删除
    return dbDelete(db,key);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movq %rsi, %rbx
movq %rdi, %r14
callq 0x326b1
xorl %ebp, %ebp
testq %rax, %rax
js 0x31449
leaq 0x98be0(%rip), %r12     # 0xc9fa8
cmpl $0x0, 0x2f0(%r12)
jne 0x31449
movq %rax, %r15
cmpq $0x0, 0x7f0(%r12)
je 0x313eb
movq 0x808(%r12), %rax
jmp 0x313f0
callq 0x232a3
cmpq $0x0, 0x650(%r12)
je 0x31406
xorl %ebp, %ebp
cmpq %r15, %rax
setg %bpl
jmp 0x31449
cmpq %r15, %rax
jle 0x31449
incq 0x358(%r12)
movq %r14, %rdi
movq %rbx, %rsi
callq 0x328ff
movl 0x30(%r14), %ecx
leaq 0x6328e(%rip), %rsi     # 0x946b7
movl $0x100, %edi            # imm = 0x100
movq %rbx, %rdx
callq 0x608b5
movq %r14, %rdi
movq %rbx, %rsi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x3174b
movl %ebp, %eax
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: lookupKeyReadOrReply
robj *lookupKeyReadOrReply(redisClient *c, robj *key, robj *reply) {

    // 查找
    robj *o = lookupKeyRead(c->db, key);

    // 决定是否发送信息
    if (!o) addReply(c,reply);

    return o;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdx, %rbx
movq %rdi, %r14
movq 0x8(%rdi), %rdi
callq 0x3136a
movq %rax, %r15
testq %rax, %rax
jne 0x3149c
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2d6f0
movq %r15, %rax
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: dbAdd
void dbAdd(redisDb *db, robj *key, robj *val) {

    // 复制键名
    sds copy = sdsdup(key->ptr);

    // 尝试添加键值对
    int retval = dictAdd(db->dict, copy, val);

    // 如果键已经存在，那么停止
    redisAssertWithInfo(NULL,key,retval == REDIS_OK);

    // 如果开启了集群模式，那么将键保存到槽里面
    if (server.cluster_enabled) slotToKeyAdd(key);
 }

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdx, %r14
movq %rsi, %rbx
movq %rdi, %r15
movq 0x8(%rsi), %rdi
callq 0x281fb
movq (%r15), %rdi
movq %rax, %rsi
movq %r14, %rdx
callq 0x222b6
testl %eax, %eax
jne 0x3153b
leaq 0x98a89(%rip), %rax     # 0xc9fa8
cmpl $0x0, 0x7bc(%rax)
je 0x31535
movq %rbx, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x31563
popq %rbx
popq %r14
popq %r15
retq
leaq 0x65f9c(%rip), %rdx     # 0x974de
leaq 0x674f4(%rip), %rcx     # 0x98a3d
xorl %edi, %edi
movq %rbx, %rsi
movl $0xaf, %r8d
callq 0x4d872
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: slotToKeyAdd
void slotToKeyAdd(robj *key) {

    // 计算出键所属的槽
    unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr));

    // 将槽 slot 作为分值，键作为成员，添加到 slots_to_keys 跳跃表里面
    zslInsert(server.cluster->slots_to_keys,hashslot,key);
    incrRefCount(key);
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
movq 0x8(%rdi), %rdi
movl -0x8(%rdi), %esi
callq 0x511c2
leaq 0x98a2e(%rip), %rcx     # 0xc9fa8
movq 0x7d0(%rcx), %rcx
movq 0x60028(%rcx), %rdi
movl %eax, %eax
cvtsi2sd %rax, %xmm0
movq %rbx, %rsi
callq 0x3d096
movq %rbx, %rdi
popq %rbx
jmp 0x3041b
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: dbOverwrite
void dbOverwrite(redisDb *db, robj *key, robj *val) {
    dictEntry *de = dictFind(db->dict,key->ptr);
    
    // 节点必须存在，否则中止
    redisAssertWithInfo(NULL,key,de != NULL);

    // 覆写旧值
    dictReplace(db->dict, key->ptr, val);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdx, %r14
movq %rsi, %rbx
movq %rdi, %r15
movq (%rdi), %rdi
movq 0x8(%rsi), %rsi
callq 0x224dc
testq %rax, %rax
je 0x315d3
movq (%r15), %rdi
movq 0x8(%rbx), %rsi
movq %r14, %rdx
popq %rbx
popq %r14
popq %r15
jmp 0x2246a
leaq 0x660c8(%rip), %rdx     # 0x976a2
leaq 0x6745c(%rip), %rcx     # 0x98a3d
xorl %edi, %edi
movq %rbx, %rsi
movl $0xc8, %r8d
callq 0x4d872
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: setKey
void setKey(redisDb *db, robj *key, robj *val) {

    // 添加或覆写数据库中的键值对
    if (lookupKeyWrite(db,key) == NULL) {
        dbAdd(db,key,val);
    } else {
        dbOverwrite(db,key,val);
    }

    incrRefCount(val);

    // 移除键的过期时间
    removeExpire(db,key);

    // 发送键修改通知
    signalModifiedKey(db,key);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdx, %r15
movq %rsi, %rbx
movq %rdi, %r14
callq 0x313a3
movq %r14, %rdi
movq %rbx, %rsi
callq 0x31328
movq %r14, %rdi
movq %rbx, %rsi
movq %r15, %rdx
testq %rax, %rax
je 0x3162e
callq 0x315a0
jmp 0x31633
callq 0x314ef
movq %r15, %rdi
callq 0x3041b
movq %r14, %rdi
movq %rbx, %rsi
callq 0x31656
movq %r14, %rdi
movq %rbx, %rsi
popq %rbx
popq %r14
popq %r15
jmp 0x4c839
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: removeExpire
int removeExpire(redisDb *db, robj *key) {
    /* An expire may only be removed if there is a corresponding entry in the
     * main dict. Otherwise, the key will never be freed. */
    // 确保键带有过期时间
    redisAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL);

    // 删除过期时间
    return dictDelete(db->expires,key->ptr) == DICT_OK;
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
movq (%rdi), %rdi
movq 0x8(%rsi), %rsi
callq 0x224dc
testq %rax, %rax
je 0x3168f
movq 0x8(%r14), %rdi
movq 0x8(%rbx), %rsi
callq 0x225d3
xorl %ecx, %ecx
testl %eax, %eax
sete %cl
movl %ecx, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
leaq 0x65fe7(%rip), %rdx     # 0x9767d
leaq 0x673a0(%rip), %rcx     # 0x98a3d
xorl %edi, %edi
movq %rbx, %rsi
movl $0x438, %r8d            # imm = 0x438
callq 0x4d872
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: dbRandomKey
robj *dbRandomKey(redisDb *db) {
    dictEntry *de;

    while(1) {
        sds key;
        robj *keyobj;

        // 从键空间中随机取出一个键节点
        de = dictGetRandomKey(db->dict);

        // 数据库为空
        if (de == NULL) return NULL;

        // 取出键
        key = dictGetKey(de);
        // 为键创建一个字符串对象，对象的值为键的名字
        keyobj = createStringObject(key,sdslen(key));
        // 检查键是否带有过期时间
        if (dictFind(db->expires,key)) {
            // 如果键已经过期，那么将它删除，并继续随机下个键
            if (expireIfNeeded(db,keyobj)) {
                decrRefCount(keyobj);
                continue; /* search for another key. This expired. */
            }
        }

        // 返回被随机到的键（的名字）
        return keyobj;
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq (%rbx), %rdi
callq 0x22a1c
testq %rax, %rax
je 0x31733
movq (%rax), %r12
movslq -0x8(%r12), %rsi
movq %r12, %rdi
callq 0x303b7
movq %rax, %r15
movq 0x8(%rbx), %rdi
movq %r12, %rsi
callq 0x224dc
testq %rax, %rax
je 0x3172c
movq %rbx, %rdi
movq %r15, %rsi
callq 0x313a3
testl %eax, %eax
je 0x3172c
movq %r15, %rdi
callq 0x30834
movb $0x1, %al
jmp 0x31738
xorl %eax, %eax
movq %r15, %r14
jmp 0x31738
xorl %r14d, %r14d
xorl %eax, %eax
testb %al, %al
jne 0x316e0
movq %r14, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: dbDelete
int dbDelete(redisDb *db, robj *key) {

    /* Deleting an entry from the expires dict will not free the sds of
     * the key, because it is shared with the main dictionary. */
    // 删除键的过期时间
    if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);

    // 删除键值对
    if (dictDelete(db->dict,key->ptr) == DICT_OK) {
        // 如果开启了集群模式，那么从槽中删除给定的键
        if (server.cluster_enabled) slotToKeyDel(key);
        return 1;
    } else {
        // 键不存在
        return 0;
    }
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
movq %rsi, %rbx
movq %rdi, %r14
movq 0x8(%rdi), %rdi
movq 0x28(%rdi), %rax
addq 0x48(%rdi), %rax
je 0x3176c
movq 0x8(%rbx), %rsi
callq 0x225d3
movq (%r14), %rdi
movq 0x8(%rbx), %rsi
callq 0x225d3
xorl %ebp, %ebp
testl %eax, %eax
jne 0x3179b
leaq 0x98823(%rip), %rax     # 0xc9fa8
movl $0x1, %ebp
cmpl $0x0, 0x7bc(%rax)
je 0x3179b
movq %rbx, %rdi
callq 0x317a2
movl %ebp, %eax
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: dbUnshareStringValue
robj *dbUnshareStringValue(redisDb *db, robj *key, robj *o) {
    redisAssert(o->type == REDIS_STRING);
    if (o->refcount != 1 || o->encoding != REDIS_ENCODING_RAW) {
        robj *decoded = getDecodedObject(o);
        o = createRawStringObject(decoded->ptr, sdslen(decoded->ptr));
        decrRefCount(decoded);
        dbOverwrite(db,key,o);
    }
    return o;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movl (%rdx), %eax
testb $0xf, %al
jne 0x31839
movq %rdx, %r14
movq %rsi, %rbx
movq %rdi, %r15
testb $-0x10, %al
jne 0x317f9
cmpl $0x1, 0x4(%r14)
je 0x3182a
movq %r14, %rdi
callq 0x30ac3
movq %rax, %r12
movq 0x8(%rax), %rdi
movslq -0x8(%rdi), %rsi
callq 0x302ff
movq %rax, %r14
movq %r12, %rdi
callq 0x30834
movq %r15, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x315a0
movq %r14, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x654e6(%rip), %rdi     # 0x96d26
leaq 0x671f6(%rip), %rsi     # 0x98a3d
movl $0x155, %edx            # imm = 0x155
callq 0x4d037
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: emptyDb
long long emptyDb(void(callback)(void*)) {
    int j;
    long long removed = 0;

    // 清空所有数据库
    for (j = 0; j < server.dbnum; j++) {

        // 记录被删除键的数量
        removed += dictSize(server.db[j].dict);

        // 删除所有键值对
        dictEmpty(server.db[j].dict,callback);
        // 删除所有键的过期时间
        dictEmpty(server.db[j].expires,callback);
    }

    // 如果开启了集群模式，那么还要移除槽记录
    if (server.cluster_enabled) slotToKeyFlush();

    // 返回键的数量
    return removed;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
leaq 0x9873d(%rip), %r15     # 0xc9fa8
cmpl $0x0, 0x480(%r15)
jle 0x318be
movq %rdi, %r14
xorl %r12d, %r12d
xorl %r13d, %r13d
xorl %ebx, %ebx
movq 0x10(%r15), %rax
movq (%rax,%r12), %rdi
addq 0x28(%rdi), %rbx
addq 0x48(%rdi), %rbx
movq %r14, %rsi
callq 0x22d54
movq 0x10(%r15), %rax
movq 0x8(%rax,%r12), %rdi
movq %r14, %rsi
callq 0x22d54
incq %r13
movslq 0x480(%r15), %rax
addq $0x40, %r12
cmpq %rax, %r13
jl 0x31880
jmp 0x318c0
xorl %ebx, %ebx
cmpl $0x0, 0x7bc(%r15)
je 0x318f0
movq 0x7d0(%r15), %rax
movq 0x60028(%rax), %rdi
callq 0x3d036
callq 0x3cfc2
movq 0x7d0(%r15), %rcx
movq %rax, 0x60028(%rcx)
movq %rbx, %rax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: selectDb
int selectDb(redisClient *c, int id) {

    // 确保 id 在正确范围内
    if (id < 0 || id >= server.dbnum)
        return REDIS_ERR;

    // 切换数据库（更新指针）
    c->db = &server.db[id];

    return REDIS_OK;
}

// Assembly:
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
testl %esi, %esi
js 0x31955
leaq 0x9866b(%rip), %rcx     # 0xc9fa8
cmpl %esi, 0x480(%rcx)
jle 0x31955
movl %esi, %eax
shlq $0x6, %rax
addq 0x10(%rcx), %rax
movq %rax, 0x8(%rdi)
xorl %eax, %eax
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: flushdbCommand
void flushdbCommand(redisClient *c) {

    server.dirty += dictSize(c->db->dict);

    // 发送通知
    signalFlushedDb(c->db->id);

    // 清空指定数据库中的 dict 和 expires 字典
    dictEmpty(c->db->dict,NULL);
    dictEmpty(c->db->expires,NULL);

    // 如果开启了集群模式，那么还要移除槽记录
    if (server.cluster_enabled) slotToKeyFlush();

    addReply(c,shared.ok);
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x8(%rdi), %rax
movq (%rax), %rcx
movq 0x48(%rcx), %rdx
addq 0x28(%rcx), %rdx
leaq 0x98630(%rip), %r14     # 0xc9fa8
addq %rdx, 0x560(%r14)
movl 0x30(%rax), %edi
callq 0x4c892
movq 0x8(%rbx), %rax
movq (%rax), %rdi
xorl %esi, %esi
callq 0x22d54
movq 0x8(%rbx), %rax
movq 0x8(%rax), %rdi
xorl %esi, %esi
callq 0x22d54
cmpl $0x0, 0x7bc(%r14)
je 0x319d4
movq 0x7d0(%r14), %rax
movq 0x60028(%rax), %rdi
callq 0x3d036
callq 0x3cfc2
movq 0x7d0(%r14), %rcx
movq %rax, 0x60028(%rcx)
leaq 0x98e25(%rip), %rax     # 0xca800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x2d6f0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: flushallCommand
void flushallCommand(redisClient *c) {

    // 发送通知
    signalFlushedDb(-1);

    // 清空所有数据库
    server.dirty += emptyDb(NULL);
    addReply(c,shared.ok);

    // 如果正在保存新的 RDB ，那么取消保存操作
    if (server.rdb_child_pid != -1) {
        kill(server.rdb_child_pid,SIGUSR1);
        rdbRemoveTempFile(server.rdb_child_pid);
    }

    // 更新 RDB 文件
    if (server.saveparamslen > 0) {
        /* Normally rdbSave() will reset dirty, but we don't want this here
         * as otherwise FLUSHALL will not be replicated nor put into the AOF. */
        // rdbSave() 会清空服务器的 dirty 属性
        // 但为了确保 FLUSHALL 命令会被正常传播，
        // 程序需要保存并在 rdbSave() 调用之后还原服务器的 dirty 属性
        int saved_dirty = server.dirty;

        rdbSave(server.rdb_filename);

        server.dirty = saved_dirty;
    }

    server.dirty++;
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x4c892
xorl %edi, %edi
callq 0x3185b
leaq 0x9859b(%rip), %r14     # 0xc9fa8
addq %rax, 0x560(%r14)
leaq 0x98de5(%rip), %rax     # 0xca800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
callq 0x2d6f0
movl 0x570(%r14), %edi
cmpl $-0x1, %edi
je 0x31a49
movl $0xa, %esi
callq 0x1f620
movl 0x570(%r14), %edi
callq 0x3779c
cmpl $0x0, 0x580(%r14)
jle 0x31a6d
movslq 0x560(%r14), %rbx
movq 0x588(%r14), %rdi
callq 0x3725a
movq %rbx, 0x560(%r14)
incq 0x560(%r14)
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: delCommand
void delCommand(redisClient *c) {
    int deleted = 0, j;

    // 遍历所有输入键
    for (j = 1; j < c->argc; j++) {

        // 先删除过期的键
        expireIfNeeded(c->db,c->argv[j]);

        // 尝试删除键
        if (dbDelete(c->db,c->argv[j])) {

            // 删除键成功，发送通知

            signalModifiedKey(c->db,c->argv[j]);
            notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,
                "del",c->argv[j],c->db->id);

            server.dirty++;

            // 成功删除才增加 deleted 计数器的值
            deleted++;
        }
    }

    // 返回被删除键的数量
    addReplyLongLong(c,deleted);
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movq %rdi, %rbx
xorl %r14d, %r14d
cmpl $0x2, 0x30(%rdi)
jl 0x31b15
movl $0x1, %r12d
leaq 0x629eb(%rip), %r15     # 0x9448d
leaq 0x984ff(%rip), %r13     # 0xc9fa8
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq (%rax,%r12,8), %rsi
callq 0x313a3
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq (%rax,%r12,8), %rsi
callq 0x3174b
testl %eax, %eax
je 0x31b06
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq (%rax,%r12,8), %rsi
callq 0x4c839
movq 0x8(%rbx), %rax
movq 0x38(%rbx), %rcx
movq (%rcx,%r12,8), %rdx
movl 0x30(%rax), %ecx
movl $0x4, %edi
movq %r15, %rsi
callq 0x608b5
incq 0x560(%r13)
incl %r14d
incq %r12
movslq 0x30(%rbx), %rax
cmpq %rax, %r12
jl 0x31aa9
movslq %r14d, %r14
movq %rbx, %rdi
movq %r14, %rsi
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
jmp 0x2dea3
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: existsCommand
void existsCommand(redisClient *c) {

    // 检查键是否已经过期，如果已过期的话，那么将它删除
    // 这可以避免已过期的键被误认为存在
    expireIfNeeded(c->db,c->argv[1]);

    // 在数据库中查找
    if (dbExists(c->db,c->argv[1])) {
        addReply(c, shared.cone);
    } else {
        addReply(c, shared.czero);
    }
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
movq 0x8(%rdi), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x313a3
movq 0x8(%rbx), %rax
movq 0x38(%rbx), %rcx
movq 0x8(%rcx), %rcx
movq (%rax), %rdi
movq 0x8(%rcx), %rsi
callq 0x224dc
xorl %ecx, %ecx
testq %rax, %rax
setne %cl
leaq 0x98c9b(%rip), %rax     # 0xca800
movq 0x20(%rax,%rcx,8), %rsi
movq %rbx, %rdi
popq %rbx
jmp 0x2d6f0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: selectCommand
void selectCommand(redisClient *c) {
    long id;

    // 不合法的数据库号码
    if (getLongFromObjectOrReply(c, c->argv[1], &id,
        "invalid DB index") != REDIS_OK)
        return;

    if (server.cluster_enabled && id != 0) {
        addReplyError(c,"SELECT is not allowed in cluster mode");
        return;
    }

    // 切换数据库
    if (selectDb(c,id) == REDIS_ERR) {
        addReplyError(c,"invalid DB index");
    } else {
        addReply(c,shared.ok);
    }
}

// Assembly:
pushq %rbx
subq $0x10, %rsp
movq %rdi, %rbx
movq 0x38(%rdi), %rax
movq 0x8(%rax), %rsi
leaq 0x65967(%rip), %rcx     # 0x974f1
leaq 0x8(%rsp), %rdx
callq 0x310df
testl %eax, %eax
jne 0x31c09
leaq 0x98409(%rip), %rax     # 0xc9fa8
cmpl $0x0, 0x7bc(%rax)
setne %dl
movq 0x8(%rsp), %rcx
testq %rcx, %rcx
setne %sil
andb %dl, %sil
cmpb $0x1, %sil
jne 0x31bc7
leaq 0x6593d(%rip), %rsi     # 0x97502
jmp 0x31c01
testl %ecx, %ecx
js 0x31bfa
cmpl %ecx, 0x480(%rax)
jle 0x31bfa
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
shlq $0x6, %rcx
addq 0x10(%rax), %rcx
movq %rcx, 0x8(%rbx)
leaq 0x98c14(%rip), %rax     # 0xca800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
callq 0x2d6f0
jmp 0x31c09
leaq 0x658f0(%rip), %rsi     # 0x974f1
movq %rbx, %rdi
callq 0x2d9d7
addq $0x10, %rsp
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: randomkeyCommand
void randomkeyCommand(redisClient *c) {
    robj *key;

    // 随机返回键
    if ((key = dbRandomKey(c->db)) == NULL) {
        addReply(c,shared.nullbulk);
        return;
    }

    addReplyBulk(c,key);
    decrRefCount(key);
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x8(%rdi), %rdi
callq 0x316d5
testq %rax, %rax
je 0x31c41
movq %rax, %r14
movq %rbx, %rdi
movq %rax, %rsi
callq 0x2df74
movq %r14, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x30834
leaq 0x98bb8(%rip), %rax     # 0xca800
movq 0x50(%rax), %rsi
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x2d6f0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: keysCommand
void keysCommand(redisClient *c) {
    dictIterator *di;
    dictEntry *de;

    // 模式
    sds pattern = c->argv[1]->ptr;

    int plen = sdslen(pattern), allkeys;
    unsigned long numkeys = 0;
    void *replylen = addDeferredMultiBulkLength(c);

    // 遍历整个数据库，返回（名字）和模式匹配的键
    di = dictGetSafeIterator(c->db->dict);
    allkeys = (pattern[0] == '*' && pattern[1] == '\0');
    while((de = dictNext(di)) != NULL) {
        sds key = dictGetKey(de);
        robj *keyobj;

        // 将键名和模式进行比对
        if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {

            // 创建一个保存键名字的字符串对象
            keyobj = createStringObject(key,sdslen(key));

            // 删除已过期键
            if (expireIfNeeded(c->db,keyobj) == 0) {
                addReplyBulk(c,keyobj);
                numkeys++;
            }

            decrRefCount(keyobj);
        }
    }
    dictReleaseIterator(di);

    setDeferredMultiBulkLength(c,replylen,numkeys);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
movq 0x38(%rdi), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %r15
movl -0x8(%r15), %eax
movl %eax, 0xc(%rsp)
callq 0x2dc0a
movq %rax, 0x10(%rsp)
movq 0x8(%rbx), %rax
movq (%rax), %rdi
callq 0x228e4
movq %rax, %r12
cmpb $0x2a, (%r15)
jne 0x31caa
cmpb $0x0, 0x1(%r15)
sete %bpl
jmp 0x31cac
xorl %ebp, %ebp
movq %r12, %rdi
callq 0x22913
xorl %r13d, %r13d
testq %rax, %rax
je 0x31d1d
movq (%rax), %r14
testb %bpl, %bpl
jne 0x31cde
movl -0x8(%r14), %ecx
movq %r15, %rdi
movl 0xc(%rsp), %esi
movq %r14, %rdx
xorl %r8d, %r8d
callq 0x2f97c
testl %eax, %eax
je 0x31d13
movslq -0x8(%r14), %rsi
movq %r14, %rdi
callq 0x303b7
movq %rax, %r14
movq 0x8(%rbx), %rdi
movq %rax, %rsi
callq 0x313a3
testl %eax, %eax
jne 0x31d0b
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2df74
incq %r13
movq %r14, %rdi
callq 0x30834
movq %r12, %rdi
callq 0x22913
jmp 0x31cb7
movq %r12, %rdi
callq 0x229b9
movq %rbx, %rdi
movq 0x10(%rsp), %rsi
movq %r13, %rdx
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2dc46
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: scanCallback
void scanCallback(void *privdata, const dictEntry *de) {
    void **pd = (void**) privdata;
    list *keys = pd[0];
    robj *o = pd[1];
    robj *key, *val = NULL;

    if (o == NULL) {
        sds sdskey = dictGetKey(de);
        key = createStringObject(sdskey, sdslen(sdskey));
    } else if (o->type == REDIS_SET) {
        key = dictGetKey(de);
        incrRefCount(key);
    } else if (o->type == REDIS_HASH) {
        key = dictGetKey(de);
        incrRefCount(key);
        val = dictGetVal(de);
        incrRefCount(val);
    } else if (o->type == REDIS_ZSET) {
        key = dictGetKey(de);
        incrRefCount(key);
        val = createStringObjectFromLongDouble(*(double*)dictGetVal(de));
    } else {
        redisPanic("Type not handled in SCAN callback.");
    }

    listAddNodeTail(keys, key);
    if (val) listAddNodeTail(keys, val);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rsi, %r15
movq (%rdi), %rbx
movq 0x8(%rdi), %rax
testq %rax, %rax
je 0x31d80
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x4, %eax
je 0x31db2
cmpl $0x3, %eax
je 0x31d94
cmpl $0x2, %eax
jne 0x31df7
movq (%r15), %r14
movq %r14, %rdi
callq 0x3041b
jmp 0x31d8f
movq (%r15), %rdi
movslq -0x8(%rdi), %rsi
callq 0x303b7
movq %rax, %r14
xorl %r15d, %r15d
jmp 0x31dc9
movq (%r15), %r14
movq %r14, %rdi
callq 0x3041b
movq 0x8(%r15), %rax
fldl (%rax)
fstpt (%rsp)
callq 0x3041f
movq %rax, %r15
jmp 0x31dc9
movq (%r15), %r14
movq %r14, %rdi
callq 0x3041b
movq 0x8(%r15), %r15
movq %r15, %rdi
callq 0x3041b
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2045f
testq %r15, %r15
je 0x31ded
movq %rbx, %rdi
movq %r15, %rsi
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
jmp 0x2045f
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
leaq 0x6572a(%rip), %rdi     # 0x97528
leaq 0x66c38(%rip), %rsi     # 0x98a3d
movl $0x267, %edx            # imm = 0x267
callq 0x4d0e5
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: parseScanCursorOrReply
int parseScanCursorOrReply(redisClient *c, robj *o, unsigned long *cursor) {
    char *eptr;

    /* Use strtoul() because we need an *unsigned* long, so
     * getLongLongFromObject() does not cover the whole cursor space. */
    errno = 0;
    *cursor = strtoul(o->ptr, &eptr, 10);
    if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || errno == ERANGE)
    {
        addReplyError(c, "invalid cursor");
        return REDIS_ERR;
    }
    return REDIS_OK;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %rbx
callq 0x1f810
movq %rax, %r14
movl $0x0, (%rax)
movq 0x8(%r12), %rdi
movq %rsp, %rsi
movl $0xa, %edx
callq 0x1fba0
movq %rax, (%r15)
callq 0x1f550
movq (%rax), %rax
movq 0x8(%r12), %rcx
movsbq (%rcx), %rcx
testb $0x20, 0x1(%rax,%rcx,2)
jne 0x31e76
movq (%rsp), %rax
cmpb $0x0, (%rax)
jne 0x31e76
xorl %eax, %eax
cmpl $0x22, (%r14)
jne 0x31e8a
leaq 0x656d0(%rip), %rsi     # 0x9754d
movq %rbx, %rdi
callq 0x2d9d7
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: typeCommand
void typeCommand(redisClient *c) {
    robj *o;
    char *type;

    o = lookupKeyRead(c->db,c->argv[1]);

    if (o == NULL) {
        type = "none";
    } else {
        switch(o->type) {
        case REDIS_STRING: type = "string"; break;
        case REDIS_LIST: type = "list"; break;
        case REDIS_SET: type = "set"; break;
        case REDIS_ZSET: type = "zset"; break;
        case REDIS_HASH: type = "hash"; break;
        default: type = "unknown"; break;
        }
    }

    addReplyStatus(c,type);
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
movq 0x8(%rdi), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x3136a
testq %rax, %rax
je 0x32423
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x4, %eax
ja 0x3242c
leaq 0x652b2(%rip), %rcx     # 0x976cc
movslq (%rcx,%rax,4), %rsi
addq %rcx, %rsi
jmp 0x32433
leaq 0x651dc(%rip), %rsi     # 0x97606
jmp 0x32433
leaq 0x6505b(%rip), %rsi     # 0x9748e
movq %rbx, %rdi
popq %rbx
jmp 0x2db27
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: shutdownCommand
void shutdownCommand(redisClient *c) {
    int flags = 0;

    if (c->argc > 2) {
        addReply(c,shared.syntaxerr);
        return;
    } else if (c->argc == 2) {

        // 停机时不进行保存
        if (!strcasecmp(c->argv[1]->ptr,"nosave")) {
            flags |= REDIS_SHUTDOWN_NOSAVE;

        // 停机时进行保存
        } else if (!strcasecmp(c->argv[1]->ptr,"save")) {
            flags |= REDIS_SHUTDOWN_SAVE;

        } else {
            addReply(c,shared.syntaxerr);
            return;
        }
    }

    /* When SHUTDOWN is called while the server is loading a dataset in
     * memory we need to make sure no attempt is performed to save
     * the dataset on shutdown (otherwise it could overwrite the current DB
     * with half-read data).
     *
     * Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */
    if (server.loading || server.sentinel_mode)
        flags = (flags & ~REDIS_SHUTDOWN_SAVE) | REDIS_SHUTDOWN_NOSAVE;

    if (prepareForShutdown(flags) == REDIS_OK) exit(0);

    addReplyError(c,"Errors trying to SHUTDOWN. Check logs.");
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movl 0x30(%rdi), %ecx
cmpl $0x3, %ecx
jl 0x32468
leaq 0x983ae(%rip), %rax     # 0xca800
movq 0x80(%rax), %rsi
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x2d6f0
xorl %eax, %eax
cmpl $0x2, %ecx
jne 0x324ad
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %r14
leaq 0x65193(%rip), %rsi     # 0x97615
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x324a8
leaq 0x65728(%rip), %rsi     # 0x97bbd
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
jne 0x3244b
movl $0x1, %eax
jmp 0x324ad
movl $0x2, %eax
leaq 0x97af4(%rip), %rcx     # 0xc9fa8
movl 0x84(%rcx), %edx
orl 0x2f0(%rcx), %edx
movl $0x2, %edi
cmovel %eax, %edi
xorl %eax, %eax
callq 0x26664
testl %eax, %eax
je 0x324e9
leaq 0x65142(%rip), %rsi     # 0x9761c
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x2d9d7
xorl %edi, %edi
callq 0x1f2b0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: getExpire
long long getExpire(redisDb *db, robj *key) {
    dictEntry *de;

    /* No expire? return ASAP */
    // 获取键的过期时间
    // 如果过期时间不存在，那么直接返回
    if (dictSize(db->expires) == 0 ||
       (de = dictFind(db->expires,key->ptr)) == NULL) return -1;

    /* The entry was found in the expire dict, this means it should also
     * be present in the main dict (safety check). */
    redisAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL);

    // 返回过期时间
    return dictGetSignedIntegerVal(de);
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %r15
movq 0x8(%rdi), %rdi
movq 0x28(%rdi), %rax
movq $-0x1, %r14
addq 0x48(%rdi), %rax
je 0x326fb
movq %rsi, %rbx
movq 0x8(%rsi), %rsi
callq 0x224dc
testq %rax, %rax
je 0x326fb
movq %rax, %r12
movq (%r15), %rdi
movq 0x8(%rbx), %rsi
callq 0x224dc
testq %rax, %rax
je 0x3270a
movq 0x8(%r12), %r14
movq %r14, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x64f6c(%rip), %rdx     # 0x9767d
leaq 0x66325(%rip), %rcx     # 0x98a3d
xorl %edi, %edi
movq %rbx, %rsi
movl $0x465, %r8d            # imm = 0x465
callq 0x4d872
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: setExpire
void setExpire(redisDb *db, robj *key, long long when) {

    dictEntry *kde, *de;

    /* Reuse the sds from the main dict in the expire dict */
    // 取出键
    kde = dictFind(db->dict,key->ptr);

    redisAssertWithInfo(NULL,key,kde != NULL);

    // 根据键取出键的过期时间
    de = dictReplaceRaw(db->expires,dictGetKey(kde));

    // 设置键的过期时间
    // 这里是直接使用整数值来保存过期时间，不是用 INT 编码的 String 对象
    dictSetSignedIntegerVal(de,when);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdx, %rbx
movq %rsi, %r14
movq %rdi, %r15
movq (%rdi), %rdi
movq 0x8(%rsi), %rsi
callq 0x224dc
testq %rax, %rax
je 0x32767
movq 0x8(%r15), %rdi
movq (%rax), %rsi
callq 0x225a5
movq %rbx, 0x8(%rax)
popq %rbx
popq %r14
popq %r15
retq
leaq 0x64f33(%rip), %rdx     # 0x976a1
leaq 0x662c8(%rip), %rcx     # 0x98a3d
xorl %edi, %edi
movq %r14, %rsi
movl $0x449, %r8d            # imm = 0x449
callq 0x4d872
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: propagateExpire
void propagateExpire(redisDb *db, robj *key) {
    robj *argv[2];

    // 构造一个 DEL key 命令
    argv[0] = shared.del;
    argv[1] = key;
    incrRefCount(argv[0]);
    incrRefCount(argv[1]);

    // 传播到 AOF 
    if (server.aof_state != REDIS_AOF_OFF)
        feedAppendOnlyFile(server.delCommand,db->id,argv,2);

    // 传播到所有附属节点
    replicationFeedSlaves(server.slaves,db->id,argv,2);

    decrRefCount(argv[0]);
    decrRefCount(argv[1]);
}

// Assembly:
pushq %r14
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
leaq 0x97ef0(%rip), %rax     # 0xca800
movq 0x128(%rax), %rdi
movq %rdi, (%rsp)
movq %rsi, 0x8(%rsp)
callq 0x3041b
movq 0x8(%rsp), %rdi
callq 0x3041b
leaq 0x97672(%rip), %r14     # 0xc9fa8
cmpl $0x0, 0x4d0(%r14)
je 0x32957
movq 0x318(%r14), %rdi
movl 0x30(%rbx), %esi
movq %rsp, %rdx
movl $0x2, %ecx
callq 0x49e0e
movq 0x1c0(%r14), %rdi
movl 0x30(%rbx), %esi
movq %rsp, %rbx
movq %rbx, %rdx
movl $0x2, %ecx
callq 0x332f9
movq (%rbx), %rdi
callq 0x30834
movq 0x8(%rbx), %rdi
callq 0x30834
addq $0x18, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: ttlGenericCommand
void ttlGenericCommand(redisClient *c, int output_ms) {
    long long expire, ttl = -1;

    /* If the key does not exist at all, return -2 */
    // 取出键
    if (lookupKeyRead(c->db,c->argv[1]) == NULL) {
        addReplyLongLong(c,-2);
        return;
    }

    /* The key exists. Return -1 if it has no expire, or the actual
     * TTL value otherwise. */
    // 取出过期时间
    expire = getExpire(c->db,c->argv[1]);

    if (expire != -1) {
        // 计算剩余生存时间
        ttl = expire-mstime();
        if (ttl < 0) ttl = 0;
    }

    if (ttl == -1) {
        // 键是持久的
        addReplyLongLong(c,-1);
    } else {
        // 返回 TTL 
        // (ttl+500)/1000 计算的是渐近秒数
        addReplyLongLong(c,output_ms ? ttl : ((ttl+500)/1000));
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movl %esi, %ebp
movq %rdi, %rbx
movq 0x8(%rdi), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x3136a
testq %rax, %rax
je 0x32be9
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x326b1
movq %rax, %r15
movq $-0x1, %r14
movq $-0x1, %rax
cmpq $-0x1, %r15
je 0x32bda
callq 0x232a3
subq %rax, %r15
xorl %eax, %eax
testq %r15, %r15
cmovgq %r15, %rax
cmpq $-0x1, %rax
je 0x32c10
testl %ebp, %ebp
je 0x32bf2
movq %rax, %r14
jmp 0x32c10
movq $-0x2, %r14
jmp 0x32c10
addq $0x1f4, %rax            # imm = 0x1F4
shrq $0x3, %rax
movabsq $0x20c49ba5e353f7cf, %rcx # imm = 0x20C49BA5E353F7CF
mulq %rcx
movq %rdx, %r14
shrq $0x4, %r14
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x2dea3
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: persistCommand
void persistCommand(redisClient *c) {
    dictEntry *de;

    // 取出键
    de = dictFind(c->db->dict,c->argv[1]->ptr);

    if (de == NULL) {
        // 键没有过期时间
        addReply(c,shared.czero);

    } else {

        // 键带有过期时间，那么将它移除
        if (removeExpire(c->db,c->argv[1])) {
            addReply(c,shared.cone);
            server.dirty++;

        // 键已经是持久的了
        } else {
            addReply(c,shared.czero);
        }
    }
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
movq 0x8(%rdi), %rax
movq 0x38(%rdi), %rcx
movq (%rax), %rdi
movq 0x8(%rcx), %rax
movq 0x8(%rax), %rsi
callq 0x224dc
testq %rax, %rax
je 0x32c8f
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x31656
testl %eax, %eax
je 0x32c8f
leaq 0x97b8d(%rip), %rax     # 0xca800
movq 0x28(%rax), %rsi
movq %rbx, %rdi
callq 0x2d6f0
leaq 0x97322(%rip), %rax     # 0xc9fa8
incq 0x560(%rax)
popq %rbx
retq
leaq 0x97b6a(%rip), %rax     # 0xca800
movq 0x20(%rax), %rsi
movq %rbx, %rdi
popq %rbx
jmp 0x2d6f0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: getKeysUsingCommandTable
int *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, int *numkeys) {
    int j, i = 0, last, *keys;
    REDIS_NOTUSED(argv);

    if (cmd->firstkey == 0) {
        *numkeys = 0;
        return NULL;
    }
    last = cmd->lastkey;
    if (last < 0) last = argc+last;
    keys = zmalloc(sizeof(int)*((last - cmd->firstkey)+1));
    for (j = cmd->firstkey; j <= last; j += cmd->keystep) {
        redisAssert(j < argc);
        keys[i++] = j;
    }
    *numkeys = i;
    return keys;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movq %rcx, %rbx
movl 0x30(%rdi), %eax
xorl %r15d, %r15d
testl %eax, %eax
je 0x32d02
movl %edx, %ebp
movq %rdi, %r14
movl 0x34(%rdi), %ecx
movl %ecx, %r12d
sarl $0x1f, %r12d
andl %edx, %r12d
addl %ecx, %r12d
movl %r12d, %ecx
subl %eax, %ecx
incl %ecx
movslq %ecx, %rdi
shlq $0x2, %rdi
callq 0x29709
movl 0x30(%r14), %ecx
cmpl %r12d, %ecx
jg 0x32d04
xorl %r15d, %r15d
cmpl %ebp, %ecx
jge 0x32d10
movl %ecx, (%rax,%r15,4)
incq %r15
addl 0x38(%r14), %ecx
cmpl %r12d, %ecx
jle 0x32cec
jmp 0x32d04
xorl %eax, %eax
movl %r15d, (%rbx)
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x649aa(%rip), %rdi     # 0x976c1
leaq 0x65d1f(%rip), %rsi     # 0x98a3d
movl $0x596, %edx            # imm = 0x596
callq 0x4d037
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: zunionInterGetKeys
int *zunionInterGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {
    int i, num, *keys;
    REDIS_NOTUSED(cmd);

    num = atoi(argv[2]->ptr);
    /* Sanity check. Don't return any key if the command is going to
     * reply with syntax error. */
    if (num > (argc-3)) {
        *numkeys = 0;
        return NULL;
    }

    /* Keys in z{union,inter}store come from two places:
     * argv[1] = storage key,
     * argv[3...n] = keys to intersect */
    keys = zmalloc(sizeof(int)*(num+1));

    /* Add all key positions for argv[3...n] to keys[] */
    for (i = 0; i < num; i++) keys[i] = 3+i;

    /* Finally add the argv[1] key position (the storage key target). */
    keys[num] = 1;
    *numkeys = num+1;  /* Total keys = {union,inter} keys + storage key */
    return keys;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rcx, %rbx
movl %edx, %ebp
movq 0x10(%rsi), %rax
movq 0x8(%rax), %rdi
callq 0x1f710
addl $-0x3, %ebp
cmpl %ebp, %eax
jle 0x32d6d
xorl %r14d, %r14d
xorl %eax, %eax
jmp 0x32da3
movl %eax, %r14d
movslq %eax, %r15
leaq 0x4(,%r15,4), %rdi
callq 0x29709
testl %r14d, %r14d
jle 0x32d98
movl %r14d, %ecx
xorl %edx, %edx
leal 0x3(%rdx), %esi
movl %esi, (%rax,%rdx,4)
incq %rdx
cmpq %rdx, %rcx
jne 0x32d8a
incl %r14d
movl $0x1, (%rax,%r15,4)
movl %r14d, (%rbx)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: evalGetKeys
int *evalGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {
    int i, num, *keys;
    REDIS_NOTUSED(cmd);

    num = atoi(argv[2]->ptr);
    /* Sanity check. Don't return any key if the command is going to
     * reply with syntax error. */
    if (num > (argc-3)) {
        *numkeys = 0;
        return NULL;
    }

    keys = zmalloc(sizeof(int)*num);
    *numkeys = num;

    /* Add all key positions for argv[3...n] to keys[] */
    for (i = 0; i < num; i++) keys[i] = 3+i;

    return keys;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
movq %rcx, %rbx
movl %edx, %r14d
movq 0x10(%rsi), %rax
movq 0x8(%rax), %rdi
callq 0x1f710
addl $-0x3, %r14d
cmpl %r14d, %eax
jle 0x32ddb
movl $0x0, (%rbx)
xorl %eax, %eax
jmp 0x32e01
movl %eax, %ebp
movslq %eax, %rdi
shlq $0x2, %rdi
callq 0x29709
movl %ebp, (%rbx)
testl %ebp, %ebp
jle 0x32e01
movl %ebp, %ecx
xorl %edx, %edx
leal 0x3(%rdx), %esi
movl %esi, (%rax,%rdx,4)
incq %rdx
cmpq %rdx, %rcx
jne 0x32df3
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: sortGetKeys
int *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) {
    int i, j, num, *keys;
    REDIS_NOTUSED(cmd);

    num = 0;
    keys = zmalloc(sizeof(int)*2); /* Alloc 2 places for the worst case. */

    keys[num++] = 1; /* <sort-key> is always present. */

    /* Search for STORE option. By default we consider options to don't
     * have arguments, so if we find an unknown option name we scan the
     * next. However there are options with 1 or 2 arguments, so we
     * provide a list here in order to skip the right number of args. */
    struct {
        char *name;
        int skip;
    } skiplist[] = {
        {"limit", 2},
        {"get", 1},
        {"by", 1},
        {NULL, 0} /* End of elements. */
    };

    for (i = 2; i < argc; i++) {
        for (j = 0; skiplist[j].name != NULL; j++) {
            if (!strcasecmp(argv[i]->ptr,skiplist[j].name)) {
                i += skiplist[j].skip;
                break;
            } else if (!strcasecmp(argv[i]->ptr,"store") && i+1 < argc) {
                /* Note: we don't increment "num" here and continue the loop
                 * to be sure to process the *last* "STORE" option if multiple
                 * ones are provided. This is same behavior as SORT. */
                keys[num] = i+1; /* <store-key> */
                break;
            }
        }
    }
    *numkeys = num;
    return keys;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rcx, 0x18(%rsp)
movl %edx, %r14d
movq %rsi, 0x20(%rsp)
movl $0x8, %edi
callq 0x29709
movq %rax, 0x10(%rsp)
movl $0x1, (%rax)
cmpl $0x3, %r14d
jl 0x32ee8
movl $0x2, %r13d
leaq 0x90463(%rip), %rbp     # 0xc32b0
movl %r14d, 0xc(%rsp)
movslq %r13d, %rax
movq 0x20(%rsp), %rcx
movq (%rcx,%rax,8), %rax
movq 0x8(%rax), %rbx
movq %rbx, %rdi
leaq 0x66ad0(%rip), %rsi     # 0x9993c
callq 0x1f2e0
movq %rbp, %r15
testl %eax, %eax
je 0x32ec8
leal 0x1(%r13), %r12d
cmpl %r14d, %r12d
setge %r15b
movq %rbx, %rdi
leaq 0x61754(%rip), %rsi     # 0x945e1
callq 0x1f2e0
testl %eax, %eax
setne %r14b
orb %r15b, %r14b
xorl %ecx, %ecx
testb %r14b, %r14b
je 0x32ece
leaq 0x10(%rcx), %r15
cmpq $0x30, %r15
je 0x32ed7
movq 0x10(%rcx,%rbp), %rsi
movq %rbx, %rdi
callq 0x1f2e0
movq %r15, %rcx
testl %eax, %eax
jne 0x32e9d
addq %rbp, %r15
movl 0xc(%rsp), %r14d
addl 0x8(%r15), %r13d
jmp 0x32edc
movq 0x10(%rsp), %rax
movl %r12d, 0x4(%rax)
movl 0xc(%rsp), %r14d
incl %r13d
cmpl %r14d, %r13d
jl 0x32e52
movq 0x18(%rsp), %rax
movl $0x1, (%rax)
movq 0x10(%rsp), %rax
addq $0x28, %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/db.c
// Function: getKeysInSlot
unsigned int getKeysInSlot(unsigned int hashslot, robj **keys, unsigned int count) {
    zskiplistNode *n;
    zrangespec range;
    int j = 0;

    range.min = range.max = hashslot;
    range.minex = range.maxex = 0;

    // 定位到第一个属于指定 slot 的键上面
    n = zslFirstInRange(server.cluster->slots_to_keys, &range);
    // 遍历跳跃表，并保存属于指定 slot 的键
    // n && n->score 检查当前键是否属于指定 slot
    // && count-- 用来计数
    while(n && n->score == hashslot && count--) {
        // 记录键
        keys[j++] = n->obj;
        n = n->level[0].forward;
    }
    return j;
}

// Assembly:
pushq %rbp
pushq %rbx
subq $0x28, %rsp
movl %edx, %ebp
movl %edi, %eax
cvtsi2sd %rax, %xmm0
movq %rsi, %rbx
leaq 0x10(%rsp), %rsi
movsd %xmm0, 0x8(%rsi)
movsd %xmm0, 0x8(%rsp)
movsd %xmm0, (%rsi)
movq $0x0, 0x10(%rsi)
leaq 0x9706c(%rip), %rax     # 0xc9fa8
movq 0x7d0(%rax), %rax
movq 0x60028(%rax), %rdi
callq 0x3d4e8
testq %rax, %rax
je 0x32f87
movq %rax, %rcx
movl %ebp, %edx
xorl %eax, %eax
movsd 0x8(%rsp), %xmm1
movsd 0x8(%rcx), %xmm0
ucomisd %xmm1, %xmm0
jne 0x32f89
jp 0x32f89
cmpl %eax, %edx
je 0x32f89
movq (%rcx), %rsi
movq %rsi, (%rbx,%rax,8)
incq %rax
movq 0x18(%rcx), %rcx
testq %rcx, %rcx
jne 0x32f61
jmp 0x32f89
xorl %eax, %eax
addq $0x28, %rsp
popq %rbx
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: delKeysInSlot
unsigned int delKeysInSlot(unsigned int hashslot) {
    zskiplistNode *n;
    zrangespec range;
    int j = 0;

    range.min = range.max = hashslot;
    range.minex = range.maxex = 0;

    n = zslFirstInRange(server.cluster->slots_to_keys, &range);
    while(n && n->score == hashslot) {
        robj *key = n->obj;
        n = n->level[0].forward; /* Go to the next item before freeing it. */
        incrRefCount(key); /* Protect the object while freeing it. */
        dbDelete(&server.db[0],key);
        decrRefCount(key);
        j++;
    }
    return j;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %edi, %eax
cvtsi2sd %rax, %xmm0
leaq 0x10(%rsp), %rsi
movsd %xmm0, 0x8(%rsi)
movsd %xmm0, 0x8(%rsp)
movsd %xmm0, (%rsi)
movq $0x0, 0x10(%rsi)
leaq 0x96fe3(%rip), %r12     # 0xc9fa8
movq 0x7d0(%r12), %rax
movq 0x60028(%rax), %rdi
callq 0x3d4e8
testq %rax, %rax
je 0x33020
movq %rax, %r14
xorl %ebx, %ebx
movsd 0x8(%r14), %xmm0
ucomisd 0x8(%rsp), %xmm0
jne 0x33022
jp 0x33022
movq (%r14), %r15
movq 0x18(%r14), %r14
movq %r15, %rdi
callq 0x3041b
movq 0x10(%r12), %rdi
movq %r15, %rsi
callq 0x3174b
movq %r15, %rdi
callq 0x30834
incl %ebx
testq %r14, %r14
jne 0x32fe3
jmp 0x33022
xorl %ebx, %ebx
movl %ebx, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/db.c
// Function: countKeysInSlot
unsigned int countKeysInSlot(unsigned int hashslot) {
    zskiplist *zsl = server.cluster->slots_to_keys;
    zskiplistNode *zn;
    zrangespec range;
    int rank, count = 0;

    range.min = range.max = hashslot;
    range.minex = range.maxex = 0;

    /* Find first element in range */
    // 定位到第一个在指定 slot 上的键
    zn = zslFirstInRange(zsl, &range);

    /* Use rank of first element, if any, to determine preliminary count */
    // 使用第一个指定 slot 键的排位减去最后一个指定 slot 键的排位
    // 这一方法来计算 slot 键的数量
    // 类似区间算法

    // 第一个在指定 slot 上的键存在
    if (zn != NULL) {
        // 获取第一个键的排位
        rank = zslGetRank(zsl, zn->score, zn->obj);
        count = (zsl->length - (rank - 1));

        /* Find last element in range */
        // 获取最后一个指定 slot 的键
        zn = zslLastInRange(zsl, &range);

        /* Use rank of last element, if any, to determine the actual count */
        // 最后一个键存在
        if (zn != NULL) {
            // 获取排位
            rank = zslGetRank(zsl, zn->score, zn->obj);
            // 计算数量
            count -= (zsl->length - rank);
        }
    }

    return count;
}

// Assembly:
pushq %r14
pushq %rbx
subq $0x18, %rsp
leaq 0x96f6a(%rip), %rax     # 0xc9fa8
movq 0x7d0(%rax), %rax
movq 0x60028(%rax), %rbx
movl %edi, %eax
cvtsi2sd %rax, %xmm0
movq %rsp, %rsi
movsd %xmm0, 0x8(%rsi)
movsd %xmm0, (%rsi)
movq $0x0, 0x10(%rsi)
movq %rbx, %rdi
callq 0x3d4e8
testq %rax, %rax
je 0x330c1
movsd 0x8(%rax), %xmm0
movq (%rax), %rsi
movq %rbx, %rdi
callq 0x3d98d
movq 0x10(%rbx), %rcx
subq %rax, %rcx
movabsq $-0xffffffff, %r14      # imm = 0xFFFFFFFF00000001
addq %rcx, %r14
movq %rsp, %rsi
movq %rbx, %rdi
callq 0x3d5ad
testq %rax, %rax
je 0x330c4
movsd 0x8(%rax), %xmm0
movq (%rax), %rsi
movq %rbx, %rdi
callq 0x3d98d
addl %eax, %r14d
subl 0x10(%rbx), %r14d
jmp 0x330c4
xorl %r14d, %r14d
movl %r14d, %eax
addq $0x18, %rsp
popq %rbx
popq %r14
retq
nop
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/replication.c
// Function: feedReplicationBacklogWithObject
void feedReplicationBacklogWithObject(robj *o) {
    char llstr[REDIS_LONGSTR_SIZE];
    void *p;
    size_t len;

    if (o->encoding == REDIS_ENCODING_INT) {
        len = ll2string(llstr,sizeof(llstr),(long)o->ptr);
        p = llstr;
    } else {
        len = sdslen(o->ptr);
        p = o->ptr;
    }
    feedReplicationBacklog(p,len);
}

// Assembly:
pushq %rbx
subq $0x20, %rsp
movl $0xf0, %eax
andl (%rdi), %eax
movq 0x8(%rdi), %rdx
cmpl $0x10, %eax
jne 0x332e5
movq %rsp, %rbx
movl $0x15, %esi
movq %rbx, %rdi
callq 0x2fe12
movq %rbx, %rdx
jmp 0x332e8
movl -0x8(%rdx), %eax
movslq %eax, %rsi
movq %rdx, %rdi
callq 0x331fa
addq $0x20, %rsp
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/replication.c
// Function: refreshGoodSlavesCount
void refreshGoodSlavesCount(void) {
    listIter li;
    listNode *ln;
    int good = 0;

    if (!server.repl_min_slaves_to_write ||
        !server.repl_min_slaves_max_lag) return;

    listRewind(server.slaves,&li);
    while((ln = listNext(&li))) {
        redisClient *slave = ln->value;

        // 计算延迟值
        time_t lag = server.unixtime - slave->repl_ack_time;

        // 计入 GOOD
        if (slave->replstate == REDIS_REPL_ONLINE &&
            lag <= server.repl_min_slaves_max_lag) good++;
    }

    // 更新状态良好的从服务器数量
    server.repl_good_slaves_count = good;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0x10, %rsp
leaq 0x96500(%rip), %r14     # 0xc9fa8
cmpl $0x0, 0x638(%r14)
je 0x33b20
cmpl $0x0, 0x63c(%r14)
je 0x33b20
movq 0x1c0(%r14), %rdi
movq %rsp, %rbx
movq %rbx, %rsi
callq 0x205d2
movq %rbx, %rdi
callq 0x205ef
xorl %ebp, %ebp
testq %rax, %rax
je 0x33b19
movq %rsp, %rbx
movq 0x10(%rax), %rax
cmpl $0x9, 0x98(%rax)
jne 0x33b0c
movq 0x798(%r14), %rcx
subq 0xc8(%rax), %rcx
movslq 0x63c(%r14), %rax
xorl %edx, %edx
cmpq %rax, %rcx
setle %dl
addl %edx, %ebp
movq %rbx, %rdi
callq 0x205ef
testq %rax, %rax
jne 0x33ae0
movl %ebp, 0x640(%r14)
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
retq