Counter Strike : Global Offensive Source Code
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

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "MySqlDatabase.h"
  8. //-----------------------------------------------------------------------------
  9. // Purpose: Constructor
  10. //-----------------------------------------------------------------------------
  11. CMySqlDatabase::CMySqlDatabase()
  12. {
  13. }
  14. //-----------------------------------------------------------------------------
  15. // Purpose: Destructor
  16. // blocks until db process thread has stopped
  17. //-----------------------------------------------------------------------------
  18. CMySqlDatabase::~CMySqlDatabase()
  19. {
  20. // flag the thread to stop
  21. m_bRunThread = false;
  22. // pulse the thread to make it run
  23. ::SetEvent(m_hEvent);
  24. // make sure it's done
  25. ::EnterCriticalSection(&m_csThread);
  26. ::LeaveCriticalSection(&m_csThread);
  27. }
  28. //-----------------------------------------------------------------------------
  29. // Purpose: Thread access function
  30. //-----------------------------------------------------------------------------
  31. static DWORD WINAPI staticThreadFunc(void *param)
  32. {
  33. ((CMySqlDatabase *)param)->RunThread();
  34. return 0;
  35. }
  36. //-----------------------------------------------------------------------------
  37. // Purpose: Establishes connection to the database and sets up this object to handle db command
  38. // Output : Returns true on success, false on failure.
  39. //-----------------------------------------------------------------------------
  40. bool CMySqlDatabase::Initialize()
  41. {
  42. // prepare critical sections
  43. //!! need to download SDK and replace these with InitializeCriticalSectionAndSpinCount() calls
  44. ::InitializeCriticalSection(&m_csThread);
  45. ::InitializeCriticalSection(&m_csInQueue);
  46. ::InitializeCriticalSection(&m_csOutQueue);
  47. ::InitializeCriticalSection(&m_csDBAccess);
  48. // initialize wait calls
  49. m_hEvent = ::CreateEvent(NULL, false, true, NULL);
  50. // start the DB-access thread
  51. m_bRunThread = true;
  52. unsigned long threadID;
  53. ::CreateThread(NULL, 0, staticThreadFunc, this, 0, &threadID);
  54. return true;
  55. }
  56. //-----------------------------------------------------------------------------
  57. // Purpose: Main thread loop
  58. //-----------------------------------------------------------------------------
  59. void CMySqlDatabase::RunThread()
  60. {
  61. ::EnterCriticalSection(&m_csThread);
  62. while (m_bRunThread)
  63. {
  64. if (m_InQueue.Count() > 0)
  65. {
  66. // get a dispatched DB request
  67. ::EnterCriticalSection(&m_csInQueue);
  68. // pop the front of the queue
  69. int headIndex = m_InQueue.Head();
  70. msg_t msg = m_InQueue[headIndex];
  71. m_InQueue.Remove(headIndex);
  72. ::LeaveCriticalSection(&m_csInQueue);
  73. ::EnterCriticalSection(&m_csDBAccess);
  74. // run sqldb command
  75. msg.result = msg.cmd->RunCommand();
  76. ::LeaveCriticalSection(&m_csDBAccess);
  77. if (msg.replyTarget)
  78. {
  79. // put the results in the outgoing queue
  80. ::EnterCriticalSection(&m_csOutQueue);
  81. m_OutQueue.AddToTail(msg);
  82. ::LeaveCriticalSection(&m_csOutQueue);
  83. // wake up out queue
  84. msg.replyTarget->WakeUp();
  85. }
  86. else
  87. {
  88. // there is no return data from the call, so kill the object now
  89. msg.cmd->deleteThis();
  90. }
  91. }
  92. else
  93. {
  94. // nothing in incoming queue, so wait until we get the signal
  95. ::WaitForSingleObject(m_hEvent, INFINITE);
  96. }
  97. // check the size of the outqueue; if it's getting too big, sleep to let the main thread catch up
  98. if (m_OutQueue.Count() > 50)
  99. {
  100. ::Sleep(2);
  101. }
  102. }
  103. ::LeaveCriticalSection(&m_csThread);
  104. }
  105. //-----------------------------------------------------------------------------
  106. // Purpose: Adds a database command to the queue, and wakes the db thread
  107. //-----------------------------------------------------------------------------
  108. void CMySqlDatabase::AddCommandToQueue(ISQLDBCommand *cmd, ISQLDBReplyTarget *replyTarget, int returnState)
  109. {
  110. ::EnterCriticalSection(&m_csInQueue);
  111. // add to the queue
  112. msg_t msg = { cmd, replyTarget, 0, returnState };
  113. m_InQueue.AddToTail(msg);
  114. ::LeaveCriticalSection(&m_csInQueue);
  115. // signal the thread to start running
  116. ::SetEvent(m_hEvent);
  117. }
  118. //-----------------------------------------------------------------------------
  119. // Purpose: Dispatches responses to SQLDB queries
  120. //-----------------------------------------------------------------------------
  121. bool CMySqlDatabase::RunFrame()
  122. {
  123. bool doneWork = false;
  124. while (m_OutQueue.Count() > 0)
  125. {
  126. ::EnterCriticalSection(&m_csOutQueue);
  127. // pop the first item in the queue
  128. int headIndex = m_OutQueue.Head();
  129. msg_t msg = m_OutQueue[headIndex];
  130. m_OutQueue.Remove(headIndex);
  131. ::LeaveCriticalSection(&m_csOutQueue);
  132. // run result
  133. if (msg.replyTarget)
  134. {
  135. msg.replyTarget->SQLDBResponse(msg.cmd->GetID(), msg.returnState, msg.result, msg.cmd->GetReturnData());
  136. // kill command
  137. // it would be a good optimization to be able to reuse these
  138. msg.cmd->deleteThis();
  139. }
  140. doneWork = true;
  141. }
  142. return doneWork;
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Purpose: load info - returns the number of sql db queries waiting to be processed
  146. //-----------------------------------------------------------------------------
  147. int CMySqlDatabase::QueriesInOutQueue()
  148. {
  149. // the queue names are from the DB point of view, not the server - thus the reversal
  150. return m_InQueue.Count();
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Purpose: number of queries finished processing, waiting to be responded to
  154. //-----------------------------------------------------------------------------
  155. int CMySqlDatabase::QueriesInFinishedQueue()
  156. {
  157. return m_OutQueue.Count();
  158. }