From 39ed87570bdb2f86969d4be821c94b722dc71179 Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Wed, 26 Jun 2013 15:22:04 -0700 Subject: First version of the SOurce SDK 2013 --- sp/src/utils/common/MySqlDatabase.cpp | 192 ++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 sp/src/utils/common/MySqlDatabase.cpp (limited to 'sp/src/utils/common/MySqlDatabase.cpp') diff --git a/sp/src/utils/common/MySqlDatabase.cpp b/sp/src/utils/common/MySqlDatabase.cpp new file mode 100644 index 00000000..46d8a4b9 --- /dev/null +++ b/sp/src/utils/common/MySqlDatabase.cpp @@ -0,0 +1,192 @@ +//========= 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(); +} -- cgit v1.2.3