MysqlConnPool.cpp 9.2 KB

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