LLM4Binary/decompile-bench-makefile huggingface dataset:
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/object.c
// Function: getLongDoubleFromObject
int getLongDoubleFromObject(robj *o, long double *target) {
    long double value;
    char *eptr;

    if (o == NULL) {
        value = 0;
    } else {

        redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);

        // RAW 编码，尝试从字符串中转换 long double
        if (sdsEncodedObject(o)) {
            errno = 0;
            value = strtold(o->ptr, &eptr);
            if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' ||
                errno == ERANGE || isnan(value))
                return REDIS_ERR;

        // INT 编码，直接保存
        } else if (o->encoding == REDIS_ENCODING_INT) {
            value = (long)o->ptr;

        } else {
            redisPanic("Unknown string encoding");
        }
    }

    *target = value;
    return REDIS_OK;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x20, %rsp
movq %rsi, %rbx
fldz
testq %rdi, %rdi
je 0x2f497
movq %rdi, %r14
fstp %st(0)
movl (%rdi), %eax
testb $0xf, %al
jne 0x2f4a9
shrl $0x4, %eax
andl $0xf, %eax
cmpl $0x8, %eax
je 0x2f435
cmpl $0x1, %eax
je 0x2f48c
testl %eax, %eax
jne 0x2f4c9
callq 0x1f810
movq %rax, %r15
andl $0x0, (%rax)
movq 0x8(%r14), %rdi
leaq 0x8(%rsp), %rsi
callq 0x1f0f0
fstpt 0x14(%rsp)
callq 0x1f550
movq (%rax), %rcx
movq 0x8(%r14), %rax
movsbq (%rax), %rdx
pushq $-0x1
popq %rax
testb $0x20, 0x1(%rcx,%rdx,2)
jne 0x2f49b
movq 0x8(%rsp), %rcx
cmpb $0x0, (%rcx)
jne 0x2f49b
cmpl $0x22, (%r15)
sete %cl
fldt 0x14(%rsp)
fucomi %st(0), %st
setp %dl
orb %cl, %dl
je 0x2f497
jmp 0x2f49d
movq 0x8(%r14), %rax
movq %rax, (%rsp)
fildll (%rsp)
fstpt (%rbx)
xorl %eax, %eax
fldz
fstp %st(0)
addq $0x20, %rsp
popq %rbx
popq %r14
popq %r15
retq
leaq 0x5d8a6(%rip), %rdx     # 0x8cd56
leaq 0x5de9c(%rip), %rcx     # 0x8d353
xorl %edi, %edi
movq %r14, %rsi
movl $0x344, %r8d            # imm = 0x344
callq 0x4980c
jmp 0x2f4e1
leaq 0x5df98(%rip), %rdi     # 0x8d468
leaq 0x5de7c(%rip), %rsi     # 0x8d353
movl $0x353, %edx            # imm = 0x353
callq 0x490e8
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/object.c
// Function: getLongDoubleFromObjectOrReply
int getLongDoubleFromObjectOrReply(redisClient *c, robj *o, long double *target, const char *msg) {

    long double value;

    if (getLongDoubleFromObject(o, &value) != REDIS_OK) {
        if (msg != NULL) {
            addReplyError(c,(char*)msg);
        } else {
            addReplyError(c,"value is not a valid float");
        }
        return REDIS_ERR;
    }

    *target = value;
    return REDIS_OK;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rcx, %rbx
movq %rdx, %r15
movq %rsi, %rax
movq %rdi, %r14
movq %rsp, %rsi
movq %rax, %rdi
callq 0x2f3f7
testl %eax, %eax
je 0x2f51a
testq %rbx, %rbx
je 0x2f524
movq %r14, %rdi
movq %rbx, %rsi
jmp 0x2f52e
fldt (%rsp)
fstpt (%r15)
xorl %eax, %eax
jmp 0x2f536
leaq 0x60172(%rip), %rsi     # 0x8f69d
movq %r14, %rdi
callq 0x2c2da
pushq $-0x1
popq %rax
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/object.c
// Function: getLongLongFromObject
int getLongLongFromObject(robj *o, long long *target) {
    long long value;
    char *eptr;

    if (o == NULL) {
        // o 为 NULL 时，将值设为 0 。
        value = 0;
    } else {

        // 确保对象为 REDIS_STRING 类型
        redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
        if (sdsEncodedObject(o)) {
            errno = 0;
            // T = O(N)
            value = strtoll(o->ptr, &eptr, 10);
            if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' ||
                errno == ERANGE)
                return REDIS_ERR;
        } else if (o->encoding == REDIS_ENCODING_INT) {
            // 对于 REDIS_ENCODING_INT 编码的整数值
            // 直接将它的值保存到 value 中
            value = (long)o->ptr;
        } else {
            redisPanic("Unknown string encoding");
        }
    }

    // 保存值到指针
    if (target) *target = value;

    // 返回结果标识符
    return REDIS_OK;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbx
xorl %r15d, %r15d
testq %rdi, %rdi
je 0x2f5c1
movq %rdi, %r14
movl (%rdi), %eax
testb $0xf, %al
jne 0x2f5d7
shrl $0x4, %eax
andl $0xf, %eax
cmpl $0x8, %eax
je 0x2f574
cmpl $0x1, %eax
je 0x2f5bd
testl %eax, %eax
jne 0x2f5f7
callq 0x1f810
movq %rax, %r12
andl $0x0, (%rax)
movq 0x8(%r14), %rdi
movq %rsp, %rsi
pushq $0xa
popq %rdx
callq 0x1fa70
movq %rax, %r15
callq 0x1f550
movq (%rax), %rcx
movq 0x8(%r14), %rax
movsbq (%rax), %rdx
pushq $-0x1
popq %rax
testb $0x20, 0x1(%rcx,%rdx,2)
jne 0x2f5cb
movq (%rsp), %rcx
cmpb $0x0, (%rcx)
jne 0x2f5cb
cmpl $0x22, (%r12)
jne 0x2f5c1
jmp 0x2f5cb
movq 0x8(%r14), %r15
testq %rbx, %rbx
je 0x2f5c9
movq %r15, (%rbx)
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x5d778(%rip), %rdx     # 0x8cd56
leaq 0x5dd6e(%rip), %rcx     # 0x8d353
xorl %edi, %edi
movq %r14, %rsi
movl $0x38a, %r8d            # imm = 0x38A
callq 0x4980c
jmp 0x2f60f
leaq 0x5de6a(%rip), %rdi     # 0x8d468
leaq 0x5dd4e(%rip), %rsi     # 0x8d353
movl $0x397, %edx            # imm = 0x397
callq 0x490e8
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/object.c
// Function: getLongLongFromObjectOrReply
int getLongLongFromObjectOrReply(redisClient *c, robj *o, long long *target, const char *msg) {

    long long value;

    // T = O(N)
    if (getLongLongFromObject(o, &value) != REDIS_OK) {
        if (msg != NULL) {
            addReplyError(c,(char*)msg);
        } else {
            addReplyError(c,"value is not an integer or out of range");
        }
        return REDIS_ERR;
    }

    *target = value;

    return REDIS_OK;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rcx, %rbx
movq %rdx, %r15
movq %rsi, %rax
movq %rdi, %r14
leaq 0x8(%rsp), %rsi
movq %rax, %rdi
callq 0x2f540
testl %eax, %eax
je 0x2f64a
testq %rbx, %rbx
je 0x2f656
movq %r14, %rdi
movq %rbx, %rsi
jmp 0x2f660
movq 0x8(%rsp), %rax
movq %rax, (%r15)
xorl %eax, %eax
jmp 0x2f668
leaq 0x5de25(%rip), %rsi     # 0x8d482
movq %r14, %rdi
callq 0x2c2da
pushq $-0x1
popq %rax
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/db.c
// Function: lookupKeyRead
robj *lookupKeyRead(redisDb *db, robj *key) {
    robj *val;

    // 检查 key 释放已经过期
    expireIfNeeded(db,key);

    // 从数据库中取出键的值
    val = lookupKey(db,key);

    // 更新命中/不命中信息
    if (val == NULL)
        server.stat_keyspace_misses++;
    else
        server.stat_keyspace_hits++;

    // 返回值
    return val;
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
callq 0x2f8d7
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2f85c
xorl %ecx, %ecx
testq %rax, %rax
sete %cl
leaq 0x976e1(%rip), %rdx     # 0xc6fa8
incq 0x368(%rdx,%rcx,8)
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O2/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 0x30ab1
xorl %ebp, %ebp
testq %rax, %rax
js 0x2f97d
leaq 0x976ac(%rip), %r12     # 0xc6fa8
cmpl $0x0, 0x2f0(%r12)
jne 0x2f97d
movq %rax, %r15
cmpq $0x0, 0x7f0(%r12)
je 0x2f91f
movq 0x808(%r12), %rax
jmp 0x2f924
callq 0x22843
cmpq $0x0, 0x650(%r12)
je 0x2f93a
xorl %ebp, %ebp
cmpq %r15, %rax
setg %bpl
jmp 0x2f97d
cmpq %r15, %rax
jle 0x2f97d
incq 0x358(%r12)
movq %r14, %rdi
movq %rbx, %rsi
callq 0x30cd9
movl 0x30(%r14), %ecx
leaq 0x5ad6a(%rip), %rsi     # 0x8a6c7
movl $0x100, %edi            # imm = 0x100
movq %rbx, %rdx
callq 0x5b488
movq %r14, %rdi
movq %rbx, %rsi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x2fc3b
movl %ebp, %eax
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/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 0x2f89e
movq %rax, %r15
testq %rax, %rax
jne 0x2f9d0
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2c10d
movq %r15, %rax
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O2/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 0x271ee
movq (%r15), %rdi
movq %rax, %rsi
movq %r14, %rdx
callq 0x21956
testl %eax, %eax
jne 0x2fa55
leaq 0x9756f(%rip), %rax     # 0xc6fa8
cmpl $0x0, 0x7bc(%rax)
je 0x2fa4f
movq %rbx, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x2fa7b
popq %rbx
popq %r14
popq %r15
retq
leaq 0x5dad6(%rip), %rdx     # 0x8d532
leaq 0x5effa(%rip), %rcx     # 0x8ea5d
xorl %edi, %edi
movq %rbx, %rsi
movl $0xaf, %r8d
callq 0x4980c
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/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 0x4cb17
leaq 0x97516(%rip), %rcx     # 0xc6fa8
movq 0x7d0(%rcx), %rcx
movq 0x60028(%rcx), %rdi
movl %eax, %eax
cvtsi2sd %rax, %xmm0
movq %rbx, %rsi
callq 0x3a577
movq %rbx, %rdi
popq %rbx
jmp 0x2eacc
// File: /workspace/github_c_makefile_star2_O2/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 0x21b64
testq %rax, %rax
je 0x2faeb
movq (%r15), %rdi
movq 0x8(%rbx), %rsi
movq %r14, %rdx
popq %rbx
popq %r14
popq %r15
jmp 0x21af4
leaq 0x5dc04(%rip), %rdx     # 0x8d6f6
leaq 0x5ef64(%rip), %rcx     # 0x8ea5d
xorl %edi, %edi
movq %rbx, %rsi
movl $0xc8, %r8d
callq 0x4980c
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/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 0x21b64
testq %rax, %rax
je 0x2fb9a
movq 0x8(%r14), %rdi
movq 0x8(%rbx), %rsi
callq 0x21c36
xorl %ecx, %ecx
testl %eax, %eax
sete %cl
movl %ecx, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
leaq 0x5db30(%rip), %rdx     # 0x8d6d1
leaq 0x5eeb5(%rip), %rcx     # 0x8ea5d
xorl %edi, %edi
movq %rbx, %rsi
movl $0x438, %r8d            # imm = 0x438
callq 0x4980c
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/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 0x2fd27
movq %rdx, %r14
movq %rsi, %rbx
movq %rdi, %r15
testb $-0x10, %al
jne 0x2fce7
cmpl $0x1, 0x4(%r14)
je 0x2fd18
movq %r14, %rdi
callq 0x2f087
movq %rax, %r12
movq 0x8(%rax), %rdi
movslq -0x8(%rdi), %rsi
callq 0x2e9ed
movq %rax, %r14
movq %r12, %rdi
callq 0x2ee1f
movq %r15, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x2fab8
movq %r14, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x5d028(%rip), %rdi     # 0x8cd56
leaq 0x5ed28(%rip), %rsi     # 0x8ea5d
movl $0x155, %edx            # imm = 0x155
callq 0x4906b
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/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:
pushq $-0x1
popq %rax
testl %esi, %esi
js 0x2fe16
leaq 0x971aa(%rip), %rcx     # 0xc6fa8
cmpl %esi, 0x480(%rcx)
jle 0x2fe16
movl %esi, %eax
shlq $0x6, %rax
addq 0x10(%rcx), %rax
movq %rax, 0x8(%rdi)
xorl %eax, %eax
retq
// File: /workspace/github_c_makefile_star2_O2/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
pushq $-0x1
popq %rdi
callq 0x48922
xorl %edi, %edi
callq 0x2fd47
leaq 0x970fd(%rip), %r14     # 0xc6fa8
addq %rax, 0x560(%r14)
leaq 0x97947(%rip), %rax     # 0xc7800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
callq 0x2c10d
movl 0x570(%r14), %edi
cmpl $-0x1, %edi
je 0x2fee5
pushq $0xa
popq %rsi
callq 0x1f620
movl 0x570(%r14), %edi
callq 0x351f9
cmpl $0x0, 0x580(%r14)
movq 0x560(%r14), %rbx
jle 0x2ff05
movq 0x588(%r14), %rdi
callq 0x34d06
movslq %ebx, %rbx
incq %rbx
movq %rbx, 0x560(%r14)
addq $0x8, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O2/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 %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
xorl %r15d, %r15d
pushq $0x1
popq %r12
leaq 0x5a56a(%rip), %r14     # 0x8a49d
pushq $0x4
popq %rbp
leaq 0x9706b(%rip), %r13     # 0xc6fa8
movslq 0x30(%rbx), %rax
cmpq %rax, %r12
jge 0x2ffa5
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq (%rax,%r12,8), %rsi
callq 0x2f8d7
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq (%rax,%r12,8), %rsi
callq 0x2fc3b
testl %eax, %eax
je 0x2ffa0
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq (%rax,%r12,8), %rsi
callq 0x488d7
movq 0x8(%rbx), %rax
movq 0x38(%rbx), %rcx
movq (%rcx,%r12,8), %rdx
movl 0x30(%rax), %ecx
movl %ebp, %edi
movq %r14, %rsi
callq 0x5b488
incq 0x560(%r13)
incl %r15d
incq %r12
jmp 0x2ff3d
movslq %r15d, %rsi
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2c794
// File: /workspace/github_c_makefile_star2_O2/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 0x5d52e(%rip), %rcx     # 0x8d545
leaq 0x8(%rsp), %rdx
callq 0x2f672
testl %eax, %eax
jne 0x30096
leaq 0x96f7c(%rip), %rax     # 0xc6fa8
cmpl $0x0, 0x7bc(%rax)
setne %dl
movq 0x8(%rsp), %rcx
testq %rcx, %rcx
setne %sil
andb %dl, %sil
cmpb $0x1, %sil
jne 0x30054
leaq 0x5d504(%rip), %rsi     # 0x8d556
jmp 0x3008e
testl %ecx, %ecx
js 0x30087
cmpl %ecx, 0x480(%rax)
jle 0x30087
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
shlq $0x6, %rcx
addq 0x10(%rax), %rcx
movq %rcx, 0x8(%rbx)
leaq 0x97787(%rip), %rax     # 0xc7800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
callq 0x2c10d
jmp 0x30096
leaq 0x5d4b7(%rip), %rsi     # 0x8d545
movq %rbx, %rdi
callq 0x2c2da
addq $0x10, %rsp
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O2/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 0x3020a
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x4, %eax
je 0x3023c
cmpl $0x3, %eax
je 0x3021e
cmpl $0x2, %eax
jne 0x30281
movq (%r15), %r14
movq %r14, %rdi
callq 0x2eacc
jmp 0x30219
movq (%r15), %rdi
movslq -0x8(%rdi), %rsi
callq 0x2ea81
movq %rax, %r14
xorl %r15d, %r15d
jmp 0x30253
movq (%r15), %r14
movq %r14, %rdi
callq 0x2eacc
movq 0x8(%r15), %rax
fldl (%rax)
fstpt (%rsp)
callq 0x2ead0
movq %rax, %r15
jmp 0x30253
movq (%r15), %r14
movq %r14, %rdi
callq 0x2eacc
movq 0x8(%r15), %r15
movq %r15, %rdi
callq 0x2eacc
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1fe4c
testq %r15, %r15
je 0x30277
movq %rbx, %rdi
movq %r15, %rsi
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
jmp 0x1fe4c
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
leaq 0x5d2f4(%rip), %rdi     # 0x8d57c
leaq 0x5e7ce(%rip), %rsi     # 0x8ea5d
movl $0x267, %edx            # imm = 0x267
callq 0x490e8
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/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
andl $0x0, (%rax)
movq 0x8(%r12), %rdi
movq %rsp, %rsi
pushq $0xa
popq %rdx
callq 0x1fba0
movq %rax, (%r15)
callq 0x1f550
movq (%rax), %rax
movq 0x8(%r12), %rcx
movsbq (%rcx), %rcx
testb $0x20, 0x1(%rax,%rcx,2)
jne 0x302f9
movq (%rsp), %rax
cmpb $0x0, (%rax)
jne 0x302f9
xorl %eax, %eax
cmpl $0x22, (%r14)
jne 0x3030b
leaq 0x5d2a1(%rip), %rsi     # 0x8d5a1
movq %rbx, %rdi
callq 0x2c2da
pushq $-0x1
popq %rax
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/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 0x2f89e
testq %rax, %rax
je 0x30862
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x4, %eax
ja 0x3086b
leaq 0x5cec7(%rip), %rcx     # 0x8d720
movslq (%rcx,%rax,4), %rsi
addq %rcx, %rsi
jmp 0x30872
leaq 0x5cdf1(%rip), %rsi     # 0x8d65a
jmp 0x30872
leaq 0x5cc70(%rip), %rsi     # 0x8d4e2
movq %rbx, %rdi
popq %rbx
jmp 0x2c423
// File: /workspace/github_c_makefile_star2_O2/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 %rbp
pushq %r14
pushq %rbx
movq %rdi, %rbx
movl 0x30(%rdi), %eax
cmpl $0x3, %eax
jl 0x308a4
leaq 0x96f6f(%rip), %rax     # 0xc7800
movq 0x80(%rax), %rsi
movq %rbx, %rdi
popq %rbx
popq %r14
popq %rbp
jmp 0x2c10d
xorl %edi, %edi
pushq $0x2
popq %rbp
cmpl $0x2, %eax
jne 0x308e5
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %r14
leaq 0x5cda8(%rip), %rsi     # 0x8d669
movq %r14, %rdi
callq 0x1f2e0
movl %ebp, %edi
testl %eax, %eax
je 0x308e5
leaq 0x5d31b(%rip), %rsi     # 0x8dbf1
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
jne 0x3088a
pushq $0x1
popq %rdi
leaq 0x966bc(%rip), %rax     # 0xc6fa8
movl 0x84(%rax), %ecx
orl 0x2f0(%rax), %ecx
cmovnel %ebp, %edi
xorl %eax, %eax
callq 0x2577d
testl %eax, %eax
je 0x30919
leaq 0x5cd63(%rip), %rsi     # 0x8d670
movq %rbx, %rdi
popq %rbx
popq %r14
popq %rbp
jmp 0x2c2da
xorl %edi, %edi
callq 0x1f2b0
// File: /workspace/github_c_makefile_star2_O2/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
pushq $-0x1
popq %r14
addq 0x48(%rdi), %rax
je 0x30af8
movq %rsi, %rbx
movq 0x8(%rsi), %rsi
callq 0x21b64
testq %rax, %rax
je 0x30af8
movq %rax, %r12
movq (%r15), %rdi
movq 0x8(%rbx), %rsi
callq 0x21b64
testq %rax, %rax
je 0x30b07
movq 0x8(%r12), %r14
movq %r14, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x5cbc3(%rip), %rdx     # 0x8d6d1
leaq 0x5df48(%rip), %rcx     # 0x8ea5d
xorl %edi, %edi
movq %rbx, %rsi
movl $0x465, %r8d            # imm = 0x465
callq 0x4980c
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/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 0x21b64
testq %rax, %rax
je 0x30b62
movq 0x8(%r15), %rdi
movq (%rax), %rsi
callq 0x21c08
movq %rbx, 0x8(%rax)
popq %rbx
popq %r14
popq %r15
retq
leaq 0x5cb8c(%rip), %rdx     # 0x8d6f5
leaq 0x5deed(%rip), %rcx     # 0x8ea5d
xorl %edi, %edi
movq %r14, %rsi
movl $0x449, %r8d            # imm = 0x449
callq 0x4980c
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/db.c
// Function: moveCommand
void moveCommand(redisClient *c) {
    robj *o;
    redisDb *src, *dst;
    int srcid;

    if (server.cluster_enabled) {
        addReplyError(c,"MOVE is not allowed in cluster mode");
        return;
    }

    /* Obtain source and target DB pointers */
    // 源数据库
    src = c->db;
    // 源数据库的 id
    srcid = c->db->id;

    // 切换到目标数据库
    if (selectDb(c,atoi(c->argv[2]->ptr)) == REDIS_ERR) {
        addReply(c,shared.outofrangeerr);
        return;
    }

    // 目标数据库
    dst = c->db;

    // 切换回源数据库
    selectDb(c,srcid); /* Back to the source DB */

    /* If the user is moving using as target the same
     * DB as the source DB it is probably an error. */
    // 如果源数据库和目标数据库相等，那么返回错误
    if (src == dst) {
        addReply(c,shared.sameobjecterr);
        return;
    }

    /* Check if the element exists and get a reference */
    // 取出要移动的对象
    o = lookupKeyWrite(c->db,c->argv[1]);
    if (!o) {
        addReply(c,shared.czero);
        return;
    }

    /* Return zero if the key already exists in the target DB */
    // 如果键已经存在于目标数据库，那么返回
    if (lookupKeyWrite(dst,c->argv[1]) != NULL) {
        addReply(c,shared.czero);
        return;
    }

    // 将键添加到目标数据库中
    dbAdd(dst,c->argv[1],o);
    // 增加对对象的引用计数，避免接下来在源数据库中删除时 o 被清理
    incrRefCount(o);

    /* OK! key moved, free the entry in the source DB */
    // 将键从源数据库中返回
    dbDelete(src,c->argv[1]);

    server.dirty++;

    addReply(c,shared.cone);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
leaq 0x963fc(%rip), %r13     # 0xc6fa8
cmpl $0x0, 0x7bc(%r13)
je 0x30bd3
leaq 0x5caf0(%rip), %rsi     # 0x8d6ad
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2c2da
movq 0x8(%rbx), %r14
movq 0x38(%rbx), %r12
movl 0x30(%r14), %ebp
movq 0x10(%r12), %rax
movq 0x8(%rax), %rdi
callq 0x1f710
testl %eax, %eax
js 0x30c66
cmpl %eax, 0x480(%r13)
jle 0x30c66
movq 0x10(%r13), %rcx
movl %eax, %r15d
shlq $0x6, %r15
addq %rcx, %r15
movq %r15, 0x8(%rbx)
movq %r15, %rdi
testl %ebp, %ebp
js 0x30c2d
movq %r15, %rdi
cmpl %ebp, 0x480(%r13)
jle 0x30c2d
shlq $0x6, %rbp
addq %rbp, %rcx
movq %rcx, 0x8(%rbx)
movq %rcx, %rdi
cmpq %r15, %r14
je 0x30c76
movq 0x8(%r12), %rsi
callq 0x2f988
testq %rax, %rax
je 0x30c59
movq %rax, %r12
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
movq %r15, %rdi
callq 0x2f988
testq %rax, %rax
je 0x30c86
leaq 0x96ba0(%rip), %rax     # 0xc7800
movq 0x20(%rax), %rsi
jmp 0x30cc3
leaq 0x96b93(%rip), %rax     # 0xc7800
movq 0x90(%rax), %rsi
jmp 0x30cc3
leaq 0x96b83(%rip), %rax     # 0xc7800
movq 0x88(%rax), %rsi
jmp 0x30cc3
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
movq %r15, %rdi
movq %r12, %rdx
callq 0x2fa09
movq %r12, %rdi
callq 0x2eacc
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
movq %r14, %rdi
callq 0x2fc3b
incq 0x560(%r13)
leaq 0x96b41(%rip), %rax     # 0xc7800
movq 0x28(%rax), %rsi
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2c10d
// File: /workspace/github_c_makefile_star2_O2/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 %rsi, %r14
movq %rdi, %rbx
leaq 0x96b13(%rip), %rax     # 0xc7800
movq 0x128(%rax), %rdi
movq %rdi, (%rsp)
movq %rsi, 0x8(%rsp)
callq 0x2eacc
movq %r14, %rdi
callq 0x2eacc
leaq 0x96297(%rip), %r14     # 0xc6fa8
cmpl $0x0, 0x4d0(%r14)
je 0x30d30
movq 0x318(%r14), %rdi
movl 0x30(%rbx), %esi
movq %rsp, %rdx
pushq $0x2
popq %rcx
callq 0x46371
movq 0x1c0(%r14), %rdi
movl 0x30(%rbx), %esi
movq %rsp, %rbx
pushq $0x2
popq %rcx
movq %rbx, %rdx
callq 0x31639
movq (%rbx), %rdi
callq 0x2ee1f
movq 0x8(%rbx), %rdi
callq 0x2ee1f
addq $0x18, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O2/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 %r14
pushq %rbx
movl %esi, %ebp
movq %rdi, %rbx
movq 0x8(%rdi), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x2f89e
testq %rax, %rax
je 0x30fb2
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x30ab1
cmpq $-0x1, %rax
je 0x30fb6
movq %rax, %r14
callq 0x22843
subq %rax, %r14
xorl %esi, %esi
testq %r14, %r14
cmovgq %r14, %rsi
testl %ebp, %ebp
jne 0x30fb9
addq $0x1f4, %rsi            # imm = 0x1F4
movl $0x3e8, %ecx            # imm = 0x3E8
movq %rsi, %rax
xorl %edx, %edx
divq %rcx
movq %rax, %rsi
jmp 0x30fb9
pushq $-0x2
jmp 0x30fb8
pushq $-0x1
popq %rsi
movq %rbx, %rdi
popq %rbx
popq %r14
popq %rbp
jmp 0x2c794
// File: /workspace/github_c_makefile_star2_O2/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 0x21b64
testq %rax, %rax
je 0x3102d
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x2fb61
testl %eax, %eax
je 0x3102d
leaq 0x967ef(%rip), %rax     # 0xc7800
movq 0x28(%rax), %rsi
movq %rbx, %rdi
callq 0x2c10d
leaq 0x95f84(%rip), %rax     # 0xc6fa8
incq 0x560(%rax)
popq %rbx
retq
leaq 0x967cc(%rip), %rax     # 0xc7800
movq 0x20(%rax), %rsi
movq %rbx, %rdi
popq %rbx
jmp 0x2c10d
// File: /workspace/github_c_makefile_star2_O2/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 %rbx
pushq %rax
movq %rcx, %rbx
movl 0x30(%rdi), %eax
testl %eax, %eax
je 0x31095
movl %edx, %ebp
movq %rdi, %r14
movl 0x34(%rdi), %ecx
movl %ecx, %r15d
sarl $0x1f, %r15d
andl %edx, %r15d
addl %ecx, %r15d
movl %r15d, %ecx
subl %eax, %ecx
incl %ecx
movslq %ecx, %rdi
shlq $0x2, %rdi
callq 0x2828d
movl 0x30(%r14), %edx
xorl %ecx, %ecx
cmpl %r15d, %edx
jg 0x31099
cmpl %ebp, %edx
jge 0x310a6
movl %edx, (%rax,%rcx,4)
incq %rcx
addl 0x38(%r14), %edx
jmp 0x31080
xorl %ecx, %ecx
xorl %eax, %eax
movl %ecx, (%rbx)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
leaq 0x5c668(%rip), %rdi     # 0x8d715
leaq 0x5d9a9(%rip), %rsi     # 0x8ea5d
movl $0x596, %edx            # imm = 0x596
callq 0x4906b
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/replication.c
// Function: createReplicationBacklog
void createReplicationBacklog(void) {

    redisAssert(server.repl_backlog == NULL);

    // backlog
    server.repl_backlog = zmalloc(server.repl_backlog_size);
    // 数据长度
    server.repl_backlog_histlen = 0;
    // 索引值，增加数据时使用
    server.repl_backlog_idx = 0;
    /* When a new backlog buffer is created, we increment the replication
     * offset by one to make sure we'll not be able to PSYNC with any
     * previous slave. This is needed because we avoid incrementing the
     * master_repl_offset if no backlog exists nor slaves are attached. */
    // 每次创建 backlog 时都将 master_repl_offset 增一
    // 这是为了防止之前使用过 backlog 的从服务器引发错误的 PSYNC 请求
    server.master_repl_offset++;

    /* We don't have any data inside our buffer, but virtually the first
     * byte we have is the next byte that will be generated for the
     * replication stream. */
    // 尽管没有任何数据，
    // 但 backlog 第一个字节的逻辑位置应该是 repl_offset 后的第一个字节
    server.repl_backlog_off = server.master_repl_offset+1;
}

// Assembly:
pushq %rbx
leaq 0x95b8c(%rip), %rbx     # 0xc6fa8
cmpq $0x0, 0x600(%rbx)
jne 0x31462
movq 0x608(%rbx), %rdi
callq 0x2828d
movq %rax, 0x600(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x610(%rbx)
movq 0x5f0(%rbx), %rax
leaq 0x1(%rax), %rcx
movq %rcx, 0x5f0(%rbx)
addq $0x2, %rax
movq %rax, 0x620(%rbx)
popq %rbx
retq
leaq 0x5c2cb(%rip), %rdi     # 0x8d734
leaq 0x5c2e0(%rip), %rsi     # 0x8d750
pushq $0x33
popq %rdx
callq 0x4906b
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/replication.c
// Function: feedReplicationBacklog
void feedReplicationBacklog(void *ptr, size_t len) {
    unsigned char *p = ptr;

    // 将长度累加到全局 offset 中
    server.master_repl_offset += len;

    /* This is a circular buffer, so write as much data we can at every
     * iteration and rewind the "idx" index if we reach the limit. */
    // 环形 buffer ，每次写尽可能多的数据，并在到达尾部时将 idx 重置到头部
    while(len) {
        // 从 idx 到 backlog 尾部的字节数
        size_t thislen = server.repl_backlog_size - server.repl_backlog_idx;
        // 如果 idx 到 backlog 尾部这段空间足以容纳要写入的内容
        // 那么直接将写入数据长度设为 len
        // 在将这些 len 字节复制之后，这个 while 循环将跳出
        if (thislen > len) thislen = len;
        // 将 p 中的 thislen 字节内容复制到 backlog
        memcpy(server.repl_backlog+server.repl_backlog_idx,p,thislen);
        // 更新 idx ，指向新写入的数据之后
        server.repl_backlog_idx += thislen;
        // 如果写入达到尾部，那么将索引重置到头部
        if (server.repl_backlog_idx == server.repl_backlog_size)
            server.repl_backlog_idx = 0;
        // 减去已写入的字节数
        len -= thislen;
        // 将指针移动到已被写入数据的后面，指向未被复制数据的开头
        p += thislen;
        // 增加实际长度
        server.repl_backlog_histlen += thislen;
    }
    // histlen 的最大值只能等于 backlog_size
    // 另外，当 histlen 大于 repl_backlog_size 时，
    // 表示写入数据的前头有一部分数据被自己的尾部覆盖了
    // 举个例子，例如 abcde 要写入到一个只有三个字节的环形数组中
    // 且假设索引为 0
    // 那么 abc 首先被写入，数组为 [a, b, c] 
    // 然后 de 被写入，数组为 [d, e, c]
    if (server.repl_backlog_histlen > server.repl_backlog_size)
        server.repl_backlog_histlen = server.repl_backlog_size;
    /* Set the offset of the first byte we have in the backlog. */
    // 记录程序可以依靠 backlog 来还原的数据的第一个字节的偏移量
    // 比如 master_repl_offset = 10086
    // repl_backlog_histlen = 30
    // 那么 backlog 所保存的数据的第一个字节的偏移量为
    // 10086 - 30 + 1 = 10056 + 1 = 10057
    // 这说明如果从服务器如果从 10057 至 10086 之间的任何时间断线
    // 那么从服务器都可以使用 PSYNC
    server.repl_backlog_off = server.master_repl_offset -
                              server.repl_backlog_histlen + 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movl $0x5f0, %eax            # imm = 0x5F0
addq 0x91a68(%rip), %rax     # 0xc2fb8
leaq 0x95a51(%rip), %r15     # 0xc6fa8
xorl %r12d, %r12d
leaq 0x610(%r15), %r13
movq %rsi, %rbp
addq %r14, (%rax)
testq %rbp, %rbp
je 0x315bd
movq 0x608(%r15), %r14
movq 0x618(%r15), %rdi
subq %rdi, %r14
cmpq %rbp, %r14
cmovaeq %rbp, %r14
addq 0x600(%r15), %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x1fbd0
movq 0x618(%r15), %rax
addq %r14, %rax
cmpq 0x608(%r15), %rax
cmoveq %r12, %rax
movq %rax, 0x618(%r15)
subq %r14, %rbp
addq %r14, %rbx
movq %r13, %rax
jmp 0x31564
movq 0x608(%r15), %rcx
movq 0x610(%r15), %rax
cmpq %rcx, %rax
jle 0x315da
movq %rcx, 0x610(%r15)
movq %rcx, %rax
movq 0x5f0(%r15), %rcx
subq %rax, %rcx
incq %rcx
movq %rcx, 0x620(%r15)
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/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 0x31625
movq %rsp, %rbx
pushq $0x15
popq %rsi
movq %rbx, %rdi
callq 0x2e511
movq %rbx, %rdx
jmp 0x31628
movl -0x8(%rdx), %eax
movslq %eax, %rsi
movq %rdx, %rdi
callq 0x31533
addq $0x20, %rsp
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O2/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 0x9521b(%rip), %r14     # 0xc6fa8
cmpl $0x0, 0x638(%r14)
je 0x31df7
cmpl $0x0, 0x63c(%r14)
je 0x31df7
movq 0x1c0(%r14), %rdi
movq %rsp, %rbx
movq %rbx, %rsi
callq 0x1ffac
xorl %ebp, %ebp
movq %rbx, %rdi
callq 0x1ffc6
testq %rax, %rax
je 0x31df0
movq 0x10(%rax), %rax
cmpl $0x9, 0x98(%rax)
jne 0x31db5
movq 0x798(%r14), %rcx
subq 0xc8(%rax), %rcx
movslq 0x63c(%r14), %rax
xorl %edx, %edx
cmpq %rax, %rcx
setle %dl
addl %edx, %ebp
jmp 0x31db5
movl %ebp, 0x640(%r14)
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/replication.c
// Function: replicationSendAck
void replicationSendAck(void) {
    redisClient *c = server.master;

    if (c != NULL) {
        c->flags |= REDIS_MASTER_FORCE_REPLY;
        addReplyMultiBulkLen(c,3);
        addReplyBulkCString(c,"REPLCONF");
        addReplyBulkCString(c,"ACK");
        // 发送偏移量
        addReplyBulkLongLong(c,c->reploff);
        c->flags &= ~REDIS_MASTER_FORCE_REPLY;
    }
}

// Assembly:
pushq %rbx
leaq 0x94e08(%rip), %rax     # 0xc6fa8
movq 0x660(%rax), %rbx
testq %rbx, %rbx
je 0x321f2
orb $0x20, 0x91(%rbx)
pushq $0x3
popq %rsi
movq %rbx, %rdi
callq 0x2c7c7
leaq 0x5866f(%rip), %rsi     # 0x8a834
movq %rbx, %rdi
callq 0x2c6b4
leaq 0x5866c(%rip), %rsi     # 0x8a840
movq %rbx, %rdi
callq 0x2c6b4
movq 0xb8(%rbx), %rsi
movq %rbx, %rdi
callq 0x2c8bb
andb $-0x21, 0x91(%rbx)
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/replication.c
// Function: replicationAbortSyncTransfer
void replicationAbortSyncTransfer(void) {
    redisAssert(server.repl_state == REDIS_REPL_TRANSFER);

    aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE);
    close(server.repl_transfer_s);
    close(server.repl_transfer_fd);
    unlink(server.repl_transfer_tmpfile);
    zfree(server.repl_transfer_tmpfile);
    server.repl_state = REDIS_REPL_CONNECT;
}

// Assembly:
pushq %rbx
leaq 0x949cf(%rip), %rbx     # 0xc6fa8
cmpl $0x4, 0x674(%rbx)
jne 0x3262e
movq 0x28(%rbx), %rdi
movl 0x690(%rbx), %esi
pushq $0x1
popq %rdx
callq 0x203cd
movl 0x690(%rbx), %edi
callq 0x1f170
movl 0x694(%rbx), %edi
callq 0x1f170
movq 0x698(%rbx), %rdi
callq 0x1f3a0
movq 0x698(%rbx), %rdi
callq 0x283cd
movl $0x1, 0x674(%rbx)
popq %rbx
retq
leaq 0x5b75e(%rip), %rdi     # 0x8dd93
leaq 0x5b114(%rip), %rsi     # 0x8d750
movl $0x38d, %edx            # imm = 0x38D
callq 0x4906b
pushq $0x1
popq %rdi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/replication.c
// Function: replicationDiscardCachedMaster
void replicationDiscardCachedMaster(void) {

    if (server.cached_master == NULL) return;

    redisLog(REDIS_NOTICE,"Discarding previously cached master state.");
    server.cached_master->flags &= ~REDIS_MASTER;
    freeClient(server.cached_master);
    server.cached_master = NULL;
}

// Assembly:
pushq %rbx
leaq 0x94167(%rip), %rbx     # 0xc6fa8
cmpq $0x0, 0x668(%rbx)
je 0x32e77
leaq 0x5b8fb(%rip), %rsi     # 0x8e74d
pushq $0x2
popq %rdi
xorl %eax, %eax
callq 0x22613
movq 0x668(%rbx), %rdi
andl $-0x3, 0x90(%rdi)
callq 0x2cb56
andq $0x0, 0x668(%rbx)
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/replication.c
// Function: replicationResurrectCachedMaster
void replicationResurrectCachedMaster(int newfd) {
    
    // 设置 master
    server.master = server.cached_master;
    server.cached_master = NULL;

    server.master->fd = newfd;

    server.master->flags &= ~(REDIS_CLOSE_AFTER_REPLY|REDIS_CLOSE_ASAP);

    server.master->authenticated = 1;
    server.master->lastinteraction = server.unixtime;

    // 回到已连接状态
    server.repl_state = REDIS_REPL_CONNECTED;

    /* Re-add to the list of clients. */
    // 将 master 重新加入到客户端列表中
    listAddNodeTail(server.clients,server.master);
    // 监听 master 的读事件
    if (aeCreateFileEvent(server.el, newfd, AE_READABLE,
                          readQueryFromClient, server.master)) {
        redisLog(REDIS_WARNING,"Error resurrecting the cached master, impossible to add the readable handler: %s", strerror(errno));
        freeClientAsync(server.master); /* Close ASAP. */
    }

    /* We may also need to install the write handler as well if there is
     * pending data in the write buffers. */
    if (server.master->bufpos || listLength(server.master->reply)) {
        if (aeCreateFileEvent(server.el, newfd, AE_WRITABLE,
                          sendReplyToClient, server.master)) {
            redisLog(REDIS_WARNING,"Error resurrecting the cached master, impossible to add the writable handler: %s", strerror(errno));
            freeClientAsync(server.master); /* Close ASAP. */
        }
    }
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movl %edi, %ebx
leaq 0x94122(%rip), %r14     # 0xc6fa8
movq 0x668(%r14), %rsi
movq %rsi, 0x660(%r14)
andq $0x0, 0x668(%r14)
movl %edi, (%rsi)
andl $0xfffffbbf, 0x90(%rsi) # imm = 0xFFFFFBBF
movl $0x1, 0x94(%rsi)
movq 0x798(%r14), %rax
movq %rax, 0x80(%rsi)
movl $0x5, 0x674(%r14)
movq 0x1b0(%r14), %rdi
callq 0x1fe4c
movq 0x28(%r14), %rdi
movq 0x660(%r14), %r8
leaq -0x7549(%rip), %rcx     # 0x2b9a0
pushq $0x1
popq %rdx
movl %ebx, %esi
callq 0x2030c
testl %eax, %eax
je 0x32f23
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x5b86e(%rip), %rsi     # 0x8e778
pushq $0x3
popq %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x22613
movq 0x660(%r14), %rdi
callq 0x2ced9
movq 0x660(%r14), %r8
cmpl $0x0, 0x170(%r8)
jne 0x32f3f
movq 0x60(%r8), %rax
cmpq $0x0, 0x28(%rax)
je 0x32f8b
movq 0x28(%r14), %rdi
leaq -0x73ab(%rip), %rcx     # 0x2bb9f
pushq $0x2
popq %rdx
movl %ebx, %esi
callq 0x2030c
testl %eax, %eax
je 0x32f8b
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x5b85e(%rip), %rsi     # 0x8e7c9
pushq $0x3
popq %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x22613
movq 0x660(%r14), %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x2ced9
addq $0x8, %rsp
popq %rbx
popq %r14
retq