aboutsummaryrefslogtreecommitdiff
path: root/mp/src/utils/common/MySqlDatabase.cpp
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /mp/src/utils/common/MySqlDatabase.cpp
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/utils/common/MySqlDatabase.cpp')
-rw-r--r--mp/src/utils/common/MySqlDatabase.cpp192
1 files changed, 192 insertions, 0 deletions
diff --git a/mp/src/utils/common/MySqlDatabase.cpp b/mp/src/utils/common/MySqlDatabase.cpp
new file mode 100644
index 00000000..46d8a4b9
--- /dev/null
+++ b/mp/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();
+}