// File: /workspace/github_c_makefile_star2_O2/zuocheng-liu[P]ae-memcached/src/memcached.c
// Function: drive_machine
void drive_machine(conn *c) {

    int exit = 0;
    int sfd, flags = 1;
    socklen_t addrlen;
    struct sockaddr addr;
    conn *newc;
    int res;

    while (!exit) {
        switch(c->state) {
        case conn_listening:
            addrlen = sizeof(addr);
            if ((sfd = accept(c->sfd, &addr, &addrlen)) == -1) {
                if (errno == EAGAIN || errno == EWOULDBLOCK) {
                    exit = 1;
                    break;
                } else {
                    perror("accept()");
                }
                break;
            }
            if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
                fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
                perror("setting O_NONBLOCK");
                close(sfd);
                break;
            }
            newc = conn_new(sfd, conn_read, AE_READABLE, DATA_BUFFER_SIZE, 0);
            if (!newc) {
                LOG_INFO("Couldn't create new connection\n");
                close(sfd);
                break;
            }

            break;

        case conn_read:
            if (try_read_command(c)) {
                continue;
            }
            if (c->udp ? try_read_udp(c) : try_read_network(c)) {
                continue;
            }
            /* we have no command line and no data to read from network */
            if (!update_event(c, AE_READABLE)) {
                LOG_INFO("Couldn't update event\n");
                conn_set_state(c, conn_closing);
                break;
            }
            exit = 1;
            break;

        case conn_nread:
            /* we are reading rlbytes into ritem; */
            if (c->rlbytes == 0) {
                complete_nread(c);
                break;
            }
            /* first check if we have leftovers in the conn_read buffer */
            if (c->rbytes > 0) {
                int tocopy = c->rbytes > c->rlbytes ? c->rlbytes : c->rbytes;
                memcpy(c->ritem, c->rcurr, tocopy);
                c->ritem += tocopy;
                c->rlbytes -= tocopy;
                c->rcurr += tocopy;
                c->rbytes -= tocopy;
                break;
            }

            /*  now try reading from the socket */
            res = read(c->sfd, c->ritem, c->rlbytes);
            if (res > 0) {
                stats.bytes_read += res;
                c->ritem += res;
                c->rlbytes -= res;
                break;
            }
            if (res == 0) { /* end of stream */
                conn_set_state(c, conn_closing);
                break;
            }
            if (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
                if (!update_event(c, AE_READABLE)) {
                    LOG_INFO("Couldn't update event\n");
                    conn_set_state(c, conn_closing);
                    break;
                }
                exit = 1;
                break;
            }
            /* otherwise we have a real error, on which we close the connection */
            LOG_INFO("Failed to read, and not due to blocking\n");
            conn_set_state(c, conn_closing);
            break;

        case conn_swallow:
            /* we are reading sbytes and throwing them away */
            if (c->sbytes == 0) {
                conn_set_state(c, conn_read);
                break;
            }

            /* first check if we have leftovers in the conn_read buffer */
            if (c->rbytes > 0) {
                int tocopy = c->rbytes > c->sbytes ? c->sbytes : c->rbytes;
                c->sbytes -= tocopy;
                c->rcurr += tocopy;
                c->rbytes -= tocopy;
                break;
            }

            /*  now try reading from the socket */
            res = read(c->sfd, c->rbuf, c->rsize > c->sbytes ? c->sbytes : c->rsize);
            if (res > 0) {
                stats.bytes_read += res;
                c->sbytes -= res;
                break;
            }
            if (res == 0) { /* end of stream */
                conn_set_state(c, conn_closing);
                break;
            }
            if (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
                if (!update_event(c, AE_READABLE)) {
                    LOG_INFO("Couldn't update event\n");
                    conn_set_state(c, conn_closing);
                    break;
                }
                exit = 1;
                break;
            }
            /* otherwise we have a real error, on which we close the connection */
            LOG_INFO("Failed to read, and not due to blocking\n");
            conn_set_state(c, conn_closing);
            break;

        case conn_write:
            /*
             * We want to write out a simple response. If we haven't already,
             * assemble it into a msgbuf list (this will be a single-entry
             * list for TCP or a two-entry list for UDP).
             */
            if (c->iovused == 0) {
                if (add_iov(c, c->wcurr, c->wbytes) ||
                        (c->udp && build_udp_headers(c))) {
                    LOG_INFO("Couldn't build response\n");
                    conn_set_state(c, conn_closing);
                    break;
                }
            }

            /* fall through... */

        case conn_mwrite:
            switch (transmit(c)) {
            case TRANSMIT_COMPLETE:
                if (c->state == conn_mwrite) {
                    while (c->ileft > 0) {
                        item *it = *(c->icurr);
                        assert((it->it_flags & ITEM_SLABBED) == 0);
                        item_remove(it);
                        c->icurr++;
                        c->ileft--;
                    }
                    conn_set_state(c, conn_read);
                } else if (c->state == conn_write) {
                    if (c->write_and_free) {
                        free(c->write_and_free);
                        c->write_and_free = 0;
                    }
                    conn_set_state(c, c->write_and_go);
                } else {
                    LOG_INFO_F1("Unexpected state %d\n", c->state);
                    conn_set_state(c, conn_closing);
                }
                break;

            case TRANSMIT_INCOMPLETE:
            case TRANSMIT_HARD_ERROR:
                break;                   /* Continue in state machine. */

            case TRANSMIT_SOFT_ERROR:
                exit = 1;
                break;
            }
            break;

        case conn_closing:
            if (c->udp)
                conn_cleanup(c);
            else
                conn_close(c);
            exit = 1;
            break;
        }

    }

    return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
