diff options
author | megamage <none@none> | 2009-02-19 18:46:58 -0600 |
---|---|---|
committer | megamage <none@none> | 2009-02-19 18:46:58 -0600 |
commit | 72e8c092128a33515d6f4b48a71526ece81b17b7 (patch) | |
tree | 301c1badaa1f4b097bc425c67883258d9f7f1d3e /src | |
parent | 83adfb5692e3daa4d09d233f193f23b746e5e4c4 (diff) |
[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
Diffstat (limited to 'src')
-rw-r--r-- | src/game/PoolHandler.cpp | 46 | ||||
-rw-r--r-- | src/game/PoolHandler.h | 1 | ||||
-rw-r--r-- | src/shared/revision_nr.h | 2 |
3 files changed, 48 insertions, 1 deletions
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<max_pool_id; ++i) + { + std::set<uint16> 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<uint16>::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<PoolHandler::Pool>::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<PoolHandler::Pool>::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<PoolObject> 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__ |