// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/replication.c
// Function: readSyncBulkPayload
void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) {
    char buf[4096];
    ssize_t nread, readlen;
    off_t left;
    REDIS_NOTUSED(el);
    REDIS_NOTUSED(privdata);
    REDIS_NOTUSED(mask);

    /* If repl_transfer_size == -1 we still have to read the bulk length
     * from the master reply. */
    // 读取 RDB 文件的大小
    if (server.repl_transfer_size == -1) {

        // 调用读函数
        if (syncReadLine(fd,buf,1024,server.repl_syncio_timeout*1000) == -1) {
            redisLog(REDIS_WARNING,
                "I/O error reading bulk count from MASTER: %s",
                strerror(errno));
            goto error;
        }

        // 出错？
        if (buf[0] == '-') {
            redisLog(REDIS_WARNING,
                "MASTER aborted replication with an error: %s",
                buf+1);
            goto error;
        } else if (buf[0] == '\0') {
            /* At this stage just a newline works as a PING in order to take
             * the connection live. So we refresh our last interaction
             * timestamp. */
            // 只接到了一个作用和 PING 一样的 '\0'
            // 更新最后互动时间
            server.repl_transfer_lastio = server.unixtime;
            return;
        } else if (buf[0] != '$') {
            // 读入的内容出错，和协议格式不符
            redisLog(REDIS_WARNING,"Bad protocol from MASTER, the first byte is not '$' (we received '%s'), are you sure the host and port are right?", buf);
            goto error;
        }

        // 分析 RDB 文件大小
        server.repl_transfer_size = strtol(buf+1,NULL,10);

        redisLog(REDIS_NOTICE,
            "MASTER <-> SLAVE sync: receiving %lld bytes from master",
            (long long) server.repl_transfer_size);
        return;
    }

    /* Read bulk data */
    // 读数据

    // 还有多少字节要读？
    left = server.repl_transfer_size - server.repl_transfer_read;
    readlen = (left < (signed)sizeof(buf)) ? left : (signed)sizeof(buf);
    // 读取
    nread = read(fd,buf,readlen);
    if (nread <= 0) {
        redisLog(REDIS_WARNING,"I/O error trying to sync with MASTER: %s",
            (nread == -1) ? strerror(errno) : "connection lost");
        replicationAbortSyncTransfer();
        return;
    }
    // 更新最后 RDB 产生的 IO 时间
    server.repl_transfer_lastio = server.unixtime;
    if (write(server.repl_transfer_fd,buf,nread) != nread) {
        redisLog(REDIS_WARNING,"Write error or short write writing to the DB dump file needed for MASTER <-> SLAVE synchronization: %s", strerror(errno));
        goto error;
    }
    // 加上刚读取好的字节数
    server.repl_transfer_read += nread;

    /* Sync data on disk from time to time, otherwise at the end of the transfer
     * we may suffer a big delay as the memory buffers are copied into the
     * actual disk. */
    // 定期将读入的文件 fsync 到磁盘，以免 buffer 太多，一下子写入时撑爆 IO
    if (server.repl_transfer_read >=
        server.repl_transfer_last_fsync_off + REPL_MAX_WRITTEN_BEFORE_FSYNC)
    {
        off_t sync_size = server.repl_transfer_read -
                          server.repl_transfer_last_fsync_off;
        rdb_fsync_range(server.repl_transfer_fd,
            server.repl_transfer_last_fsync_off, sync_size);
        server.repl_transfer_last_fsync_off += sync_size;
    }

    /* Check if the transfer is now complete */
    // 检查 RDB 是否已经传送完毕
    if (server.repl_transfer_read == server.repl_transfer_size) {

        // 完毕，将临时文件改名为 dump.rdb
        if (rename(server.repl_transfer_tmpfile,server.rdb_filename) == -1) {
            redisLog(REDIS_WARNING,"Failed trying to rename the temp DB into dump.rdb in MASTER <-> SLAVE synchronization: %s", strerror(errno));
            replicationAbortSyncTransfer();
            return;
        }

        // 先清空旧数据库
        redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Flushing old data");
        signalFlushedDb(-1);
        emptyDb(replicationEmptyDbCallback);
        /* Before loading the DB into memory we need to delete the readable
         * handler, otherwise it will get called recursively since
         * rdbLoad() will call the event loop to process events from time to
         * time for non blocking loading. */
        // 先删除主服务器的读事件监听，因为 rdbLoad() 函数也会监听读事件
        aeDeleteFileEvent(server.el,server.repl_transfer_s,AE_READABLE);

        // 载入 RDB
        if (rdbLoad(server.rdb_filename) != REDIS_OK) {
            redisLog(REDIS_WARNING,"Failed trying to load the MASTER synchronization DB from disk");
            replicationAbortSyncTransfer();
            return;
        }

        /* Final setup of the connected slave <- master link */
        // 关闭临时文件
        zfree(server.repl_transfer_tmpfile);
        close(server.repl_transfer_fd);

        // 将主服务器设置成一个 redis client
        // 注意 createClient 会为主服务器绑定事件，为接下来接收命令做好准备
        server.master = createClient(server.repl_transfer_s);
        // 标记这个客户端为主服务器
        server.master->flags |= REDIS_MASTER;
        // 标记它为已验证身份
        server.master->authenticated = 1;
        // 更新复制状态
        server.repl_state = REDIS_REPL_CONNECTED;
        // 设置主服务器的复制偏移量
        server.master->reploff = server.repl_master_initial_offset;
        // 保存主服务器的 RUN ID
        memcpy(server.master->replrunid, server.repl_master_runid,
            sizeof(server.repl_master_runid));

        /* If master offset is set to -1, this master is old and is not
         * PSYNC capable, so we flag it accordingly. */
        // 如果 offset 被设置为 -1 ，那么表示主服务器的版本低于 2.8 
        // 无法使用 PSYNC ，所以需要设置相应的标识值
        if (server.master->reploff == -1)
            server.master->flags |= REDIS_PRE_PSYNC;
        redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: Finished with success");

        /* Restart the AOF subsystem now that we finished the sync. This
         * will trigger an AOF rewrite, and when done will start appending
         * to the new file. */
        // 如果有开启 AOF 持久化，那么重启 AOF 功能，并强制生成新数据库的 AOF 文件
        if (server.aof_state != REDIS_AOF_OFF) {
            int retry = 10;

            // 关闭
            stopAppendOnly();
            // 再重启
            while (retry-- && startAppendOnly() == REDIS_ERR) {
                redisLog(REDIS_WARNING,"Failed enabling the AOF after successful master synchronization! Trying it again in one second.");
                sleep(1);
            }
            if (!retry) {
                redisLog(REDIS_WARNING,"FATAL: this slave instance finished the synchronization with its master, but the AOF can't be turned on. Exiting now.");
                exit(1);
            }
        }
    }

    return;

error:
    replicationAbortSyncTransfer();
    return;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1060, %rsp           # imm = 0x1060
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
leaq 0xd2ee8(%rip), %rax     # 0x1138f8
cmpq $-0x1, 0x678(%rax)
jne 0x40b4e
movl -0xc(%rbp), %edi
leaq -0x1020(%rbp), %rsi
leaq 0xd2ec9(%rip), %rax     # 0x1138f8
imull $0x3e8, 0x670(%rax), %eax # imm = 0x3E8
movslq %eax, %rcx
movl $0x400, %edx            # imm = 0x400
callq 0x67e10
cmpq $-0x1, %rax
jne 0x40a73
callq 0x1f820
movl (%rax), %edi
callq 0x1f630
movq %rax, %rdx
movl $0x3, %edi
leaq 0xa145d(%rip), %rsi     # 0xe1ec4
movb $0x0, %al
callq 0x24fb0
jmp 0x41013
movsbl -0x1020(%rbp), %eax
cmpl $0x2d, %eax
jne 0x40aa2
leaq -0x1020(%rbp), %rdx
addq $0x1, %rdx
movl $0x3, %edi
leaq 0xa145b(%rip), %rsi     # 0xe1ef1
movb $0x0, %al
callq 0x24fb0
jmp 0x41013
movsbl -0x1020(%rbp), %eax
cmpl $0x0, %eax
jne 0x40acf
leaq 0xd2e43(%rip), %rax     # 0x1138f8
movq 0x798(%rax), %rcx
leaq 0xd2e35(%rip), %rax     # 0x1138f8
movq %rcx, 0x6a0(%rax)
jmp 0x41018
movsbl -0x1020(%rbp), %eax
cmpl $0x24, %eax
je 0x40afa
leaq -0x1020(%rbp), %rdx
movl $0x3, %edi
leaq 0xa1430(%rip), %rsi     # 0xe1f1e
movb $0x0, %al
callq 0x24fb0
jmp 0x41013
jmp 0x40afc
jmp 0x40afe
leaq -0x1020(%rbp), %rdi
addq $0x1, %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0xa, %edx
callq 0x1f6c0
movq %rax, %rcx
leaq 0xd2dd7(%rip), %rax     # 0x1138f8
movq %rcx, 0x678(%rax)
leaq 0xd2dc9(%rip), %rax     # 0x1138f8
movq 0x678(%rax), %rdx
movl $0x2, %edi
leaq 0xa144e(%rip), %rsi     # 0xe1f90
movb $0x0, %al
callq 0x24fb0
jmp 0x41018
leaq 0xd2da3(%rip), %rax     # 0x1138f8
movq 0x678(%rax), %rax
leaq 0xd2d95(%rip), %rcx     # 0x1138f8
subq 0x680(%rcx), %rax
movq %rax, -0x1038(%rbp)
cmpq $0x1000, -0x1038(%rbp) # imm = 0x1000
jge 0x40b8e
movq -0x1038(%rbp), %rax
movq %rax, -0x1050(%rbp)
jmp 0x40b9c
movl $0x1000, %eax           # imm = 0x1000
movq %rax, -0x1050(%rbp)
jmp 0x40b9c
movq -0x1050(%rbp), %rax
movq %rax, -0x1030(%rbp)
movl -0xc(%rbp), %edi
leaq -0x1020(%rbp), %rsi
movq -0x1030(%rbp), %rdx
callq 0x1f330
movq %rax, -0x1028(%rbp)
cmpq $0x0, -0x1028(%rbp)
jg 0x40c24
cmpq $-0x1, -0x1028(%rbp)
jne 0x40bf0
callq 0x1f820
movl (%rax), %edi
callq 0x1f630
movq %rax, -0x1058(%rbp)
jmp 0x40c00
leaq 0xa13fa(%rip), %rax     # 0xe1ff1
movq %rax, -0x1058(%rbp)
jmp 0x40c00
movq -0x1058(%rbp), %rdx
movl $0x3, %edi
leaq 0xa13b5(%rip), %rsi     # 0xe1fc8
movb $0x0, %al
callq 0x24fb0
callq 0x408c0
jmp 0x41018
leaq 0xd2ccd(%rip), %rax     # 0x1138f8
movq 0x798(%rax), %rcx
leaq 0xd2cbf(%rip), %rax     # 0x1138f8
movq %rcx, 0x6a0(%rax)
leaq 0xd2cb1(%rip), %rax     # 0x1138f8
movl 0x694(%rax), %edi
leaq -0x1020(%rbp), %rsi
movq -0x1028(%rbp), %rdx
callq 0x1fb50
cmpq -0x1028(%rbp), %rax
je 0x40c90
callq 0x1f820
movl (%rax), %edi
callq 0x1f630
movq %rax, %rdx
movl $0x3, %edi
leaq 0xa137d(%rip), %rsi     # 0xe2001
movb $0x0, %al
callq 0x24fb0
jmp 0x41013
movq -0x1028(%rbp), %rcx
leaq 0xd2c5a(%rip), %rax     # 0x1138f8
addq 0x680(%rax), %rcx
leaq 0xd2c4c(%rip), %rax     # 0x1138f8
movq %rcx, 0x680(%rax)
leaq 0xd2c3e(%rip), %rax     # 0x1138f8
movq 0x680(%rax), %rax
leaq 0xd2c30(%rip), %rcx     # 0x1138f8
movq 0x688(%rcx), %rcx
addq $0x800000, %rcx         # imm = 0x800000
cmpq %rcx, %rax
jl 0x40d4d
leaq 0xd2c16(%rip), %rax     # 0x1138f8
movq 0x680(%rax), %rax
leaq 0xd2c08(%rip), %rcx     # 0x1138f8
subq 0x688(%rcx), %rax
movq %rax, -0x1040(%rbp)
leaq 0xd2bf3(%rip), %rax     # 0x1138f8
movl 0x694(%rax), %edi
leaq 0xd2be6(%rip), %rax     # 0x1138f8
movq 0x688(%rax), %rsi
movq -0x1040(%rbp), %rdx
movl $0x3, %ecx
callq 0x1fc50
movq -0x1040(%rbp), %rcx
leaq 0xd2bc0(%rip), %rax     # 0x1138f8
addq 0x688(%rax), %rcx
leaq 0xd2bb2(%rip), %rax     # 0x1138f8
movq %rcx, 0x688(%rax)
leaq 0xd2ba4(%rip), %rax     # 0x1138f8
movq 0x680(%rax), %rax
leaq 0xd2b96(%rip), %rcx     # 0x1138f8
cmpq 0x678(%rcx), %rax
jne 0x41011
leaq 0xd2b82(%rip), %rax     # 0x1138f8
movq 0x698(%rax), %rdi
leaq 0xd2b74(%rip), %rax     # 0x1138f8
movq 0x588(%rax), %rsi
callq 0x1fc40
cmpl $-0x1, %eax
jne 0x40dc1
callq 0x1f820
movl (%rax), %edi
callq 0x1f630
movq %rax, %rdx
movl $0x3, %edi
leaq 0xa12b8(%rip), %rsi     # 0xe2068
movb $0x0, %al
callq 0x24fb0
callq 0x408c0
jmp 0x41018
movl $0x2, %edi
leaq 0xa12f5(%rip), %rsi     # 0xe20c2
movb $0x0, %al
callq 0x24fb0
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3c830
leaq -0x415(%rip), %rdi      # 0x409d0
callq 0x3c6a0
leaq 0xd2b07(%rip), %rax     # 0x1138f8
movq 0x28(%rax), %rdi
leaq 0xd2afc(%rip), %rax     # 0x1138f8
movl 0x690(%rax), %esi
movl $0x1, %edx
callq 0x20c60
leaq 0xd2ae5(%rip), %rax     # 0x1138f8
movq 0x588(%rax), %rdi
callq 0x45f70
cmpl $0x0, %eax
je 0x40e41
movl $0x3, %edi
leaq 0xa12bb(%rip), %rsi     # 0xe20eb
movb $0x0, %al
callq 0x24fb0
callq 0x408c0
jmp 0x41018
leaq 0xd2ab0(%rip), %rax     # 0x1138f8
movq 0x698(%rax), %rdi
callq 0x2e3a0
leaq 0xd2a9d(%rip), %rax     # 0x1138f8
movl 0x694(%rax), %edi
callq 0x1f170
leaq 0xd2a8b(%rip), %rax     # 0x1138f8
movl 0x690(%rax), %edi
callq 0x34950
movq %rax, %rcx
leaq 0xd2a76(%rip), %rax     # 0x1138f8
movq %rcx, 0x660(%rax)
leaq 0xd2a68(%rip), %rax     # 0x1138f8
movq 0x660(%rax), %rax
movl 0x90(%rax), %ecx
orl $0x2, %ecx
movl %ecx, 0x90(%rax)
leaq 0xd2a4b(%rip), %rax     # 0x1138f8
movq 0x660(%rax), %rax
movl $0x1, 0x94(%rax)
leaq 0xd2a33(%rip), %rax     # 0x1138f8
movl $0x5, 0x674(%rax)
leaq 0xd2a22(%rip), %rax     # 0x1138f8
movq 0x6f0(%rax), %rcx
leaq 0xd2a14(%rip), %rax     # 0x1138f8
movq 0x660(%rax), %rax
movq %rcx, 0xb8(%rax)
leaq 0xd29ff(%rip), %rax     # 0x1138f8
movq 0x660(%rax), %rdi
addq $0xd0, %rdi
leaq 0xd29ea(%rip), %rsi     # 0x1138f8
addq $0x6c0, %rsi            # imm = 0x6C0
movl $0x29, %edx
callq 0x1fbf0
leaq 0xd29d2(%rip), %rax     # 0x1138f8
movq 0x660(%rax), %rax
cmpq $-0x1, 0xb8(%rax)
jne 0x40f57
leaq 0xd29ba(%rip), %rax     # 0x1138f8
movq 0x660(%rax), %rax
movl 0x90(%rax), %ecx
orl $0x10000, %ecx          # imm = 0x10000
movl %ecx, 0x90(%rax)
movl $0x2, %edi
leaq 0xa11c6(%rip), %rsi     # 0xe2129
movb $0x0, %al
callq 0x24fb0
leaq 0xd2987(%rip), %rax     # 0x1138f8
cmpl $0x0, 0x4d0(%rax)
je 0x4100f
movl $0xa, -0x1044(%rbp)
callq 0x5eaf0
movl -0x1044(%rbp), %ecx
movl %ecx, %eax
addl $-0x1, %eax
movl %eax, -0x1044(%rbp)
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, -0x1059(%rbp)
je 0x40fbc
callq 0x5f170
cmpl $-0x1, %eax
sete %al
movb %al, -0x1059(%rbp)
movb -0x1059(%rbp), %al
testb $0x1, %al
jne 0x40fc8
jmp 0x40fe7
movl $0x3, %edi
leaq 0xa1182(%rip), %rsi     # 0xe2156
movb $0x0, %al
callq 0x24fb0
movl $0x1, %edi
callq 0x1f5c0
jmp 0x40f8d
cmpl $0x0, -0x1044(%rbp)
jne 0x4100d
movl $0x3, %edi
leaq 0xa11ba(%rip), %rsi     # 0xe21b6
movb $0x0, %al
callq 0x24fb0
movl $0x1, %edi
callq 0x1f2c0
jmp 0x4100f
jmp 0x41011
jmp 0x41018
callq 0x408c0
addq $0x1060, %rsp           # imm = 0x1060
popq %rbp
retq
nopw %cs:(%rax,%rax)