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