// File: /workspace/github_c_makefile_star2_O3/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 0x1cd2(%rip), %r13      # 0x8348
leaq 0x8(%rsp), %r14
leaq 0x4(%rsp), %r15
leaq 0x6c01(%rip), %r12      # 0xd288
movl 0x4(%rbx), %eax
cmpq $0x6, %rax
ja 0x6687
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movl $0x10, 0x4(%rsp)
movl (%rbx), %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x23d0
cmpl $-0x1, %eax
je 0x688c
movl %eax, %ebp
movl %eax, %edi
movl $0x3, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x20f0
testl %eax, %eax
js 0x69df
orl $0x800, %eax            # imm = 0x800
movl %ebp, %edi
movl $0x4, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x20f0
testl %eax, %eax
js 0x69df
movl %ebp, %edi
movl $0x1, %esi
movl $0x1, %edx
movl $0x800, %ecx            # imm = 0x800
xorl %r8d, %r8d
callq 0x3b94
testq %rax, %rax
jne 0x6687
cmpl $0x0, 0x18(%r12)
jle 0x69eb
callq 0x26da
jmp 0x69eb
movslq 0x60(%rbx), %rdx
testq %rdx, %rdx
je 0x6852
movl 0x2c(%rbx), %ecx
movq 0x58(%rbx), %rax
testl %ecx, %ecx
jle 0x68fa
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 0x6687
cmpl $0x0, 0x84(%rbx)
je 0x685f
movq %rbx, %rdi
callq 0x652d
testl %eax, %eax
je 0x67ed
cmpl $0x2, %eax
jne 0x6687
jmp 0x6a9a
movq %rbx, %rdi
callq 0x628c
testl %eax, %eax
jne 0x6687
cmpl $0x0, 0xbc(%rbx)
je 0x6986
movq %rbx, %rdi
callq 0x6301
jmp 0x698e
movl 0x74(%rbx), %eax
testl %eax, %eax
je 0x6840
movl 0x2c(%rbx), %ecx
testl %ecx, %ecx
jle 0x692b
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 0x6687
movl 0x4(%rbx), %edx
cmpl $0x2, %edx
je 0x68ab
cmpl $0x6, %edx
jne 0x68d1
cmpl $0x0, 0xb8(%rbx)
jle 0x6840
movq 0xb0(%rbx), %rax
movq (%rax), %rdi
callq 0x489a
movq 0xb0(%rbx), %rax
addq $0x8, %rax
movq %rax, 0xb0(%rbx)
movl 0xb8(%rbx), %ecx
leal -0x1(%rcx), %edx
movl %edx, 0xb8(%rbx)
cmpl $0x1, %ecx
jg 0x6812
movq %rbx, %rdi
movl $0x1, %esi
callq 0x4189
jmp 0x6687
movq %rbx, %rdi
callq 0x5099
jmp 0x6687
movq 0x38(%rbx), %rsi
movl 0x44(%rbx), %edx
movq %rbx, %rdi
callq 0x424c
testl %eax, %eax
je 0x6964
cmpl $0x0, 0x18(%r12)
jle 0x6a66
callq 0x260e
jmp 0x6a66
callq 0x2040
cmpl $0xb, (%rax)
je 0x6a9a
leaq 0x207f(%rip), %rdi      # 0x8920
callq 0x23b0
jmp 0x6687
movq 0x50(%rbx), %rdi
testq %rdi, %rdi
je 0x68c1
callq 0x2030
movq $0x0, 0x50(%rbx)
movl 0x48(%rbx), %esi
movq %rbx, %rdi
callq 0x4189
jmp 0x6687
cmpl $0x0, 0x18(%r12)
jle 0x6a66
movq 0x6714(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x20b0(%rip), %rsi      # 0x899e
xorl %eax, %eax
callq 0x2260
jmp 0x6a66
movl (%rbx), %edi
movq %rax, %rsi
callq 0x21f0
testl %eax, %eax
jle 0x69c1
movl %eax, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
leaq 0x69c5(%rip), %rdx      # 0xd2e0
addq %rcx, 0x48(%rdx)
addq %rcx, 0x58(%rbx)
subl %eax, 0x60(%rbx)
jmp 0x6687
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 0x69d0
movl %eax, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
leaq 0x6988(%rip), %rdx      # 0xd2e0
addq %rcx, 0x48(%rdx)
subl %eax, 0x74(%rbx)
jmp 0x6687
cmpl $0x0, 0xbc(%rbx)
je 0x677a
movq %rbx, %rdi
callq 0x4f9a
testl %eax, %eax
jne 0x6876
jmp 0x677a
movq %rbx, %rdi
callq 0x63a4
testl %eax, %eax
jne 0x6687
movq %rbx, %rdi
movl $0x1, %esi
callq 0x64bd
testl %eax, %eax
jne 0x6a9a
cmpl $0x0, 0x18(%r12)
jle 0x6a66
callq 0x26b8
jmp 0x6a66
cmpl $-0x1, %eax
je 0x69f7
testl %eax, %eax
je 0x6a66
jmp 0x6a25
cmpl $-0x1, %eax
je 0x6a34
testl %eax, %eax
je 0x6a66
jmp 0x6a5e
leaq 0x1f43(%rip), %rdi      # 0x8929
callq 0x23b0
movl %ebp, %edi
callq 0x21b0
jmp 0x6687
callq 0x2040
cmpl $0xb, (%rax)
jne 0x6a25
movq %rbx, %rdi
movl $0x1, %esi
callq 0x64bd
testl %eax, %eax
jne 0x6a9a
cmpl $0x0, 0x18(%r12)
jle 0x6a66
callq 0x2674
jmp 0x6a66
cmpl $0x0, 0x18(%r12)
jle 0x6a66
callq 0x2696
jmp 0x6a66
callq 0x2040
cmpl $0xb, (%rax)
jne 0x6a5e
movq %rbx, %rdi
movl $0x1, %esi
callq 0x64bd
testl %eax, %eax
jne 0x6a9a
cmpl $0x0, 0x18(%r12)
jle 0x6a66
callq 0x2630
jmp 0x6a66
cmpl $0x0, 0x18(%r12)
jg 0x6a78
movq %rbx, %rdi
movl $0x5, %esi
callq 0x4189
jmp 0x6687
callq 0x2652
jmp 0x6a66
cmpl $0x0, 0xbc(%rbx)
je 0x6a92
movq %rbx, %rdi
callq 0x3ecf
jmp 0x6a9a
movq %rbx, %rdi
callq 0x3f3f
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq