Пример #1
0
bool LocalNode::_cmdAddListener( Command& command )
{
    NodeAddListenerPacket* packet =
        command.getModifiable< NodeAddListenerPacket >();
    ConnectionDescriptionPtr description =
        new ConnectionDescription( packet->connectionData );
    command.getNode()->addConnectionDescription( description );

    if( command.getNode() != this )
        return true;

    EQASSERT( packet->connection );
    ConnectionPtr connection = packet->connection;
    packet->connection = 0;
    connection->unref( CO_REFERENCED_PARAM );

    _connectionNodes[ connection ] = this;
    _incoming.addConnection( connection );
    if( connection->getDescription()->type >= CONNECTIONTYPE_MULTICAST )
    {
        MCData data;
        data.connection = connection;
        data.node = this;

        base::ScopedMutex<> mutex( _outMulticast );
        _multicasts.push_back( data );
    }

    connection->acceptNB();
    return true;
}
Пример #2
0
ConnectionPtr Connection::create( ConnectionDescriptionPtr description )
{
    ConnectionPtr connection;
    switch( description->type )
    {
        case CONNECTIONTYPE_TCPIP:
        case CONNECTIONTYPE_SDP:
            connection = new SocketConnection( description->type );
            break;

        case CONNECTIONTYPE_PIPE:
            connection = new PipeConnection;
            break;
            
#ifdef _WIN32
        case CONNECTIONTYPE_NAMEDPIPE:
            connection = new NamedPipeConnection;
            break;
#endif

#ifdef EQ_INFINIBAND
        case CONNECTIONTYPE_IB:
            connection = new IBConnection;
            break;
#endif
#ifdef EQ_PGM
        case CONNECTIONTYPE_PGM:
            connection = new PGMConnection;
            break;

#endif
        case CONNECTIONTYPE_RSP:
            connection = new RSPConnection;
            break;

#ifdef CO_USE_OFED
        case CONNECTIONTYPE_RDMA:
            connection = new RDMAConnection;
            break;
#endif
#ifdef CO_USE_UDT
        case CONNECTIONTYPE_UDT:
            connection = new UDTConnection;
            break;
#endif

        default:
            LBWARN << "Connection type " << description->type
                   << " not supported" << std::endl;
            return 0;
    }

    if( description->bandwidth == 0 )
        description->bandwidth = connection->getDescription()->bandwidth;

    connection->setDescription( description );
    return connection;
}
Пример #3
0
void LocalNode::addListener( ConnectionPtr connection )
{
    EQASSERT( isListening( ));
    EQASSERT( connection->isListening( ));

    connection->ref( CO_REFERENCED_PARAM );
    NodeAddListenerPacket packet( connection );
    Nodes nodes;
    getNodes( nodes );

    for( Nodes::iterator i = nodes.begin(); i != nodes.end(); ++i )
    {
        (*i)->send( packet, connection->getDescription()->toString( ));
    }
}
Пример #4
0
uint32_t LocalNode::removeListenerNB( ConnectionPtr connection )
{
    EQASSERT( isListening( ));
    EQASSERT( connection->isListening( ));

    connection->ref( CO_REFERENCED_PARAM );
    NodeRemoveListenerPacket packet( connection, registerRequest( ));
    Nodes nodes;
    getNodes( nodes );

    for( Nodes::iterator i = nodes.begin(); i != nodes.end(); ++i )
    {
        (*i)->send( packet, connection->getDescription()->toString( ));
    }
    return packet.requestID;
}
Пример #5
0
void Node::_removeMulticast( ConnectionPtr connection )
{
    LBASSERT( connection->getDescription()->type >= CONNECTIONTYPE_MULTICAST );

    lunchbox::ScopedMutex<> mutex( _impl->outMulticast );
    if( _impl->outMulticast == connection )
        _impl->outMulticast.data = 0;
    else
    {
        for( MCDatas::iterator j = _impl->multicasts.begin();
             j != _impl->multicasts.end(); ++j )
        {
            if( (*j).connection != connection )
                continue;

            _impl->multicasts.erase( j );
            return;
        }
    }
}
Пример #6
0
bool LocalNode::_cmdRemoveListener( Command& command )
{
    NodeRemoveListenerPacket* packet = 
        command.getModifiable< NodeRemoveListenerPacket >();

    ConnectionDescriptionPtr description =
        new ConnectionDescription( packet->connectionData );
    EQCHECK( command.getNode()->removeConnectionDescription( description ));

    if( command.getNode() != this )
        return true;

    EQASSERT( packet->connection );
    ConnectionPtr connection = packet->connection;
    packet->connection = 0;
    connection->unref( CO_REFERENCED_PARAM );

    if( connection->getDescription()->type >= CONNECTIONTYPE_MULTICAST )
    {
        base::ScopedMutex<> mutex( _outMulticast );
        for( MCDatas::iterator i = _multicasts.begin();
             i != _multicasts.end(); ++i )
        {
            if( i->connection == connection )
            {
                _multicasts.erase( i );
                break;
            }
        }
    }

    _incoming.removeConnection( connection );
    EQASSERT( _connectionNodes.find( connection ) != _connectionNodes.end( ));
    _connectionNodes.erase( connection );
    serveRequest( packet->requestID );
    return true;
}
Пример #7
0
bool LocalNode::_handleData()
{
    ConnectionPtr connection = _incoming.getConnection();
    EQASSERT( connection.isValid( ));

    NodePtr node;
    ConnectionNodeHash::const_iterator i = _connectionNodes.find( connection );
    if( i != _connectionNodes.end( ))
        node = i->second;
    EQASSERTINFO( !node || // unconnected node
                  *(node->_outgoing) == *connection || // correct UC connection
                  connection->getDescription()->type>=CONNECTIONTYPE_MULTICAST,
                  base::className( node ));

    EQVERB << "Handle data from " << node << std::endl;

    void* sizePtr( 0 );
    uint64_t bytes( 0 );
    const bool gotSize = connection->recvSync( &sizePtr, &bytes, false );

    if( !gotSize ) // Some systems signal data on dead connections.
    {
        connection->recvNB( sizePtr, sizeof( uint64_t ));
        return false;
    }

    EQASSERT( sizePtr );
    const uint64_t size = *reinterpret_cast< uint64_t* >( sizePtr );
    if( bytes == 0 ) // fluke signal
    {
        EQWARN << "Erronous network event on " << connection->getDescription()
               << std::endl;
        _incoming.setDirty();
        return false;
    }

    EQASSERT( size );
    EQASSERTINFO( bytes == sizeof( uint64_t ), bytes );
    EQASSERT( size > sizeof( size ));

    if( node )
        node->_lastReceive = getTime64();

    Command& command = _commandCache.alloc( node, this, size );
    uint8_t* ptr = reinterpret_cast< uint8_t* >(
        command.getModifiable< Packet >()) + sizeof( uint64_t );

    connection->recvNB( ptr, size - sizeof( uint64_t ));
    const bool gotData = connection->recvSync( 0, 0 );

    EQASSERT( gotData );
    EQASSERT( command.isValid( ));
    EQASSERT( command.isFree( ));

    // start next receive
    connection->recvNB( sizePtr, sizeof( uint64_t ));

    if( !gotData )
    {
        EQERROR << "Incomplete packet read: " << command << std::endl;
        return false;
    }

    // This is one of the initial packets during the connection handshake, at
    // this point the remote node is not yet available.
    EQASSERTINFO( node.isValid() ||
                 ( command->type == PACKETTYPE_CO_NODE &&
                  ( command->command == CMD_NODE_CONNECT  || 
                    command->command == CMD_NODE_CONNECT_REPLY ||
                    command->command == CMD_NODE_ID )),
                  command << " connection " << connection );

    _dispatchCommand( command );
    return true;
}
Пример #8
0
void LocalNode::_handleDisconnect()
{
    while( _handleData( )) ; // read remaining data off connection

    ConnectionPtr connection = _incoming.getConnection();
    ConnectionNodeHash::iterator i = _connectionNodes.find( connection );

    if( i != _connectionNodes.end( ))
    {
        NodePtr node = i->second;
        Command& command = _commandCache.alloc( node, this,
                                                sizeof( NodeRemoveNodePacket ));
         NodeRemoveNodePacket* packet =
             command.getModifiable< NodeRemoveNodePacket >();
        *packet = NodeRemoveNodePacket();
        packet->node = node.get();
        _dispatchCommand( command );

        if( node->_outgoing == connection )
        {
            _objectStore->removeInstanceData( node->_id );
            _connectionNodes.erase( i );
            node->_state    = STATE_CLOSED;
            node->_outgoing = 0;

            if( node->_outMulticast.data.isValid( ) )
                _removeConnection( node->_outMulticast.data );

            node->_outMulticast = 0;
            node->_multicasts.clear();

            EQINFO << node << " disconnected from " << *this << std::endl;
            base::ScopedMutex< base::SpinLock > mutex( _nodes );
            _nodes->erase( node->_id );
        }
        else
        {
            EQASSERT( connection->getDescription()->type >= 
                      CONNECTIONTYPE_MULTICAST );

            base::ScopedMutex<> mutex( _outMulticast );
            if( node->_outMulticast == connection )
                node->_outMulticast = 0;
            else
            {
                for( MCDatas::iterator j = node->_multicasts.begin();
                     j != node->_multicasts.end(); ++j )
                {
                    if( (*j).connection != connection )
                        continue;

                    node->_multicasts.erase( j );
                    break;
                }
            }
        }
    }

    _removeConnection( connection );
    EQINFO << "connection used " << connection->getRefCount() << std::endl;
}
Пример #9
0
bool LocalNode::_cmdID( Command& command )
{
    EQASSERT( _inReceiverThread( ));

    const NodeIDPacket* packet = command.get< NodeIDPacket >();
    NodeID nodeID = packet->id;

    if( command.getNode().isValid( ))
    {
        EQASSERT( nodeID == command.getNode()->getNodeID( ));
        EQASSERT( command.getNode()->_outMulticast->isValid( ));
        return true;
    }

    EQINFO << "handle ID " << packet << " node " << nodeID << std::endl;

    ConnectionPtr connection = _incoming.getConnection();
    EQASSERT( connection->getDescription()->type >= CONNECTIONTYPE_MULTICAST );
    EQASSERT( _connectionNodes.find( connection ) == _connectionNodes.end( ));

    NodePtr node;
    if( nodeID == _id ) // 'self' multicast connection
        node = this;
    else
    {
        // No locking needed, only recv thread writes
        NodeHash::const_iterator i = _nodes->find( nodeID );

        if( i == _nodes->end( ))
        {
            // unknown node: create and add unconnected node
            node = createNode( packet->nodeType );
            std::string data = packet->data;

            if( !node->deserialize( data ))
                EQWARN << "Error during node initialization" << std::endl;
            EQASSERTINFO( data.empty(), data );

            {
                base::ScopedMutex< base::SpinLock > mutex( _nodes );
                _nodes.data[ nodeID ] = node;
            }
            EQVERB << "Added node " << nodeID << " with multicast "
                   << connection << std::endl;
        }
        else
            node = i->second;
    }
    EQASSERT( node.isValid( ));
    EQASSERTINFO( node->_id == nodeID, node->_id << "!=" << nodeID );

    base::ScopedMutex<> mutex( _outMulticast );
    MCDatas::iterator i = node->_multicasts.begin();
    for( ; i != node->_multicasts.end(); ++i )
    {
        if( (*i).connection == connection )
            break;
    }

    if( node->_outMulticast->isValid( ))
    {
        if( node->_outMulticast.data == connection ) // connection already used
        {
            // nop
            EQASSERT( i == node->_multicasts.end( ));
        }
        else // another connection is used as multicast connection, save this
        {
            if( i == node->_multicasts.end( ))
            {
                EQASSERT( _state == STATE_LISTENING );
                MCData data;
                data.connection = connection;
                data.node = this;
                node->_multicasts.push_back( data );
            }
            // else nop, already know connection
        }
    }
    else
    {
        node->_outMulticast.data = connection;
        if( i != node->_multicasts.end( ))
            node->_multicasts.erase( i );
    }

    _connectionNodes[ connection ] = node;
    EQINFO << "Added multicast connection " << connection << " from " << nodeID
           << " to " << _id << std::endl;
    return true;
}