MysqlConnPool.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include "StdAfx.h"
  2. #include "MysqlConnPool.h"
  3. CMysqlConnPool::CMysqlConnPool()
  4. {
  5. m_nMinCount = 3;//3
  6. m_nMaxCount = 30;
  7. m_bNeedStop = FALSE;
  8. m_bNeedConnection = FALSE;
  9. m_hMaintanceThread = INVALID_HANDLE_VALUE;
  10. m_hMaintanceThread = CreateEvent(NULL, TRUE, FALSE, _T("DataConnPool"));
  11. // 划定临界区
  12. InitializeCriticalSectionAndSpinCount(&m_csIdleConnList, MAXCRITICALSECTIONSPINCOUNT);
  13. InitializeCriticalSectionAndSpinCount(&m_csBusyConnList, MAXCRITICALSECTIONSPINCOUNT);
  14. }
  15. CMysqlConnPool::~CMysqlConnPool()
  16. {
  17. m_hMaintanceThread = INVALID_HANDLE_VALUE;
  18. m_bNeedStop = TRUE;
  19. CloseHandle(m_hHaveData);
  20. CloseHandle(m_hMaintanceThread);
  21. CloseAllConn();
  22. DeleteCriticalSection(&m_csIdleConnList);
  23. DeleteCriticalSection(&m_csBusyConnList);
  24. }
  25. int CMysqlConnPool::InitAllConn()
  26. {
  27. CloseAllConn();
  28. // 按照最小数量创建
  29. //CMysqlConn * pMysqlConn = NULL;
  30. int nCount = 0;
  31. for(unsigned int i = 0; i < m_nMinCount; i++)
  32. {
  33. nCount = InitNewConn();
  34. }
  35. // 创建守护线程,用来进行维护工作
  36. if(INVALID_HANDLE_VALUE == m_hMaintanceThread)
  37. {
  38. m_hMaintanceThread = CreateThread(NULL, NULL, thread_run, (LPVOID)this, 0, NULL);
  39. }
  40. return nCount;
  41. }
  42. void CMysqlConnPool::CloseAllConn()
  43. {
  44. // 销毁数据连接,使用大锁
  45. EnterCriticalSection(&m_csIdleConnList);
  46. DBConnectList::iterator itIdle = m_listIdleConnection.begin();
  47. for (; itIdle != m_listIdleConnection.end();)
  48. {
  49. if(NULL != (*itIdle)){
  50. (*itIdle)->Close();
  51. delete (*itIdle);
  52. }
  53. itIdle = m_listIdleConnection.erase(itIdle);
  54. }
  55. LeaveCriticalSection(&m_csIdleConnList);
  56. // 使用中的链接
  57. EnterCriticalSection(&m_csBusyConnList);
  58. DBConnectList::iterator itBusy = m_listBusyConnection.begin();
  59. for(; itBusy != m_listBusyConnection.end();)
  60. {
  61. if(NULL != (*itBusy))
  62. {
  63. (*itBusy)->Close();
  64. delete(*itBusy);
  65. }
  66. //itBusy = m_listBusyConnection.erase(itBusy);
  67. m_listBusyConnection.erase(itBusy++);
  68. }
  69. LeaveCriticalSection(&m_csBusyConnList);
  70. }
  71. CMysqlConn* CMysqlConnPool::GetNewConn()
  72. {
  73. CMysqlConn * pDBEngine = NULL;
  74. // 做一个循环,反复尝试五次取连接,每次间隔1秒钟
  75. int nTimes = 0;
  76. while ((m_listIdleConnection.size() <= 0) && (nTimes < 5))
  77. {
  78. Sleep(1000);
  79. nTimes++;
  80. }
  81. if (5 == nTimes)
  82. {
  83. // 这样狼狈的进来肯定是没有可用连接了,记录日志退出
  84. // g_pSvrLog->AddRunLog(LL_ERROR, _T("Waiting for a connection for a long time, but failed."));
  85. return pDBEngine;
  86. }
  87. // 从空闲队列中取出,并且加入到使用队列中
  88. EnterCriticalSection(&m_csIdleConnList);
  89. if (m_listIdleConnection.size() > 0)
  90. {
  91. pDBEngine = m_listIdleConnection.front();
  92. m_listIdleConnection.pop_front();
  93. // 加入使用的连接队列
  94. EnterCriticalSection(&m_csBusyConnList);
  95. m_listBusyConnection.push_back(pDBEngine);
  96. LeaveCriticalSection(&m_csBusyConnList);
  97. }
  98. LeaveCriticalSection(&m_csIdleConnList);
  99. if (m_listIdleConnection.size() <= 1)
  100. {
  101. // 剩余空闲连接的数目小于等于1个时候需要检查开始创建
  102. if ((m_listIdleConnection.size() + m_listBusyConnection.size()) < m_nMaxCount)
  103. {
  104. // 还小于最大限制,可以创建
  105. SetEvent(m_hHaveData);
  106. m_bNeedConnection = TRUE;
  107. }
  108. else
  109. {
  110. // 超出限制了,做个记录吧
  111. //g_pSvrLog->AddRunLog(LL_ERROR, _T("Database connection reached max count."));
  112. }
  113. }
  114. return pDBEngine;
  115. }
  116. int CMysqlConnPool::RestoreConn( CMysqlConn* pDBEngine )
  117. {
  118. if (NULL != pDBEngine)
  119. {
  120. // 从使用中的队列取出
  121. EnterCriticalSection(&m_csBusyConnList);
  122. m_listBusyConnection.remove(pDBEngine);
  123. LeaveCriticalSection(&m_csBusyConnList);
  124. // 加入到空闲队列中
  125. EnterCriticalSection(&m_csIdleConnList);
  126. m_listIdleConnection.push_back(pDBEngine);
  127. LeaveCriticalSection(&m_csIdleConnList);
  128. }
  129. EnterCriticalSection(&m_csIdleConnList);
  130. int nCount = m_listIdleConnection.size();
  131. LeaveCriticalSection(&m_csIdleConnList);
  132. return nCount;
  133. }
  134. void CMysqlConnPool::Init(const char* szOption, const char *szHost, const char *szUser, const char *szPwd, const char *szDbName, unsigned int nPort, const char * szUnixSocket, unsigned long nClientFlag )
  135. {
  136. m_strOption = szOption;
  137. m_strHost = szHost;
  138. m_strUser = szUser;
  139. m_strPwd = szPwd;
  140. m_strDbName = szDbName;
  141. m_nPort = nPort;
  142. if(szUnixSocket != NULL){
  143. m_strUnixSocket = szUnixSocket;
  144. }
  145. m_nClientFlag = nClientFlag;
  146. }
  147. int CMysqlConnPool::InitNewConn()
  148. {
  149. bool bSuccess = false;
  150. CMysqlConn * pDBEngine = new CMysqlConn(m_strOption.c_str(), m_strHost.c_str(), m_strUser.c_str(), m_strPwd.c_str(), m_strDbName.c_str(),
  151. m_nPort, m_strUnixSocket.c_str(), m_nClientFlag, bSuccess);
  152. if (bSuccess)
  153. {
  154. m_bNeedConnection = FALSE;
  155. return RestoreConn(pDBEngine);
  156. }
  157. else
  158. {
  159. delete pDBEngine;
  160. return m_listIdleConnection.size();
  161. }
  162. }
  163. void CMysqlConnPool::CloseConn( CMysqlConn* pDBEngine )
  164. {
  165. pDBEngine->Close();
  166. // 从空闲队列将其删除
  167. EnterCriticalSection(&m_csIdleConnList);
  168. m_listIdleConnection.remove(pDBEngine);
  169. LeaveCriticalSection(&m_csIdleConnList);
  170. }
  171. void CMysqlConnPool::StopThread()
  172. {
  173. m_bNeedStop = TRUE;
  174. // 因为线程是无限制等待信号的,所以这里先把标志位置为停止,然后发信号让线程检测
  175. SetEvent(m_hHaveData);
  176. // 等待退出
  177. WaitForSingleObject(m_hMaintanceThread, INFINITE);
  178. CloseHandle(m_hMaintanceThread);
  179. }
  180. BOOL CMysqlConnPool::IsNeedStop()
  181. {
  182. return m_bNeedStop;
  183. }
  184. BOOL CMysqlConnPool::IsNeedConnection()
  185. {
  186. return m_bNeedConnection;
  187. }
  188. DWORD WINAPI CMysqlConnPool::thread_run( LPVOID pdata )
  189. {
  190. CMysqlConnPool * pConPool = (CMysqlConnPool *) pdata;
  191. while (!pConPool->IsNeedStop())
  192. {
  193. // 设置事件为无信号, 并且无限制等待
  194. ResetEvent(pConPool->m_hHaveData);
  195. WaitForSingleObject(pConPool->m_hHaveData, INFINITE);
  196. if (pConPool->IsNeedConnection())
  197. {
  198. // g_pSvrLog->AddRunLog(LL_DEBUG, _T("Create a new DB connection."));
  199. pConPool->InitNewConn();
  200. }
  201. }
  202. return 0;
  203. }
  204. CMysqlConn::CMysqlConn( const char *option, const char *host, const char *user, const char *password,
  205. const char* dbname, unsigned int port, const char *unix_socket, unsigned long clientflag, bool &state )
  206. {
  207. m_option = option;
  208. m_host = host;
  209. m_user = user;
  210. m_pwd = password;
  211. m_db = dbname;
  212. m_port = port;
  213. m_unix_socket = unix_socket;
  214. m_clientflag = clientflag;
  215. m_bOpen = false;
  216. m_pConn = mysql_init(NULL);
  217. if( 0 == SetOption())
  218. {
  219. if(0 == Open())
  220. {
  221. state = true;
  222. }else{
  223. state = false;
  224. }
  225. }else{
  226. state = false;
  227. }
  228. }
  229. CMysqlConn::~CMysqlConn()
  230. {
  231. Close();
  232. }
  233. int CMysqlConn::SetOption()
  234. {
  235. if(mysql_options(m_pConn, MYSQL_SET_CHARSET_NAME, m_option))
  236. return 1;
  237. return 0;
  238. }
  239. int CMysqlConn::Open()
  240. {
  241. HRESULT hr = ::CoInitialize(NULL);
  242. if(FAILED(hr))
  243. return -1;
  244. m_clientflag |= CLIENT_MULTI_STATEMENTS;
  245. if(!mysql_real_connect(m_pConn, m_host, m_user, m_pwd, m_db, m_port, m_unix_socket, m_clientflag))
  246. return 1;
  247. m_bOpen = true;
  248. return 0;
  249. }
  250. int CMysqlConn::Close()
  251. {
  252. if (m_bOpen)
  253. {
  254. mysql_close(m_pConn);
  255. ::CoUninitialize();
  256. m_bOpen = false;
  257. }
  258. return 0;
  259. }
  260. bool CMysqlConn::IsOpen() const
  261. {
  262. return m_bOpen;
  263. }
  264. MYSQL_RES * CMysqlConn::Execute( const char * strSQL, int &err)
  265. {
  266. if(strSQL == "") return NULL;
  267. MYSQL_RES * pRes;
  268. int _error = mysql_query(m_pConn, strSQL);
  269. err = _error;
  270. if(_error){
  271. return NULL;
  272. }
  273. pRes = mysql_use_result(m_pConn);
  274. return pRes;
  275. }
  276. void CMysqlConn::MultiExecute( const char * strSQL, int &err)
  277. {
  278. if(strSQL == "")
  279. err = 0;
  280. MYSQL_RES * pRes;
  281. int _error = mysql_query(m_pConn, strSQL);
  282. //每条语句对应一个pRes,需要释放每一个结果集;避免数据错乱
  283. //不然通过mysql_error()会得知是Commands out of sync; you can't run this command now错误
  284. do
  285. {
  286. pRes = mysql_use_result(m_pConn);
  287. mysql_free_result(pRes);
  288. } while (!mysql_next_result(m_pConn));
  289. /*if (_error != 0)
  290. {
  291. CString str = _T("");
  292. str = mysql_error(m_pConn);
  293. TRACE(str);
  294. }*/
  295. }