// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: rdbSaveBackground
int rdbSaveBackground(char *filename) {
    pid_t childpid;
    long long start;

    // 如果 BGSAVE 已经在执行，那么出错
    if (server.rdb_child_pid != -1) return REDIS_ERR;

    // 记录 BGSAVE 执行前的数据库被修改次数
    server.dirty_before_bgsave = server.dirty;

    // 最近一次尝试执行 BGSAVE 的时间
    server.lastbgsave_try = time(NULL);

    // fork() 开始前的时间，记录 fork() 返回耗时用
    start = ustime();

    if ((childpid = fork()) == 0) {
        int retval;

        /* Child */

        // 关闭网络连接 fd
        closeListeningSockets(0);

        // 设置进程的标题，方便识别
        redisSetProcTitle("redis-rdb-bgsave");

        // 执行保存操作
        retval = rdbSave(filename);

        // 打印 copy-on-write 时使用的内存数
        if (retval == REDIS_OK) {
            size_t private_dirty = zmalloc_get_private_dirty();

            if (private_dirty) {
                redisLog(REDIS_NOTICE,
                    "RDB: %zu MB of memory used by copy-on-write",
                    private_dirty/(1024*1024));
            }
        }

        // 向父进程发送信号
        exitFromChild((retval == REDIS_OK) ? 0 : 1);

    } else {

        /* Parent */

        // 计算 fork() 执行的时间
        server.stat_fork_time = ustime()-start;

        // 如果 fork() 出错，那么报告错误
        if (childpid == -1) {
            server.lastbgsave_status = REDIS_ERR;
            redisLog(REDIS_WARNING,"Can't save in background: fork: %s",
                strerror(errno));
            return REDIS_ERR;
        }

        // 打印 BGSAVE 开始的日志
        redisLog(REDIS_NOTICE,"Background saving started by pid %d",childpid);

        // 记录数据库开始 BGSAVE 的时间
        server.rdb_save_time_start = time(NULL);

        // 记录负责执行 BGSAVE 的子进程 ID
        server.rdb_child_pid = childpid;

        // 关闭自动 rehash
        updateDictResizePolicy();

        return REDIS_OK;
    }

    return REDIS_OK; /* unreached */
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
leaq 0x92771(%rip), %r12     # 0xc9fa8
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
cmpl $-0x1, 0x570(%r12)
je 0x37852
movl %ebx, %eax
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movq %rdi, %r14
movq 0x560(%r12), %rax
movq %rax, 0x568(%r12)
xorl %edi, %edi
callq 0x1fc50
movq %rax, 0x5a0(%r12)
callq 0x2343e
movq %rax, %r15
callq 0x1fa30
testl %eax, %eax
je 0x378d8
movl %eax, %ebp
callq 0x2343e
subq %r15, %rax
movq %rax, 0x380(%r12)
cmpl $-0x1, %ebp
je 0x37931
leaq 0x6138d(%rip), %rsi     # 0x98c34
xorl %ebx, %ebx
movl $0x2, %edi
movl %ebp, %edx
xorl %eax, %eax
callq 0x23223
xorl %edi, %edi
callq 0x1fc50
movq %rax, 0x5b0(%r12)
movl %ebp, 0x570(%r12)
callq 0x23747
jmp 0x37847
xorl %ebx, %ebx
xorl %edi, %edi
callq 0x267d6
leaq 0x612ec(%rip), %rdi     # 0x98bd4
callq 0x27fbf
movq %r14, %rdi
callq 0x37460
movl %eax, %ebp
testl %eax, %eax
jne 0x3791f
callq 0x29cb7
testq %rax, %rax
je 0x3791f
shrq $0x14, %rax
leaq 0x612d5(%rip), %rsi     # 0x98be5
movl $0x2, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0x23223
xorl %edi, %edi
testl %ebp, %ebp
setne %dil
callq 0x2349f
jmp 0x37847
movl $0xffffffff, 0x5b8(%r12) # imm = 0xFFFFFFFF
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x612c1(%rip), %rsi     # 0x98c11
movl $0x3, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0x23223
jmp 0x37847