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.

1525 lines
41 KiB

  1. /******************************************************************************
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. Cache.cpp
  5. Abstract:
  6. Handles caching of database lookups.
  7. Revision History:
  8. ******************************************************************************/
  9. #include "stdafx.h"
  10. ////////////////////////////////////////////////////////////////////////////////
  11. static const DWORD l_dwVersion = 0x01314351; // QC1 01
  12. static const DWORD l_dwSizeThresholdHIGH = 2048*1024;
  13. static const DWORD l_dwSizeThresholdLOW = 1024*1024;
  14. static const DATE l_dSaveThreshold = (60.0/86400.0); // 60 seconds.
  15. static const WCHAR l_szBase [] = HC_ROOT_HELPSVC_CONFIG L"\\Cache";
  16. static const WCHAR l_szIndex [] = L"Directory.bin";
  17. static const WCHAR l_szQuery [] = L"Query_%08x.bin";
  18. static const WCHAR l_szBackup[] = L".bak";
  19. ////////////////////////////////////////////////////////////////////////////////
  20. ////////////////////////////////////////////////////////////////////////////////
  21. HRESULT Taxonomy::operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ Taxonomy::Cache::NodeEntry& val )
  22. {
  23. __HCP_FUNC_ENTRY( "Taxonomy::operator>> Taxonomy::Cache::NodeEntry" );
  24. HRESULT hr;
  25. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_rs_data );
  26. hr = S_OK;
  27. __HCP_FUNC_CLEANUP;
  28. __HCP_FUNC_EXIT(hr);
  29. }
  30. HRESULT Taxonomy::operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const Taxonomy::Cache::NodeEntry& val )
  31. {
  32. __HCP_FUNC_ENTRY( "Taxonomy::operator<< Taxonomy::Cache::NodeEntry" );
  33. HRESULT hr;
  34. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_rs_data );
  35. hr = S_OK;
  36. __HCP_FUNC_CLEANUP;
  37. __HCP_FUNC_EXIT(hr);
  38. }
  39. Taxonomy::Cache::NodeEntry::NodeEntry()
  40. {
  41. m_rs_data.m_ID_parent = -1;
  42. m_rs_data.m_ID_node = -1;
  43. }
  44. bool Taxonomy::Cache::NodeEntry::operator<( /*[in]*/ NodeEntry const &en ) const
  45. {
  46. long lCmp = (m_rs_data.m_ID_parent - en.m_rs_data.m_ID_parent);
  47. if(lCmp == 0)
  48. {
  49. lCmp = MPC::StrICmp( m_rs_data.m_strEntry, en.m_rs_data.m_strEntry );
  50. }
  51. return (lCmp < 0);
  52. }
  53. bool Taxonomy::Cache::NodeEntry::operator==( /*[in]*/ long ID ) const
  54. {
  55. return m_rs_data.m_ID_node == ID;
  56. }
  57. Taxonomy::Cache::NodeEntry::MatchNode::MatchNode( /*[in]*/ long ID )
  58. {
  59. m_ID = ID; // long m_ID;
  60. }
  61. bool Taxonomy::Cache::NodeEntry::MatchNode::operator()( /*[in]*/ Taxonomy::Cache::NodeEntry const &en ) const
  62. {
  63. return en == m_ID;
  64. }
  65. ////////////////////////////////////////////////////////////////////////////////
  66. ////////////////////////////////////////////////////////////////////////////////
  67. HRESULT Taxonomy::operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ Taxonomy::Cache::QueryEntry& val )
  68. {
  69. __HCP_FUNC_ENTRY( "Taxonomy::operator>> Taxonomy::Cache::QueryEntry" );
  70. HRESULT hr;
  71. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_strID );
  72. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_iType );
  73. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_iSequence );
  74. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_fNull );
  75. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_dwSize );
  76. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> val.m_dLastUsed );
  77. val.m_fRemoved = false;
  78. hr = S_OK;
  79. __HCP_FUNC_CLEANUP;
  80. __HCP_FUNC_EXIT(hr);
  81. }
  82. HRESULT Taxonomy::operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const Taxonomy::Cache::QueryEntry& val )
  83. {
  84. __HCP_FUNC_ENTRY( "Taxonomy::operator<< Taxonomy::Cache::QueryEntry" );
  85. HRESULT hr;
  86. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_strID );
  87. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_iType );
  88. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_iSequence );
  89. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_fNull );
  90. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_dwSize );
  91. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << val.m_dLastUsed );
  92. hr = S_OK;
  93. __HCP_FUNC_CLEANUP;
  94. __HCP_FUNC_EXIT(hr);
  95. }
  96. Taxonomy::Cache::QueryEntry::QueryEntry()
  97. {
  98. // MPC::wstring m_strID;
  99. m_iType = OfflineCache::ET_INVALID; // int m_iType;
  100. m_iSequence = 0; // int m_iSequence;
  101. m_fNull = true; // bool m_fNull;
  102. //
  103. m_dwSize = 0; // DWORD m_dwSize;
  104. m_dLastUsed = 0; // DATE m_dLastUsed;
  105. m_fRemoved = true; // bool m_fRemoved;
  106. }
  107. bool Taxonomy::Cache::QueryEntry::operator<( /*[in]*/ QueryEntry const &en ) const
  108. {
  109. int iCmp = MPC::StrCmp( m_strID, en.m_strID );
  110. if(iCmp == 0)
  111. {
  112. iCmp = (m_iType - en.m_iType);
  113. }
  114. return (iCmp < 0);
  115. }
  116. ////////////////////////////////////////
  117. void Taxonomy::Cache::QueryEntry::Touch()
  118. {
  119. m_dLastUsed = MPC::GetLocalTime();
  120. m_fRemoved = false;
  121. }
  122. HRESULT Taxonomy::Cache::QueryEntry::GetFile( /*[out]*/ MPC::wstring& strFile )
  123. {
  124. WCHAR rgTmp[64]; swprintf( rgTmp, l_szQuery, m_iSequence );
  125. strFile = rgTmp;
  126. return S_OK;
  127. }
  128. ////////////////////////////////////////
  129. HRESULT Taxonomy::Cache::QueryEntry::Store( /*[in]*/ MPC::StorageObject& disk ,
  130. /*[in]*/ const CPCHQueryResultCollection* pColl )
  131. {
  132. __HCP_FUNC_ENTRY( "Taxonomy::Cache::QueryEntry::Store" );
  133. HRESULT hr;
  134. MPC::StorageObject* child;
  135. MPC::wstring strFile;
  136. __MPC_EXIT_IF_METHOD_FAILS(hr, GetFile( strFile ));
  137. m_fNull = (pColl->Size() == 0);
  138. __MPC_EXIT_IF_METHOD_FAILS(hr, disk.GetChild( strFile.c_str(), child, STGM_READWRITE, (m_fNull == false) ? STGTY_STREAM : 0 ));
  139. if(m_fNull == false)
  140. {
  141. if(child)
  142. {
  143. CComPtr<IStream> stream;
  144. __MPC_EXIT_IF_METHOD_FAILS(hr, child->GetStream( stream ));
  145. if(stream)
  146. {
  147. STATSTG statstg;
  148. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->SaveToCache( stream ));
  149. __MPC_EXIT_IF_METHOD_FAILS(hr, stream->Stat( &statstg, STATFLAG_NONAME ));
  150. m_dwSize = statstg.cbSize.LowPart;
  151. }
  152. }
  153. }
  154. else
  155. {
  156. if(child)
  157. {
  158. __MPC_EXIT_IF_METHOD_FAILS(hr, child->Delete());
  159. }
  160. }
  161. Touch();
  162. hr = S_OK;
  163. __HCP_FUNC_CLEANUP;
  164. __HCP_FUNC_EXIT(hr);
  165. }
  166. HRESULT Taxonomy::Cache::QueryEntry::Retrieve( /*[in]*/ MPC::StorageObject& disk ,
  167. /*[in]*/ CPCHQueryResultCollection* pColl )
  168. {
  169. __HCP_FUNC_ENTRY( "Taxonomy::Cache::QueryEntry::Retrieve" );
  170. HRESULT hr;
  171. if(m_fNull == false)
  172. {
  173. MPC::StorageObject* child;
  174. MPC::wstring strFile;
  175. __MPC_EXIT_IF_METHOD_FAILS(hr, GetFile( strFile ));
  176. __MPC_EXIT_IF_METHOD_FAILS(hr, disk.GetChild( strFile.c_str(), child, STGM_READWRITE, 0 ));
  177. if(child)
  178. {
  179. CComPtr<IStream> stream;
  180. __MPC_EXIT_IF_METHOD_FAILS(hr, child->GetStream( stream ));
  181. if(stream)
  182. {
  183. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->LoadFromCache( stream ));
  184. }
  185. }
  186. }
  187. Touch();
  188. hr = S_OK;
  189. __HCP_FUNC_CLEANUP;
  190. __HCP_FUNC_EXIT(hr);
  191. }
  192. HRESULT Taxonomy::Cache::QueryEntry::Release( /*[in]*/ MPC::StorageObject& disk )
  193. {
  194. __HCP_FUNC_ENTRY( "Taxonomy::Cache::QueryEntry::Release" );
  195. HRESULT hr;
  196. if(m_fNull == false)
  197. {
  198. MPC::StorageObject* child;
  199. MPC::wstring strFile;
  200. __MPC_EXIT_IF_METHOD_FAILS(hr, GetFile( strFile ));
  201. __MPC_EXIT_IF_METHOD_FAILS(hr, disk.GetChild( strFile.c_str(), child, STGM_READWRITE, 0 ));
  202. if(child)
  203. {
  204. __MPC_EXIT_IF_METHOD_FAILS(hr, child->Delete());
  205. }
  206. }
  207. m_fRemoved = true;
  208. hr = S_OK;
  209. __HCP_FUNC_CLEANUP;
  210. __HCP_FUNC_EXIT(hr);
  211. }
  212. ////////////////////////////////////////////////////////////////////////////////
  213. ////////////////////////////////////////////////////////////////////////////////
  214. bool Taxonomy::Cache::SortEntries::operator()( /*[in]*/ QueryEntry* const &left, /*[in]*/ QueryEntry* const &right ) const
  215. {
  216. return (left->m_dLastUsed < right->m_dLastUsed);
  217. }
  218. ////////////////////////////////////////////////////////////////////////////////
  219. //
  220. // ITSS.DLL is broken under IA64....
  221. //
  222. #ifdef _IA64_
  223. #define CACHEDHELPSET_STORAGETOUSE false
  224. #else
  225. #define CACHEDHELPSET_STORAGETOUSE true
  226. #endif
  227. Taxonomy::Cache::CachedHelpSet::CachedHelpSet() : m_disk( STGM_READWRITE, /*fITSS*/CACHEDHELPSET_STORAGETOUSE )
  228. {
  229. Init();
  230. }
  231. Taxonomy::Cache::CachedHelpSet::~CachedHelpSet()
  232. {
  233. if(m_fDirty)
  234. {
  235. (void)EnsureInSync( true );
  236. }
  237. //
  238. // Copy working file as the backup.
  239. //
  240. if(m_fLoaded)
  241. {
  242. MPC::wstring strFileBack = m_strFile; strFileBack += l_szBackup;
  243. if(SUCCEEDED(m_disk.Compact()))
  244. {
  245. (void)MPC::MoveFile( m_strFile, strFileBack );
  246. }
  247. }
  248. }
  249. Taxonomy::Cache::CachedHelpSet::CachedHelpSet( /*[in]*/ const CachedHelpSet& chs ) : m_disk( STGM_READWRITE, /*fITSS*/CACHEDHELPSET_STORAGETOUSE )
  250. {
  251. Init();
  252. m_ths = chs.m_ths; // Taxonomy::HelpSet m_ths;
  253. m_strFile = chs.m_strFile; // MPC::wstring m_strFile;
  254. // MPC::StorageObject m_disk;
  255. //
  256. // bool m_fLoaded;
  257. // bool m_fDirty;
  258. // bool m_fMarkedForLoad;
  259. // DATE m_dLastSaved;
  260. // long m_lTopNode;
  261. // NodeEntrySet m_setNodes;
  262. // QueryEntrySet m_setQueries;
  263. // int m_iLastSequence;
  264. }
  265. Taxonomy::Cache::CachedHelpSet& Taxonomy::Cache::CachedHelpSet::operator=( /*[in]*/ const CachedHelpSet& chs )
  266. {
  267. Clean();
  268. m_ths = chs.m_ths; // Taxonomy::HelpSet m_ths;
  269. m_strFile = chs.m_strFile; // MPC::wstring m_strFile;
  270. // MPC::StorageObject m_disk;
  271. //
  272. // bool m_fLoaded;
  273. // bool m_fDirty;
  274. // bool m_fMarkedForLoad;
  275. // DATE m_dLastSaved;
  276. // long m_lTopNode;
  277. // NodeEntrySet m_setNodes;
  278. // QueryEntrySet m_setQueries;
  279. // int m_iLastSequence;
  280. return *this;
  281. }
  282. bool Taxonomy::Cache::CachedHelpSet::operator<( /*[in]*/ CachedHelpSet const &hs ) const
  283. {
  284. return m_ths < hs.m_ths;
  285. }
  286. ////////////////////////////////////////////////////////////////////////////////
  287. void Taxonomy::Cache::CachedHelpSet::Init()
  288. {
  289. // Taxonomy::HelpSet m_ths;
  290. // MPC::wstring m_strFile;
  291. // MPC::StorageObject m_disk;
  292. //
  293. m_fLoaded = false; // bool m_fLoaded;
  294. m_fDirty = false; // bool m_fDirty;
  295. m_fMarkedForLoad = false; // bool m_fMarkedForLoad;
  296. m_dLastSaved = 0; // DATE m_dLastSaved;
  297. m_lTopNode = -1; // long m_lTopNode;
  298. // NodeEntrySet m_setNodes;
  299. // QueryEntrySet m_setQueries;
  300. m_iLastSequence = 1; // int m_iLastSequence;
  301. }
  302. void Taxonomy::Cache::CachedHelpSet::Clean()
  303. {
  304. // Taxonomy::HelpSet m_ths;
  305. // MPC::wstring m_strFile;
  306. m_disk.Release(); // MPC::StorageObject m_disk;
  307. //
  308. m_fLoaded = false; // bool m_fLoaded;
  309. m_fDirty = false; // bool m_fDirty;
  310. // DATE m_dLastSaved;
  311. m_lTopNode = -1; // long m_lTopNode;
  312. m_setNodes .clear(); // NodeEntrySet m_setNodes;
  313. m_setQueries .clear(); // QueryEntrySet m_setQueries;
  314. m_iLastSequence = 1; // int m_iLastSequence;
  315. }
  316. HRESULT Taxonomy::Cache::CachedHelpSet::Load()
  317. {
  318. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::Load" );
  319. HRESULT hr;
  320. MPC::StorageObject* child;
  321. Clean();
  322. DEBUG_AppendPerf( DEBUG_PERF_CACHE_L1, "Loading Taxonomy Cache" );
  323. //
  324. // Copy the backup on top of the working file.
  325. //
  326. {
  327. MPC::wstring strFileBack = m_strFile; strFileBack += l_szBackup;
  328. (void)MPC::DeleteFile( m_strFile );
  329. (void)MPC::CopyFile ( strFileBack, m_strFile );
  330. }
  331. if(FAILED(m_disk.Exists()))
  332. {
  333. __MPC_EXIT_IF_METHOD_FAILS(hr, m_disk.Create());
  334. }
  335. __MPC_EXIT_IF_METHOD_FAILS(hr, m_disk.GetChild( l_szIndex, child, STGM_READWRITE, 0 ));
  336. if(child)
  337. {
  338. CComPtr<IStream> stream;
  339. __MPC_EXIT_IF_METHOD_FAILS(hr, child->GetStream( stream ));
  340. if(stream)
  341. {
  342. MPC::Serializer_IStream streamReal( stream );
  343. MPC::Serializer_Buffering streamBuf ( streamReal );
  344. DWORD dwVer;
  345. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> dwVer ); if(dwVer != l_dwVersion) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  346. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> m_iLastSequence);
  347. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> m_lTopNode );
  348. DEBUG_AppendPerf( DEBUG_PERF_CACHE_L1, "Loading Taxonomy Cache : nodes" );
  349. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> m_setNodes );
  350. DEBUG_AppendPerf( DEBUG_PERF_CACHE_L1, "Loading Taxonomy Cache : queries" );
  351. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> m_setQueries );
  352. }
  353. }
  354. DEBUG_AppendPerf( DEBUG_PERF_CACHE_L1, "Loaded Taxonomy Cache" );
  355. hr = S_OK;
  356. __HCP_FUNC_CLEANUP;
  357. if(FAILED(hr)) Clean();
  358. __HCP_FUNC_EXIT(hr);
  359. }
  360. HRESULT Taxonomy::Cache::CachedHelpSet::Save()
  361. {
  362. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::Save" );
  363. HRESULT hr;
  364. MPC::StorageObject* child;
  365. if(FAILED(m_disk.Exists()))
  366. {
  367. __MPC_EXIT_IF_METHOD_FAILS(hr, m_disk.Create());
  368. }
  369. __MPC_EXIT_IF_METHOD_FAILS(hr, m_disk.GetChild( l_szIndex, child, STGM_READWRITE, STGTY_STREAM ));
  370. if(child)
  371. {
  372. CComPtr<IStream> stream;
  373. __MPC_EXIT_IF_METHOD_FAILS(hr, child->GetStream( stream ));
  374. if(stream)
  375. {
  376. MPC::Serializer_IStream streamReal( stream );
  377. MPC::Serializer_Buffering streamBuf ( streamReal );
  378. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << l_dwVersion );
  379. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << m_iLastSequence);
  380. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << m_lTopNode );
  381. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << m_setNodes );
  382. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << m_setQueries );
  383. __MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf.Flush());
  384. }
  385. }
  386. #if 0
  387. ////////////////////////////////////////////////////////////////////////////////
  388. //
  389. // DEBUG CODE
  390. //
  391. {
  392. USES_CONVERSION;
  393. HHK::Writer writer;
  394. CHAR rgBuf[1024];
  395. QueryEntryIter it;
  396. SortEntries Pr;
  397. SortedEntryVec vec;
  398. SortedEntryIter it2;
  399. strFile += L".debug";
  400. __MPC_EXIT_IF_METHOD_FAILS(hr, writer.Init( strFile.c_str() ));
  401. for(it = m_setQueries.begin(); it != m_setQueries.end(); it++)
  402. {
  403. vec.push_back( &(*it) );
  404. }
  405. std::sort( vec.begin(), vec.end(), Pr );
  406. for(it2 = vec.begin(); it2 != vec.end(); it2++)
  407. {
  408. QueryEntry* en = *it2;
  409. sprintf( rgBuf, "%80s: %1d %3d %5d %1d %5.12g\n",
  410. W2A( en->m_strID.c_str() ),
  411. en->m_iType ,
  412. en->m_iSequence ,
  413. (int)en->m_dwSize ,
  414. (int)en->m_fRemoved ,
  415. en->m_dLastUsed );
  416. __MPC_EXIT_IF_METHOD_FAILS(hr, writer.OutputLine( rgBuf ));
  417. }
  418. }
  419. //
  420. // DEBUG CODE
  421. //
  422. ////////////////////////////////////////////////////////////////////////////////
  423. #endif
  424. hr = S_OK;
  425. __HCP_FUNC_CLEANUP;
  426. __HCP_FUNC_EXIT(hr);
  427. }
  428. HRESULT Taxonomy::Cache::CachedHelpSet::EnsureInSync( /*[in]*/ bool fForceSave )
  429. {
  430. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::EnsureInSync" );
  431. HRESULT hr;
  432. if(m_fLoaded == false)
  433. {
  434. m_fDirty = false;
  435. m_disk = m_strFile.c_str();
  436. __MPC_EXIT_IF_METHOD_FAILS(hr, Load());
  437. m_dLastSaved = MPC::GetSystemTime();
  438. m_fLoaded = true;
  439. }
  440. if(m_fDirty)
  441. {
  442. DATE dNow = MPC::GetSystemTime();
  443. if(fForceSave == false)
  444. {
  445. if(dNow - m_dLastSaved > l_dSaveThreshold)
  446. {
  447. fForceSave = true;
  448. }
  449. }
  450. if(fForceSave)
  451. {
  452. __MPC_EXIT_IF_METHOD_FAILS(hr, Save());
  453. m_dLastSaved = dNow;
  454. m_fDirty = false;
  455. }
  456. }
  457. hr = S_OK;
  458. __HCP_FUNC_CLEANUP;
  459. __HCP_FUNC_EXIT(hr);
  460. }
  461. ////////////////////
  462. HRESULT Taxonomy::Cache::CachedHelpSet::GenerateDefaultQueries( /*[in]*/ Taxonomy::Settings& ts ,
  463. /*[in]*/ Taxonomy::Updater& updater ,
  464. /*[in]*/ long ID ,
  465. /*[in]*/ long lLevel )
  466. {
  467. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::GenerateDefaultQueries" );
  468. HRESULT hr;
  469. CComPtr<CPCHQueryResultCollection> coll;
  470. MPC::wstring strPath;
  471. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &coll ));
  472. __MPC_EXIT_IF_METHOD_FAILS(hr, BuildNodePath( ID, strPath, /*fParent*/false ));
  473. //
  474. // Build the queries.
  475. //
  476. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.LookupNode ( strPath.c_str(), coll )); coll->Erase();
  477. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.LookupSubNodes ( strPath.c_str(), /*fVisibleOnly*/true, coll )); coll->Erase();
  478. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.LookupNodesAndTopics( strPath.c_str(), /*fVisibleOnly*/true, coll )); coll->Erase();
  479. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.LookupTopics ( strPath.c_str(), /*fVisibleOnly*/true, coll )); coll->Erase();
  480. //
  481. // Recurse for sub-levels.
  482. //
  483. if(lLevel++ < 3)
  484. {
  485. MatchSet res;
  486. MatchIter it;
  487. __MPC_EXIT_IF_METHOD_FAILS(hr, LocateSubNodes( ID, /*fRecurse*/false, /*fOnlyVisible*/true, res ));
  488. for(it=res.begin(); it!=res.end(); it++)
  489. {
  490. __MPC_EXIT_IF_METHOD_FAILS(hr, GenerateDefaultQueries( ts, updater, *it, lLevel ));
  491. }
  492. }
  493. hr = S_OK;
  494. __HCP_FUNC_CLEANUP;
  495. __HCP_FUNC_EXIT(hr);
  496. }
  497. HRESULT Taxonomy::Cache::CachedHelpSet::GenerateDefaultQueries( /*[in]*/ Taxonomy::Settings& ts ,
  498. /*[in]*/ Taxonomy::Updater& updater )
  499. {
  500. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::GenerateDefaultQueries" );
  501. HRESULT hr;
  502. static WCHAR* c_rgNodes[] = { L"", L"_SYSTEM_", L"UNMAPPED" };
  503. for(int i=0; i<ARRAYSIZE(c_rgNodes); i++)
  504. {
  505. long id = m_lTopNode;
  506. MPC::WStringVector vec;
  507. MPC::WStringVectorIter it;
  508. NodeEntryIter it2;
  509. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SplitAtDelimiter( vec, c_rgNodes[i], L"/" ));
  510. for(it = vec.begin(); it != vec.end(); it++)
  511. {
  512. if(!LocateNode( id, it->c_str(), it2 )) break;
  513. id = it2->m_rs_data.m_ID_node;
  514. }
  515. if(it == vec.end())
  516. {
  517. __MPC_EXIT_IF_METHOD_FAILS(hr, GenerateDefaultQueries( ts, updater, id, 0 ));
  518. }
  519. }
  520. hr = S_OK;
  521. __HCP_FUNC_CLEANUP;
  522. __HCP_FUNC_EXIT(hr);
  523. }
  524. HRESULT Taxonomy::Cache::CachedHelpSet::PrePopulate( /*[in]*/ Cache* parent )
  525. {
  526. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::PrePopulate" );
  527. HRESULT hr;
  528. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  529. //
  530. // This opens the database, walks through all the nodes in the taxonomy and makes a copy in the cache.
  531. //
  532. DEBUG_AppendPerf( DEBUG_PERF_CACHE_L1, "PrePopulating Taxonomy Cache" );
  533. {
  534. Taxonomy::Settings ts( m_ths );
  535. JetBlue::SessionHandle handle;
  536. JetBlue::Database* db;
  537. Taxonomy::Updater updater;
  538. Taxonomy::RS_Taxonomy* rs;
  539. bool fFound;
  540. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.GetDatabase( handle, db, /*fReadOnly*/true ));
  541. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.Init ( ts, db, parent ));
  542. __MPC_EXIT_IF_METHOD_FAILS(hr, updater.GetTaxonomy( &rs ));
  543. m_lTopNode = -1;
  544. m_setNodes.clear();
  545. __MPC_EXIT_IF_METHOD_FAILS(hr, rs->Move( 0, JET_MoveFirst, &fFound ));
  546. while(fFound)
  547. {
  548. NodeEntry en;
  549. en.m_rs_data = *rs;
  550. if(!en.m_rs_data.m_fValid__ID_parent)
  551. {
  552. en.m_rs_data.m_ID_parent = -1;
  553. m_lTopNode = en.m_rs_data.m_ID_node;
  554. }
  555. m_setNodes.insert( en );
  556. __MPC_EXIT_IF_METHOD_FAILS(hr, rs->Move( 0, JET_MoveNext, &fFound ));
  557. }
  558. m_fDirty = true;
  559. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync( true ));
  560. DEBUG_AppendPerf( DEBUG_PERF_CACHE_L1, "PrePopulating Taxonomy Cache : Nodes done" );
  561. //
  562. // Walk through the first 3 level of nodes and pre-generate the queries.
  563. //
  564. // We disable offline flushing of the root index, because it gets changed too often...
  565. //
  566. __MPC_EXIT_IF_METHOD_FAILS(hr, OfflineCache::Root::s_GLOBAL->DisableSave( ));
  567. __MPC_EXIT_IF_METHOD_FAILS(hr, GenerateDefaultQueries ( ts, updater ));
  568. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync ( true ));
  569. __MPC_EXIT_IF_METHOD_FAILS(hr, OfflineCache::Root::s_GLOBAL->EnableSave ( ));
  570. }
  571. DEBUG_AppendPerf( DEBUG_PERF_CACHE_L1, "PrePopulated Taxonomy Cache : Nodes done" );
  572. hr = S_OK;
  573. __HCP_FUNC_CLEANUP;
  574. __HCP_FUNC_EXIT(hr);
  575. }
  576. HRESULT Taxonomy::Cache::CachedHelpSet::Erase()
  577. {
  578. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::Erase" );
  579. HRESULT hr;
  580. Clean();
  581. {
  582. MPC::wstring strFileBack = m_strFile; strFileBack += l_szBackup;
  583. (void)MPC::DeleteFile( m_strFile , /*fForce*/true, /*fDelayed*/false );
  584. (void)MPC::DeleteFile( strFileBack, /*fForce*/true, /*fDelayed*/false );
  585. }
  586. //
  587. // Propagate change to the offline cache.
  588. //
  589. {
  590. OfflineCache::Handle handle;
  591. if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->Locate( m_ths, handle )))
  592. {
  593. if(SUCCEEDED(handle->RemoveQueries()))
  594. {
  595. (void)OfflineCache::Root::s_GLOBAL->Flush();
  596. }
  597. }
  598. }
  599. hr = S_OK;
  600. __HCP_FUNC_EXIT(hr);
  601. }
  602. HRESULT Taxonomy::Cache::CachedHelpSet::PrepareToLoad()
  603. {
  604. m_fMarkedForLoad = true;
  605. return S_OK;
  606. }
  607. HRESULT Taxonomy::Cache::CachedHelpSet::LoadIfMarked()
  608. {
  609. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::LoadIfMarked" );
  610. HRESULT hr;
  611. if(m_fMarkedForLoad)
  612. {
  613. m_fMarkedForLoad = false;
  614. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  615. //
  616. // Load the JetBlue database.
  617. //
  618. {
  619. Taxonomy::Settings ts( m_ths );
  620. JetBlue::SessionHandle handle;
  621. JetBlue::Database* db;
  622. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.GetDatabase( handle, db, /*fReadOnly*/true ));
  623. }
  624. }
  625. hr = S_OK;
  626. __HCP_FUNC_CLEANUP;
  627. __HCP_FUNC_EXIT(hr);
  628. }
  629. HRESULT Taxonomy::Cache::CachedHelpSet::MRU()
  630. {
  631. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::MRU" );
  632. HRESULT hr;
  633. QueryEntryIter it;
  634. DWORD dwSizeTot = 0;
  635. //
  636. // Get total cache size.
  637. //
  638. for(it = m_setQueries.begin(); it != m_setQueries.end(); it++)
  639. {
  640. if(it->m_fRemoved == false)
  641. {
  642. dwSizeTot += it->m_dwSize;
  643. }
  644. }
  645. //
  646. // If the total size of the cache is bigger than a certain value, start to purge from the least used query.
  647. //
  648. if(dwSizeTot > l_dwSizeThresholdHIGH)
  649. {
  650. SortEntries Pr;
  651. SortedEntryVec vec;
  652. SortedEntryIter it2;
  653. for(it = m_setQueries.begin(); it != m_setQueries.end(); it++)
  654. {
  655. if(it->m_fRemoved == false)
  656. {
  657. vec.push_back( &(*it) );
  658. }
  659. }
  660. std::sort( vec.begin(), vec.end(), Pr );
  661. for(it2 = vec.begin(); it2 != vec.end(); it2++)
  662. {
  663. QueryEntry* en = *it2;
  664. __MPC_EXIT_IF_METHOD_FAILS(hr, en->Release( m_disk ));
  665. m_fDirty = true;
  666. dwSizeTot -= en->m_dwSize;
  667. if(dwSizeTot < l_dwSizeThresholdLOW) break;
  668. }
  669. }
  670. hr = S_OK;
  671. __HCP_FUNC_CLEANUP;
  672. __HCP_FUNC_EXIT(hr);
  673. }
  674. ////////////////////
  675. bool Taxonomy::Cache::CachedHelpSet::LocateNode( /*[in] */ long ID_parent ,
  676. /*[in] */ LPCWSTR szEntry ,
  677. /*[out]*/ NodeEntryIter& it )
  678. {
  679. NodeEntry en;
  680. en.m_rs_data.m_ID_parent = ID_parent;
  681. en.m_rs_data.m_strEntry = SAFEWSTR(szEntry);
  682. it = m_setNodes.find( en );
  683. return (it != m_setNodes.end());
  684. }
  685. HRESULT Taxonomy::Cache::CachedHelpSet::LocateNode( /*[in] */ long ID_parent ,
  686. /*[in] */ LPCWSTR szEntry ,
  687. /*[out]*/ RS_Data_Taxonomy& rs_data )
  688. {
  689. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::LocateNode" );
  690. HRESULT hr;
  691. NodeEntryIter it;
  692. rs_data.m_ID_node = -1;
  693. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  694. if(LocateNode( ID_parent, szEntry, it ) == false)
  695. {
  696. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  697. }
  698. rs_data = it->m_rs_data;
  699. hr = S_OK;
  700. __HCP_FUNC_CLEANUP;
  701. __HCP_FUNC_EXIT(hr);
  702. }
  703. HRESULT Taxonomy::Cache::CachedHelpSet::LocateSubNodes( /*[in] */ long ID_node ,
  704. /*[in] */ bool fRecurse ,
  705. /*[in] */ bool fOnlyVisible ,
  706. /*[out]*/ MatchSet& res )
  707. {
  708. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::LocateSubNodes" );
  709. HRESULT hr;
  710. NodeEntry en;
  711. NodeEntryIterConst it;
  712. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  713. en.m_rs_data.m_ID_parent = ID_node;
  714. it = m_setNodes.lower_bound( en );
  715. while(it != m_setNodes.end() && it->m_rs_data.m_ID_parent == ID_node)
  716. {
  717. if(fOnlyVisible == false || it->m_rs_data.m_fVisible)
  718. {
  719. res.insert( it->m_rs_data.m_ID_node );
  720. if(fRecurse)
  721. {
  722. __MPC_EXIT_IF_METHOD_FAILS(hr, LocateSubNodes( it->m_rs_data.m_ID_node, /*fRecurse*/true, fOnlyVisible, res ));
  723. }
  724. }
  725. it++;
  726. }
  727. hr = S_OK;
  728. __HCP_FUNC_CLEANUP;
  729. __HCP_FUNC_EXIT(hr);
  730. }
  731. HRESULT Taxonomy::Cache::CachedHelpSet::LocateNodesFromURL( /*[in] */ LPCWSTR szURL ,
  732. /*[out]*/ MatchSet& res )
  733. {
  734. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::LocateNodesFromURL" );
  735. HRESULT hr;
  736. NodeEntryIterConst it;
  737. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  738. for(it = m_setNodes.begin(); it != m_setNodes.end(); it++)
  739. {
  740. if(!MPC::StrICmp( szURL, it->m_rs_data.m_strDescriptionURI ))
  741. {
  742. res.insert( it->m_rs_data.m_ID_node );
  743. }
  744. }
  745. hr = S_OK;
  746. __HCP_FUNC_CLEANUP;
  747. __HCP_FUNC_EXIT(hr);
  748. }
  749. HRESULT Taxonomy::Cache::CachedHelpSet::BuildNodePath( /*[in] */ long ID ,
  750. /*[out]*/ MPC::wstring& strPath ,
  751. /*[in] */ bool fParent )
  752. {
  753. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::BuildNodePath" );
  754. HRESULT hr;
  755. NodeEntryIterConst it;
  756. MPC::wstring strTmp;
  757. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  758. strTmp .reserve( 1024 );
  759. strPath.reserve( 1024 );
  760. strPath = L"";
  761. while(ID != m_lTopNode)
  762. {
  763. NodeEntry::MatchNode cmp( ID );
  764. it = std::find_if( m_setNodes.begin(), m_setNodes.end(), cmp );
  765. if(it == m_setNodes.end())
  766. {
  767. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  768. }
  769. if(fParent == false)
  770. {
  771. strTmp = it->m_rs_data.m_strEntry;
  772. if(strPath.size())
  773. {
  774. strTmp += L"/";
  775. strTmp += strPath;
  776. }
  777. strPath = strTmp;
  778. }
  779. else
  780. {
  781. fParent = true;
  782. }
  783. ID = it->m_rs_data.m_ID_parent;
  784. }
  785. hr = S_OK;
  786. __HCP_FUNC_CLEANUP;
  787. __HCP_FUNC_EXIT(hr);
  788. }
  789. ////////////////////
  790. HRESULT Taxonomy::Cache::CachedHelpSet::LocateQuery( /*[in] */ LPCWSTR szID ,
  791. /*[in] */ int iType ,
  792. /*[out]*/ QueryEntry* &pEntry ,
  793. /*[in] */ bool fCreate )
  794. {
  795. __HCP_FUNC_ENTRY( "Taxonomy::Cache::CachedHelpSet::LocateQuery" );
  796. HRESULT hr;
  797. QueryEntry en;
  798. QueryEntryIter it;
  799. pEntry = NULL;
  800. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  801. en.m_strID = SAFEWSTR(szID);
  802. en.m_iType = iType;
  803. it = m_setQueries.find( en );
  804. if(it == m_setQueries.end())
  805. {
  806. if(fCreate == false)
  807. {
  808. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  809. }
  810. it = m_setQueries.insert( en ).first;
  811. it->m_iSequence = m_iLastSequence++;
  812. }
  813. else
  814. {
  815. if(fCreate == false)
  816. {
  817. if(it->m_fRemoved)
  818. {
  819. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  820. }
  821. }
  822. }
  823. pEntry = &(*it);
  824. pEntry->m_fRemoved = false;
  825. m_fDirty = true;
  826. hr = S_OK;
  827. __HCP_FUNC_CLEANUP;
  828. __HCP_FUNC_EXIT(hr);
  829. }
  830. ////////////////////////////////////////////////////////////////////////////////
  831. ////////////////////////////////////////////////////////////////////////////////
  832. Taxonomy::Cache::Cache()
  833. {
  834. // CacheSet m_skus;
  835. (void)MPC::_MPC_Module.RegisterCallback( this, (void (Taxonomy::Cache::*)())Shutdown );
  836. }
  837. Taxonomy::Cache::~Cache()
  838. {
  839. MPC::_MPC_Module.UnregisterCallback( this );
  840. Shutdown();
  841. }
  842. ////////////////////
  843. Taxonomy::Cache* Taxonomy::Cache::s_GLOBAL( NULL );
  844. HRESULT Taxonomy::Cache::InitializeSystem()
  845. {
  846. if(s_GLOBAL == NULL)
  847. {
  848. s_GLOBAL = new Taxonomy::Cache;
  849. }
  850. return s_GLOBAL ? S_OK : E_OUTOFMEMORY;
  851. }
  852. void Taxonomy::Cache::FinalizeSystem()
  853. {
  854. if(s_GLOBAL)
  855. {
  856. delete s_GLOBAL; s_GLOBAL = NULL;
  857. }
  858. }
  859. ////////////////////
  860. void Taxonomy::Cache::Shutdown()
  861. {
  862. m_skus.clear();
  863. }
  864. HRESULT Taxonomy::Cache::Locate( /*[in] */ const Taxonomy::HelpSet& ths ,
  865. /*[out]*/ CacheIter& it )
  866. {
  867. __HCP_FUNC_ENTRY( "Taxonomy::Cache::Locate" );
  868. HRESULT hr;
  869. CachedHelpSet hs;
  870. MPC::SmartLock<_ThreadModel> lock( this );
  871. hs.m_ths = ths;
  872. it = m_skus.find( hs );
  873. if(it == m_skus.end())
  874. {
  875. WCHAR rgTmp[MAX_PATH]; _snwprintf( rgTmp, MAXSTRLEN(rgTmp), L"%s\\%s_%ld.dat", l_szBase, hs.m_ths.GetSKU(), hs.m_ths.GetLanguage() );
  876. it = m_skus.insert( hs ).first;
  877. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SubstituteEnvVariables( it->m_strFile = rgTmp ));
  878. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir ( it->m_strFile ));
  879. it->m_fDirty = true;
  880. }
  881. hr = S_OK;
  882. __HCP_FUNC_CLEANUP;
  883. __HCP_FUNC_EXIT(hr);
  884. }
  885. ////////////////////////////////////////
  886. HRESULT Taxonomy::Cache::PrePopulate( /*[in]*/ const Taxonomy::HelpSet& ths )
  887. {
  888. __HCP_FUNC_ENTRY( "Taxonomy::Cache::PrePopulate" );
  889. HRESULT hr;
  890. CacheIter it;
  891. MPC::SmartLock<_ThreadModel> lock( this );
  892. __MPC_EXIT_IF_METHOD_FAILS(hr, Locate( ths, it ));
  893. __MPC_EXIT_IF_METHOD_FAILS(hr, it->PrePopulate( this ));
  894. hr = S_OK;
  895. __HCP_FUNC_CLEANUP;
  896. __HCP_FUNC_EXIT(hr);
  897. }
  898. HRESULT Taxonomy::Cache::Erase( /*[in]*/ const Taxonomy::HelpSet& ths )
  899. {
  900. __HCP_FUNC_ENTRY( "Taxonomy::Cache::Erase" );
  901. HRESULT hr;
  902. CacheIter it;
  903. MPC::SmartLock<_ThreadModel> lock( this );
  904. __MPC_EXIT_IF_METHOD_FAILS(hr, Locate( ths, it ));
  905. __MPC_EXIT_IF_METHOD_FAILS(hr, it->Erase());
  906. hr = S_OK;
  907. __HCP_FUNC_CLEANUP;
  908. __HCP_FUNC_EXIT(hr);
  909. }
  910. HRESULT Taxonomy::Cache::PrepareToLoad( /*[in]*/ const Taxonomy::HelpSet& ths )
  911. {
  912. __HCP_FUNC_ENTRY( "Taxonomy::Cache::PrepareToLoad" );
  913. HRESULT hr;
  914. CacheIter it;
  915. MPC::SmartLock<_ThreadModel> lock( this );
  916. __MPC_EXIT_IF_METHOD_FAILS(hr, Locate( ths, it ));
  917. __MPC_EXIT_IF_METHOD_FAILS(hr, it->PrepareToLoad());
  918. hr = S_OK;
  919. __HCP_FUNC_CLEANUP;
  920. __HCP_FUNC_EXIT(hr);
  921. }
  922. HRESULT Taxonomy::Cache::LoadIfMarked( /*[in]*/ const Taxonomy::HelpSet& ths )
  923. {
  924. __HCP_FUNC_ENTRY( "Taxonomy::Cache::LoadIfMarked" );
  925. HRESULT hr;
  926. CacheIter it;
  927. MPC::SmartLock<_ThreadModel> lock( this );
  928. __MPC_EXIT_IF_METHOD_FAILS(hr, Locate( ths, it ));
  929. __MPC_EXIT_IF_METHOD_FAILS(hr, it->LoadIfMarked());
  930. hr = S_OK;
  931. __HCP_FUNC_CLEANUP;
  932. __HCP_FUNC_EXIT(hr);
  933. }
  934. ////////////////////
  935. HRESULT Taxonomy::Cache::LocateNode( /*[in] */ const Taxonomy::HelpSet& ths ,
  936. /*[in] */ long ID_parent ,
  937. /*[in] */ LPCWSTR szEntry ,
  938. /*[out]*/ RS_Data_Taxonomy& rs_data )
  939. {
  940. __HCP_FUNC_ENTRY( "Taxonomy::Cache::LocateNode" );
  941. HRESULT hr;
  942. CacheIter it;
  943. MPC::SmartLock<_ThreadModel> lock( this );
  944. __MPC_EXIT_IF_METHOD_FAILS(hr, Locate( ths, it ));
  945. __MPC_EXIT_IF_METHOD_FAILS(hr, it->LocateNode( ID_parent, szEntry, rs_data ));
  946. hr = S_OK;
  947. __HCP_FUNC_CLEANUP;
  948. __HCP_FUNC_EXIT(hr);
  949. }
  950. HRESULT Taxonomy::Cache::LocateSubNodes( /*[in] */ const Taxonomy::HelpSet& ths ,
  951. /*[in] */ long ID_node ,
  952. /*[in] */ bool fRecurse ,
  953. /*[in] */ bool fOnlyVisible ,
  954. /*[out]*/ MatchSet& res )
  955. {
  956. __HCP_FUNC_ENTRY( "Taxonomy::Cache::LocateSubNodes" );
  957. HRESULT hr;
  958. CacheIter it;
  959. MPC::SmartLock<_ThreadModel> lock( this );
  960. __MPC_EXIT_IF_METHOD_FAILS(hr, Locate( ths, it ));
  961. __MPC_EXIT_IF_METHOD_FAILS(hr, it->LocateSubNodes( ID_node, fRecurse, fOnlyVisible, res ));
  962. hr = S_OK;
  963. __HCP_FUNC_CLEANUP;
  964. __HCP_FUNC_EXIT(hr);
  965. }
  966. HRESULT Taxonomy::Cache::LocateNodesFromURL( /*[in] */ const Taxonomy::HelpSet& ths ,
  967. /*[in] */ LPCWSTR szURL ,
  968. /*[out]*/ MatchSet& res )
  969. {
  970. __HCP_FUNC_ENTRY( "Taxonomy::Cache::LocateNodesFromURL" );
  971. HRESULT hr;
  972. CacheIter it;
  973. MPC::SmartLock<_ThreadModel> lock( this );
  974. __MPC_EXIT_IF_METHOD_FAILS(hr, Locate( ths, it ));
  975. __MPC_EXIT_IF_METHOD_FAILS(hr, it->LocateNodesFromURL( szURL, res ));
  976. hr = S_OK;
  977. __HCP_FUNC_CLEANUP;
  978. __HCP_FUNC_EXIT(hr);
  979. }
  980. HRESULT Taxonomy::Cache::BuildNodePath( /*[in] */ const Taxonomy::HelpSet& ths ,
  981. /*[in] */ long ID ,
  982. /*[out]*/ MPC::wstring& strPath ,
  983. /*[in] */ bool fParent )
  984. {
  985. __HCP_FUNC_ENTRY( "Taxonomy::Cache::BuildNodePath" );
  986. HRESULT hr;
  987. CacheIter it;
  988. MPC::SmartLock<_ThreadModel> lock( this );
  989. __MPC_EXIT_IF_METHOD_FAILS(hr, Locate( ths, it ));
  990. __MPC_EXIT_IF_METHOD_FAILS(hr, it->BuildNodePath( ID, strPath, fParent ));
  991. hr = S_OK;
  992. __HCP_FUNC_CLEANUP;
  993. __HCP_FUNC_EXIT(hr);
  994. }
  995. ////////////////////
  996. HRESULT Taxonomy::Cache::StoreQuery( /*[in]*/ const Taxonomy::HelpSet& ths ,
  997. /*[in]*/ LPCWSTR szID ,
  998. /*[in]*/ int iType ,
  999. /*[in]*/ const CPCHQueryResultCollection* pColl )
  1000. {
  1001. __HCP_FUNC_ENTRY( "Taxonomy::Cache::StoreQuery" );
  1002. HRESULT hr;
  1003. CacheIter it;
  1004. QueryEntry* pEntry;
  1005. MPC::SmartLock<_ThreadModel> lock( this );
  1006. __MPC_PARAMCHECK_BEGIN(hr)
  1007. __MPC_PARAMCHECK_NOTNULL(pColl);
  1008. __MPC_PARAMCHECK_END();
  1009. __MPC_EXIT_IF_METHOD_FAILS(hr, Locate( ths, it ));
  1010. __MPC_EXIT_IF_METHOD_FAILS(hr, it->LocateQuery( szID, iType, pEntry, true ));
  1011. __MPC_EXIT_IF_METHOD_FAILS(hr, pEntry->Store( it->m_disk, pColl ));
  1012. __MPC_EXIT_IF_METHOD_FAILS(hr, it->MRU ());
  1013. __MPC_EXIT_IF_METHOD_FAILS(hr, it->EnsureInSync());
  1014. //
  1015. // Propagate change to the offline cache.
  1016. //
  1017. {
  1018. OfflineCache::Handle handle;
  1019. if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->Locate( it->m_ths, handle )))
  1020. {
  1021. if(handle->AreYouInterested( szID, iType ))
  1022. {
  1023. if(SUCCEEDED(handle->Store( szID, iType, pColl )))
  1024. {
  1025. (void)OfflineCache::Root::s_GLOBAL->Flush();
  1026. }
  1027. }
  1028. }
  1029. }
  1030. hr = S_OK;
  1031. __HCP_FUNC_CLEANUP;
  1032. __HCP_FUNC_EXIT(hr);
  1033. }
  1034. HRESULT Taxonomy::Cache::RetrieveQuery( /*[in]*/ const Taxonomy::HelpSet& ths ,
  1035. /*[in]*/ LPCWSTR szID ,
  1036. /*[in]*/ int iType ,
  1037. /*[in]*/ CPCHQueryResultCollection* pColl )
  1038. {
  1039. __HCP_FUNC_ENTRY( "Taxonomy::Cache::Retrieve" );
  1040. HRESULT hr;
  1041. CacheIter it;
  1042. QueryEntry* pEntry;
  1043. MPC::SmartLock<_ThreadModel> lock( this );
  1044. __MPC_PARAMCHECK_BEGIN(hr)
  1045. __MPC_PARAMCHECK_NOTNULL(pColl);
  1046. __MPC_PARAMCHECK_END();
  1047. __MPC_EXIT_IF_METHOD_FAILS(hr, Locate( ths, it ));
  1048. __MPC_EXIT_IF_METHOD_FAILS(hr, it->LocateQuery( szID, iType, pEntry, false ));
  1049. __MPC_EXIT_IF_METHOD_FAILS(hr, pEntry->Retrieve( it->m_disk, pColl ));
  1050. __MPC_EXIT_IF_METHOD_FAILS(hr, it->EnsureInSync());
  1051. hr = S_OK;
  1052. __HCP_FUNC_CLEANUP;
  1053. __HCP_FUNC_EXIT(hr);
  1054. }