예제 #1
0
bool ObjectCM::_initSlave( const MasterCMCommand& command,
                           const uint128_t& replyVersion, bool replyUseCache )
{
#if 0
    LBLOG( LOG_OBJECTS ) << "Object id " << _object->_id << " v" << _version
                         << ", instantiate on " << node->getNodeID()
                         << std::endl;
#endif

#ifndef NDEBUG
    const uint128_t& version = command.getRequestedVersion();
    if( version != VERSION_OLDEST && version < replyVersion )
        LBINFO << "Mapping version " << replyVersion << " instead of "
               << version << std::endl;
#endif

    if( replyUseCache &&
        command.getMinCachedVersion() <= replyVersion &&
        command.getMaxCachedVersion() >= replyVersion )
    {
#ifdef CO_INSTRUMENT_MULTICAST
        ++_hit;
#endif
        _sendMapSuccess( command, false );
        _sendMapReply( command, replyVersion, true, replyUseCache, false );
        return true;
    }

    lunchbox::ScopedFastWrite mutex( _lock );
    if( !_object )
    {
        LBWARN << "Map to detached object requested" << std::endl;
        return false;
    }

#ifdef CO_INSTRUMENT_MULTICAST
    ++_miss;
#endif
    replyUseCache = false;

    _sendMapSuccess( command, true );

    // send instance data
    ObjectInstanceDataOStream os( this );

    os.enableMap( replyVersion, command.getNode(), command.getInstanceID( ));
    _object->getInstanceData( os );
    os.disable();
    if( !os.hasSentData( ))
        // no data, send empty command to set version
        _sendEmptyVersion( command, replyVersion, true /* mc */ );

    _sendMapReply( command, replyVersion, true, replyUseCache, true );
    return true;
}
예제 #2
0
파일: objectCM.cpp 프로젝트: rttag/Collage
void ObjectCM::_addSlave( MasterCMCommand command, const uint128_t& version )
{
    LBASSERT( version != VERSION_NONE );
    LBASSERT( command.getType() == COMMANDTYPE_NODE );
    LBASSERT( command.getCommand() == CMD_NODE_MAP_OBJECT );

    // process request
    if( command.getRequestedVersion() == VERSION_NONE )
    {
        // no data to send, send empty version
        _sendMapSuccess( command, false /* mc */ );
        _sendEmptyVersion( command, VERSION_NONE, false /* mc */ );
        _sendMapReply( command, VERSION_NONE, true, false, false /* mc */ );

        return;
    }

    const bool replyUseCache = command.useCache() &&
                   (command.getMasterInstanceID() == _object->getInstanceID( ));
    _initSlave( command, version, replyUseCache );
}
예제 #3
0
void FullMasterCM::addSlave( Command& command, NodeMapObjectReplyPacket& reply )
{
    EQ_TS_THREAD( _cmdThread );
    EQASSERT( command->type == PACKETTYPE_CO_NODE );
    EQASSERT( command->command == CMD_NODE_MAP_OBJECT );

    NodePtr node = command.getNode();
    const NodeMapObjectPacket* packet = command.get< NodeMapObjectPacket >();
    const uint128_t requested  = packet->requestedVersion;
    const uint32_t instanceID = packet->instanceID;

    Mutex mutex( _slaves );
    EQASSERT( _version != VERSION_NONE );
    _checkConsistency();

    // add to subscribers
    ++_slavesCount[ node->getNodeID() ];
    _slaves->push_back( node );
    stde::usort( *_slaves );

    if( requested == VERSION_NONE ) // no data to send
    {
        _sendEmptyVersion( node, instanceID, _version );
        reply.version = _version;
        return;
    }

    const uint128_t oldest = _instanceDatas.front()->os.getVersion();
    uint128_t start = (requested == VERSION_OLDEST || requested < oldest ) ?
                          oldest : requested;
    uint128_t end = _version;
    const bool useCache = packet->masterInstanceID == _object->getInstanceID();

#ifndef NDEBUG
    if( requested != VERSION_OLDEST && requested < start )
        EQINFO << "Mapping version " << start
               << " instead of requested version " << requested << std::endl;
#endif

    reply.version = start;
    reply.useCache = packet->useCache && useCache;

    if( reply.useCache )
    {
        if( packet->minCachedVersion <= start && 
            packet->maxCachedVersion >= start )
        {
#ifdef EQ_INSTRUMENT_MULTICAST
            _hit += packet->maxCachedVersion + 1 - start;
#endif
            start = packet->maxCachedVersion + 1;
        }
        else if( packet->maxCachedVersion == end )
        {
            end = EQ_MAX( start, packet->minCachedVersion - 1 );
#ifdef EQ_INSTRUMENT_MULTICAST
            _hit += _version - end;
#endif
        }
        // TODO else cached block in the middle, send head and tail elements
    }

#if 0
    EQLOG( LOG_OBJECTS )
        << *_object << ", instantiate on " << node->getNodeID() << " with v"
        << ((requested == VERSION_OLDEST) ? oldest : requested) << " ("
        << requested << ") sending " << start << ".." << end << " have "
        << _version - _nVersions << ".." << _version << " "
        << _instanceDatas.size() << std::endl;
#endif
    EQASSERT( start >= oldest );

    // send all instance datas from start..end
    InstanceDataDeque::iterator i = _instanceDatas.begin();
    while( i != _instanceDatas.end() && (*i)->os.getVersion() < start )
        ++i;

    for( ; i != _instanceDatas.end() && (*i)->os.getVersion() <= end; ++i )
    {
        InstanceData* data = *i;
        EQASSERT( data );
        data->os.sendMapData( node, instanceID );

#ifdef EQ_INSTRUMENT_MULTICAST
        ++_miss;
#endif
    }

#ifdef EQ_INSTRUMENT_MULTICAST
    if( _miss % 100 == 0 )
        EQINFO << "Cached " << _hit << "/" << _hit + _miss
               << " instance data transmissions" << std::endl;
#endif
}
예제 #4
0
void UnbufferedMasterCM::addSlave( Command& command, 
                                   NodeMapObjectReplyPacket& reply )
{
    EQ_TS_THREAD( _cmdThread );
    EQASSERT( command->type == PACKETTYPE_CO_NODE );
    EQASSERT( command->command == CMD_NODE_MAP_OBJECT );

    NodePtr node = command.getNode();
    NodeMapObjectPacket* packet =
        command.get<NodeMapObjectPacket>();
    const uint128_t version = packet->requestedVersion;
    const uint32_t instanceID = packet->instanceID;

    // add to subscribers
    ++_slavesCount[ node->getNodeID() ];
    _slaves.push_back( node );
    stde::usort( _slaves );

#if 0
    EQLOG( LOG_OBJECTS ) << "Object id " << _object->_id << " v" << _version
                         << ", instantiate on " << node->getNodeID()
                         << std::endl;
#endif
    reply.version = _version;

    if( version == VERSION_NONE )
    {
        // no data, send empty packet to set version
        _sendEmptyVersion( node, instanceID );
        return;
    }


#ifndef NDEBUG
    if( version != VERSION_OLDEST && version < _version )
        EQINFO << "Mapping version " << _version
               << " instead of requested version" << version << std::endl;
#endif

    const bool useCache = packet->masterInstanceID == _object->getInstanceID();

    if( useCache && 
        packet->minCachedVersion <= _version && 
        packet->maxCachedVersion >= _version )
    {
#ifdef EQ_INSTRUMENT_MULTICAST
        ++_hit;
#endif
        reply.useCache = true;
        return;
    }

#ifdef EQ_INSTRUMENT_MULTICAST
    ++_miss;
#endif

    // send instance data
    ObjectInstanceDataOStream os( this );

    os.enableMap( _version, node, instanceID );
    _object->getInstanceData( os );
    os.disable();
    if( os.hasSentData( ))
        return;

    // no data, send empty packet to set version
    _sendEmptyVersion( node, instanceID );
}