// File: /workspace/github_cpp_makefile_star2_O1/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %r8, %r14
movq %rcx, %r15
movq %rdx, %r12
movq %rdi, %rbx
xorl %edx, %edx
callq 0x20460
leaq 0x2cc04(%rip), %rax     # 0x45958
movq %rax, (%rbx)
movb $0x0, 0x100(%rbx)
movq %r12, 0x108(%rbx)
movq %r15, 0x110(%rbx)
leaq 0x118(%rbx), %r15
movq $0x0, 0x138(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x118(%rbx)
movups %xmm0, 0x121(%rbx)
movq %r14, 0x140(%rbx)
leaq 0x148(%rbx), %r13
leaq 0x160(%rbx), %r12
leaq 0x180(%rbx), %r14
movups %xmm0, 0x148(%rbx)
movups %xmm0, 0x158(%rbx)
movups %xmm0, 0x168(%rbx)
movups %xmm0, 0x178(%rbx)
movups %xmm0, 0x188(%rbx)
movups %xmm0, 0x198(%rbx)
movups %xmm0, 0x1a8(%rbx)
movl $0x5, %esi
movq %r13, %rdi
callq 0x17148
leaq 0x2e0d0(%rip), %rax     # 0x46ec0
lock
incq 0x100(%rax)
lock
incq 0x108(%rax)
xorps %xmm0, %xmm0
movaps %xmm0, (%rsp)
movaps %xmm0, 0x10(%rsp)
movq %rbx, (%rsp)
leaq 0x3561(%rip), %rcx      # 0x1c378
movq %rcx, 0x18(%rsp)
leaq 0x37ab(%rip), %rdx      # 0x1c5ce
movq %rdx, 0x10(%rsp)
movaps (%rsp), %xmm0
movaps %xmm0, 0x20(%rsp)
movups (%r12), %xmm1
movaps %xmm1, (%rsp)
movups %xmm0, (%r12)
movq 0x170(%rbx), %rax
movq %rax, 0x10(%rsp)
movq %rdx, 0x170(%rbx)
movq 0x178(%rbx), %rdx
movq %rdx, 0x18(%rsp)
movq %rcx, 0x178(%rbx)
testq %rax, %rax
je 0x18e77
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
xorps %xmm0, %xmm0
movaps %xmm0, (%rsp)
movaps %xmm0, 0x10(%rsp)
movq %rbx, (%rsp)
leaq 0x3766(%rip), %rcx      # 0x1c5f4
movq %rcx, 0x18(%rsp)
leaq 0x37b0(%rip), %rdx      # 0x1c64a
movq %rdx, 0x10(%rsp)
movaps (%rsp), %xmm0
movaps %xmm0, 0x20(%rsp)
movups (%r14), %xmm1
movaps %xmm1, (%rsp)
movups %xmm0, (%r14)
movq 0x190(%rbx), %rax
movq %rax, 0x10(%rsp)
movq %rdx, 0x190(%rbx)
movq 0x198(%rbx), %rdx
movq %rdx, 0x18(%rsp)
movq %rcx, 0x198(%rbx)
testq %rax, %rax
je 0x18eec
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x18f74
jmp 0x18f74
movq %rax, %rbp
movq 0x1a0(%rbx), %rdi
testq %rdi, %rdi
je 0x18f1d
movq 0x1b0(%rbx), %rsi
subq %rdi, %rsi
callq 0x7510
movq 0x190(%rbx), %rax
testq %rax, %rax
je 0x18f36
movq %r14, %rdi
movq %r14, %rsi
movl $0x3, %edx
callq *%rax
movq 0x170(%rbx), %rax
testq %rax, %rax
je 0x18f4f
movq %r12, %rdi
movq %r12, %rsi
movl $0x3, %edx
callq *%rax
movq %r13, %rdi
movq %rbx, %rsi
callq 0x7ec0
movq %r15, %rdi
callq 0x96e2
movq %rbx, %rdi
callq 0x14e28
movq %rbp, %rdi
callq 0x79b0
jmp 0x18f74
movq %rax, %rdi
callq 0x8fc6