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.

903 lines
28 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CClusDBJoin.cpp
  7. //
  8. // Description:
  9. // Contains the definition of the CClusDBJoin class.
  10. //
  11. // Maintained By:
  12. // David Potter (DavidP) 14-JUN-2001
  13. // Vij Vasu (Vvasu) 08-MAR-2000
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. //////////////////////////////////////////////////////////////////////////////
  17. // Include Files
  18. //////////////////////////////////////////////////////////////////////////////
  19. // The precompiled header.
  20. #include "Pch.h"
  21. // The header for this file
  22. #include "CClusDBJoin.h"
  23. // For the CBaseClusterJoin class.
  24. #include "CBaseClusterJoin.h"
  25. // For the CImpersonateUser class.
  26. #include "CImpersonateUser.h"
  27. //////////////////////////////////////////////////////////////////////////////
  28. //++
  29. //
  30. // CClusDBJoin::CClusDBJoin
  31. //
  32. // Description:
  33. // Constructor of the CClusDBJoin class
  34. //
  35. // Arguments:
  36. // m_pcjClusterJoinIn
  37. // Pointer to the base cluster action of which this action is a part.
  38. //
  39. // Return Value:
  40. // None.
  41. //
  42. // Exceptions Thrown:
  43. // Any exceptions thrown by underlying functions
  44. //
  45. //--
  46. //////////////////////////////////////////////////////////////////////////////
  47. CClusDBJoin::CClusDBJoin( CBaseClusterJoin * pcjClusterJoinIn )
  48. : BaseClass( pcjClusterJoinIn )
  49. , m_pcjClusterJoin( pcjClusterJoinIn )
  50. , m_fHasNodeBeenAddedToSponsorDB( false )
  51. {
  52. TraceFunc( "" );
  53. SetRollbackPossible( true );
  54. TraceFuncExit();
  55. } //*** CClusDBJoin::CClusDBJoin
  56. //////////////////////////////////////////////////////////////////////////////
  57. //++
  58. //
  59. // CClusDBJoin::~CClusDBJoin
  60. //
  61. // Description:
  62. // Destructor of the CClusDBJoin class.
  63. //
  64. // Arguments:
  65. // None.
  66. //
  67. // Return Value:
  68. // None.
  69. //
  70. // Exceptions Thrown:
  71. // Any exceptions thrown by underlying functions
  72. //
  73. //--
  74. //////////////////////////////////////////////////////////////////////////////
  75. CClusDBJoin::~CClusDBJoin( void )
  76. {
  77. TraceFunc( "" );
  78. TraceFuncExit();
  79. } //*** CClusDBJoin::~CClusDBJoin
  80. //////////////////////////////////////////////////////////////////////////////
  81. //++
  82. //
  83. // CClusDBJoin::Commit
  84. //
  85. // Description:
  86. // Create the cluster database. If anything goes wrong with the creation,
  87. // cleanup the tasks already done.
  88. //
  89. // Arguments:
  90. // None.
  91. //
  92. // Return Value:
  93. // None.
  94. //
  95. // Exceptions Thrown:
  96. // Any that are thrown by the contained actions.
  97. //
  98. //--
  99. //////////////////////////////////////////////////////////////////////////////
  100. void
  101. CClusDBJoin::Commit( void )
  102. {
  103. TraceFunc( "" );
  104. // Call the base class commit method.
  105. BaseClass::Commit();
  106. //
  107. // Perform a ClusDB cleanup just to make sure that we do not use some files left over
  108. // from a previous install, aborted uninstall, etc.
  109. //
  110. LogMsg( "[BC-ClusDB-Commit] Cleaning up old cluster database files that may already exist before starting creation." );
  111. {
  112. CStatusReport srCleanDB(
  113. PbcaGetParent()->PBcaiGetInterfacePointer()
  114. , TASKID_Major_Configure_Cluster_Services
  115. , TASKID_Minor_Cleaning_Up_Cluster_Database
  116. , 0, 1
  117. , IDS_TASK_CLEANINGUP_CLUSDB
  118. );
  119. // Send the next step of this status report.
  120. srCleanDB.SendNextStep( S_OK );
  121. CleanupHive();
  122. // Send the last step of this status report.
  123. srCleanDB.SendNextStep( S_OK );
  124. }
  125. try
  126. {
  127. // Create the cluster database
  128. Create();
  129. } // try:
  130. catch( ... )
  131. {
  132. // If we are here, then something went wrong with the create.
  133. LogMsg( "[BC-ClusDB-Commit] Caught exception during commit." );
  134. //
  135. // Cleanup anything that the failed add operation might have done.
  136. // Catch any exceptions thrown during Cleanup to make sure that there
  137. // is no collided unwind.
  138. //
  139. try
  140. {
  141. // Cleanup the database.
  142. Cleanup();
  143. }
  144. catch( ... )
  145. {
  146. //
  147. // The rollback of the committed action has failed.
  148. // There is nothing that we can do.
  149. // We certainly cannot rethrow this exception, since
  150. // the exception that caused the rollback is more important.
  151. //
  152. TW32( ERROR_CLUSCFG_ROLLBACK_FAILED );
  153. LogMsg( "[BC-ClusDB-Commit] THIS COMPUTER MAY BE IN AN INVALID STATE. Caught an exception during cleanup." );
  154. } // catch: all
  155. // Rethrow the exception thrown by commit.
  156. throw;
  157. } // catch: all
  158. // If we are here, then everything went well.
  159. SetCommitCompleted( true );
  160. TraceFuncExit();
  161. } //*** CClusDBJoin::Commit
  162. //////////////////////////////////////////////////////////////////////////////
  163. //++
  164. //
  165. // CClusDBJoin::Rollback
  166. //
  167. // Description:
  168. // Unload the cluster hive and cleanup any associated files.
  169. //
  170. // Arguments:
  171. // None.
  172. //
  173. // Return Value:
  174. // None.
  175. //
  176. // Exceptions Thrown:
  177. // Any that are thrown by the underlying functions.
  178. //
  179. //--
  180. //////////////////////////////////////////////////////////////////////////////
  181. void
  182. CClusDBJoin::Rollback( void )
  183. {
  184. TraceFunc( "" );
  185. // Call the base class rollback method.
  186. BaseClass::Rollback();
  187. // Undo the actions performed by.
  188. Cleanup();
  189. SetCommitCompleted( false );
  190. TraceFuncExit();
  191. } //*** CClusDBJoin::Rollback
  192. //////////////////////////////////////////////////////////////////////////////
  193. //++
  194. //
  195. // CClusDBJoin::Create
  196. //
  197. // Description:
  198. // Create the cluster database.
  199. //
  200. // Arguments:
  201. // None.
  202. //
  203. // Return Value:
  204. // None.
  205. //
  206. // Exceptions Thrown:
  207. // CRuntimeError
  208. // If any of the APIs fail.
  209. //
  210. // Any that are thrown by the called functions.
  211. //
  212. //--
  213. //////////////////////////////////////////////////////////////////////////////
  214. void
  215. CClusDBJoin::Create( void )
  216. {
  217. TraceFunc( "" );
  218. LogMsg( "[BC-ClusDB-Create] Attempting to create the cluster database required to add the node to a cluster." );
  219. DWORD sc = ERROR_SUCCESS;
  220. SmartFileHandle sfhClusDBFile;
  221. {
  222. //
  223. // Get the full path and name of the cluster database file.
  224. //
  225. CStr strClusterHiveFileName( PbcaGetParent()->RStrGetClusterInstallDirectory() );
  226. strClusterHiveFileName += L"\\" CLUSTER_DATABASE_NAME;
  227. LogMsg( "[BC-ClusDB-Create] The cluster hive backing file is '%s'.", strClusterHiveFileName.PszData() );
  228. //
  229. // Create the cluster database file.
  230. //
  231. sfhClusDBFile.Assign(
  232. CreateFile(
  233. strClusterHiveFileName.PszData()
  234. , GENERIC_READ | GENERIC_WRITE
  235. , 0
  236. , NULL
  237. , CREATE_ALWAYS
  238. , 0
  239. , NULL
  240. )
  241. );
  242. if ( sfhClusDBFile.FIsInvalid() )
  243. {
  244. sc = TW32( GetLastError() );
  245. LogMsg( "[BC-ClusDB-Create] Error %#08x occurred trying to create the cluster database file. Throwing an exception.", sc );
  246. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_JOIN_SYNC_DB );
  247. } // if: CreateFile() failed
  248. // Store the file handle just obtained in a member variable so that it can be used during Synchronize()
  249. // Note, this file is closed when sfhClusDBFile goes out of scope, so m_hClusDBFile should not be used
  250. // outside this function or any function that this function calls.
  251. m_hClusDBFile = sfhClusDBFile.HHandle();
  252. }
  253. //
  254. // In the scope below, the cluster service account is impersonated, so that we can communicate with the
  255. // sponsor cluster
  256. //
  257. {
  258. LogMsg( "[BC-ClusDB-Create] Attempting to impersonate the cluster service account." );
  259. // Impersonate the cluster service account, so that we can contact the sponsor cluster.
  260. // The impersonation is automatically ended when this object is destroyed.
  261. CImpersonateUser ciuImpersonateClusterServiceAccount( m_pcjClusterJoin->HGetClusterServiceAccountToken() );
  262. // Add this node to the sponsor cluster database
  263. do
  264. {
  265. DWORD dwSuiteType = ClRtlGetSuiteType();
  266. BOOL bJoinerRunningWin64;
  267. SYSTEM_INFO SystemInfo;
  268. m_fHasNodeBeenAddedToSponsorDB = false;
  269. LogMsg(
  270. "[BC-ClusDB-Create] Trying to add node '%s' (suite type %d) to the sponsor cluster database."
  271. , m_pcjClusterJoin->PszGetNodeName()
  272. , dwSuiteType
  273. );
  274. bJoinerRunningWin64 = ClRtlIsProcessRunningOnWin64(GetCurrentProcess());
  275. GetSystemInfo(&SystemInfo);
  276. sc = TW32( JoinAddNode4(
  277. m_pcjClusterJoin->RbhGetJoinBindingHandle()
  278. , m_pcjClusterJoin->PszGetNodeName()
  279. , m_pcjClusterJoin->DwGetNodeHighestVersion()
  280. , m_pcjClusterJoin->DwGetNodeLowestVersion()
  281. , dwSuiteType
  282. , bJoinerRunningWin64
  283. , SystemInfo.wProcessorArchitecture
  284. ) );
  285. if (sc == RPC_S_PROCNUM_OUT_OF_RANGE)
  286. {
  287. LogMsg( "[BC-ClusDB-Create] Error %#08x returned from JoinAddNode4. Sponser must be Windows 2000.", sc );
  288. //this happens when the sponsorer is win2K
  289. sc = TW32( JoinAddNode3(
  290. m_pcjClusterJoin->RbhGetJoinBindingHandle()
  291. , m_pcjClusterJoin->PszGetNodeName()
  292. , m_pcjClusterJoin->DwGetNodeHighestVersion()
  293. , m_pcjClusterJoin->DwGetNodeLowestVersion()
  294. , dwSuiteType
  295. ) );
  296. }
  297. if ( sc != ERROR_SUCCESS )
  298. {
  299. LogMsg( "[BC-ClusDB-Create] Error %#08x returned from JoinAddNodeN.", sc );
  300. break;
  301. } // if: JoinAddNodeN() failed
  302. // Set the flag that indicates that the sponsor database has been modified, so that
  303. // we can undo this if we need to rollback or cleanup.
  304. m_fHasNodeBeenAddedToSponsorDB = true;
  305. }
  306. while( false ); // dummy do while loop to avoid gotos.
  307. if ( sc != ERROR_SUCCESS )
  308. {
  309. LogMsg( "[BC-ClusDB-Create] Error %#08x occurred trying to add this node to the sponsor cluster database. Throwing an exception.", sc );
  310. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_JOINING_SPONSOR_DB );
  311. } // if: something has gone wrong
  312. LogMsg( "[BC-ClusDB-Create] This node has been successfully added to the sponsor cluster database." );
  313. // Get the node id of the newly formed node.
  314. do
  315. {
  316. // Smart handle to sponsor cluster
  317. SmartClusterHandle schSponsorCluster;
  318. // Smart handle to this node
  319. SmartNodeHandle snhThisNodeHandle;
  320. //
  321. // Get a handle to the sponsor cluster.
  322. //
  323. {
  324. LogMsg( "[BC-ClusDB-Create] Opening a cluster handle to the sponsor cluster with the '%ws' binding string.", m_pcjClusterJoin->RStrGetClusterBindingString().PszData() );
  325. // Open a handle to the sponsor cluster.
  326. HCLUSTER hSponsorCluster = OpenCluster( m_pcjClusterJoin->RStrGetClusterBindingString().PszData() );
  327. // Assign it to a smart handle for safe release.
  328. schSponsorCluster.Assign( hSponsorCluster );
  329. }
  330. // Did we succeed in opening a handle to the sponsor cluster?
  331. if ( schSponsorCluster.FIsInvalid() )
  332. {
  333. sc = TW32( GetLastError() );
  334. LogMsg(
  335. "[BC-ClusDB-Create] Error %#08x occurred trying to open a cluster handle to the sponsor cluster with the '%ws' binding string."
  336. , sc
  337. , m_pcjClusterJoin->RStrGetClusterBindingString().PszData()
  338. );
  339. break;
  340. } // if: OpenCluster() failed
  341. //
  342. // Get a handle to this node.
  343. //
  344. {
  345. LogMsg( "[BC-ClusDB-Create] Opening a cluster handle to the local node with the '%ws' binding string.", m_pcjClusterJoin->PszGetNodeName() );
  346. // Open a handle to this node.
  347. HNODE hThisNode = OpenClusterNode( schSponsorCluster.HHandle(), m_pcjClusterJoin->PszGetNodeName() );
  348. // Assign it to a smart handle for safe release.
  349. snhThisNodeHandle.Assign( hThisNode );
  350. }
  351. // Did we succeed in opening a handle to this node?
  352. if ( snhThisNodeHandle.FIsInvalid() )
  353. {
  354. sc = TW32( GetLastError() );
  355. LogMsg( "[BC-ClusDB-Create] Error %#08x occurred trying to open a cluster handle to the local node with the '%ws' binding string.", sc, m_pcjClusterJoin->PszGetNodeName() );
  356. break;
  357. } // if: OpenClusterNode() failed
  358. // Get the node id string.
  359. {
  360. DWORD cchIdSize = 0;
  361. SmartSz sszNodeId;
  362. sc = GetClusterNodeId(
  363. snhThisNodeHandle.HHandle()
  364. , NULL
  365. , &cchIdSize
  366. );
  367. if ( ( sc != ERROR_SUCCESS ) && ( sc != ERROR_MORE_DATA ) )
  368. {
  369. TW32( sc );
  370. LogMsg( "[BC-ClusDB-Create] Error %#08x returned from GetClusterNodeId() trying to get the required length of the node id buffer.", sc );
  371. break;
  372. } // if: GetClusterNodeId() failed
  373. // cchIdSize returned by the above call is the count of characters and does not include the space for
  374. // the terminating NULL.
  375. ++cchIdSize;
  376. sszNodeId.Assign( new WCHAR[ cchIdSize ] );
  377. if ( sszNodeId.FIsEmpty() )
  378. {
  379. sc = TW32( ERROR_OUTOFMEMORY );
  380. LogMsg( "[BC-ClusDB-Create] A memory allocation failure occurred trying to allocate %d characters.", cchIdSize );
  381. break;
  382. } // if: memory allocation failed
  383. sc = TW32( GetClusterNodeId(
  384. snhThisNodeHandle.HHandle()
  385. , sszNodeId.PMem()
  386. , &cchIdSize
  387. ) );
  388. if ( sc != ERROR_SUCCESS )
  389. {
  390. LogMsg( "Error %#08x returned from GetClusterNodeId() trying to get the node id of this node.", sc );
  391. break;
  392. } // if: GetClusterNodeId() failed
  393. LogMsg( "[BC-ClusDB-Create] The node id of this node is '%s'.", sszNodeId.PMem() );
  394. // Set the node id for later use.
  395. m_pcjClusterJoin->SetNodeIdString( sszNodeId.PMem() );
  396. }
  397. }
  398. while( false ); // dummy do while loop to avoid gotos.
  399. if ( sc != ERROR_SUCCESS )
  400. {
  401. LogMsg( "[BC-ClusDB-Create] Error %#08x occurred trying to get the node id of this node. Throwing an exception.", sc );
  402. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_GET_NEW_NODE_ID );
  403. } // if: something has gone wrong
  404. {
  405. CStatusReport srSyncDB(
  406. PbcaGetParent()->PBcaiGetInterfacePointer()
  407. , TASKID_Major_Configure_Cluster_Services
  408. , TASKID_Minor_Join_Sync_Cluster_Database
  409. , 0, 1
  410. , IDS_TASK_JOIN_SYNC_CLUSDB
  411. );
  412. // Send the next step of this status report.
  413. srSyncDB.SendNextStep( S_OK );
  414. // Synchronize the cluster database.
  415. Synchronize();
  416. // Send the last step of this status report.
  417. srSyncDB.SendNextStep( S_OK );
  418. }
  419. }
  420. LogMsg( "[BC-ClusDB-Create] The cluster database has been successfully created and synchronized with the sponsor cluster." );
  421. TraceFuncExit();
  422. } //*** CClusDBJoin::Create
  423. //////////////////////////////////////////////////////////////////////////////
  424. //++
  425. //
  426. // CClusDBJoin::Cleanup
  427. //
  428. // Description:
  429. // Cleanup the effects of Create()
  430. //
  431. // Arguments:
  432. // None.
  433. //
  434. // Return Value:
  435. // None.
  436. //
  437. // Exceptions Thrown:
  438. // CRuntimeError
  439. // If any of the APIs fail.
  440. //
  441. // Any that are thrown by the called functions.
  442. //
  443. //--
  444. //////////////////////////////////////////////////////////////////////////////
  445. void
  446. CClusDBJoin::Cleanup( void )
  447. {
  448. TraceFunc( "" );
  449. LogMsg( "[BC-ClusDB-Cleanup] Attempting to cleanup the cluster database." );
  450. DWORD sc = ERROR_SUCCESS;
  451. DWORD cRetryCount = 0;
  452. //
  453. // Check if we added this node to the sponsor cluster database. If so, remove it from there.
  454. //
  455. if ( m_fHasNodeBeenAddedToSponsorDB )
  456. {
  457. LogMsg( "[BC-ClusDB-Cleanup] Attempting to impersonate the cluster service account." );
  458. // Impersonate the cluster service account, so that we can contact the sponsor cluster.
  459. // The impersonation is automatically ended when this object is destroyed.
  460. CImpersonateUser ciuImpersonateClusterServiceAccount( m_pcjClusterJoin->HGetClusterServiceAccountToken() );
  461. //
  462. // Remove this node from the sponsor cluster database
  463. //
  464. do
  465. {
  466. // Smart handle to sponsor cluster
  467. SmartClusterHandle schSponsorCluster;
  468. // Smart handle to this node
  469. SmartNodeHandle snhThisNodeHandle;
  470. //
  471. // Get a handle to the sponsor cluster.
  472. //
  473. {
  474. LogMsg( "[BC-ClusDB-Cleanup] Opening a clusterhandle to the sponsor cluster with the '%ws' binding string.", m_pcjClusterJoin->RStrGetClusterBindingString().PszData() );
  475. // Open a handle to the sponsor cluster.
  476. HCLUSTER hSponsorCluster = OpenCluster( m_pcjClusterJoin->RStrGetClusterBindingString().PszData() );
  477. // Assign it to a smart handle for safe release.
  478. schSponsorCluster.Assign( hSponsorCluster );
  479. }
  480. // Did we succeed in opening a handle to the sponsor cluster?
  481. if ( schSponsorCluster.FIsInvalid() )
  482. {
  483. sc = TW32( GetLastError() );
  484. LogMsg( "[BC-ClusDB-Cleanup] Error %#08x occurred trying to open a cluster handle to the sponsor cluster with the '%ws' binding string.", sc, m_pcjClusterJoin->RStrGetClusterBindingString().PszData() );
  485. break;
  486. } // if: OpenCluster() failed
  487. //
  488. // Get a handle to this node.
  489. //
  490. {
  491. LogMsg( "[BC-ClusDB-Cleanup] Open a clusterhandle to the local node with the '%ws' binding string.", m_pcjClusterJoin->PszGetNodeName() );
  492. // Open a handle to this node.
  493. HNODE hThisNode = OpenClusterNode( schSponsorCluster.HHandle(), m_pcjClusterJoin->PszGetNodeName() );
  494. if ( hThisNode == NULL )
  495. {
  496. sc = TW32( GetLastError() );
  497. LogMsg( "[BC-ClusDB-Cleanup] Error %#08x occurred trying to open a cluster handle to the local node with the '%ws' binding string.", sc, m_pcjClusterJoin->PszGetNodeName() );
  498. break;
  499. } // if: OpenClusterNode() failed.
  500. // Assign it to a smart handle for safe release.
  501. snhThisNodeHandle.Assign( hThisNode );
  502. }
  503. //
  504. // If the cluster is still dealing with the join process we'll get ERROR_CLUSTER_JOIN_IN_PROGRESS.
  505. // After the join finishes/fails/stabilizes we'll be able to make the evict call without the
  506. // join process getting in the way.
  507. //
  508. cRetryCount = 1;
  509. sc = EvictClusterNode( snhThisNodeHandle.HHandle() );
  510. while( sc == ERROR_CLUSTER_JOIN_IN_PROGRESS && cRetryCount < 25 ) // Allow a two minute wait. (24 * 5 seconds)
  511. {
  512. LogMsg( "[BC-ClusDB-Cleanup] EvictClusterNode returned ERROR_CLUSTER_JOIN_IN_PROGRESS. Retry attempt %d.", cRetryCount++ );
  513. // Sleep for a few seconds.
  514. Sleep( 5000 );
  515. // Try again.
  516. sc = EvictClusterNode( snhThisNodeHandle.HHandle() );
  517. }
  518. if ( sc != ERROR_SUCCESS )
  519. {
  520. TW32( sc );
  521. LogMsg( "[BC-ClusDB-Cleanup] Error %#08x occurred trying to evict this node from the sponsor cluster.", sc );
  522. break;
  523. } // if: EvictClusterNode() failed
  524. }
  525. while( false ); // dummy do while loop to avoid gotos.
  526. if ( sc != ERROR_SUCCESS )
  527. {
  528. LogMsg( "[BC-ClusDB-Cleanup] Error %#08x occurred trying to remove this node from the sponsor cluster database. Throwing exception.", sc );
  529. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_EVICTING_NODE );
  530. } // if: something has gone wrong
  531. LogMsg( "[BC-ClusDB-Cleanup] This node has been successfully removed from the sponsor cluster database." );
  532. } // if: we had added this node to the sponsor cluster database
  533. // Cleanup the cluster hive
  534. CleanupHive();
  535. TraceFuncExit();
  536. } //*** CClusDBJoin::Cleanup
  537. //////////////////////////////////////////////////////////////////////////////
  538. //++
  539. //
  540. // CClusDBJoin::Synchronize
  541. //
  542. // Description:
  543. // Synchronize the cluster database with the sponsor cluster.
  544. //
  545. // Arguments:
  546. // None.
  547. //
  548. // Return Value:
  549. // None.
  550. //
  551. // Exceptions Thrown:
  552. // CRuntimeError
  553. // If any of the APIs fail.
  554. //
  555. // Any that are thrown by the called functions.
  556. //
  557. //--
  558. //////////////////////////////////////////////////////////////////////////////
  559. void
  560. CClusDBJoin::Synchronize( void )
  561. {
  562. TraceFunc( "" );
  563. LogMsg( "[BC-ClusDB-Synchronize] Attempting to synchronize the cluster database with the sponsor cluster." );
  564. DWORD sc = ERROR_SUCCESS;
  565. //
  566. // Initialize the byte pipe.
  567. //
  568. m_bpBytePipe.state = reinterpret_cast< char * >( this );
  569. m_bpBytePipe.alloc = S_BytePipeAlloc;
  570. m_bpBytePipe.push = S_BytePipePush;
  571. m_bpBytePipe.pull = S_BytePipePull;
  572. //
  573. // Synchronize the database
  574. //
  575. sc = TW32( DmSyncDatabase( m_pcjClusterJoin->RbhGetJoinBindingHandle(), m_bpBytePipe ) );
  576. if ( sc != ERROR_SUCCESS )
  577. {
  578. LogMsg( "[BC-ClusDB-Synchronize] Error %#08x occurred trying to suck the database down from the sponsor cluster.", sc );
  579. goto Cleanup;
  580. } // if: DmSyncDatabase() failed
  581. Cleanup:
  582. if ( sc != ERROR_SUCCESS )
  583. {
  584. LogMsg( "[BC-ClusDB-Synchronize] Error %#08x occurred trying to synchronize the cluster database with the sponsor cluster. Throwing an exception.", sc );
  585. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_JOIN_SYNC_DB );
  586. } // if: something has gone wrong
  587. LogMsg( "[BC-ClusDB-Synchronize] The cluster database has been synchronized with the sponsor cluster." );
  588. TraceFuncExit();
  589. } //*** CClusDBJoin::Synchronize
  590. //////////////////////////////////////////////////////////////////////////////
  591. //++
  592. //
  593. // static
  594. // CClusDBJoin::S_BytePipePush
  595. //
  596. // Description:
  597. // Callback function used by RPC to push data.
  598. //
  599. // Arguments:
  600. // pchStateIn
  601. // State of the byte pipe
  602. //
  603. // pchBufferIn
  604. // ulBufferSizeIn
  605. // Buffer contained the pushed data and its size.
  606. //
  607. // Return Value:
  608. // None.
  609. //
  610. // Exceptions Thrown:
  611. // RPC Exceptions.
  612. //
  613. //--
  614. //////////////////////////////////////////////////////////////////////////////
  615. void
  616. CClusDBJoin::S_BytePipePush(
  617. char * pchStateIn
  618. , unsigned char * pchBufferIn
  619. , unsigned long ulBufferSizeIn
  620. )
  621. {
  622. TraceFunc( "" );
  623. CClusDBJoin * pThis = reinterpret_cast< CClusDBJoin * >( pchStateIn );
  624. if ( ulBufferSizeIn != 0 )
  625. {
  626. DWORD dwBytesWritten;
  627. if ( WriteFile(
  628. pThis->m_hClusDBFile
  629. , pchBufferIn
  630. , ulBufferSizeIn
  631. , &dwBytesWritten
  632. , NULL
  633. )
  634. == 0
  635. )
  636. {
  637. DWORD sc = TW32( GetLastError() );
  638. RpcRaiseException( sc );
  639. } // if: WriteFile() failed
  640. Assert( dwBytesWritten == ulBufferSizeIn );
  641. } // if: the buffer is non-empty
  642. TraceFuncExit();
  643. } //*** CClusDBJoin::S_BytePipePush
  644. //////////////////////////////////////////////////////////////////////////////
  645. //++
  646. //
  647. // static
  648. // CClusDBJoin::S_BytePipePull
  649. //
  650. // Description:
  651. // Callback function used by RPC to pull data.
  652. //
  653. // Arguments:
  654. // pchStateIn
  655. // State of the byte pipe
  656. //
  657. // pchBufferIn
  658. // ulBufferSizeIn
  659. // Buffer contained the pushed data and its size.
  660. //
  661. // pulWrittenOut
  662. // Pointer to the number of bytes actually filled into the buffer.
  663. //
  664. // Return Value:
  665. // None.
  666. //
  667. // Exceptions Thrown:
  668. // RPC Exceptions.
  669. //
  670. //--
  671. //////////////////////////////////////////////////////////////////////////////
  672. void
  673. CClusDBJoin::S_BytePipePull(
  674. char * pchStateIn
  675. , unsigned char * pchBufferIn
  676. , unsigned long ulBufferSizeIn
  677. , unsigned long * pulWrittenOut
  678. )
  679. {
  680. TraceFunc( "" );
  681. CClusDBJoin * pThis = reinterpret_cast< CClusDBJoin * >( pchStateIn );
  682. if ( ulBufferSizeIn != 0 )
  683. {
  684. if ( ReadFile(
  685. pThis->m_hClusDBFile
  686. , pchBufferIn
  687. , ulBufferSizeIn
  688. , pulWrittenOut
  689. , NULL
  690. )
  691. == 0
  692. )
  693. {
  694. DWORD sc = TW32( GetLastError() );
  695. RpcRaiseException( sc );
  696. } // if: ReadFile() failed
  697. Assert( *pulWrittenOut <= ulBufferSizeIn );
  698. } // if: the buffer is non-empty
  699. TraceFuncExit();
  700. } //*** CClusDBJoin::S_BytePipePull
  701. //////////////////////////////////////////////////////////////////////////////
  702. //++
  703. //
  704. // static
  705. // CClusDBJoin::S_BytePipeAlloc
  706. //
  707. // Description:
  708. // Callback function used by RPC to allocate a buffer.
  709. //
  710. // Arguments:
  711. // pchStateIn
  712. // State of the file pipe
  713. //
  714. // ulRequestedSizeIn
  715. // Requested size of the buffer
  716. //
  717. // ppchBufferOut
  718. // Pointer to the buffer pointer
  719. //
  720. // pulActualSizeOut
  721. // Pointer to the actual size of the allocated buffer
  722. //
  723. // Return Value:
  724. // None.
  725. //
  726. // Exceptions Thrown:
  727. // None.
  728. //
  729. //--
  730. //////////////////////////////////////////////////////////////////////////////
  731. void
  732. CClusDBJoin::S_BytePipeAlloc(
  733. char * pchStateIn
  734. , unsigned long ulRequestedSizeIn
  735. , unsigned char ** ppchBufferOut
  736. , unsigned long * pulActualSizeOut
  737. )
  738. {
  739. TraceFunc( "" );
  740. CClusDBJoin * pThis = reinterpret_cast< CClusDBJoin * >( pchStateIn );
  741. *ppchBufferOut = reinterpret_cast< unsigned char * >( pThis->m_rgbBytePipeBuffer );
  742. *pulActualSizeOut = ( ulRequestedSizeIn < pThis->ms_nFILE_PIPE_BUFFER_SIZE ) ? ulRequestedSizeIn : pThis->ms_nFILE_PIPE_BUFFER_SIZE;
  743. TraceFuncExit();
  744. } //*** CClusDBJoin::S_BytePipeAlloc