//------------------------------------------------------------------------------------- void Channel::clearState( bool warnOnDiscard /*=false*/ ) { // 清空未处理的接受包缓存 if (bufferedReceives_.size() > 0) { BufferedReceives::iterator iter = bufferedReceives_.begin(); int hasDiscard = 0; for(; iter != bufferedReceives_.end(); iter++) { Packet* pPacket = (*iter); if(pPacket->opsize() > 0) hasDiscard++; if(pPacket->isTCPPacket()) TCPPacket::ObjPool().reclaimObject(static_cast<TCPPacket*>(pPacket)); else UDPPacket::ObjPool().reclaimObject(static_cast<UDPPacket*>(pPacket)); } if (hasDiscard > 0 && warnOnDiscard) { WARNING_MSG( "Channel::clearState( %s ): " "Discarding %u buffered packet(s)\n", this->c_str(), hasDiscard ); } bufferedReceives_.clear(); } lastReceivedTime_ = timestamp(); roundTripTime_ = this->isInternal() ? stampsPerSecond() / 10 : stampsPerSecond(); isCondemn_ = false; shouldDropNextSend_ = false; numPacketsSent_ = 0; numPacketsReceived_ = 0; numBytesSent_ = 0; numBytesReceived_ = 0; fragmentDatasFlag_ = FRAGMENT_DATA_UNKNOW; pFragmentDatasWpos_ = 0; pFragmentDatasRemain_ = 0; currMsgID_ = 0; currMsgLen_ = 0; proxyID_ = 0; isHandshake_ = false; channelType_ = CHANNEL_NORMAL; SAFE_RELEASE_ARRAY(pFragmentDatas_); MemoryStream::ObjPool().reclaimObject(pFragmentStream_); pFragmentStream_ = NULL; inactivityTimerHandle_.cancel(); this->endpoint(NULL); }
void Channel::startInactivityDetection(float period, float checkPeriod) { stopInactivityDetection(); // 如果周期为负数则不检查 if(period > 0.001f) { checkPeriod = max(1.f, checkPeriod); mInactivityExceptionPeriod = uint64(period * stampsPerSecond() ) - uint64( 0.05f * stampsPerSecond()); mLastReceivedTime = timestamp(); mInactivityTimerHandle = mpNetworkManager->dispatcher().addTimer(int( checkPeriod * 1000000 ), this, (void *)Timeout_InactivityCheck); } }
//------------------------------------------------------------------------------------- bool Cellapp::initializeWatcher() { ProfileVal::setWarningPeriod(stampsPerSecond() / g_kbeSrvConfig.gameUpdateHertz()); WATCH_OBJECT("stats/runningTime", &runningTime); return EntityApp<Entity>::initializeWatcher(); }
//------------------------------------------------------------------------------------- void DBTransaction::commit() { KBE_ASSERT(!committed_); uint64 startTime = timestamp(); try { pdbi_->query(SQL_COMMIT, false); } catch (DBException & e) { bool ret = static_cast<DBInterfaceMysql*>(pdbi_)->processException(e); KBE_ASSERT(ret); } uint64 duration = timestamp() - startTime; if(duration > stampsPerSecond() * 0.2f) { WARNING_MSG(fmt::format("DBTransaction::commit(): took {:.2f} seconds\n", (double(duration)/stampsPerSecondD()))); } committed_ = true; }
/** * This is called every frame. We use this as an oportunity to RedrawWindow() * the control if the user has moved. */ /*afx_msg*/ void ChunkWatchControl::OnUpdateControl() { // Don't update to frequently. if (lastUpdateTime_ != 0) { uint64 now = timestamp(); if ((now - lastUpdateTime_)/(double)stampsPerSecond() < UPDATE_DELTA) { return; } } lastUpdateTime_ = timestamp(); Matrix view = WorldEditorCamera::instance().currentCamera().view(); view.invert(); Chunk *workingChunk = WorldManager::instance().workingChunk(); if ( !similar(view, drawPos_, MATRICES_COMP_EPSILON) || workingChunk != lastWorkingChunk_ ) { RedrawWindow(); } }
//------------------------------------------------------------------------------------- ProfileGroup::ProfileGroup(std::string name): name_(name) { stampsPerSecond(); ProfileVal * pRunningTime = new ProfileVal("RunningTime", this); pRunningTime->start(); }
//------------------------------------------------------------------------------------- bool Bots::initializeBegin() { gameTimer_ = this->getMainDispatcher().addTimer(1000000 / g_kbeSrvConfig.gameUpdateHertz(), this, reinterpret_cast<void *>(TIMEOUT_GAME_TICK)); ProfileVal::setWarningPeriod(stampsPerSecond() / g_kbeSrvConfig.gameUpdateHertz()); return true; }
//------------------------------------------------------------------------------------- void EventDispatcher::processStats() { if (timestamp() - lastStatisticsGathered_ >= stampsPerSecond()) { oldSpareTime_ = totSpareTime_; totSpareTime_ = accSpareTime_ + pPoller_->spareTime(); lastStatisticsGathered_ = timestamp(); } }
//------------------------------------------------------------------------------------- void Logger::handleTick() { if(timestamp() - g_lastCalcsecsNumlogsTime > uint64( stampsPerSecond() )) { g_lastCalcsecsNumlogsTime = timestamp(); g_secsNumlogs = 0; } threadPool_.onMainThreadTick(); networkInterface().processChannels(&LoggerInterface::messageHandlers); }
/** 向管理器添加一个回调 */ CALLBACK_ID save(T callback, uint64 timeout = 0/*secs*/) { if(timeout == 0) timeout = uint64(ServerConfig::getSingleton().callback_timeout_); CALLBACK_ID cbID = idAlloc_.alloc(); cbMap_.insert(typename CALLBACKS::value_type(cbID, std::pair< T, uint64 >(callback, timestamp() + (timeout * stampsPerSecond())))); tick(); return cbID; }
//------------------------------------------------------------------------------------- bool DBTaskBase::process() { uint64 startTime = timestamp(); bool ret = db_thread_process(); uint64 duration = startTime - initTime_; if(duration > stampsPerSecond()) { WARNING_MSG(fmt::format("DBTask::process(): delay {0:.2f} seconds, try adjusting the kbengine[_defs].xml(numConnections) and MySQL(my.cnf->max_connections or innodb_flush_log_at_trx_commit)!\nsql:({1})\n", (double(duration)/stampsPerSecondD()), pdbi_->lastquery())); } duration = timestamp() - startTime; if (duration > stampsPerSecond() * 0.2f) { WARNING_MSG(fmt::format("DBTask::process(): took {:.2f} seconds\nsql:({})\n", (double(duration)/stampsPerSecondD()), pdbi_->lastquery())); } return ret; }
/** * This makes sure that the project view is up to date. * * @returns True if the dib was up to date. */ bool ChunkWatchControl::updateProjectDib() { // Are we up to date? if (!projectDib_.isEmpty() && projectMark_ == SpaceMap::instance().mark()) return true; // Are we updating too frequently? if (lastUpdateProjectTime_ != 0) { uint64 now = timestamp(); if ((now - lastUpdateProjectTime_)/(double)stampsPerSecond() < PROJECT_UPDATE_DELTA) return true; lastUpdateProjectTime_ = now; } else { lastUpdateProjectTime_ = timestamp(); } Moo::BaseTexturePtr baseTexture; DX::Texture *texture = static_cast<DX::Texture *>(SpaceMap::instance().texture()); if (texture == NULL) { ChunkDirMapping *dirMap = WorldManager::instance().chunkDirMapping(); if (dirMap != NULL) { // TODO: Check which is first, space.thumbnail.dds or // space.temp_thumbnail.dds. std::string mapName = dirMap->path() + "space.temp_thumbnail.dds"; baseTexture = Moo::TextureManager::instance()->get(mapName, true, false, true, "texture/chunk watcher"); if (baseTexture.hasObject()) { texture = static_cast<DX::Texture *>(baseTexture->pTexture()); } else { mapName = dirMap->path() + "space.thumbnail.dds"; baseTexture = Moo::TextureManager::instance()->get(mapName, true, false, true, "texture/chunk watcher"); if (baseTexture.hasObject()) texture = static_cast<DX::Texture *>(baseTexture->pTexture()); } } } if (texture != NULL) { projectDib_.copyFromTexture(texture); projectMark_ = SpaceMap::instance().mark(); } return false; }
//------------------------------------------------------------------------------------- bool ClientApp::initializeBegin() { gameTimer_ = this->dispatcher().addTimer(1000000 / g_kbeConfig.gameUpdateHertz(), this, reinterpret_cast<void *>(TIMEOUT_GAME_TICK)); ProfileVal::setWarningPeriod(stampsPerSecond() / g_kbeConfig.gameUpdateHertz()); Network::g_extReceiveWindowBytesOverflow = 0; Network::g_intReceiveWindowBytesOverflow = 0; Network::g_intReceiveWindowMessagesOverflow = 0; Network::g_extReceiveWindowMessagesOverflow = 0; Network::g_receiveWindowMessagesOverflowCritical = 0; return true; }
//------------------------------------------------------------------------------------- bool SyncAppDatasHandler::process() { if(lastRegAppTime_ == 0) return true; if(timestamp() - lastRegAppTime_ < uint64( 3 * stampsPerSecond() ) ) return true; bool hasDone = false; std::vector<COMPONENT_ID>::iterator iter = apps_.begin(); for(; iter != apps_.end(); iter++) { COMPONENT_ID componentID = (*iter); Components::ComponentInfos* cinfos = Componentbridge::getComponents().findComponent(componentID); if(cinfos == NULL) continue; switch(cinfos->componentType) { case BASEAPP_TYPE: { Dbmgr::getSingleton().onGlobalDataClientLogon(cinfos->pChannel, cinfos->componentType); hasDone = true; } break; case CELLAPP_TYPE: { Dbmgr::getSingleton().onGlobalDataClientLogon(cinfos->pChannel, cinfos->componentType); hasDone = true; } break; default: break; } } apps_.clear(); lastRegAppTime_ = timestamp(); if(!hasDone) { return true; } delete this; return false; }
//------------------------------------------------------------------------------------- void Channel::startInactivityDetection( float period, float checkPeriod ) { stopInactivityDetection(); // 如果周期为负数则不检查 if(period > 0.f) { inactivityExceptionPeriod_ = uint64( period * stampsPerSecond() ); lastReceivedTime_ = timestamp(); inactivityTimerHandle_ = this->dispatcher().addTimer( int( checkPeriod * 1000000 ), this, (void *)TIMEOUT_INACTIVITY_CHECK ); } }
//------------------------------------------------------------------------------------- void GhostManager::checkRoute() { std::map<ENTITY_ID, ROUTE_INFO>::iterator iter = ghost_route_.begin(); for(; iter != ghost_route_.end(); ) { if(timestamp() - iter->second.lastTime > uint64( 5 * stampsPerSecond() )) { ghost_route_.erase(iter++); } else { ++iter; } } }
//------------------------------------------------------------------------------------- void ClientObject::sendTick() { // 向服务器发送tick uint64 check = uint64( Mercury::g_channelExternalTimeout * stampsPerSecond() ) / 2; if (timestamp() - lastSentActiveTickTime_ > check) { lastSentActiveTickTime_ = timestamp(); Mercury::Bundle bundle; if(connectedGateway_) bundle.newMessage(BaseappInterface::onClientActiveTick); else bundle.newMessage(LoginappInterface::onClientActiveTick); bundle.send(*pChannel_->endpoint()); } }
void DumpD3DResourceReleaseResults() { Record::const_iterator ri = record.begin(); //INFO_MSG( "Dumping D3D resource release results...\n\n" ); //INFO_MSG( "Resource, Total time, Total calls\n" ); while ( ri != record.end() ) { double seconds = double(ri->second.first)/double( stampsPerSecond() ); //INFO_MSG("%s, %f, %d\n", // ri->first.c_str(), seconds, ri->second.second ); ri++; } }
//------------------------------------------------------------------------------------- void DBTransaction::commit() { KBE_ASSERT(!committed_); uint64 startTime = timestamp(); pdbi_->query(SQL_COMMIT, false); uint64 duration = timestamp() - startTime; if(duration > stampsPerSecond() * 0.2f) { WARNING_MSG(fmt::format("DBTransaction::commit(): took {:.2f} seconds\n", (double(duration)/stampsPerSecondD()))); } committed_ = true; }
/** * Adds a new error message for an address to the reporter count map. * Emits an error message if there has been no previous equivalent error * string provider for this address. */ void ErrorReporter::addReport(const Address & address, const std::string & errorString) { AddressAndErrorString addressError(address, errorString); ErrorsAndCounts::iterator searchIter = errorsAndCounts_.find(addressError); uint64 now = timestamp(); // see if we have ever reported this error if (searchIter != errorsAndCounts_.end()) { // this error has been reported recently.. ErrorReportAndCount & reportAndCount = searchIter->second; reportAndCount.count++; int64 millisSinceLastReport = 1000 * (now - reportAndCount.lastReportStamps) / stampsPerSecond(); reportAndCount.lastRaisedStamps = now; if (millisSinceLastReport >= ERROR_REPORT_MIN_PERIOD_MS) { ERROR_MSG(fmt::format("{}\n", addressErrorToString(address, errorString, reportAndCount, now).c_str())); reportAndCount.count = 0; reportAndCount.lastReportStamps = now; } } else { ERROR_MSG(fmt::format("{}\n", addressErrorToString(address, errorString).c_str())); ErrorReportAndCount reportAndCount = { now, // lastReportStamps, now, // lastRaisedStamps, 0, // count }; errorsAndCounts_[ addressError ] = reportAndCount; } }
//------------------------------------------------------------------------------------- void GhostManager::handleTimeout(TimerHandle, void * arg) { if(timestamp() - checkTime_ > uint64( stampsPerSecond() * 0.1 )) { if(messages_.size() == 0 && ghost_route_.size() == 0 && realEntities_.size() == 0) { cancel(); return; } checkRoute(); checkTime_ = timestamp(); } syncMessages(); syncGhosts(); }
/** * This forces the window to be repainted. This function prevents repainting * too rapidly by selectively choosing between Invalidate and RedrawWindow. * * @param force If true then the repaint is done immmediately. */ void ChunkWatchControl::redraw(bool force /*= false*/) { if (!force) { if (lastUpdateTime_ != 0) { uint64 now = timestamp(); if ((now - lastUpdateTime_)/(double)stampsPerSecond() < UPDATE_DELTA) { Invalidate(); // add to message queue for painting later return; } lastUpdateTime_ = now; } else { lastUpdateTime_ = timestamp(); } } RedrawWindow(); }
//------------------------------------------------------------------------------------- void ClientObjectBase::tickSend() { if(!pServerChannel_ || !pServerChannel_->endpoint()) return; // 向服务器发送tick uint64 check = uint64( Mercury::g_channelExternalTimeout * stampsPerSecond() ) / 2; if (timestamp() - lastSentActiveTickTime_ > check) { lastSentActiveTickTime_ = timestamp(); Mercury::Bundle* pBundle = Mercury::Bundle::ObjPool().createObject(); if(connectedGateway_) (*pBundle).newMessage(BaseappInterface::onClientActiveTick); else (*pBundle).newMessage(LoginappInterface::onClientActiveTick); pServerChannel_->pushBundle(pBundle); } pServerChannel_->send(); }
//------------------------------------------------------------------------------------- void ResourceObject::update() { timeout_ = timestamp() + uint64( Resmgr::respool_timeout * stampsPerSecond() ); }
/** * 每秒cpu所耗时间 double版本 */ double stampsPerSecondD() { static double stampsPerSecondCacheD = double(stampsPerSecond()); return stampsPerSecondCacheD; }
//------------------------------------------------------------------------------------- void Interfaces::charge(Network::Channel* pChannel, KBEngine::MemoryStream& s) { OrdersCharge* pOrdersCharge = new OrdersCharge(); pOrdersCharge->timeout = timestamp() + uint64(g_kbeSrvConfig.interfaces_orders_timeout_ * stampsPerSecond()); pOrdersCharge->dbmgrID = pChannel->componentID(); pOrdersCharge->address = pChannel->addr(); s >> pOrdersCharge->baseappID; s >> pOrdersCharge->ordersID; s >> pOrdersCharge->dbid; s.readBlob(pOrdersCharge->postDatas); s >> pOrdersCharge->cbid; INFO_MSG(fmt::format("Interfaces::charge: componentID={4}, chargeID={0}, dbid={1}, cbid={2}, datas={3}!\n", pOrdersCharge->ordersID, pOrdersCharge->dbid, pOrdersCharge->cbid, pOrdersCharge->postDatas, pOrdersCharge->baseappID)); ORDERS::iterator iter = orders_.find(pOrdersCharge->ordersID); if(iter != orders_.end()) { ERROR_MSG(fmt::format("Interfaces::charge: chargeID={} is exist!\n", pOrdersCharge->ordersID)); delete pOrdersCharge; return; } ChargeTask* pinfo = new ChargeTask(); pinfo->orders = *pOrdersCharge; pinfo->pOrders = pOrdersCharge; orders_[pOrdersCharge->ordersID].reset(pOrdersCharge); // 把请求交由脚本处理 SCOPED_PROFILE(SCRIPTCALL_PROFILE); PyObject* pyResult = PyObject_CallMethod(getEntryScript().get(), const_cast<char*>("onRequestCharge"), const_cast<char*>("sKy#"), pOrdersCharge->ordersID.c_str(), pOrdersCharge->dbid, pOrdersCharge->postDatas.c_str(), pOrdersCharge->postDatas.length()); if(pyResult != NULL) Py_DECREF(pyResult); else SCRIPT_ERROR_CHECK(); }
/** * Output all exception's reports that have not yet been output. */ void ErrorReporter::reportPendingExceptions(bool reportBelowThreshold) { uint64 now = timestamp(); // this is set to any iterator slated for removal ErrorsAndCounts::iterator staleIter = this->errorsAndCounts_.end(); for ( ErrorsAndCounts::iterator exceptionCountIter = this->errorsAndCounts_.begin(); exceptionCountIter != this->errorsAndCounts_.end(); ++exceptionCountIter) { // remove any stale mappings from the last loop's run if (staleIter != this->errorsAndCounts_.end()) { this->errorsAndCounts_.erase(staleIter); staleIter = this->errorsAndCounts_.end(); } // check this iteration's last report and see if we need to output // anything const AddressAndErrorString & addressError = exceptionCountIter->first; ErrorReportAndCount & reportAndCount = exceptionCountIter->second; int64 millisSinceLastReport = 1000 * (now - reportAndCount.lastReportStamps) / stampsPerSecond(); if (reportBelowThreshold || millisSinceLastReport >= ERROR_REPORT_MIN_PERIOD_MS) { if (reportAndCount.count) { ERROR_MSG(fmt::format("{}\n", addressErrorToString( addressError.first, addressError.second, reportAndCount, now).c_str() )); reportAndCount.count = 0; reportAndCount.lastReportStamps = now; } } // see if we can remove this mapping if it has not been raised in a // while uint64 sinceLastRaisedMillis = 1000 * (now - reportAndCount.lastRaisedStamps) / stampsPerSecond(); if (sinceLastRaisedMillis > ERROR_REPORT_COUNT_MAX_LIFETIME_MS) { // it's hung around for too long without being raised again, // so remove it in the next iteration staleIter = exceptionCountIter; } } // remove the last mapping if it is marked stale if (staleIter != this->errorsAndCounts_.end()) { this->errorsAndCounts_.erase(staleIter); } }
/** * This method executes the action for the given frame of time. The dTime * parameter is the time elapsed since the last call. * * @param particleSystem The particle system on which to operate. * @param dTime Elapsed time in seconds. */ void CollidePSA::execute( ParticleSystem &particleSystem, float dTime ) { BW_GUARD; SourcePSA* pSource = static_cast<SourcePSA*>( &*particleSystem.pAction( PSA_SOURCE_TYPE_ID ) ); if ( !pSource ) return; RompColliderPtr pGS = pSource->groundSpecifier(); if ( !pGS ) return; uint64 tend = timestamp() + stampsPerSecond() / 2000; bool soundHit = false; float maxVelocity = 0; Vector3 soundPos; uint materialKind; Particles::iterator it = particleSystem.begin(); Particles::iterator end = particleSystem.end(); WorldTriangle tri; //bust out of the loop if we take more than 0.5 msec //Sprite particles don't calculate spin while ( it != end && timestamp()<tend ) { Particle &particle = *it++; if (!particle.isAlive()) { continue; } //note - particles get moved after actions. Vector3 velocity; particle.getVelocity(velocity); Vector3 pos; Vector3 newPos; if(particleSystem.isLocal()) { Matrix world = particleSystem.worldTransform(); pos = world.applyPoint(particle.position()); Vector3 nPos; particleSystem.predictPosition( particle, dTime, nPos ); newPos = world.applyPoint(nPos); } else { pos = particle.position(); particleSystem.predictPosition( particle, dTime, newPos ); } float tValue = pGS->collide( pos, newPos, tri ); if ( tValue >= 0.f && tValue <= 1.f ) { // calc v as a dotprod of the two normalised vectors (before and after collision) Vector3 oldVel = velocity / velocity.length(); tri.bounce( velocity, elasticity_ ); particle.setVelocity( velocity ); float newSpeed = velocity.length(); Vector3 newVel(velocity / newSpeed); float severity = oldVel.dotProduct(newVel); //DEBUG_MSG("severity: %1.3f, speed=%1.3f\n", severity, newSpeed); float v = (1 - severity) * newSpeed; //now spin the particle ( mesh only ) if ( !spriteBased_ ) { //first, calculate the current rotation, and update the pitch/yaw value. Matrix currentRot; currentRot.setRotate( particle.yaw(), particle.pitch(), 0.f ); Matrix spin; float spinSpeed = particle.meshSpinSpeed(); Vector3 meshSpinAxis = particle.meshSpinAxis(); // If there is no spin direction then creating a rotation // matrix can create weird matrices - e.g. matrices with // negative scale components and a translation. We choose the // velocity as the spin direction (aribitrarily choosing, for // example up looks weird). if (meshSpinAxis == Vector3::zero()) { meshSpinAxis = velocity; meshSpinAxis.normalise(); } D3DXMatrixRotationAxis ( &spin, &meshSpinAxis, spinSpeed * (particle.age()-particle.meshSpinAge()) ); currentRot.preMultiply( spin ); particle.pitch( currentRot.pitch() ); particle.yaw( currentRot.yaw() ); //now, reset the age of the spin particle.meshSpinAge( particle.age() ); //finally, update the spin ( stored in the particle's colour ) float addedSpin = unitRand() * (maxAddedRotation_-minAddedRotation_) + minAddedRotation_; addedSpin *= min( newSpeed, 1.f ); spinSpeed = Math::clamp( 0.f, spinSpeed + addedSpin, 1.f ); particle.meshSpinSpeed(spinSpeed); particle.meshSpinAxis(meshSpinAxis); } if ( soundEnabled_ && v > 0.5f ) { soundHit = true; if (v > maxVelocity) { maxVelocity = v; soundPos = particle.position(); materialKind = tri.materialKind(); } } } } if ( soundHit ) { SmartPointer < RompSound > rs = RompSound::getProvider(); if (rs) { if (!soundTag_.empty()) { rs->playParticleSound( soundTag_.c_str(), soundPos, maxVelocity, soundSrcIdx_, materialKind ); } } } }
/** tick */ void tick() { if(timestamp() - lastTimestamp_ < (ServerConfig::getSingleton().callback_timeout_ * stampsPerSecond())) return; lastTimestamp_ = timestamp(); typename CALLBACKS::iterator iter = cbMap_.begin(); for(; iter!= cbMap_.end(); ) { if(lastTimestamp_ > iter->second.second) { if(processTimeout(iter->first, iter->second.first)) { idAlloc_.reclaim(iter->first); cbMap_.erase(iter++); continue; } } ++iter; } }
//------------------------------------------------------------------------------------- bool RestoreEntityHandler::process() { Components::COMPONENTS& cts = Components::getSingleton().getComponents(CELLAPP_TYPE); Mercury::Channel* pChannel = NULL; if(cts.size() > 0) { Components::COMPONENTS::iterator ctiter = cts.begin(); if((*ctiter).pChannel == NULL) return true; pChannel = (*ctiter).pChannel; } if(pChannel == NULL) return true; int count = 0; // 首先需要找到这个cell上的space // KBE_ASSERT(restoreSpaces_.size() > 0); // 如果spaceEntity不在这个baseapp上创建则继续等待 // 当spaceEntity的cell创建好了之后会广播给所有的baseapp, 每个baseapp // 去判断是否有需要恢复的entity if(restoreSpaces_.size() > 0) { if(timestamp() - tickReport_ > uint64( 3 * stampsPerSecond() )) { tickReport_ = timestamp(); INFO_MSG(boost::format("RestoreEntityHandler::process(%3%): wait for localSpace to get cell!, entitiesSize(%1%), spaceSize=%2%\n") % entities_.size() % restoreSpaces_.size() % cellappID_); } int spaceCellCount = 0; // 必须等待space恢复 std::vector<RestoreData>::iterator restoreSpacesIter = restoreSpaces_.begin(); for(; restoreSpacesIter != restoreSpaces_.end(); restoreSpacesIter++) { Base* pBase = Baseapp::getSingleton().findEntity((*restoreSpacesIter).id); if(pBase) { if(++count > (int)g_kbeSrvConfig.getBaseApp().entityRestoreSize) { return true; } if((*restoreSpacesIter).creatingCell == false) { (*restoreSpacesIter).creatingCell = true; pBase->restoreCell(NULL); } else { if(pBase->cellMailbox() == NULL) { return true; } else { spaceCellCount++; if(!(*restoreSpacesIter).processed) { (*restoreSpacesIter).processed = true; pBase->onRestore(); } } } } else { ERROR_MSG(boost::format("RestoreEntityHandler::process(%1%): lose space(%2%).\n") % cellappID_ % (*restoreSpacesIter).id); } } if(spaceCellCount != (int)restoreSpaces_.size()) return true; // 通知其他baseapp, space恢复了cell if(!broadcastOtherBaseapps_) { broadcastOtherBaseapps_ = true; INFO_MSG(boost::format("RestoreEntityHandler::process(%1%): begin broadcast-spaceGetCell to otherBaseapps...\n") % cellappID_); std::vector<RestoreData>::iterator restoreSpacesIter = restoreSpaces_.begin(); for(; restoreSpacesIter != restoreSpaces_.end(); restoreSpacesIter++) { Base* pBase = Baseapp::getSingleton().findEntity((*restoreSpacesIter).id); bool destroyed = (pBase == NULL || pBase->isDestroyed()); COMPONENT_ID baseappID = g_componentID; COMPONENT_ID cellappID = 0; SPACE_ID spaceID = (*restoreSpacesIter).spaceID; ENTITY_ID spaceEntityID = (*restoreSpacesIter).id; ENTITY_SCRIPT_UID utype = 0; if(!destroyed) { utype = pBase->scriptModule()->getUType(); cellappID = pBase->cellMailbox()->componentID(); } spaceIDs_.erase(std::remove(spaceIDs_.begin(), spaceIDs_.end(), spaceID), spaceIDs_.end()); Mercury::Channel* pChannel = NULL; Components::COMPONENTS& cts = Componentbridge::getComponents().getComponents(BASEAPP_TYPE); Components::COMPONENTS::iterator comsiter = cts.begin(); for(; comsiter != cts.end(); comsiter++) { pChannel = (*comsiter).pChannel; if(pChannel) { INFO_MSG(boost::format("RestoreEntityHandler::process(%5%): broadcast baseapp[%1%, %2%], spaceID[%3%], utype[%4%]...\n") % (*comsiter).cid % pChannel->c_str() % spaceID % utype % cellappID_); Mercury::Bundle* pBundle = Mercury::Bundle::ObjPool().createObject(); (*pBundle).newMessage(BaseappInterface::onRestoreSpaceCellFromOtherBaseapp); (*pBundle) << baseappID << cellappID << spaceID << spaceEntityID << utype << destroyed; pBundle->send(Baseapp::getSingleton().getNetworkInterface(), pChannel); Mercury::Bundle::ObjPool().reclaimObject(pBundle); } } } } } if(spaceIDs_.size() > 0) { if(timestamp() - tickReport_ > uint64( 3 * stampsPerSecond() )) { tickReport_ = timestamp(); INFO_MSG(boost::format("RestoreEntityHandler::process(%1%): wait for otherBaseappSpaces to get cell!, entitiesSize(%2%), spaceSize=%3%\n") % cellappID_ % entities_.size() % spaceIDs_.size()); } return true; } // 恢复其他entity std::vector<RestoreData>::iterator iter = entities_.begin(); for(; iter != entities_.end(); ) { RestoreData& data = (*iter); Base* pBase = Baseapp::getSingleton().findEntity(data.id); if(pBase) { if(++count > g_kbeSrvConfig.getBaseApp().entityRestoreSize) { return true; } if(pBase->cellMailbox() != NULL) { if(!data.processed) { data.processed = true; pBase->onRestore(); } iter = entities_.erase(iter); } else { if(!data.creatingCell) { data.creatingCell = true; EntityMailboxAbstract* cellMailbox = NULL; std::vector<RestoreData>::iterator restoreSpacesIter = restoreSpaces_.begin(); for(; restoreSpacesIter != restoreSpaces_.end(); restoreSpacesIter++) { Base* pSpace = Baseapp::getSingleton().findEntity((*restoreSpacesIter).id); if(pSpace && pBase->spaceID() == pSpace->spaceID()) { cellMailbox = pSpace->cellMailbox(); break; } } if(cellMailbox == NULL) { restoreSpacesIter = otherRestoredSpaces_.begin(); for(; restoreSpacesIter != otherRestoredSpaces_.end(); restoreSpacesIter++) { if(pBase->spaceID() == (*restoreSpacesIter).spaceID && (*restoreSpacesIter).cell) { cellMailbox = (*restoreSpacesIter).cell; break; } } } if(cellMailbox) { pBase->restoreCell(cellMailbox); } else { ENTITY_ID delID = pBase->id(); pBase->destroy(); WARNING_MSG(boost::format("RestoreEntityHandler::process(%1%): not fount spaceCell, killed base(%2%)!") % cellappID_ % delID); if(Baseapp::getSingleton().findEntity(delID) == NULL) iter = entities_.erase(iter); continue; } } iter++; } } else { iter = entities_.erase(iter); } } if(entities_.size() == 0) { std::vector<RestoreData>::iterator restoreSpacesIter = otherRestoredSpaces_.begin(); for(; restoreSpacesIter != otherRestoredSpaces_.end(); restoreSpacesIter++) { if((*restoreSpacesIter).cell) { Py_DECREF((*restoreSpacesIter).cell); (*restoreSpacesIter).cell = NULL; } } otherRestoredSpaces_.clear(); inProcess_ = false; Baseapp::getSingleton().onRestoreEntitiesOver(this); return false; } return true; }