static int64_t now(void) { struct timeval tv = { 0xffffffff, 0xffffffff }; int r = real_gettimeofday(&tv, NULL); assert(r == 0); assert(tv.tv_sec != 0xffffffff); assert(tv.tv_usec != 0xffffffff); return from_timeval(&tv); }
void linux_event_loop<handler>::run() { int ready_cnt; int buf_size; struct epoll_event evlist[MAX_EVENTS]; char buffer[MAX_BUFFER]; struct msghdr msg; struct iovec iov; char ctrl[CMSG_SPACE(sizeof(struct timeval))]; struct cmsghdr *cmsg = (struct cmsghdr *) & ctrl; struct timeval kernel_time; iov.iov_base = buffer; iov.iov_len = MAX_BUFFER; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = (char *)ctrl; msg.msg_controllen = sizeof(ctrl); struct timeval tcp_time; _is_running = true; while( _is_running ) { ready_cnt = epoll_wait( _fd_epoll, evlist, MAX_EVENTS, -1 ); if( ready_cnt < 0 ) { char m[1000]; perror(m); std::cerr << "Error in epoll_wait " << m << std::endl; continue; } if( ready_cnt == 0 ) continue; for( int i = 0; i < ready_cnt; ++i) { if (evlist[i].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP)) { std::string what_exactly; if( evlist[i].events & EPOLLHUP ) what_exactly = "EPOLLHUP"; else if ( evlist[i].events & EPOLLERR ) what_exactly = "EPOLLERR"; else if ( evlist[i].events & EPOLLRDHUP ) what_exactly = "EPOLLRDHUP"; std::cerr << "Error " << what_exactly << " on fd =" << evlist[i].data.fd << std::endl; disable(evlist[i].data.fd); remove(evlist[i].data.fd); _handler->on_disconnect(evlist[i].data.fd); continue; } con_type type = _cons[ evlist[i].data.fd ].type; if(type == UDP) { if(evlist[i].events & EPOLLIN) { iov.iov_len = MAX_BUFFER; while( (buf_size = recvmsg(evlist[i].data.fd, &msg, MSG_DONTWAIT)) > 0 ) { if(cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_TIMESTAMP || cmsg->cmsg_len != CMSG_LEN(sizeof(kernel_time))) { std::cerr << "cannot obtain kernel timestamp ignoring UDP packet" << std::endl; } else { _handler->on_udp_packet(evlist[i].data.fd, buffer, buf_size, from_timeval(*(struct timeval *)CMSG_DATA(cmsg))); } iov.iov_len = MAX_BUFFER; } } } else if(type == TCP) { if(evlist[i].events & EPOLLIN) { while( ( buf_size = recv(evlist[i].data.fd, buffer, MAX_BUFFER, MSG_DONTWAIT)) > 0) { gettimeofday((struct timeval *)&tcp_time, NULL); _handler->on_tcp_packet(evlist[i].data.fd, buffer, buf_size, from_timeval(tcp_time)); } } } else if(type == TIMER) { if(evlist[i].events & EPOLLIN) { if ( (buf_size = read(evlist[i].data.fd, buffer, MAX_BUFFER)) > 0) { gettimeofday((struct timeval *)&tcp_time, NULL); _handler->on_timer(evlist[i].data.fd, buffer, buf_size, from_timeval(tcp_time)); } } } } } }
bool linux_event_loop<handler>::poll() { _iov.iov_base = _buffer; _iov.iov_len = MAX_BUFFER; _msg.msg_name = NULL; _msg.msg_namelen = 0; _msg.msg_iov = &_iov; _msg.msg_iovlen = 1; _msg.msg_control = (char *)_ctrl; _msg.msg_controllen = sizeof(_ctrl); struct cmsghdr *cmsg = (struct cmsghdr *) & _ctrl; // auto t0 = _tsc(); _ready_cnt = epoll_wait( _fd_epoll, _evlist, MAX_EVENTS, 0 ); // auto t1 = _tsc(); /* if(false && _params != nullptr && _params->strategy().log_timing()) { _log_msg.type = MSG_TYPE::MSG_LATENCY; _log_msg.uber.a_latency.epoch = 0; _log_msg.uber.a_latency.nanos = _tsc.nanos(t0,t1); _log_msg.uber.a_latency.type = LATENCY_TYPE::LT_EPOLL; _oob_logger->log(_log_msg); }*/ if( _ready_cnt < 0 ) { std::cout << "Error in epoll_wait " << std::endl; return false; } if( _ready_cnt == 0 ) { return true; } for( int i = 0; i < _ready_cnt; ++i) { if (_evlist[i].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP)) { disable(_evlist[i].data.fd); remove(_evlist[i].data.fd); _handler->on_disconnect(_evlist[i].data.fd); continue; } con_type type = _cons[ _evlist[i].data.fd ].type; if(type == UDP) { if(_evlist[i].events & EPOLLIN) { _iov.iov_len = MAX_BUFFER; while( true) { // auto t2 = _tsc(); _buf_size = recvmsg(_evlist[i].data.fd, &_msg, MSG_DONTWAIT); // auto t3 = _tsc(); if(_buf_size <= 0) break; /*if(false && _params != nullptr && _params->strategy().log_timing()) { _log_msg.type = MSG_TYPE::MSG_LATENCY; _log_msg.uber.a_latency.epoch = 0; _log_msg.uber.a_latency.nanos = _tsc.nanos(t2,t3); _log_msg.uber.a_latency.type = LATENCY_TYPE::LT_EPOLL; _oob_logger->log(_log_msg); }*/ if(cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_TIMESTAMP || cmsg->cmsg_len != CMSG_LEN(sizeof(_kernel_time))) { std::cout << "cannot obtain kernel timestamp ignoring UDP packet" << std::endl; } else { _handler->on_udp_packet(_evlist[i].data.fd, _buffer, _buf_size, from_timeval(*(struct timeval *)CMSG_DATA(cmsg))); } _iov.iov_len = MAX_BUFFER; } } } else if(type == TCP) { if(_evlist[i].events & EPOLLIN) { while( ( _buf_size = recv(_evlist[i].data.fd, _buffer, MAX_BUFFER, MSG_DONTWAIT)) > 0) { gettimeofday((struct timeval *)&_tcp_time, NULL); _handler->on_tcp_packet(_evlist[i].data.fd, _buffer, _buf_size, from_timeval(_tcp_time)); } } } else if(type == TIMER) { if(_evlist[i].events & EPOLLIN) { if ( (_buf_size = read(_evlist[i].data.fd, _buffer, MAX_BUFFER)) > 0) { gettimeofday((struct timeval *)&_tcp_time, NULL); _handler->on_timer(_evlist[i].data.fd, _buffer, _buf_size, from_timeval(_tcp_time)); } } } } return true; }