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
903 lines
28 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1999-2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// CClusDBJoin.cpp
|
|
//
|
|
// Description:
|
|
// Contains the definition of the CClusDBJoin class.
|
|
//
|
|
// Maintained By:
|
|
// David Potter (DavidP) 14-JUN-2001
|
|
// Vij Vasu (Vvasu) 08-MAR-2000
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Include Files
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The precompiled header.
|
|
#include "Pch.h"
|
|
|
|
// The header for this file
|
|
#include "CClusDBJoin.h"
|
|
|
|
// For the CBaseClusterJoin class.
|
|
#include "CBaseClusterJoin.h"
|
|
|
|
// For the CImpersonateUser class.
|
|
#include "CImpersonateUser.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDBJoin::CClusDBJoin
|
|
//
|
|
// Description:
|
|
// Constructor of the CClusDBJoin class
|
|
//
|
|
// Arguments:
|
|
// m_pcjClusterJoinIn
|
|
// Pointer to the base cluster action of which this action is a part.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by underlying functions
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CClusDBJoin::CClusDBJoin( CBaseClusterJoin * pcjClusterJoinIn )
|
|
: BaseClass( pcjClusterJoinIn )
|
|
, m_pcjClusterJoin( pcjClusterJoinIn )
|
|
, m_fHasNodeBeenAddedToSponsorDB( false )
|
|
{
|
|
|
|
TraceFunc( "" );
|
|
|
|
SetRollbackPossible( true );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDBJoin::CClusDBJoin
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDBJoin::~CClusDBJoin
|
|
//
|
|
// Description:
|
|
// Destructor of the CClusDBJoin class.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by underlying functions
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CClusDBJoin::~CClusDBJoin( void )
|
|
{
|
|
TraceFunc( "" );
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDBJoin::~CClusDBJoin
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDBJoin::Commit
|
|
//
|
|
// Description:
|
|
// Create the cluster database. If anything goes wrong with the creation,
|
|
// cleanup the tasks already done.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any that are thrown by the contained actions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDBJoin::Commit( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
// Call the base class commit method.
|
|
BaseClass::Commit();
|
|
|
|
//
|
|
// Perform a ClusDB cleanup just to make sure that we do not use some files left over
|
|
// from a previous install, aborted uninstall, etc.
|
|
//
|
|
|
|
LogMsg( "[BC-ClusDB-Commit] Cleaning up old cluster database files that may already exist before starting creation." );
|
|
|
|
{
|
|
CStatusReport srCleanDB(
|
|
PbcaGetParent()->PBcaiGetInterfacePointer()
|
|
, TASKID_Major_Configure_Cluster_Services
|
|
, TASKID_Minor_Cleaning_Up_Cluster_Database
|
|
, 0, 1
|
|
, IDS_TASK_CLEANINGUP_CLUSDB
|
|
);
|
|
|
|
// Send the next step of this status report.
|
|
srCleanDB.SendNextStep( S_OK );
|
|
|
|
CleanupHive();
|
|
|
|
// Send the last step of this status report.
|
|
srCleanDB.SendNextStep( S_OK );
|
|
}
|
|
|
|
try
|
|
{
|
|
// Create the cluster database
|
|
Create();
|
|
|
|
} // try:
|
|
catch( ... )
|
|
{
|
|
// If we are here, then something went wrong with the create.
|
|
|
|
LogMsg( "[BC-ClusDB-Commit] Caught exception during commit." );
|
|
|
|
//
|
|
// Cleanup anything that the failed add operation might have done.
|
|
// Catch any exceptions thrown during Cleanup to make sure that there
|
|
// is no collided unwind.
|
|
//
|
|
try
|
|
{
|
|
// Cleanup the database.
|
|
Cleanup();
|
|
}
|
|
catch( ... )
|
|
{
|
|
//
|
|
// The rollback of the committed action has failed.
|
|
// There is nothing that we can do.
|
|
// We certainly cannot rethrow this exception, since
|
|
// the exception that caused the rollback is more important.
|
|
//
|
|
|
|
TW32( ERROR_CLUSCFG_ROLLBACK_FAILED );
|
|
|
|
LogMsg( "[BC-ClusDB-Commit] THIS COMPUTER MAY BE IN AN INVALID STATE. Caught an exception during cleanup." );
|
|
|
|
} // catch: all
|
|
|
|
// Rethrow the exception thrown by commit.
|
|
throw;
|
|
|
|
} // catch: all
|
|
|
|
// If we are here, then everything went well.
|
|
SetCommitCompleted( true );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDBJoin::Commit
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDBJoin::Rollback
|
|
//
|
|
// Description:
|
|
// Unload the cluster hive and cleanup any associated files.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDBJoin::Rollback( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
// Call the base class rollback method.
|
|
BaseClass::Rollback();
|
|
|
|
// Undo the actions performed by.
|
|
Cleanup();
|
|
|
|
SetCommitCompleted( false );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDBJoin::Rollback
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDBJoin::Create
|
|
//
|
|
// Description:
|
|
// Create the cluster database.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the called functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDBJoin::Create( void )
|
|
{
|
|
TraceFunc( "" );
|
|
LogMsg( "[BC-ClusDB-Create] Attempting to create the cluster database required to add the node to a cluster." );
|
|
|
|
DWORD sc = ERROR_SUCCESS;
|
|
SmartFileHandle sfhClusDBFile;
|
|
|
|
|
|
{
|
|
//
|
|
// Get the full path and name of the cluster database file.
|
|
//
|
|
CStr strClusterHiveFileName( PbcaGetParent()->RStrGetClusterInstallDirectory() );
|
|
strClusterHiveFileName += L"\\" CLUSTER_DATABASE_NAME;
|
|
|
|
LogMsg( "[BC-ClusDB-Create] The cluster hive backing file is '%s'.", strClusterHiveFileName.PszData() );
|
|
|
|
|
|
//
|
|
// Create the cluster database file.
|
|
//
|
|
sfhClusDBFile.Assign(
|
|
CreateFile(
|
|
strClusterHiveFileName.PszData()
|
|
, GENERIC_READ | GENERIC_WRITE
|
|
, 0
|
|
, NULL
|
|
, CREATE_ALWAYS
|
|
, 0
|
|
, NULL
|
|
)
|
|
);
|
|
|
|
if ( sfhClusDBFile.FIsInvalid() )
|
|
{
|
|
sc = TW32( GetLastError() );
|
|
LogMsg( "[BC-ClusDB-Create] Error %#08x occurred trying to create the cluster database file. Throwing an exception.", sc );
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_JOIN_SYNC_DB );
|
|
} // if: CreateFile() failed
|
|
|
|
// Store the file handle just obtained in a member variable so that it can be used during Synchronize()
|
|
// Note, this file is closed when sfhClusDBFile goes out of scope, so m_hClusDBFile should not be used
|
|
// outside this function or any function that this function calls.
|
|
m_hClusDBFile = sfhClusDBFile.HHandle();
|
|
}
|
|
|
|
|
|
//
|
|
// In the scope below, the cluster service account is impersonated, so that we can communicate with the
|
|
// sponsor cluster
|
|
//
|
|
{
|
|
LogMsg( "[BC-ClusDB-Create] Attempting to impersonate the cluster service account." );
|
|
|
|
// Impersonate the cluster service account, so that we can contact the sponsor cluster.
|
|
// The impersonation is automatically ended when this object is destroyed.
|
|
CImpersonateUser ciuImpersonateClusterServiceAccount( m_pcjClusterJoin->HGetClusterServiceAccountToken() );
|
|
|
|
|
|
// Add this node to the sponsor cluster database
|
|
do
|
|
{
|
|
DWORD dwSuiteType = ClRtlGetSuiteType();
|
|
BOOL bJoinerRunningWin64;
|
|
SYSTEM_INFO SystemInfo;
|
|
|
|
m_fHasNodeBeenAddedToSponsorDB = false;
|
|
|
|
LogMsg(
|
|
"[BC-ClusDB-Create] Trying to add node '%s' (suite type %d) to the sponsor cluster database."
|
|
, m_pcjClusterJoin->PszGetNodeName()
|
|
, dwSuiteType
|
|
);
|
|
|
|
bJoinerRunningWin64 = ClRtlIsProcessRunningOnWin64(GetCurrentProcess());
|
|
GetSystemInfo(&SystemInfo);
|
|
|
|
sc = TW32( JoinAddNode4(
|
|
m_pcjClusterJoin->RbhGetJoinBindingHandle()
|
|
, m_pcjClusterJoin->PszGetNodeName()
|
|
, m_pcjClusterJoin->DwGetNodeHighestVersion()
|
|
, m_pcjClusterJoin->DwGetNodeLowestVersion()
|
|
, dwSuiteType
|
|
, bJoinerRunningWin64
|
|
, SystemInfo.wProcessorArchitecture
|
|
) );
|
|
|
|
if (sc == RPC_S_PROCNUM_OUT_OF_RANGE)
|
|
{
|
|
LogMsg( "[BC-ClusDB-Create] Error %#08x returned from JoinAddNode4. Sponser must be Windows 2000.", sc );
|
|
//this happens when the sponsorer is win2K
|
|
sc = TW32( JoinAddNode3(
|
|
m_pcjClusterJoin->RbhGetJoinBindingHandle()
|
|
, m_pcjClusterJoin->PszGetNodeName()
|
|
, m_pcjClusterJoin->DwGetNodeHighestVersion()
|
|
, m_pcjClusterJoin->DwGetNodeLowestVersion()
|
|
, dwSuiteType
|
|
) );
|
|
}
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC-ClusDB-Create] Error %#08x returned from JoinAddNodeN.", sc );
|
|
break;
|
|
} // if: JoinAddNodeN() failed
|
|
|
|
// Set the flag that indicates that the sponsor database has been modified, so that
|
|
// we can undo this if we need to rollback or cleanup.
|
|
m_fHasNodeBeenAddedToSponsorDB = true;
|
|
}
|
|
while( false ); // dummy do while loop to avoid gotos.
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC-ClusDB-Create] Error %#08x occurred trying to add this node to the sponsor cluster database. Throwing an exception.", sc );
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_JOINING_SPONSOR_DB );
|
|
} // if: something has gone wrong
|
|
|
|
LogMsg( "[BC-ClusDB-Create] This node has been successfully added to the sponsor cluster database." );
|
|
|
|
// Get the node id of the newly formed node.
|
|
do
|
|
{
|
|
// Smart handle to sponsor cluster
|
|
SmartClusterHandle schSponsorCluster;
|
|
|
|
// Smart handle to this node
|
|
SmartNodeHandle snhThisNodeHandle;
|
|
|
|
//
|
|
// Get a handle to the sponsor cluster.
|
|
//
|
|
{
|
|
LogMsg( "[BC-ClusDB-Create] Opening a cluster handle to the sponsor cluster with the '%ws' binding string.", m_pcjClusterJoin->RStrGetClusterBindingString().PszData() );
|
|
|
|
// Open a handle to the sponsor cluster.
|
|
HCLUSTER hSponsorCluster = OpenCluster( m_pcjClusterJoin->RStrGetClusterBindingString().PszData() );
|
|
|
|
// Assign it to a smart handle for safe release.
|
|
schSponsorCluster.Assign( hSponsorCluster );
|
|
}
|
|
|
|
// Did we succeed in opening a handle to the sponsor cluster?
|
|
if ( schSponsorCluster.FIsInvalid() )
|
|
{
|
|
sc = TW32( GetLastError() );
|
|
LogMsg(
|
|
"[BC-ClusDB-Create] Error %#08x occurred trying to open a cluster handle to the sponsor cluster with the '%ws' binding string."
|
|
, sc
|
|
, m_pcjClusterJoin->RStrGetClusterBindingString().PszData()
|
|
);
|
|
break;
|
|
} // if: OpenCluster() failed
|
|
|
|
|
|
//
|
|
// Get a handle to this node.
|
|
//
|
|
{
|
|
LogMsg( "[BC-ClusDB-Create] Opening a cluster handle to the local node with the '%ws' binding string.", m_pcjClusterJoin->PszGetNodeName() );
|
|
|
|
// Open a handle to this node.
|
|
HNODE hThisNode = OpenClusterNode( schSponsorCluster.HHandle(), m_pcjClusterJoin->PszGetNodeName() );
|
|
|
|
// Assign it to a smart handle for safe release.
|
|
snhThisNodeHandle.Assign( hThisNode );
|
|
}
|
|
|
|
// Did we succeed in opening a handle to this node?
|
|
if ( snhThisNodeHandle.FIsInvalid() )
|
|
{
|
|
sc = TW32( GetLastError() );
|
|
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() );
|
|
break;
|
|
} // if: OpenClusterNode() failed
|
|
|
|
// Get the node id string.
|
|
{
|
|
DWORD cchIdSize = 0;
|
|
SmartSz sszNodeId;
|
|
|
|
sc = GetClusterNodeId(
|
|
snhThisNodeHandle.HHandle()
|
|
, NULL
|
|
, &cchIdSize
|
|
);
|
|
|
|
if ( ( sc != ERROR_SUCCESS ) && ( sc != ERROR_MORE_DATA ) )
|
|
{
|
|
TW32( sc );
|
|
LogMsg( "[BC-ClusDB-Create] Error %#08x returned from GetClusterNodeId() trying to get the required length of the node id buffer.", sc );
|
|
break;
|
|
} // if: GetClusterNodeId() failed
|
|
|
|
// cchIdSize returned by the above call is the count of characters and does not include the space for
|
|
// the terminating NULL.
|
|
++cchIdSize;
|
|
|
|
sszNodeId.Assign( new WCHAR[ cchIdSize ] );
|
|
if ( sszNodeId.FIsEmpty() )
|
|
{
|
|
sc = TW32( ERROR_OUTOFMEMORY );
|
|
LogMsg( "[BC-ClusDB-Create] A memory allocation failure occurred trying to allocate %d characters.", cchIdSize );
|
|
break;
|
|
} // if: memory allocation failed
|
|
|
|
sc = TW32( GetClusterNodeId(
|
|
snhThisNodeHandle.HHandle()
|
|
, sszNodeId.PMem()
|
|
, &cchIdSize
|
|
) );
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "Error %#08x returned from GetClusterNodeId() trying to get the node id of this node.", sc );
|
|
break;
|
|
} // if: GetClusterNodeId() failed
|
|
|
|
LogMsg( "[BC-ClusDB-Create] The node id of this node is '%s'.", sszNodeId.PMem() );
|
|
|
|
// Set the node id for later use.
|
|
m_pcjClusterJoin->SetNodeIdString( sszNodeId.PMem() );
|
|
}
|
|
|
|
}
|
|
while( false ); // dummy do while loop to avoid gotos.
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC-ClusDB-Create] Error %#08x occurred trying to get the node id of this node. Throwing an exception.", sc );
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_GET_NEW_NODE_ID );
|
|
} // if: something has gone wrong
|
|
|
|
|
|
{
|
|
CStatusReport srSyncDB(
|
|
PbcaGetParent()->PBcaiGetInterfacePointer()
|
|
, TASKID_Major_Configure_Cluster_Services
|
|
, TASKID_Minor_Join_Sync_Cluster_Database
|
|
, 0, 1
|
|
, IDS_TASK_JOIN_SYNC_CLUSDB
|
|
);
|
|
|
|
// Send the next step of this status report.
|
|
srSyncDB.SendNextStep( S_OK );
|
|
|
|
// Synchronize the cluster database.
|
|
Synchronize();
|
|
|
|
// Send the last step of this status report.
|
|
srSyncDB.SendNextStep( S_OK );
|
|
}
|
|
}
|
|
|
|
LogMsg( "[BC-ClusDB-Create] The cluster database has been successfully created and synchronized with the sponsor cluster." );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDBJoin::Create
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDBJoin::Cleanup
|
|
//
|
|
// Description:
|
|
// Cleanup the effects of Create()
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the called functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDBJoin::Cleanup( void )
|
|
{
|
|
TraceFunc( "" );
|
|
LogMsg( "[BC-ClusDB-Cleanup] Attempting to cleanup the cluster database." );
|
|
|
|
DWORD sc = ERROR_SUCCESS;
|
|
DWORD cRetryCount = 0;
|
|
|
|
//
|
|
// Check if we added this node to the sponsor cluster database. If so, remove it from there.
|
|
//
|
|
if ( m_fHasNodeBeenAddedToSponsorDB )
|
|
{
|
|
LogMsg( "[BC-ClusDB-Cleanup] Attempting to impersonate the cluster service account." );
|
|
|
|
// Impersonate the cluster service account, so that we can contact the sponsor cluster.
|
|
// The impersonation is automatically ended when this object is destroyed.
|
|
CImpersonateUser ciuImpersonateClusterServiceAccount( m_pcjClusterJoin->HGetClusterServiceAccountToken() );
|
|
|
|
|
|
//
|
|
// Remove this node from the sponsor cluster database
|
|
//
|
|
|
|
do
|
|
{
|
|
// Smart handle to sponsor cluster
|
|
SmartClusterHandle schSponsorCluster;
|
|
|
|
// Smart handle to this node
|
|
SmartNodeHandle snhThisNodeHandle;
|
|
|
|
//
|
|
// Get a handle to the sponsor cluster.
|
|
//
|
|
{
|
|
LogMsg( "[BC-ClusDB-Cleanup] Opening a clusterhandle to the sponsor cluster with the '%ws' binding string.", m_pcjClusterJoin->RStrGetClusterBindingString().PszData() );
|
|
|
|
// Open a handle to the sponsor cluster.
|
|
HCLUSTER hSponsorCluster = OpenCluster( m_pcjClusterJoin->RStrGetClusterBindingString().PszData() );
|
|
|
|
// Assign it to a smart handle for safe release.
|
|
schSponsorCluster.Assign( hSponsorCluster );
|
|
}
|
|
|
|
// Did we succeed in opening a handle to the sponsor cluster?
|
|
if ( schSponsorCluster.FIsInvalid() )
|
|
{
|
|
sc = TW32( GetLastError() );
|
|
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() );
|
|
break;
|
|
} // if: OpenCluster() failed
|
|
|
|
|
|
//
|
|
// Get a handle to this node.
|
|
//
|
|
{
|
|
LogMsg( "[BC-ClusDB-Cleanup] Open a clusterhandle to the local node with the '%ws' binding string.", m_pcjClusterJoin->PszGetNodeName() );
|
|
|
|
// Open a handle to this node.
|
|
HNODE hThisNode = OpenClusterNode( schSponsorCluster.HHandle(), m_pcjClusterJoin->PszGetNodeName() );
|
|
|
|
if ( hThisNode == NULL )
|
|
{
|
|
sc = TW32( GetLastError() );
|
|
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() );
|
|
break;
|
|
} // if: OpenClusterNode() failed.
|
|
|
|
// Assign it to a smart handle for safe release.
|
|
snhThisNodeHandle.Assign( hThisNode );
|
|
}
|
|
|
|
//
|
|
// If the cluster is still dealing with the join process we'll get ERROR_CLUSTER_JOIN_IN_PROGRESS.
|
|
// After the join finishes/fails/stabilizes we'll be able to make the evict call without the
|
|
// join process getting in the way.
|
|
//
|
|
cRetryCount = 1;
|
|
sc = EvictClusterNode( snhThisNodeHandle.HHandle() );
|
|
while( sc == ERROR_CLUSTER_JOIN_IN_PROGRESS && cRetryCount < 25 ) // Allow a two minute wait. (24 * 5 seconds)
|
|
{
|
|
LogMsg( "[BC-ClusDB-Cleanup] EvictClusterNode returned ERROR_CLUSTER_JOIN_IN_PROGRESS. Retry attempt %d.", cRetryCount++ );
|
|
|
|
// Sleep for a few seconds.
|
|
Sleep( 5000 );
|
|
|
|
// Try again.
|
|
sc = EvictClusterNode( snhThisNodeHandle.HHandle() );
|
|
}
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
TW32( sc );
|
|
LogMsg( "[BC-ClusDB-Cleanup] Error %#08x occurred trying to evict this node from the sponsor cluster.", sc );
|
|
break;
|
|
} // if: EvictClusterNode() failed
|
|
}
|
|
while( false ); // dummy do while loop to avoid gotos.
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC-ClusDB-Cleanup] Error %#08x occurred trying to remove this node from the sponsor cluster database. Throwing exception.", sc );
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_EVICTING_NODE );
|
|
} // if: something has gone wrong
|
|
|
|
LogMsg( "[BC-ClusDB-Cleanup] This node has been successfully removed from the sponsor cluster database." );
|
|
} // if: we had added this node to the sponsor cluster database
|
|
|
|
// Cleanup the cluster hive
|
|
CleanupHive();
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDBJoin::Cleanup
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusDBJoin::Synchronize
|
|
//
|
|
// Description:
|
|
// Synchronize the cluster database with the sponsor cluster.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the called functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDBJoin::Synchronize( void )
|
|
{
|
|
TraceFunc( "" );
|
|
LogMsg( "[BC-ClusDB-Synchronize] Attempting to synchronize the cluster database with the sponsor cluster." );
|
|
|
|
DWORD sc = ERROR_SUCCESS;
|
|
|
|
//
|
|
// Initialize the byte pipe.
|
|
//
|
|
|
|
m_bpBytePipe.state = reinterpret_cast< char * >( this );
|
|
m_bpBytePipe.alloc = S_BytePipeAlloc;
|
|
m_bpBytePipe.push = S_BytePipePush;
|
|
m_bpBytePipe.pull = S_BytePipePull;
|
|
|
|
|
|
//
|
|
// Synchronize the database
|
|
//
|
|
sc = TW32( DmSyncDatabase( m_pcjClusterJoin->RbhGetJoinBindingHandle(), m_bpBytePipe ) );
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC-ClusDB-Synchronize] Error %#08x occurred trying to suck the database down from the sponsor cluster.", sc );
|
|
goto Cleanup;
|
|
} // if: DmSyncDatabase() failed
|
|
|
|
Cleanup:
|
|
|
|
if ( sc != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "[BC-ClusDB-Synchronize] Error %#08x occurred trying to synchronize the cluster database with the sponsor cluster. Throwing an exception.", sc );
|
|
THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_JOIN_SYNC_DB );
|
|
} // if: something has gone wrong
|
|
|
|
LogMsg( "[BC-ClusDB-Synchronize] The cluster database has been synchronized with the sponsor cluster." );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDBJoin::Synchronize
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// static
|
|
// CClusDBJoin::S_BytePipePush
|
|
//
|
|
// Description:
|
|
// Callback function used by RPC to push data.
|
|
//
|
|
// Arguments:
|
|
// pchStateIn
|
|
// State of the byte pipe
|
|
//
|
|
// pchBufferIn
|
|
// ulBufferSizeIn
|
|
// Buffer contained the pushed data and its size.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// RPC Exceptions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDBJoin::S_BytePipePush(
|
|
char * pchStateIn
|
|
, unsigned char * pchBufferIn
|
|
, unsigned long ulBufferSizeIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
CClusDBJoin * pThis = reinterpret_cast< CClusDBJoin * >( pchStateIn );
|
|
|
|
if ( ulBufferSizeIn != 0 )
|
|
{
|
|
DWORD dwBytesWritten;
|
|
|
|
if ( WriteFile(
|
|
pThis->m_hClusDBFile
|
|
, pchBufferIn
|
|
, ulBufferSizeIn
|
|
, &dwBytesWritten
|
|
, NULL
|
|
)
|
|
== 0
|
|
)
|
|
{
|
|
DWORD sc = TW32( GetLastError() );
|
|
RpcRaiseException( sc );
|
|
} // if: WriteFile() failed
|
|
|
|
Assert( dwBytesWritten == ulBufferSizeIn );
|
|
|
|
} // if: the buffer is non-empty
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDBJoin::S_BytePipePush
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// static
|
|
// CClusDBJoin::S_BytePipePull
|
|
//
|
|
// Description:
|
|
// Callback function used by RPC to pull data.
|
|
//
|
|
// Arguments:
|
|
// pchStateIn
|
|
// State of the byte pipe
|
|
//
|
|
// pchBufferIn
|
|
// ulBufferSizeIn
|
|
// Buffer contained the pushed data and its size.
|
|
//
|
|
// pulWrittenOut
|
|
// Pointer to the number of bytes actually filled into the buffer.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// RPC Exceptions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDBJoin::S_BytePipePull(
|
|
char * pchStateIn
|
|
, unsigned char * pchBufferIn
|
|
, unsigned long ulBufferSizeIn
|
|
, unsigned long * pulWrittenOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
CClusDBJoin * pThis = reinterpret_cast< CClusDBJoin * >( pchStateIn );
|
|
|
|
if ( ulBufferSizeIn != 0 )
|
|
{
|
|
if ( ReadFile(
|
|
pThis->m_hClusDBFile
|
|
, pchBufferIn
|
|
, ulBufferSizeIn
|
|
, pulWrittenOut
|
|
, NULL
|
|
)
|
|
== 0
|
|
)
|
|
{
|
|
DWORD sc = TW32( GetLastError() );
|
|
RpcRaiseException( sc );
|
|
} // if: ReadFile() failed
|
|
|
|
Assert( *pulWrittenOut <= ulBufferSizeIn );
|
|
|
|
} // if: the buffer is non-empty
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDBJoin::S_BytePipePull
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// static
|
|
// CClusDBJoin::S_BytePipeAlloc
|
|
//
|
|
// Description:
|
|
// Callback function used by RPC to allocate a buffer.
|
|
//
|
|
// Arguments:
|
|
// pchStateIn
|
|
// State of the file pipe
|
|
//
|
|
// ulRequestedSizeIn
|
|
// Requested size of the buffer
|
|
//
|
|
// ppchBufferOut
|
|
// Pointer to the buffer pointer
|
|
//
|
|
// pulActualSizeOut
|
|
// Pointer to the actual size of the allocated buffer
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// None.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusDBJoin::S_BytePipeAlloc(
|
|
char * pchStateIn
|
|
, unsigned long ulRequestedSizeIn
|
|
, unsigned char ** ppchBufferOut
|
|
, unsigned long * pulActualSizeOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
CClusDBJoin * pThis = reinterpret_cast< CClusDBJoin * >( pchStateIn );
|
|
|
|
*ppchBufferOut = reinterpret_cast< unsigned char * >( pThis->m_rgbBytePipeBuffer );
|
|
*pulActualSizeOut = ( ulRequestedSizeIn < pThis->ms_nFILE_PIPE_BUFFER_SIZE ) ? ulRequestedSizeIn : pThis->ms_nFILE_PIPE_BUFFER_SIZE;
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CClusDBJoin::S_BytePipeAlloc
|