Source code of Windows XP (NT5)
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.

670 lines
19 KiB

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