740 lines
19 KiB
C++
740 lines
19 KiB
C++
/******************************************************************************
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
AsyncDatabase.cpp
|
|
|
|
Abstract:
|
|
This file contains the implementation of the asynchronous database access.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 08/13/2000
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
AsynchronousTaxonomyDatabase::NotifyHandle::NotifyHandle()
|
|
{
|
|
m_iType = OfflineCache::ET_INVALID; // int m_iType;
|
|
// CComBSTR m_bstrID;
|
|
//
|
|
m_hEvent = NULL; // HANDLE m_hEvent;
|
|
//
|
|
m_hr = HRESULT_FROM_WIN32(ERROR_BUSY); // HRESULT m_hr;
|
|
m_pColl = NULL; // CPCHQueryResultCollection* m_pColl;
|
|
}
|
|
|
|
AsynchronousTaxonomyDatabase::NotifyHandle::~NotifyHandle()
|
|
{
|
|
Detach();
|
|
|
|
MPC::Release( m_pColl );
|
|
|
|
if(m_hEvent)
|
|
{
|
|
::CloseHandle( m_hEvent );
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) AsynchronousTaxonomyDatabase::NotifyHandle::AddRef()
|
|
{
|
|
return InternalAddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) AsynchronousTaxonomyDatabase::NotifyHandle::Release()
|
|
{
|
|
ULONG c = InternalRelease();
|
|
|
|
if(c == 0) delete this;
|
|
|
|
return c;
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
HRESULT AsynchronousTaxonomyDatabase::NotifyHandle::Init()
|
|
{
|
|
__HCP_FUNC_ENTRY( "AsynchronousTaxonomyDatabase::NotifyHandle::Init" );
|
|
|
|
HRESULT hr;
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (m_hEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL )));
|
|
m_fAttached = true;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
void AsynchronousTaxonomyDatabase::NotifyHandle::Bind( /*[in]*/ int iType, /*[in]*/ LPCWSTR szID )
|
|
{
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
|
|
m_iType = iType;
|
|
m_bstrID = szID;
|
|
|
|
m_hr = HRESULT_FROM_WIN32(ERROR_BUSY);
|
|
|
|
MPC::Release( m_pColl );
|
|
}
|
|
|
|
void AsynchronousTaxonomyDatabase::NotifyHandle::Call( /*[in]*/ QueryStore* qs )
|
|
{
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
|
|
MPC::Release( m_pColl );
|
|
|
|
m_hr = qs ? qs->GetData( &m_pColl ) : E_ABORT;
|
|
|
|
//
|
|
// Look ahead all the URLs, to Get all the Copy the items in the remote collection.
|
|
//
|
|
if(m_pColl)
|
|
{
|
|
long lCount;
|
|
long lPos;
|
|
|
|
if(SUCCEEDED(m_pColl->get_Count( &lCount )))
|
|
{
|
|
for(lPos=0; lPos<lCount; lPos++)
|
|
{
|
|
CComPtr<CPCHQueryResult> item;
|
|
|
|
if(SUCCEEDED(m_pColl->GetItem( lPos, &item )))
|
|
{
|
|
CComBSTR bstrURL;
|
|
|
|
if(SUCCEEDED(item->get_TopicURL( &bstrURL )))
|
|
{
|
|
if(STRINGISPRESENT(bstrURL)) (void)HyperLinks::Lookup::s_GLOBAL->Queue( bstrURL );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if(m_hEvent)
|
|
{
|
|
::SetEvent( m_hEvent );
|
|
}
|
|
}
|
|
|
|
void AsynchronousTaxonomyDatabase::NotifyHandle::Detach()
|
|
{
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
|
|
m_fAttached = false;
|
|
}
|
|
|
|
bool AsynchronousTaxonomyDatabase::NotifyHandle::IsAttached()
|
|
{
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
|
|
return m_fAttached;
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
HRESULT AsynchronousTaxonomyDatabase::NotifyHandle::GetData( /*[out]*/ CPCHQueryResultCollection* *pColl )
|
|
{
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
|
|
if(pColl)
|
|
{
|
|
*pColl = NULL;
|
|
|
|
if(SUCCEEDED(m_hr))
|
|
{
|
|
if(m_pColl) (*pColl = m_pColl)->AddRef();
|
|
}
|
|
}
|
|
|
|
return m_hr;
|
|
}
|
|
|
|
HRESULT AsynchronousTaxonomyDatabase::NotifyHandle::Wait( /*[in]*/ DWORD dwTimeout )
|
|
{
|
|
if(IsAttached())
|
|
{
|
|
for(int pass=0; pass<2; pass++)
|
|
{
|
|
DWORD dwRes;
|
|
DWORD dwWait;
|
|
|
|
//
|
|
// On first pass, do a synchronous wait.
|
|
//
|
|
if(pass == 0)
|
|
{
|
|
dwRes = ::WaitForSingleObject( m_hEvent, min( dwTimeout, 200 ) );
|
|
}
|
|
else
|
|
{
|
|
dwRes = MPC::WaitForSingleObject( m_hEvent, dwTimeout );
|
|
}
|
|
|
|
if(dwRes == WAIT_OBJECT_0 ||
|
|
dwRes == WAIT_ABANDONED_0 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(pass == 1)
|
|
{
|
|
return HRESULT_FROM_WIN32(ERROR_BUSY);
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
AsynchronousTaxonomyDatabase::Notifier::Notifier()
|
|
{
|
|
// List m_lstCallback;
|
|
}
|
|
|
|
AsynchronousTaxonomyDatabase::Notifier::~Notifier()
|
|
{
|
|
MPC::ReleaseAll( m_lstCallback );
|
|
}
|
|
|
|
////////////////////
|
|
|
|
void AsynchronousTaxonomyDatabase::Notifier::Notify( /*[in]*/ QueryStore* qs )
|
|
{
|
|
List lst;
|
|
Iter it;
|
|
|
|
|
|
//
|
|
// Phase 1: copy list, under lock.
|
|
//
|
|
{
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
|
|
for(it = m_lstCallback.begin(); it != m_lstCallback.end(); it++)
|
|
{
|
|
NotifyHandle* nb = *it;
|
|
|
|
if(qs)
|
|
{
|
|
if(qs->m_iType != nb->m_iType || MPC::StrCmp( qs->m_bstrID, nb->m_bstrID )) continue;
|
|
}
|
|
|
|
lst.push_back( nb ); nb->AddRef();
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Phase 2: send the notification.
|
|
//
|
|
for(it = lst.begin(); it != lst.end(); it++)
|
|
{
|
|
NotifyHandle* nb = *it;
|
|
|
|
nb->Call ( qs );
|
|
nb->Detach( );
|
|
}
|
|
MPC::ReleaseAll( lst );
|
|
|
|
|
|
//
|
|
// Phase 3: clean list, under lock.
|
|
//
|
|
{
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
|
|
for(it = m_lstCallback.begin(); it != m_lstCallback.end();)
|
|
{
|
|
NotifyHandle* nb = *it;
|
|
|
|
if(nb->IsAttached() == false)
|
|
{
|
|
m_lstCallback.erase( it ); nb->Release();
|
|
|
|
it = m_lstCallback.begin();
|
|
}
|
|
else
|
|
{
|
|
it++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT AsynchronousTaxonomyDatabase::Notifier::AddNotification( /*[in]*/ QueryStore* qs, /*[in]*/ NotifyHandle* nb )
|
|
{
|
|
__HCP_FUNC_ENTRY( "AsynchronousTaxonomyDatabase::Notifier::AddNotification" );
|
|
|
|
HRESULT hr;
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
|
|
if(nb == NULL)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, E_OUTOFMEMORY);
|
|
}
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, nb->Init());
|
|
|
|
nb->Bind( qs->m_iType, qs->m_bstrID );
|
|
|
|
m_lstCallback.push_back( nb ); nb->AddRef();
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
AsynchronousTaxonomyDatabase::QueryStore::QueryStore( /*[in]*/ int iType, /*[in]*/ LPCWSTR szID, /*[in]*/ VARIANT* option )
|
|
{
|
|
m_iType = iType; // int m_iType;
|
|
m_bstrID = szID; // CComBSTR m_bstrID;
|
|
// CComVariant m_vOption;
|
|
//
|
|
m_fDone = false; // bool m_fDone;
|
|
m_hr = E_INVALIDARG; // HRESULT m_hr;
|
|
// MPC::CComHGLOBAL m_hgData;
|
|
// FILETIME m_dLastUsed;
|
|
|
|
if(option) m_vOption = *option;
|
|
}
|
|
|
|
AsynchronousTaxonomyDatabase::QueryStore::~QueryStore()
|
|
{
|
|
Invalidate();
|
|
}
|
|
|
|
////////////////////
|
|
|
|
bool AsynchronousTaxonomyDatabase::QueryStore::LessThen( /*[in]*/ QueryStore const &qs ) const
|
|
{
|
|
int iCmp = (m_iType - qs.m_iType);
|
|
|
|
if(iCmp == 0)
|
|
{
|
|
iCmp = MPC::StrCmp( m_bstrID, qs.m_bstrID );
|
|
if(iCmp == 0)
|
|
{
|
|
switch(m_iType)
|
|
{
|
|
case OfflineCache::ET_LOCATECONTEXT:
|
|
case OfflineCache::ET_SEARCH :
|
|
{
|
|
bool fHasLeft = ( m_vOption.vt == VT_BSTR);
|
|
bool fHasRight = (qs.m_vOption.vt == VT_BSTR);
|
|
|
|
if(fHasLeft)
|
|
{
|
|
iCmp = fHasRight ? MPC::StrCmp( m_vOption.bstrVal, qs.m_vOption.bstrVal ) : 1;
|
|
}
|
|
else
|
|
{
|
|
iCmp = fHasRight ? -1 : 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (iCmp < 0);
|
|
}
|
|
|
|
bool AsynchronousTaxonomyDatabase::QueryStore::NewerThen( /*[in]*/ QueryStore const &qs ) const
|
|
{
|
|
return ::CompareFileTime( &m_dLastUsed, &qs.m_dLastUsed ) > 0;
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT AsynchronousTaxonomyDatabase::QueryStore::Execute( /*[in]*/ OfflineCache::Handle* handle ,
|
|
/*[in]*/ CPCHProxy_IPCHTaxonomyDatabase* parent ,
|
|
/*[in]*/ bool fForce )
|
|
{
|
|
__HCP_FUNC_ENTRY( "AsynchronousTaxonomyDatabase::QueryStore::Execute" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<IPCHCollection> pColl;
|
|
|
|
|
|
__MPC_TRY_BEGIN();
|
|
|
|
if(fForce) m_fDone = false;
|
|
|
|
if(m_fDone == false)
|
|
{
|
|
DebugLog( L"AsynchronousTaxonomyDatabase::QueryStore::Execute - Start : %s\n", SAFEBSTR( m_bstrID ) );
|
|
|
|
DEBUG_AppendPerf( DEBUG_PERF_QUERIES, L"AsynchronousTaxonomyDatabase::QueryStore::Execute - Start : %s", SAFEBSTR( m_bstrID ) );
|
|
|
|
if(handle)
|
|
{
|
|
CComPtr<CPCHQueryResultCollection> coll;
|
|
|
|
if(SUCCEEDED((*handle)->Retrieve( m_bstrID, m_iType, &coll )))
|
|
{
|
|
DEBUG_AppendPerf( DEBUG_PERF_QUERIES, L"AsynchronousTaxonomyDatabase::QueryStore::Execute - Cache Hit" );
|
|
|
|
pColl = coll;
|
|
}
|
|
}
|
|
|
|
if(!pColl && parent)
|
|
{
|
|
CComPtr<IPCHTaxonomyDatabase> db;
|
|
|
|
DEBUG_AppendPerf( DEBUG_PERF_QUERIES, L"AsynchronousTaxonomyDatabase::QueryStore::Execute - Get DB" );
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, parent->EnsureDirectConnection( db ));
|
|
DEBUG_AppendPerf( DEBUG_PERF_QUERIES, L"AsynchronousTaxonomyDatabase::QueryStore::Execute - Got DB" );
|
|
|
|
switch(m_iType)
|
|
{
|
|
case OfflineCache::ET_NODE : hr = db->LookupNode ( m_bstrID, &pColl ); break;
|
|
case OfflineCache::ET_SUBNODES : hr = db->LookupSubNodes ( m_bstrID, VARIANT_FALSE, &pColl ); break;
|
|
case OfflineCache::ET_SUBNODES_VISIBLE : hr = db->LookupSubNodes ( m_bstrID, VARIANT_TRUE , &pColl ); break;
|
|
case OfflineCache::ET_NODESANDTOPICS : hr = db->LookupNodesAndTopics( m_bstrID, VARIANT_FALSE, &pColl ); break;
|
|
case OfflineCache::ET_NODESANDTOPICS_VISIBLE: hr = db->LookupNodesAndTopics( m_bstrID, VARIANT_TRUE , &pColl ); break;
|
|
case OfflineCache::ET_TOPICS : hr = db->LookupTopics ( m_bstrID, VARIANT_FALSE, &pColl ); break;
|
|
case OfflineCache::ET_TOPICS_VISIBLE : hr = db->LookupTopics ( m_bstrID, VARIANT_TRUE , &pColl ); break;
|
|
case OfflineCache::ET_LOCATECONTEXT : hr = db->LocateContext ( m_bstrID, m_vOption , &pColl ); break;
|
|
case OfflineCache::ET_SEARCH : hr = db->KeywordSearch ( m_bstrID, m_vOption , &pColl ); break;
|
|
case OfflineCache::ET_NODES_RECURSIVE : hr = db->GatherNodes ( m_bstrID, VARIANT_TRUE , &pColl ); break;
|
|
case OfflineCache::ET_TOPICS_RECURSIVE : hr = db->GatherTopics ( m_bstrID, VARIANT_TRUE , &pColl ); break;
|
|
default : hr = E_INVALIDARG;
|
|
}
|
|
DEBUG_AppendPerf( DEBUG_PERF_QUERIES, L"AsynchronousTaxonomyDatabase::QueryStore::Execute - Query Done" );
|
|
}
|
|
}
|
|
|
|
if(pColl)
|
|
{
|
|
CComPtr<IPersistStream> persist;
|
|
CComPtr<IStream> stream;
|
|
|
|
|
|
DEBUG_AppendPerf( DEBUG_PERF_QUERIES, L"AsynchronousTaxonomyDatabase::QueryStore::Execute - Local Copy Start" );
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl->QueryInterface( IID_IPersistStream, (void**)&persist ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_hgData.NewStream( &stream ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, persist->Save ( stream, FALSE ));
|
|
|
|
DEBUG_AppendPerf( DEBUG_PERF_QUERIES, L"AsynchronousTaxonomyDatabase::QueryStore::Execute - Local Copy Done" );
|
|
}
|
|
|
|
::GetSystemTimeAsFileTime( &m_dLastUsed );
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__MPC_TRY_CATCHALL(hr);
|
|
|
|
if(m_fDone == false)
|
|
{
|
|
m_hr = hr;
|
|
m_fDone = true;
|
|
}
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT AsynchronousTaxonomyDatabase::QueryStore::GetData( /*[out]*/ CPCHQueryResultCollection* *ppC )
|
|
{
|
|
__HCP_FUNC_ENTRY( "AsynchronousTaxonomyDatabase::QueryStore::GetData" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHQueryResultCollection> pColl;
|
|
CComPtr<IPersistStream> persist;
|
|
CComPtr<IStream> stream;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_POINTER_AND_SET(ppC,NULL);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl->QueryInterface( IID_IPersistStream, (void**)&persist ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_hgData.GetAsStream( &stream, /*fClone*/false ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, persist->Load ( stream ));
|
|
|
|
*ppC = pColl.Detach();
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
void AsynchronousTaxonomyDatabase::QueryStore::Invalidate()
|
|
{
|
|
m_hgData.Release();
|
|
|
|
m_fDone = false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool AsynchronousTaxonomyDatabase::Engine::CompareQueryStores::operator()( /*[in]*/ const QueryStore *left, /*[in]*/ const QueryStore *right ) const
|
|
{
|
|
if(left)
|
|
{
|
|
return right ? left->LessThen( *right ) : true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
AsynchronousTaxonomyDatabase::Engine::Engine( /*[in]*/ CPCHProxy_IPCHTaxonomyDatabase* parent )
|
|
{
|
|
m_parent = parent; // CPCHProxy_IPCHTaxonomyDatabase* m_parent;
|
|
// Set m_setQueries;
|
|
// Notifier m_notifier;
|
|
}
|
|
|
|
AsynchronousTaxonomyDatabase::Engine::~Engine()
|
|
{
|
|
Passivate();
|
|
}
|
|
|
|
////////////////////
|
|
|
|
void AsynchronousTaxonomyDatabase::Engine::Passivate()
|
|
{
|
|
Thread_Wait();
|
|
|
|
MPC::CallDestructorForAll( m_setQueries );
|
|
}
|
|
|
|
void AsynchronousTaxonomyDatabase::Engine::RefreshConnection()
|
|
{
|
|
//
|
|
// The connection to the database has changed, so we need to flush all the cached queries...
|
|
//
|
|
InvalidateQueries();
|
|
|
|
Thread_Signal();
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
bool AsynchronousTaxonomyDatabase::Engine::LookupCache( /*[out]*/ OfflineCache::Handle& handle )
|
|
{
|
|
if(m_parent && m_parent->Parent())
|
|
{
|
|
CComPtr<CPCHProxy_IPCHUserSettings2> us;
|
|
|
|
if(SUCCEEDED(m_parent->Parent()->GetUserSettings2( &us )))
|
|
{
|
|
if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->Locate( us->THS(), handle )))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void AsynchronousTaxonomyDatabase::Engine::InvalidateQueries()
|
|
{
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
Iter it;
|
|
|
|
for(it = m_setQueries.begin(); it != m_setQueries.end(); it++)
|
|
{
|
|
QueryStore* qs = *it;
|
|
|
|
qs->Invalidate();
|
|
}
|
|
}
|
|
|
|
HRESULT AsynchronousTaxonomyDatabase::Engine::Run()
|
|
{
|
|
__HCP_FUNC_ENTRY( "AsynchronousTaxonomyDatabase::Engine::Run" );
|
|
|
|
HRESULT hr;
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
|
|
|
|
while(Thread_IsAborted() == false)
|
|
{
|
|
OfflineCache::Handle handle;
|
|
bool fValidCache = false;
|
|
bool fInit = false;
|
|
bool fSleep = true;
|
|
Iter it;
|
|
|
|
|
|
//
|
|
// Look for the first query store not ready and execute it.
|
|
//
|
|
for(it = m_setQueries.begin(); it != m_setQueries.end(); it++)
|
|
{
|
|
QueryStore* qs = *it;
|
|
|
|
if(qs->m_fDone == false)
|
|
{
|
|
if(fInit == false)
|
|
{
|
|
__MPC_PROTECT( fValidCache = LookupCache( handle ) );
|
|
|
|
fInit = true;
|
|
}
|
|
|
|
lock = NULL;
|
|
qs->Execute( fValidCache ? &handle : NULL, m_parent );
|
|
lock = this;
|
|
|
|
fSleep = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Notify all the query stores that are ready.
|
|
//
|
|
if(it == m_setQueries.end())
|
|
{
|
|
for(it = m_setQueries.begin(); it != m_setQueries.end(); it++)
|
|
{
|
|
QueryStore* qs = *it;
|
|
|
|
if(qs->m_fDone)
|
|
{
|
|
m_notifier.Notify( qs );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if(fSleep)
|
|
{
|
|
lock = NULL;
|
|
Thread_WaitForEvents( NULL, INFINITE );
|
|
lock = this;
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
m_notifier.Notify( NULL );
|
|
|
|
Thread_Abort();
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
HRESULT AsynchronousTaxonomyDatabase::Engine::ExecuteQuery( /*[in]*/ int iType ,
|
|
/*[in]*/ LPCWSTR szID ,
|
|
/*[in]*/ VARIANT* option ,
|
|
/*[in]*/ NotifyHandle* nb )
|
|
{
|
|
__HCP_FUNC_ENTRY( "AsynchronousTaxonomyDatabase::Engine::ExecuteQuery" );
|
|
|
|
HRESULT hr;
|
|
MPC::SmartLock<_ThreadModel> lock( this );
|
|
QueryStore* qsNew = NULL;
|
|
QueryStore* qs;
|
|
Iter it;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_NOTNULL(m_parent);
|
|
__MPC_PARAMCHECK_NOTNULL(nb);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
__MPC_EXIT_IF_ALLOC_FAILS(hr, qsNew, new QueryStore( iType, szID, option ));
|
|
|
|
it = m_setQueries.find( qsNew );
|
|
if(it == m_setQueries.end())
|
|
{
|
|
qs = qsNew;
|
|
|
|
m_setQueries.insert( qsNew ); qsNew = NULL;
|
|
}
|
|
else
|
|
{
|
|
qs = *it;
|
|
}
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_notifier.AddNotification( qs, nb ));
|
|
|
|
if(Thread_IsRunning() == false)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, Run, NULL ));
|
|
}
|
|
else
|
|
{
|
|
Thread_Signal();
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
delete qsNew;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT AsynchronousTaxonomyDatabase::Engine::ExecuteQuery( /*[in]*/ int iType ,
|
|
/*[in]*/ LPCWSTR szID ,
|
|
/*[in]*/ VARIANT* option ,
|
|
/*[out, retval]*/ CPCHQueryResultCollection* *ppC )
|
|
{
|
|
__HCP_FUNC_ENTRY( "AsynchronousTaxonomyDatabase::Engine::ExecuteQuery" );
|
|
|
|
HRESULT hr;
|
|
NotifyHandle* nb = new NotifyHandle(); if(nb) nb->AddRef();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ExecuteQuery( iType, szID, option, nb ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, nb->Wait());
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, nb->GetData( ppC ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
if(nb) nb->Release();
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|