331 lines
7.4 KiB
C
331 lines
7.4 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
join.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
GUM routines to implement the special join updates.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Vert (jvert) 6/10/1996
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
#include "gump.h"
|
|||
|
|
|||
|
//
|
|||
|
// Define structure used to pass arguments to node enumeration callback
|
|||
|
//
|
|||
|
typedef struct _GUMP_JOIN_INFO {
|
|||
|
GUM_UPDATE_TYPE UpdateType;
|
|||
|
DWORD Status;
|
|||
|
DWORD Sequence;
|
|||
|
DWORD LockerNode;
|
|||
|
} GUMP_JOIN_INFO, *PGUMP_JOIN_INFO;
|
|||
|
|
|||
|
//
|
|||
|
// Local function prototypes
|
|||
|
//
|
|||
|
BOOL
|
|||
|
GumpNodeCallback(
|
|||
|
IN PVOID Context1,
|
|||
|
IN PVOID Context2,
|
|||
|
IN PVOID Object,
|
|||
|
IN LPCWSTR Name
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
GumBeginJoinUpdate(
|
|||
|
IN GUM_UPDATE_TYPE UpdateType,
|
|||
|
OUT DWORD *Sequence
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Begins the special join update for a joining node. This
|
|||
|
function gets the current GUM sequence number for the
|
|||
|
specified update type from another node in the cluster.
|
|||
|
It also gets the list of nodes currently participating
|
|||
|
in the updates.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
UpdateType - Supplies the GUM_UPDATE_TYPE.
|
|||
|
|
|||
|
Sequence - Returns the sequence number that should be
|
|||
|
passed to GumEndJoinUpdate.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
GUMP_JOIN_INFO JoinInfo;
|
|||
|
|
|||
|
//
|
|||
|
// Enumerate the list of nodes. The callback routine will attempt
|
|||
|
// to obtain the required information from each node that is online.
|
|||
|
//
|
|||
|
JoinInfo.Status = ERROR_GEN_FAILURE;
|
|||
|
JoinInfo.UpdateType = UpdateType;
|
|||
|
OmEnumObjects(ObjectTypeNode,
|
|||
|
GumpNodeCallback,
|
|||
|
&JoinInfo,
|
|||
|
NULL);
|
|||
|
if (JoinInfo.Status == ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
"[GUM] GumBeginJoinUpdate succeeded with sequence %1!d!\n",
|
|||
|
JoinInfo.Sequence);
|
|||
|
*Sequence = JoinInfo.Sequence;
|
|||
|
}
|
|||
|
|
|||
|
return(JoinInfo.Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
GumpNodeCallback(
|
|||
|
IN PVOID Context1,
|
|||
|
IN PVOID Context2,
|
|||
|
IN PVOID Object,
|
|||
|
IN LPCWSTR Name
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Node enumeration callback routine for GumBeginJoinUpdate. For each
|
|||
|
node that is currently online, it attempts to connect and obtain
|
|||
|
the current GUM information (sequence and nodelist) for the specified
|
|||
|
update type.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Context1 - Supplies a pointer to the GUMP_JOIN_INFO structure.
|
|||
|
|
|||
|
Context2 - not used
|
|||
|
|
|||
|
Object - Supplies a pointer to the NM_NODE object
|
|||
|
|
|||
|
Name - Supplies the node's name.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
FALSE - if the information was successfully obtained and enumeration
|
|||
|
should stop.
|
|||
|
|
|||
|
TRUE - If enumeration should continue.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD Status;
|
|||
|
DWORD Sequence;
|
|||
|
PGUMP_JOIN_INFO JoinInfo = (PGUMP_JOIN_INFO)Context1;
|
|||
|
PGUM_NODE_LIST NodeList = NULL;
|
|||
|
PNM_NODE Node = (PNM_NODE)Object;
|
|||
|
GUM_UPDATE_TYPE UpdateType;
|
|||
|
DWORD i;
|
|||
|
DWORD LockerNodeId;
|
|||
|
DWORD nodeId;
|
|||
|
|
|||
|
if (NmGetNodeState(Node) != ClusterNodeUp &&
|
|||
|
NmGetNodeState(Node) != ClusterNodePaused){
|
|||
|
//
|
|||
|
// This node is not up, so don't try and get any
|
|||
|
// information from it.
|
|||
|
//
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get the sequence and nodelist information from this node.
|
|||
|
//
|
|||
|
UpdateType = JoinInfo->UpdateType;
|
|||
|
if (UpdateType != GumUpdateTesting) {
|
|||
|
//
|
|||
|
// Our node should not be marked as ClusterNodeUp yet.
|
|||
|
//
|
|||
|
CL_ASSERT(Node != NmLocalNode);
|
|||
|
}
|
|||
|
|
|||
|
nodeId = NmGetNodeId(Node);
|
|||
|
NmStartRpc(nodeId);
|
|||
|
Status = GumGetNodeSequence(GumpRpcBindings[NmGetNodeId(Node)],
|
|||
|
UpdateType,
|
|||
|
&Sequence,
|
|||
|
&LockerNodeId,
|
|||
|
&NodeList);
|
|||
|
NmEndRpc(nodeId);
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_UNUSUAL,
|
|||
|
"[GUM] GumGetNodeSequence from %1!ws! failed %2!d!\n",
|
|||
|
OmObjectId(Node),
|
|||
|
Status);
|
|||
|
NmDumpRpcExtErrorInfo(Status);
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
JoinInfo->Status = ERROR_SUCCESS;
|
|||
|
JoinInfo->Sequence = Sequence;
|
|||
|
JoinInfo->LockerNode = LockerNodeId;
|
|||
|
|
|||
|
//
|
|||
|
// Zero out all the nodes in the active node array.
|
|||
|
//
|
|||
|
ZeroMemory(&GumTable[UpdateType].ActiveNode,
|
|||
|
sizeof(GumTable[UpdateType].ActiveNode));
|
|||
|
|
|||
|
//
|
|||
|
// Set all the nodes that are currently active in the
|
|||
|
// active node array.
|
|||
|
//
|
|||
|
for (i=0; i < NodeList->NodeCount; i++) {
|
|||
|
CL_ASSERT(NmIsValidNodeId(NodeList->NodeId[i]));
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
"[GUM] GumpNodeCallback setting node %1!d! active.\n",
|
|||
|
NodeList->NodeId[i]);
|
|||
|
GumTable[UpdateType].ActiveNode[NodeList->NodeId[i]] = TRUE;;
|
|||
|
}
|
|||
|
MIDL_user_free(NodeList);
|
|||
|
|
|||
|
//
|
|||
|
// Add in our own node.
|
|||
|
//
|
|||
|
GumTable[UpdateType].ActiveNode[NmGetNodeId(NmLocalNode)] = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// Set the current locker node
|
|||
|
//
|
|||
|
GumpLockerNode = LockerNodeId;
|
|||
|
return(FALSE);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
GumCreateRpcBindings(
|
|||
|
PNM_NODE Node
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Creates GUM's private RPC bindings for a joining node.
|
|||
|
Called by the Node Manager.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Node - A pointer to the node for which to create RPC bindings
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A Win32 status code.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD Status;
|
|||
|
RPC_BINDING_HANDLE BindingHandle;
|
|||
|
CL_NODE_ID NodeId = NmGetNodeId(Node);
|
|||
|
|
|||
|
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
"[GUM] Creating RPC bindings for node %1!u!.\n",
|
|||
|
NodeId
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Main binding
|
|||
|
//
|
|||
|
if (GumpRpcBindings[NodeId] != NULL) {
|
|||
|
//
|
|||
|
// Reuse the old binding.
|
|||
|
//
|
|||
|
Status = ClMsgVerifyRpcBinding(GumpRpcBindings[NodeId]);
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_ERROR,
|
|||
|
"[GUM] Failed to verify 1st RPC binding for node %1!u!, status %2!u!.\n",
|
|||
|
NodeId,
|
|||
|
Status
|
|||
|
);
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
//
|
|||
|
// Create a new binding
|
|||
|
//
|
|||
|
Status = ClMsgCreateRpcBinding(
|
|||
|
Node,
|
|||
|
&(GumpRpcBindings[NodeId]),
|
|||
|
0 );
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_ERROR,
|
|||
|
"[GUM] Failed to create 1st RPC binding for node %1!u!, status %2!u!.\n",
|
|||
|
NodeId,
|
|||
|
Status
|
|||
|
);
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Replay binding
|
|||
|
//
|
|||
|
if (GumpReplayRpcBindings[NodeId] != NULL) {
|
|||
|
//
|
|||
|
// Reuse the old binding.
|
|||
|
//
|
|||
|
Status = ClMsgVerifyRpcBinding(GumpReplayRpcBindings[NodeId]);
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_ERROR,
|
|||
|
"[GUM] Failed to verify 2nd RPC binding for node %1!u!, status %2!u!.\n",
|
|||
|
NodeId,
|
|||
|
Status
|
|||
|
);
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
//
|
|||
|
// Create a new binding
|
|||
|
//
|
|||
|
Status = ClMsgCreateRpcBinding(
|
|||
|
Node,
|
|||
|
&(GumpReplayRpcBindings[NodeId]),
|
|||
|
0 );
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_ERROR,
|
|||
|
"[GUM] Failed to create 2nd RPC binding for node %1!u!, status %2!u!.\n",
|
|||
|
NodeId,
|
|||
|
Status
|
|||
|
);
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return(ERROR_SUCCESS);
|
|||
|
|
|||
|
} // GumCreateRpcBindings
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|