leaq 0x2664(%rip), %r13      # 0x8308
leaq 0x4(%rsp), %r15
pushq $0x1
popq %r12
leaq 0x75d4(%rip), %r14      # 0xd288
movl 0x4(%rbx), %eax
cmpq $0x6, %rax
ja 0x5cb4
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movl $0x10, 0x4(%rsp)
movl (%rbx), %edi
leaq 0x8(%rsp), %rsi
movq %r15, %rdx
callq 0x23d0
cmpl $-0x1, %eax
je 0x5ec3
movl %eax, %ebp
movl %eax, %edi
pushq $0x3
popq %rsi
xorl %edx, %edx
xorl %eax, %eax
callq 0x20f0
testl %eax, %eax
js 0x6006
orl $0x800, %eax            # imm = 0x800
movl %ebp, %edi
pushq $0x4
popq %rsi
movl %eax, %edx
xorl %eax, %eax
callq 0x20f0
testl %eax, %eax
js 0x6006
movl %ebp, %edi
movl %r12d, %esi
movl %r12d, %edx
movl $0x800, %ecx            # imm = 0x800
xorl %r8d, %r8d
callq 0x33a1
testq %rax, %rax
jne 0x5cb4
cmpl $0x0, 0x18(%r14)
jle 0x6012
movq 0x72b2(%rip), %rax      # 0xcff8
movq (%rax), %rcx
leaq 0x2bac(%rip), %rdi      # 0x88fc
pushq $0x1f
popq %rsi
pushq $0x1
popq %rdx
callq 0x2420
jmp 0x6012
movslq 0x60(%rbx), %rdx
testq %rdx, %rdx
je 0x5e7c
movl 0x2c(%rbx), %ecx
movq 0x58(%rbx), %rax
testl %ecx, %ecx
jle 0x5f2d
cmpl %edx, %ecx
cmovll %ecx, %edx
movq 0x20(%rbx), %rsi
movslq %edx, %rbp
movq %rax, %rdi
movq %rbp, %rdx
callq 0x2280
addq %rbp, 0x58(%rbx)
subl %ebp, 0x60(%rbx)
addq %rbp, 0x20(%rbx)
subl %ebp, 0x2c(%rbx)
jmp 0x5cb4
cmpl $0x0, 0x84(%rbx)
je 0x5e89
movq %rbx, %rdi
callq 0x5b40
testl %eax, %eax
je 0x5e26
cmpl $0x2, %eax
jne 0x5cb4
jmp 0x6076
movq %rbx, %rdi
callq 0x5884
testl %eax, %eax
jne 0x5cb4
cmpl $0x0, 0xbc(%rbx)
je 0x5fc7
movq %rbx, %rdi
callq 0x58f5
jmp 0x5fcf
movl 0x74(%rbx), %eax
testl %eax, %eax
je 0x5e6c
movl 0x2c(%rbx), %ecx
testl %ecx, %ecx
jle 0x5f5a
cmpl %eax, %ecx
movl %eax, %edx
cmovll %ecx, %edx
subl %edx, %eax
movl %eax, 0x74(%rbx)
movslq %edx, %rax
addq %rax, 0x20(%rbx)
subl %eax, %ecx
movl %ecx, 0x2c(%rbx)
jmp 0x5cb4
movl 0x4(%rbx), %edx
cmpl $0x2, %edx
je 0x5ee2
cmpl $0x6, %edx
jne 0x5f05
movl 0xb8(%rbx), %eax
testl %eax, %eax
jle 0x5e6c
movq 0xb0(%rbx), %rax
movq (%rax), %rdi
callq 0x3fb4
addq $0x8, 0xb0(%rbx)
movl 0xb8(%rbx), %eax
decl %eax
movl %eax, 0xb8(%rbx)
jmp 0x5e41
movq %rbx, %rdi
movl %r12d, %esi
callq 0x391f
jmp 0x5cb4
movq %rbx, %rdi
callq 0x46fe
jmp 0x5cb4
movq 0x38(%rbx), %rsi
movl 0x44(%rbx), %edx
movq %rbx, %rdi
callq 0x39dd
testl %eax, %eax
je 0x5fa5
cmpl $0x0, 0x18(%r14)
jle 0x604b
movq 0x7146(%rip), %rax      # 0xcff8
movq (%rax), %rcx
leaq 0x2a89(%rip), %rdi      # 0x8945
pushq $0x18
jmp 0x6042
callq 0x2040
cmpl $0xb, (%rax)
je 0x6076
leaq 0x2a08(%rip), %rdi      # 0x88e0
callq 0x23b0
jmp 0x5cb4
movq 0x50(%rbx), %rdi
testq %rdi, %rdi
je 0x5ef5
callq 0x2030
andq $0x0, 0x50(%rbx)
movl 0x48(%rbx), %esi
movq %rbx, %rdi
callq 0x391f
jmp 0x5cb4
cmpl $0x0, 0x18(%r14)
jle 0x604b
movq 0x70e1(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x2a3d(%rip), %rsi      # 0x895e
xorl %eax, %eax
callq 0x2260
jmp 0x604b
movl (%rbx), %edi
movq %rax, %rsi
callq 0x21f0
testl %eax, %eax
jle 0x5f8f
movl %eax, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
leaq 0x7396(%rip), %rdx      # 0xd2e0
addq %rcx, 0x48(%rdx)
addq %rcx, 0x58(%rbx)
subl %eax, 0x60(%rbx)
jmp 0x5cb4
movl (%rbx), %edi
movq 0x18(%rbx), %rsi
movl 0x28(%rbx), %ecx
cmpl %eax, %ecx
cmovll %ecx, %eax
movslq %eax, %rdx
callq 0x21f0
testl %eax, %eax
jle 0x5f8f
movl %eax, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
leaq 0x735d(%rip), %rdx      # 0xd2e0
addq %rcx, 0x48(%rdx)
subl %eax, 0x74(%rbx)
jmp 0x5cb4
cmpl $-0x1, %eax
je 0x601e
testl %eax, %eax
je 0x604b
jmp 0x6028
cmpl $0x0, 0xbc(%rbx)
je 0x5db3
movq %rbx, %rdi
callq 0x462b
testl %eax, %eax
jne 0x5ea0
jmp 0x5db3
movq %rbx, %rdi
callq 0x5996
testl %eax, %eax
jne 0x5cb4
movq %rbx, %rdi
movl %r12d, %esi
callq 0x5abc
testl %eax, %eax
jne 0x6076
cmpl $0x0, 0x18(%r14)
jle 0x604b
movq 0x7000(%rip), %rax      # 0xcff8
movq (%rax), %rcx
leaq 0x289d(%rip), %rdi      # 0x889f
pushq $0x16
jmp 0x6042
leaq 0x28dc(%rip), %rdi      # 0x88e9
callq 0x23b0
movl %ebp, %edi
callq 0x21b0
jmp 0x5cb4
callq 0x2040
cmpl $0xb, (%rax)
je 0x5fd7
cmpl $0x0, 0x18(%r14)
jle 0x604b
movq 0x6fc2(%rip), %rax      # 0xcff8
movq (%rax), %rcx
leaq 0x28dc(%rip), %rdi      # 0x891c
pushq $0x28
popq %rsi
pushq $0x1
popq %rdx
callq 0x2420
movq %rbx, %rdi
pushq $0x5
popq %rsi
callq 0x391f
jmp 0x5cb4
cmpl $0x0, 0xbc(%rbx)
je 0x606e
movq %rbx, %rdi
callq 0x36ab
jmp 0x6076
movq %rbx, %rdi
callq 0x370c
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq