void SocketSet::private_test_dump_request_sets( timeval *timeout ) { std::ostringstream ostr; ostr<<"calling select with fds="; for (Set::iterator it = _autoset.begin(); it != _autoset.end(); it++) { VsnetSocketBase *b = (*it); int fd = b->get_fd(); if (fd >= 0) { ostr<<fd<<" "; if ( b->need_test_writable() ) ostr<<"+"<<b->get_write_fd()<<" "; } } #ifndef USE_NO_THREAD ostr<<_thread_wakeup.getread()<<"(w)"; #endif if (timeout) ostr<<" t="<<timeout->tv_sec<<":"<<timeout->tv_usec; else ostr<<" t=NULL (blocking)"; ostr<<ends; if (!timeout || timeout->tv_sec >= 1) { COUT<<ostr.str()<<endl; } else { static long waitabit = 0; waitabit += 1; if (waitabit > 100) { COUT<<ostr.str()<<endl; waitabit = 0; } } }
void SocketSet::private_test_dump_active_sets( int maxfd, fd_set& read_before, fd_set& read_after, fd_set& write_before, fd_set& write_after ) { #if 0 // Causes compile errors and I'm too lazy to figure it out at the moment. std::ostringstream str_r; std::ostringstream str_w; str_r << " *** read set: "; str_w << " *** write set: "; for( int i=0; i<maxfd; i++ ) { if( FD_ISSET( i, &read_before ) ) { if( FD_ISSET( i, &read_after ) ) str_r << i << "(!) "; else str_r << i << " "; } else if( FD_ISSET( i, &read_after ) ) { str_r << "(?>>" << i << "<<?)"; } if( FD_ISSET( i, &write_before ) ) { if( FD_ISSET( i, &write_after ) ) str_w << i << "(!) "; else str_w << i << " "; } else if( FD_ISSET( i, &write_after ) ) { str_w << "(?>>" << i << "<<?)"; } } str_r << ends; str_w << ends; std::ostringstream ostr_r; std::ostringstream ostr_w; ostr_r << " *** read fds tested: "; ostr_w << " *** write fds tested: "; for( Set::iterator it = _autoset.begin(); it != _autoset.end(); it++ ) { VsnetSocketBase* b = (*it); int fd = b->get_fd(); if( fd >= 0 ) { if( FD_ISSET(fd,&read_after) ) { ostr_r << b->get_socktype() << " "; } } fd = b->get_write_fd(); if( fd >= 0 ) { if( FD_ISSET(fd,&write_after) ) { ostr_w << "+" << b->get_socktype() << " "; } } } #ifndef USE_NO_THREAD if( FD_ISSET( _thread_wakeup.getread(), &read_after ) ) { ostr_r << _thread_wakeup.getread() << "(pipe)"; } #endif ostr_r << ends; ostr_w << ends; COUT << "select saw activity:" << endl << str_r.str() << endl << str_w.str() << endl << ostr_r.str() << endl << ostr_w.str() << endl; #endif }
int SocketSet::private_select( timeval* timeout ) { #ifdef VSNET_DEBUG timeval* enter_timeout = NULL; if( timeout ) enter_timeout = new timeval(*timeout); fd_set debug_copy_of_read_set_select; fd_set debug_copy_of_write_set_select; FD_ZERO( &debug_copy_of_read_set_select ); FD_ZERO( &debug_copy_of_write_set_select ); #endif fd_set read_set_select; fd_set write_set_select; int max_sock_select = 0; FD_ZERO( &read_set_select ); FD_ZERO( &write_set_select ); if( !_client_mgr.expired() ) { boost::shared_ptr<VsnetDownload::Client::Manager> mgr( _client_mgr.lock()); if( (bool)mgr ) { mgr->lower_check_queues( ); } } if( !_server_mgr.expired() ) { boost::shared_ptr<VsnetDownload::Server::Manager> mgr( _server_mgr.lock() ); if( (bool)mgr ) { mgr->lower_check_queues( ); } } // private_test_dump_request_sets( timeout ); for( Set::iterator it = _autoset.begin(); it != _autoset.end(); it++ ) { VsnetSocketBase* b = (*it); int fd = b->get_fd(); bool wrote_on_negative=false; if (fd<0&&b->write_on_negative()) { b->lower_clean_sendbuf( ); wrote_on_negative=true; fd = b->get_fd(); } if( fd >= 0 ) { private_addset( fd, read_set_select, max_sock_select ); if( b->need_test_writable( )&& !wrote_on_negative ) { private_addset( b->get_write_fd(), write_set_select, max_sock_select ); // printf("Checking for read/writability..."); } else { // printf("Checking for readability..."); } } } #ifndef USE_NO_THREAD private_addset( _thread_wakeup.getread(), read_set_select, max_sock_select ); #endif #ifdef VSNET_DEBUG timeval* used_timeout = NULL; if( timeout ) used_timeout = new timeval(*timeout); for( int i=0; i<max_sock_select; i++ ) { if( FD_ISSET( i, &read_set_select ) ) FD_SET( i, &debug_copy_of_read_set_select ); if( FD_ISSET( i, &write_set_select ) ) FD_SET( i, &debug_copy_of_write_set_select ); } #endif int ret = ::select( max_sock_select, &read_set_select, &write_set_select, 0, timeout ); if( ret == -1 ) { #if defined(_WIN32) && !defined(__CYGWIN__) if( WSAGetLastError()!=WSAEINVAL) COUT<<"WIN32 error : "<<WSAGetLastError()<<endl; #else perror( "Select failed : "); #endif } else if( ret == 0 ) { // printf("Nothing to do.\n"); #ifdef VSNET_DEBUG #if 0 std::ostringstream s1; std::ostringstream s2; if( enter_timeout ) s1 << *enter_timeout << ends; else s1 << "(NULL)" << ends; if( used_timeout ) s2 << *used_timeout << ends; else s2 << "(NULL)" << ends; COUT << "Timeout:" << endl << " *** SocketSet::select called with " << s1.str() << endl << " *** ::select called with " << s2.str() << endl; #endif #endif } else { ret++; #if defined(VSNET_DEBUG) private_test_dump_active_sets( max_sock_select, debug_copy_of_read_set_select, read_set_select, debug_copy_of_write_set_select, write_set_select ); #endif for( Set::iterator it = _autoset.begin(); it != _autoset.end(); it++ ) { VsnetSocketBase* b = (*it); int fd = b->get_fd(); if( fd >= 0 ) { if( FD_ISSET(fd,&read_set_select) ) { // printf("Reading.\n"); if (!b->lower_selected( )) ret--; // No complete packet received yet. } if(b->isReadyToSend(&write_set_select) ) { // printf("Writing.\n"); ret--; b->lower_sendbuf( ); } } else { if(b->isReadyToSend(&write_set_select)) { // printf("reconnecting?\n"); #ifdef VSNET_DEBUG COUT << "saw activity on " << b->get_write_fd() << " but main file descriptor is " << b->get_fd() << endl; #endif b->lower_clean_sendbuf( ); } } } #ifndef USE_NO_THREAD if( FD_ISSET( _thread_wakeup.getread(), &read_set_select ) ) { char c; _thread_wakeup.read( &c, 1 ); } #endif } if( _blockmain ) { // whatever the reason for leaving select, if we have been asked // to signal the main thread on wakeup, we do it _blockmain_mx.lock( ); _blockmain_cond.signal( ); _blockmain_mx.unlock( ); } return ret; }