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; } } }
int Executor_execute(Executor *executor, int timeout_ms) { DEBUG(("Executor execute start\n")); //determine max endtime based on timeout struct timespec tm; clock_gettime(CLOCK_MONOTONIC, &tm); DEBUG(("Executor start_tm_ms: %3.2f\n", TIMESPEC_TO_MS(tm))); executor->end_tm_ms = TIMESPEC_TO_MS(tm) + ((float)timeout_ms); DEBUG(("Executor end_tm_ms: %3.2f\n", executor->end_tm_ms)); executor->numevents = 0; for(int i = 0; i < executor->numpairs; i++) { struct _Pair *pair = &executor->pairs[i]; Connection_execute_start(pair->connection, executor, pair->batch, i); } int poll_result = 1; //for as long there are outstanding events and no error or timeout occurred: while(executor->numevents > 0 && poll_result > 0) { //figure out how many ms left for this execution int timeout; if (Executor_current_timeout(executor, &timeout) == -1) { //if no time is left, force a timeout poll_result = 0; } else { //do the poll DEBUG(("Executor start poll num_events: %d\n", executor->numevents)); poll_result = poll(executor->fds, executor->numpairs, timeout); DEBUG(("Executor select res %d\n", poll_result)); } for(int i = 0; i < executor->numpairs; i++) { struct _Pair *pair = &executor->pairs[i]; Connection *connection = pair->connection; Batch *batch = pair->batch; struct pollfd *fd = &executor->fds[i]; EventType event = 0; if(fd->revents & POLLIN) { event |= EVENT_READ; fd->events &= ~POLLIN; fd->revents &= ~POLLIN; executor->numevents -= 1; } if(fd->revents & POLLOUT) { event |= EVENT_WRITE; fd->events &= ~POLLOUT; fd->revents &= ~POLLOUT; executor->numevents -= 1; } if(poll_result == 0) { event = EVENT_TIMEOUT; } else if(poll_result < 0) { event = EVENT_ERROR; } if(event > 0 && Batch_has_command(batch)) { //there is an event, and batch is not finished Connection_handle_event(connection, event, i); } } } if(poll_result > 1) { poll_result = 1; } if(poll_result < 0) { Module_set_error(GET_MODULE(), "Execute select error, errno: [%d] %s", errno, strerror(errno)); } else if(poll_result == 0) { Module_set_error(GET_MODULE(), "Execute timeout"); } DEBUG(("Executor execute done\n")); return poll_result; }
int Executor_execute(Executor *executor, int timeout_ms) { DEBUG(("Executor execute start\n")); //determine max endtime based on timeout struct timespec tm; clock_gettime(CLOCK_MONOTONIC, &tm); DEBUG(("Executor start_tm_ms: %3.2f\n", TIMESPEC_TO_MS(tm))); executor->end_tm_ms = TIMESPEC_TO_MS(tm) + ((float)timeout_ms); DEBUG(("Executor end_tm_ms: %3.2f\n", executor->end_tm_ms)); executor->numevents = 0; for(int i = 0; i < executor->numpairs; i++) { struct _Pair *pair = &executor->pairs[i]; Connection_execute_start(pair->connection, executor, pair->batch); } int select_result = 1; //for as long there are outstanding events and no error or timeout occurred: while(executor->numevents > 0 && select_result > 0) { //figure out how many ms left for this execution struct timeval tv; Executor_current_timeout(executor, &tv); //copy filedes. sets, because select is going to modify them fd_set readfds; fd_set writefds; readfds = executor->readfds; writefds = executor->writefds; //do the select DEBUG(("Executor start select max_fd %d, num_events: %d\n", executor->max_fd, executor->numevents)); select_result = select(executor->max_fd + 1, &readfds, &writefds, NULL, &tv); DEBUG(("Executor select res %d\n", select_result)); for(int i = 0; i < executor->numpairs; i++) { struct _Pair *pair = &executor->pairs[i]; Connection *connection = pair->connection; Batch *batch = pair->batch; EventType event = 0; if(FD_ISSET(connection->sockfd, &readfds)) { event |= EVENT_READ; FD_CLR(connection->sockfd, &executor->readfds); executor->numevents -= 1; } if(FD_ISSET(connection->sockfd, &writefds)) { event |= EVENT_WRITE; FD_CLR(connection->sockfd, &executor->writefds); executor->numevents -= 1; } if(select_result == 0) { event = EVENT_TIMEOUT; } else if(select_result < 0) { event = EVENT_ERROR; } if(event > 0 && Batch_has_command(batch)) { //there is an event, and batch is not finished Connection_handle_event(connection, event); } } } if(select_result > 1) { select_result = 1; } if(select_result < 0) { Module_set_error(GET_MODULE(), "Execute select error, errno: [%d] %s", errno, strerror(errno)); } else if(select_result == 0) { Module_set_error(GET_MODULE(), "Execute timeout"); } DEBUG(("Executor execute done\n")); return select_result; }