Exemple #1
0
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;
}