Core/InstanceSaveMgr: Optimize instance packing and cleaning up
--HG-- branch : trunk
This commit is contained in:
@@ -246,120 +246,47 @@ void InstanceSaveManager::_DelHelper(const char *fields, const char *table, cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceSaveManager::CleanupInstances()
|
void InstanceSaveManager::CleanupAndPackInstances()
|
||||||
{
|
{
|
||||||
barGoLink bar(2);
|
|
||||||
bar.step();
|
|
||||||
|
|
||||||
// load reset times and clean expired instances
|
// load reset times and clean expired instances
|
||||||
sInstanceSaveMgr.LoadResetTimes();
|
sInstanceSaveMgr.LoadResetTimes();
|
||||||
|
|
||||||
// clean character/group - instance binds with invalid group/characters
|
// Delete invalid character_instance and group_instance references
|
||||||
_DelHelper("character_instance.guid, instance", "character_instance", "LEFT JOIN characters ON character_instance.guid = characters.guid WHERE characters.guid IS NULL");
|
CharacterDatabase.DirectExecute("DELETE ci.* FROM character_instance AS ci LEFT JOIN characters AS c ON ci.guid = c.guid WHERE c.guid IS NULL");
|
||||||
_DelHelper("group_instance.guid, instance", "group_instance", "LEFT JOIN groups ON group_instance.guid = groups.guid LEFT JOIN characters ON groups.leaderGuid = characters.guid WHERE characters.guid IS NULL OR groups.guid IS NULL");
|
CharacterDatabase.DirectExecute("DELETE gi.* FROM group_instance AS gi LEFT JOIN groups AS g ON gi.guid = g.guid WHERE g.guid IS NULL");
|
||||||
|
|
||||||
// clean instances that do not have any players or groups bound to them
|
// Delete invalid instance references
|
||||||
_DelHelper("id, map, difficulty", "instance", "LEFT JOIN character_instance ON character_instance.instance = id LEFT JOIN group_instance ON group_instance.instance = id WHERE character_instance.instance IS NULL AND group_instance.instance IS NULL");
|
CharacterDatabase.DirectExecute("DELETE i.* FROM instance AS i LEFT JOIN character_instance AS ci ON i.id = ci.instance LEFT JOIN group_instance AS gi ON i.id = gi.instance WHERE ci.guid IS NULL AND gi.guid IS NULL");
|
||||||
|
|
||||||
// clean invalid instance references in other tables
|
// Delete invalid references to instance
|
||||||
_DelHelper("character_instance.guid, instance", "character_instance", "LEFT JOIN instance ON character_instance.instance = instance.id WHERE instance.id IS NULL");
|
CharacterDatabase.DirectExecute("DELETE tmp.* FROM creature_respawn AS tmp LEFT JOIN instance ON tmp.instance = instance.id WHERE tmp.instance > 0 AND instance.id IS NULL");
|
||||||
_DelHelper("guid, instance", "group_instance", "LEFT JOIN instance ON group_instance.instance = instance.id WHERE instance.id IS NULL");
|
CharacterDatabase.DirectExecute("DELETE tmp.* FROM gameobject_respawn AS tmp LEFT JOIN instance ON tmp.instance = instance.id WHERE tmp.instance > 0 AND instance.id IS NULL");
|
||||||
|
CharacterDatabase.DirectExecute("DELETE tmp.* FROM character_instance AS tmp LEFT JOIN instance ON tmp.instance = instance.id WHERE tmp.instance > 0 AND instance.id IS NULL");
|
||||||
|
CharacterDatabase.DirectExecute("DELETE tmp.* FROM group_instance AS tmp LEFT JOIN instance ON tmp.instance = instance.id WHERE tmp.instance > 0 AND instance.id IS NULL");
|
||||||
|
|
||||||
// Clean respawn data from non existing instances
|
// Clean invalid references to instance
|
||||||
CharacterDatabase.PExecute("DELETE FROM creature_respawn WHERE instance <> 0 AND instance NOT IN (SELECT id FROM instance)");
|
CharacterDatabase.DirectExecute("UPDATE corpse AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = 0 WHERE tmp.instance > 0 AND instance.id IS NULL");
|
||||||
CharacterDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance <> 0 AND instance NOT IN (SELECT id FROM instance)");
|
CharacterDatabase.DirectExecute("UPDATE characters AS tmp LEFT JOIN instance ON tmp.instance_id = instance.id SET tmp.instance_id = 0 WHERE tmp.instance_id > 0 AND instance.id IS NULL");
|
||||||
|
|
||||||
// first, obtain total instance set
|
// Create new index
|
||||||
std::set<uint32> InstanceSet;
|
CharacterDatabase.DirectExecute("ALTER TABLE instance ADD newid INT UNSIGNED AUTO_INCREMENT, ADD INDEX(newid)");
|
||||||
QueryResult result = CharacterDatabase.Query("SELECT id FROM instance");
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Field *fields = result->Fetch();
|
|
||||||
InstanceSet.insert(fields[0].GetUInt32());
|
|
||||||
}
|
|
||||||
while (result->NextRow());
|
|
||||||
}
|
|
||||||
|
|
||||||
// characters
|
// Update old ids
|
||||||
result = CharacterDatabase.Query("SELECT DISTINCT(instance_id) FROM characters WHERE instance_id <> 0");
|
CharacterDatabase.DirectExecute("UPDATE corpse AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = instance.newid WHERE tmp.instance > 0");
|
||||||
if (result)
|
CharacterDatabase.DirectExecute("UPDATE character_instance AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = instance.newid WHERE tmp.instance > 0");
|
||||||
{
|
CharacterDatabase.DirectExecute("UPDATE group_instance AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = instance.newid WHERE tmp.instance > 0");
|
||||||
do
|
CharacterDatabase.DirectExecute("UPDATE characters AS tmp LEFT JOIN instance ON tmp.instance_id = instance.id SET tmp.instance_id = instance.newid WHERE tmp.instance_id > 0");
|
||||||
{
|
CharacterDatabase.DirectExecute("UPDATE creature_respawn AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = instance.newid WHERE tmp.instance > 0");
|
||||||
Field *fields = result->Fetch();
|
CharacterDatabase.DirectExecute("UPDATE gameobject_respawn AS tmp LEFT JOIN instance ON tmp.instance = instance.id SET tmp.instance = instance.newid WHERE tmp.instance > 0");
|
||||||
if (InstanceSet.find(fields[0].GetUInt32()) == InstanceSet.end())
|
|
||||||
CharacterDatabase.PExecute("UPDATE characters SET instance_id = '0' WHERE instance_id = '%u'", fields[0].GetUInt32());
|
|
||||||
}
|
|
||||||
while (result->NextRow());
|
|
||||||
}
|
|
||||||
|
|
||||||
// corpse
|
// Update instance too
|
||||||
result = CharacterDatabase.Query("SELECT DISTINCT(instance) FROM corpse WHERE instance <> 0");
|
CharacterDatabase.Query("UPDATE instance SET id = newid");
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Field *fields = result->Fetch();
|
|
||||||
if (InstanceSet.find(fields[0].GetUInt32()) == InstanceSet.end())
|
|
||||||
CharacterDatabase.PExecute("UPDATE corpse SET instance = '0' WHERE instance = '%u'", fields[0].GetUInt32());
|
|
||||||
}
|
|
||||||
while (result->NextRow());
|
|
||||||
}
|
|
||||||
|
|
||||||
bar.step();
|
// Finally drop the no longer needed column
|
||||||
sLog.outString();
|
CharacterDatabase.Query("ALTER TABLE instance DROP COLUMN newid");
|
||||||
sLog.outString(">> Initialized %u instances", (uint32)InstanceSet.size());
|
|
||||||
}
|
// Bake some cookies for click
|
||||||
|
sLog.outString(">> Cleaned up and packed instances");
|
||||||
void InstanceSaveManager::PackInstances()
|
|
||||||
{
|
|
||||||
// this routine renumbers player instance associations in such a way so they start from 1 and go up
|
|
||||||
// TODO: this can be done a LOT more efficiently
|
|
||||||
|
|
||||||
// obtain set of all associations
|
|
||||||
std::set<uint32> InstanceSet;
|
|
||||||
|
|
||||||
// all valid ids are in the instance table
|
|
||||||
// any associations to ids not in this table are assumed to be
|
|
||||||
// cleaned already in CleanupInstances
|
|
||||||
QueryResult result = CharacterDatabase.Query("SELECT id FROM instance");
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Field *fields = result->Fetch();
|
|
||||||
InstanceSet.insert(fields[0].GetUInt32());
|
|
||||||
}
|
|
||||||
while (result->NextRow());
|
|
||||||
}
|
|
||||||
|
|
||||||
barGoLink bar(InstanceSet.size() + 1);
|
|
||||||
bar.step();
|
|
||||||
|
|
||||||
uint32 InstanceNumber = 1;
|
|
||||||
// we do assume std::set is sorted properly on integer value
|
|
||||||
for (std::set<uint32>::iterator i = InstanceSet.begin(); i != InstanceSet.end(); ++i)
|
|
||||||
{
|
|
||||||
if (*i != InstanceNumber)
|
|
||||||
{
|
|
||||||
// remap instance id
|
|
||||||
CharacterDatabase.PExecute("UPDATE creature_respawn SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i);
|
|
||||||
CharacterDatabase.PExecute("UPDATE gameobject_respawn SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i);
|
|
||||||
CharacterDatabase.PExecute("UPDATE characters SET instance_id = '%u' WHERE instance_id = '%u'", InstanceNumber, *i);
|
|
||||||
CharacterDatabase.PExecute("UPDATE corpse SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i);
|
|
||||||
CharacterDatabase.PExecute("UPDATE character_instance SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i);
|
|
||||||
CharacterDatabase.PExecute("UPDATE instance SET id = '%u' WHERE id = '%u'", InstanceNumber, *i);
|
|
||||||
CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u' WHERE instance = '%u'", InstanceNumber, *i);
|
|
||||||
}
|
|
||||||
|
|
||||||
++InstanceNumber;
|
|
||||||
bar.step();
|
|
||||||
}
|
|
||||||
|
|
||||||
sLog.outString();
|
|
||||||
sLog.outString(">> Instance numbers remapped, next instance id is %u", InstanceNumber);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceSaveManager::LoadResetTimes()
|
void InstanceSaveManager::LoadResetTimes()
|
||||||
|
|||||||
@@ -141,8 +141,7 @@ class InstanceSaveManager
|
|||||||
};
|
};
|
||||||
typedef std::multimap<time_t /*resetTime*/, InstResetEvent> ResetTimeQueue;
|
typedef std::multimap<time_t /*resetTime*/, InstResetEvent> ResetTimeQueue;
|
||||||
|
|
||||||
void CleanupInstances();
|
void CleanupAndPackInstances();
|
||||||
void PackInstances();
|
|
||||||
|
|
||||||
void LoadResetTimes();
|
void LoadResetTimes();
|
||||||
time_t GetResetTimeFor(uint32 mapid, Difficulty d) const
|
time_t GetResetTimeFor(uint32 mapid, Difficulty d) const
|
||||||
|
|||||||
@@ -1256,11 +1256,8 @@ void World::SetInitialWorldSettings()
|
|||||||
sSpellMgr.LoadSkillLineAbilityMap();
|
sSpellMgr.LoadSkillLineAbilityMap();
|
||||||
|
|
||||||
///- Clean up and pack instances
|
///- Clean up and pack instances
|
||||||
sLog.outString("Cleaning up instances...");
|
sLog.outString("Cleaning up and packing instances...");
|
||||||
sInstanceSaveMgr.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables
|
sInstanceSaveMgr.CleanupAndPackInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables
|
||||||
|
|
||||||
sLog.outString("Packing instances...");
|
|
||||||
sInstanceSaveMgr.PackInstances();
|
|
||||||
|
|
||||||
sLog.outString("Loading Localization strings...");
|
sLog.outString("Loading Localization strings...");
|
||||||
sObjectMgr.LoadCreatureLocales();
|
sObjectMgr.LoadCreatureLocales();
|
||||||
|
|||||||
Reference in New Issue
Block a user