MysqlConnPool.cpp 7.5 KB

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