// File: cybozu[P]yrmcds/src/memcache/sockets.cpp
// Function: yrmcds::memcache::memcache_socket::memcache_socket(int, std::function<cybozu::worker* ()> const&, cybozu::hash_map<yrmcds::memcache::object>&, std::vector<yrmcds::memcache::repl_socket*, std::allocator<yrmcds::memcache::repl_socket*>> const&)
memcache_socket::memcache_socket(int fd,
                                 const std::function<cybozu::worker*()>& finder,
                                 cybozu::hash_map<object>& hash,
                                 const std::vector<repl_socket*>& slaves)
    : cybozu::tcp_socket(fd),
      m_busy(false),
      m_finder(finder),
      m_hash(hash),
      m_pending(0),
      m_slaves_origin(slaves) {
    m_slaves.reserve(MAX_SLAVES);
    g_stats.curr_connections.fetch_add(1, relaxed);
    g_stats.total_connections.fetch_add(1, relaxed);

    m_recvjob = [this](cybozu::dynbuf& buf) {
        // set lock context for objects.
        with_fd([](int fd) -> bool {
            g_context = fd;
            return true;
        });

        // load pending data
        if( ! m_pending.empty() ) {
            buf.append(m_pending.data(), m_pending.size());
            m_pending.reset();
        }

        while( true ) {
            auto res = receive(buf, MAX_RECVSIZE);
            if( res == recv_result::AGAIN )
                break;
            if( res == recv_result::RESET || res == recv_result::NONE ) {
                buf.reset();
                unlock_all();
                break;
            }

            const char* head = buf.data();
            std::size_t len = buf.size();
            while( len > 0 ) {
                if( mc::is_binary_request(head) ) {
                    mc::binary_request parser(head, len);
                    std::size_t c = parser.length();
                    if( c == 0 ) break;
                    head += c;
                    len -= c;
                    cmd_bin(parser);
                } else {
                    mc::text_request parser(head, len);
                    std::size_t c = parser.length();
                    if( c == 0 ) break;
                    head += c;
                    len -= c;
                    cmd_text(parser);
                }
            }
            if( len > MAX_REQUEST_LENGTH ) {
                cybozu::logger::warning() << "denied too large request of "
                                          << len << " bytes.";
                buf.reset();
                unlock_all();
                invalidate_and_close();
                break;
            }
            buf.erase(head - buf.data());
        }

        // recv returns EAGAIN, or some error happens.
        if( buf.size() > 0 )
            m_pending.append(buf.data(), buf.size());

        m_busy.store(false, std::memory_order_release);
    };

    m_sendjob = [this](cybozu::dynbuf&) {
        with_fd([=](int fd) -> bool {
            return write_pending_data(fd);
        });
    };
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rdi, -0x58(%rbp)
movl %esi, -0x5c(%rbp)
movq %rdx, -0x68(%rbp)
movq %rcx, -0x70(%rbp)
movq %r8, -0x78(%rbp)
movq -0x58(%rbp), %rdi
movq %rdi, -0xb0(%rbp)
movl -0x5c(%rbp), %esi
xorl %edx, %edx
movl %edx, -0xa4(%rbp)
callq 0x55720
movq -0xb0(%rbp), %rdi
movl -0xa4(%rbp), %esi
leaq 0x6d8a3(%rip), %rax     # 0xae950
movq %rax, (%rdi)
addq $0x100, %rdi            # imm = 0x100
callq 0x22f60
movq -0xb0(%rbp), %rdi
movl -0xa4(%rbp), %edx
movq -0x68(%rbp), %rax
movq %rax, 0x108(%rdi)
movq -0x70(%rbp), %rax
movq %rax, 0x110(%rdi)
addq $0x118, %rdi            # imm = 0x118
movq %rdi, -0xa0(%rbp)
movl %edx, %esi
callq 0x22f90
jmp 0x410f6
movq -0xb0(%rbp), %rdi
movq -0x78(%rbp), %rax
movq %rax, 0x140(%rdi)
addq $0x148, %rdi            # imm = 0x148
movq %rdi, -0xb8(%rbp)
callq 0x399c0
movq -0xb0(%rbp), %rdi
addq $0x160, %rdi            # imm = 0x160
movq %rdi, -0xd0(%rbp)
callq 0x23000
movq -0xb0(%rbp), %rdi
addq $0x180, %rdi            # imm = 0x180
movq %rdi, -0xc8(%rbp)
callq 0x23000
movq -0xb0(%rbp), %rdi
addq $0x1a0, %rdi            # imm = 0x1A0
movq %rdi, -0xc0(%rbp)
callq 0x506d0
movq -0xb8(%rbp), %rdi
movl $0x5, %esi
callq 0x399e0
jmp 0x4117c
leaq 0x6ee7d(%rip), %rax     # 0xb0000
addq $0x100, %rax            # imm = 0x100
movq %rax, -0x8(%rbp)
movq $0x1, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xe0(%rbp)
movl -0x14(%rbp), %eax
movq -0x10(%rbp), %rcx
movq %rcx, -0x20(%rbp)
decl %eax
movl %eax, %ecx
movq %rcx, -0xd8(%rbp)
subl $0x4, %eax
ja 0x411d9
movq -0xd8(%rbp), %rax
leaq 0x3a600(%rip), %rcx     # 0x7b7d0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0xe0(%rbp), %rcx
movq -0x20(%rbp), %rax
lock
xaddq %rax, (%rcx)
movq %rax, -0x28(%rbp)
jmp 0x41245
movq -0xe0(%rbp), %rcx
movq -0x20(%rbp), %rax
lock
xaddq %rax, (%rcx)
movq %rax, -0x28(%rbp)
jmp 0x41245
movq -0xe0(%rbp), %rcx
movq -0x20(%rbp), %rax
lock
xaddq %rax, (%rcx)
movq %rax, -0x28(%rbp)
jmp 0x41245
movq -0xe0(%rbp), %rcx
movq -0x20(%rbp), %rax
lock
xaddq %rax, (%rcx)
movq %rax, -0x28(%rbp)
jmp 0x41245
movq -0xe0(%rbp), %rcx
movq -0x20(%rbp), %rax
lock
xaddq %rax, (%rcx)
movq %rax, -0x28(%rbp)
leaq 0x6edb4(%rip), %rax     # 0xb0000
addq $0x108, %rax            # imm = 0x108
movq %rax, -0x30(%rbp)
movq $0x1, -0x38(%rbp)
movl $0x0, -0x3c(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0xf0(%rbp)
movl -0x3c(%rbp), %eax
movq -0x38(%rbp), %rcx
movq %rcx, -0x48(%rbp)
decl %eax
movl %eax, %ecx
movq %rcx, -0xe8(%rbp)
subl $0x4, %eax
ja 0x412a2
movq -0xe8(%rbp), %rax
leaq 0x3a54b(%rip), %rcx     # 0x7b7e4
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0xf0(%rbp), %rcx
movq -0x48(%rbp), %rax
lock
xaddq %rax, (%rcx)
movq %rax, -0x50(%rbp)
jmp 0x4130e
movq -0xf0(%rbp), %rcx
movq -0x48(%rbp), %rax
lock
xaddq %rax, (%rcx)
movq %rax, -0x50(%rbp)
jmp 0x4130e
movq -0xf0(%rbp), %rcx
movq -0x48(%rbp), %rax
lock
xaddq %rax, (%rcx)
movq %rax, -0x50(%rbp)
jmp 0x4130e
movq -0xf0(%rbp), %rcx
movq -0x48(%rbp), %rax
lock
xaddq %rax, (%rcx)
movq %rax, -0x50(%rbp)
jmp 0x4130e
movq -0xf0(%rbp), %rcx
movq -0x48(%rbp), %rax
lock
xaddq %rax, (%rcx)
movq %rax, -0x50(%rbp)
movq -0xb0(%rbp), %rdi
movq %rdi, -0x90(%rbp)
addq $0x160, %rdi            # imm = 0x160
leaq -0x90(%rbp), %rsi
callq 0x413d0
movq -0xb0(%rbp), %rdi
movq %rdi, -0x98(%rbp)
addq $0x180, %rdi            # imm = 0x180
leaq -0x98(%rbp), %rsi
callq 0x41420
addq $0xf0, %rsp
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x413b5
movq -0xc0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
callq 0x506f0
movq -0xc8(%rbp), %rdi
callq 0xc560
movq -0xd0(%rbp), %rdi
callq 0xc560
movq -0xb8(%rbp), %rdi
callq 0x39ae0
movq -0xa0(%rbp), %rdi
callq 0xc580
movq -0xb0(%rbp), %rdi
callq 0x33280
movq -0x80(%rbp), %rdi
callq 0x8bc0
nopw (%rax,%rax)