Core/Instances: Fixed and optimized instance id reuse
Port From (https://github.com/TrinityCore/TrinityCore/commit/fbdf8784a5c03dfcb575ef7b760a62d0d9d2acc1)
This commit is contained in:
@@ -199,11 +199,6 @@ namespace Game.Maps
|
|||||||
{
|
{
|
||||||
uint instanceId = result.Read<uint>(0);
|
uint instanceId = result.Read<uint>(0);
|
||||||
|
|
||||||
// Instances are pulled in ascending order from db and nextInstanceId is initialized with 1,
|
|
||||||
// so if the instance id is used, increment until we find the first unused one for a potential new instance
|
|
||||||
if (Global.MapMgr.GetNextInstanceId() == instanceId)
|
|
||||||
Global.MapMgr.SetNextInstanceId(instanceId + 1);
|
|
||||||
|
|
||||||
// Mark instance id as being used
|
// Mark instance id as being used
|
||||||
Global.MapMgr.RegisterInstanceId(instanceId);
|
Global.MapMgr.RegisterInstanceId(instanceId);
|
||||||
long resettime = result.Read<long>(3);
|
long resettime = result.Read<long>(3);
|
||||||
|
|||||||
@@ -16,12 +16,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using Framework.Constants;
|
using Framework.Constants;
|
||||||
|
using Framework.Database;
|
||||||
using Game.DataStorage;
|
using Game.DataStorage;
|
||||||
using Game.Groups;
|
using Game.Groups;
|
||||||
using Game.Maps;
|
using Game.Maps;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Game.Entities
|
namespace Game.Entities
|
||||||
{
|
{
|
||||||
@@ -321,35 +322,59 @@ namespace Game.Entities
|
|||||||
public void InitInstanceIds()
|
public void InitInstanceIds()
|
||||||
{
|
{
|
||||||
_nextInstanceId = 1;
|
_nextInstanceId = 1;
|
||||||
|
|
||||||
|
SQLResult result = DB.Characters.Query("SELECT IFNULL(MAX(id), 0) FROM instance");
|
||||||
|
if (!result.IsEmpty())
|
||||||
|
_freeInstanceIds = new BitSet(result.Read<int>(0) + 2, true); // make space for one extra to be able to access [_nextInstanceId] index in case all slots are taken
|
||||||
|
else
|
||||||
|
_freeInstanceIds = new BitSet((int)_nextInstanceId + 1, true);
|
||||||
|
|
||||||
|
// never allow 0 id
|
||||||
|
_freeInstanceIds[0] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterInstanceId(uint instanceId)
|
public void RegisterInstanceId(uint instanceId)
|
||||||
{
|
{
|
||||||
// Allocation and sizing was done in InitInstanceIds()
|
_freeInstanceIds[(int)instanceId] = false;
|
||||||
_instanceIds[instanceId] = true;
|
|
||||||
|
// Instances are pulled in ascending order from db and nextInstanceId is initialized with 1,
|
||||||
|
// so if the instance id is used, increment until we find the first unused one for a potential new instance
|
||||||
|
if (_nextInstanceId == instanceId)
|
||||||
|
++_nextInstanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GenerateInstanceId()
|
public uint GenerateInstanceId()
|
||||||
{
|
{
|
||||||
|
if (_nextInstanceId == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Maps, "Instance ID overflow!! Can't continue, shutting down server. ");
|
||||||
|
Global.WorldMgr.StopNow();
|
||||||
|
return _nextInstanceId;
|
||||||
|
}
|
||||||
|
|
||||||
uint newInstanceId = _nextInstanceId;
|
uint newInstanceId = _nextInstanceId;
|
||||||
|
Cypher.Assert(newInstanceId < _freeInstanceIds.Length);
|
||||||
|
_freeInstanceIds[(int)newInstanceId] = false;
|
||||||
|
|
||||||
// Find the lowest available id starting from the current NextInstanceId (which should be the lowest according to the logic in FreeInstanceId()
|
// Find the lowest available id starting from the current NextInstanceId (which should be the lowest according to the logic in FreeInstanceId()
|
||||||
for (uint i = ++_nextInstanceId; i < 0xFFFFFFFF; ++i)
|
int nextFreeId = -1;
|
||||||
|
for (var i = (int)_nextInstanceId++; i < _freeInstanceIds.Length; i++)
|
||||||
{
|
{
|
||||||
if ((i < _instanceIds.Count && !_instanceIds[i]) || i >= _instanceIds.Count)
|
if (_freeInstanceIds[i])
|
||||||
{
|
{
|
||||||
_nextInstanceId = i;
|
nextFreeId = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newInstanceId == _nextInstanceId)
|
if (nextFreeId == -1)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Maps, "Instance ID overflow!! Can't continue, shutting down server. ");
|
_nextInstanceId = (uint)_freeInstanceIds.Length;
|
||||||
Global.WorldMgr.StopNow();
|
_freeInstanceIds.Length += 1;
|
||||||
|
_freeInstanceIds[(int)_nextInstanceId] = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
_instanceIds[newInstanceId] = true;
|
_nextInstanceId = (uint)nextFreeId;
|
||||||
|
|
||||||
return newInstanceId;
|
return newInstanceId;
|
||||||
}
|
}
|
||||||
@@ -357,10 +382,8 @@ namespace Game.Entities
|
|||||||
public void FreeInstanceId(uint instanceId)
|
public void FreeInstanceId(uint instanceId)
|
||||||
{
|
{
|
||||||
// If freed instance id is lower than the next id available for new instances, use the freed one instead
|
// If freed instance id is lower than the next id available for new instances, use the freed one instead
|
||||||
if (instanceId < _nextInstanceId)
|
_nextInstanceId = Math.Min(instanceId, _nextInstanceId);
|
||||||
SetNextInstanceId(instanceId);
|
_freeInstanceIds[(int)instanceId] = true;
|
||||||
|
|
||||||
_instanceIds[instanceId] = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetGridCleanUpDelay(uint t)
|
public void SetGridCleanUpDelay(uint t)
|
||||||
@@ -455,7 +478,7 @@ namespace Game.Entities
|
|||||||
IntervalTimer i_timer = new IntervalTimer();
|
IntervalTimer i_timer = new IntervalTimer();
|
||||||
object _mapsLock= new object();
|
object _mapsLock= new object();
|
||||||
uint i_gridCleanUpDelay;
|
uint i_gridCleanUpDelay;
|
||||||
Dictionary<uint, bool> _instanceIds = new Dictionary<uint, bool>();
|
BitSet _freeInstanceIds;
|
||||||
uint _nextInstanceId;
|
uint _nextInstanceId;
|
||||||
MapUpdater m_updater;
|
MapUpdater m_updater;
|
||||||
uint _scheduledScripts;
|
uint _scheduledScripts;
|
||||||
|
|||||||
Reference in New Issue
Block a user