Exemplo n.º 1
0
void Connection_execute_start(Connection *connection, Executor *executor, Batch *batch, int ordinal)
{
	DEBUG(("Connection exec\n"));

	connection->current_batch = batch;
	connection->current_executor = executor;

	if(CS_ABORTED == connection->state) {
		connection->state = CS_CLOSED;
	}

	ReplyParser_reset(connection->parser);
	Buffer_flip(Batch_write_buffer(batch));

	DEBUG(("Connection exec write buff:\n"));
#ifndef NDEBUG
	Buffer_dump(Batch_write_buffer(batch), 128);
#endif

	//kick off writing:
	Connection_write_data(connection, ordinal);

	//kick off reading when socket becomes readable
	if(CS_CONNECTED == connection->state) {
		Executor_notify_event(connection->current_executor, connection, EVENT_READ, ordinal);
	}
}
Exemplo n.º 2
0
void Connection_read_data(Connection *connection, int ordinal)
{
    if(CS_ABORTED == connection->state) {
        return;
    }

    DEBUG(("connection read data fd: %d\n", connection->sockfd));
    assert(connection->current_batch != NULL);
    assert(connection->current_executor != NULL);
    assert(CS_CONNECTED == connection->state);

    Buffer *buffer = Batch_read_buffer(connection->current_batch);
    assert(buffer != NULL);

    while(Batch_has_command(connection->current_batch)) {
        DEBUG(("exec rp\n"));
        Reply *reply = NULL;
        ReplyParserResult rp_res = ReplyParser_execute(connection->parser, Buffer_data(buffer), Buffer_position(buffer), &reply);
        switch(rp_res) {
        case RPR_ERROR: {
            Connection_abort(connection, "result parse error");
            return;
        }
        case RPR_MORE: {
            DEBUG(("read data RPR_MORE buf recv\n"));
            size_t res = Buffer_recv(buffer, connection->sockfd);
            DEBUG(("read data RPR_MORE res: %d\n", res));
#ifndef NDEBUG
        Buffer_dump(buffer, 128);
#endif
            if(res == -1) {
                if(errno == EAGAIN) {
                     DEBUG(("read data expecting more data in future, adding event\n"));
                    Executor_notify_event(connection->current_executor, connection, EVENT_READ, ordinal);
                    return;
                }
                else {
                    Connection_abort(connection, "read error, errno: [%d] %s", errno, strerror(errno));
                    return;
                }
            }
            else if(res == 0) {
                Connection_abort(connection, "read eof");
                return;
            }
            break;
        }
        case RPR_REPLY: {
            DEBUG(("read data RPR_REPLY batch add reply\n"));
            Batch_add_reply(connection->current_batch, reply);
            break;
        }
        default:
            Connection_abort(connection, "unexpected result parser result, rpres: %d", rp_res);
            return;
        }
    }
}
Exemplo n.º 3
0
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;
				}
			}
		}
	}
}