size_t Buffer_send(Buffer *buffer, int fd) { DEBUG(("Buffer_send fd: %d, position: %d, limit: %d, remaining: %d\n", fd, buffer->position, buffer->limit, Buffer_remaining(buffer))); size_t bytes_written = write(fd, buffer->data + buffer->position, Buffer_remaining(buffer)); DEBUG(("Buffer_send fd: %d, bytes_written: %d\n", fd, bytes_written)); if(bytes_written != -1) { buffer->position += bytes_written; } return bytes_written; }
size_t Buffer_recv(Buffer *buffer, int fd) { Buffer_ensure_remaining(buffer, (buffer->capacity * 256) / 2048); //make sure we have still 1/8 remaining DEBUG(("Buffer_recv fd: %d, position: %d, limit: %d, remaining: %d\n", fd, buffer->position, buffer->limit, Buffer_remaining(buffer))); size_t bytes_read = read(fd, buffer->data + buffer->position, Buffer_remaining(buffer)); DEBUG(("Buffer_recv fd: %d, bytes_read: %d\n", fd, bytes_read)); if(bytes_read != -1) { buffer->position += bytes_read; } return bytes_read; }
void Buffer_ensure_remaining(Buffer *buffer, int min_remaining) { DEBUG(("Buffer %p ensure remaining: position: %d, limit: %d, cap: %d\n", (void *)buffer, buffer->position, buffer->limit, buffer->capacity)); assert(buffer->limit == buffer->capacity); while(Buffer_remaining(buffer) < min_remaining) { buffer->limit *= 2; } assert(buffer->limit >= buffer->capacity); if(buffer->limit > buffer->capacity) { if(buffer->capacity == buffer->buff_size) { DEBUG(("growing buffer first time, new cap: %d, old cap: %d\n", buffer->limit, buffer->capacity)); buffer->data = Alloc_alloc(buffer->limit); memcpy(buffer->data, buffer->buff, buffer->capacity); } else { DEBUG(("growing buffer second or more time, new cap: %d, old cap: %d\n", buffer->limit, buffer->capacity)); buffer->data = Alloc_realloc(buffer->data, buffer->limit, buffer->capacity); } buffer->capacity = buffer->limit; } assert(buffer->limit == buffer->capacity); }
void Connection_write_data(Connection *connection, int ordinal) { DEBUG(("connection write_data fd: %d\n", connection->sockfd)); assert(connection->current_batch != NULL); assert(connection->current_executor != NULL); if(CS_ABORTED == connection->state) { return; } if(CS_CLOSED == connection->state) { if(-1 == Connection_create_socket(connection)) { //already aborted in create_socket return; } //connect the socket struct addrinfo *addrinfo = connection->addrinfo; if(-1 == connect(connection->sockfd, addrinfo->ai_addr, addrinfo->ai_addrlen)) { //open the connection if(EINPROGRESS == errno) { //normal async connect connection->state = CS_CONNECTING; DEBUG(("async connecting, adding write event\n")); Executor_notify_event(connection->current_executor, connection, EVENT_WRITE, ordinal); DEBUG(("write event added, now returning\n")); return; } else { Connection_abort(connection, "connect error 1, errno [%d] %s", errno, strerror(errno)); return; } } else { //immediate connect succeeded DEBUG(("sync connected\n")); connection->state = CS_CONNECTED; } } if(CS_CONNECTING == connection->state) { //now check for error to see if we are really connected int error; socklen_t len = sizeof(int); if(-1 == getsockopt(connection->sockfd, SOL_SOCKET, SO_ERROR, &error, &len)) { Connection_abort(connection, "getsockopt error for connect result, errno: [%d] %s", errno, strerror(errno)); return; } if(error != 0) { Connection_abort(connection, "connect error 2, error: [%d] %s", error, strerror(error)); return; } else { connection->state = CS_CONNECTED; Executor_notify_event(connection->current_executor, connection, EVENT_READ, ordinal); } } if(CS_CONNECTED == connection->state) { Buffer *buffer = Batch_write_buffer(connection->current_batch); assert(buffer != NULL); while(Buffer_remaining(buffer)) { //still something to write size_t res = Buffer_send(buffer, connection->sockfd); DEBUG(("bfr send res: %d\n", res)); if(res == -1) { if(errno == EAGAIN) { Executor_notify_event(connection->current_executor, connection, EVENT_WRITE, ordinal); return; } else { Connection_abort(connection, "write error, errno: [%d] %s", errno, strerror(errno)); return; } } } } }