// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/aof.c
// Function: rewriteAppendOnlyFile
int rewriteAppendOnlyFile(char *filename) {
    dictIterator *di = NULL;
    dictEntry *de;
    rio aof;
    FILE *fp;
    char tmpfile[256];
    int j;
    long long now = mstime();

    /* Note that we have to use a different temp name here compared to the
     * one used by rewriteAppendOnlyFileBackground() function. 
     *
     * 创建临时文件
     *
     * 注意这里创建的文件名和 rewriteAppendOnlyFileBackground() 创建的文件名稍有不同
     */
    snprintf(tmpfile,256,"temp-rewriteaof-%d.aof", (int) getpid());
    fp = fopen(tmpfile,"w");
    if (!fp) {
        redisLog(REDIS_WARNING, "Opening the temp file for AOF rewrite in rewriteAppendOnlyFile(): %s", strerror(errno));
        return REDIS_ERR;
    }

    // 初始化文件 io
    rioInitWithFile(&aof,fp);

    // 设置每写入 REDIS_AOF_AUTOSYNC_BYTES 字节
    // 就执行一次 FSYNC 
    // 防止缓存中积累太多命令内容，造成 I/O 阻塞时间过长
    if (server.aof_rewrite_incremental_fsync)
        rioSetAutoSync(&aof,REDIS_AOF_AUTOSYNC_BYTES);

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

        char selectcmd[] = "*2\r\n$6\r\nSELECT\r\n";

        redisDb *db = server.db+j;

        // 指向键空间
        dict *d = db->dict;
        if (dictSize(d) == 0) continue;

        // 创建键空间迭代器
        di = dictGetSafeIterator(d);
        if (!di) {
            fclose(fp);
            return REDIS_ERR;
        }

        /* SELECT the new DB 
         *
         * 首先写入 SELECT 命令，确保之后的数据会被插入到正确的数据库上
         */
        if (rioWrite(&aof,selectcmd,sizeof(selectcmd)-1) == 0) goto werr;
        if (rioWriteBulkLongLong(&aof,j) == 0) goto werr;

        /* Iterate this DB writing every entry 
         *
         * 遍历数据库所有键，并通过命令将它们的当前状态（值）记录到新 AOF 文件中
         */
        while((de = dictNext(di)) != NULL) {
            sds keystr;
            robj key, *o;
            long long expiretime;

            // 取出键
            keystr = dictGetKey(de);

            // 取出值
            o = dictGetVal(de);
            initStaticStringObject(key,keystr);

            // 取出过期时间
            expiretime = getExpire(db,&key);

            /* If this key is already expired skip it 
             *
             * 如果键已经过期，那么跳过它，不保存
             */
            if (expiretime != -1 && expiretime < now) continue;

            /* Save the key and associated value 
             *
             * 根据值的类型，选择适当的命令来保存值
             */
            if (o->type == REDIS_STRING) {
                /* Emit a SET command */
                char cmd[]="*3\r\n$3\r\nSET\r\n";
                if (rioWrite(&aof,cmd,sizeof(cmd)-1) == 0) goto werr;
                /* Key and value */
                if (rioWriteBulkObject(&aof,&key) == 0) goto werr;
                if (rioWriteBulkObject(&aof,o) == 0) goto werr;
            } else if (o->type == REDIS_LIST) {
                if (rewriteListObject(&aof,&key,o) == 0) goto werr;
            } else if (o->type == REDIS_SET) {
                if (rewriteSetObject(&aof,&key,o) == 0) goto werr;
            } else if (o->type == REDIS_ZSET) {
                if (rewriteSortedSetObject(&aof,&key,o) == 0) goto werr;
            } else if (o->type == REDIS_HASH) {
                if (rewriteHashObject(&aof,&key,o) == 0) goto werr;
            } else {
                redisPanic("Unknown object type");
            }

            /* Save the expire time 
             *
             * 保存键的过期时间
             */
            if (expiretime != -1) {
                char cmd[]="*3\r\n$9\r\nPEXPIREAT\r\n";

                // 写入 PEXPIREAT expiretime 命令
                if (rioWrite(&aof,cmd,sizeof(cmd)-1) == 0) goto werr;
                if (rioWriteBulkObject(&aof,&key) == 0) goto werr;
                if (rioWriteBulkLongLong(&aof,expiretime) == 0) goto werr;
            }
        }

        // 释放迭代器
        dictReleaseIterator(di);
    }

    /* Make sure data will not remain on the OS's output buffers */
    // 冲洗并关闭新 AOF 文件
    if (fflush(fp) == EOF) goto werr;
    if (aof_fsync(fileno(fp)) == -1) goto werr;
    if (fclose(fp) == EOF) goto werr;

    /* Use RENAME to make sure the DB file is changed atomically only
     * if the generate DB file is ok. 
     *
     * 原子地改名，用重写后的新 AOF 文件覆盖旧 AOF 文件
     */
    if (rename(tmpfile,filename) == -1) {
        redisLog(REDIS_WARNING,"Error moving temp append only file on the final destination: %s", strerror(errno));
        unlink(tmpfile);
        return REDIS_ERR;
    }

    redisLog(REDIS_NOTICE,"SYNC append only file rewrite performed");

    return REDIS_OK;

