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

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. MERGERREQ.H
  5. Abstract:
  6. Definitions of Merger Request classes
  7. History:
  8. 28-Feb-01 sanjes Created.
  9. --*/
  10. #ifndef _MERGERREQ_H_
  11. #define _MERGERREQ_H_
  12. // forward class definitions
  13. class CWmiMerger;
  14. class CWmiMergerRecord;
  15. //
  16. // Merger Requests
  17. //
  18. // In previous releases, when the query engine analyzed a query, it enqueued
  19. // a large number of requests, one for each dynamically provided class. Each
  20. // of these could be handled on a separate thread, which could cause a
  21. // significant thread explosion as each request was handed to a separate thread.
  22. //
  23. // In order to better control the threads, we are using the merger to perform
  24. // a more intelligent analysis of a query and then spin off threads only when
  25. // we reach throttling conditions. Now, instead of enqueing a large number of
  26. // requests, the merger maintains hierarchical information regarding parents and
  27. // their children in its record classes, and stores necessary requests in a
  28. // manager which doles out requests as we need them.
  29. //
  30. // The idea is, is that we will spin off a single request which will begin
  31. // executing the first topmost request, say "ClassA:. As we execute the request
  32. // for instances of "ClassA" if the request is throttled in the merger, we check
  33. // if we have submitted a request to handle children of "ClassA". If not, then
  34. // prior to throttling, we will schedule a "Children of ClassA" request. This
  35. // request will use the merger record for "ClassA" to determine what child classes
  36. // there are for "ClassA", and then we will walk the child classes, pulling the
  37. // appropriate requests from the merger request manager.
  38. //
  39. // As we process each request, it in turn may be throttled, at which point we will
  40. // spin off another child request. In this way, we limit the number of threads
  41. // required to service the query to at most one per level of a hierarchy. In each
  42. // case, once all children are processed, we will return the thread back to the
  43. // threadpool.
  44. //
  45. // Note that we are absolutely reliant on the threadpool recognizing that these
  46. // requests are all dependent requests and ensuring that they WILL be processed.
  47. //
  48. //
  49. // CMergerReq
  50. //
  51. // Base class for all merger requests.
  52. //
  53. class CMergerReq : public CNamespaceReq
  54. {
  55. private:
  56. public:
  57. CMergerReq( CWbemNamespace* pNamespace, IWbemObjectSink* pHandler,
  58. IWbemContext* pContext)
  59. : CNamespaceReq( pNamespace, pHandler, pContext, true )
  60. {};
  61. ~CMergerReq() {};
  62. virtual BOOL IsStatic( void ) { return FALSE; }
  63. virtual LPCWSTR GetName( void ) { return L""; }
  64. };
  65. //
  66. // Class Request Base Class
  67. //
  68. class CMergerClassReq : public CMergerReq
  69. {
  70. protected:
  71. CWmiMerger* m_pMerger;
  72. CWmiMergerRecord* m_pParentRecord;
  73. CBasicObjectSink* m_pSink;
  74. public:
  75. CMergerClassReq( CWmiMerger* pMerger, CWmiMergerRecord* pParentRecord,
  76. CWbemNamespace* pNamespace, CBasicObjectSink* pHandler,
  77. IWbemContext* pContext);
  78. ~CMergerClassReq();
  79. virtual BOOL IsLongRunning() {return TRUE;}
  80. void DumpError();
  81. };
  82. //
  83. // Parent Class Request
  84. //
  85. class CMergerParentReq : public CMergerClassReq
  86. {
  87. public:
  88. CMergerParentReq( CWmiMerger* pMerger, CWmiMergerRecord* pParentRecord,
  89. CWbemNamespace* pNamespace, CBasicObjectSink* pHandler,
  90. IWbemContext* pContext)
  91. : CMergerClassReq( pMerger, pParentRecord, pNamespace, pHandler, pContext )
  92. {};
  93. ~CMergerParentReq() {};
  94. HRESULT Execute ();
  95. LPCWSTR GetReqInfo(){ return L"MergerParentReq"; };
  96. };
  97. //
  98. // Child Class Request
  99. //
  100. class CMergerChildReq : public CMergerClassReq
  101. {
  102. public:
  103. CMergerChildReq( CWmiMerger* pMerger, CWmiMergerRecord* pParentRecord,
  104. CWbemNamespace* pNamespace, CBasicObjectSink* pHandler,
  105. IWbemContext* pContext)
  106. : CMergerClassReq( pMerger, pParentRecord, pNamespace, pHandler, pContext )
  107. {};
  108. ~CMergerChildReq() {};
  109. HRESULT Execute ();
  110. LPCWSTR GetReqInfo(){ return L"MergerChildReq"; };
  111. };
  112. // Base class for Dynamic requests
  113. class CMergerDynReq : public CMergerReq
  114. {
  115. private:
  116. CVar m_varClassName;
  117. public:
  118. CMergerDynReq(CWbemObject* pClassDef, CWbemNamespace* pNamespace, IWbemObjectSink* pHandler,
  119. IWbemContext* pContext);
  120. ~CMergerDynReq() {};
  121. LPCWSTR GetName( void ) { return m_varClassName.GetLPWSTR(); }
  122. };
  123. //
  124. // CMergerDynReq_DynAux_GetInstances
  125. //
  126. // This request processes CreateInstanceEnum calls to providers.
  127. //
  128. class CMergerDynReq_DynAux_GetInstances : public CMergerDynReq
  129. {
  130. private:
  131. CWbemObject *m_pClassDef ;
  132. IWbemContext *m_pCtx ;
  133. long m_lFlags ;
  134. CBasicObjectSink *m_pSink ;
  135. public:
  136. CMergerDynReq_DynAux_GetInstances (CWbemNamespace *pNamespace,
  137. CWbemObject *pClassDef,
  138. long lFlags,
  139. IWbemContext *pCtx,
  140. CBasicObjectSink *pSink):
  141. CMergerDynReq (pClassDef,pNamespace,pSink,pCtx),
  142. m_pClassDef(pClassDef),
  143. m_pCtx(pCtx),
  144. m_pSink(pSink),
  145. m_lFlags(lFlags)
  146. {
  147. if (m_pClassDef) m_pClassDef->AddRef () ;
  148. if (m_pCtx) m_pCtx->AddRef () ;
  149. if (m_pSink) m_pSink->AddRef () ;
  150. }
  151. ~CMergerDynReq_DynAux_GetInstances ()
  152. {
  153. if (m_pClassDef) m_pClassDef->Release () ;
  154. if (m_pCtx) m_pCtx->Release () ;
  155. if (m_pSink) m_pSink->Release () ;
  156. }
  157. HRESULT Execute ();
  158. virtual BOOL IsLongRunning() {return TRUE;}
  159. void DumpError();
  160. LPCWSTR GetReqInfo()
  161. {
  162. _variant_t varClass;
  163. if (FAILED(m_pClassDef->Get(L"__CLASS",0,&varClass,0,0))) return L"";
  164. if (VT_BSTR == V_VT(&varClass))
  165. {
  166. StringCchCopyW(CNamespaceReq::s_DumpBuffer,LENGTH_OF(CNamespaceReq::s_DumpBuffer)-1,V_BSTR(&varClass));
  167. return CNamespaceReq::s_DumpBuffer;
  168. }
  169. else return L"";
  170. };
  171. };
  172. //
  173. // CMergerDynReq_DynAux_ExecQueryAsync
  174. //
  175. // This request processes ExecQuery calls to providers.
  176. //
  177. class CMergerDynReq_DynAux_ExecQueryAsync : public CMergerDynReq
  178. {
  179. private:
  180. CWbemObject *m_pClassDef ;
  181. BSTR m_Query ;
  182. BSTR m_QueryFormat ;
  183. IWbemContext *m_pCtx ;
  184. long m_lFlags ;
  185. CBasicObjectSink *m_pSink ;
  186. HRESULT m_Result ;
  187. public:
  188. CMergerDynReq_DynAux_ExecQueryAsync(CWbemNamespace *pNamespace,
  189. CWbemObject *pClassDef,
  190. long lFlags,
  191. LPCWSTR Query,
  192. LPCWSTR QueryFormat,
  193. IWbemContext *pCtx,
  194. CBasicObjectSink *pSink):
  195. CMergerDynReq(pClassDef,
  196. pNamespace,
  197. pSink,
  198. pCtx),
  199. m_pClassDef(pClassDef),
  200. m_pCtx(pCtx),
  201. m_pSink(pSink),
  202. m_lFlags(lFlags),
  203. m_Query(NULL),
  204. m_QueryFormat(NULL),
  205. m_Result (S_OK)
  206. {
  207. if (m_pClassDef) m_pClassDef->AddRef () ;
  208. if (m_pCtx) m_pCtx->AddRef () ;
  209. if (m_pSink) m_pSink->AddRef () ;
  210. if (Query)
  211. {
  212. m_Query = SysAllocString ( Query ) ;
  213. if ( m_Query == NULL )
  214. {
  215. m_Result = WBEM_E_OUT_OF_MEMORY ;
  216. }
  217. }
  218. if (QueryFormat)
  219. {
  220. m_QueryFormat = SysAllocString ( QueryFormat ) ;
  221. if ( m_QueryFormat == NULL )
  222. {
  223. m_Result = WBEM_E_OUT_OF_MEMORY ;
  224. }
  225. }
  226. }
  227. HRESULT Initialize ()
  228. {
  229. return m_Result ;
  230. }
  231. ~CMergerDynReq_DynAux_ExecQueryAsync ()
  232. {
  233. if (m_pClassDef) m_pClassDef->Release();
  234. if (m_pCtx)m_pCtx->Release();
  235. if (m_pSink) m_pSink->Release();
  236. SysFreeString(m_Query);
  237. SysFreeString(m_QueryFormat);
  238. }
  239. HRESULT Execute ();
  240. virtual BOOL IsLongRunning() {return TRUE;}
  241. void DumpError();
  242. LPCWSTR GetReqInfo(){ return m_Query; };
  243. };
  244. //
  245. // CMergerDynReq_Static_GetInstances
  246. //
  247. // This request processes CreateInstanceEnum calls to the repository.
  248. //
  249. class CMergerDynReq_Static_GetInstances : public CMergerDynReq
  250. {
  251. private:
  252. CWbemObject *m_pClassDef ;
  253. IWbemContext *m_pCtx ;
  254. long m_lFlags ;
  255. CBasicObjectSink *m_pSink ;
  256. QL_LEVEL_1_RPN_EXPRESSION* m_pParsedQuery;
  257. public:
  258. CMergerDynReq_Static_GetInstances (CWbemNamespace *pNamespace ,
  259. CWbemObject *pClassDef ,
  260. long lFlags ,
  261. IWbemContext *pCtx ,
  262. CBasicObjectSink *pSink ,
  263. QL_LEVEL_1_RPN_EXPRESSION* pParsedQuery);
  264. ~CMergerDynReq_Static_GetInstances();
  265. HRESULT Execute();
  266. virtual BOOL IsLongRunning() {return TRUE;}
  267. void DumpError();
  268. BOOL IsStatic( void ) { return TRUE; }
  269. LPCWSTR GetReqInfo()
  270. {
  271. _variant_t varClass;
  272. if (FAILED(m_pClassDef->Get(L"__CLASS",0,&varClass,0,0))) return L"";
  273. if (VT_BSTR == V_VT(&varClass))
  274. {
  275. StringCchCopyW(CNamespaceReq::s_DumpBuffer,LENGTH_OF(CNamespaceReq::s_DumpBuffer)-1,V_BSTR(&varClass));
  276. return CNamespaceReq::s_DumpBuffer;
  277. }
  278. else return L"";
  279. };
  280. };
  281. //
  282. // CWmiMergerRequestMgr
  283. //
  284. // Manager class for Merger Requests. It keeps an array of sorted arrays
  285. // corresponding to the actual requests we will be performing. The sorted
  286. // arrays contain merger requests for handling calls to the various
  287. // dynamic instance providers.
  288. //
  289. class CWmiMergerRequestMgr
  290. {
  291. CWmiMerger* m_pMerger;
  292. CFlexArray m_HierarchyArray;
  293. DWORD m_dwNumRequests;
  294. DWORD m_dwMinLevel;
  295. DWORD m_dwMaxLevel;
  296. DWORD m_dwLevelMask;
  297. DWORD* m_pdwLevelMask;
  298. public:
  299. CWmiMergerRequestMgr( CWmiMerger* pMerger );
  300. ~CWmiMergerRequestMgr();
  301. HRESULT AddRequest( CMergerDynReq* pReq, DWORD dwLevel );
  302. HRESULT RemoveRequest( DWORD dwLevel, LPCWSTR pwszName,
  303. wmilib::auto_ptr<CMergerReq> & pReq );
  304. HRESULT GetTopmostParentReqName( WString& wsClassName );
  305. BOOL HasSingleStaticRequest( void );
  306. HRESULT Clear();
  307. void DumpRequestHierarchy( void );
  308. DWORD GetNumRequests( void ) { return m_dwNumRequests; }
  309. DWORD GetNumRequestsAtLevel( DWORD dwLevel );
  310. BOOL GetRequestAtLevel( DWORD dwLevel, wmilib::auto_ptr<CMergerReq> & pReq );
  311. };
  312. #endif
  313.