void LocalNode::_connectMulticast( NodePtr node ) { EQASSERT( _inReceiverThread( )); base::ScopedMutex<> mutex( _outMulticast ); if( node->_outMulticast.data.isValid( )) // multicast already connected by previous _cmdID return; // Search if the connected node is in the same multicast group as we are ConnectionDescriptions descriptions = getConnectionDescriptions(); for( ConnectionDescriptions::const_iterator i = descriptions.begin(); i != descriptions.end(); ++i ) { ConnectionDescriptionPtr description = *i; if( description->type < CONNECTIONTYPE_MULTICAST ) continue; const ConnectionDescriptions& fromDescs = node->getConnectionDescriptions(); for( ConnectionDescriptions::const_iterator j = fromDescs.begin(); j != fromDescs.end(); ++j ) { ConnectionDescriptionPtr fromDescription = *j; if( !description->isSameMulticastGroup( fromDescription )) continue; EQASSERT( !node->_outMulticast.data ); EQASSERT( node->_multicasts.empty( )); if( _outMulticast->isValid() && _outMulticast.data->getDescription() == description ) { node->_outMulticast.data = _outMulticast.data; EQINFO << "Using " << description << " as multicast group for " << node->getNodeID() << std::endl; } // find unused multicast connection to node else for( MCDatas::const_iterator k = _multicasts.begin(); k != _multicasts.end(); ++k ) { const MCData& data = *k; ConnectionDescriptionPtr dataDesc = data.connection->getDescription(); if( !description->isSameMulticastGroup( dataDesc )) continue; node->_multicasts.push_back( data ); EQINFO << "Adding " << dataDesc << " as multicast group for " << node->getNodeID() << std::endl; } } } }
std::string serialize( const ConnectionDescriptions& descriptions ) { std::ostringstream data; data << descriptions.size() << CO_SEPARATOR; for( ConnectionDescriptions::const_iterator i = descriptions.begin(); i != descriptions.end(); ++i ) { ConnectionDescriptionPtr desc = *i; desc->serialize( data ); } return data.str(); }
bool LocalNode::listen() { EQVERB << "Listener data: " << serialize() << std::endl; if( !isClosed() || !_connectSelf( )) return false; ConnectionDescriptions descriptions = getConnectionDescriptions(); for( ConnectionDescriptions::const_iterator i = descriptions.begin(); i != descriptions.end(); ++i ) { ConnectionDescriptionPtr description = *i; ConnectionPtr connection = Connection::create( description ); if( !connection ) continue; if( !connection->listen( )) { EQWARN << "Can't create listener connection: " << description << std::endl; return false; } _connectionNodes[ connection ] = this; _incoming.addConnection( connection ); if( description->type >= CONNECTIONTYPE_MULTICAST ) { MCData data; data.connection = connection; data.node = this; _multicasts.push_back( data ); } connection->acceptNB(); EQVERB << "Added node " << _id << " using " << connection << std::endl; } _state = STATE_LISTENING; EQVERB << base::className( this ) << " start command and receiver thread " << std::endl; _receiverThread->start(); EQINFO << *this << std::endl; return true; }
bool deserialize( std::string& data, ConnectionDescriptions& descriptions ) { if( !descriptions.empty( )) LBWARN << "Connection descriptions already hold data before deserialize" << std::endl; // num connection descriptions size_t nextPos = data.find( CO_SEPARATOR ); if( nextPos == std::string::npos || nextPos == 0 ) { LBERROR << "Could not parse number of connection descriptions" << std::endl; return false; } const std::string sizeStr = data.substr( 0, nextPos ); if( !isdigit( sizeStr[0] )) { LBERROR << "Could not parse number of connection descriptions" << std::endl; return false; } const size_t nDesc = atoi( sizeStr.c_str( )); data = data.substr( nextPos + 1 ); // connection descriptions for( size_t i = 0; i < nDesc; ++i ) { ConnectionDescriptionPtr desc = new ConnectionDescription; if( !desc->fromString( data )) { LBERROR << "Error during connection description parsing" << std::endl; return false; } descriptions.push_back( desc ); } return true; }