DBConnPool.cpp 12 KB

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