windows-nt/Source/XPSP1/NT/base/cluster/service/gum/join.c
2020-09-26 16:20:57 +08:00

331 lines
7.4 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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