Source code of Windows XP (NT5)
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.

330 lines
7.4 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. join.c
  5. Abstract:
  6. GUM routines to implement the special join updates.
  7. Author:
  8. John Vert (jvert) 6/10/1996
  9. Revision History:
  10. --*/
  11. #include "gump.h"
  12. //
  13. // Define structure used to pass arguments to node enumeration callback
  14. //
  15. typedef struct _GUMP_JOIN_INFO {
  16. GUM_UPDATE_TYPE UpdateType;
  17. DWORD Status;
  18. DWORD Sequence;
  19. DWORD LockerNode;
  20. } GUMP_JOIN_INFO, *PGUMP_JOIN_INFO;
  21. //
  22. // Local function prototypes
  23. //
  24. BOOL
  25. GumpNodeCallback(
  26. IN PVOID Context1,
  27. IN PVOID Context2,
  28. IN PVOID Object,
  29. IN LPCWSTR Name
  30. );
  31. DWORD
  32. GumBeginJoinUpdate(
  33. IN GUM_UPDATE_TYPE UpdateType,
  34. OUT DWORD *Sequence
  35. )
  36. /*++
  37. Routine Description:
  38. Begins the special join update for a joining node. This
  39. function gets the current GUM sequence number for the
  40. specified update type from another node in the cluster.
  41. It also gets the list of nodes currently participating
  42. in the updates.
  43. Arguments:
  44. UpdateType - Supplies the GUM_UPDATE_TYPE.
  45. Sequence - Returns the sequence number that should be
  46. passed to GumEndJoinUpdate.
  47. Return Value:
  48. ERROR_SUCCESS if successful
  49. Win32 error code otherwise
  50. --*/
  51. {
  52. GUMP_JOIN_INFO JoinInfo;
  53. //
  54. // Enumerate the list of nodes. The callback routine will attempt
  55. // to obtain the required information from each node that is online.
  56. //
  57. JoinInfo.Status = ERROR_GEN_FAILURE;
  58. JoinInfo.UpdateType = UpdateType;
  59. OmEnumObjects(ObjectTypeNode,
  60. GumpNodeCallback,
  61. &JoinInfo,
  62. NULL);
  63. if (JoinInfo.Status == ERROR_SUCCESS) {
  64. ClRtlLogPrint(LOG_NOISE,
  65. "[GUM] GumBeginJoinUpdate succeeded with sequence %1!d!\n",
  66. JoinInfo.Sequence);
  67. *Sequence = JoinInfo.Sequence;
  68. }
  69. return(JoinInfo.Status);
  70. }
  71. BOOL
  72. GumpNodeCallback(
  73. IN PVOID Context1,
  74. IN PVOID Context2,
  75. IN PVOID Object,
  76. IN LPCWSTR Name
  77. )
  78. /*++
  79. Routine Description:
  80. Node enumeration callback routine for GumBeginJoinUpdate. For each
  81. node that is currently online, it attempts to connect and obtain
  82. the current GUM information (sequence and nodelist) for the specified
  83. update type.
  84. Arguments:
  85. Context1 - Supplies a pointer to the GUMP_JOIN_INFO structure.
  86. Context2 - not used
  87. Object - Supplies a pointer to the NM_NODE object
  88. Name - Supplies the node's name.
  89. Return Value:
  90. FALSE - if the information was successfully obtained and enumeration
  91. should stop.
  92. TRUE - If enumeration should continue.
  93. --*/
  94. {
  95. DWORD Status;
  96. DWORD Sequence;
  97. PGUMP_JOIN_INFO JoinInfo = (PGUMP_JOIN_INFO)Context1;
  98. PGUM_NODE_LIST NodeList = NULL;
  99. PNM_NODE Node = (PNM_NODE)Object;
  100. GUM_UPDATE_TYPE UpdateType;
  101. DWORD i;
  102. DWORD LockerNodeId;
  103. DWORD nodeId;
  104. if (NmGetNodeState(Node) != ClusterNodeUp &&
  105. NmGetNodeState(Node) != ClusterNodePaused){
  106. //
  107. // This node is not up, so don't try and get any
  108. // information from it.
  109. //
  110. return(TRUE);
  111. }
  112. //
  113. // Get the sequence and nodelist information from this node.
  114. //
  115. UpdateType = JoinInfo->UpdateType;
  116. if (UpdateType != GumUpdateTesting) {
  117. //
  118. // Our node should not be marked as ClusterNodeUp yet.
  119. //
  120. CL_ASSERT(Node != NmLocalNode);
  121. }
  122. nodeId = NmGetNodeId(Node);
  123. NmStartRpc(nodeId);
  124. Status = GumGetNodeSequence(GumpRpcBindings[NmGetNodeId(Node)],
  125. UpdateType,
  126. &Sequence,
  127. &LockerNodeId,
  128. &NodeList);
  129. NmEndRpc(nodeId);
  130. if (Status != ERROR_SUCCESS) {
  131. ClRtlLogPrint(LOG_UNUSUAL,
  132. "[GUM] GumGetNodeSequence from %1!ws! failed %2!d!\n",
  133. OmObjectId(Node),
  134. Status);
  135. NmDumpRpcExtErrorInfo(Status);
  136. return(TRUE);
  137. }
  138. JoinInfo->Status = ERROR_SUCCESS;
  139. JoinInfo->Sequence = Sequence;
  140. JoinInfo->LockerNode = LockerNodeId;
  141. //
  142. // Zero out all the nodes in the active node array.
  143. //
  144. ZeroMemory(&GumTable[UpdateType].ActiveNode,
  145. sizeof(GumTable[UpdateType].ActiveNode));
  146. //
  147. // Set all the nodes that are currently active in the
  148. // active node array.
  149. //
  150. for (i=0; i < NodeList->NodeCount; i++) {
  151. CL_ASSERT(NmIsValidNodeId(NodeList->NodeId[i]));
  152. ClRtlLogPrint(LOG_NOISE,
  153. "[GUM] GumpNodeCallback setting node %1!d! active.\n",
  154. NodeList->NodeId[i]);
  155. GumTable[UpdateType].ActiveNode[NodeList->NodeId[i]] = TRUE;;
  156. }
  157. MIDL_user_free(NodeList);
  158. //
  159. // Add in our own node.
  160. //
  161. GumTable[UpdateType].ActiveNode[NmGetNodeId(NmLocalNode)] = TRUE;
  162. //
  163. // Set the current locker node
  164. //
  165. GumpLockerNode = LockerNodeId;
  166. return(FALSE);
  167. }
  168. DWORD
  169. GumCreateRpcBindings(
  170. PNM_NODE Node
  171. )
  172. /*++
  173. Routine Description:
  174. Creates GUM's private RPC bindings for a joining node.
  175. Called by the Node Manager.
  176. Arguments:
  177. Node - A pointer to the node for which to create RPC bindings
  178. Return Value:
  179. A Win32 status code.
  180. --*/
  181. {
  182. DWORD Status;
  183. RPC_BINDING_HANDLE BindingHandle;
  184. CL_NODE_ID NodeId = NmGetNodeId(Node);
  185. ClRtlLogPrint(LOG_NOISE,
  186. "[GUM] Creating RPC bindings for node %1!u!.\n",
  187. NodeId
  188. );
  189. //
  190. // Main binding
  191. //
  192. if (GumpRpcBindings[NodeId] != NULL) {
  193. //
  194. // Reuse the old binding.
  195. //
  196. Status = ClMsgVerifyRpcBinding(GumpRpcBindings[NodeId]);
  197. if (Status != ERROR_SUCCESS) {
  198. ClRtlLogPrint(LOG_ERROR,
  199. "[GUM] Failed to verify 1st RPC binding for node %1!u!, status %2!u!.\n",
  200. NodeId,
  201. Status
  202. );
  203. return(Status);
  204. }
  205. }
  206. else {
  207. //
  208. // Create a new binding
  209. //
  210. Status = ClMsgCreateRpcBinding(
  211. Node,
  212. &(GumpRpcBindings[NodeId]),
  213. 0 );
  214. if (Status != ERROR_SUCCESS) {
  215. ClRtlLogPrint(LOG_ERROR,
  216. "[GUM] Failed to create 1st RPC binding for node %1!u!, status %2!u!.\n",
  217. NodeId,
  218. Status
  219. );
  220. return(Status);
  221. }
  222. }
  223. //
  224. // Replay binding
  225. //
  226. if (GumpReplayRpcBindings[NodeId] != NULL) {
  227. //
  228. // Reuse the old binding.
  229. //
  230. Status = ClMsgVerifyRpcBinding(GumpReplayRpcBindings[NodeId]);
  231. if (Status != ERROR_SUCCESS) {
  232. ClRtlLogPrint(LOG_ERROR,
  233. "[GUM] Failed to verify 2nd RPC binding for node %1!u!, status %2!u!.\n",
  234. NodeId,
  235. Status
  236. );
  237. return(Status);
  238. }
  239. }
  240. else {
  241. //
  242. // Create a new binding
  243. //
  244. Status = ClMsgCreateRpcBinding(
  245. Node,
  246. &(GumpReplayRpcBindings[NodeId]),
  247. 0 );
  248. if (Status != ERROR_SUCCESS) {
  249. ClRtlLogPrint(LOG_ERROR,
  250. "[GUM] Failed to create 2nd RPC binding for node %1!u!, status %2!u!.\n",
  251. NodeId,
  252. Status
  253. );
  254. return(Status);
  255. }
  256. }
  257. return(ERROR_SUCCESS);
  258. } // GumCreateRpcBindings