mirror of
https://gitlab.com/Scribble/gdlenhanced.git
synced 2026-08-17 14:23:04 -04:00
213 lines
4.5 KiB
C++
213 lines
4.5 KiB
C++
|
|
#include "StdAfx.h"
|
|
#include "ObjectIDGen.h"
|
|
#include "DatabaseIO.h"
|
|
#include "Server.h"
|
|
|
|
const uint32_t IDQUEUEMAX = 250000;
|
|
const uint32_t IDQUEUEMIN = 50000;
|
|
const uint32_t IDRANGESTART = 0x80000000;
|
|
const uint32_t IDRANGEEND = 0xff000000;
|
|
|
|
const uint32_t IDEPHEMERALSTART = 0x60000000;
|
|
const uint32_t IDEPHEMERALMASK = 0x6fffffff;
|
|
|
|
|
|
CObjectIDGenerator::CObjectIDGenerator()
|
|
{
|
|
m_ephemeral = IDEPHEMERALSTART;
|
|
if (g_pConfig->UseIncrementalID())
|
|
{
|
|
WINLOG(Data, Normal, "Using Incremental ID system.....\n");
|
|
}
|
|
else
|
|
{
|
|
// Verify IDRanges tables exists and has values
|
|
if (g_pDBIO->IDRangeTableExistsAndValid())
|
|
{
|
|
WINLOG(Data, Normal, "Using ID Mined system.....\n");
|
|
}
|
|
else
|
|
{
|
|
isIdRangeValid = false;
|
|
}
|
|
}
|
|
LoadRangeStart();
|
|
LoadState();
|
|
}
|
|
|
|
CObjectIDGenerator::~CObjectIDGenerator()
|
|
{
|
|
}
|
|
|
|
void CObjectIDGenerator::LoadState()
|
|
{
|
|
if (!g_pConfig->UseIncrementalID())
|
|
{
|
|
g_pDB2->QueueAsyncQuery(
|
|
new AvailableIdQuery(
|
|
m_dwHintDynamicGUID, IDQUEUEMAX, listOfIdsForWeenies, m_lock, m_bLoadingState));
|
|
|
|
//queryInProgress = true;
|
|
//std::list<unsigned int> startupRange = g_pDBIO->GetNextIDRange(m_dwHintDynamicGUID, IDQUEUEMAX);
|
|
//m_dwHintDynamicGUID += IDQUEUEMAX;
|
|
SaveRangeStart();
|
|
|
|
//DEBUG_DATA << "New Group count:" << startupRange.size();
|
|
|
|
//for (std::list<unsigned int>::iterator it = startupRange.begin(); it != startupRange.end(); ++it)
|
|
// listOfIdsForWeenies.push(*it);
|
|
|
|
//if (listOfIdsForWeenies.empty())
|
|
// outOfIds = true;
|
|
|
|
//startupRange.clear();
|
|
|
|
//m_bLoadingState = false;
|
|
//queryInProgress = false;
|
|
}
|
|
else
|
|
m_dwHintDynamicGUID = g_pDBIO->GetHighestWeenieID(IDRANGESTART, IDRANGEEND);
|
|
}
|
|
|
|
DWORD CObjectIDGenerator::GenerateGUID(eGUIDClass type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case eDynamicGUID:
|
|
{
|
|
|
|
DWORD result = 0;
|
|
|
|
if (!g_pConfig->UseIncrementalID())
|
|
{
|
|
if (outOfIds || listOfIdsForWeenies.empty())
|
|
{
|
|
SERVER_ERROR << "Dynamic GUID overflow!";
|
|
return 0;
|
|
}
|
|
|
|
{
|
|
std::scoped_lock lock(m_lock);
|
|
result = listOfIdsForWeenies.front();
|
|
listOfIdsForWeenies.pop();
|
|
}
|
|
|
|
if (!m_bLoadingState /*&& !queryInProgress*/ && listOfIdsForWeenies.size() < IDQUEUEMIN)
|
|
{
|
|
m_bLoadingState = true;
|
|
LoadState();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_dwHintDynamicGUID >= IDRANGEEND)
|
|
{
|
|
SERVER_ERROR << "Dynamic GUID overflow!";
|
|
return 0;
|
|
}
|
|
result = ++m_dwHintDynamicGUID;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
case eEphemeral:
|
|
{
|
|
m_ephemeral &= IDEPHEMERALMASK;
|
|
return m_ephemeral++;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CObjectIDGenerator::SaveRangeStart()
|
|
{
|
|
BinaryWriter banData;
|
|
banData.Write<DWORD>(m_dwHintDynamicGUID);
|
|
if (!g_pConfig->UseIncrementalID())
|
|
{
|
|
g_pDBIO->CreateOrUpdateGlobalData(DBIO_GLOBAL_ID_RANGE_START, banData.GetData(), banData.GetSize());
|
|
}
|
|
}
|
|
|
|
void CObjectIDGenerator::LoadRangeStart()
|
|
{
|
|
void *data = NULL;
|
|
DWORD length = 0;
|
|
if (!g_pConfig->UseIncrementalID())
|
|
{
|
|
g_pDBIO->GetGlobalData(DBIO_GLOBAL_ID_RANGE_START, &data, &length);
|
|
BinaryReader reader(data, length);
|
|
m_dwHintDynamicGUID = reader.ReadDWORD() + IDQUEUEMIN;
|
|
if (m_dwHintDynamicGUID < IDRANGESTART)
|
|
m_dwHintDynamicGUID = IDRANGESTART;
|
|
|
|
AvailableIdQuery query(m_dwHintDynamicGUID, IDQUEUEMAX, listOfIdsForWeenies, m_lock, m_bLoadingState);
|
|
query.PerformQuery((MYSQL*)g_pDB2->GetInternalConnection());
|
|
}
|
|
}
|
|
|
|
bool AvailableIdQuery::PerformQuery(MYSQL *c)
|
|
{
|
|
if (!c)
|
|
return false;
|
|
|
|
MYSQL_STMT *statement = mysql_stmt_init(c);
|
|
bool failed = false;
|
|
|
|
if (statement)
|
|
{
|
|
std::string query = "SELECT unused FROM idranges WHERE unused > ? limit 250000" ;
|
|
mysql_stmt_prepare(statement, query.c_str(), query.length());
|
|
|
|
MYSQL_BIND params = { 0 };
|
|
params.buffer = &m_start;
|
|
params.buffer_length = sizeof(uint32_t);
|
|
params.buffer_type = MYSQL_TYPE_LONG;
|
|
params.is_unsigned = true;
|
|
|
|
failed = mysql_stmt_bind_param(statement, ¶ms);
|
|
if (!failed)
|
|
{
|
|
failed = mysql_stmt_execute(statement);
|
|
if (!failed)
|
|
{
|
|
uint32_t value = 0;
|
|
MYSQL_BIND result = { 0 };
|
|
result.buffer = &value;
|
|
result.buffer_length = sizeof(uint32_t);
|
|
result.buffer_type = MYSQL_TYPE_LONG;
|
|
result.is_unsigned = true;
|
|
|
|
failed = mysql_stmt_bind_result(statement, &result);
|
|
bool done = failed;
|
|
|
|
while (!done)
|
|
{
|
|
std::scoped_lock lock(m_lock);
|
|
|
|
for (int i = 0; i < 5000 && !failed; i++)
|
|
{
|
|
if (!(done = mysql_stmt_fetch(statement)))
|
|
{
|
|
m_queue.push(value);
|
|
m_start = value;
|
|
}
|
|
}
|
|
std::this_thread::yield();
|
|
}
|
|
}
|
|
}
|
|
|
|
mysql_stmt_close(statement);
|
|
}
|
|
|
|
m_busy = false;
|
|
|
|
if (failed)
|
|
SERVER_ERROR << "Error in AvailableIdQuery::PerformQuery: " << mysql_error(c);
|
|
|
|
return !failed;
|
|
|
|
}
|