SafeList.h 7.0 KB

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