rspConnection.cpp

00001 
00002 /* Copyright (c) 2009, Cedric Stalder <[email protected]>
00003  *               2009-2010, Stefan Eilemann <[email protected]>
00004  *
00005  * This library is free software; you can redistribute it and/or modify it under
00006  * the terms of the GNU Lesser General Public License version 2.1 as published
00007  * by the Free Software Foundation.
00008  *  
00009  * This library is distributed in the hope that it will be useful, but WITHOUT
00010  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00012  * details.
00013  * 
00014  * You should have received a copy of the GNU Lesser General Public License
00015  * along with this library; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017  */
00018 
00019 #include "rspConnection.h"
00020 
00021 #ifdef EQ_USE_BOOST
00022 #include "connection.h"
00023 #include "connectionDescription.h"
00024 #include "global.h"
00025 #include "log.h"
00026 
00027 #include <eq/base/rng.h>
00028 #include <eq/base/sleep.h>
00029 
00030 #include <boost/bind.hpp>
00031 
00032 //#define EQ_INSTRUMENT_RSP
00033 #define EQ_RSP_MERGE_WRITES
00034 #define EQ_RSP_MAX_TIMEOUTS 2000
00035 
00036 using namespace boost::asio;
00037 
00038 namespace eq
00039 {
00040 namespace net
00041 {
00042 
00043 namespace
00044 {
00045 #ifdef EQ_INSTRUMENT_RSP
00046 base::a_int32_t nReadData;
00047 base::a_int32_t nBytesRead;
00048 base::a_int32_t nBytesWritten;
00049 base::a_int32_t nDatagrams;
00050 base::a_int32_t nRepeated;
00051 base::a_int32_t nMergedDatagrams;
00052 base::a_int32_t nAckRequests;
00053 base::a_int32_t nAcksSend;
00054 base::a_int32_t nAcksSendTotal;
00055 base::a_int32_t nAcksRead;
00056 base::a_int32_t nAcksAccepted;
00057 base::a_int32_t nNAcksSend;
00058 base::a_int32_t nNAcksRead;
00059 base::a_int32_t nNAcksResend;
00060 
00061 float writeWaitTime = 0.f;
00062 base::Clock instrumentClock;
00063 #endif
00064 
00065 static uint16_t _numBuffers = 0;
00066 }
00067 
00068 RSPConnection::RSPConnection()
00069         : _id( 0 )
00070         , _idAccepted( false )
00071         , _mtu( Global::getIAttribute( Global::IATTR_UDP_MTU ))
00072         , _ackFreq( Global::getIAttribute( Global::IATTR_RSP_ACK_FREQUENCY ))
00073         , _payloadSize( _mtu - sizeof( DatagramData ))
00074         , _timeouts( 0 )
00075         , _event( new EventConnection )
00076         , _read( 0 )
00077         , _write( 0 )
00078         , _timeout( _ioService )
00079         , _wakeup( _ioService )
00080         , _maxBucketSize( ( _mtu * _ackFreq) >> 1 )
00081         , _bucketSize( 0 )
00082         , _sendRate( 0 )
00083         , _thread ( 0 )
00084         , _acked( std::numeric_limits< uint16_t >::max( ))
00085         , _threadBuffers( Global::getIAttribute( Global::IATTR_RSP_NUM_BUFFERS))
00086         , _recvBuffer( _mtu )
00087         , _readBuffer( 0 )
00088         , _readBufferPos( 0 )
00089         , _sequence( 0 )
00090 {
00091     _buildNewID();
00092     _description->type = CONNECTIONTYPE_RSP;
00093     _description->bandwidth = 102400;
00094 
00095     EQCHECK( _event->connect( ));
00096 
00097     _buffers.reserve( Global::getIAttribute( Global::IATTR_RSP_NUM_BUFFERS ));
00098     while( static_cast< int32_t >( _buffers.size( )) <
00099            Global::getIAttribute( Global::IATTR_RSP_NUM_BUFFERS ))
00100     {
00101         _buffers.push_back( new Buffer( _mtu ));
00102     }
00103 
00104     EQASSERT( sizeof( DatagramNack ) <= size_t( _mtu ));
00105     EQLOG( LOG_RSP ) << "New RSP connection, " << _buffers.size()
00106                      << " buffers of " << _mtu << " bytes" << std::endl;
00107 }
00108 
00109 RSPConnection::~RSPConnection()
00110 {
00111     close();
00112     while( !_buffers.empty( ))
00113     {
00114         delete _buffers.back();
00115         _buffers.pop_back();
00116     }
00117 }
00118 
00119 void RSPConnection::close()
00120 {
00121     if( _parent.isValid() && _parent->_id == _id )
00122         _parent->close();
00123 
00124     while(( !_parent && _isWriting() ))
00125     {
00126         base::sleep( 10 );
00127     }
00128     _close();
00129     _event->set();
00130 }
00131 
00132 void RSPConnection::_close()
00133 {
00134     if( _state == STATE_CLOSED )
00135         return;
00136     _state = STATE_CLOSING;
00137     base::ScopedMutex<> mutex( _mutexEvent );
00138  
00139     if( _thread )
00140     {
00141         EQASSERT( !_thread->isCurrent( ));
00142         _sendSimpleDatagram( ID_EXIT, _id );
00143         _ioService.stop();
00144         _thread->join();
00145         _thread = 0;
00146         
00147         for( RSPConnections::iterator i = _children.begin();
00148              i != _children.end(); ++i )
00149         {
00150             RSPConnectionPtr child = *i;
00151             base::ScopedMutex<> mutexChild( child->_mutexEvent );
00152             child->_appBuffers.push( 0 );
00153             child->_event->set();
00154         }
00155 
00156         _children.clear();
00157         _childrenConnecting.clear();
00158     }
00159 
00160     _parent = 0;
00161 
00162     if( _read )
00163         _read->close();
00164     delete _read;
00165     _read = 0;
00166 
00167     if( _write )
00168         _write->close();
00169     delete _write;
00170     _write = 0;
00171 
00172     _threadBuffers.clear();
00173     _appBuffers.push( 0 ); // unlock any other read/write threads
00174 
00175     _state = STATE_CLOSED;
00176     _fireStateChanged();
00177 }
00178 
00179 //----------------------------------------------------------------------
00180 // Async IO handles
00181 //----------------------------------------------------------------------
00182 uint16_t RSPConnection::_buildNewID()
00183 {
00184     eq::base::RNG rng;
00185     _id = rng.get< uint16_t >();
00186     return _id;
00187 }
00188 
00189 bool RSPConnection::listen()
00190 {
00191     EQASSERT( _description->type == CONNECTIONTYPE_RSP );
00192 
00193     if( _state != STATE_CLOSED )
00194         return false;
00195     
00196     _state = STATE_CONNECTING;
00197     _numBuffers =  Global::getIAttribute( Global::IATTR_RSP_NUM_BUFFERS );
00198     _fireStateChanged();
00199 
00200     // init udp connection
00201     if( _description->port == 0 )
00202         _description->port = EQ_DEFAULT_PORT;
00203     if( _description->getHostname().empty( ))
00204         _description->setHostname( "239.255.42.43" );
00205     if( _description->getInterface().empty( ))
00206         _description->setInterface( "0.0.0.0" );
00207 
00208     try
00209     {
00210         const ip::address readAddress( ip::address::from_string( "0.0.0.0" ));
00211         const ip::udp::endpoint readEndpoint( readAddress, _description->port );
00212 
00213         const ip::address mcAddr(
00214             ip::address::from_string( _description->getHostname( )));
00215         const ip::udp::endpoint writeEndpoint( mcAddr, _description->port );
00216 
00217         _read = new ip::udp::socket( _ioService );
00218         _write = new ip::udp::socket( _ioService );
00219         _read->open( readEndpoint.protocol( ));
00220         _write->open( writeEndpoint.protocol( ));
00221 
00222         _read->set_option( ip::udp::socket::reuse_address( true ));
00223         _write->set_option( ip::udp::socket::reuse_address( true ));
00224         _read->set_option( ip::udp::socket::receive_buffer_size( 
00225                        Global::getIAttribute( Global::IATTR_UDP_BUFFER_SIZE )));
00226         _write->set_option( ip::udp::socket::send_buffer_size( 
00227                        Global::getIAttribute( Global::IATTR_UDP_BUFFER_SIZE )));
00228 
00229         _read->bind( readEndpoint );
00230 
00231         const ip::address ifAddr( 
00232             ip::address::from_string( _description->getInterface( )));
00233 
00234         _read->set_option( ip::multicast::join_group( mcAddr.to_v4(),
00235                                                       ifAddr.to_v4( )));
00236         _write->set_option( ip::multicast::outbound_interface( ifAddr.to_v4()));
00237 
00238         _write->connect( writeEndpoint );
00239 
00240         _read->set_option( ip::multicast::enable_loopback( false ));
00241         _write->set_option( ip::multicast::enable_loopback( false ));
00242     }
00243     catch( boost::system::system_error& error )
00244     {
00245         EQWARN << "can't setup underlying UDP connection: " << error.what()
00246                << std::endl;
00247         delete _read;
00248         delete _write;
00249         _read = 0;
00250         _write = 0;
00251         return false;
00252     }
00253 
00254     // init communication protocol thread
00255     _thread = new Thread( this );
00256     _bucketSize = 0;
00257     _sendRate = _description->bandwidth;
00258 
00259     // waits until RSP protocol establishes connection to the multicast network
00260     if( !_thread->start( ) )
00261     {
00262         close();
00263         return false;
00264     }
00265 
00266     // Make all buffers available for writing
00267     EQASSERT(_appBuffers.isEmpty());
00268     _appBuffers.push( _buffers );
00269 
00270     _fireStateChanged();
00271 
00272     EQINFO << "Listening on " << _description->getHostname() << ":"
00273            << _description->port << " (" << _description->toString() << " @"
00274            << (void*)this << ")" << std::endl;
00275     return true;
00276 }
00277 
00278 ConnectionPtr RSPConnection::acceptSync()
00279 {
00280     if( _state != STATE_LISTENING )
00281         return 0;
00282         
00283     // protect event->set, _children and _childrenConnecting
00284     base::ScopedMutex<> mutexConn( _mutexConnection );
00285     EQASSERT( !_childrenConnecting.empty( ));
00286     if( _childrenConnecting.empty( ))
00287         return 0;
00288 
00289     RSPConnectionPtr newConnection = _childrenConnecting.back();
00290     _childrenConnecting.pop_back();
00291     _children.push_back( newConnection );
00292     _sendDatagramCountNode();
00293 
00294     EQINFO << "accepted RSP connection " << newConnection->_id << std::endl;
00295 
00296     if ( !_childrenConnecting.empty() )
00297         _event->set();
00298     else 
00299         _event->reset();
00300 
00301     ConnectionPtr connection = newConnection.get();
00302     return connection;
00303 }
00304 
00305 int64_t RSPConnection::readSync( void* buffer, const uint64_t bytes, const bool)
00306 {
00307     EQASSERT( bytes > 0 );
00308     if( _state != STATE_CONNECTED )
00309         return -1;
00310 
00311     uint64_t bytesLeft = bytes;
00312     uint8_t* ptr = reinterpret_cast< uint8_t* >( buffer );
00313 
00314     // redundant (done by the caller already), but saves some lock ops
00315     while( bytesLeft )
00316     {
00317         if( !_readBuffer )
00318         {
00319             EQASSERT( _readBufferPos == 0 );
00320             _readBuffer = _appBuffers.pop();
00321             if( !_readBuffer )
00322             {
00323                 close();
00324                 return (bytes == bytesLeft) ? 
00325                     -1 : static_cast< int64_t >( bytes - bytesLeft );
00326             }
00327         }
00328         EQASSERT( _readBuffer );
00329 
00330         const DatagramData* header = reinterpret_cast< const DatagramData* >(
00331             _readBuffer->getData( ));
00332         const uint8_t* payload = reinterpret_cast< const uint8_t* >( header+1 );
00333 
00334         const size_t dataLeft = header->size - _readBufferPos;
00335         const size_t size = EQ_MIN( static_cast< size_t >( bytesLeft ),
00336                                     dataLeft );
00337 
00338         memcpy( ptr, payload + _readBufferPos, size );
00339         _readBufferPos += size;
00340         ptr += size;
00341         bytesLeft -= size;
00342 
00343         // if all data in the buffer has been taken
00344         if( _readBufferPos == header->size )
00345         {
00346             //EQLOG( LOG_RSP ) << "reset read buffer  " << header->sequence
00347             //                 << std::endl;
00348 
00349             EQCHECK( _threadBuffers.push( _readBuffer ));
00350             _readBuffer = 0;
00351             _readBufferPos = 0;
00352         }
00353         else
00354         {
00355             EQASSERT( _readBufferPos < header->size );
00356         }
00357     }
00358 
00359     if( _readBuffer || !_appBuffers.isEmpty( ))
00360         _event->set();
00361     else
00362     {
00363         base::ScopedMutex<> mutex( _mutexEvent );
00364         if( _appBuffers.isEmpty( ))
00365             _event->reset();
00366 
00367     }
00368 
00369 #ifdef EQ_INSTRUMENT_RSP
00370     nBytesRead += bytes;
00371 #endif
00372     return bytes;
00373 }
00374 
00375 void RSPConnection::Thread::run()
00376 {
00377     _connection->_runThread();
00378     _connection = 0;
00379     EQINFO << "Left RSP protocol thread" << std::endl;
00380 }
00381 
00382 void RSPConnection::_handleTimeout( const boost::system::error_code& error )
00383 {
00384     if( error == boost::asio::error::operation_aborted )
00385         return;
00386     
00387     if( _state == STATE_LISTENING )
00388         _handleConnectedTimeout();
00389     else if( _idAccepted )
00390         _handleInitTimeout();
00391     else
00392         _handleAcceptIDTimeout();
00393 }
00394 
00395 void RSPConnection::_handleAcceptIDTimeout( )
00396 {
00397     ++_timeouts;
00398     if ( _timeouts < 20 )
00399     {
00400         EQLOG( LOG_RSP ) << "Announce " << _id << std::endl;
00401         _sendSimpleDatagram( ID_HELLO, _id );
00402     }
00403     else 
00404     {
00405         EQLOG( LOG_RSP ) << "Confirm " << _id << std::endl;
00406         EQINFO << "opened RSP connection " << _id << std::endl;
00407         _sendSimpleDatagram( ID_CONFIRM, _id );
00408         _addNewConnection( _id );
00409         _idAccepted = true;
00410         _timeouts = 0;
00411         // send a first datagram to announce me and discover all other
00412         // connections
00413         _sendDatagramCountNode();
00414     }
00415     _setTimeout( 10 );
00416 }
00417 
00418 void RSPConnection::_handleInitTimeout( )
00419 {
00420     EQASSERT( _state != STATE_LISTENING );
00421     ++_timeouts;
00422     if( _timeouts < 20 )
00423         _sendDatagramCountNode();
00424     else
00425     {
00426         _state = STATE_LISTENING;
00427         _timeouts = 0;
00428         if( _children.empty() )
00429             _ioService.stop();
00430     } 
00431     _setTimeout( 10 );
00432 }
00433 
00434 void RSPConnection::_handleConnectedTimeout( )
00435 {
00436     if( _state != STATE_LISTENING )
00437     {
00438         _ioService.stop();
00439         return;
00440     }
00441 
00442     _processOutgoing();
00443 
00444     if( _timeouts >= EQ_RSP_MAX_TIMEOUTS )
00445     {
00446         EQERROR << "Too many timeouts during send: " << _timeouts << std::endl;
00447         _sendSimpleDatagram( ID_EXIT, _id );
00448         _appBuffers.pushFront( 0 ); // unlock write function
00449         for( RSPConnections::iterator i = _children.begin();
00450              i != _children.end(); ++i )
00451         {
00452             RSPConnectionPtr child = *i;
00453             child->_state = STATE_CLOSING;
00454             child->_appBuffers.push( 0 ); // unlock read func
00455         }
00456         _ioService.stop();
00457     }
00458 }
00459 
00460 bool RSPConnection::_initThread()
00461 {
00462     EQINFO << "Started RSP protocol thread" << std::endl;
00463     _timeouts = 0;
00464  
00465    // send a first datagram for announce me and discover other connection 
00466     EQLOG( LOG_RSP ) << "Announce " << _id << std::endl;
00467     _sendSimpleDatagram( ID_HELLO, _id );
00468     _setTimeout( 10 ); 
00469     _asyncReceiveFrom();
00470     _ioService.run();
00471     return  _state == STATE_LISTENING;
00472 }
00473 
00474 void RSPConnection::_runThread()
00475 {
00476     //__debugbreak();
00477     _ioService.reset();
00478     _ioService.run();
00479 }
00480 
00481 void RSPConnection::_setTimeout( const int32_t timeOut )
00482 {
00483     EQASSERT( timeOut >= 0 );
00484     _timeout.expires_from_now( boost::posix_time::milliseconds( timeOut ));
00485     _timeout.async_wait( boost::bind( &RSPConnection::_handleTimeout, this,
00486                                       placeholders::error ));
00487 }
00488 
00489 void RSPConnection::_postWakeup()
00490 {
00491     _wakeup.expires_from_now( boost::posix_time::milliseconds( 0 ));
00492     _wakeup.async_wait( boost::bind( &RSPConnection::_handleTimeout, this,
00493                                      placeholders::error ));
00494 }
00495 
00496 void RSPConnection::_processOutgoing()
00497 {
00498 #ifdef EQ_INSTRUMENT_RSP
00499     if( instrumentClock.getTime64() > 1000 )
00500     {
00501         EQWARN << *this << std::endl;
00502         instrumentClock.reset();
00503     }
00504 #endif
00505 
00506     if( !_repeatQueue.empty( ))
00507         _repeatData();
00508     else
00509         _writeData();
00510 
00511     if( !_threadBuffers.isEmpty() || !_repeatQueue.empty( ))
00512     {
00513         _setTimeout( 0 ); // call again to send remaining
00514         return;
00515     }
00516     // no more data to write, check/send ack request, reset timeout
00517 
00518     if( _writeBuffers.empty( )) // got all acks
00519     {
00520         _timeouts = 0;
00521         _timeout.cancel();
00522         return;
00523     }
00524 
00525     const int64_t timeout =
00526         Global::getIAttribute( Global::IATTR_RSP_ACK_TIMEOUT );
00527     const int64_t left = timeout - _clock.getTime64();
00528 
00529     if( left > 0 )
00530     {
00531         _setTimeout( left );
00532         return;
00533     }
00534 
00535     // (repeat) ack request
00536     _clock.reset();
00537     ++_timeouts;
00538     _sendAckRequest();
00539     _setTimeout( timeout );
00540 }
00541 
00542 void RSPConnection::_writeData()
00543 {
00544     Buffer* buffer = 0;
00545     if( !_threadBuffers.pop( buffer )) // nothing to write
00546         return;
00547 
00548     _timeouts = 0;
00549     EQASSERT( buffer );
00550 
00551     // write buffer
00552     DatagramData* header = reinterpret_cast<DatagramData*>( buffer->getData( ));
00553     header->sequence = _sequence++;
00554 
00555 #ifdef EQ_RSP_MERGE_WRITES
00556     if( header->size < _payloadSize && !_threadBuffers.isEmpty( ))
00557     {
00558         std::vector< Buffer* > appBuffers;
00559         while( header->size < _payloadSize && !_threadBuffers.isEmpty( ))
00560         {
00561             Buffer* buffer2 = 0;
00562             EQCHECK( _threadBuffers.getFront( buffer2 ));
00563             EQASSERT( buffer2 );
00564             DatagramData* header2 = 
00565                 reinterpret_cast<DatagramData*>( buffer2->getData( ));
00566 
00567             if( uint32_t( header->size + header2->size ) > _payloadSize )
00568                 break;
00569 
00570             memcpy( reinterpret_cast<uint8_t*>( header + 1 ) + header->size,
00571                     header2 + 1, header2->size );
00572             header->size += header2->size;
00573             EQCHECK( _threadBuffers.pop( buffer2 ));
00574             appBuffers.push_back( buffer2 );
00575 #ifdef EQ_INSTRUMENT_RSP
00576             ++nMergedDatagrams;
00577 #endif
00578         }
00579 
00580         if( !appBuffers.empty( ))
00581             _appBuffers.push( appBuffers );
00582     }
00583 #endif
00584 
00585     // send data
00586     //  Note 1: We could optimize the send away if we're all alone, but this is
00587     //          not a use case for RSP, so we don't care.
00588     //  Note 2: Data to myself will be 'written' in _finishWriteQueue once we
00589     //          got all acks for the packet
00590     const uint32_t size = header->size + sizeof( DatagramData );
00591 
00592     _waitWritable( size ); // OPT: process incoming in between
00593     _write->send( boost::asio::buffer( header, size ));
00594 
00595 #ifdef EQ_INSTRUMENT_RSP
00596     ++nDatagrams;
00597     nBytesWritten += header->size;
00598 #endif
00599 
00600     // save datagram for repeats (and self)
00601     _writeBuffers.push_back( buffer );
00602 
00603     if( _children.size() == 1 ) // We're all alone
00604     {
00605         EQASSERT( _children.front()->_id == _id );
00606         _finishWriteQueue( _sequence - 1 );
00607     }
00608 }
00609 
00610 void RSPConnection::_waitWritable( const uint64_t bytes )
00611 {
00612 #ifdef EQ_INSTRUMENT_RSP
00613     base::Clock clock;
00614 #endif
00615 
00616     _bucketSize += static_cast< uint64_t >( _clock.resetTimef() * _sendRate );
00617                                                      // opt omit: * 1024 / 1000;
00618     _bucketSize = EQ_MIN( _bucketSize, _maxBucketSize );
00619 
00620     const uint64_t size = EQ_MIN( bytes, static_cast< uint64_t >( _mtu ));
00621     while( _bucketSize < size )
00622     {
00623         //base::sleep( 1 );
00624         base::Thread::yield();
00625         float time = _clock.resetTimef();
00626 
00627         while( time == 0.f )
00628         {
00629             base::Thread::yield();
00630             time = _clock.resetTimef();
00631         }
00632 
00633         _bucketSize += static_cast< int64_t >( time * _sendRate );
00634         _bucketSize = EQ_MIN( _bucketSize, _maxBucketSize );
00635     }
00636     _bucketSize -= size;
00637 
00638 #ifdef EQ_INSTRUMENT_RSP
00639     writeWaitTime += clock.getTimef();
00640 #endif
00641 
00642     if( _sendRate < _description->bandwidth )
00643     {
00644         _sendRate += int64_t(
00645             float( Global::getIAttribute( Global::IATTR_RSP_ERROR_UPSCALE )) *
00646             float( _description->bandwidth ) * .001f );
00647         EQLOG( LOG_RSP ) << "speeding up to " << _sendRate << " KB/s"
00648                          << std::endl;
00649     }
00650 }
00651 
00652 void RSPConnection::_repeatData()
00653 {
00654     _timeouts = 0;
00655 
00656     while( !_repeatQueue.empty( ))
00657     {
00658         Nack& request = _repeatQueue.front(); 
00659         const uint16_t distance = _sequence - request.start;
00660         EQASSERT( distance != 0 );
00661 
00662         if( distance <= _writeBuffers.size( )) // not already acked
00663         {
00664 //          EQLOG( LOG_RSP ) << "Repeat " << request.start << ", " << _sendRate
00665 //                           << "KB/s"<< std::endl;
00666 
00667             const size_t i = _writeBuffers.size() - distance;
00668             Buffer* buffer = _writeBuffers[i];
00669             EQASSERT( buffer );
00670 
00671             DatagramData* header = 
00672                 reinterpret_cast<DatagramData*>( buffer->getData( ));
00673             const uint32_t size = header->size + sizeof( DatagramData );
00674             EQASSERT( header->sequence == request.start );
00675 
00676             // send data
00677             _waitWritable( size ); // OPT: process incoming in between
00678             _write->send( boost::asio::buffer( header, size ) );
00679 #ifdef EQ_INSTRUMENT_RSP
00680             ++nRepeated;
00681 #endif
00682         }
00683 
00684         if( request.start == request.end )
00685             _repeatQueue.pop_front();    // done with request
00686         else
00687             ++request.start;
00688 
00689         if( distance <= _writeBuffers.size( )) // send something
00690             return;
00691     }
00692 }
00693 
00694 void RSPConnection::_finishWriteQueue( const uint16_t sequence )
00695 {
00696     EQLOG( LOG_RSP ) << "Got all remote acks for " << sequence << " current "
00697                      << _sequence << std::endl;
00698     EQASSERT( !_writeBuffers.empty( ));
00699 
00700     RSPConnectionPtr connection = _findConnection( _id );
00701     EQASSERT( connection.isValid( ));
00702     EQASSERT( connection->_recvBuffers.empty( ));
00703 
00704     // Bundle pushing the buffers to the app to avoid excessive lock ops
00705     Buffers readBuffers;
00706     Buffers freeBuffers;
00707 
00708     const uint16_t size = _sequence - sequence - 1;
00709     EQASSERTINFO( size <= uint16_t( _writeBuffers.size( )),
00710                   size << " > " << _writeBuffers.size( ));
00711 
00712     while( _writeBuffers.size() > size_t( size ))
00713     {
00714         Buffer* buffer = _writeBuffers.front();
00715         _writeBuffers.pop_front();
00716 
00717 #ifndef NDEBUG
00718         const DatagramData* datagram = 
00719             reinterpret_cast< const DatagramData* >( buffer->getData( ));
00720         EQASSERT( datagram->writerID == _id );
00721         EQASSERTINFO( datagram->sequence == 
00722                       uint16_t( connection->_sequence + readBuffers.size( )),
00723                       datagram->sequence << ", " << connection->_sequence <<
00724                       ", " << readBuffers.size( ));
00725       //EQLOG( LOG_RSP ) << "self receive " << datagram->sequence << std::endl;
00726 #endif
00727 
00728         Buffer* newBuffer = connection->_newDataBuffer( *buffer );
00729         if( !newBuffer && !readBuffers.empty( )) // push prepared app buffers
00730         {
00731             base::ScopedMutex<> mutex( connection->_mutexEvent );
00732             EQLOG( LOG_RSP ) << "post " << readBuffers.size()
00733                              << " buffers starting with sequence "
00734                              << connection->_sequence << std::endl;
00735 
00736             connection->_appBuffers.push( readBuffers );
00737             connection->_sequence += readBuffers.size();
00738             readBuffers.clear();
00739             connection->_event->set();
00740         }
00741 
00742         while( !newBuffer ) // no more data buffers, wait for app to drain
00743         {
00744             newBuffer = connection->_newDataBuffer( *buffer );
00745             //base::sleep( 1 );
00746             base::Thread::yield();
00747         }
00748 
00749         freeBuffers.push_back( buffer );
00750         readBuffers.push_back( newBuffer );
00751     }
00752 
00753     _appBuffers.push( freeBuffers );
00754     if( !readBuffers.empty( ))
00755     {
00756         base::ScopedMutex<> mutex( connection->_mutexEvent );
00757 #if 0
00758         EQLOG( LOG_RSP ) 
00759             << "post " << readBuffers.size() << " buffers starting at "
00760             << connection->_sequence << std::endl;
00761 #endif
00762 
00763         connection->_appBuffers.push( readBuffers );
00764         connection->_sequence += readBuffers.size();
00765         connection->_event->set();
00766     }
00767 
00768     connection->_acked = uint16_t( connection->_sequence - 1 );
00769     EQASSERT( connection->_acked == sequence );
00770 
00771     _timeouts = 0;
00772 }
00773 
00774 void RSPConnection::_handlePacket( const boost::system::error_code& /* error */,
00775                                    const size_t /* bytes */ )
00776 {
00777     if( _state == STATE_LISTENING )
00778     {
00779         _handleConnectedData( _recvBuffer.getData() );
00780 
00781         if( _state == STATE_LISTENING )
00782             _processOutgoing();
00783         else
00784         {
00785             _ioService.stop();
00786             return;
00787         }
00788     }
00789     else if( _idAccepted )
00790         _handleInitData( _recvBuffer.getData() );
00791     else
00792         _handleAcceptIDData( _recvBuffer.getData() );
00793 
00794     //EQLOG( LOG_RSP ) << "_handlePacket timeout " << timeout << std::endl;
00795     _asyncReceiveFrom();
00796 }
00797 
00798 void RSPConnection::_handleAcceptIDData( const void* data )
00799 {
00800     const uint16_t type = *reinterpret_cast< const uint16_t* >( data );
00801     const DatagramNode* node = 
00802         reinterpret_cast< const DatagramNode* >( data );
00803     switch( type )
00804     {
00805         case ID_HELLO:
00806             _checkNewID( node->connectionID );
00807             break;
00808 
00809         case ID_DENY:
00810             // a connection refused my ID, try another ID
00811             if( node->connectionID == _id ) 
00812             {
00813                 _timeouts = 0;
00814                 _sendSimpleDatagram( ID_HELLO, _buildNewID() );
00815                 EQLOG( LOG_RSP ) << "Announce " << _id << std::endl;
00816             }
00817             break;
00818 
00819         case ID_EXIT:
00820             _removeConnection( node->connectionID );
00821             break;
00822 
00823         default:
00824             break;    
00825     }
00826 }
00827 
00828 void RSPConnection::_handleInitData( const void* data)
00829 {
00830     const uint16_t type = *reinterpret_cast< const uint16_t* >( data );
00831     const DatagramNode* node = reinterpret_cast< const DatagramNode* >( data );
00832     switch( type )
00833     {
00834         case ID_HELLO:
00835             _timeouts = 0;
00836             _checkNewID( node->connectionID ) ;
00837             return;
00838 
00839         case ID_CONFIRM:
00840             _timeouts = 0;
00841             _addNewConnection( node->connectionID );
00842             return;
00843 
00844         case COUNTNODE:
00845             if( _handleCountNode( ))
00846                 _state = STATE_LISTENING;
00847             break;
00848     
00849         case ID_EXIT:
00850             _removeConnection( node->connectionID );
00851             return;
00852 
00853         default:
00854             EQUNIMPLEMENTED;
00855             break;
00856     }
00857 }
00858 void RSPConnection::_handleConnectedData( const void* data )
00859 {
00860     const uint16_t type = *reinterpret_cast< const uint16_t* >( data );
00861     switch( type )
00862     {
00863         case DATA:
00864             EQCHECK( _handleData( _recvBuffer ));
00865             break;
00866 
00867         case ACK:
00868             EQCHECK( _handleAck( 
00869                       reinterpret_cast< const DatagramAck* >( data )));
00870             break;
00871 
00872         case NACK:
00873             EQCHECK( _handleNack(
00874                       reinterpret_cast< const DatagramNack* >( data )));
00875             break;
00876 
00877         case ACKREQ: // The writer asks for an ack/nack
00878             EQCHECK( _handleAckRequest(
00879                 reinterpret_cast< const DatagramAckRequest* >( data )));
00880             break;
00881 
00882         case ID_HELLO:
00883         {
00884             const DatagramNode* node =
00885                 reinterpret_cast< const DatagramNode* >( data );
00886             _checkNewID( node->connectionID );
00887             break;
00888         }
00889 
00890         case ID_CONFIRM:
00891         {
00892             const DatagramNode* node =
00893                 reinterpret_cast< const DatagramNode* >( data );
00894             _addNewConnection( node->connectionID );
00895             break;
00896         }
00897 
00898         case ID_EXIT:
00899         {
00900             const DatagramNode* node = 
00901                 reinterpret_cast< const DatagramNode* >( data );
00902             _removeConnection( node->connectionID );
00903             break;
00904         }
00905 
00906         case COUNTNODE:
00907             _handleCountNode();
00908             break;
00909 
00910         default:
00911             EQASSERTINFO( false, 
00912                           "Don't know how to handle packet of type " <<
00913                           type );
00914     }
00915 
00916 }
00917 
00918 void RSPConnection::_asyncReceiveFrom()
00919 {
00920     _read->async_receive_from(
00921         buffer( _recvBuffer.getData(), _mtu ), _readAddr,
00922         boost::bind( &RSPConnection::_handlePacket, this,
00923                      placeholders::error,
00924                      placeholders::bytes_transferred ));
00925 }
00926 
00927 bool RSPConnection::_handleData( Buffer& buffer )
00928 {
00929 #ifdef EQ_INSTRUMENT_RSP
00930     ++nReadData;
00931 #endif
00932     const DatagramData* datagram = 
00933         reinterpret_cast< const DatagramData* >( buffer.getData( ));
00934     const uint16_t writerID = datagram->writerID;
00935 #ifdef Darwin
00936     // There is occasionally a packet from ourselves, even though multicast loop
00937     // is not set?!
00938     if( writerID == _id )
00939         return true;
00940 #else
00941     EQASSERT( writerID != _id );
00942 #endif
00943 
00944     RSPConnectionPtr connection = _findConnection( writerID );
00945 
00946     if( !connection )  // unknown connection ?
00947     {
00948         EQASSERTINFO( false, "Can't find connection with id " << writerID );
00949         return false;
00950     }
00951     EQASSERT( connection->_id == writerID );
00952 
00953     const uint16_t sequence = datagram->sequence;
00954 //  EQLOG( LOG_RSP ) << "rcvd " << sequence << " from " << writerID <<std::endl;
00955 
00956     if( connection->_sequence == sequence ) // in-order packet
00957     {
00958         Buffer* newBuffer = connection->_newDataBuffer( buffer );
00959         if( !newBuffer ) // no more data buffers, drop packet
00960             return true;
00961 
00962         base::ScopedMutex<> mutex( connection->_mutexEvent );
00963         connection->_pushDataBuffer( newBuffer );
00964             
00965         while( !connection->_recvBuffers.empty( )) // enqueue ready pending data
00966         {
00967             newBuffer = connection->_recvBuffers.front();
00968             if( !newBuffer )
00969                 break;
00970             
00971             connection->_recvBuffers.pop_front();
00972             connection->_pushDataBuffer( newBuffer );
00973         }
00974 
00975         if( !connection->_recvBuffers.empty() &&
00976             !connection->_recvBuffers.front( )) // update for new _sequence
00977         {
00978             connection->_recvBuffers.pop_front();
00979         }
00980 
00981         connection->_event->set();
00982         return true;
00983     }
00984     
00985     if( connection->_sequence > sequence ||
00986         uint16_t( connection->_sequence - sequence ) <= _numBuffers )
00987     {
00988         // ignore it if it's a repetition for another reader
00989         return true;
00990     }
00991 
00992     // else out of order
00993 
00994     const uint16_t size = sequence - connection->_sequence;
00995     EQASSERT( size != 0 );
00996     EQASSERTINFO( size <= _numBuffers, size << " > " << _numBuffers );
00997 
00998     ssize_t i = ssize_t( size ) - 1;
00999     const bool gotPacket = ( connection->_recvBuffers.size() >= size && 
01000                              connection->_recvBuffers[ i ] );
01001     if( gotPacket )
01002         return true;
01003 
01004     Buffer* newBuffer = connection->_newDataBuffer( buffer );
01005     if( !newBuffer ) // no more data buffers, drop packet
01006         return true;
01007 
01008     if( connection->_recvBuffers.size() < size )
01009         connection->_recvBuffers.resize( size, 0 );
01010 
01011     EQASSERT( !connection->_recvBuffers[ i ] );
01012     connection->_recvBuffers[ i ] = newBuffer;
01013 
01014     // early nack: request missing packets before current
01015     --i;
01016     Nack nack = { connection->_sequence, sequence - 1 };
01017     if( i > 0 )
01018     {
01019         if( connection->_recvBuffers[i] ) // got previous packet
01020             return true;
01021 
01022         while( i >= 0 && !connection->_recvBuffers[i] )
01023             --i;
01024 
01025         const Buffer* lastBuffer = i>=0 ? connection->_recvBuffers[i] : 0;
01026         if( lastBuffer )
01027         {
01028             const DatagramData* last = 
01029                 reinterpret_cast<const DatagramData*>( lastBuffer->getData( ));
01030             nack.start = last->sequence + 1;
01031         }
01032     }
01033 
01034     EQLOG( LOG_RSP ) << "send early nack " << nack.start << ".." << nack.end
01035                      << " current " << connection->_sequence << " ooo "
01036                      << connection->_recvBuffers.size() << std::endl;
01037 
01038     if( nack.end < nack.start )
01039         // OPT: don't drop nack 0..nack.end, but it doesn't happen often
01040         nack.end = std::numeric_limits< uint16_t >::max();
01041 
01042     _sendNack( writerID, &nack, 1 );
01043     return true;
01044 }
01045 
01046 RSPConnection::Buffer* RSPConnection::_newDataBuffer( Buffer& inBuffer )
01047 {
01048     EQASSERT( static_cast< int32_t >( inBuffer.getMaxSize( )) == _mtu );
01049 
01050     Buffer* buffer = 0;
01051     if( !_threadBuffers.pop( buffer ))
01052     {
01053         // we do not have a free buffer, which means that the receiver is slower
01054         // then our read thread. This is bad, because now we'll drop the data
01055         // and will send a NAck packet upon the ack request, causing
01056         // retransmission even though we'll probably drop it again
01057         EQLOG( LOG_RSP ) << "Reader too slow, dropping data" << std::endl;
01058         return 0;
01059     }
01060 
01061     buffer->swap( inBuffer );
01062     return buffer;
01063 }
01064 
01065 void RSPConnection::_pushDataBuffer( Buffer* buffer )
01066 {
01067     EQASSERT( _parent );
01068     EQASSERTINFO( ((DatagramData*)buffer->getData( ))->sequence == _sequence,
01069                   ((DatagramData*)buffer->getData( ))->sequence << " != " <<
01070                   _sequence );
01071 
01072     if( (( _sequence + _id ) % _ackFreq ) == 0 )
01073         _parent->_sendAck( _id, _sequence );
01074 
01075     EQLOG( LOG_RSP ) << "post buffer " << _sequence << std::endl;
01076     ++_sequence;
01077     _appBuffers.push( buffer );
01078 }
01079 
01080 bool RSPConnection::_handleAck( const DatagramAck* ack )
01081 {
01082 #ifdef EQ_INSTRUMENT_RSP
01083     ++nAcksRead;
01084 #endif
01085 
01086     if ( ack->writerID != _id )
01087         return true;
01088 
01089     EQLOG( LOG_RSP ) << "got ack from " << ack->readerID << " for "
01090                      << ack->writerID << " sequence " << ack->sequence
01091                      << " current " << _sequence << std::endl;
01092 
01093     // find connection destination and if we have not received an ack from it,
01094     // we update the ack data.
01095     RSPConnectionPtr connection = _findConnection( ack->readerID );
01096     if( !connection )
01097     {
01098         EQUNREACHABLE;
01099         return false;
01100     }
01101 
01102     if( connection->_acked >= ack->sequence &&
01103         connection->_acked - ack->sequence <= _numBuffers )
01104     {
01105         // I have received a later ack previously from the reader
01106         EQLOG( LOG_RSP ) << "Late ack" << std::endl;
01107         return true;
01108     }
01109 
01110 #ifdef EQ_INSTRUMENT_RSP
01111     ++nAcksAccepted;
01112 #endif
01113     connection->_acked = ack->sequence;
01114     _timeouts = 0; // reset timeout counter
01115 
01116     // Check if we got all acks until here
01117     for( std::vector< RSPConnectionPtr >::iterator i = _children.begin(); 
01118           i != _children.end(); ++i )
01119     {
01120         RSPConnectionPtr child = *i;
01121         if( child->_id == _id )
01122             continue;
01123 
01124         const uint16_t distance = child->_acked - ack->sequence;
01125         if( distance > _numBuffers )
01126             return true;
01127     }
01128 
01129     _finishWriteQueue( ack->sequence );
01130     return true;
01131 }
01132 
01133 bool RSPConnection::_handleNack( const DatagramNack* nack )
01134 {
01135 #ifdef EQ_INSTRUMENT_RSP
01136     ++nNAcksRead;
01137 #endif
01138 
01139     EQLOG( LOG_RSP )
01140         << "handle " << nack->count << " nacks from " << nack->readerID
01141         << " for " << nack->writerID << std::endl;
01142 
01143     if( _id != nack->writerID )
01144     {
01145         EQLOG( LOG_RSP ) << "ignore nack, it's not for me" << std::endl;
01146         return true;
01147     }
01148     
01149     RSPConnectionPtr connection = _findConnection( nack->readerID );
01150     if( !connection )
01151     {
01152         EQUNREACHABLE;
01153         return false;
01154         // it's an unknown connection, TODO add this connection?
01155     }
01156 
01157     _timeouts = 0;
01158     _addRepeat( nack->nacks, nack->count );
01159     return true;
01160 }
01161 
01162 void RSPConnection::_addRepeat( const Nack* nacks, uint16_t num )
01163 {
01164     EQLOG( LOG_RSP ) << base::disableFlush << "Queue repeat requests ";
01165     size_t lost = 0;
01166 
01167     for( size_t i = 0; i < num; ++i )
01168     {
01169         const Nack& nack = nacks[ i ];
01170         EQASSERT( nack.start <= nack.end );
01171 
01172         EQLOG( LOG_RSP ) << nack.start << ".." << nack.end << " ";
01173 
01174         bool merged = false;
01175         for( RepeatQueue::iterator j = _repeatQueue.begin();
01176              j != _repeatQueue.end() && !merged; ++j )
01177         {
01178             Nack& old = *j;
01179             if( old.start <= nack.end && old.end >= nack.start )
01180             {
01181                 if( old.start > nack.start )
01182                 {
01183                     lost += old.start - nack.start;
01184                     old.start = nack.start;
01185                     merged = true;
01186                 }
01187                 if( old.end < nack.end )
01188                 {
01189                     lost += nack.end - old.end;
01190                     old.end = nack.end;
01191                     merged = true;
01192                 }
01193                 EQASSERT( lost < _numBuffers );
01194             }
01195         }
01196 
01197         if( !merged )
01198         {
01199             lost += uint16_t( nack.end - nack.start ) + 1;
01200             EQASSERT( lost <= _numBuffers );
01201             _repeatQueue.push_back( nack );
01202         }
01203     }
01204 
01205     if( _sendRate >
01206         ( _description->bandwidth >> 
01207           Global::getIAttribute( Global::IATTR_RSP_MIN_SENDRATE_SHIFT )))
01208     {
01209         const float delta = float( lost ) * .001f *
01210                      Global::getIAttribute( Global::IATTR_RSP_ERROR_DOWNSCALE );
01211         const float maxDelta = .01f *
01212             float( Global::getIAttribute( Global::IATTR_RSP_ERROR_MAXSCALE ));
01213         const float downScale = EQ_MIN( delta, maxDelta );
01214         _sendRate -= 1 + int64_t( _sendRate * downScale );
01215         EQLOG( LOG_RSP ) 
01216             << ", lost " << lost << " slowing down " << downScale * 100.f
01217             << "% to " << _sendRate << " KB/s" << std::endl <<base::enableFlush;
01218     }
01219     else
01220         EQLOG( LOG_RSP ) << std::endl << base::enableFlush;
01221 }
01222 
01223 bool RSPConnection::_handleAckRequest( const DatagramAckRequest* ackRequest )
01224 {
01225     const uint16_t writerID = ackRequest->writerID;
01226 #ifdef Darwin
01227     // There is occasionally a packet from ourselves, even though multicast loop
01228     // is not set?!
01229     if( writerID == _id )
01230         return true;
01231 #else
01232     EQASSERT( writerID != _id );
01233 #endif
01234     RSPConnectionPtr connection = _findConnection( writerID );
01235     if( !connection )
01236     {
01237         EQUNREACHABLE;
01238         return false;
01239     }
01240 
01241     const uint16_t reqID = ackRequest->sequence;
01242     const uint16_t gotID = connection->_sequence - 1;
01243     const uint16_t distance = reqID - gotID;
01244 
01245     EQLOG( LOG_RSP ) << "ack request "  << reqID << " from " << writerID
01246                      << " got " << gotID << " missing " << distance <<std::endl;
01247 
01248     if( (reqID == gotID) ||
01249         (gotID > reqID && gotID - reqID <= _numBuffers) ||
01250         (gotID < reqID && distance > _numBuffers) )
01251     {
01252         _sendAck( connection->_id, gotID );
01253         return true;
01254     }
01255     // else find all missing datagrams
01256 
01257     const uint16_t max = EQ_RSP_MAX_NACKS - 2;
01258     Nack nacks[ EQ_RSP_MAX_NACKS ];
01259     uint16_t i = 0;
01260 
01261     nacks[ i ].start = connection->_sequence;
01262     EQLOG( LOG_RSP ) << base::disableFlush << "nacks: " << nacks[i].start
01263                      << "..";
01264     
01265     std::deque<Buffer*>::const_iterator j = connection->_recvBuffers.begin();
01266     std::deque<Buffer*>::const_iterator first = j;
01267     for( ; j != connection->_recvBuffers.end() && i < max; ++j )
01268     {
01269         if( *j ) // got buffer
01270         {
01271             nacks[ i ].end = connection->_sequence + std::distance( first, j);
01272             EQLOG( LOG_RSP ) << nacks[i].end << ", ";
01273             if( nacks[ i ].end < nacks[ i ].start )
01274             {
01275                 EQASSERT( nacks[ i ].end < _numBuffers );
01276                 nacks[ i + 1 ].start = 0;
01277                 nacks[ i + 1 ].end = nacks[ i ].end;
01278                 nacks[ i ].end = std::numeric_limits< uint16_t >::max();
01279                 ++i;
01280             }
01281             ++i;
01282 
01283             // find next hole
01284             for( ++j; j != connection->_recvBuffers.end() && (*j); ++j )
01285                 /* nop */;
01286       
01287             if( j == connection->_recvBuffers.end( ))
01288                 break;
01289 
01290             nacks[i].start = connection->_sequence + std::distance(first, j) +1;
01291             EQLOG( LOG_RSP ) << nacks[i].start << "..";
01292         }
01293     }
01294 
01295     if( j != connection->_recvBuffers.end() || i == 0 )
01296     {
01297         nacks[ i ].end = reqID;
01298         EQLOG( LOG_RSP ) << nacks[i].end;
01299         ++i;
01300     }
01301     else if( uint16_t( reqID - nacks[i-1].end ) < _numBuffers )
01302     {
01303         nacks[i].start = nacks[i-1].end + 1;
01304         nacks[i].end = reqID;
01305         EQLOG( LOG_RSP ) << nacks[i].start << ".." << nacks[i].end;
01306         ++i;
01307     }
01308     if( nacks[ i -1 ].end < nacks[ i - 1 ].start )
01309     {
01310         EQASSERT( nacks[ i - 1 ].end < _numBuffers );
01311         nacks[ i ].start = 0;
01312         nacks[ i ].end = nacks[ i - 1 ].end;
01313         nacks[ i - 1 ].end = std::numeric_limits< uint16_t >::max();
01314         ++i;
01315     }
01316 
01317     EQLOG( LOG_RSP ) << std::endl << base::enableFlush << "send " << i
01318                      << " nacks to " << connection->_id << std::endl;
01319 
01320     EQASSERT( i > 0 );
01321     _sendNack( connection->_id, nacks, i );
01322     return true;
01323 }
01324 
01325 bool RSPConnection::_handleCountNode()
01326 {
01327     const DatagramCount* countConn = 
01328     reinterpret_cast< const DatagramCount* >( _recvBuffer.getData( ));
01329 
01330     EQLOG( LOG_RSP ) << "Got " << countConn->numConnections << " nodes from " 
01331                      << countConn->clientID << std::endl;
01332     // we know all connections
01333     if( _children.size() == countConn->numConnections ) 
01334         return true;
01335 
01336     _addNewConnection( countConn->clientID );
01337     return false;
01338 }
01339 
01340 void RSPConnection::_checkNewID( uint16_t id )
01341 {
01342     // look if the new ID exist in another connection
01343     if( id == _id || _findConnection( id ).isValid() )
01344     {
01345         EQLOG( LOG_RSP ) << "Deny " << id << std::endl;
01346         _sendSimpleDatagram( ID_DENY, _id );
01347     }
01348 }
01349 
01350 RSPConnection::RSPConnectionPtr RSPConnection::_findConnection( 
01351     const uint16_t id )
01352 {
01353     for( std::vector< RSPConnectionPtr >::const_iterator i = _children.begin();
01354          i != _children.end(); ++i )
01355     {
01356         if( (*i)->_id == id )
01357             return *i;
01358     }
01359     return 0;
01360 }
01361 
01362 
01363 bool RSPConnection::_addNewConnection( const uint16_t id )
01364 {
01365     if( _findConnection( id ).isValid() )
01366         return false;
01367 
01368     base::ScopedMutex<> mutexConn( _mutexConnection );
01369     for( std::vector< RSPConnectionPtr >::const_iterator i = _children.begin();
01370          i != _children.end(); ++i )
01371     {
01372         if( (*i)->_id == id )
01373             return false;
01374     }
01375     for( std::vector< RSPConnectionPtr >::const_iterator i = 
01376              _childrenConnecting.begin();
01377          i != _childrenConnecting.end(); ++i )
01378     {
01379         if( (*i)->_id == id )
01380             return false;
01381     }
01382 
01383     RSPConnectionPtr connection = new RSPConnection();
01384     connection->_id            = id;
01385     connection->_parent        = this;
01386     connection->_state         = STATE_CONNECTED;
01387     connection->_description   = _description;
01388     EQASSERT( connection->_appBuffers.isEmpty( ));
01389 
01390     // Make all buffers available for reading
01391     for( Buffers::iterator i = connection->_buffers.begin();
01392          i != connection->_buffers.end(); ++i )
01393     {
01394         Buffer* buffer = *i;
01395         EQCHECK( connection->_threadBuffers.push( buffer ));
01396     }
01397 
01398     _childrenConnecting.push_back( connection );
01399     _event->set();
01400     return true;
01401 }
01402 
01403 void RSPConnection::_removeConnection( const uint16_t id )
01404 {
01405     EQINFO << "remove connection " << id << std::endl;
01406     if( id == _id )
01407         return;
01408 
01409     for( std::vector< RSPConnectionPtr >::iterator i = _children.begin(); 
01410           i != _children.end(); ++i )
01411     {
01412         RSPConnectionPtr child = *i;
01413         if( child->_id == id )
01414         {
01415             base::ScopedMutex<> mutex( _mutexEvent ); 
01416             _children.erase( i );
01417                 
01418             child->_appBuffers.push( 0 );
01419             child->_event->set();
01420             break;
01421         }
01422     }
01423     
01424     _sendDatagramCountNode();
01425 }
01426 
01427 int64_t RSPConnection::write( const void* inData, const uint64_t bytes )
01428 {
01429     // to do : modify caller for use only rsp parent write
01430     if ( _parent.isValid() )
01431         return _parent->write( inData, bytes );
01432 
01433     EQASSERT( _state == STATE_LISTENING );
01434 
01435     if ( !_write )
01436         return -1;
01437 
01438     // compute number of datagrams
01439     uint64_t nDatagrams = bytes  / _payloadSize;    
01440     if ( nDatagrams * _payloadSize != bytes )
01441         ++nDatagrams;
01442 
01443     // queue each datagram (might block if buffers exhausted)
01444     const uint8_t* data = reinterpret_cast< const uint8_t* >( inData );
01445     const uint8_t* end = data + bytes;
01446     for( uint64_t i = 0; i < nDatagrams; ++i )
01447     {
01448         size_t packetSize = end - data;
01449         packetSize = EQ_MIN( packetSize, _payloadSize );
01450 
01451         if( _appBuffers.isEmpty( ))
01452             // trigger processing
01453             _postWakeup();
01454 
01455         Buffer* buffer = _appBuffers.pop();
01456         if( !buffer )
01457         {
01458             close();
01459             return -1;
01460         }
01461 
01462         // prepare packet header (sequence is done by thread)
01463         DatagramData* header =
01464             reinterpret_cast< DatagramData* >( buffer->getData( ));
01465         header->type = DATA;
01466         header->size = uint16_t( packetSize );
01467         header->writerID = _id;
01468         
01469         memcpy( header + 1, data, packetSize );
01470         data += packetSize;
01471 
01472         EQCHECK( _threadBuffers.push( buffer ));
01473     }
01474     _postWakeup();
01475     EQLOG( LOG_RSP ) << "queued " << nDatagrams << " datagrams, " 
01476                      << bytes << " bytes" << std::endl;
01477     return bytes;
01478 }
01479 
01480 void RSPConnection::_sendDatagramCountNode()
01481 {
01482     if ( !_findConnection( _id ) )
01483         return;
01484 
01485     EQLOG( LOG_RSP ) << _children.size() << " nodes" << std::endl;
01486     const DatagramCount count = { COUNTNODE, _id,
01487                                   uint16_t( _children.size( ))};
01488     _write->send( buffer( &count, sizeof( count )) );
01489 }
01490 
01491 void RSPConnection::_sendSimpleDatagram( DatagramType type, uint16_t id )
01492 {
01493     const DatagramNode simple = { type, id };
01494     _write->send( buffer( &simple, sizeof( simple )) );
01495 }
01496 
01497 void RSPConnection::_sendAck( const uint16_t writerID,
01498                               const uint16_t sequence )
01499 {
01500     EQASSERT( _id != writerID );
01501 #ifdef EQ_INSTRUMENT_RSP
01502     ++nAcksSend;
01503 #endif
01504 
01505     EQLOG( LOG_RSP ) << "send ack " << sequence << std::endl;
01506     const DatagramAck ack = { ACK, _id, writerID, sequence };
01507     _write->send( buffer( &ack, sizeof( ack )) );
01508 }
01509 
01510 void RSPConnection::_sendNack( const uint16_t writerID, const Nack* nacks,
01511                                const uint16_t count )
01512 {
01513     EQASSERT( count > 0 );
01514     EQASSERT( count <= EQ_RSP_MAX_NACKS );
01515 #ifdef EQ_INSTRUMENT_RSP
01516     ++nNAcksSend;
01517 #endif
01518     /* optimization: use the direct access to the reader. */
01519     if( writerID == _id )
01520     {
01521          _addRepeat( nacks, count );
01522          return;
01523     }
01524 
01525     const size_t size = sizeof( DatagramNack ) - 
01526                         (EQ_RSP_MAX_NACKS - count) * sizeof( Nack );
01527 
01528     // set the header
01529     DatagramNack packet;
01530     packet.set( _id, writerID, count );
01531     memcpy( packet.nacks, nacks, count * sizeof( Nack ));
01532     _write->send( buffer( &packet, size ));
01533 }
01534 
01535 void RSPConnection::_sendAckRequest()
01536 {
01537 #ifdef EQ_INSTRUMENT_RSP
01538     ++nAckRequests;
01539 #endif
01540     EQLOG( LOG_RSP ) << "send ack request for " << uint16_t( _sequence -1 )
01541                      << std::endl;
01542     const DatagramAckRequest ackRequest = { ACKREQ, _id, _sequence - 1 };
01543     _write->send( buffer( &ackRequest, sizeof( DatagramAckRequest )) );
01544 }
01545 
01546 std::ostream& operator << ( std::ostream& os,
01547                             const RSPConnection& connection )
01548 {
01549     os << base::disableFlush << base::disableHeader << "RSPConnection id "
01550        << connection.getID() << " send rate " << connection.getSendRate();
01551 
01552 #ifdef EQ_INSTRUMENT_RSP
01553     const int prec = os.precision();
01554     os.precision( 3 );
01555 
01556     const float time = instrumentClock.getTimef();
01557     const float mbps = 1048.576f * time;
01558     os << ": " << base::indent << std::endl
01559        << float( nBytesRead ) / mbps << " / " << float( nBytesWritten ) / mbps
01560        <<  " MB/s r/w using " << nDatagrams << " dgrams " << nRepeated
01561        << " repeats " << nMergedDatagrams
01562        << " merged"
01563        << std::endl;
01564 
01565     os.precision( prec );
01566     os << "sender: " << nAckRequests << " ack requests " << nAcksAccepted << "/"
01567        << nAcksRead << " acks " << nNAcksRead << " nacks, throttle "
01568        << writeWaitTime << " ms"
01569        << std::endl
01570        << "receiver: " << nAcksSend << " acks " << nNAcksSend << " nacks"
01571        << base::exdent;
01572 
01573     nReadData = 0;
01574     nBytesRead = 0;
01575     nBytesWritten = 0;
01576     nDatagrams = 0;
01577     nRepeated = 0;
01578     nMergedDatagrams = 0;
01579     nAckRequests = 0;
01580     nAcksSend = 0;
01581     nAcksRead = 0;
01582     nAcksAccepted = 0;
01583     nNAcksSend = 0;
01584     nNAcksRead = 0;
01585     writeWaitTime = 0.f;
01586 #endif
01587     os << std::endl << base::enableHeader << base::enableFlush;
01588 
01589     return os;
01590 }
01591 
01592 }
01593 }
01594 #endif //EQ_USE_BOOST
Generated on Wed Dec 1 2010 15:34:21 for EqualizerInternal 1.0-alpha by  1.7.2