void ObjectCM::_sendMapSuccess( const MasterCMCommand& command, const bool multicast ) { command.getNode()->send( CMD_NODE_MAP_OBJECT_SUCCESS, multicast ) << command.getNode()->getNodeID() << command.getObjectID() << command.getRequestID() << command.getInstanceID() << _object->getChangeType() << _object->getInstanceID(); }
void ObjectCM::_sendMapReply( const MasterCMCommand& command, const uint128_t& version, const bool result, const bool useCache, const bool multicast ) { command.getNode()->send( CMD_NODE_MAP_OBJECT_REPLY, multicast ) << command.getNode()->getNodeID() << command.getObjectID() << version << command.getRequestID() << result << command.useCache() << useCache; }
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::_sendEmptyVersion( const MasterCMCommand& command, const uint128_t& version, const bool multicast ) { NodePtr node = command.getNode(); ConnectionPtr connection = node->getConnection( multicast ); ObjectDataOCommand( Connections( 1, connection ), CMD_OBJECT_INSTANCE, COMMANDTYPE_OBJECT, _object->getID(), command.getInstanceID(), version, 0, 0, true, 0 ) << NodeID() << _object->getInstanceID(); }
bool ObjectCM::sendSync( const MasterCMCommand& command ) { lunchbox::ScopedFastWrite mutex( _lock ); if( !_object ) { LBWARN << "Sync from detached object requested" << std::endl; return false; } const uint128_t& maxCachedVersion = command.getMaxCachedVersion(); const bool useCache = command.useCache() && command.getMasterInstanceID() == _object->getInstanceID() && maxCachedVersion == getVersion(); if( !useCache ) { ObjectInstanceDataOStream os( this ); os.enableSync( getVersion(), command ); _object->getInstanceData( os ); os.disable(); } NodePtr node = command.getNode(); node->send( CMD_NODE_SYNC_OBJECT_REPLY, useCache /*preferMulticast*/ ) << node->getNodeID() << command.getObjectID() << command.getRequestID() << true << command.useCache() << useCache; 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 ); }
bool VersionedMasterCM::addSlave( const MasterCMCommand& command ) { LB_TS_THREAD( _cmdThread ); Mutex mutex( _slaves ); if( !ObjectCM::_addSlave( command, _version )) return false; SlaveData data; data.node = command.getNode(); data.instanceID = command.getInstanceID(); data.maxVersion = command.getMaxVersion(); if( data.maxVersion == 0 ) data.maxVersion = std::numeric_limits< uint64_t >::max(); else if( data.maxVersion < std::numeric_limits< uint64_t >::max( )) data.maxVersion += _version.low(); _slaveData.push_back( data ); _updateMaxVersion(); _slaves->push_back( data.node ); lunchbox::usort( *_slaves ); return true; }
bool FullMasterCM::sendSync( const MasterCMCommand& command ) { //const uint128_t& version = command.getRequestedVersion(); const uint128_t& maxCachedVersion = command.getMaxCachedVersion(); const bool useCache = command.useCache() && command.getMasterInstanceID() == _object->getInstanceID() && maxCachedVersion == _version; if( !useCache ) { Mutex mutex( _slaves ); InstanceData* instanceData = _instanceDatas.back(); instanceData->os.sync( command ); } NodePtr node = command.getNode(); node->send( CMD_NODE_SYNC_OBJECT_REPLY, useCache /*preferMulticast*/ ) << node->getNodeID() << command.getObjectID() << command.getRequestID() << true << command.useCache() << useCache; return true; }
bool FullMasterCM::_initSlave( const MasterCMCommand& command, const uint128_t& /*replyVersion*/, bool replyUseCache ) { _checkConsistency(); const uint128_t& version = command.getRequestedVersion(); const uint128_t oldest = _instanceDatas.front()->os.getVersion(); uint128_t start = (version == VERSION_OLDEST || version < oldest ) ? oldest : version; uint128_t end = _version; #ifndef NDEBUG if( version != VERSION_OLDEST && version < start ) LBINFO << "Mapping version " << start << " instead of requested " << version << " for " << lunchbox::className( _object ) << " " << ObjectVersion( _object->getID(), _version ) << " of " << _instanceDatas.size() << "/" << _nVersions << std::endl; #endif const uint128_t& minCachedVersion = command.getMinCachedVersion(); const uint128_t& maxCachedVersion = command.getMaxCachedVersion(); const uint128_t replyVersion = start; if( replyUseCache ) { if( minCachedVersion <= start && maxCachedVersion >= start ) { #ifdef CO_INSTRUMENT_MULTICAST _hit += maxCachedVersion + 1 - start; #endif start = maxCachedVersion + 1; } else if( maxCachedVersion == end ) { end = LB_MAX( start, minCachedVersion - 1 ); #ifdef CO_INSTRUMENT_MULTICAST _hit += _version - end; #endif } // TODO else cached block in the middle, send head and tail elements } #if 0 LBLOG( 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 LBASSERT( start >= oldest ); bool dataSent = false; // 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 ) { if( !dataSent ) { _sendMapSuccess( command, true ); dataSent = true; } InstanceData* data = *i; LBASSERT( data ); data->os.sendMapData( command.getRemoteNode(), command.getInstanceID( )); #ifdef CO_INSTRUMENT_MULTICAST ++_miss; #endif } if( !dataSent ) { _sendMapSuccess( command, false ); _sendMapReply( command, replyVersion, true, replyUseCache, false ); } else _sendMapReply( command, replyVersion, true, replyUseCache, true ); #ifdef CO_INSTRUMENT_MULTICAST if( _miss % 100 == 0 ) LBINFO << "Cached " << _hit << "/" << _hit + _miss << " instance data transmissions" << std::endl; #endif return true; }