/****************************************************************************** Copyright (c) 1999-2000 Microsoft Corporation Module Name: OfflineCache_Master.cpp Abstract: Handles caching of database lookups, service-side. Revision History: Davide Massarenti (Dmassare) 07/17/2000 created ******************************************************************************/ #include "stdafx.h" //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// HRESULT OfflineCache::Query::Store( /*[in]*/ const MPC::wstring& strDir , /*[in]*/ const CPCHQueryResultCollection* pColl ) { __HCP_FUNC_ENTRY( "OfflineCache::Query::Store" ); HRESULT hr; if(m_fNull == false) { MPC::wstring strFile; CComPtr stream; __MPC_EXIT_IF_METHOD_FAILS(hr, InitFile ( strDir, strFile )); __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Init( strFile, stream )); // // Create an IStream from the collection. // { MPC::Serializer_IStream streamGen ( stream ); MPC::Serializer_Buffering streamGen2( streamGen ); __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->Save( streamGen2 )); __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2.Flush()); } __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Finalize( strFile, stream )); } hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT OfflineCache::Query::Remove( /*[in]*/ const MPC::wstring& strDir ) { __HCP_FUNC_ENTRY( "OfflineCache::Query::Remove" ); HRESULT hr; if(m_fNull == false) { MPC::wstring strFile; __MPC_EXIT_IF_METHOD_FAILS(hr, InitFile( strDir, strFile )); __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::DeleteFile( strFile, /*fForce*/true, /*fDelayed*/false )); } hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// bool OfflineCache::SetOfHelpTopics::AreYouInterested( /*[in]*/ LPCWSTR szID , /*[in]*/ int iType ) { int iDepth = 1; switch(iType) { case ET_NODE : case ET_SUBNODES : case ET_SUBNODES_VISIBLE : case ET_NODESANDTOPICS : case ET_NODESANDTOPICS_VISIBLE: case ET_TOPICS : case ET_TOPICS_VISIBLE : break; default : return false; // Not interested for now... } // // Count the depth of the taxonomy node, we are only interested in the first two levels. // if(szID) { WCHAR c; while((c = *szID++)) { if(c == '/') iDepth++; } } if(m_inst.m_fDesktop && iDepth < 4) return true; if( iDepth < 3) return true; return false; } HRESULT OfflineCache::SetOfHelpTopics::Store( /*[in]*/ LPCWSTR szID , /*[in]*/ int iType , /*[in]*/ const CPCHQueryResultCollection* pColl ) { __HCP_FUNC_ENTRY( "OfflineCache::SetOfHelpTopics::Store" ); HRESULT hr; QueryIter it; __MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_NOTNULL(pColl); __MPC_PARAMCHECK_END(); __MPC_EXIT_IF_METHOD_FAILS(hr, Find( szID, iType, it )); if(it == m_lstQueries.end()) { it = m_lstQueries.insert( m_lstQueries.end() ); it->m_strID = szID; it->m_iType = iType; it->m_iSequence = m_iLastSeq++; it->m_fNull = (pColl->Size() == 0); if(m_parent) __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->SetDirty()); } // // Persist to disk. // if(it->m_fNull == false) { MPC::wstring strDir; __MPC_EXIT_IF_METHOD_FAILS(hr, InitDir( strDir )); __MPC_EXIT_IF_METHOD_FAILS(hr, it->Store( strDir, pColl )); } hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT OfflineCache::SetOfHelpTopics::RemoveQueries() { __HCP_FUNC_ENTRY( "OfflineCache::SetOfHelpTopics::RemoveQueries" ); HRESULT hr; MPC::wstring strDir; QueryIter it; __MPC_EXIT_IF_METHOD_FAILS(hr, InitDir( strDir )); for(it = m_lstQueries.begin(); it != m_lstQueries.end(); it++) { __MPC_EXIT_IF_METHOD_FAILS(hr, it->Remove( strDir )); } m_lstQueries.clear(); m_iLastSeq = 0; { MPC::FileSystemObject fso( strDir.c_str() ); __MPC_EXIT_IF_METHOD_FAILS(hr, fso.DeleteChildren( /*fForce*/true, /*fComplain*/false )); } if(m_parent) __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->SetDirty()); hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// HRESULT OfflineCache::Root::SetDirty() { m_fDirty = true; return S_OK; } HRESULT OfflineCache::Root::DisableSave() { MPC::SmartLock<_ThreadModel> lock( this ); m_dwDisableSave++; return S_OK; } HRESULT OfflineCache::Root::EnableSave() { __HCP_FUNC_ENTRY( "OfflineCache::Root::EnableSave" ); HRESULT hr; MPC::SmartLock<_ThreadModel> lock( this ); if(m_dwDisableSave) { if(--m_dwDisableSave == 0) { __MPC_EXIT_IF_METHOD_FAILS(hr, Save()); } } hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT OfflineCache::Root::Save() { __HCP_FUNC_ENTRY( "OfflineCache::Root::Save" ); HRESULT hr; if(m_fDirty && m_fMaster && m_dwDisableSave == 0) // Only master can write to the registry. { MPC::wstring strIndex; CComPtr stream; __MPC_EXIT_IF_METHOD_FAILS(hr, GetIndexFile ( strIndex )); __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Init( strIndex, stream )); // // Create IStream from the collection. // { MPC::Serializer_IStream streamGen ( stream ); MPC::Serializer_Buffering streamGen2( streamGen ); DWORD dwVer = s_dwVersion; __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 << dwVer ); __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 << *this ); __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2.Flush()); } __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Finalize( strIndex, stream )); m_fDirty = false; } hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } //////////////////////////////////////// HRESULT OfflineCache::Root::Import( /*[in]*/ const Taxonomy::Instance& inst ) { __HCP_FUNC_ENTRY( "OfflineCache::Root::Import" ); HRESULT hr; MPC::SmartLock<_ThreadModel> lock( this ); SKUIter it; if(m_fMaster == false) { __MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED); } __MPC_EXIT_IF_METHOD_FAILS(hr, Find( inst.m_ths, it )); if(it == m_lstSKUs.end()) { it = m_lstSKUs.insert( m_lstSKUs.end() ); it->ConnectToParent( this ); it->m_inst = inst; m_fDirty = true; } hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } //////////////////// HRESULT OfflineCache::Root::Remove( /*[in]*/ const Taxonomy::HelpSet& ths ) { __HCP_FUNC_ENTRY( "OfflineCache::Root::Remove" ); HRESULT hr; MPC::SmartLock<_ThreadModel> lock( this ); SKUIter it; if(m_fMaster == false) { __MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED); } __MPC_EXIT_IF_METHOD_FAILS(hr, Find( ths, it )); if(it != m_lstSKUs.end()) { (void)it->RemoveQueries(); m_lstSKUs.erase( it ); m_fDirty = true; } hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } HRESULT OfflineCache::Root::Flush( /*[in]*/ bool fForce ) { __HCP_FUNC_ENTRY( "OfflineCache::Root::Flush" ); HRESULT hr; MPC::SmartLock<_ThreadModel> lock( this ); if(m_fMaster) { if(fForce) m_fDirty = true; } else { // // On the slave side, Flush is like Reload. // __MPC_EXIT_IF_METHOD_FAILS(hr, Clean()); } __MPC_EXIT_IF_METHOD_FAILS(hr, Save()); hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } //////////////////////////////////////// HRESULT OfflineCache::Root::SetReady( /*[in]*/ bool fReady ) { __HCP_FUNC_ENTRY( "OfflineCache::Root::SetReady" ); HRESULT hr; MPC::SmartLock<_ThreadModel> lock( this ); m_fReady = fReady; m_fDirty = true; hr = S_OK; __HCP_FUNC_EXIT(hr); }