DBConnPool.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. // DBConnPool.cpp: implementation of the DBConnPool class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "DBConnPool.h"
  6. DBConnect * pDBConn = NULL;
  7. void InitDBIterface(LPCSTR strDstAddress, LPCSTR strUsername, LPCSTR strPassword, LPCSTR strDBName,int minConn,int maxConn)
  8. {
  9. DBConnPool::Instanse()->SetDBInfo(strDstAddress,strUsername,strPassword,strDBName,minConn,maxConn);
  10. int cout = DBConnPool::Instanse()->InitializeAllDBConnections();
  11. }
  12. DBConnect * GetAConnect()
  13. {
  14. DBConnGuard oConnGuard(pDBConn);
  15. return pDBConn;
  16. }
  17. //////////////////////////////////////DBConnect/////////////////////////
  18. DBConnect::DBConnect(LPCTSTR strDstAddress, LPCTSTR strUsername, LPCTSTR strPassword, LPCTSTR strDBName,BOOL &state)
  19. {
  20. m_bDBOpen = false;
  21. if (0 == Open(strDstAddress,strUsername,strPassword,strDBName))
  22. {
  23. state =true;
  24. }
  25. else
  26. {
  27. state = false;
  28. }
  29. }
  30. DBConnect::~DBConnect()
  31. {
  32. Close();
  33. }
  34. int DBConnect::Open(LPCTSTR strDstAddress, LPCTSTR strUsername, LPCTSTR strPassword, LPCTSTR strDBName)
  35. {
  36. _strDstAddress = strDstAddress;
  37. _strDBName = strDBName;
  38. _strUsername = strUsername;
  39. _strPassword = strPassword;
  40. HRESULT comhr = ::CoInitialize(NULL);
  41. if (FAILED(comhr))
  42. {
  43. return -1;
  44. }
  45. HRESULT hr = _connection_ptr.CreateInstance(__uuidof(Connection));
  46. if (FAILED(hr))
  47. {
  48. return -1;
  49. }
  50. char szSQL[SQL_BUFFER_LEN] = {0};
  51. memset(szSQL, 0, SQL_BUFFER_LEN);
  52. sprintf(szSQL, "Driver=SQL Server;Server=%s;DATABASE=%s", strDstAddress, strDBName);
  53. //sprintf(szSQL, _T("Provider=sqloledb;Data Source=%s,%s;Initial Catalog=%s"), strDstAddress, strDBName);
  54. try
  55. {
  56. // 连接到服务器上数据库
  57. _connection_ptr->Open(szSQL, strUsername, strPassword,adModeUnknown) ;
  58. if (FAILED(hr))
  59. return -1;
  60. }
  61. catch (_com_error &err)
  62. {
  63. TRACE(_T("数据库操作失败! 错误信息:%s, 文件:%s, 行:%d.\n"), err.ErrorMessage(), __FILE__, __LINE__);
  64. return -1;
  65. }
  66. m_bDBOpen = TRUE;
  67. return 0;
  68. }
  69. int DBConnect::Close()
  70. {
  71. if (m_bDBOpen)
  72. {
  73. HRESULT hr =_connection_ptr->Close();
  74. if (FAILED(hr))
  75. {
  76. return -1;
  77. }
  78. ::CoUninitialize();
  79. m_bDBOpen = FALSE;
  80. }
  81. return 0;
  82. }
  83. int DBConnect::GetSubmitInfo(vector<SOAP_SUBMIT_SMS> &vecsoapSms)
  84. {
  85. //*此接口为实际访问数据库的接口,和数据库字段相关,数据库为SQLSERVER
  86. if (!m_bDBOpen)
  87. {
  88. return -1;
  89. }
  90. // 创建Command对象
  91. _CommandPtr cmd;
  92. HRESULT hr = cmd.CreateInstance(__uuidof(Command));
  93. if (FAILED(hr))
  94. {
  95. return -1;
  96. }
  97. string strSql = "exec SP_SMS_GETSUBMIT";
  98. cmd->ActiveConnection = _connection_ptr;
  99. cmd->CommandText = _bstr_t(strSql.c_str());
  100. cmd->CommandType = adCmdText;
  101. try
  102. {
  103. _RecordsetPtr rs = cmd->Execute(NULL, NULL, adCmdUnknown);
  104. if (FAILED(hr))
  105. {
  106. return -1;
  107. }
  108. while (!rs->ADOEOF)
  109. {
  110. _variant_t id;
  111. _variant_t recverid;
  112. _variant_t recvertel;
  113. _variant_t messagecontent;
  114. _variant_t recverphonetype;
  115. _variant_t inout;
  116. _variant_t sendtime;
  117. _variant_t cardtime;
  118. _variant_t schoolid;
  119. _variant_t classid;
  120. _variant_t rfidno;
  121. id = rs->GetCollect("id");
  122. recverid = rs->GetCollect("recverid");
  123. recvertel = rs->GetCollect("recvertel");
  124. messagecontent = rs->GetCollect("messagecontent");
  125. recverphonetype = rs->GetCollect("recverphonetype");
  126. inout = rs->GetCollect("inout");
  127. sendtime = rs->GetCollect("sendtime");
  128. cardtime = rs->GetCollect("cardtime");
  129. schoolid = rs->GetCollect("schoolid");
  130. classid = rs->GetCollect("classid");
  131. rfidno = rs->GetCollect("rfidno");
  132. SOAP_SUBMIT_SMS submitsms;
  133. submitsms.id = (int)(long)id;
  134. VarientToString(recverid, submitsms.recverid);
  135. VarientToString(recvertel, submitsms.recvertel);
  136. VarientToString(messagecontent, submitsms.messagecontent);
  137. VarientToString(recverphonetype, submitsms.recverphonetype);
  138. submitsms.inout = (int)(long)inout;
  139. VarientToString(sendtime, submitsms.sendtime);
  140. VarientToString(cardtime, submitsms.cardtime);
  141. VarientToString(rfidno, submitsms.rfidno);
  142. submitsms.schoolid = (int)(long)schoolid;
  143. submitsms.classid = (int)(long)classid;
  144. vecsoapSms.push_back(submitsms);
  145. rs->MoveNext() ;
  146. }
  147. }
  148. catch (_com_error &err)
  149. {
  150. TRACE(_T("数据库操作失败! 错误信息:%s, 文件:%s, 行:%d.\n"), err.ErrorMessage(), __FILE__, __LINE__);
  151. return -1;
  152. }
  153. return 0;
  154. }
  155. int DBConnect::InsertHistory(int id)
  156. {
  157. if (!m_bDBOpen)
  158. {
  159. return -1;
  160. }
  161. // 创建Command对象
  162. _CommandPtr cmd;
  163. HRESULT hr = cmd.CreateInstance(__uuidof(Command));
  164. if (FAILED(hr))
  165. {
  166. return -1;
  167. }
  168. char szSQL[SQL_BUFFER_LEN] = {0};
  169. sprintf(szSQL, "exec SP_SMS_SUBMITRESULT %d", id);
  170. try
  171. {
  172. cmd->ActiveConnection = _connection_ptr;
  173. cmd->CommandText = _bstr_t(szSQL);
  174. cmd->CommandType = adCmdText;
  175. cmd->Execute(NULL, NULL, adCmdUnknown);
  176. }
  177. catch (_com_error &err)
  178. {
  179. TRACE(_T("数据库操作失败! 错误信息:%s, 文件:%s, 行:%d.\n"), err.ErrorMessage(), __FILE__, __LINE__);
  180. return -1;
  181. }
  182. return 0;
  183. }
  184. void DBConnect::VarientToString(_variant_t var, string& str)
  185. {
  186. if (VT_NULL == var.vt)
  187. {
  188. str = "";
  189. }
  190. else
  191. {
  192. str = (char*)_bstr_t(var);
  193. }
  194. }
  195. //////////////////////////////////////End//////////////////////////////
  196. //////////////////////////////////////////////////////////////////////
  197. // Construction/Destruction
  198. //////////////////////////////////////////////////////////////////////
  199. DBConnPool* DBConnPool::m_pInstanse = NULL;
  200. DBConnPool::DBConnPool()
  201. {
  202. m_bNeedStop = FALSE;
  203. m_bNeedConnection = FALSE;
  204. m_hMaintanceThread = INVALID_HANDLE_VALUE;
  205. // 线程控制
  206. m_hHaveData = CreateEvent (NULL, TRUE, FALSE, _T("DataConnPool"));
  207. InitializeCriticalSection(&m_csIdleConnList);
  208. InitializeCriticalSection(&m_csBusyConnList);
  209. }
  210. void DBConnPool::SetDBInfo(LPCSTR strDstAddress, LPCSTR strUsername, LPCSTR strPassword, LPCSTR strDBName,int minConn,int maxConn)
  211. {
  212. _strDBName = strDBName;
  213. _strDstAddress = strDstAddress;
  214. _strPassword = strPassword;
  215. _strUsername = strUsername;
  216. m_nMaxCount = maxConn;
  217. m_nMinCount = minConn;
  218. }
  219. DBConnPool::~DBConnPool()
  220. {
  221. m_hMaintanceThread = INVALID_HANDLE_VALUE;
  222. m_bNeedStop = TRUE;
  223. CloseHandle(m_hHaveData);
  224. CloseHandle(m_hMaintanceThread);
  225. DeleteCriticalSection(&m_csIdleConnList);
  226. DeleteCriticalSection(&m_csBusyConnList);
  227. }
  228. DBConnPool *DBConnPool::Instanse()
  229. {
  230. if (NULL == m_pInstanse)
  231. {
  232. m_pInstanse = new DBConnPool();
  233. }
  234. return m_pInstanse;
  235. }
  236. int DBConnPool::InitializeAllDBConnections()
  237. {
  238. // 先七公里现有的数据
  239. DestroyAllDBConnections();
  240. // 开始按照最小数量开始创建
  241. DBConnect * pDBConnect = NULL;
  242. int nCount = 0;
  243. for (int i = 0; i < m_nMinCount; i++)
  244. {
  245. nCount = InitializeAConnection();
  246. }
  247. // 创建一个工作线程,用来进行一些后台维护工作
  248. if (INVALID_HANDLE_VALUE == m_hMaintanceThread)
  249. {
  250. m_hMaintanceThread = CreateThread(NULL, NULL, thread_run, (LPVOID)this, 0, NULL);
  251. }
  252. return nCount;
  253. }
  254. void DBConnPool::DestroyAllDBConnections()
  255. {
  256. // 销毁数据库连接可以使用大锁
  257. EnterCriticalSection(&m_csIdleConnList);
  258. DBConnectList::iterator itIdle = m_listIdleConnection.begin();
  259. DBConnectList::iterator itIdleEnd = m_listIdleConnection.end();
  260. while (itIdle != itIdleEnd)
  261. {
  262. if (NULL != (*itIdle))
  263. {
  264. (*itIdle)->Close();
  265. delete (*itIdle);
  266. }
  267. // erase本身就会把跌代器指向下一个
  268. itIdle = m_listIdleConnection.erase(itIdle);
  269. }
  270. LeaveCriticalSection(&m_csIdleConnList);
  271. // 还有使用中的连接
  272. EnterCriticalSection(&m_csBusyConnList);
  273. DBConnectList::iterator itBusy = m_listBusyConnection.begin();
  274. DBConnectList::iterator itBusyEnd = m_listBusyConnection.end();
  275. while (itBusy != itBusyEnd)
  276. {
  277. if (NULL != (*itBusy))
  278. {
  279. (*itBusy)->Close();
  280. delete (*itBusy);
  281. }
  282. // erase本身就会把跌代器指向下一个
  283. itBusy = m_listBusyConnection.erase(itBusy);
  284. }
  285. LeaveCriticalSection(&m_csBusyConnList);
  286. }
  287. int DBConnPool::InitializeAConnection()
  288. {
  289. BOOL bSuccess = FALSE;
  290. DBConnect * pDBEngine = new DBConnect(_strDstAddress, _strUsername, _strPassword, _strDBName, bSuccess);
  291. if (bSuccess)
  292. {
  293. m_bNeedConnection = FALSE;
  294. return RestoreAConnection(pDBEngine);
  295. }
  296. else
  297. {
  298. delete pDBEngine;
  299. return m_listIdleConnection.size();
  300. }
  301. }
  302. void DBConnPool::CloseAConnection(DBConnect* pDBEngine)
  303. {
  304. pDBEngine->Close();
  305. // 从空闲队列将其删除
  306. EnterCriticalSection(&m_csIdleConnList);
  307. m_listIdleConnection.remove(pDBEngine);
  308. LeaveCriticalSection(&m_csIdleConnList);
  309. }
  310. DBConnect * DBConnPool::GetAConnection()
  311. {
  312. DBConnect * pDBEngine = NULL;
  313. // 做一个循环,反复尝试五次取连接,每次间隔1秒钟
  314. int nTimes = 0;
  315. while ((m_listIdleConnection.size() <= 0) && (nTimes < 5))
  316. {
  317. Sleep(1000);
  318. nTimes++;
  319. }
  320. if (5 == nTimes)
  321. {
  322. // 这样狼狈的进来肯定是没有可用连接了,记录日志退出
  323. // g_pSvrLog->AddRunLog(LL_ERROR, _T("Waiting for a connection for a long time, but failed."));
  324. return pDBEngine;
  325. }
  326. // 从空闲队列中取出,并且加入到使用队列中
  327. EnterCriticalSection(&m_csIdleConnList);
  328. if (m_listIdleConnection.size() > 0)
  329. {
  330. pDBEngine = m_listIdleConnection.front();
  331. m_listIdleConnection.pop_front();
  332. // 加入使用的连接队列
  333. EnterCriticalSection(&m_csBusyConnList);
  334. m_listBusyConnection.push_back(pDBEngine);
  335. LeaveCriticalSection(&m_csBusyConnList);
  336. }
  337. LeaveCriticalSection(&m_csIdleConnList);
  338. if (m_listIdleConnection.size() <= 1)
  339. {
  340. // 剩余空闲连接的数目小于等于1个时候需要检查开始创建
  341. if ((m_listIdleConnection.size() + m_listBusyConnection.size()) < m_nMaxCount)
  342. {
  343. // 还小于最大限制,可以创建
  344. SetEvent(m_hHaveData);
  345. m_bNeedConnection = TRUE;
  346. }
  347. else
  348. {
  349. // 超出限制了,做个记录吧
  350. //g_pSvrLog->AddRunLog(LL_ERROR, _T("Database connection reached max count."));
  351. }
  352. }
  353. return pDBEngine;
  354. }
  355. int DBConnPool::RestoreAConnection(DBConnect* pDBEngine)
  356. {
  357. if (NULL != pDBEngine)
  358. {
  359. // 从使用中的队列取出
  360. EnterCriticalSection(&m_csBusyConnList);
  361. m_listBusyConnection.remove(pDBEngine);
  362. LeaveCriticalSection(&m_csBusyConnList);
  363. // 加入到空闲队列中
  364. EnterCriticalSection(&m_csIdleConnList);
  365. m_listIdleConnection.push_back(pDBEngine);
  366. LeaveCriticalSection(&m_csIdleConnList);
  367. }
  368. EnterCriticalSection(&m_csIdleConnList);
  369. int nCount = m_listIdleConnection.size();
  370. LeaveCriticalSection(&m_csIdleConnList);
  371. return nCount;
  372. }
  373. void DBConnPool::StopThread()
  374. {
  375. m_bNeedStop = TRUE;
  376. // 因为线程是无限制等待信号的,所以这里先把标志位置为停止,然后发信号让线程检测
  377. SetEvent(m_hHaveData);
  378. // 等待退出
  379. WaitForSingleObject(m_hMaintanceThread, INFINITE);
  380. CloseHandle(m_hMaintanceThread);
  381. }
  382. BOOL DBConnPool::IsNeedStop()
  383. {
  384. return m_bNeedStop;
  385. }
  386. BOOL DBConnPool::IsNeedConnection()
  387. {
  388. return m_bNeedConnection;
  389. }
  390. /************************************************************************/
  391. /* 维护线程 */
  392. /************************************************************************/
  393. DWORD WINAPI DBConnPool::thread_run( LPVOID pdata)
  394. {
  395. DBConnPool * pConPool = (DBConnPool *) pdata;
  396. while (!pConPool->IsNeedStop())
  397. {
  398. // 设置事件为无信号, 并且无限制等待
  399. ResetEvent(pConPool->m_hHaveData);
  400. WaitForSingleObject(pConPool->m_hHaveData, INFINITE);
  401. if (pConPool->IsNeedConnection())
  402. {
  403. // g_pSvrLog->AddRunLog(LL_DEBUG, _T("Create a new DB connection."));
  404. pConPool->InitializeAConnection();
  405. }
  406. }
  407. return 0;
  408. }