From 72e8c092128a33515d6f4b48a71526ece81b17b7 Mon Sep 17 00:00:00 2001 From: megamage Date: Thu, 19 Feb 2009 18:46:58 -0600 Subject: [7299] Implemented circular loop detection for pools in pools As a result, the last relation that makes the loop is automatically removed. An error message is displayed and core go on loading remaining records. Author: Neo2003 --HG-- branch : trunk --- src/game/PoolHandler.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/game/PoolHandler.h | 1 + src/shared/revision_nr.h | 2 +- 3 files changed, 48 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/game/PoolHandler.cpp b/src/game/PoolHandler.cpp index 961e34ab369..2eef36ba9c2 100644 --- a/src/game/PoolHandler.cpp +++ b/src/game/PoolHandler.cpp @@ -270,6 +270,30 @@ void PoolHandler::LoadFromDB() mPoolSearchMap.insert(p); } while( result->NextRow() ); + + // Now check for circular reference + for(uint16 i=0; i checkedPools; + for(SearchMap::iterator poolItr = mPoolSearchMap.find(i); poolItr != mPoolSearchMap.end(); poolItr = mPoolSearchMap.find(poolItr->second)) + { + checkedPools.insert(poolItr->first); + if(checkedPools.find(poolItr->second) != checkedPools.end()) + { + std::ostringstream ss; + ss<< "The pool(s) "; + for (std::set::const_iterator itr=checkedPools.begin(); itr!=checkedPools.end(); ++itr) + ss << *itr << " "; + ss << "create(s) a circular reference, which can cause the server to freeze.\nRemoving the last link between mother pool " + << poolItr->first << " and child pool " << poolItr->second; + sLog.outErrorDb(ss.str().c_str()); + mPoolPoolGroups[poolItr->second].RemoveOneRelation(poolItr->first); + mPoolSearchMap.erase(poolItr); + --count; + break; + } + } + } sLog.outString(); sLog.outString( ">> Loaded %u pools in mother pools", count ); delete result; @@ -518,6 +542,28 @@ void PoolHandler::PoolGroup::Despawn1Object(uint32 child_pool poolhandler.DespawnPool(child_pool_id); } +// Method for a pool only to remove any found record causing a circular dependency loop +template<> +void PoolHandler::PoolGroup::RemoveOneRelation(uint16 child_pool_id) +{ + for (PoolObjectList::iterator itr = ExplicitlyChanced.begin(); itr != ExplicitlyChanced.end(); ++itr) + { + if(itr->guid == child_pool_id) + { + ExplicitlyChanced.erase(itr); + break; + } + } + for (PoolObjectList::iterator itr = EqualChanced.begin(); itr != EqualChanced.end(); ++itr) + { + if(itr->guid == child_pool_id) + { + EqualChanced.erase(itr); + break; + } + } +} + // Method that Spawn 1+ creatures or gameobject // if cache is false (initialization or event start), X creatures are spawned with X <= limit (< if limit higher that the number of creatures in pool) // if cache is true, this means only one has to be spawned (or respawned if the rolled one is same as cached one) diff --git a/src/game/PoolHandler.h b/src/game/PoolHandler.h index faeb301d48a..995c97d59b6 100644 --- a/src/game/PoolHandler.h +++ b/src/game/PoolHandler.h @@ -91,6 +91,7 @@ class PoolHandler::PoolGroup void SpawnObject(uint32 limit, bool cache=false); bool Spawn1Object(uint32 guid); bool ReSpawn1Object(uint32 guid); + void RemoveOneRelation(uint16 child_pool_id); private: typedef std::vector PoolObjectList; uint32 CacheValue; // Store the guid of the removed creature/gameobject during a pool update diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index f01c8e39d62..240926801cc 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7298" + #define REVISION_NR "7299" #endif // __REVISION_NR_H__ -- cgit v1.2.3