werr:
    fclose(fp);
    unlink(tmpfile);
    redisLog(REDIS_WARNING,"Write error writing append only file on disk: %s", strerror(errno));
    if (di) dictReleaseIterator(di);
    return REDIS_ERR;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x220, %rsp            # imm = 0x220
movq %rdi, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
callq 0x252e0
movq %rax, -0x190(%rbp)
leaq -0x180(%rbp), %rax
movq %rax, -0x218(%rbp)
callq 0x1f410
movq -0x218(%rbp), %rdi
movl %eax, %ecx
movl $0x100, %esi            # imm = 0x100
leaq 0x83e90(%rip), %rdx     # 0xe4c2b
movb $0x0, %al
callq 0x1f120
leaq -0x180(%rbp), %rdi
leaq 0x80806(%rip), %rsi     # 0xe15b6
callq 0x1fa70
movq %rax, -0x78(%rbp)
cmpq $0x0, -0x78(%rbp)
jne 0x60dee
callq 0x1f820
movl (%rax), %edi
callq 0x1f630
movq %rax, %rdx
movl $0x3, %edi
leaq 0x83e67(%rip), %rsi     # 0xe4c42
movb $0x0, %al
callq 0x24fb0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x612fb
movq -0x78(%rbp), %rsi
leaq -0x70(%rbp), %rdi
callq 0x75d70
leaq 0xb2af6(%rip), %rax     # 0x1138f8
cmpl $0x0, 0x550(%rax)
je 0x60e19
leaq -0x70(%rbp), %rdi
movl $0x2000000, %esi        # imm = 0x2000000
callq 0x75e50
movl $0x0, -0x184(%rbp)
movl -0x184(%rbp), %eax
leaq 0xb2ac8(%rip), %rcx     # 0x1138f8
cmpl 0x480(%rcx), %eax
jge 0x6120b
movq 0x8425d(%rip), %rax     # 0xe50a0
movq %rax, -0x1b0(%rbp)
movq 0x84257(%rip), %rax     # 0xe50a8
movq %rax, -0x1a8(%rbp)
movb 0x84252(%rip), %al      # 0xe50b0
movb %al, -0x1a0(%rbp)
leaq 0xb2a8d(%rip), %rax     # 0x1138f8
movq 0x10(%rax), %rax
movslq -0x184(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x1b8(%rbp)
movq -0x1b8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x1c0(%rbp)
movq -0x1c0(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x1c0(%rbp), %rcx
addq 0x48(%rcx), %rax
cmpq $0x0, %rax
jne 0x60eb6
jmp 0x611f7
movq -0x1c0(%rbp), %rdi
callq 0x24240
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
jne 0x60ee2
movq -0x78(%rbp), %rdi
callq 0x1f9b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x612fb
leaq -0x1b0(%rbp), %rsi
leaq -0x70(%rbp), %rdi
movl $0x10, %edx
callq 0x61310
cmpq $0x0, %rax
jne 0x60f02
jmp 0x612ad
movslq -0x184(%rbp), %rsi
leaq -0x70(%rbp), %rdi
callq 0x76100
cmpq $0x0, %rax
jne 0x60f1d
jmp 0x612ad
jmp 0x60f1f
movq -0x18(%rbp), %rdi
callq 0x24270
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
je 0x611ee
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x1c8(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x1e0(%rbp)
movl $0x1, -0x1d4(%rbp)
movl -0x1d8(%rbp), %eax
andl $-0x10, %eax
orl $0x0, %eax
movl %eax, -0x1d8(%rbp)
movl -0x1d8(%rbp), %eax
andl $0xffffff0f, %eax       # imm = 0xFFFFFF0F
orl $0x0, %eax
movl %eax, -0x1d8(%rbp)
movq -0x1c8(%rbp), %rax
movq %rax, -0x1d0(%rbp)
movq -0x1b8(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x3dce0
movq %rax, -0x1e8(%rbp)
cmpq $-0x1, -0x1e8(%rbp)
je 0x60fca
movq -0x1e8(%rbp), %rax
cmpq -0x190(%rbp), %rax
jge 0x60fca
jmp 0x60f1f
movq -0x1e0(%rbp), %rax
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x0, %eax
jne 0x61060
movq 0x83ca1(%rip), %rax     # 0xe4c87
movq %rax, -0x1f6(%rbp)
movl 0x83c9c(%rip), %eax     # 0xe4c8f
movl %eax, -0x1ee(%rbp)
movw 0x83c93(%rip), %ax      # 0xe4c93
movw %ax, -0x1ea(%rbp)
leaq -0x1f6(%rbp), %rsi
leaq -0x70(%rbp), %rdi
movl $0xd, %edx
callq 0x61310
cmpq $0x0, %rax
jne 0x61027
jmp 0x612ad
leaq -0x70(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x60010
cmpl $0x0, %eax
jne 0x61041
jmp 0x612ad
movq -0x1e0(%rbp), %rsi
leaq -0x70(%rbp), %rdi
callq 0x60010
cmpl $0x0, %eax
jne 0x6105b
jmp 0x612ad
jmp 0x61160
movq -0x1e0(%rbp), %rax
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x1, %eax
jne 0x61097
movq -0x1e0(%rbp), %rdx
leaq -0x70(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x600d0
cmpl $0x0, %eax
jne 0x61092
jmp 0x612ad
jmp 0x6115e
movq -0x1e0(%rbp), %rax
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x2, %eax
jne 0x610ce
movq -0x1e0(%rbp), %rdx
leaq -0x70(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x60400
cmpl $0x0, %eax
jne 0x610c9
jmp 0x612ad
jmp 0x6115c
movq -0x1e0(%rbp), %rax
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x3, %eax
jne 0x61102
movq -0x1e0(%rbp), %rdx
leaq -0x70(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x606c0
cmpl $0x0, %eax
jne 0x61100
jmp 0x612ad
jmp 0x6115a
movq -0x1e0(%rbp), %rax
movl (%rax), %eax
andl $0xf, %eax
cmpl $0x4, %eax
jne 0x61136
movq -0x1e0(%rbp), %rdx
leaq -0x70(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x60b00
cmpl $0x0, %eax
jne 0x61134
jmp 0x612ad
jmp 0x61158
leaq 0x803be(%rip), %rdi     # 0xe14fb
leaq 0x83591(%rip), %rsi     # 0xe46d5
movl $0x596, %edx            # imm = 0x596
callq 0x63d40
movl $0x1, %edi
callq 0x1f3b0
jmp 0x6115a
jmp 0x6115c
jmp 0x6115e
jmp 0x61160
cmpq $-0x1, -0x1e8(%rbp)
je 0x611e9
movq 0x83f4f(%rip), %rax     # 0xe50c0
movq %rax, -0x210(%rbp)
movq 0x83f49(%rip), %rax     # 0xe50c8
movq %rax, -0x208(%rbp)
movl 0x83f44(%rip), %eax     # 0xe50d0
movl %eax, -0x200(%rbp)
leaq -0x210(%rbp), %rsi
leaq -0x70(%rbp), %rdi
movl $0x13, %edx
callq 0x61310
cmpq $0x0, %rax
jne 0x611b2
jmp 0x612ad
leaq -0x70(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x60010
cmpl $0x0, %eax
jne 0x611cc
jmp 0x612ad
movq -0x1e8(%rbp), %rsi
leaq -0x70(%rbp), %rdi
callq 0x76100
cmpq $0x0, %rax
jne 0x611e7
jmp 0x612ad
jmp 0x611e9
jmp 0x60f1f
movq -0x18(%rbp), %rdi
callq 0x243d0
movl -0x184(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x184(%rbp)
jmp 0x60e23
movq -0x78(%rbp), %rdi
callq 0x1fc80
cmpl $-0x1, %eax
jne 0x6121e
jmp 0x612ad
movq -0x78(%rbp), %rdi
callq 0x1f070
movl %eax, %edi
callq 0x1f540
cmpl $-0x1, %eax
jne 0x61235
jmp 0x612ad
movq -0x78(%rbp), %rdi
callq 0x1f9b0
cmpl $-0x1, %eax
jne 0x61245
jmp 0x612ad
leaq -0x180(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x1fc40
cmpl $-0x1, %eax
jne 0x61291
callq 0x1f820
movl (%rax), %edi
callq 0x1f630
movq %rax, %rdx
movl $0x3, %edi
leaq 0x83a20(%rip), %rsi     # 0xe4c95
movb $0x0, %al
callq 0x24fb0
leaq -0x180(%rbp), %rdi
callq 0x1f3a0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x612fb
movl $0x2, %edi
leaq 0x83a38(%rip), %rsi     # 0xe4cd5
movb $0x0, %al
callq 0x24fb0
movl $0x0, -0x4(%rbp)
jmp 0x612fb
movq -0x78(%rbp), %rdi
callq 0x1f9b0
leaq -0x180(%rbp), %rdi
callq 0x1f3a0
callq 0x1f820
movl (%rax), %edi
callq 0x1f630
movq %rax, %rdx
movl $0x3, %edi
leaq 0x83a20(%rip), %rsi     # 0xe4cfd
movb $0x0, %al
callq 0x24fb0
cmpq $0x0, -0x18(%rbp)
je 0x612f4
movq -0x18(%rbp), %rdi
callq 0x243d0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl -0x4(%rbp), %eax
addq $0x220, %rsp            # imm = 0x220
popq %rbp
retq
nopw (%rax,%rax)