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.
222 lines
5.2 KiB
222 lines
5.2 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
init.c
|
|
|
|
Abstract:
|
|
|
|
Initialization and shutdown routines for the GUM component
|
|
of the NT Cluster Service
|
|
|
|
Author:
|
|
|
|
John Vert (jvert) 17-Apr-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "gump.h"
|
|
|
|
//SS: Adding badly needed comments to this code
|
|
//
|
|
//Lock descriptions:
|
|
// GumpLock - protects GumTable, GumNodeGeneration, GumpLockerNode, GumReplay, GumUpdatePending
|
|
// GumpUpdateLock - protects GumpLockingNode, GumpLockQueue
|
|
// GumpSendUpdateLock - makes sure only one update is dispatched at a time
|
|
// and protect GumpLastXXX variables
|
|
//
|
|
//Lock Hierarchy
|
|
// GumpSendUpdateLock - look at s_GumJoinUpdateNode, send lock is acquired first then the gumlock.
|
|
// GumpLock - in gumpSyncEventHandler, GumpLock is held first before the gumupdate lock
|
|
// GumpUpdateLock - In s_GumAttemptJoinUpdate(), the send lock is acquired first and than the
|
|
// update lock
|
|
//
|
|
//
|
|
//Lock Usage
|
|
// GumpSyncEventHandler - acquires GumpLock and GumpUpdateLock. Dont want the gumpsynceventhandler
|
|
// to wait on gym
|
|
// GumSendUpdate - acquires GumSendUpdateLock while dispatching the update to the other nodes.
|
|
|
|
//
|
|
// Global information (used to be per-update)
|
|
//
|
|
DWORD GumpSequence;
|
|
CRITICAL_SECTION GumpUpdateLock;
|
|
CRITICAL_SECTION GumpSendUpdateLock;
|
|
CRITICAL_SECTION GumpRpcLock;
|
|
PVOID GumpLastBuffer;
|
|
DWORD GumpLastContext;
|
|
DWORD GumpLastBufferLength;
|
|
DWORD GumpLastUpdateType;
|
|
LIST_ENTRY GumpLockQueue;
|
|
DWORD GumpLockingNode;
|
|
DWORD GumpLockerNode;
|
|
BOOL GumpLastBufferValid;
|
|
|
|
//
|
|
// Table of per-update information
|
|
//
|
|
GUM_INFO GumTable[GumUpdateMaximum];
|
|
CRITICAL_SECTION GumpLock;
|
|
|
|
//
|
|
// Per-node information
|
|
//
|
|
GUM_NODE_WAIT GumNodeWait[ClusterMinNodeId + ClusterDefaultMaxNodes];
|
|
RPC_BINDING_HANDLE GumpRpcBindings[ClusterMinNodeId + ClusterDefaultMaxNodes];
|
|
RPC_BINDING_HANDLE GumpReplayRpcBindings[
|
|
ClusterMinNodeId + ClusterDefaultMaxNodes
|
|
];
|
|
DWORD GumNodeGeneration[ClusterMinNodeId + ClusterDefaultMaxNodes] = {0};
|
|
|
|
|
|
|
|
DWORD
|
|
GumInitialize(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initializes the Global Update Manager.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful
|
|
|
|
Win32 error code otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD i;
|
|
DWORD Status;
|
|
|
|
//
|
|
// Initialize global data
|
|
//
|
|
InitializeCriticalSection(&GumpLock);
|
|
InitializeCriticalSection(&GumpUpdateLock);
|
|
InitializeCriticalSection(&GumpSendUpdateLock);
|
|
InitializeCriticalSection(&GumpRpcLock);
|
|
GumpSequence = 0;
|
|
InitializeListHead(&GumpLockQueue);
|
|
GumpLockingNode = (DWORD)-1;
|
|
GumpLastBuffer = NULL;
|
|
GumpLastBufferValid = FALSE;
|
|
GumpLastContext = 0;
|
|
GumpLastBufferLength = 0;
|
|
//set it to illegal value;
|
|
GumpLastUpdateType = GumUpdateMaximum;
|
|
//
|
|
// Assume we are the locker node.
|
|
//
|
|
GumpLockerNode = NmGetNodeId(NmLocalNode);
|
|
|
|
//
|
|
// Initialize GumTable
|
|
//
|
|
for (i=0; i < GumUpdateMaximum; i++) {
|
|
GumTable[i].Receivers = NULL;
|
|
GumTable[i].Joined = FALSE;
|
|
ZeroMemory(&GumTable[i].ActiveNode,
|
|
sizeof(GumTable[i].ActiveNode));
|
|
GumTable[i].ActiveNode[NmGetNodeId(NmLocalNode)] = TRUE;
|
|
}
|
|
|
|
//
|
|
// Initialize per-node information
|
|
//
|
|
for (i=ClusterMinNodeId; i <= NmMaxNodeId; i++) {
|
|
GumpRpcBindings[i] = NULL;
|
|
GumpReplayRpcBindings[i] = NULL;
|
|
|
|
GumNodeWait[i].WaiterCount = 0;
|
|
GumNodeWait[i].hSemaphore = CreateSemaphore(NULL,0,100,NULL);
|
|
if (GumNodeWait[i].hSemaphore == NULL) {
|
|
CL_UNEXPECTED_ERROR( GetLastError() );
|
|
}
|
|
}
|
|
|
|
Status = EpRegisterEventHandler(CLUSTER_EVENT_NODE_DOWN_EX,
|
|
GumpEventHandler);
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
Status = EpRegisterSyncEventHandler(CLUSTER_EVENT_NODE_DOWN_EX,
|
|
GumpSyncEventHandler);
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
VOID
|
|
GumShutdown(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Shuts down the Global Update Manager.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD i;
|
|
PGUM_RECEIVER Receiver;
|
|
PGUM_RECEIVER Next;
|
|
|
|
//
|
|
// Tear down GumTable
|
|
//
|
|
for (i=0; i < GumUpdateMaximum; i++) {
|
|
Receiver = GumTable[i].Receivers;
|
|
while (Receiver != NULL) {
|
|
Next = Receiver->Next;
|
|
LocalFree(Receiver);
|
|
Receiver = Next;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free per-node information
|
|
//
|
|
for (i=ClusterMinNodeId; i <= NmMaxNodeId; i++) {
|
|
if (GumpRpcBindings[i] != NULL) {
|
|
ClMsgDeleteRpcBinding(GumpRpcBindings[i]);
|
|
}
|
|
|
|
if (GumpReplayRpcBindings[i] != NULL) {
|
|
ClMsgDeleteRpcBinding(GumpReplayRpcBindings[i]);
|
|
}
|
|
|
|
if (GumNodeWait[i].hSemaphore != NULL) {
|
|
CloseHandle(GumNodeWait[i].hSemaphore);
|
|
}
|
|
}
|
|
|
|
DeleteCriticalSection(&GumpLock);
|
|
DeleteCriticalSection(&GumpUpdateLock);
|
|
DeleteCriticalSection(&GumpSendUpdateLock);
|
|
}
|
|
|
|
|