SafeList.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. #ifndef __SAFE_LIST__
  2. #define __SAFE_LIST__
  3. #include <list>
  4. #include <locale.h>
  5. #include "CritSection.h"
  6. class CDatabase;
  7. using namespace std;
  8. extern void WriteTextLog(const TCHAR *format, ...);
  9. template <class _Ty,class _Ax = allocator<_Ty>>
  10. class SafeList: public std::list<_Ty, _Ax>
  11. {
  12. public:
  13. ThreadSection _critSection;
  14. void _push_back(const _Ty& _Val)
  15. {
  16. AutoThreadSection aSection(&_critSection);
  17. push_back(_Val);
  18. }
  19. void _push_front(const _Ty& _Val)
  20. {
  21. AutoThreadSection aSection(&_critSection);
  22. push_front(_Val);
  23. }
  24. void _pop_front()
  25. {
  26. AutoThreadSection aSection(&_critSection);
  27. pop_front();
  28. }
  29. _Ty _pop_front_()
  30. {
  31. AutoThreadSection aSection(&_critSection);
  32. if (_Mysize != 0)
  33. {
  34. _Ty it = front();
  35. pop_front();
  36. return it;
  37. }
  38. return NULL;
  39. }
  40. void _pop_back()
  41. {
  42. AutoThreadSection aSection(&_critSection);
  43. pop_back();
  44. }
  45. void _remove(const _Ty& _Val_arg)
  46. {
  47. AutoThreadSection aSection(&_critSection);
  48. remove(_Val_arg);
  49. }
  50. reference _front()
  51. {
  52. AutoThreadSection aSection(&_critSection);
  53. return (*begin());
  54. }
  55. const_reference _front() const
  56. {
  57. AutoThreadSection aSection(&_critSection);
  58. return (*begin());
  59. }
  60. reference _back()
  61. {
  62. AutoThreadSection aSection(&_critSection);
  63. return (*(--end()));
  64. }
  65. const_reference _back() const
  66. {
  67. AutoThreadSection aSection(&_critSection);
  68. return (*(--end()));
  69. }
  70. size_type _size()
  71. {
  72. //AutoThreadSection aSection(&_critSection);
  73. return (_Mysize);
  74. }
  75. };
  76. typedef SafeList<CDatabase*> ODBCConnectList;
  77. class CODBCPool
  78. {
  79. ThreadSection m_critSection;
  80. // 空闲数据库连接池;
  81. ODBCConnectList m_listIdleConnections;
  82. // 在使用的数据库连接池;
  83. ODBCConnectList m_listBusyConnections;
  84. // 可用的指标:最大、最小;
  85. INT m_nMaxCount;
  86. INT m_nMinCount;
  87. // 引入的指针变量;
  88. DWORD m_dwDBPort;
  89. CString m_strDBSource;
  90. CString m_strDBAccount;
  91. CString m_strPassWord;
  92. CString m_strDBName;
  93. BOOL m_bNeedExit; // 退出数据池;
  94. BOOL m_bNeedStop;
  95. BOOL m_bNeedConnection;
  96. public:
  97. CODBCPool(void) {
  98. m_nRef = 0;
  99. m_nObjRef = 0;
  100. m_nMaxCount = 0;
  101. m_nMinCount = 0;
  102. m_bNeedExit = FALSE;
  103. m_bNeedStop = FALSE;
  104. m_bNeedConnection = FALSE;
  105. };
  106. ~CODBCPool(void) {DestroyAllDBConnections();};
  107. // 获取实例指针;
  108. static CODBCPool* GetInstance()
  109. {
  110. static CODBCPool* pInstance = NULL;
  111. if ( pInstance == NULL )
  112. pInstance = new CODBCPool;
  113. return pInstance;
  114. }
  115. // 初始化所有连接;
  116. DWORD InitializePool( IN LPCTSTR lpDBSource, IN CONST DWORD &dwDBPort, IN LPCTSTR lpDBAccount, IN LPCTSTR lpPassWord, IN LPCTSTR lpDBName, IN CONST INT &nMinConn = 1, IN CONST INT &nMaxConn = 5)
  117. {
  118. if ( !lpDBSource || lpDBSource[0] == _T('\0') || !lpDBName || lpDBName[0] == _T('\0') )
  119. {
  120. return 0;
  121. }
  122. m_strDBSource = lpDBSource;
  123. m_dwDBPort = dwDBPort;
  124. m_strDBAccount = lpDBAccount;
  125. m_strPassWord = lpPassWord;
  126. m_strDBName = lpDBName;
  127. m_nMinCount = nMinConn;
  128. m_nMaxCount = nMaxConn;
  129. return IntiAllConnections();
  130. }
  131. // 关闭所有连接;
  132. void ReleasePool(){DestroyAllDBConnections();}
  133. // 设置数据库信息;
  134. void SetDBConnectionInfo(IN LPCTSTR lpDBSource, IN CONST DWORD &dwDBPort, IN LPCTSTR lpDBAccount, IN LPCTSTR lpPassWord, IN LPCTSTR lpDBName);
  135. // 初始化所有连接;
  136. INT IntiAllConnections()
  137. {
  138. DestroyAllDBConnections();
  139. // 开始按照最小数量开始创建;
  140. int nCount = 0;
  141. CDatabase *pDatabase = NULL;
  142. for (int i = 0; i < m_nMinCount; i++)
  143. {
  144. pDatabase = InitAConnection();
  145. if ( pDatabase )
  146. {
  147. nCount++;
  148. m_listIdleConnections._push_back(pDatabase);
  149. InterlockedIncrement(&m_nObjRef); //增加引用计数;
  150. pDatabase = NULL;
  151. }
  152. }
  153. return nCount;
  154. }
  155. // 断开所有连接;
  156. void DestroyAllDBConnections()
  157. {
  158. m_bNeedExit = TRUE;
  159. // 首先等待m_listBusyConnections.size() == 0;
  160. while(1)
  161. {
  162. if ( m_listBusyConnections.size() == 0 )
  163. break;
  164. Sleep(1000);
  165. }
  166. ODBCConnectList::iterator itIdle = m_listIdleConnections.begin();
  167. while (itIdle != m_listIdleConnections.end())
  168. {
  169. if (NULL != (*itIdle))
  170. {
  171. (*itIdle)->Close();
  172. delete (*itIdle);
  173. }
  174. itIdle = m_listIdleConnections.erase(itIdle);
  175. }
  176. m_bNeedExit = FALSE;
  177. }
  178. // 获取一个空闲连接;
  179. CDatabase* GetAConnection( IN CONST DWORD &dwTimeOut = 1000 )
  180. {
  181. if ( m_bNeedExit )// 停止获取;
  182. return NULL;
  183. // 1.首先到池中查找有无空闲对象;
  184. BOOL bGetIdl = FALSE;
  185. DWORD dwTime = GetTickCount();
  186. CDatabase* pDBEngine = NULL;
  187. do
  188. {
  189. if ( m_listIdleConnections._size() > 0){
  190. //AutoThreadSection aSection(&m_critSection);
  191. pDBEngine = m_listIdleConnections._pop_front_();
  192. if (pDBEngine)
  193. {
  194. m_listBusyConnections._push_back(pDBEngine);
  195. bGetIdl = TRUE;
  196. }
  197. }
  198. else
  199. {
  200. if (m_nObjRef < m_nMaxCount)
  201. {
  202. //AutoThreadSection aSection(&m_critSection);
  203. pDBEngine = InitAConnection();
  204. if (pDBEngine){
  205. //bGetIdl = TRUE;
  206. m_listBusyConnections._push_back(pDBEngine);
  207. InterlockedIncrement(&m_nObjRef); //增加引用计数;
  208. WriteTextLog(_T("创建连接对象:共有 %d 个"), m_nObjRef);
  209. break;
  210. }
  211. }
  212. }
  213. if ( !bGetIdl ) {
  214. // 未找到,小憩一会,防止CPU爆满;
  215. Sleep(0);
  216. // 超时,则结束返回NULL;
  217. if ( (GetTickCount() - dwTime) >= dwTimeOut){
  218. WriteTextLog(_T("获取连接对象超时"));
  219. break;
  220. }
  221. }
  222. } while ( !bGetIdl );
  223. return pDBEngine;
  224. }
  225. // 交还连接给空闲队列;
  226. void RestoreAConnection(IN CDatabase *pDBEngine)
  227. {
  228. if ( pDBEngine != NULL ){
  229. m_listBusyConnections._remove(pDBEngine);
  230. m_listIdleConnections._push_back(pDBEngine);
  231. }
  232. }
  233. private:
  234. volatile LONG m_nRef;
  235. volatile LONG m_nObjRef;
  236. // 创建一个连接;
  237. CDatabase* InitAConnection()
  238. {
  239. if ( m_nObjRef == m_nMaxCount )
  240. return NULL;
  241. CDatabase * pDBEngine = new CDatabase;
  242. TCHAR szConnString[MAX_PATH] = {0};
  243. if (m_dwDBPort != 0)
  244. {
  245. if ( m_strDBAccount.IsEmpty() )
  246. _stprintf_s(szConnString, MAX_PATH, DB_SW_CONN_WITH_PORT, m_strDBSource.GetString(), m_dwDBPort, m_strDBName.GetString());
  247. else
  248. _stprintf_s(szConnString, MAX_PATH, DB_SS_CONN_WITH_PORT, m_strDBSource.GetString(), m_dwDBPort, m_strDBName.GetString(), m_strDBAccount.GetString(), m_strPassWord.GetString());
  249. }
  250. else
  251. {
  252. if ( m_strDBAccount.IsEmpty() )
  253. _stprintf_s(szConnString, MAX_PATH, DB_SW_CONN_WITHOUT_PORT, m_strDBSource.GetString(), m_strDBName.GetString());
  254. else
  255. _stprintf_s(szConnString, MAX_PATH, DB_SS_CONN_WITHOUT_PORT, m_strDBSource.GetString(), m_strDBName.GetString(), m_strDBAccount.GetString(), m_strPassWord.GetString());
  256. }
  257. try
  258. {
  259. pDBEngine->OpenEx(szConnString, CDatabase::noOdbcDialog);
  260. }
  261. catch (CDBException* e)
  262. {
  263. if ( pDBEngine )
  264. delete pDBEngine;
  265. pDBEngine = NULL;
  266. WriteTextLog(_T("SQL连接串:%s, 返回错误:%s"), szConnString, e->m_strError);
  267. }
  268. return pDBEngine;
  269. }
  270. // 关闭一个连接;
  271. void CloseAConnection(CDatabase* pDBEngine)
  272. {
  273. m_listIdleConnections._remove(pDBEngine);
  274. InterlockedDecrement(&m_nObjRef); // 减少计数;
  275. if ( pDBEngine )
  276. delete pDBEngine;
  277. }
  278. // 将守卫类友元化;
  279. friend class ODBCConnGuard;
  280. public:
  281. //////////////////////////////////////////////////////////////////////////
  282. // 数据库接口;
  283. BOOL ExecuteSQL( IN LPCTSTR lpExcuteSQL, IN CONST DWORD &dwTimeOut = 30000 );
  284. };
  285. #endif // __SAFE_LIST__