// File: /workspace/github_c_makefile_star2_O2/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 0x32254
movslq -0x8(%rsi), %rdx
movl %ebp, %edi
callq 0x1fb30
cmpq $-0x1, %rax
je 0x32338
movq 0xb0(%rbx), %rdi
pushq $-0x1
popq %rdx
movl %eax, %esi
callq 0x27a3e
movq 0xb0(%rbx), %rdi
cmpl $0x0, -0x8(%rdi)
jne 0x3236e
callq 0x271f7
andq $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 0x3234f
movq %rsp, %rsi
movl %ebp, %edi
movq %rax, %rdx
callq 0x1fb30
cmpq $-0x1, %rax
je 0x32362
addq 0xa0(%rbx), %rax
movq %rax, 0xa0(%rbx)
cmpq 0xa8(%rbx), %rax
jne 0x3236e
movl 0x9c(%rbx), %edi
callq 0x1f170
orl $-0x1, 0x9c(%rbx)
leaq 0x94cd9(%rip), %r14     # 0xc6fa8
movq 0x28(%r14), %rdi
movl (%rbx), %esi
pushq $0x2
popq %rbp
movl %ebp, %edx
callq 0x203cd
movl $0x9, 0x98(%rbx)
movq 0x798(%r14), %rax
movq %rax, 0xc8(%rbx)
movq 0x28(%r14), %rdi
movl (%rbx), %esi
leaq -0x6765(%rip), %rcx     # 0x2bb9f
movl %ebp, %edx
movq %rbx, %r8
callq 0x2030c
cmpl $-0x1, %eax
je 0x3239b
callq 0x31d7e
leaq 0x5b9cb(%rip), %rsi     # 0x8dcee
pushq $0x2
popq %rdi
xorl %eax, %eax
addq $0x4000, %rsp           # imm = 0x4000
popq %rbx
popq %r14
popq %rbp
jmp 0x22613
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x5b8e2(%rip), %rsi     # 0x8dc2d
pushq $0x1
jmp 0x323b0
je 0x3237a
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
movq %rax, %rdx
jmp 0x32381
callq 0x1f810
movl (%rax), %edi
cmpl $0xb, %edi
jne 0x3238d
addq $0x4000, %rsp           # imm = 0x4000
popq %rbx
popq %r14
popq %rbp
retq
leaq 0x5b8fd(%rip), %rdx     # 0x8dc7e
leaq 0x5b8d3(%rip), %rsi     # 0x8dc5b
pushq $0x3
popq %rdi
jmp 0x323b4
callq 0x1f630
leaq 0x5b8f3(%rip), %rsi     # 0x8dc8c
jmp 0x323ae
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x5b902(%rip), %rsi     # 0x8dcb0
pushq $0x3
popq %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x22613
movq %rbx, %rdi
addq $0x4000, %rsp           # imm = 0x4000
popq %rbx
popq %r14
popq %rbp
jmp 0x2cb56