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.
 
 
 
 
 
 

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