cache.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 12k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  2. //
  3. // cache.cpp 
  4. //
  5. //   XML document cache.
  6. //
  7. //   History:
  8. //
  9. //       4/15/97  edwardp   Created.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. //
  15. #include "stdinc.h"
  16. #include "persist.h"
  17. #include "cache.h"
  18. #include "cdfidl.h"
  19. #include "xmlutil.h"
  20. #include "dll.h"
  21. //
  22. // Cache functions.
  23. //
  24. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  25. //
  26. // *** Cache_Initialize *** 
  27. //
  28. //   Prepare the XML document cache for use.
  29. //
  30. ////////////////////////////////////////////////////////////////////////////////
  31. void
  32. Cache_Initialize(
  33.     void
  34. )
  35. {
  36.     ASSERT(NULL == g_pCache);
  37.     InitializeCriticalSection(&g_csCache);
  38.     return;
  39. }
  40. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  41. //
  42. // *** Cache_Initialize *** 
  43. //
  44. //   Deactivate the cache.
  45. //
  46. ////////////////////////////////////////////////////////////////////////////////
  47. void
  48. Cache_Deinitialize(
  49.     void
  50. )
  51. {
  52.     // BUGBUG: MSXML has gone away at this point
  53.     // Cache_FreeAll();
  54.     DeleteCriticalSection(&g_csCache);
  55.     return;
  56. }
  57. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  58. //
  59. // *** Cache_EnterWriteLock ***
  60. //
  61. //    Obtain exclusive use of the XML document cache.
  62. //
  63. ////////////////////////////////////////////////////////////////////////////////
  64. void
  65. Cache_EnterWriteLock(
  66.     void
  67. )
  68. {
  69.     EnterCriticalSection(&g_csCache);
  70.     return;
  71. }
  72. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  73. //
  74. // *** Cache_EnterWriteLock ***
  75. //
  76. //    Release exclusive use of the XML document cache.
  77. //
  78. ////////////////////////////////////////////////////////////////////////////////
  79. void
  80. Cache_LeaveWriteLock(
  81.     void
  82. )
  83. {
  84.     LeaveCriticalSection(&g_csCache);
  85.     return;
  86. }
  87. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  88. //
  89. // *** Cache_EnterReadLock ***
  90. //
  91. //    Exclude writes to the the items list.  Currently this also excludes other
  92. //    reads.  If need be this can be modified to allow multiple reads while
  93. //    still excluding writes.
  94. //
  95. ////////////////////////////////////////////////////////////////////////////////
  96. void
  97. Cache_EnterReadLock(
  98.     void
  99. )
  100. {
  101.     EnterCriticalSection(&g_csCache);
  102.     return;
  103. }
  104. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  105. //
  106. // *** Cache_LeaveReadLock ***
  107. //
  108. //    Release a read hold on the use of the XML document cache.
  109. //
  110. ////////////////////////////////////////////////////////////////////////////////
  111. void
  112. Cache_LeaveReadLock(
  113.     void
  114. )
  115. {
  116.     LeaveCriticalSection(&g_csCache);
  117.     return;
  118. }
  119. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  120. //
  121. // *** Cache_AddItem ***
  122. //
  123. //
  124. // Description:
  125. //     Add an xml document to the cache.
  126. //
  127. // Parameters:
  128. //     [In]  szURL         - The URL of the cdf file.
  129. //     [In]  pIXMLDocument - The already parsed xml document.
  130. //
  131. // Return:
  132. //     S_OK if the document was added to the cache.
  133. //     E_OUTOFMEMORY if the document couldn't be aded to the cache.
  134. //
  135. // Comments:
  136. //     The xml document is AddRefed when inserted into the cache and
  137. //     Released on removal from the cache.
  138. //
  139. ////////////////////////////////////////////////////////////////////////////////
  140. HRESULT
  141. Cache_AddItem(
  142.     LPTSTR szURL,
  143.     IXMLDocument* pIXMLDocument,
  144.     DWORD dwParseFlags,
  145.     FILETIME ftLastMod,
  146.     DWORD dwCacheCount
  147. )
  148. {
  149.     ASSERT(szURL);
  150.     ASSERT(pIXMLDocument);
  151.     Cache_EnterWriteLock();
  152.     HRESULT hr;
  153.     PCACHEITEM pNewItem = new CACHEITEM;
  154.     if (pNewItem)
  155.     {
  156.         LPTSTR szURLCopy = (LPTSTR)new TCHAR[(StrLen(szURL) + 1)];
  157.         if (szURLCopy)
  158.         {
  159.             //
  160.             // Limit the cache to one item by freeing all current items.
  161.             //
  162.             Cache_FreeAll();
  163.             //
  164.             // Remove an old cache entry for this url if it exists.
  165.             //
  166.             // Check no longer needed since we just cleared the cache.
  167.             /*IXMLDocument* pIXMLDocumentOld;
  168.             if (SUCCEEDED(Cache_QueryItem(szURL, &pIXMLDocumentOld,
  169.                                           PARSE_LOCAL)))
  170.             {
  171.                 ASSERT(pIXMLDocumentOld);
  172.                 Cache_RemoveItem(szURL);
  173.                 pIXMLDocumentOld->Release();
  174.             }*/
  175.             StrCpy(szURLCopy, szURL);
  176.             pIXMLDocument->AddRef();
  177.             pNewItem->szURL         = szURLCopy;
  178.             pNewItem->dwParseFlags  = dwParseFlags;
  179.             pNewItem->ftLastMod     = ftLastMod;
  180.             pNewItem->dwCacheCount  = dwCacheCount;
  181.             pNewItem->pIXMLDocument = pIXMLDocument;
  182.             //
  183.             // REVIEW:  Check for duplicate cache items?
  184.             //
  185.             pNewItem->pNext = g_pCache;
  186.             g_pCache = pNewItem;
  187.             hr = S_OK;
  188.         }
  189.         else
  190.         {
  191.             delete pNewItem;
  192.             hr = E_OUTOFMEMORY;
  193.         }
  194.     }
  195.     else
  196.     {
  197.         hr = E_OUTOFMEMORY;
  198.     }
  199.     Cache_LeaveWriteLock();
  200.     return hr;
  201. }
  202. //
  203. //
  204. //
  205. BOOL
  206. IsEmptyTime(
  207.     FILETIME ft
  208. )
  209. {
  210.     return (0 == ft.dwLowDateTime && 0 == ft.dwHighDateTime);
  211. }
  212. BOOL
  213. IsEqualTime(
  214.     FILETIME ft1,
  215.     FILETIME ft2
  216. )
  217. {
  218.     return ((ft1.dwLowDateTime == ft2.dwLowDateTime) && 
  219.             (ft1.dwHighDateTime == ft2.dwHighDateTime));
  220. }
  221. void
  222. Cache_RefreshItem(
  223.     CACHEITEM* pItem,
  224.     LPTSTR pszLocalFile,
  225.     FILETIME ftLastMod
  226. )
  227. {
  228.     ASSERT(pItem);
  229.     //
  230.     // Try and parse the cdf from the wininet cache.
  231.     //
  232.     IXMLDocument* pIXMLDocument;
  233.     HRESULT hr;
  234.     DLL_ForcePreloadDlls(PRELOAD_MSXML);
  235.     
  236.     hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  237.                           IID_IXMLDocument, (void**)&pIXMLDocument);
  238.     BOOL bCoInit = FALSE;
  239.     if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) &&
  240.         SUCCEEDED(CoInitialize(NULL)))
  241.     {
  242.         bCoInit = TRUE;
  243.         hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  244.                               IID_IXMLDocument, (void**)&pIXMLDocument);
  245.     }
  246.     if (SUCCEEDED(hr))
  247.     {
  248.         ASSERT(pIXMLDocument);
  249.         hr = XML_SynchronousParse(pIXMLDocument, pszLocalFile);
  250.         if (FAILED(hr))
  251.             pIXMLDocument->Release();
  252.     }
  253.     if (bCoInit)
  254.         CoUninitialize();
  255.     //
  256.     // If the new cdf was parsed, replace the old one.
  257.     //
  258.     if (SUCCEEDED(hr))
  259.     {
  260.         pItem->pIXMLDocument->Release();
  261.         pItem->pIXMLDocument = pIXMLDocument;
  262.         pItem->ftLastMod = ftLastMod;
  263.     }
  264.     return;
  265. }
  266. BOOL
  267. Cache_IsItemFresh(
  268.     CACHEITEM* pItem,
  269.     DWORD dwParseFlags
  270. )
  271. {
  272.     ASSERT(pItem);
  273.     BOOL  fRet;
  274.     DWORD dwCurrentCacheCount = g_dwCacheCount;                            
  275.     //
  276.     // If the caller asked for "Net" quality data and we only have "Local" data
  277.     // then throw the "Local" data away.  The resultant cache miss will cause
  278.     // the caller to pick up fresher data.
  279.     //
  280.     if ((dwParseFlags & PARSE_NET) && (pItem->dwParseFlags & PARSE_LOCAL))
  281.     {
  282.         fRet = FALSE;
  283.     }
  284.     else
  285.     {
  286.         fRet = TRUE;
  287.         //
  288.         // If the global cache counter is greater than the counter for this
  289.         // item, then a cdf has been added to the cache.
  290.         //
  291.         if (dwCurrentCacheCount > pItem->dwCacheCount)
  292.         {
  293.             //
  294.             // Get the last mod time from the the cdf in the wininet cache.
  295.             //
  296.             FILETIME ftLastMod;
  297.             TCHAR    szLocalFile[MAX_PATH];
  298.             if (SUCCEEDED(URLGetLocalFileName(pItem->szURL, szLocalFile,
  299.                                 ARRAYSIZE(szLocalFile), &ftLastMod)))
  300.             {
  301.                 //
  302.                 //  If the last mod times are different then the cdf in the
  303.                 //  wininet cache is newer, pick it up.
  304.                 //  If there are no last modified times then do the conservative
  305.                 //  thing and pick up the cdf from the wininet cache.
  306.                 //
  307.                 if ((IsEmptyTime(ftLastMod) && IsEmptyTime(pItem->ftLastMod)) ||
  308.                     !IsEqualTime(ftLastMod, pItem->ftLastMod))
  309.                 {
  310.                     Cache_RefreshItem(pItem, szLocalFile, ftLastMod);
  311.                 }
  312.             }
  313.             pItem->dwCacheCount = dwCurrentCacheCount;
  314.         }
  315.     }
  316.     return fRet;
  317. }
  318. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  319. //
  320. // *** Cache_QueryItem ***
  321. //
  322. //
  323. // Description:
  324. //     Returns a xml document from the cache if it is found.
  325. //
  326. // Parameters:
  327. //     [In]  szURL          - The URL associated with the xml document.
  328. //     [Out] ppIXMLDocument - A pointer that receives the xml document.
  329. //
  330. // Return:
  331. //     S_OK if the document associtaed with the given URL is found in the cache.
  332. //     E_FAIL if the document isn't in the cache.
  333. //
  334. // Comments:
  335. //     The returned pointer is AddRefed.  The caller isresposible for releasing
  336. //     this pointer.
  337. //
  338. ////////////////////////////////////////////////////////////////////////////////
  339. HRESULT
  340. Cache_QueryItem(
  341.     LPTSTR szURL,
  342.     IXMLDocument** ppIXMLDocument,
  343.     DWORD dwParseFlags
  344. )
  345. {
  346.     ASSERT(szURL);
  347.     ASSERT(ppIXMLDocument);
  348.     HRESULT hr = E_FAIL;
  349.     Cache_EnterReadLock();
  350.     PCACHEITEM pItem = g_pCache;
  351.     //
  352.     // REVIEW: Use CompareUrl from shlwapip?
  353.     //
  354.     while (pItem && !StrEql(szURL, pItem->szURL))
  355.         pItem = pItem->pNext;
  356.     if (pItem)
  357.     {
  358.         if (Cache_IsItemFresh(pItem, dwParseFlags))
  359.         {
  360.             ASSERT(pItem->pIXMLDocument);
  361.             pItem->pIXMLDocument->AddRef();
  362.             *ppIXMLDocument = pItem->pIXMLDocument;
  363.             hr = S_OK;
  364.         }
  365.         else
  366.         {
  367.             Cache_RemoveItem(szURL);
  368.         }
  369.     }
  370.     Cache_LeaveReadLock();
  371.     ASSERT(SUCCEEDED(hr) && ppIXMLDocument || FAILED(hr));
  372.     return hr;
  373. }
  374. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  375. //
  376. // *** Cache_FreeAll ***
  377. //
  378. //
  379. // Description:
  380. //     Frees all items from the xml document cache.
  381. //
  382. // Parameters:
  383. //     None.
  384. //
  385. // Return:
  386. //     None.
  387. //
  388. // Comments:
  389. //     Frees all memory held in the xml document cache.
  390. //
  391. ////////////////////////////////////////////////////////////////////////////////
  392. void
  393. Cache_FreeAll(
  394.     void
  395. )
  396. {
  397.     Cache_EnterWriteLock();
  398.  
  399.     PCACHEITEM pItem = g_pCache;
  400.     g_pCache = NULL;
  401.     Cache_LeaveWriteLock();
  402.     while (pItem)
  403.     {
  404.         PCACHEITEM pNext = pItem->pNext;
  405.         ASSERT(pItem->szURL);
  406.         ASSERT(pItem->pIXMLDocument);
  407.         pItem->pIXMLDocument->Release();
  408.         delete [] pItem->szURL;
  409.         delete pItem;
  410.         pItem = pNext;
  411.     }
  412.     return;
  413. }
  414. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  415. //
  416. // *** Cache_FreeItem ***
  417. //
  418. //
  419. // Description:
  420. //     Frees item associated with given URL from the xml document cache.
  421. //
  422. // Parameters:
  423. //     LPTSTR szURL
  424. //
  425. // Return:
  426. //     HRESULT S_OK if item in cache and deleted, E_FAIL if item not in cache
  427. //
  428. ////////////////////////////////////////////////////////////////////////////////
  429. HRESULT
  430. Cache_RemoveItem(
  431.     LPCTSTR szURL
  432. )
  433. {
  434.     ASSERT(szURL);
  435.     HRESULT hr;
  436.     Cache_EnterWriteLock();
  437.     PCACHEITEM pItem = g_pCache;
  438.     PCACHEITEM pItemPrev = NULL;
  439.     //
  440.     // REVIEW: Use CompareUrl from slwapip?.
  441.     //
  442.     while (pItem && !StrEql(szURL, pItem->szURL))
  443.     {
  444.         pItemPrev = pItem;
  445.         pItem = pItem->pNext;
  446.     }
  447.     if (pItem)
  448.     {
  449.         ASSERT(pItem->pIXMLDocument);
  450.         if (pItemPrev)
  451.         {
  452.             pItemPrev->pNext = pItem->pNext;
  453.         }
  454.         else
  455.         {
  456.             g_pCache = pItem->pNext; // handle remove first item case
  457.         }
  458.         pItem->pIXMLDocument->Release();
  459.         delete [] pItem->szURL;
  460.         delete pItem;
  461.         hr = S_OK;
  462.     }
  463.     else
  464.     {
  465.         hr = E_FAIL;
  466.     }
  467.     Cache_LeaveWriteLock();
  468.     return hr;
  469. }