You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
5.6 KiB
192 lines
5.6 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "MySqlDatabase.h" |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CMySqlDatabase::CMySqlDatabase() |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Destructor |
|
// blocks until db process thread has stopped |
|
//----------------------------------------------------------------------------- |
|
CMySqlDatabase::~CMySqlDatabase() |
|
{ |
|
// flag the thread to stop |
|
m_bRunThread = false; |
|
|
|
// pulse the thread to make it run |
|
::SetEvent(m_hEvent); |
|
|
|
// make sure it's done |
|
::EnterCriticalSection(&m_csThread); |
|
::LeaveCriticalSection(&m_csThread); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Thread access function |
|
//----------------------------------------------------------------------------- |
|
static DWORD WINAPI staticThreadFunc(void *param) |
|
{ |
|
((CMySqlDatabase *)param)->RunThread(); |
|
return 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Establishes connection to the database and sets up this object to handle db command |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CMySqlDatabase::Initialize() |
|
{ |
|
// prepare critical sections |
|
//!! need to download SDK and replace these with InitializeCriticalSectionAndSpinCount() calls |
|
::InitializeCriticalSection(&m_csThread); |
|
::InitializeCriticalSection(&m_csInQueue); |
|
::InitializeCriticalSection(&m_csOutQueue); |
|
::InitializeCriticalSection(&m_csDBAccess); |
|
|
|
// initialize wait calls |
|
m_hEvent = ::CreateEvent(NULL, false, true, NULL); |
|
|
|
// start the DB-access thread |
|
m_bRunThread = true; |
|
|
|
unsigned long threadID; |
|
::CreateThread(NULL, 0, staticThreadFunc, this, 0, &threadID); |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Main thread loop |
|
//----------------------------------------------------------------------------- |
|
void CMySqlDatabase::RunThread() |
|
{ |
|
::EnterCriticalSection(&m_csThread); |
|
while (m_bRunThread) |
|
{ |
|
if (m_InQueue.Count() > 0) |
|
{ |
|
// get a dispatched DB request |
|
::EnterCriticalSection(&m_csInQueue); |
|
|
|
// pop the front of the queue |
|
int headIndex = m_InQueue.Head(); |
|
msg_t msg = m_InQueue[headIndex]; |
|
m_InQueue.Remove(headIndex); |
|
|
|
::LeaveCriticalSection(&m_csInQueue); |
|
|
|
::EnterCriticalSection(&m_csDBAccess); |
|
|
|
// run sqldb command |
|
msg.result = msg.cmd->RunCommand(); |
|
|
|
::LeaveCriticalSection(&m_csDBAccess); |
|
|
|
if (msg.replyTarget) |
|
{ |
|
// put the results in the outgoing queue |
|
::EnterCriticalSection(&m_csOutQueue); |
|
m_OutQueue.AddToTail(msg); |
|
::LeaveCriticalSection(&m_csOutQueue); |
|
|
|
// wake up out queue |
|
msg.replyTarget->WakeUp(); |
|
} |
|
else |
|
{ |
|
// there is no return data from the call, so kill the object now |
|
msg.cmd->deleteThis(); |
|
} |
|
} |
|
else |
|
{ |
|
// nothing in incoming queue, so wait until we get the signal |
|
::WaitForSingleObject(m_hEvent, INFINITE); |
|
} |
|
|
|
// check the size of the outqueue; if it's getting too big, sleep to let the main thread catch up |
|
if (m_OutQueue.Count() > 50) |
|
{ |
|
::Sleep(2); |
|
} |
|
} |
|
::LeaveCriticalSection(&m_csThread); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Adds a database command to the queue, and wakes the db thread |
|
//----------------------------------------------------------------------------- |
|
void CMySqlDatabase::AddCommandToQueue(ISQLDBCommand *cmd, ISQLDBReplyTarget *replyTarget, int returnState) |
|
{ |
|
::EnterCriticalSection(&m_csInQueue); |
|
|
|
// add to the queue |
|
msg_t msg = { cmd, replyTarget, 0, returnState }; |
|
m_InQueue.AddToTail(msg); |
|
|
|
::LeaveCriticalSection(&m_csInQueue); |
|
|
|
// signal the thread to start running |
|
::SetEvent(m_hEvent); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Dispatches responses to SQLDB queries |
|
//----------------------------------------------------------------------------- |
|
bool CMySqlDatabase::RunFrame() |
|
{ |
|
bool doneWork = false; |
|
|
|
while (m_OutQueue.Count() > 0) |
|
{ |
|
::EnterCriticalSection(&m_csOutQueue); |
|
|
|
// pop the first item in the queue |
|
int headIndex = m_OutQueue.Head(); |
|
msg_t msg = m_OutQueue[headIndex]; |
|
m_OutQueue.Remove(headIndex); |
|
|
|
::LeaveCriticalSection(&m_csOutQueue); |
|
|
|
// run result |
|
if (msg.replyTarget) |
|
{ |
|
msg.replyTarget->SQLDBResponse(msg.cmd->GetID(), msg.returnState, msg.result, msg.cmd->GetReturnData()); |
|
|
|
// kill command |
|
// it would be a good optimization to be able to reuse these |
|
msg.cmd->deleteThis(); |
|
} |
|
|
|
doneWork = true; |
|
} |
|
|
|
return doneWork; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: load info - returns the number of sql db queries waiting to be processed |
|
//----------------------------------------------------------------------------- |
|
int CMySqlDatabase::QueriesInOutQueue() |
|
{ |
|
// the queue names are from the DB point of view, not the server - thus the reversal |
|
return m_InQueue.Count(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: number of queries finished processing, waiting to be responded to |
|
//----------------------------------------------------------------------------- |
|
int CMySqlDatabase::QueriesInFinishedQueue() |
|
{ |
|
return m_OutQueue.Count(); |
|
}
|
|
|