MysqlConnPool.cpp 6.7 KB

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