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.
386 lines
11 KiB
386 lines
11 KiB
|
|
|
|
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
MERGERREQ.H
|
|
|
|
Abstract:
|
|
|
|
Definitions of Merger Request classes
|
|
|
|
History:
|
|
|
|
28-Feb-01 sanjes Created.
|
|
|
|
--*/
|
|
|
|
#ifndef _MERGERREQ_H_
|
|
#define _MERGERREQ_H_
|
|
|
|
// forward class definitions
|
|
class CWmiMerger;
|
|
class CWmiMergerRecord;
|
|
|
|
//
|
|
// Merger Requests
|
|
//
|
|
// In previous releases, when the query engine analyzed a query, it enqueued
|
|
// a large number of requests, one for each dynamically provided class. Each
|
|
// of these could be handled on a separate thread, which could cause a
|
|
// significant thread explosion as each request was handed to a separate thread.
|
|
//
|
|
// In order to better control the threads, we are using the merger to perform
|
|
// a more intelligent analysis of a query and then spin off threads only when
|
|
// we reach throttling conditions. Now, instead of enqueing a large number of
|
|
// requests, the merger maintains hierarchical information regarding parents and
|
|
// their children in its record classes, and stores necessary requests in a
|
|
// manager which doles out requests as we need them.
|
|
//
|
|
// The idea is, is that we will spin off a single request which will begin
|
|
// executing the first topmost request, say "ClassA:. As we execute the request
|
|
// for instances of "ClassA" if the request is throttled in the merger, we check
|
|
// if we have submitted a request to handle children of "ClassA". If not, then
|
|
// prior to throttling, we will schedule a "Children of ClassA" request. This
|
|
// request will use the merger record for "ClassA" to determine what child classes
|
|
// there are for "ClassA", and then we will walk the child classes, pulling the
|
|
// appropriate requests from the merger request manager.
|
|
//
|
|
// As we process each request, it in turn may be throttled, at which point we will
|
|
// spin off another child request. In this way, we limit the number of threads
|
|
// required to service the query to at most one per level of a hierarchy. In each
|
|
// case, once all children are processed, we will return the thread back to the
|
|
// threadpool.
|
|
//
|
|
// Note that we are absolutely reliant on the threadpool recognizing that these
|
|
// requests are all dependent requests and ensuring that they WILL be processed.
|
|
//
|
|
|
|
|
|
//
|
|
// CMergerReq
|
|
//
|
|
// Base class for all merger requests.
|
|
//
|
|
|
|
class CMergerReq : public CNamespaceReq
|
|
{
|
|
private:
|
|
|
|
public:
|
|
CMergerReq( CWbemNamespace* pNamespace, IWbemObjectSink* pHandler,
|
|
IWbemContext* pContext)
|
|
: CNamespaceReq( pNamespace, pHandler, pContext, true )
|
|
{};
|
|
|
|
~CMergerReq() {};
|
|
|
|
virtual BOOL IsStatic( void ) { return FALSE; }
|
|
|
|
virtual LPCWSTR GetName( void ) { return L""; }
|
|
};
|
|
|
|
//
|
|
// Class Request Base Class
|
|
//
|
|
|
|
class CMergerClassReq : public CMergerReq
|
|
{
|
|
protected:
|
|
CWmiMerger* m_pMerger;
|
|
CWmiMergerRecord* m_pParentRecord;
|
|
CBasicObjectSink* m_pSink;
|
|
|
|
|
|
public:
|
|
CMergerClassReq( CWmiMerger* pMerger, CWmiMergerRecord* pParentRecord,
|
|
CWbemNamespace* pNamespace, CBasicObjectSink* pHandler,
|
|
IWbemContext* pContext);
|
|
|
|
~CMergerClassReq();
|
|
|
|
virtual BOOL IsLongRunning() {return TRUE;}
|
|
|
|
void DumpError();
|
|
|
|
};
|
|
|
|
//
|
|
// Parent Class Request
|
|
//
|
|
|
|
class CMergerParentReq : public CMergerClassReq
|
|
{
|
|
public:
|
|
CMergerParentReq( CWmiMerger* pMerger, CWmiMergerRecord* pParentRecord,
|
|
CWbemNamespace* pNamespace, CBasicObjectSink* pHandler,
|
|
IWbemContext* pContext)
|
|
: CMergerClassReq( pMerger, pParentRecord, pNamespace, pHandler, pContext )
|
|
{};
|
|
|
|
~CMergerParentReq() {};
|
|
|
|
HRESULT Execute ();
|
|
LPCWSTR GetReqInfo(){ return L"MergerParentReq"; };
|
|
};
|
|
|
|
//
|
|
// Child Class Request
|
|
//
|
|
|
|
class CMergerChildReq : public CMergerClassReq
|
|
{
|
|
|
|
public:
|
|
CMergerChildReq( CWmiMerger* pMerger, CWmiMergerRecord* pParentRecord,
|
|
CWbemNamespace* pNamespace, CBasicObjectSink* pHandler,
|
|
IWbemContext* pContext)
|
|
: CMergerClassReq( pMerger, pParentRecord, pNamespace, pHandler, pContext )
|
|
{};
|
|
|
|
~CMergerChildReq() {};
|
|
|
|
HRESULT Execute ();
|
|
LPCWSTR GetReqInfo(){ return L"MergerChildReq"; };
|
|
};
|
|
|
|
|
|
// Base class for Dynamic requests
|
|
class CMergerDynReq : public CMergerReq
|
|
{
|
|
private:
|
|
CVar m_varClassName;
|
|
|
|
public:
|
|
CMergerDynReq(CWbemObject* pClassDef, CWbemNamespace* pNamespace, IWbemObjectSink* pHandler,
|
|
IWbemContext* pContext);
|
|
|
|
~CMergerDynReq() {};
|
|
|
|
LPCWSTR GetName( void ) { return m_varClassName.GetLPWSTR(); }
|
|
};
|
|
|
|
//
|
|
// CMergerDynReq_DynAux_GetInstances
|
|
//
|
|
// This request processes CreateInstanceEnum calls to providers.
|
|
//
|
|
|
|
class CMergerDynReq_DynAux_GetInstances : public CMergerDynReq
|
|
{
|
|
private:
|
|
|
|
CWbemObject *m_pClassDef ;
|
|
IWbemContext *m_pCtx ;
|
|
long m_lFlags ;
|
|
CBasicObjectSink *m_pSink ;
|
|
|
|
public:
|
|
|
|
CMergerDynReq_DynAux_GetInstances (CWbemNamespace *pNamespace,
|
|
CWbemObject *pClassDef,
|
|
long lFlags,
|
|
IWbemContext *pCtx,
|
|
CBasicObjectSink *pSink):
|
|
CMergerDynReq (pClassDef,pNamespace,pSink,pCtx),
|
|
m_pClassDef(pClassDef),
|
|
m_pCtx(pCtx),
|
|
m_pSink(pSink),
|
|
m_lFlags(lFlags)
|
|
{
|
|
if (m_pClassDef) m_pClassDef->AddRef () ;
|
|
if (m_pCtx) m_pCtx->AddRef () ;
|
|
if (m_pSink) m_pSink->AddRef () ;
|
|
}
|
|
|
|
~CMergerDynReq_DynAux_GetInstances ()
|
|
{
|
|
if (m_pClassDef) m_pClassDef->Release () ;
|
|
if (m_pCtx) m_pCtx->Release () ;
|
|
if (m_pSink) m_pSink->Release () ;
|
|
}
|
|
|
|
HRESULT Execute ();
|
|
virtual BOOL IsLongRunning() {return TRUE;}
|
|
void DumpError();
|
|
LPCWSTR GetReqInfo()
|
|
{
|
|
_variant_t varClass;
|
|
if (FAILED(m_pClassDef->Get(L"__CLASS",0,&varClass,0,0))) return L"";
|
|
if (VT_BSTR == V_VT(&varClass))
|
|
{
|
|
StringCchCopyW(CNamespaceReq::s_DumpBuffer,LENGTH_OF(CNamespaceReq::s_DumpBuffer)-1,V_BSTR(&varClass));
|
|
return CNamespaceReq::s_DumpBuffer;
|
|
}
|
|
else return L"";
|
|
};
|
|
};
|
|
|
|
//
|
|
// CMergerDynReq_DynAux_ExecQueryAsync
|
|
//
|
|
// This request processes ExecQuery calls to providers.
|
|
//
|
|
|
|
class CMergerDynReq_DynAux_ExecQueryAsync : public CMergerDynReq
|
|
{
|
|
private:
|
|
CWbemObject *m_pClassDef ;
|
|
BSTR m_Query ;
|
|
BSTR m_QueryFormat ;
|
|
IWbemContext *m_pCtx ;
|
|
long m_lFlags ;
|
|
CBasicObjectSink *m_pSink ;
|
|
HRESULT m_Result ;
|
|
public:
|
|
|
|
CMergerDynReq_DynAux_ExecQueryAsync(CWbemNamespace *pNamespace,
|
|
CWbemObject *pClassDef,
|
|
long lFlags,
|
|
LPCWSTR Query,
|
|
LPCWSTR QueryFormat,
|
|
IWbemContext *pCtx,
|
|
CBasicObjectSink *pSink):
|
|
CMergerDynReq(pClassDef,
|
|
pNamespace,
|
|
pSink,
|
|
pCtx),
|
|
m_pClassDef(pClassDef),
|
|
m_pCtx(pCtx),
|
|
m_pSink(pSink),
|
|
m_lFlags(lFlags),
|
|
m_Query(NULL),
|
|
m_QueryFormat(NULL),
|
|
m_Result (S_OK)
|
|
{
|
|
if (m_pClassDef) m_pClassDef->AddRef () ;
|
|
if (m_pCtx) m_pCtx->AddRef () ;
|
|
if (m_pSink) m_pSink->AddRef () ;
|
|
|
|
|
|
if (Query)
|
|
{
|
|
m_Query = SysAllocString ( Query ) ;
|
|
if ( m_Query == NULL )
|
|
{
|
|
m_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
|
|
if (QueryFormat)
|
|
{
|
|
m_QueryFormat = SysAllocString ( QueryFormat ) ;
|
|
if ( m_QueryFormat == NULL )
|
|
{
|
|
m_Result = WBEM_E_OUT_OF_MEMORY ;
|
|
}
|
|
}
|
|
}
|
|
|
|
HRESULT Initialize ()
|
|
{
|
|
return m_Result ;
|
|
}
|
|
|
|
~CMergerDynReq_DynAux_ExecQueryAsync ()
|
|
{
|
|
if (m_pClassDef) m_pClassDef->Release();
|
|
if (m_pCtx)m_pCtx->Release();
|
|
if (m_pSink) m_pSink->Release();
|
|
SysFreeString(m_Query);
|
|
SysFreeString(m_QueryFormat);
|
|
}
|
|
|
|
HRESULT Execute ();
|
|
virtual BOOL IsLongRunning() {return TRUE;}
|
|
void DumpError();
|
|
LPCWSTR GetReqInfo(){ return m_Query; };
|
|
};
|
|
|
|
//
|
|
// CMergerDynReq_Static_GetInstances
|
|
//
|
|
// This request processes CreateInstanceEnum calls to the repository.
|
|
//
|
|
|
|
class CMergerDynReq_Static_GetInstances : public CMergerDynReq
|
|
{
|
|
private:
|
|
|
|
CWbemObject *m_pClassDef ;
|
|
IWbemContext *m_pCtx ;
|
|
long m_lFlags ;
|
|
CBasicObjectSink *m_pSink ;
|
|
QL_LEVEL_1_RPN_EXPRESSION* m_pParsedQuery;
|
|
|
|
public:
|
|
|
|
CMergerDynReq_Static_GetInstances (CWbemNamespace *pNamespace ,
|
|
CWbemObject *pClassDef ,
|
|
long lFlags ,
|
|
IWbemContext *pCtx ,
|
|
CBasicObjectSink *pSink ,
|
|
QL_LEVEL_1_RPN_EXPRESSION* pParsedQuery);
|
|
|
|
~CMergerDynReq_Static_GetInstances();
|
|
HRESULT Execute();
|
|
virtual BOOL IsLongRunning() {return TRUE;}
|
|
void DumpError();
|
|
BOOL IsStatic( void ) { return TRUE; }
|
|
LPCWSTR GetReqInfo()
|
|
{
|
|
_variant_t varClass;
|
|
if (FAILED(m_pClassDef->Get(L"__CLASS",0,&varClass,0,0))) return L"";
|
|
if (VT_BSTR == V_VT(&varClass))
|
|
{
|
|
StringCchCopyW(CNamespaceReq::s_DumpBuffer,LENGTH_OF(CNamespaceReq::s_DumpBuffer)-1,V_BSTR(&varClass));
|
|
return CNamespaceReq::s_DumpBuffer;
|
|
}
|
|
else return L"";
|
|
};
|
|
};
|
|
|
|
|
|
//
|
|
// CWmiMergerRequestMgr
|
|
//
|
|
// Manager class for Merger Requests. It keeps an array of sorted arrays
|
|
// corresponding to the actual requests we will be performing. The sorted
|
|
// arrays contain merger requests for handling calls to the various
|
|
// dynamic instance providers.
|
|
//
|
|
|
|
class CWmiMergerRequestMgr
|
|
{
|
|
CWmiMerger* m_pMerger;
|
|
CFlexArray m_HierarchyArray;
|
|
DWORD m_dwNumRequests;
|
|
DWORD m_dwMinLevel;
|
|
DWORD m_dwMaxLevel;
|
|
DWORD m_dwLevelMask;
|
|
DWORD* m_pdwLevelMask;
|
|
|
|
public:
|
|
CWmiMergerRequestMgr( CWmiMerger* pMerger );
|
|
~CWmiMergerRequestMgr();
|
|
|
|
HRESULT AddRequest( CMergerDynReq* pReq, DWORD dwLevel );
|
|
HRESULT RemoveRequest( DWORD dwLevel, LPCWSTR pwszName,
|
|
wmilib::auto_ptr<CMergerReq> & pReq );
|
|
HRESULT GetTopmostParentReqName( WString& wsClassName );
|
|
BOOL HasSingleStaticRequest( void );
|
|
HRESULT Clear();
|
|
void DumpRequestHierarchy( void );
|
|
|
|
DWORD GetNumRequests( void ) { return m_dwNumRequests; }
|
|
DWORD GetNumRequestsAtLevel( DWORD dwLevel );
|
|
BOOL GetRequestAtLevel( DWORD dwLevel, wmilib::auto_ptr<CMergerReq> & pReq );
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|