aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormegamage <none@none>2009-02-19 18:46:58 -0600
committermegamage <none@none>2009-02-19 18:46:58 -0600
commit72e8c092128a33515d6f4b48a71526ece81b17b7 (patch)
tree301c1badaa1f4b097bc425c67883258d9f7f1d3e /src
parent83adfb5692e3daa4d09d233f193f23b746e5e4c4 (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.cpp46
-rw-r--r--src/game/PoolHandler.h1
-rw-r--r--src/shared/revision_nr.h2
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__