// File: /workspace/github_c_makefile_star2_O3/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 0x34410
movslq -0x8(%rsi), %rdx
movl %ebp, %edi
callq 0x1fb30
cmpq $-0x1, %rax
je 0x344fc
movq 0xb0(%rbx), %rdi
movl %eax, %esi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x28f3c
movq 0xb0(%rbx), %rdi
cmpl $0x0, -0x8(%rdi)
jne 0x34535
callq 0x2850d
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 0x34516
movq %rsp, %rsi
movl %ebp, %edi
movq %rax, %rdx
callq 0x1fb30
cmpq $-0x1, %rax
je 0x34529
addq 0xa0(%rbx), %rax
movq %rax, 0xa0(%rbx)
cmpq 0xa8(%rbx), %rax
jne 0x34535
movl 0x9c(%rbx), %edi
callq 0x1f170
movl $0xffffffff, 0x9c(%rbx) # imm = 0xFFFFFFFF
leaq 0x95b1a(%rip), %r14     # 0xc9fa8
movq 0x28(%r14), %rdi
movl (%rbx), %esi
movl $0x2, %edx
callq 0x20ce8
movl $0x9, 0x98(%rbx)
movq 0x798(%r14), %rax
movq %rax, 0xc8(%rbx)
movq 0x28(%r14), %rdi
movl (%rbx), %esi
leaq -0x70f7(%rip), %rcx     # 0x2d3cc
movl $0x2, %edx
movq %rbx, %r8
callq 0x20c22
cmpl $-0x1, %eax
je 0x34564
callq 0x33f0b
leaq 0x63845(%rip), %rsi     # 0x97d2a
movl $0x2, %edi
xorl %eax, %eax
addq $0x4000, %rsp           # imm = 0x4000
popq %rbx
popq %r14
popq %rbp
jmp 0x23223
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x6375a(%rip), %rsi     # 0x97c69
movl $0x1, %edi
jmp 0x3457c
je 0x34541
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
movq %rax, %rdx
jmp 0x34548
callq 0x1f810
movl (%rax), %edi
cmpl $0xb, %edi
jne 0x34556
addq $0x4000, %rsp           # imm = 0x4000
popq %rbx
popq %r14
popq %rbp
retq
leaq 0x63772(%rip), %rdx     # 0x97cba
leaq 0x63748(%rip), %rsi     # 0x97c97
movl $0x3, %edi
jmp 0x3457f
callq 0x1f630
leaq 0x63766(%rip), %rsi     # 0x97cc8
jmp 0x34577
callq 0x1f810
movl (%rax), %edi
callq 0x1f630
leaq 0x63775(%rip), %rsi     # 0x97cec
movl $0x3, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0x23223
movq %rbx, %rdi
addq $0x4000, %rsp           # imm = 0x4000
popq %rbx
popq %r14
popq %rbp
jmp 0x2e517