// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/replication.c
// Function: sendBulkToSlave
void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) {
    redisClient *slave = privdata;
    REDIS_NOTUSED(el);
    REDIS_NOTUSED(mask);
    char buf[REDIS_IOBUF_LEN];
    ssize_t nwritten, buflen;

    /* Before sending the RDB file, we send the preamble as configured by the
     * replication process. Currently the preamble is just the bulk count of
     * the file in the form "$<length>\r\n". */
    if (slave->replpreamble) {
        nwritten = write(fd,slave->replpreamble,sdslen(slave->replpreamble));
        if (nwritten == -1) {
            redisLog(REDIS_VERBOSE,"Write error sending RDB preamble to slave: %s",
                strerror(errno));
            freeClient(slave);
            return;
        }
        sdsrange(slave->replpreamble,nwritten,-1);
        if (sdslen(slave->replpreamble) == 0) {
            sdsfree(slave->replpreamble);
            slave->replpreamble = NULL;
            /* fall through sending data. */
        } else {
            return;
        }
    }

    /* If the preamble was already transfered, send the RDB bulk data. */
    lseek(slave->repldbfd,slave->repldboff,SEEK_SET);
    // 读取 RDB 数据
    buflen = read(slave->repldbfd,buf,REDIS_IOBUF_LEN);
    if (buflen <= 0) {
        redisLog(REDIS_WARNING,"Read error sending DB to slave: %s",
            (buflen == 0) ? "premature EOF" : strerror(errno));
        freeClient(slave);
        return;
    }
    // 写入数据到 slave
    if ((nwritten = write(fd,buf,buflen)) == -1) {
        if (errno != EAGAIN) {
            redisLog(REDIS_WARNING,"Write error sending DB to slave: %s",
                strerror(errno));
            freeClient(slave);
        }
        return;
    }

    // 如果写入成功，那么更新写入字节数到 repldboff ，等待下次继续写入
    slave->repldboff += nwritten;

    // 如果写入已经完成
    if (slave->repldboff == slave->repldbsize) {
        // 关闭 RDB 文件描述符
        close(slave->repldbfd);
        slave->repldbfd = -1;
        // 删除之前绑定的写事件处理器
        aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE);
        // 将状态更新为 REDIS_REPL_ONLINE
        slave->replstate = REDIS_REPL_ONLINE;
        // 更新响应时间
        slave->repl_ack_time = server.unixtime;
        // 创建向从服务器发送命令的写事件处理器
        // 将保存并发送 RDB 期间的回复全部发送给从服务器
        if (aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE,
            sendReplyToClient, slave) == AE_ERR) {
            redisLog(REDIS_WARNING,"Unable to register writable event for slave bulk transfer: %s", strerror(errno));
            freeClient(slave);
            return;
        }
        // 刷新低延迟 slave 数量
        refreshGoodSlavesCount();
        redisLog(REDIS_NOTICE,"Synchronization with slave succeeded");
    }
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0x4000, %rsp           # imm = 0x4000
movq %rdx, %rbx
movl %esi, %ebp
movq 0xb0(%rdx), %rsi
testq %rsi, %rsi
je 0x33fd7
movslq -0x8(%rsi), %rdx
movl %ebp, %edi
callq 0x1fb30
cmpq $-0x1, %rax
je 0x340c3
movq 0xb0(%rbx), %rdi
movl %eax, %esi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x28c31
movq 0xb0(%rbx), %rdi
cmpl $0x0, -0x8(%rdi)
jne 0x340fc
callq 0x28204
movq $0x0, 0xb0(%rbx)
movl 0x9c(%rbx), %edi
movq 0xa0(%rbx), %rsi
xorl %edx, %edx
callq 0x1f9f0
movl 0x9c(%rbx), %edi
movq %rsp, %rsi
movl $0x4000, %edx           # imm = 0x4000
callq 0x1f330
testq %rax, %rax
jle 0x340dd
movq %rsp, %rsi
movl %ebp, %edi
movq %rax, %rdx
callq 0x1fb30
cmpq $-0x1, %rax
je 0x340f0
addq 0xa0(%rbx), %rax
movq %rax, 0xa0(%rbx)
cmpq 0xa8(%rbx), %rax
jne 0x340fc
movl 0x9c(%rbx), %edi
callq 0x1f170
movl $0xffffffff, 0x9c(%rbx) # imm = 0xFFFFFFFF
leaq 0x95f53(%rip), %r14     # 0xc9fa8
movq 0x28(%r14), %rdi
movl (%rbx), %esi
movl $0x2, %edx
callq 0x20a9d
movl $0x9, 0x98(%rbx)
movq 0x798(%r14), %rax
movq %rax, 0xc8(%rbx)
movq 0x28(%r14), %rdi
movl (%rbx), %esi
leaq -0x6f50(%rip), %rcx     # 0x2d13a
movl $0x2, %edx
movq %rbx, %r8
callq 0x209d7
cmpl $-0x1, %eax
je 0x3412b
callq 0x33a99
leaq 0x63c0e(%rip), %rsi     # 0x97cba
movl $0x2, %edi
xorl %eax, %eax
addq $0x4000, %rsp           # imm = 0x4000
popq %rbx
popq %r14
popq %rbp
jmp 0x23064
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x63b23(%rip), %rsi     # 0x97bf9
movl $0x1, %edi
jmp 0x34143
je 0x34108
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
movq %rax, %rdx
jmp 0x3410f
callq 0x1f810
movl (%rax), %edi
cmpl $0xb, %edi
jne 0x3411d
addq $0x4000, %rsp           # imm = 0x4000
popq %rbx
popq %r14
popq %rbp
retq
leaq 0x63b3b(%rip), %rdx     # 0x97c4a
leaq 0x63b11(%rip), %rsi     # 0x97c27
movl $0x3, %edi
jmp 0x34146
callq 0x1f630
leaq 0x63b2f(%rip), %rsi     # 0x97c58
jmp 0x3413e
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x63b3e(%rip), %rsi     # 0x97c7c
movl $0x3, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0x23064
movq %rbx, %rdi
addq $0x4000, %rsp           # imm = 0x4000
popq %rbx
popq %r14
popq %rbp
jmp 0x2e287