Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

822 lines
20 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Session.cpp
  5. Abstract:
  6. This file contains the implementation of the JetBlue::Session* classes.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 05/17/2000
  9. created
  10. ******************************************************************************/
  11. #include <stdafx.h>
  12. ////////////////////////////////////////////////////////////////////////////////
  13. JetBlue::Session::Session( /*[in]*/ SessionPool* parent ,
  14. /*[in]*/ JET_INSTANCE inst )
  15. {
  16. m_parent = parent; // SessionPool* m_parent;
  17. m_inst = inst; // JET_INSTANCE m_inst;
  18. m_sesid = JET_sesidNil; // JET_SESID m_sesid;
  19. // DbMap m_mapDBs;
  20. m_dwTransactionNesting = 0; // DWORD m_dwTransactionNesting;
  21. m_fAborted = false; // bool m_fAborted;
  22. }
  23. JetBlue::Session::~Session()
  24. {
  25. (void)Close( true );
  26. }
  27. ////////////////////////////////////////
  28. bool JetBlue::Session::LockDatabase ( /*[in]*/ const MPC::string& strDB, /*[in]*/ bool fReadOnly ) { return m_parent->LockDatabase ( this, strDB, fReadOnly ); }
  29. void JetBlue::Session::UnlockDatabase ( /*[in]*/ const MPC::string& strDB ) { m_parent->UnlockDatabase ( this, strDB ); }
  30. HRESULT JetBlue::Session::ReleaseDatabase( /*[in]*/ const MPC::string& strDB ) { return m_parent->ReleaseDatabase( strDB.c_str() ); }
  31. ////////////////////////////////////////
  32. HRESULT JetBlue::Session::Init()
  33. {
  34. __HCP_FUNC_ENTRY( "JetBlue::Session::Init" );
  35. HRESULT hr;
  36. if(m_sesid == JET_sesidNil)
  37. {
  38. __MPC_EXIT_IF_JET_FAILS(hr, ::JetBeginSession( m_inst, &m_sesid, NULL, NULL ));
  39. }
  40. hr = S_OK;
  41. __HCP_FUNC_CLEANUP;
  42. __HCP_FUNC_EXIT(hr);
  43. }
  44. HRESULT JetBlue::Session::Close( /*[in]*/ bool fForce )
  45. {
  46. __HCP_FUNC_ENTRY( "JetBlue::Session::Close" );
  47. HRESULT hr;
  48. DbIter it;
  49. for(it = m_mapDBs.begin(); it != m_mapDBs.end(); it++)
  50. {
  51. Database* db = it->second;
  52. if(db)
  53. {
  54. HRESULT hr2 = db->Close( fForce ); if(!fForce) __MPC_EXIT_IF_METHOD_FAILS(hr, hr2);
  55. delete db;
  56. }
  57. }
  58. m_mapDBs.clear();
  59. if(m_sesid != JET_sesidNil)
  60. {
  61. JET_ERR err = ::JetEndSession( m_sesid, 0 ); if(!fForce) __MPC_EXIT_IF_JET_FAILS(hr, err);
  62. m_sesid = JET_sesidNil;
  63. }
  64. hr = S_OK;
  65. __HCP_FUNC_CLEANUP;
  66. __HCP_FUNC_EXIT(hr);
  67. }
  68. void JetBlue::Session::Release()
  69. {
  70. if(m_fAborted)
  71. {
  72. DbIter it;
  73. for(it = m_mapDBs.begin(); it != m_mapDBs.end(); it++)
  74. {
  75. Database* db = it->second;
  76. if(db)
  77. {
  78. db->Close( /*fForce*/true, /*fAll*/false );
  79. }
  80. }
  81. __MPC_JET__MTSAFE_NORESULT(m_sesid, ::JetRollback( m_sesid, JET_bitRollbackAll ));
  82. m_fAborted = false;
  83. }
  84. }
  85. ////////////////////////////////////////
  86. HRESULT JetBlue::Session::GetDatabase( /*[in] */ LPCSTR szName ,
  87. /*[out]*/ Database*& db ,
  88. /*[in]*/ bool fReadOnly ,
  89. /*[in]*/ bool fCreate ,
  90. /*[in]*/ bool fRepair )
  91. {
  92. __HCP_FUNC_ENTRY( "JetBlue::Session::GetDatabase" );
  93. HRESULT hr;
  94. Database* dbNew = NULL;
  95. DbIter it;
  96. db = NULL;
  97. it = m_mapDBs.find( szName );
  98. if(it == m_mapDBs.end())
  99. {
  100. __MPC_EXIT_IF_ALLOC_FAILS(hr, dbNew, new Database( this, m_sesid, szName ));
  101. m_mapDBs[szName] = dbNew;
  102. db = dbNew; dbNew = NULL;
  103. }
  104. else
  105. {
  106. db = it->second;
  107. }
  108. __MPC_EXIT_IF_METHOD_FAILS(hr, db->Open( fReadOnly, fCreate, fRepair ));
  109. hr = S_OK;
  110. __HCP_FUNC_CLEANUP;
  111. if(dbNew) delete dbNew;
  112. __HCP_FUNC_EXIT(hr);
  113. }
  114. ////////////////////////////////////////
  115. HRESULT JetBlue::Session::BeginTransaction()
  116. {
  117. __HCP_FUNC_ENTRY( "JetBlue::Session::BeginTransaction" );
  118. HRESULT hr;
  119. __MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetBeginTransaction( m_sesid ));
  120. m_dwTransactionNesting++;
  121. hr = S_OK;
  122. __HCP_FUNC_CLEANUP;
  123. __HCP_FUNC_EXIT(hr);
  124. }
  125. HRESULT JetBlue::Session::CommitTransaction()
  126. {
  127. __HCP_FUNC_ENTRY( "JetBlue::Session::CommitTransaction" );
  128. HRESULT hr;
  129. if(m_dwTransactionNesting > 0)
  130. {
  131. __MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetCommitTransaction( m_sesid, JET_bitCommitLazyFlush ));
  132. m_dwTransactionNesting--;
  133. }
  134. hr = S_OK;
  135. __HCP_FUNC_CLEANUP;
  136. __HCP_FUNC_EXIT(hr);
  137. }
  138. HRESULT JetBlue::Session::RollbackTransaction()
  139. {
  140. __HCP_FUNC_ENTRY( "JetBlue::Session::RollbackTransaction" );
  141. HRESULT hr;
  142. if(m_dwTransactionNesting > 0)
  143. {
  144. m_fAborted = true;
  145. __MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetRollback( m_sesid, 0 ));
  146. m_dwTransactionNesting--;
  147. }
  148. hr = S_OK;
  149. __HCP_FUNC_CLEANUP;
  150. __HCP_FUNC_EXIT(hr);
  151. }
  152. ////////////////////////////////////////
  153. JetBlue::Database* JetBlue::Session::GetDB( /*[in]*/ int iPos )
  154. {
  155. for(DbIter it = m_mapDBs.begin(); it != m_mapDBs.end(); it++)
  156. {
  157. if(iPos-- == 0) return it->second;
  158. }
  159. return NULL;
  160. }
  161. JetBlue::Database* JetBlue::Session::GetDB( LPCSTR szDB )
  162. {
  163. DbIter it = m_mapDBs.find( szDB );
  164. return (it == m_mapDBs.end()) ? NULL : it->second;
  165. }
  166. ////////////////////////////////////////////////////////////////////////////////
  167. ////////////////////////////////////////////////////////////////////////////////
  168. ////////////////////////////////////////////////////////////////////////////////
  169. JetBlue::TransactionHandle::TransactionHandle()
  170. {
  171. m_sess = NULL; // Session* m_sess;
  172. }
  173. JetBlue::TransactionHandle::~TransactionHandle()
  174. {
  175. (void)Rollback();
  176. }
  177. HRESULT JetBlue::TransactionHandle::Begin( /*[in]*/ Session* sess )
  178. {
  179. __HCP_FUNC_ENTRY( "JetBlue::TransactionHandle::Begin" );
  180. HRESULT hr;
  181. __MPC_EXIT_IF_METHOD_FAILS(hr, Rollback());
  182. if(sess)
  183. {
  184. __MPC_EXIT_IF_METHOD_FAILS(hr, sess->BeginTransaction());
  185. m_sess = sess;
  186. }
  187. hr = S_OK;
  188. __HCP_FUNC_CLEANUP;
  189. __HCP_FUNC_EXIT(hr);
  190. }
  191. HRESULT JetBlue::TransactionHandle::Commit()
  192. {
  193. __HCP_FUNC_ENTRY( "JetBlue::TransactionHandle::Commit" );
  194. HRESULT hr;
  195. if(m_sess)
  196. {
  197. __MPC_EXIT_IF_METHOD_FAILS(hr, m_sess->CommitTransaction());
  198. m_sess = NULL;
  199. }
  200. hr = S_OK;
  201. __HCP_FUNC_CLEANUP;
  202. __HCP_FUNC_EXIT(hr);
  203. }
  204. HRESULT JetBlue::TransactionHandle::Rollback()
  205. {
  206. __HCP_FUNC_ENTRY( "JetBlue::TransactionHandle::Rollback" );
  207. HRESULT hr;
  208. if(m_sess)
  209. {
  210. __MPC_EXIT_IF_METHOD_FAILS(hr, m_sess->RollbackTransaction());
  211. m_sess = NULL;
  212. }
  213. hr = S_OK;
  214. __HCP_FUNC_CLEANUP;
  215. __HCP_FUNC_EXIT(hr);
  216. }
  217. ////////////////////////////////////////////////////////////////////////////////
  218. ////////////////////////////////////////////////////////////////////////////////
  219. ////////////////////////////////////////////////////////////////////////////////
  220. JetBlue::SessionHandle::SessionHandle()
  221. {
  222. m_pool = NULL; // SessionPool* m_pool;
  223. m_sess = NULL; // Session* m_sess;
  224. }
  225. JetBlue::SessionHandle::~SessionHandle()
  226. {
  227. Release();
  228. }
  229. ////////////////////////////////////////
  230. void JetBlue::SessionHandle::Release()
  231. {
  232. if(m_pool)
  233. {
  234. m_pool->ReleaseSession( m_sess );
  235. m_pool = NULL;
  236. }
  237. m_sess = NULL;
  238. }
  239. void JetBlue::SessionHandle::Init( /*[in]*/ SessionPool* pool ,
  240. /*[in]*/ Session* sess )
  241. {
  242. Release();
  243. m_pool = pool; // SessionPool* m_pool;
  244. m_sess = sess; // Session* m_sess;
  245. }
  246. ////////////////////////////////////////////////////////////////////////////////
  247. ////////////////////////////////////////////////////////////////////////////////
  248. ////////////////////////////////////////////////////////////////////////////////
  249. JetBlue::SessionPool::SessionPool()
  250. {
  251. m_fInitialized = false; // bool m_fInitialized;
  252. m_inst = JET_instanceNil; // JET_INSTANCE m_inst;
  253. // SessionList m_lstSessions;
  254. // DbInUseList m_lstDbInUse;
  255. m_iAllocated = 0; // int m_iAllocated;
  256. m_iInUse = 0; // int m_iInUse;
  257. (void)MPC::_MPC_Module.RegisterCallback( this, (void (JetBlue::SessionPool::*)())Shutdown );
  258. }
  259. JetBlue::SessionPool::~SessionPool()
  260. {
  261. MPC::_MPC_Module.UnregisterCallback( this );
  262. Shutdown();
  263. }
  264. ////////////////////
  265. JetBlue::SessionPool* JetBlue::SessionPool::s_GLOBAL( NULL );
  266. HRESULT JetBlue::SessionPool::InitializeSystem()
  267. {
  268. if(s_GLOBAL == NULL)
  269. {
  270. s_GLOBAL = new JetBlue::SessionPool;
  271. }
  272. return s_GLOBAL ? S_OK : E_OUTOFMEMORY;
  273. }
  274. void JetBlue::SessionPool::FinalizeSystem()
  275. {
  276. if(s_GLOBAL)
  277. {
  278. delete s_GLOBAL; s_GLOBAL = NULL;
  279. }
  280. }
  281. ////////////////////
  282. void JetBlue::SessionPool::Shutdown()
  283. {
  284. (void)Close( true );
  285. }
  286. ////////////////////////////////////////
  287. void JetBlue::SessionPool::ReleaseSession( /*[in]*/ Session* sess )
  288. {
  289. MPC::SmartLock<_ThreadModel> lock( this );
  290. SessionIter it;
  291. for(it = m_lstSessions.begin(); it != m_lstSessions.end(); it++)
  292. {
  293. if(it->m_sess == sess)
  294. {
  295. sess->Release();
  296. it->m_fInUse = false; m_iInUse--;
  297. if(m_iAllocated - m_iInUse > l_MaxFreePoolSize)
  298. {
  299. m_lstSessions.erase( it ); m_iAllocated--;
  300. }
  301. break;
  302. }
  303. }
  304. }
  305. bool JetBlue::SessionPool::LockDatabase( /*[in]*/ Session* sess, /*[in]*/ const MPC::string& strDB, /*[in]*/ bool fReadOnly )
  306. {
  307. MPC::SmartLock<_ThreadModel> lock( this );
  308. DbInUseIter it;
  309. bool fLockedForRead = false;
  310. bool fLockedForWrite = false;
  311. for(it = m_lstDbInUse.begin(); it != m_lstDbInUse.end(); it++)
  312. {
  313. DatabaseInUse& db = *it;
  314. if(db.m_strDB == strDB)
  315. {
  316. if(db.m_fReadOnly) fLockedForRead = true;
  317. else fLockedForWrite = true;
  318. }
  319. }
  320. if(fLockedForRead && !fReadOnly) return false; // Someone has the database opened in read-only mode...
  321. if(fLockedForWrite ) fReadOnly = false; // The database is already opened for writing, so do the same.
  322. for(it = m_lstDbInUse.begin(); it != m_lstDbInUse.end(); it++)
  323. {
  324. DatabaseInUse& db = *it;
  325. if(db.m_sess == sess &&
  326. db.m_strDB == strDB )
  327. {
  328. return true; // Already locked.
  329. }
  330. }
  331. //
  332. // Create new entry.
  333. //
  334. it = m_lstDbInUse.insert( m_lstDbInUse.end() );
  335. it->m_sess = sess;
  336. it->m_strDB = strDB;
  337. it->m_fReadOnly = fReadOnly;
  338. return true;
  339. }
  340. void JetBlue::SessionPool::UnlockDatabase( /*[in]*/ Session* sess, /*[in]*/ const MPC::string& strDB )
  341. {
  342. MPC::SmartLock<_ThreadModel> lock( this );
  343. DbInUseIter it = m_lstDbInUse.begin();
  344. bool fInUse = false;
  345. bool fSeen = false;
  346. while(it != m_lstDbInUse.end())
  347. {
  348. DbInUseIter it2 = it++; // Copy iterator and move to the next one. This protects us from node removal.
  349. DatabaseInUse& db = *it2;
  350. if(db.m_strDB == strDB)
  351. {
  352. fSeen = true;
  353. if(db.m_sess == sess)
  354. {
  355. m_lstDbInUse.erase( it2 );
  356. }
  357. else
  358. {
  359. fInUse = true;
  360. }
  361. }
  362. }
  363. //
  364. // Last session to release the database, detach from it.
  365. //
  366. if(fSeen && !fInUse)
  367. {
  368. (void)::JetDetachDatabase( sess->GetSESID(), strDB.c_str() );
  369. }
  370. }
  371. HRESULT JetBlue::SessionPool::ReleaseDatabase( /*[in]*/ LPCSTR szDB )
  372. {
  373. __HCP_FUNC_ENTRY( "JetBlue::SessionPool::ReleaseDatabase" );
  374. HRESULT hr;
  375. MPC::SmartLock<_ThreadModel> lock ( this );
  376. MPC::string strDB( szDB );
  377. DbInUseIter it;
  378. for(it = m_lstDbInUse.begin(); it != m_lstDbInUse.end();)
  379. {
  380. DatabaseInUse& db = *it;
  381. if(db.m_strDB == strDB)
  382. {
  383. SessionIter it2;
  384. for(it2 = m_lstSessions.begin(); it2 != m_lstSessions.end(); it2++)
  385. {
  386. if(it2->m_sess == db.m_sess) break;
  387. }
  388. if(it2 != m_lstSessions.end())
  389. {
  390. if(it2->m_fInUse)
  391. {
  392. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_BUSY);
  393. }
  394. m_lstSessions.erase( it2 ); m_iAllocated--;
  395. //
  396. // The list of databases in use has been changed by the delete operator.
  397. //
  398. it = m_lstDbInUse.begin(); continue;
  399. }
  400. }
  401. it++;
  402. }
  403. hr = S_OK;
  404. __HCP_FUNC_CLEANUP;
  405. __HCP_FUNC_EXIT(hr);
  406. }
  407. ////////////////////////////////////////
  408. HRESULT JetBlue::SessionPool::Init( /*[in]*/ LPCWSTR szLogs )
  409. {
  410. __HCP_FUNC_ENTRY( "JetBlue::SessionPool::Init" );
  411. USES_CONVERSION;
  412. HRESULT hr;
  413. MPC::SmartLock<_ThreadModel> lock( this );
  414. if(m_fInitialized == false)
  415. {
  416. static const JET_SETSYSPARAM sConfig_Normal[] =
  417. {
  418. //unsigned long paramid , ULONG_PTR lParam, const char *sz, JET_ERR err
  419. #ifdef DEBUG
  420. { JET_paramAssertAction , JET_AssertMsgBox, NULL , JET_errSuccess },
  421. #endif
  422. { JET_paramSystemPath , 0 , (LPSTR)-1 , JET_errSuccess },
  423. { JET_paramTempPath , 0 , (LPSTR)-1 , JET_errSuccess },
  424. { JET_paramLogFilePath , 0 , (LPSTR)-1 , JET_errSuccess },
  425. { JET_paramBaseName , 0 , "edb" , JET_errSuccess },
  426. { JET_paramEventSource , 0 , "HelpSvc.exe" , JET_errSuccess },
  427. { JET_paramNoInformationEvent, 1 , NULL , JET_errSuccess },
  428. { JET_paramGlobalMinVerPages , 1 , NULL , JET_errSuccess },
  429. { JET_paramMaxVerPages , 1024 , NULL , JET_errSuccess },
  430. { JET_paramCacheSizeMax , 1024 , NULL , JET_errSuccess },
  431. //// { JET_paramLogFileSize , 128 , NULL , JET_errSuccess },
  432. //// { JET_paramCircularLog , 1 , NULL , JET_errSuccess },
  433. { -1 }
  434. };
  435. static const JET_SETSYSPARAM sConfig_LargeSet[] =
  436. {
  437. //unsigned long paramid , ULONG_PTR lParam, const char *sz, JET_ERR err
  438. #ifdef DEBUG
  439. { JET_paramAssertAction , JET_AssertMsgBox, NULL , JET_errSuccess },
  440. #endif
  441. { JET_paramSystemPath , 0 , (LPSTR)-1 , JET_errSuccess },
  442. { JET_paramTempPath , 0 , (LPSTR)-1 , JET_errSuccess },
  443. { JET_paramLogFilePath , 0 , (LPSTR)-1 , JET_errSuccess },
  444. { JET_paramBaseName , 0 , "edb" , JET_errSuccess },
  445. { JET_paramEventSource , 0 , "HelpSvc.exe" , JET_errSuccess },
  446. { JET_paramNoInformationEvent, 1 , NULL , JET_errSuccess },
  447. { JET_paramGlobalMinVerPages , 64 , NULL , JET_errSuccess },
  448. { JET_paramMaxVerPages , 2048 , NULL , JET_errSuccess },
  449. { JET_paramCacheSizeMax , 4096 , NULL , JET_errSuccess },
  450. //// { JET_paramLogFileSize , 1024 , NULL , JET_errSuccess },
  451. //// { JET_paramCircularLog , 0 , NULL , JET_errSuccess },
  452. { -1 }
  453. };
  454. ////////////////////
  455. MPC::wstring strDir;
  456. LPCSTR szDirAnsi;
  457. const JET_SETSYSPARAM* pParam;
  458. JET_ERR err;
  459. if(szLogs == NULL)
  460. {
  461. szLogs = HC_ROOT_HELPSVC_CONFIG L"\\CheckPoint\\";
  462. pParam = sConfig_Normal;
  463. }
  464. else
  465. {
  466. pParam = sConfig_LargeSet;
  467. }
  468. MPC::SubstituteEnvVariables( strDir = szLogs ); szDirAnsi = W2A( strDir.c_str() );
  469. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( strDir ));
  470. ::JetSetSystemParameter( &m_inst, 0, JET_paramRecovery, 0, "off" );
  471. while(pParam->paramid != -1)
  472. {
  473. JET_SETSYSPARAM param = *pParam++;
  474. JET_ERR err;
  475. if(param.sz == (LPSTR)-1)
  476. {
  477. param.sz = szDirAnsi;
  478. }
  479. err = ::JetSetSystemParameter( &m_inst, 0, param.paramid, param.lParam, param.sz );
  480. if(err == JET_errInvalidParameter) continue; // Ignore version problems.
  481. __MPC_EXIT_IF_JET_FAILS(hr, err);
  482. }
  483. err = ::JetInit( &m_inst );
  484. //
  485. // If it's a log problem, delete the log files and retry.
  486. //
  487. if(err >= JET_errSoftRecoveryOnSnapshot &&
  488. err <= JET_errInvalidLoggedOperation )
  489. {
  490. MPC::FileSystemObject fso( strDir.c_str() );
  491. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.DeleteChildren( true, false ));
  492. err = ::JetInit( &m_inst );
  493. }
  494. __MPC_EXIT_IF_JET_FAILS(hr, err);
  495. m_fInitialized = true;
  496. }
  497. hr = S_OK;
  498. __HCP_FUNC_CLEANUP;
  499. __HCP_FUNC_EXIT(hr);
  500. }
  501. HRESULT JetBlue::SessionPool::Close( /*[in]*/ bool fForce )
  502. {
  503. __HCP_FUNC_ENTRY( "JetBlue::SessionPool::Close" );
  504. HRESULT hr;
  505. MPC::SmartLock<_ThreadModel> lock( this );
  506. while(m_lstSessions.size() > 0)
  507. {
  508. SessionState& ss = m_lstSessions.front();
  509. if(ss.m_sess)
  510. {
  511. HRESULT hr2 = ss.m_sess->Close( fForce ); if(!fForce) __MPC_EXIT_IF_JET_FAILS(hr, hr2);
  512. }
  513. m_lstSessions.pop_front();
  514. }
  515. if(m_fInitialized)
  516. {
  517. JET_ERR err = ::JetTerm2( m_inst, JET_bitTermComplete ); if(!fForce) __MPC_EXIT_IF_JET_FAILS(hr, err);
  518. m_inst = JET_instanceNil;
  519. m_fInitialized = false;
  520. }
  521. hr = S_OK;
  522. __HCP_FUNC_CLEANUP;
  523. __HCP_FUNC_EXIT(hr);
  524. }
  525. ////////////////////////////////////////////////////////////////////////////////
  526. HRESULT JetBlue::SessionPool::GetSession( /*[out]*/ SessionHandle& handle ,
  527. /*[in]*/ DWORD dwTimeout )
  528. {
  529. __HCP_FUNC_ENTRY( "JetBlue::SessionPool::GetSession" );
  530. HRESULT hr;
  531. SessionIter it;
  532. Session* sess = NULL;
  533. MPC::SmartLock<_ThreadModel> lock( this );
  534. handle.Release();
  535. __MPC_EXIT_IF_METHOD_FAILS(hr, Init());
  536. while(1)
  537. {
  538. if(m_iAllocated > m_iInUse)
  539. {
  540. //
  541. // Look for free session.
  542. //
  543. for(it = m_lstSessions.begin(); it != m_lstSessions.end(); it++)
  544. {
  545. if(it->m_fInUse == false)
  546. {
  547. it->m_fInUse = true; m_iInUse++;
  548. handle.Init( this, it->m_sess );
  549. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  550. }
  551. }
  552. }
  553. //
  554. // No free session, but still below maximum number of sessions, so let's create a new one.
  555. //
  556. if(m_iAllocated < l_MaxPoolSize)
  557. {
  558. __MPC_EXIT_IF_ALLOC_FAILS(hr, sess, new Session( this, m_inst ));
  559. __MPC_EXIT_IF_METHOD_FAILS(hr, sess->Init());
  560. it = m_lstSessions.insert( m_lstSessions.end() ); m_iAllocated++;
  561. it->m_sess = sess; sess = NULL;
  562. it->m_fInUse = true; m_iInUse++;
  563. handle.Init( this, it->m_sess );
  564. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  565. }
  566. //
  567. // Out of resources, wait for other threads to release them...
  568. //
  569. if(dwTimeout == 0)
  570. {
  571. __MPC_SET_ERROR_AND_EXIT(hr, ERROR_NO_SYSTEM_RESOURCES);
  572. }
  573. lock = NULL;
  574. ::Sleep( 100 );
  575. if(dwTimeout < 100) dwTimeout = 0;
  576. else dwTimeout -= 100;
  577. lock = this;
  578. }
  579. hr = S_OK;
  580. __HCP_FUNC_CLEANUP;
  581. if(sess) delete sess;
  582. __HCP_FUNC_EXIT(hr);
  583. }