int Executor_current_timeout(Executor *executor, struct timeval *tv) { struct timespec tm; clock_gettime(CLOCK_MONOTONIC, &tm); double cur_tm_ms = TIMESPEC_TO_MS(tm); DEBUG(("Executor cur_tm: %3.2f\n", cur_tm_ms)); double left_ms = executor->end_tm_ms - cur_tm_ms; DEBUG(("Time left: %3.2f\n", left_ms)); tv->tv_sec = (time_t)left_ms / 1000.0; tv->tv_usec = (left_ms - (tv->tv_sec * 1000.0)) * 1000.0; DEBUG(("Timeout: %d sec, %d usec\n", (int)tv->tv_sec, (int)tv->tv_usec)); return 0; }
int Executor_current_timeout(Executor *executor, int *timeout) { struct timespec tm; clock_gettime(CLOCK_MONOTONIC, &tm); double cur_tm_ms = TIMESPEC_TO_MS(tm); DEBUG(("Executor cur_tm: %3.2f\n", cur_tm_ms)); double left_ms = executor->end_tm_ms - cur_tm_ms; DEBUG(("Time left: %3.2f\n", left_ms)); if (left_ms < 0.0) { return -1; } *timeout = (int)left_ms; DEBUG(("Timeout: %d msec\n", *timeout)); return 0; }
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; }