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;
}