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.

970 lines
24 KiB

  1. /*****************************************************************************\
  2. * MODULE: cachemgr.cxx
  3. *
  4. * The module contains routines to implement the caching algorithm for
  5. * the printers provider
  6. *
  7. * Purpose:
  8. *
  9. * Description:
  10. *
  11. * The Caching algorithm operates based on a state machine. There are five
  12. * states in the cache:
  13. *
  14. * CACHE_STATE_INIT
  15. * CACHE_STATE_ACCESSED_VALID,
  16. * CACHE_STATE_DATA_VALID,
  17. * CACHE_STATE_ACCESSED_VALID_AGAIN,
  18. * CACHE_STATE_NOT_ACCESSED_VALID_AGAIN
  19. *
  20. * CACHE_STATE_INIT is the initial state. Once the first cache hit
  21. * comes in, the cahce manager calles FetchData to fetch the data
  22. * and goes into CACHE_STATE_ACCESSED_VALID state.
  23. *
  24. * In CACHE_STATE_ACCESSED_VALID state, the cache manager waits
  25. * for the minimum cache timeout and go to CACHE_STATE_DATA_VALID
  26. *
  27. * In CACHE_STATE_DATA_VALID state, the cache manager waits for
  28. * another cache hit withing half of the last fetch time.
  29. *
  30. * If there is a hit during this waiting, the cache manager will go
  31. * for another fetch and go to CACHE_STATE_ACCESSED_VALID state.
  32. *
  33. * If there is no hit during the waiting period, the cache manager
  34. * waits for another timeout or another cache hit.
  35. *
  36. * If there is no access during the waiting, the cache manager
  37. * invalidates the cache. Otherwise, the cache manager go out and
  38. * do anther data fetch and then go to CACHE_STATE_ACCESSED_VALID.
  39. *
  40. *
  41. *
  42. * Copyright (C) 1998-1999 Microsoft Corporation
  43. *
  44. * History:
  45. * 10/16/98 weihaic Created
  46. *
  47. \*****************************************************************************/
  48. #include "precomp.h"
  49. #include "priv.h"
  50. extern BOOL _ppinfo_net_get_info(
  51. IN PCINETMONPORT pIniPort,
  52. OUT PPRINTER_INFO_2 *ppInfo,
  53. OUT LPDWORD lpBufAllocated,
  54. IN ALLOCATORFN pAllocator);
  55. extern BOOL ppjob_EnumForCache(
  56. IN PCINETMONPORT pIniPort,
  57. OUT LPPPJOB_ENUM *ppje);
  58. // cdwMaxCacheValidTime is the maximum expire time for the current cache
  59. // Idealy, we should put a large number to increase the effiency of the cache
  60. // so we choose 30 seconds (30*1000) as the final number. For testing purpose,
  61. // we put 15 seconds to increase the hit of the fetch data code
  62. //
  63. // weihaic 10/23/98
  64. //
  65. const DWORD cdwMaxCacheValidTime = 30*1000; // The cache content will expire after 30 seconds.
  66. const DWORD cdwMinCacheValidTime = 2*1000; // The cache content will be valid for at least 2 seconds
  67. CacheMgr::CacheMgr ():
  68. m_dwState (CACHE_STATE_INIT),
  69. m_pIniPort (NULL),
  70. m_pData (NULL),
  71. m_hDataReadyEvent (NULL),
  72. m_hHitEvent (NULL),
  73. m_hInvalidateCacheEvent (NULL),
  74. m_hThread (NULL),
  75. m_bCacheStopped (FALSE),
  76. m_bAccessed (FALSE),
  77. m_bInvalidateFlag (FALSE),
  78. m_dwThreadRefCount (0),
  79. m_bValid (FALSE)
  80. {
  81. if ((m_hDataReadyEvent = CreateEvent (NULL, TRUE, FALSE, NULL)) &&
  82. (m_hHitEvent = CreateEvent (NULL, FALSE, FALSE, NULL)) &&
  83. (m_hInvalidateCacheEvent = CreateEvent (NULL, FALSE, FALSE, NULL)) )
  84. m_bValid = TRUE;
  85. }
  86. CacheMgr::~CacheMgr ()
  87. {
  88. }
  89. VOID
  90. CacheMgr::AttachThreadHandle (
  91. HANDLE hThread
  92. )
  93. {
  94. CacheData.Lock();
  95. m_hThread = hThread;
  96. m_dwThreadRefCount = 1;
  97. DBGMSGT (DBG_CACHE_TRACE, ( TEXT ("AttachThreadHandle (hThread = %d)"), hThread));
  98. CacheData.Unlock();
  99. }
  100. HANDLE
  101. CacheMgr::GetThreadHandle (
  102. VOID
  103. )
  104. {
  105. HANDLE hThread;
  106. CacheData.Lock();
  107. hThread = m_hThread;
  108. if (m_hThread)
  109. {
  110. m_dwThreadRefCount++;
  111. }
  112. DBGMSGT (DBG_CACHE_TRACE, ( TEXT ("GetThreadHandle (hThread = %d, Count = %d)"), hThread, m_dwThreadRefCount));
  113. CacheData.Unlock();
  114. return hThread;
  115. }
  116. VOID
  117. CacheMgr::ReleaseThreadHandle (
  118. VOID
  119. )
  120. {
  121. HANDLE hThread = NULL;
  122. CacheData.Lock();
  123. if (m_hThread)
  124. {
  125. m_dwThreadRefCount--;
  126. DBGMSGT (DBG_CACHE_TRACE, ( TEXT ("ReleaseThreadHandle (hThread = %d, Count = %d)"), hThread, m_dwThreadRefCount));
  127. if (m_dwThreadRefCount == 0)
  128. {
  129. hThread = m_hThread;
  130. m_hThread = NULL;
  131. }
  132. }
  133. CacheData.Unlock();
  134. if (hThread)
  135. {
  136. CloseHandle (hThread);
  137. }
  138. }
  139. VOID
  140. CacheMgr::Shutdown ()
  141. {
  142. HANDLE hThread;
  143. CacheRead.Lock ();
  144. // No more read is possible
  145. m_bCacheStopped = TRUE;
  146. if (hThread = GetThreadHandle ()) {
  147. SetEvent (m_hInvalidateCacheEvent);
  148. // Wait for another thread to exit
  149. WaitForSingleObject (hThread, INFINITE);
  150. ReleaseThreadHandle ();
  151. }
  152. if (m_hDataReadyEvent) {
  153. CloseHandle (m_hDataReadyEvent);
  154. }
  155. if (m_hHitEvent) {
  156. CloseHandle (m_hHitEvent);
  157. }
  158. if (m_hInvalidateCacheEvent) {
  159. CloseHandle (m_hInvalidateCacheEvent);
  160. }
  161. m_bValid = FALSE;
  162. CacheRead.Unlock ();
  163. delete this;
  164. }
  165. BOOL
  166. CacheMgr::SetupAsyncFetch (
  167. PCINETMONPORT pIniPort)
  168. {
  169. BOOL bRet = FALSE;
  170. PTHREADCONTEXT pThreadData = new THREADCONTEXT;
  171. HANDLE hThread = NULL;
  172. if (pThreadData) {
  173. pThreadData->pIniPort = pIniPort;
  174. pThreadData->pCache = this;
  175. pThreadData->pSidToken = new CSid;
  176. if (pThreadData->pSidToken && pThreadData->pSidToken->bValid()) {
  177. if (hThread = CreateThread (NULL, COMMITTED_STACK_SIZE, (LPTHREAD_START_ROUTINE)CacheMgr::WorkingThread,
  178. (PVOID) pThreadData, CREATE_SUSPENDED, NULL)) {
  179. bRet = TRUE;
  180. }
  181. }
  182. if (bRet)
  183. {
  184. AttachThreadHandle (hThread);
  185. //
  186. // The thread is created in the suspended state
  187. //
  188. if (ResumeThread (hThread) == -1)
  189. {
  190. //
  191. // Resume thread failed, so we need to clean up the thread handle
  192. //
  193. ReleaseThreadHandle ();
  194. bRet = FALSE;
  195. }
  196. }
  197. if (!bRet) {
  198. if (pThreadData->pSidToken) {
  199. delete pThreadData->pSidToken;
  200. }
  201. delete (pThreadData);
  202. }
  203. }
  204. return bRet;
  205. }
  206. VOID
  207. CacheMgr::TransitState (
  208. PCINETMONPORT pIniPort)
  209. {
  210. PVOID pData = NULL;
  211. DWORD dwFetchTime = 0;
  212. CACHESTATE dwState, dwOldState;
  213. BOOL bNewData;
  214. HANDLE hHandles[2];
  215. hHandles [0] = m_hHitEvent;
  216. hHandles [1] = m_hInvalidateCacheEvent;
  217. dwState = m_dwState;
  218. do {
  219. DBGMSGT (DBG_CACHE_TRACE, ( TEXT ("TransitState: current state %d"), m_dwState));
  220. dwState = m_dwState;
  221. bNewData = FALSE;
  222. m_bAccessed = FALSE;
  223. switch (dwState) {
  224. case CACHE_STATE_INIT:
  225. // Clean the data ready event
  226. ResetEvent (m_hDataReadyEvent);
  227. if (GetFetchTime (pIniPort, &dwFetchTime, &pData)) {
  228. bNewData = TRUE;
  229. dwState = CACHE_STATE_ACCESSED_VALID;
  230. }
  231. else {
  232. //Invalid Cache Content
  233. DBGMSGT (DBG_CACHE_ERROR, ( TEXT ("TransitState: FatalError %d"), GetLastError));
  234. // Invalidate the cache content, so that when the next get comes, it will
  235. // get the NULL pointer.
  236. pData = NULL;
  237. bNewData = TRUE;
  238. dwState = CACHE_STATE_ACCESSED_VALID;
  239. }
  240. break;
  241. case CACHE_STATE_ACCESSED_VALID:
  242. WaitForSingleObject (m_hInvalidateCacheEvent, cdwMinCacheValidTime);
  243. dwState = CACHE_STATE_DATA_VALID;
  244. break;
  245. case CACHE_STATE_DATA_VALID:
  246. WaitForSingleObject (m_hInvalidateCacheEvent, dwFetchTime / 2);
  247. if (m_bAccessed) {
  248. // The cache has been accessed during the waiting time
  249. dwState = CACHE_STATE_ACCESSED_VALID_AGAIN;
  250. }
  251. else {
  252. // The cache has not been accessed during the waiting time
  253. dwState = CACHE_STATE_NOT_ACCESSED_VALID_AGAIN;
  254. }
  255. break;
  256. case CACHE_STATE_ACCESSED_VALID_AGAIN:
  257. if (GetFetchTime (pIniPort, &dwFetchTime, &pData)) {
  258. bNewData = TRUE;
  259. dwState = CACHE_STATE_ACCESSED_VALID;
  260. }
  261. else {
  262. //Invalid Cache Content
  263. DBGMSGT (DBG_CACHE_ERROR, ( TEXT ("TransitState: FatalError %d"), GetLastError));
  264. // Invalidate the cache content, so that when the next access to cache comes,
  265. // it will get a NULL pointer.
  266. pData = NULL;
  267. bNewData = TRUE;
  268. dwState = CACHE_STATE_ACCESSED_VALID;
  269. }
  270. break;
  271. case CACHE_STATE_NOT_ACCESSED_VALID_AGAIN:
  272. // This has to be a long wait so that the cache will be valid for an access long after
  273. // the last fetch happeen
  274. ResetEvent (m_hHitEvent);
  275. switch (WaitForMultipleObjects (2, hHandles, FALSE, cdwMaxCacheValidTime ))
  276. {
  277. case WAIT_TIMEOUT:
  278. dwState = CACHE_STATE_INIT;
  279. break;
  280. case WAIT_OBJECT_0:
  281. //Accessed
  282. if (GetFetchTime (pIniPort, &dwFetchTime, &pData)) {
  283. bNewData = TRUE;
  284. dwState = CACHE_STATE_ACCESSED_VALID;
  285. }
  286. else {
  287. //Invalid Cache Content
  288. DBGMSGT (DBG_CACHE_ERROR, ( TEXT ("TransitState: FatalError %d"), GetLastError));
  289. // Invalidate the cache content, so that when the next access to cache comes,
  290. // it will get a NULL pointer.
  291. pData = NULL;
  292. bNewData = TRUE;
  293. dwState = CACHE_STATE_ACCESSED_VALID;
  294. }
  295. break;
  296. case WAIT_OBJECT_0 + 1:
  297. dwState = CACHE_STATE_INIT;
  298. break;
  299. default:
  300. // ERROR
  301. DBGMSGT (DBG_CACHE_ERROR, ( TEXT ("TransitState: WaitForSingleObject FatalError %d"), GetLastError));
  302. // Invalidate the cache
  303. dwState = CACHE_STATE_INIT;
  304. break;
  305. }
  306. break;
  307. default:
  308. DBGMSGT (DBG_CACHE_ERROR, (TEXT ("AsyncFech: wrong state %d"), m_dwState));
  309. // Invalidate the cache
  310. dwState = CACHE_STATE_INIT;
  311. }
  312. if (m_bCacheStopped) {
  313. // Cache is being stopped. Cleanup everything this thread generates
  314. if (bNewData) {
  315. FreeBuffer (pIniPort, pData);
  316. }
  317. // Since the caching thread is going to abort, so we need to raise
  318. // this flag so that the waiting thread can go on.
  319. SetEvent (m_hDataReadyEvent);
  320. break;
  321. }
  322. dwOldState = m_dwState;
  323. SetState (pIniPort, dwState, bNewData, pData);
  324. if (dwOldState == CACHE_STATE_INIT) {
  325. SetEvent (m_hDataReadyEvent);
  326. }
  327. if (m_bInvalidateFlag) {
  328. // Another thread called invalidate thread and hope get rid of the thread
  329. m_dwState = CACHE_STATE_INIT;
  330. }
  331. } while ( m_dwState != CACHE_STATE_INIT );
  332. // Terminate the async fetch thread
  333. ReleaseThreadHandle ();
  334. DBGMSGT (DBG_CACHE_TRACE, (TEXT ("CacheMgr::TransitState: Async thread quit")));
  335. return;
  336. }
  337. VOID
  338. CacheMgr::SetState (
  339. PCINETMONPORT pIniPort,
  340. CACHESTATE dwState,
  341. BOOL bNewData,
  342. PVOID pNewData)
  343. {
  344. PVOID pOldData = NULL;
  345. m_bAccessed = 0;
  346. if (bNewData) {
  347. CacheData.Lock ();
  348. pOldData = m_pData;
  349. m_pData = pNewData;
  350. CacheData.Unlock ();
  351. }
  352. // This line must be here, since otherwise, the state is updated to the new one
  353. // but the data are not
  354. //
  355. m_dwState = dwState;
  356. if (pOldData) {
  357. FreeBuffer (pIniPort, pOldData);
  358. }
  359. }
  360. VOID
  361. CacheMgr::WorkingThread (
  362. PTHREADCONTEXT pThreadData)
  363. {
  364. CacheMgr *pThis = pThreadData->pCache;
  365. PCINETMONPORT pIniPort = pThreadData->pIniPort;
  366. pThreadData->pSidToken->SetCurrentSid ();
  367. delete pThreadData->pSidToken;
  368. pThreadData->pSidToken = NULL;
  369. delete pThreadData;
  370. pThis->TransitState (pIniPort);
  371. }
  372. BOOL
  373. CacheMgr::GetFetchTime (
  374. PCINETMONPORT pIniPort,
  375. LPDWORD pdwTime,
  376. PVOID *ppData)
  377. {
  378. BOOL bRet = FALSE;
  379. DWORD dwT0, dwT1;
  380. dwT0 = GetTickCount();
  381. if (FetchData (pIniPort, ppData)) {
  382. bRet = TRUE;
  383. }
  384. dwT1 = GetTickCount();
  385. *pdwTime = GetTimeDiff (dwT0, dwT1);
  386. DBGMSGT (DBG_CACHE_TRACE,
  387. (TEXT ("GetFetchTime: returns %d, timediff=%d ms"),
  388. bRet, GetTimeDiff (dwT0, dwT1)));
  389. return bRet;
  390. }
  391. PVOID
  392. CacheMgr::BeginReadCache (
  393. PCINETMONPORT pIniPort)
  394. {
  395. HANDLE hThread = NULL;
  396. if (m_bValid) {
  397. CacheRead.Lock ();
  398. CUserData CurUser;
  399. while (TRUE) {
  400. if (m_dwState == CACHE_STATE_INIT) {
  401. m_CurUser = CurUser;
  402. hThread = GetThreadHandle ();
  403. if (!hThread) {
  404. // If there is no thread running, we need to reset the dataready event
  405. ResetEvent (m_hDataReadyEvent);
  406. }
  407. if (hThread // There is already a thread running
  408. || SetupAsyncFetch (pIniPort)) {
  409. // We must leave the critical section since it might take forever to
  410. // get the information at the first time
  411. CacheRead.Unlock ();
  412. WaitForSingleObject (m_hDataReadyEvent, INFINITE);
  413. CacheRead.Lock ();
  414. }
  415. if (hThread)
  416. {
  417. ReleaseThreadHandle ();
  418. }
  419. break;
  420. }
  421. else {
  422. if (m_CurUser == CurUser) {
  423. if (m_dwState == CACHE_STATE_NOT_ACCESSED_VALID_AGAIN) {
  424. SetEvent (m_hHitEvent);
  425. }
  426. break;
  427. }
  428. else {
  429. // We must call the internal version of InvalidateCache since
  430. // we have to leave the critical section when waiting for the termination
  431. // of the working thread.
  432. //
  433. _InvalidateCache ();
  434. // Now, the state becomes CACHE_STATE_INIT
  435. }
  436. }
  437. }
  438. m_bAccessed = TRUE;
  439. BOOL bRet = CacheData.Lock ();
  440. DBGMSGT (DBG_CACHE_TRACE, (TEXT ("CacheData.Lock() = %d"), bRet));
  441. return m_pData;
  442. }
  443. else
  444. return NULL;
  445. }
  446. VOID
  447. CacheMgr::EndReadCache (VOID)
  448. {
  449. DBGMSGT (DBG_CACHE_TRACE,
  450. (TEXT ("CacheMgr::EndReadCache: Entered")));
  451. if (m_bValid) {
  452. BOOL bRet = CacheData.Unlock ();
  453. DBGMSGT (DBG_CACHE_TRACE, (TEXT ("CacheData.Unlock() = %d"), bRet));
  454. CacheRead.Unlock ();
  455. }
  456. }
  457. VOID
  458. CacheMgr::_InvalidateCache ()
  459. {
  460. HANDLE hThread = NULL;
  461. if (!m_bInvalidateFlag) {
  462. m_bInvalidateFlag = TRUE;
  463. SetEvent (m_hInvalidateCacheEvent);
  464. }
  465. if (hThread = GetThreadHandle ()) {
  466. CacheRead.Unlock ();
  467. // We must leave the critical section since we don't know how long it will take for thread to exit
  468. // Wait for another thread to exit
  469. WaitForSingleObject (hThread, INFINITE);
  470. CacheRead.Lock ();
  471. ReleaseThreadHandle ();
  472. }
  473. // Clean up the event
  474. ResetEvent (m_hInvalidateCacheEvent);
  475. m_bInvalidateFlag = FALSE;
  476. DBGMSGT (DBG_CACHE_TRACE, ( TEXT ("CacheMgr::InvalidateCache dwState=%d"), m_dwState));
  477. }
  478. VOID
  479. CacheMgr::InvalidateCache ()
  480. {
  481. CacheRead.Lock ();
  482. _InvalidateCache ();
  483. CacheRead.Unlock ();
  484. }
  485. VOID
  486. CacheMgr::InvalidateCacheForUser(
  487. CLogonUserData *pUser )
  488. /*++
  489. Routine Description:
  490. This routine checks to see whether the given user is currently controlling the cache
  491. thread. If they are, the thread is terminated.
  492. Arguments:
  493. pUser - A pointer to the user.
  494. Return Value:
  495. None.
  496. --*/
  497. {
  498. CacheRead.Lock();
  499. if (m_CurUser == *(CUserData *)pUser) // Comparison is valid after caste
  500. _InvalidateCache ();
  501. CacheRead.Unlock();
  502. }
  503. inline DWORD
  504. CacheMgr::GetTimeDiff (
  505. DWORD t0,
  506. DWORD t1)
  507. {
  508. if (t1 > t0) {
  509. return t1 - t0;
  510. }
  511. else {
  512. return DWORD(-1) - t0 + t1;
  513. }
  514. }
  515. LPVOID CacheMgr::Allocator(
  516. DWORD cb)
  517. {
  518. return new CHAR[cb];
  519. }
  520. GetPrinterCache::GetPrinterCache(
  521. PCINETMONPORT pIniPort):
  522. m_pIniPort (pIniPort)
  523. {
  524. }
  525. GetPrinterCache::~GetPrinterCache (
  526. VOID)
  527. {
  528. if (m_pData) {
  529. FreeBuffer (m_pIniPort, m_pData);
  530. }
  531. }
  532. BOOL
  533. GetPrinterCache::FetchData (
  534. PCINETMONPORT pIniPort,
  535. PVOID *ppData)
  536. {
  537. BOOL bRet = FALSE;
  538. PGETPRINTER_CACHEDATA pCacheData = NULL;
  539. DBGMSGT (DBG_CACHE_TRACE, (TEXT ("GetPrinterCache::FetchData begins")));
  540. #ifdef DEBUG
  541. if (0) {
  542. // Simulate the hanging of the current thread
  543. // For debugging purpose.
  544. MessageBox (NULL, TEXT ("GetPrinterCache::FetchData called. Press OK to continue."), TEXT ("ALERT"), MB_OK);
  545. }
  546. #endif
  547. if (pCacheData = new GETPRINTER_CACHEDATA) {
  548. semEnterCrit ();
  549. pCacheData->bRet = _ppinfo_net_get_info(pIniPort,
  550. & (pCacheData->pInfo) ,
  551. & (pCacheData->cbSize),
  552. Allocator);
  553. semLeaveCrit ();
  554. pCacheData->dwLastError = GetLastError ();
  555. DBGMSGT (DBG_CACHE_TRACE, (TEXT ("GetPrinterCache::FetchData bRet=%d, err=%d\n"),
  556. pCacheData->bRet, pCacheData->dwLastError ));
  557. //
  558. // We must return TRUE, otherwise PPGetPrinter won't get the correct last error
  559. //
  560. bRet = TRUE; //pCacheData->cbSize != 0;
  561. }
  562. if (!bRet) {
  563. DBGMSGT (DBG_CACHE_TRACE,
  564. (TEXT ("GetPrinterCache::FetchData failed, call FreeBuffer (%x, %x)"), pIniPort, pCacheData));
  565. FreeBuffer (pIniPort, pCacheData);
  566. }
  567. else {
  568. *ppData = pCacheData;
  569. }
  570. return bRet;
  571. }
  572. BOOL
  573. GetPrinterCache::FreeBuffer (
  574. PCINETMONPORT pIniPort,
  575. PVOID pData)
  576. {
  577. PGETPRINTER_CACHEDATA pCacheData = (PGETPRINTER_CACHEDATA) pData;
  578. DBGMSGT (DBG_CACHE_TRACE,
  579. (TEXT ("FreeBuffer(%x, %x) called"), pIniPort, pCacheData));
  580. if (pCacheData) {
  581. if (pCacheData->pInfo) {
  582. delete [] (PCHAR)(pCacheData->pInfo);
  583. }
  584. delete pCacheData;
  585. }
  586. return TRUE;
  587. }
  588. BOOL
  589. GetPrinterCache::BeginReadCache (
  590. PPRINTER_INFO_2 *ppInfo)
  591. {
  592. BOOL bRet = FALSE;
  593. if (m_bValid) {
  594. DBGMSGT (DBG_CACHE_TRACE,
  595. (TEXT ("GetPrinterCache::BeginReadCache: Entered")));
  596. PGETPRINTER_CACHEDATA pData = (PGETPRINTER_CACHEDATA) CacheMgr::BeginReadCache (m_pIniPort);
  597. if (pData) {
  598. if (pData->bRet) {
  599. *ppInfo = pData->pInfo;
  600. bRet = TRUE;
  601. }
  602. else {
  603. SetLastError (pData->dwLastError);
  604. }
  605. }
  606. if (!bRet && GetLastError () == ERROR_SUCCESS) {
  607. SetLastError (ERROR_CAN_NOT_COMPLETE);
  608. }
  609. DBGMSGT (DBG_CACHE_TRACE,
  610. (TEXT ("GetPrinterCache::BeginReadCache: pData = %x, return = %d, lasterror = %d"),
  611. pData, bRet, GetLastError ()));
  612. }
  613. else {
  614. SetLastError (ERROR_CAN_NOT_COMPLETE);
  615. }
  616. return bRet;
  617. }
  618. EnumJobsCache::EnumJobsCache(
  619. PCINETMONPORT pIniPort):
  620. m_pIniPort (pIniPort)
  621. {
  622. }
  623. EnumJobsCache::~EnumJobsCache (
  624. VOID)
  625. {
  626. if (m_pData) {
  627. FreeBuffer (m_pIniPort, m_pData);
  628. }
  629. }
  630. BOOL
  631. EnumJobsCache::FetchData (
  632. PCINETMONPORT pIniPort,
  633. PVOID *ppData)
  634. {
  635. BOOL bRet = FALSE;
  636. HANDLE hPort = (HANDLE)pIniPort;
  637. PENUMJOBS_CACHEDATA pCacheData = NULL;
  638. DBGMSGT (DBG_CACHE_TRACE, (TEXT ("EnumJobsCache::FetchData begins")));
  639. if (pCacheData = new ENUMJOBS_CACHEDATA) {
  640. pCacheData->pje = NULL;
  641. semEnterCrit ();
  642. pCacheData->bRet = ppjob_EnumForCache(pIniPort, & (pCacheData->pje));
  643. pCacheData->dwLastError = GetLastError ();
  644. DBGMSGT (DBG_CACHE_TRACE, (TEXT ("EnumJobsCache::FetchData bRet=%d, err=%d\n"),
  645. pCacheData->bRet, pCacheData->dwLastError ));
  646. if (pCacheData->bRet) {
  647. if (pCacheData->pje) {
  648. pCacheData->cbSize = pCacheData->pje->cbSize;
  649. }
  650. else {
  651. pCacheData->cbSize = 0;
  652. }
  653. }
  654. semLeaveCrit ();
  655. bRet = TRUE;
  656. }
  657. if (bRet) {
  658. *ppData = pCacheData;
  659. }
  660. return bRet;
  661. }
  662. BOOL
  663. EnumJobsCache::FreeBuffer (
  664. PCINETMONPORT pIniPort,
  665. PVOID pData)
  666. {
  667. PENUMJOBS_CACHEDATA pCacheData = (PENUMJOBS_CACHEDATA) pData;
  668. if (pCacheData) {
  669. if (pCacheData->pje) {
  670. // memFree has access to the global link list, so it is neccesary
  671. // to run it under critical secion.
  672. //
  673. semEnterCrit ();
  674. memFree(pCacheData->pje, memGetSize(pCacheData->pje));
  675. semLeaveCrit ();
  676. }
  677. delete pCacheData;
  678. }
  679. return TRUE;
  680. }
  681. BOOL
  682. EnumJobsCache::BeginReadCache (
  683. LPPPJOB_ENUM *ppje)
  684. {
  685. BOOL bRet = FALSE;
  686. if (m_bValid) {
  687. DBGMSGT (DBG_CACHE_TRACE,
  688. (TEXT ("EnumJobsCache::BeginReadCache: Entered")));
  689. PENUMJOBS_CACHEDATA pData = (PENUMJOBS_CACHEDATA) CacheMgr::BeginReadCache (m_pIniPort);
  690. if (pData) {
  691. if (pData->bRet) {
  692. *ppje = pData->pje;
  693. bRet = TRUE;
  694. }
  695. else {
  696. SetLastError (pData->dwLastError);
  697. }
  698. }
  699. if (!bRet && GetLastError () == ERROR_SUCCESS) {
  700. SetLastError (ERROR_CAN_NOT_COMPLETE);
  701. }
  702. DBGMSGT (DBG_CACHE_TRACE,
  703. (TEXT ("EnumJobsCache::BeginReadCache: pData = %x, return = %d, lasterror = %d"),
  704. pData, bRet, GetLastError ()));
  705. }
  706. else {
  707. SetLastError (ERROR_CAN_NOT_COMPLETE);
  708. }
  709. return bRet;
  710. }
  711. VOID
  712. EnumJobsCache::EndReadCache (
  713. VOID)
  714. {
  715. DBGMSGT (DBG_CACHE_TRACE,
  716. (TEXT ("EnumJobsCache::EndReadCache: Entered")));
  717. CacheMgr::EndReadCache ();
  718. }
  719. /*********************************************************************************
  720. ** End of File (cachemgr.cxx)
  721. *********************************************************************************/