// File: /workspace/github_c_makefile_star2_O2/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 0x91ed1(%rip), %r12     # 0xc6fa8
pushq $-0x1
popq %rbx
cmpl $-0x1, 0x570(%r12)
je 0x350f0
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 0x22820
movq %rax, %r15
callq 0x1fa30
testl %eax, %eax
je 0x35174
movl %eax, %ebp
callq 0x22820
subq %r15, %rax
movq %rax, 0x380(%r12)
cmpl $-0x1, %ebp
je 0x351cb
leaq 0x59ab3(%rip), %rsi     # 0x8ebf8
xorl %ebx, %ebx
pushq $0x2
popq %rdi
movl %ebp, %edx
xorl %eax, %eax
callq 0x22613
xorl %edi, %edi
callq 0x1fc50
movq %rax, 0x5b0(%r12)
movl %ebp, 0x570(%r12)
callq 0x22a8d
jmp 0x350e5
xorl %ebx, %ebx
xorl %edi, %edi
callq 0x256de
leaq 0x59a14(%rip), %rdi     # 0x8eb98
callq 0x26d17
movq %r14, %rdi
callq 0x34d06
movl %eax, %ebp
testl %eax, %eax
jne 0x351b9
callq 0x28599
testq %rax, %rax
je 0x351b9
shrq $0x14, %rax
leaq 0x599fd(%rip), %rsi     # 0x8eba9
pushq $0x2
popq %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x22613
xorl %edi, %edi
testl %ebp, %ebp
setne %dil
callq 0x22855
jmp 0x350e5
orl $-0x1, 0x5b8(%r12)
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x599ee(%rip), %rsi     # 0x8ebd5
pushq $0x3
popq %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x22613
jmp 0x350e5