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.

597 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // AsyncEvictCleanup.cpp
  7. //
  8. // Description:
  9. // This file contains the implementation of the CAsyncEvictCleanup
  10. // class.
  11. //
  12. // Maintained By:
  13. // Galen Barbee (GalenB) 15-JUN-2000
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. //////////////////////////////////////////////////////////////////////////////
  17. // Include Files
  18. //////////////////////////////////////////////////////////////////////////////
  19. // The precompiled header for this library
  20. #include "Pch.h"
  21. // The header file for this class
  22. #include "AsyncEvictCleanup.h"
  23. // For IClusCfgEvictCleanup and related interfaces
  24. #include "ClusCfgServer.h"
  25. //////////////////////////////////////////////////////////////////////////////
  26. // Macro Definitions
  27. //////////////////////////////////////////////////////////////////////////////
  28. DEFINE_THISCLASS( "CAsyncEvictCleanup" );
  29. //////////////////////////////////////////////////////////////////////////////
  30. // Global Variable Definitions
  31. //////////////////////////////////////////////////////////////////////////////
  32. //////////////////////////////////////////////////////////////////////////////
  33. //++
  34. //
  35. // CAsyncEvictCleanup::S_HrCreateInstance
  36. //
  37. // Description:
  38. // Creates a CAsyncEvictCleanup instance.
  39. //
  40. // Arguments:
  41. // ppunkOut
  42. // The IUnknown interface of the new object.
  43. //
  44. // Return Values:
  45. // S_OK
  46. // Success.
  47. //
  48. // E_OUTOFMEMORY
  49. // Not enough memory to create the object.
  50. //
  51. // other HRESULTs
  52. // Object initialization failed.
  53. //
  54. //--
  55. //////////////////////////////////////////////////////////////////////////////
  56. HRESULT
  57. CAsyncEvictCleanup::S_HrCreateInstance( IUnknown ** ppunkOut )
  58. {
  59. TraceFunc( "" );
  60. HRESULT hr = S_OK;
  61. CAsyncEvictCleanup * pAsyncEvictCleanup = NULL;
  62. Assert( ppunkOut != NULL );
  63. if ( ppunkOut == NULL )
  64. {
  65. hr = THR( E_POINTER );
  66. goto Cleanup;
  67. }
  68. // Allocate memory for the new object.
  69. pAsyncEvictCleanup = new CAsyncEvictCleanup();
  70. if ( pAsyncEvictCleanup == NULL )
  71. {
  72. hr = THR( E_OUTOFMEMORY );
  73. goto Cleanup;
  74. } // if: out of memory
  75. // Initialize the new object.
  76. hr = THR( pAsyncEvictCleanup->HrInit() );
  77. if ( FAILED( hr ) )
  78. {
  79. goto Cleanup;
  80. } // if: the object could not be initialized
  81. hr = THR( pAsyncEvictCleanup->QueryInterface( IID_IUnknown, reinterpret_cast< void ** >( ppunkOut ) ) );
  82. if ( FAILED( hr ) )
  83. {
  84. goto Cleanup;
  85. }
  86. Cleanup:
  87. if ( pAsyncEvictCleanup != NULL )
  88. {
  89. pAsyncEvictCleanup->Release();
  90. } // if: the pointer to the resource type object is not NULL
  91. HRETURN( hr );
  92. } //*** CAsyncEvictCleanup::S_HrCreateInstance
  93. //////////////////////////////////////////////////////////////////////////////
  94. //++
  95. //
  96. // CAsyncEvictCleanup::CAsyncEvictCleanup
  97. //
  98. // Description:
  99. // Constructor of the CAsyncEvictCleanup class. This initializes
  100. // the m_cRef variable to 1 instead of 0 to account of possible
  101. // QueryInterface failure in DllGetClassObject.
  102. //
  103. // Arguments:
  104. // None.
  105. //
  106. // Return Value:
  107. // None.
  108. //
  109. // Remarks:
  110. // None.
  111. //
  112. //--
  113. //////////////////////////////////////////////////////////////////////////////
  114. CAsyncEvictCleanup::CAsyncEvictCleanup( void )
  115. : m_cRef( 1 )
  116. {
  117. TraceFunc( "" );
  118. // Increment the count of components in memory so the DLL hosting this
  119. // object cannot be unloaded.
  120. InterlockedIncrement( &g_cObjects );
  121. TraceFlow1( "CAsyncEvictCleanup::CAsyncEvictCleanup() - Component count = %d.", g_cObjects );
  122. TraceFuncExit();
  123. } //*** CAsyncEvictCleanup::CAsyncEvictCleanup
  124. //////////////////////////////////////////////////////////////////////////////
  125. //++
  126. //
  127. // CAsyncEvictCleanup::~CAsyncEvictCleanup
  128. //
  129. // Description:
  130. // Destructor of the CAsyncEvictCleanup class.
  131. //
  132. // Arguments:
  133. // None.
  134. //
  135. // Return Value:
  136. // None.
  137. //
  138. // Remarks:
  139. // None.
  140. //
  141. //--
  142. //////////////////////////////////////////////////////////////////////////////
  143. CAsyncEvictCleanup::~CAsyncEvictCleanup( void )
  144. {
  145. TraceFunc( "" );
  146. // There's going to be one less component in memory. Decrement component count.
  147. InterlockedDecrement( &g_cObjects );
  148. TraceFlow1( "CAsyncEvictCleanup::~CAsyncEvictCleanup() - Component count = %d.", g_cObjects );
  149. TraceFuncExit();
  150. } //*** CAsyncEvictCleanup::~CAsyncEvictCleanup
  151. //////////////////////////////////////////////////////////////////////////////
  152. //++
  153. //
  154. // CAsyncEvictCleanup::AddRef
  155. //
  156. // Description:
  157. // Increment the reference count of this object by one.
  158. //
  159. // Arguments:
  160. // None.
  161. //
  162. // Return Value:
  163. // The new reference count.
  164. //
  165. // Remarks:
  166. // None.
  167. //
  168. //--
  169. //////////////////////////////////////////////////////////////////////////////
  170. STDMETHODIMP_( ULONG )
  171. CAsyncEvictCleanup::AddRef( void )
  172. {
  173. TraceFunc( "[IUnknown]" );
  174. InterlockedIncrement( &m_cRef );
  175. CRETURN( m_cRef );
  176. } //*** CAsyncEvictCleanup::AddRef
  177. //////////////////////////////////////////////////////////////////////////////
  178. //++
  179. //
  180. // CAsyncEvictCleanup::Release
  181. //
  182. // Description:
  183. // Decrement the reference count of this object by one.
  184. //
  185. // Arguments:
  186. // None.
  187. //
  188. // Return Value:
  189. // The new reference count.
  190. //
  191. // Remarks:
  192. // None.
  193. //
  194. //--
  195. //////////////////////////////////////////////////////////////////////////////
  196. STDMETHODIMP_( ULONG )
  197. CAsyncEvictCleanup::Release( void )
  198. {
  199. TraceFunc( "[IUnknown]" );
  200. LONG cRef;
  201. cRef = InterlockedDecrement( &m_cRef );
  202. if ( cRef == 0 )
  203. {
  204. TraceDo( delete this );
  205. } // if: reference count decremented to zero
  206. CRETURN( cRef );
  207. } //*** CAsyncEvictCleanup::Release
  208. //////////////////////////////////////////////////////////////////////////////
  209. //++
  210. //
  211. // CAsyncEvictCleanup::QueryInterface
  212. //
  213. // Description:
  214. // Query this object for the passed in interface.
  215. //
  216. // Arguments:
  217. // riidIn
  218. // Id of interface requested.
  219. //
  220. // ppvOut
  221. // Pointer to the requested interface.
  222. //
  223. // Return Value:
  224. // S_OK
  225. // If the interface is available on this object.
  226. //
  227. // E_NOINTERFACE
  228. // If the interface is not available.
  229. //
  230. // E_POINTER
  231. // ppvOut was NULL.
  232. //
  233. // Remarks:
  234. // None.
  235. //
  236. //--
  237. //////////////////////////////////////////////////////////////////////////////
  238. STDMETHODIMP
  239. CAsyncEvictCleanup::QueryInterface(
  240. REFIID riidIn
  241. , void ** ppvOut
  242. )
  243. {
  244. TraceQIFunc( riidIn, ppvOut );
  245. HRESULT hr = S_OK;
  246. //
  247. // Validate arguments.
  248. //
  249. Assert( ppvOut != NULL );
  250. if ( ppvOut == NULL )
  251. {
  252. hr = THR( E_POINTER );
  253. goto Cleanup;
  254. }
  255. //
  256. // Handle known interfaces.
  257. //
  258. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  259. {
  260. *ppvOut = static_cast< IClusCfgAsyncEvictCleanup * >( this );
  261. } // if: IUnknown
  262. else if ( IsEqualIID( riidIn, IID_IDispatch ) )
  263. {
  264. *ppvOut = TraceInterface( __THISCLASS__, IDispatch, this, 0 );
  265. } // else if: IDispatch
  266. else if ( IsEqualIID( riidIn, IID_IClusCfgAsyncEvictCleanup ) )
  267. {
  268. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgAsyncEvictCleanup, this, 0 );
  269. } // else if: IClusCfgAsyncEvictCleanup
  270. else
  271. {
  272. *ppvOut = NULL;
  273. hr = E_NOINTERFACE;
  274. } // else
  275. //
  276. // Add a reference to the interface if successful.
  277. //
  278. if ( SUCCEEDED( hr ) )
  279. {
  280. ((IUnknown *) *ppvOut)->AddRef();
  281. } // if: success
  282. Cleanup:
  283. QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
  284. } //*** CAsyncEvictCleanup::QueryInterface
  285. //////////////////////////////////////////////////////////////////////////////
  286. //++
  287. //
  288. // CAsyncEvictCleanup::HrInit
  289. //
  290. // Description:
  291. // Second phase of a two phase constructor.
  292. //
  293. // Arguments:
  294. // None.
  295. //
  296. // Return Value:
  297. // S_OK
  298. // If the call succeeded
  299. //
  300. // Other HRESULTs
  301. // If the call failed.
  302. //
  303. //--
  304. //////////////////////////////////////////////////////////////////////////////
  305. HRESULT
  306. CAsyncEvictCleanup::HrInit( void )
  307. {
  308. TraceFunc( "" );
  309. HRESULT hr = S_OK;
  310. // IUnknown
  311. Assert( m_cRef == 1 );
  312. // Create simplified type information.
  313. hr = THR( TDispatchHandler< IClusCfgAsyncEvictCleanup >::HrInit( LIBID_ClusCfgClient ) );
  314. if ( FAILED( hr ) )
  315. {
  316. LogMsg( "[AEC] Error %#08x occurred trying to create type information for the IDispatch interface.", hr );
  317. goto Cleanup;
  318. } // if: we could not create the type info for the IDispatch interface
  319. Cleanup:
  320. HRETURN( hr );
  321. } //*** CAsyncEvictCleanup::HrInit
  322. //////////////////////////////////////////////////////////////////////////
  323. //++
  324. //
  325. // CAsyncEvictCleanup::CleanupNode
  326. //
  327. // Routine Description:
  328. // Cleanup a node that has been evicted.
  329. //
  330. // Arguments:
  331. // bstrEvictedNodeNameIn
  332. // Name of the node on which cleanup is to be initiated. If this is NULL
  333. // the local node is cleaned up.
  334. //
  335. // nDelayIn
  336. // Number of milliseconds that will elapse before cleanup is started
  337. // on the target node. If some other process cleans up the target node while
  338. // delay is in progress, the delay is terminated. If this value is zero,
  339. // the node is cleaned up immediately.
  340. //
  341. // nTimeoutIn
  342. // Number of milliseconds that this method will wait for cleanup to complete.
  343. // This timeout is independent of the delay above, so if dwDelayIn is greater
  344. // than dwTimeoutIn, this method will most probably timeout. Once initiated,
  345. // however, cleanup will run to completion - this method just may not wait for it
  346. // to complete.
  347. //
  348. // Return Value:
  349. // S_OK
  350. // If the cleanup operations were successful
  351. //
  352. // RPC_S_CALLPENDING
  353. // If cleanup is not complete in dwTimeoutIn milliseconds
  354. //
  355. // Other HRESULTS
  356. // In case of error
  357. //
  358. //--
  359. //////////////////////////////////////////////////////////////////////////
  360. HRESULT
  361. CAsyncEvictCleanup::CleanupNode(
  362. BSTR bstrEvictedNodeNameIn
  363. , long nDelayIn
  364. , long nTimeoutIn
  365. )
  366. {
  367. TraceFunc( "[IClusCfgAsyncEvictCleanup]" );
  368. HRESULT hr = S_OK;
  369. IClusCfgEvictCleanup * pcceEvict = NULL;
  370. ICallFactory * pcfCallFactory = NULL;
  371. ISynchronize * psSync = NULL;
  372. AsyncIClusCfgEvictCleanup * paicceAsyncEvict = NULL;
  373. MULTI_QI mqiInterfaces[] =
  374. {
  375. { &IID_IClusCfgEvictCleanup, NULL, S_OK },
  376. };
  377. COSERVERINFO csiServerInfo;
  378. COSERVERINFO * pcsiServerInfoPtr = &csiServerInfo;
  379. #if 0
  380. bool fWaitForDebugger = true;
  381. while ( fWaitForDebugger )
  382. {
  383. Sleep( 3000 );
  384. } // while: waiting for the debugger to break in
  385. #endif
  386. if ( ( bstrEvictedNodeNameIn == NULL ) || ( *bstrEvictedNodeNameIn == L'\0' ) )
  387. {
  388. LogMsg( "[AEC] The local node will be cleaned up." );
  389. pcsiServerInfoPtr = NULL;
  390. } // if: we have to cleanup the local node
  391. else
  392. {
  393. LogMsg( "[AEC] The remote node to be cleaned up is '%ws'.", bstrEvictedNodeNameIn );
  394. csiServerInfo.dwReserved1 = 0;
  395. csiServerInfo.pwszName = bstrEvictedNodeNameIn;
  396. csiServerInfo.pAuthInfo = NULL;
  397. csiServerInfo.dwReserved2 = 0;
  398. } // else: we have to clean up a remote node
  399. TraceFlow( "CAsyncEvictCleanup::CleanupNode() - Creating the EvictCleanup component on the evicted node." );
  400. // Instantiate this component on the node being evicted.
  401. hr = THR(
  402. CoCreateInstanceEx(
  403. CLSID_ClusCfgEvictCleanup
  404. , NULL
  405. , CLSCTX_INPROC_SERVER
  406. , pcsiServerInfoPtr
  407. , ARRAYSIZE( mqiInterfaces )
  408. , mqiInterfaces
  409. )
  410. );
  411. if ( FAILED( hr ) )
  412. {
  413. LogMsg( "[AEC] Error %#08x occurred trying to instantiate the evict processing component on the evicted node.", hr );
  414. goto Cleanup;
  415. } // if: we could not instantiate the evict processing component
  416. // Get a pointer to the IClusCfgEvictCleanup interface.
  417. pcceEvict = reinterpret_cast< IClusCfgEvictCleanup * >( mqiInterfaces[0].pItf );
  418. TraceFlow( "CAsyncEvictCleanup::CleanupNode() - Creating a call factory." );
  419. // Now, get a pointer to the ICallFactory interface.
  420. hr = THR( pcceEvict->QueryInterface< ICallFactory >( &pcfCallFactory ) );
  421. if ( FAILED( hr ) )
  422. {
  423. LogMsg( "[AEC] Error %#08x occurred trying to get a pointer to the call factory.", hr );
  424. goto Cleanup;
  425. } // if: we could not get a pointer to the call factory interface
  426. TraceFlow( "CAsyncEvictCleanup::CleanupNode() - Creating a call object to make an asynchronous call." );
  427. // Create a call factory so that we can make an asynchronous call to cleanup the evicted node.
  428. hr = THR(
  429. pcfCallFactory->CreateCall(
  430. __uuidof( paicceAsyncEvict )
  431. , NULL
  432. , __uuidof( paicceAsyncEvict )
  433. , reinterpret_cast< IUnknown ** >( &paicceAsyncEvict )
  434. )
  435. );
  436. if ( FAILED( hr ) )
  437. {
  438. LogMsg( "[AEC] Error %#08x occurred trying to create a call object.", hr );
  439. goto Cleanup;
  440. } // if: we could not get a pointer to the asynchronous evict interface
  441. TraceFlow( "CAsyncEvictCleanup::CleanupNode() - Trying to get the ISynchronize interface pointer." );
  442. // Get a pointer to the ISynchronize interface.
  443. hr = THR( paicceAsyncEvict->QueryInterface< ISynchronize >( &psSync ) );
  444. if ( FAILED( hr ) )
  445. {
  446. goto Cleanup;
  447. } // if: we could not get a pointer to the synchronization interface
  448. TraceFlow( "CAsyncEvictCleanup::CleanupNode() - Initiating cleanup on evicted node." );
  449. // Initiate cleanup
  450. hr = THR( paicceAsyncEvict->Begin_CleanupLocalNode( nDelayIn ) );
  451. if ( ( FAILED( hr ) ) && ( HRESULT_CODE( hr ) != ERROR_NONE_MAPPED ) )
  452. {
  453. LogMsg( "[AEC] Error %#08x occurred trying to initiate cleanup on evicted node.", hr );
  454. goto Cleanup;
  455. } // if: we could not initiate cleanup
  456. TraceFlow1( "CAsyncEvictCleanup::CleanupNode() - Waiting for cleanup to complete or timeout to occur (%d milliseconds).", nTimeoutIn );
  457. // Wait for specified time.
  458. hr = psSync->Wait( 0, nTimeoutIn);
  459. if ( FAILED( hr ) )
  460. {
  461. LogMsg( "[AEC] We could not wait till the cleanup completed (status code is %#08x).", hr );
  462. goto Cleanup;
  463. } // if: we could not wait till cleanup completed
  464. TraceFlow( "CAsyncEvictCleanup::CleanupNode() - Finishing cleanup." );
  465. // Finish cleanup
  466. hr = THR( paicceAsyncEvict->Finish_CleanupLocalNode() );
  467. if ( FAILED( hr ) )
  468. {
  469. LogMsg( "[AEC] Error %#08x occurred trying to finish cleanup on evicted node.", hr );
  470. goto Cleanup;
  471. } // if: we could not finish cleanup
  472. Cleanup:
  473. //
  474. // Clean up
  475. //
  476. if ( pcceEvict != NULL )
  477. {
  478. pcceEvict->Release();
  479. } // if: we had got a pointer to the IClusCfgEvictCleanup interface
  480. if ( pcfCallFactory != NULL )
  481. {
  482. pcfCallFactory->Release();
  483. } // if: we had obtained a pointer to the call factory interface
  484. if ( psSync != NULL )
  485. {
  486. psSync->Release();
  487. } // if: we had obtained a pointer to the synchronization interface
  488. if ( paicceAsyncEvict != NULL )
  489. {
  490. paicceAsyncEvict->Release();
  491. } // if: we had obtained a pointer to the asynchronous evict interface
  492. HRETURN( hr );
  493. } //*** CAsyncEvictCleanup::CleanupNode