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.

4153 lines
126 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. fmgum.c
  5. Abstract:
  6. Cluster FM Global Update processing routines.
  7. Author:
  8. Rod Gamache (rodga) 24-Apr-1996
  9. Revision History:
  10. --*/
  11. #include "fmp.h"
  12. #include "ntrtl.h"
  13. #if NO_SHARED_LOCKS
  14. extern CRITICAL_SECTION gLockDmpRoot;
  15. #else
  16. extern RTL_RESOURCE gLockDmpRoot;
  17. #endif
  18. #define LOG_MODULE FMGUM
  19. DWORD
  20. WINAPI
  21. FmpGumReceiveUpdates(
  22. IN DWORD Context,
  23. IN BOOL SourceNode,
  24. IN DWORD BufferLength,
  25. IN PVOID Buffer
  26. )
  27. /*++
  28. Routine Description:
  29. Updates the specified resource (contained within Buffer) with a new
  30. state.
  31. Arguments:
  32. Context - The message update type.
  33. SourceNode - TRUE if this is the source node for this update.
  34. FALSE otherwise.
  35. BufferLength - Length of the received buffer.
  36. Buffer - The actual buffer
  37. Returns:
  38. ERROR_SUCCESS
  39. --*/
  40. {
  41. PFM_RESOURCE resource;
  42. //
  43. // Chittur Subbaraman (chitturs) - 4/18/99
  44. //
  45. // If FM groups are not fully initialized or FM is shutting down, then
  46. // don't do anything.
  47. //
  48. if ( !FmpFMGroupsInited ||
  49. FmpShutdown ) {
  50. return(ERROR_SUCCESS);
  51. }
  52. switch ( Context ) {
  53. case FmUpdateFailureCount:
  54. {
  55. PGUM_FAILURE_COUNT failureCount;
  56. PFM_GROUP group;
  57. //
  58. // This update type is always sent.
  59. // On the originating node, all of the work must be done by
  60. // the sending thread.
  61. // On the non-originating nodes, no locks can be acquired! This
  62. // would cause hang situations with operations like move.
  63. // ... this is okay, since the locking must be done on the sending
  64. // node anyway, which owns the group.
  65. //
  66. if ( SourceNode == FALSE ) {
  67. if ( BufferLength <= sizeof(GUM_FAILURE_COUNT) ) {
  68. ClRtlLogPrint(LOG_UNUSUAL, "[FM] Gum FailureCount receive buffer too small!\n");
  69. return(ERROR_SUCCESS);
  70. }
  71. failureCount = (PGUM_FAILURE_COUNT)Buffer;
  72. group = OmReferenceObjectById( ObjectTypeGroup,
  73. (LPCWSTR)&failureCount->GroupId[0] );
  74. if ( group == NULL ) {
  75. ClRtlLogPrint(LOG_UNUSUAL,
  76. "[FM] Gum FailureCount failed to find group %1!ws!\n",
  77. failureCount->GroupId);
  78. return(ERROR_SUCCESS);
  79. }
  80. ClRtlLogPrint(LOG_NOISE,
  81. "[FM] GUM update failure count %1!ws!, count %2!u!\n",
  82. failureCount->GroupId,
  83. failureCount->Count);
  84. //FmpAcquireLocalGroupLock( group );
  85. if ( group->OwnerNode == NmLocalNode ) {
  86. ClRtlLogPrint(LOG_NOISE,
  87. "[FM] Gum FailureCount wrong owner for %1!ws!\n",
  88. failureCount->GroupId);
  89. } else {
  90. group->NumberOfFailures = failureCount->Count;
  91. if ( failureCount->NewTime ) {
  92. group->FailureTime = GetTickCount();
  93. }
  94. }
  95. //FmpReleaseLocalGroupLock( group );
  96. OmDereferenceObject( group );
  97. }
  98. break;
  99. }
  100. case FmUpdateCreateGroup:
  101. {
  102. PGUM_CREATE_GROUP GumGroup;
  103. DWORD Status = ERROR_SUCCESS;
  104. GumGroup = (PGUM_CREATE_GROUP)Buffer;
  105. Status = FmpUpdateCreateGroup( GumGroup, SourceNode );
  106. return(Status);
  107. }
  108. case FmUpdateCreateResource:
  109. {
  110. DWORD dwStatus = ERROR_SUCCESS;
  111. PGUM_CREATE_RESOURCE GumResource =
  112. (PGUM_CREATE_RESOURCE)Buffer;
  113. dwStatus = FmpUpdateCreateResource( GumResource );
  114. return( dwStatus );
  115. }
  116. case FmUpdateAddPossibleNode:
  117. case FmUpdateRemovePossibleNode:
  118. {
  119. PGUM_CHANGE_POSSIBLE_NODE pGumChange;
  120. PFM_RESOURCE pResource;
  121. LPWSTR pszResourceId;
  122. LPWSTR pszNodeId;
  123. PNM_NODE pNode;
  124. DWORD dwStatus;
  125. DWORD dwControlCode;
  126. PFMP_POSSIBLE_NODE pPossibleNode;
  127. pGumChange = (PGUM_CHANGE_POSSIBLE_NODE)Buffer;
  128. pszResourceId = pGumChange->ResourceId;
  129. pszNodeId = (LPWSTR)((PCHAR)pszResourceId +
  130. pGumChange->ResourceIdLen);
  131. pResource = OmReferenceObjectById(ObjectTypeResource,pszResourceId);
  132. pNode = OmReferenceObjectById(ObjectTypeNode, pszNodeId);
  133. CL_ASSERT(pResource != NULL);
  134. CL_ASSERT(pNode != NULL);
  135. pPossibleNode = LocalAlloc( LMEM_FIXED,
  136. sizeof(FMP_POSSIBLE_NODE) );
  137. if ( pPossibleNode == NULL )
  138. {
  139. return(ERROR_NOT_ENOUGH_MEMORY);
  140. }
  141. if (Context == FmUpdateAddPossibleNode)
  142. {
  143. dwControlCode = CLUSCTL_RESOURCE_ADD_OWNER;
  144. }
  145. else
  146. {
  147. dwControlCode = CLUSCTL_RESOURCE_REMOVE_OWNER;
  148. }
  149. dwStatus = FmpUpdateChangeResourceNode(SourceNode,
  150. pResource, pNode, dwControlCode);
  151. //if status is not successful then return, else notify
  152. //resource dlls
  153. if (dwStatus != ERROR_SUCCESS)
  154. {
  155. //dereference the objects
  156. OmDereferenceObject(pResource);
  157. OmDereferenceObject(pNode);
  158. //free the memory
  159. LocalFree(pPossibleNode);
  160. return(dwStatus);
  161. }
  162. pPossibleNode->Resource = pResource;
  163. pPossibleNode->Node = pNode;
  164. pPossibleNode->ControlCode = dwControlCode;
  165. //
  166. // Tell the resource about the ADD/REMOVE in a worker thread.
  167. //
  168. FmpPostWorkItem( FM_EVENT_RESOURCE_CHANGE,
  169. pPossibleNode,
  170. 0 );
  171. //
  172. // Chittur Subbaraman (chitturs) - 6/7/99
  173. //
  174. // Don't reference pPossibleNode any more. It could have
  175. // been freed by the worker thread by the time you get
  176. // here.
  177. //
  178. ClusterEvent( CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE,
  179. pResource );
  180. // Let the worker thread perform the derefs/Frees
  181. return(dwStatus);
  182. }
  183. case FmUpdateJoin:
  184. break;
  185. case FmUpdateCreateResourceType:
  186. {
  187. DWORD dwStatus;
  188. dwStatus = FmpUpdateCreateResourceType( Buffer );
  189. return( dwStatus );
  190. }
  191. break;
  192. case FmUpdateDeleteResourceType:
  193. {
  194. BOOL ResourceExists = FALSE;
  195. PFM_RESTYPE Type;
  196. Type = OmReferenceObjectById( ObjectTypeResType,
  197. (LPWSTR)Buffer);
  198. if (Type == NULL) {
  199. return(ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND);
  200. }
  201. //
  202. // Make sure no resources exist of this type.
  203. //
  204. OmEnumObjects( ObjectTypeResource,
  205. FmpFindResourceType,
  206. Type,
  207. &ResourceExists);
  208. if (ResourceExists) {
  209. OmDereferenceObject(Type);
  210. return(ERROR_DIR_NOT_EMPTY);
  211. }
  212. //
  213. // We need to dereference the object twice to get
  214. // rid of it. But then any notification handlers will
  215. // not get a chance to see the object by the time
  216. // the handler gets called. So we use the EP_DEREF_CONTEXT
  217. // flag to get the event processor to do the second deref
  218. // once everything has been dispatched.
  219. //
  220. FmpDeleteResType(Type);
  221. ClusterEventEx( CLUSTER_EVENT_RESTYPE_DELETED,
  222. EP_DEREF_CONTEXT,
  223. Type );
  224. }
  225. break;
  226. case FmUpdateChangeGroup:
  227. {
  228. PGUM_CHANGE_GROUP pGumChange;
  229. PFM_RESOURCE pResource;
  230. LPWSTR pszResourceId;
  231. LPWSTR pszGroupId;
  232. PFM_GROUP pNewGroup;
  233. DWORD dwStatus;
  234. DWORD dwClusterHighestVersion;
  235. pGumChange = (PGUM_CHANGE_GROUP)Buffer;
  236. pszResourceId = pGumChange->ResourceId;
  237. pszGroupId = (LPWSTR)((PCHAR)pszResourceId +
  238. pGumChange->ResourceIdLen);
  239. //
  240. // Find the specified resource and group.
  241. //
  242. pResource = OmReferenceObjectById(ObjectTypeResource,
  243. pszResourceId);
  244. if (pResource == NULL) {
  245. return(ERROR_RESOURCE_NOT_FOUND);
  246. }
  247. pNewGroup = OmReferenceObjectById(ObjectTypeGroup,
  248. pszGroupId);
  249. if (pNewGroup == NULL) {
  250. OmDereferenceObject(pResource);
  251. return(ERROR_SUCCESS);
  252. }
  253. dwStatus = FmpUpdateChangeResourceGroup(SourceNode,
  254. pResource, pNewGroup);
  255. OmDereferenceObject(pNewGroup);
  256. OmDereferenceObject(pResource);
  257. return(dwStatus);
  258. }
  259. break;
  260. default:
  261. {
  262. }
  263. ClRtlLogPrint(LOG_UNUSUAL,"[FM] Gum received bad context, %1!u!\n",
  264. Context);
  265. }
  266. return(ERROR_SUCCESS);
  267. } // FmpGumReceiveUpdates
  268. DWORD
  269. FmpUpdateChangeQuorumResource(
  270. IN BOOL SourceNode,
  271. IN LPCWSTR NewQuorumResourceId,
  272. IN LPCWSTR szRootClusFilePath,
  273. IN LPDWORD pdwMaxQuorumLogSize
  274. )
  275. /*++
  276. Routine Description:
  277. Perform updates related to changing of the quorum resource.
  278. Arguments:
  279. Return Value:
  280. ERROR_SUCCESS if successful.
  281. A Win32 error code otherwise.
  282. --*/
  283. {
  284. PFM_RESOURCE pResource;
  285. PFM_RESOURCE pOldQuoResource=NULL;
  286. DWORD dwStatus;
  287. WCHAR lpszCheckPtFile[MAX_PATH];
  288. DWORD dwChkPtSeq;
  289. HDMKEY ResKey;
  290. HLOCALXSACTION hXsaction = NULL;
  291. HLOG hNewQuoLog=NULL;
  292. WCHAR szQuorumLogPath[MAX_PATH];
  293. if ( !FmpFMGroupsInited ||
  294. FmpShutdown ) {
  295. return(ERROR_SUCCESS);
  296. }
  297. lstrcpyW(szQuorumLogPath, szRootClusFilePath);
  298. //lstrcatW(szQuorumLogPath, cszClusLogFileRootDir);
  299. pResource = OmReferenceObjectById( ObjectTypeResource,
  300. NewQuorumResourceId );
  301. if (pResource == NULL)
  302. {
  303. ClRtlLogPrint(LOG_UNUSUAL,
  304. "[FM] FmpUpdateChangeQuorumResource: Resource <%1!ws!> could not be found....\n",
  305. NewQuorumResourceId);
  306. return(ERROR_SUCCESS);
  307. }
  308. //since the resource->quorum is going to change, acquire the quocritsec
  309. //always acquire the gQuoCritsec before gQuoLock
  310. ACQUIRE_EXCLUSIVE_LOCK(gQuoChangeLock);
  311. //prevent any resources from going online at this time
  312. ACQUIRE_EXCLUSIVE_LOCK(gQuoLock);
  313. //pause any changes to the cluster database
  314. //always acquire this lock after gQuoLock(refer to the ordering of locks
  315. // in fminit.c)
  316. ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
  317. DmPauseDiskManTimer();
  318. //if this resource was already a quorum resource
  319. if (!pResource->QuorumResource)
  320. {
  321. //
  322. // Now find the current quorum resource.
  323. //
  324. OmEnumObjects( ObjectTypeResource,
  325. FmpFindQuorumResource,
  326. &pOldQuoResource,
  327. NULL );
  328. if ( pOldQuoResource != NULL )
  329. {
  330. CL_ASSERT( pOldQuoResource->QuorumResource );
  331. // Stop the quorum reservation thread!
  332. pOldQuoResource->QuorumResource = FALSE;
  333. }
  334. //set the new resource to be the quorum resource
  335. pResource->QuorumResource = TRUE;
  336. }
  337. //writes to the old log file
  338. hXsaction = DmBeginLocalUpdate();
  339. if (!hXsaction)
  340. {
  341. dwStatus = GetLastError();
  342. goto FnExit;
  343. }
  344. dwStatus = DmLocalSetValue( hXsaction,
  345. DmQuorumKey,
  346. cszPath,
  347. REG_SZ,
  348. (LPBYTE)szQuorumLogPath,
  349. (lstrlenW(szQuorumLogPath)+1) * sizeof(WCHAR));
  350. if (dwStatus != ERROR_SUCCESS)
  351. goto FnExit;
  352. #ifdef CLUSTER_TESTPOINT
  353. TESTPT(TpFailLocalXsaction) {
  354. LPWSTR pszStr = szQuorumLogPath;
  355. dwStatus = (MAX_PATH * sizeof(WCHAR));
  356. dwStatus = DmQuerySz( DmQuorumKey,
  357. cszPath,
  358. &pszStr,
  359. &dwStatus,
  360. &dwStatus);
  361. ClRtlLogPrint(LOG_UNUSUAL,
  362. "[FM] Testing failing a local transaction midway- new quorum path %1!ws!\r\n",
  363. szQuorumLogPath);
  364. dwStatus = 999999;
  365. goto FnExit;
  366. }
  367. #endif
  368. dwStatus = DmLocalSetValue( hXsaction,
  369. DmQuorumKey,
  370. cszMaxQuorumLogSize,
  371. REG_DWORD,
  372. (LPBYTE)pdwMaxQuorumLogSize,
  373. sizeof(DWORD));
  374. if (dwStatus != ERROR_SUCCESS)
  375. goto FnExit;
  376. //if the old quorum resource is different from the new quorum resource
  377. if ((pOldQuoResource) && (pOldQuoResource != pResource))
  378. {
  379. //get/set the new/old resource's flags
  380. //set the core flag on the new quorum resource
  381. ResKey = DmOpenKey( DmResourcesKey,
  382. NewQuorumResourceId,
  383. KEY_READ | KEY_SET_VALUE);
  384. if (!ResKey)
  385. {
  386. dwStatus = GetLastError();
  387. goto FnExit;
  388. }
  389. pResource->ExFlags |= CLUS_FLAG_CORE;
  390. dwStatus = DmLocalSetValue( hXsaction,
  391. ResKey,
  392. CLUSREG_NAME_FLAGS,
  393. REG_DWORD,
  394. (LPBYTE)&(pResource->ExFlags),
  395. sizeof(DWORD));
  396. DmCloseKey( ResKey );
  397. if (dwStatus != ERROR_SUCCESS)
  398. goto FnExit;
  399. //unset the core flag on the old quorum resource
  400. ResKey = DmOpenKey( DmResourcesKey,
  401. OmObjectId(pOldQuoResource),
  402. KEY_READ | KEY_SET_VALUE);
  403. if (!ResKey)
  404. {
  405. dwStatus = GetLastError();
  406. goto FnExit;
  407. }
  408. pOldQuoResource->ExFlags &= ~CLUS_FLAG_CORE;
  409. //unset the core flag on the old quorum resource
  410. dwStatus = DmLocalSetValue( hXsaction,
  411. ResKey,
  412. CLUSREG_NAME_FLAGS,
  413. REG_DWORD,
  414. (LPBYTE)&(pOldQuoResource->ExFlags),
  415. sizeof(DWORD));
  416. DmCloseKey( ResKey );
  417. if (dwStatus != ERROR_SUCCESS)
  418. goto FnExit;
  419. }
  420. //
  421. // Set the quorum resource value.
  422. //
  423. dwStatus = DmLocalSetValue( hXsaction,
  424. DmQuorumKey,
  425. CLUSREG_NAME_QUORUM_RESOURCE,
  426. REG_SZ,
  427. (CONST BYTE *)OmObjectId(pResource),
  428. (lstrlenW(OmObjectId(pResource))+1)*sizeof(WCHAR));
  429. if (dwStatus != ERROR_SUCCESS)
  430. {
  431. goto FnExit;
  432. }
  433. FnExit:
  434. if (dwStatus == ERROR_SUCCESS)
  435. {
  436. LPWSTR szClusterName=NULL;
  437. DWORD dwSize=0;
  438. //commit the update on the old log file,
  439. //any nodes that were done, will get this change
  440. //I cant delete this file
  441. DmCommitLocalUpdate(hXsaction);
  442. //close the old log file, open the new one and take a checkpoint
  443. DmSwitchToNewQuorumLog(szQuorumLogPath);
  444. // SS:the buffer should contain the current cluster name ?
  445. DmQuerySz( DmClusterParametersKey,
  446. CLUSREG_NAME_CLUS_NAME,
  447. &szClusterName,
  448. &dwSize,
  449. &dwSize);
  450. if (szClusterName)
  451. ClusterEventEx(CLUSTER_EVENT_PROPERTY_CHANGE,
  452. EP_FREE_CONTEXT,
  453. szClusterName);
  454. if ((pOldQuoResource) && (pOldQuoResource != pResource))
  455. {
  456. //generate the resource property change events
  457. ClusterEvent( CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE,
  458. pResource );
  459. ClusterEvent( CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE,
  460. pOldQuoResource );
  461. }
  462. }
  463. else
  464. {
  465. if (hXsaction) DmAbortLocalUpdate(hXsaction);
  466. //reinstall the tombstone
  467. DmReinstallTombStone(szQuorumLogPath);
  468. }
  469. if (pOldQuoResource) OmDereferenceObject(pOldQuoResource);
  470. OmDereferenceObject(pResource);
  471. DmRestartDiskManTimer();
  472. //release locks
  473. RELEASE_LOCK(gLockDmpRoot);
  474. RELEASE_LOCK(gQuoLock);
  475. RELEASE_LOCK(gQuoChangeLock);
  476. return(dwStatus);
  477. }
  478. DWORD
  479. FmpUpdateResourceState(
  480. IN BOOL SourceNode,
  481. IN LPCWSTR ResourceId,
  482. IN PGUM_RESOURCE_STATE ResourceState
  483. )
  484. /*++
  485. Routine Description:
  486. GUM update handler for resource state changes.
  487. Arguments:
  488. SourceNode - Supplies whether or not this node was the source of the update
  489. ResourceId - Supplies the id of the resource whose state is changing
  490. ResourceState - Supplies the new state of the resource.
  491. Return Value:
  492. ERROR_SUCCESS if successful
  493. Win32 error code otherwise
  494. --*/
  495. {
  496. PFM_RESOURCE resource;
  497. if ( !FmpFMGroupsInited ) {
  498. return(ERROR_SUCCESS);
  499. }
  500. //
  501. // This update type is always sent.
  502. // On the originating node, all of the work must be done by
  503. // the sending thread.
  504. // On the non-originating nodes, no locks can be acquired! This
  505. // would cause some hang situations with operations like move.
  506. // ... this is okay, since the locking must be done on the sending
  507. // node anyway, which owns the group.
  508. //
  509. if ( SourceNode == FALSE ) {
  510. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  511. if ( resource == NULL ) {
  512. ClRtlLogPrint(LOG_UNUSUAL,
  513. "[FM] Gum ResourceState failed to find resource %1!ws!\n",
  514. ResourceId);
  515. CL_LOGFAILURE( ERROR_RESOURCE_NOT_FOUND );
  516. return(ERROR_SUCCESS);
  517. }
  518. ClRtlLogPrint(LOG_NOISE,
  519. "[FM] Gum update resource %1!ws!, state %2!u!, current state %3!u!.\n",
  520. ResourceId,
  521. ResourceState->State,
  522. ResourceState->PersistentState);
  523. //FmpAcquireLocalResourceLock( resource );
  524. if ( resource->Group->OwnerNode == NmLocalNode ) {
  525. ClRtlLogPrint(LOG_NOISE,
  526. "[FM] Gum ResourceState wrong owner for %1!ws!\n",
  527. ResourceId);
  528. } else {
  529. resource->State = ResourceState->State;
  530. resource->PersistentState = ResourceState->PersistentState;
  531. resource->StateSequence = ResourceState->StateSequence;
  532. switch ( ResourceState->State ) {
  533. case ClusterResourceOnline:
  534. ClusterEvent( CLUSTER_EVENT_RESOURCE_ONLINE, resource );
  535. break;
  536. case ClusterResourceOffline:
  537. ClusterEvent( CLUSTER_EVENT_RESOURCE_OFFLINE, resource );
  538. break;
  539. case ClusterResourceFailed:
  540. ClusterEvent( CLUSTER_EVENT_RESOURCE_FAILED, resource );
  541. break;
  542. case ClusterResourceOnlinePending:
  543. case ClusterResourceOfflinePending:
  544. ClusterEvent( CLUSTER_EVENT_RESOURCE_CHANGE, resource );
  545. break;
  546. default:
  547. ClRtlLogPrint(LOG_UNUSUAL,
  548. "[FM] Gum update resource state, bad state %1!u!\n",
  549. ResourceState->State);
  550. break;
  551. }
  552. }
  553. OmDereferenceObject( resource );
  554. }
  555. return(ERROR_SUCCESS);
  556. }
  557. DWORD
  558. FmpUpdateGroupState(
  559. IN BOOL SourceNode,
  560. IN LPCWSTR GroupId,
  561. IN LPCWSTR NodeId,
  562. IN PGUM_GROUP_STATE GroupState
  563. )
  564. /*++
  565. Routine Description:
  566. GUM update handler for group state changes.
  567. Arguments:
  568. SourceNode - Supplies whether or not this node was the source of the update
  569. GroupId - Supplies the id of the resource whose state is changing
  570. NodeId - Supplies the node id of the group owner.
  571. GroupState - Supplies the new state of the group.
  572. Return Value:
  573. ERROR_SUCCESS if successful
  574. Win32 error code otherwise
  575. --*/
  576. {
  577. PFM_GROUP group;
  578. PWSTR nodeId;
  579. PNM_NODE node;
  580. if ( !FmpFMGroupsInited ) {
  581. return(ERROR_SUCCESS);
  582. }
  583. //
  584. // This update type is always sent.
  585. // On the originating node, all of the work must be done by
  586. // the sending thread.
  587. // On the non-originating nodes, no locks can be acquired! This
  588. // would cause some hang situations with operations like move.
  589. // ... this is okay, since the locking must be done on the sending
  590. // node anyway, which owns the group.
  591. //
  592. if ( SourceNode == FALSE ) {
  593. group = OmReferenceObjectById( ObjectTypeGroup,
  594. GroupId );
  595. if ( group == NULL ) {
  596. ClRtlLogPrint(LOG_UNUSUAL,
  597. "[FM] Gum GroupState failed to find group %1!ws!\n",
  598. GroupId);
  599. return(ERROR_SUCCESS);
  600. }
  601. ClRtlLogPrint(LOG_NOISE,
  602. "[FM] GUM update group %1!ws!, state %2!u!\n",
  603. GroupId,
  604. GroupState->State);
  605. if ( group->OwnerNode == NmLocalNode ) {
  606. ClRtlLogPrint(LOG_NOISE,
  607. "[FM] Gum GroupState wrong owner for %1!ws!\n",
  608. GroupId);
  609. } else {
  610. group->State = GroupState->State;
  611. group->PersistentState = GroupState->PersistentState;
  612. group->StateSequence = GroupState->StateSequence;
  613. node = OmReferenceObjectById( ObjectTypeNode,
  614. NodeId );
  615. if ( node == NULL ) {
  616. ClRtlLogPrint(LOG_UNUSUAL,
  617. "[FM] Owner of Group %1!ws! cannot be found %2!ws!\n",
  618. GroupId,
  619. NodeId);
  620. } else {
  621. ClRtlLogPrint(LOG_NOISE,
  622. "[FM] New owner of Group %1!ws! is %2!ws!, state %3!u!, curstate %4!u!.\n",
  623. OmObjectId( group ),
  624. OmObjectId( node ),
  625. group->State,
  626. group->PersistentState);
  627. if ( !FmpInPreferredList( group, node, FALSE, NULL ) ) {
  628. ClRtlLogPrint( LOG_UNUSUAL,
  629. "[FM] New owner %1!ws! is not in preferred list for group %2!ws!.\n",
  630. OmObjectId( node ),
  631. OmObjectId( group ));
  632. }
  633. }
  634. group->OwnerNode = node;
  635. switch ( GroupState->State ) {
  636. case ClusterGroupOnline:
  637. case ClusterGroupPartialOnline:
  638. ClusterEvent( CLUSTER_EVENT_GROUP_ONLINE, group );
  639. break;
  640. case ClusterGroupOffline:
  641. ClusterEvent( CLUSTER_EVENT_GROUP_OFFLINE, group );
  642. break;
  643. default:
  644. ClRtlLogPrint(LOG_UNUSUAL,"[FM] Gum update group state, bad state %1!u!\n", GroupState->State);
  645. break;
  646. }
  647. }
  648. OmDereferenceObject( group );
  649. }
  650. return(ERROR_SUCCESS);
  651. }
  652. DWORD
  653. FmpUpdateGroupNode(
  654. IN BOOL SourceNode,
  655. IN LPCWSTR GroupId,
  656. IN LPCWSTR NodeId
  657. )
  658. /*++
  659. Routine Description:
  660. GUM update handler for group node changes. This is required for
  661. notification
  662. when a group moves between nodes but does not change state (i.e. it was
  663. already offline)
  664. Arguments:
  665. SourceNode - Supplies whether or not this node was the source of the update
  666. GroupId - Supplies the id of the resource whose state is changing
  667. NodeId - Supplies the node id of the group owner.
  668. Return Value:
  669. ERROR_SUCCESS if successful
  670. Win32 error code otherwise
  671. --*/
  672. {
  673. PFM_GROUP pGroup;
  674. DWORD dwStatus = ERROR_SUCCESS;
  675. PNM_NODE pNode = NULL;
  676. PNM_NODE pPrevNode = NULL;
  677. if ( !FmpFMGroupsInited )
  678. {
  679. return(ERROR_SUCCESS);
  680. }
  681. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  682. GroupId );
  683. if (pGroup == NULL)
  684. {
  685. ClRtlLogPrint(LOG_ERROR,
  686. "[FM] FmpUpdateGroupNode: GroupID = %1!ws! could not be found...\n",
  687. GroupId);
  688. //
  689. // Chittur Subbaraman (chitturs) - 6/12/99
  690. //
  691. // Return ERROR_SUCCESS here since this is what NT4 side does.
  692. // Compatibility pain !
  693. //
  694. goto FnExit;
  695. }
  696. pNode = OmReferenceObjectById(ObjectTypeNode,
  697. NodeId);
  698. if (pNode == NULL)
  699. {
  700. dwStatus = ERROR_CLUSTER_NODE_NOT_FOUND;
  701. goto FnExit;
  702. }
  703. //
  704. // HACKHACK: Chittur Subbaraman (chitturs) - 5/20/99
  705. // Comment out as a temporary solution to avoid deadlocks.
  706. //
  707. // FmpAcquireLocalGroupLock(pGroup);
  708. pPrevNode = pGroup->OwnerNode;
  709. //set the new owner node, incr ref count
  710. OmReferenceObject(pNode);
  711. pGroup->OwnerNode = pNode;
  712. //decr ref count on previous owner
  713. OmDereferenceObject(pPrevNode);
  714. //
  715. // HACKHACK: Chittur Subbaraman (chitturs) - 5/20/99
  716. // Comment out as a temporary solution to avoid deadlocks.
  717. //
  718. // FmpReleaseLocalGroupLock(pGroup);
  719. //generate an event to signify group owner node change
  720. ClusterEvent(CLUSTER_EVENT_GROUP_CHANGE, pGroup);
  721. FnExit:
  722. if (pGroup) OmDereferenceObject(pGroup);
  723. if (pNode) OmDereferenceObject(pNode);
  724. return(dwStatus);
  725. }
  726. DWORD
  727. FmpUpdateChangeClusterName(
  728. IN BOOL SourceNode,
  729. IN LPCWSTR szNewName
  730. )
  731. /*++
  732. Routine Description:
  733. GUM update routine for changing the name of the cluster.
  734. This changes the name property of the core network name resource
  735. as well. The resource is notified about it by a worker thread that
  736. the name has been changed.
  737. Arguments:
  738. SourceNode - Supplies whether or not this node originated the update.
  739. NewName - Supplies the new name of the cluster.
  740. Return Value:
  741. ERROR_SUCCESS if successful
  742. Win32 error code otherwise
  743. --*/
  744. {
  745. LPWSTR Buffer;
  746. DWORD Length;
  747. DWORD Status = ERROR_SUCCESS;
  748. LPWSTR ClusterNameId=NULL;
  749. DWORD idMaxSize = 0;
  750. DWORD idSize = 0;
  751. PFM_RESOURCE Resource=NULL;
  752. HDMKEY ResKey = NULL;
  753. HDMKEY ParamKey = NULL;
  754. HLOCALXSACTION hXsaction=NULL;
  755. if ( !FmpFMGroupsInited ||
  756. FmpShutdown ) {
  757. return(ERROR_SUCCESS);
  758. }
  759. hXsaction = DmBeginLocalUpdate();
  760. if (!hXsaction)
  761. {
  762. Status = ERROR_SUCCESS;
  763. goto FnExit;
  764. }
  765. //find the core network name resource, set its private properties
  766. Status = DmQuerySz( DmClusterParametersKey,
  767. CLUSREG_NAME_CLUS_CLUSTER_NAME_RES,
  768. (LPWSTR*)&ClusterNameId,
  769. &idMaxSize,
  770. &idSize);
  771. if (Status != ERROR_SUCCESS) {
  772. ClRtlLogPrint(LOG_ERROR,
  773. "[FM] FmpUpdateChangeClusterName failed to get cluster name resource, error %1!u!.\n",
  774. Status);
  775. goto FnExit;
  776. }
  777. //
  778. // Reference the specified resource ID.
  779. //
  780. Resource = OmReferenceObjectById( ObjectTypeResource, ClusterNameId );
  781. if (Resource == NULL) {
  782. ClRtlLogPrint(LOG_ERROR,
  783. "[FM] FmpUpdateChangeClusterName failed to find the cluster name resource\n",
  784. Status);
  785. goto FnExit;
  786. }
  787. ResKey = DmOpenKey(DmResourcesKey, ClusterNameId, KEY_READ | KEY_SET_VALUE);
  788. if (!ResKey)
  789. {
  790. Status = GetLastError();
  791. goto FnExit;
  792. }
  793. ParamKey = DmOpenKey(ResKey, cszParameters, KEY_READ | KEY_SET_VALUE);
  794. if (!ParamKey)
  795. {
  796. Status = GetLastError();
  797. goto FnExit;
  798. }
  799. Status = DmLocalSetValue(hXsaction,
  800. ParamKey,
  801. CLUSREG_NAME_RES_NAME,
  802. REG_SZ,
  803. (CONST BYTE *)szNewName,
  804. (lstrlenW(szNewName)+1)*sizeof(WCHAR));
  805. if ( Status != ERROR_SUCCESS )
  806. goto FnExit;
  807. //update the default cluster name
  808. Status = DmLocalSetValue(hXsaction,
  809. DmClusterParametersKey,
  810. CLUSREG_NAME_CLUS_NAME,
  811. REG_SZ,
  812. (CONST BYTE *)szNewName,
  813. (lstrlenW(szNewName)+1)*sizeof(WCHAR));
  814. if (Status != ERROR_SUCCESS)
  815. goto FnExit;
  816. //notify the resource dll that the name has been changed
  817. //that will decrement the reference count on this object
  818. //current fm only has pending work associated with
  819. //this event on the name change case. If other cases require
  820. //pending work, then CLUSTER_EVENT_PROPERTY_CONTEXT must
  821. //be used
  822. FmpPostWorkItem(FM_EVENT_CLUSTER_PROPERTY_CHANGE, Resource, 0);
  823. Resource = NULL;
  824. //
  825. // Need to allocate a new buffer for posting the new name to the event
  826. // processor
  827. //
  828. Length = (lstrlenW(szNewName)+1)*sizeof(WCHAR);
  829. Buffer = LocalAlloc(LMEM_FIXED,Length);
  830. if (Buffer == NULL) {
  831. Status = ERROR_NOT_ENOUGH_MEMORY;
  832. goto FnExit;
  833. }
  834. CopyMemory(Buffer, szNewName, Length);
  835. ClusterEventEx(CLUSTER_EVENT_PROPERTY_CHANGE,
  836. EP_FREE_CONTEXT,
  837. Buffer);
  838. FnExit:
  839. if (ClusterNameId) LocalFree(ClusterNameId);
  840. if (ParamKey) DmCloseKey(ParamKey);
  841. if (ResKey) DmCloseKey(ResKey);
  842. if (Resource) OmDereferenceObject(Resource);
  843. if (hXsaction)
  844. {
  845. if (Status == ERROR_SUCCESS)
  846. DmCommitLocalUpdate(hXsaction);
  847. else
  848. DmAbortLocalUpdate(hXsaction);
  849. }
  850. return(Status);
  851. }
  852. DWORD
  853. FmpUpdateChangeResourceName(
  854. IN BOOL bSourceNode,
  855. IN LPCWSTR lpszResourceId,
  856. IN LPCWSTR lpszNewName
  857. )
  858. /*++
  859. Routine Description:
  860. GUM dispatch routine for changing the friendly name of a resource.
  861. Arguments:
  862. bSourceNode - Supplies whether or not this node initiated the GUM update.
  863. Not used.
  864. lpszResourceId - Supplies the resource ID.
  865. lpszNewName - Supplies the new friendly name.
  866. Return Value:
  867. ERROR_SUCCESS if successful.
  868. Win32 error code otherwise.
  869. --*/
  870. {
  871. PFM_RESOURCE pResource = NULL;
  872. DWORD dwStatus;
  873. HDMKEY hKey = NULL;
  874. DWORD dwDisposition;
  875. HLOCALXSACTION
  876. hXsaction = NULL;
  877. PFM_RES_CHANGE_NAME pResChangeName = NULL;
  878. if ( !FmpFMGroupsInited ||
  879. FmpShutdown ) {
  880. return( ERROR_SUCCESS );
  881. }
  882. //
  883. // Chittur Subbaraman (chitturs) - 6/28/99
  884. //
  885. // Restructure this GUM update as a local transaction.
  886. //
  887. //
  888. pResource = OmReferenceObjectById( ObjectTypeResource, lpszResourceId );
  889. if ( pResource == NULL )
  890. {
  891. ClRtlLogPrint(LOG_UNUSUAL,
  892. "[FM] FmpUpdateChangeResourceName: Resource <%1!ws!> could not be found....\n",
  893. lpszResourceId);
  894. return( ERROR_RESOURCE_NOT_FOUND );
  895. }
  896. ClRtlLogPrint(LOG_NOISE,
  897. "[FM] FmpUpdateChangeResourceName: Entry for resource <%1!ws!>, New name = <%2!ws!>...\n",
  898. lpszResourceId,
  899. lpszNewName);
  900. //
  901. // Start a transaction
  902. //
  903. hXsaction = DmBeginLocalUpdate();
  904. if ( !hXsaction )
  905. {
  906. dwStatus = GetLastError();
  907. ClRtlLogPrint(LOG_UNUSUAL,
  908. "[FM] FmpUpdateChangeResourceName: Failed in starting a transaction for resource %1!ws!, Status =%2!d!....\n",
  909. lpszResourceId,
  910. dwStatus);
  911. goto FnExit;
  912. }
  913. //
  914. // Open the resources key.
  915. //
  916. hKey = DmLocalCreateKey( hXsaction,
  917. DmResourcesKey,
  918. lpszResourceId,
  919. 0,
  920. KEY_READ | KEY_WRITE,
  921. NULL,
  922. &dwDisposition );
  923. if ( hKey == NULL )
  924. {
  925. dwStatus = GetLastError();
  926. ClRtlLogPrint(LOG_UNUSUAL,
  927. "[FM] FmpUpdateChangeResourceName: Failed in opening the resources key for resource %1!ws!, Status =%2!d!....\n",
  928. lpszResourceId,
  929. dwStatus);
  930. goto FnExit;
  931. }
  932. CL_ASSERT( dwDisposition != REG_CREATED_NEW_KEY );
  933. //
  934. // Set the resource name in the registry
  935. //
  936. dwStatus = DmLocalSetValue( hXsaction,
  937. hKey,
  938. CLUSREG_NAME_RES_NAME,
  939. REG_SZ,
  940. ( CONST BYTE * ) lpszNewName,
  941. ( lstrlenW( lpszNewName ) + 1 ) *
  942. sizeof( WCHAR ) );
  943. if( dwStatus != ERROR_SUCCESS )
  944. {
  945. ClRtlLogPrint(LOG_CRITICAL,
  946. "[FM] FmpUpdateChangeResourceName: DmLocalSetValue for resource %1!ws! fails, Status = %2!d!...\n",
  947. lpszResourceId,
  948. dwStatus);
  949. goto FnExit;
  950. }
  951. pResChangeName = LocalAlloc( LMEM_FIXED,
  952. lstrlenW( lpszNewName ) * sizeof ( WCHAR ) +
  953. sizeof( FM_RES_CHANGE_NAME ) );
  954. if ( pResChangeName == NULL )
  955. {
  956. dwStatus = GetLastError();
  957. ClRtlLogPrint(LOG_UNUSUAL,
  958. "[FM] FmpUpdateChangeResourceName: Unable to allocate memory for ResChangeName structure for resource <%1!ws!>, Status =%2!d!....\n",
  959. lpszResourceId,
  960. dwStatus);
  961. goto FnExit;
  962. }
  963. dwStatus = OmSetObjectName( pResource, lpszNewName );
  964. if ( dwStatus != ERROR_SUCCESS )
  965. {
  966. ClRtlLogPrint(LOG_CRITICAL,
  967. "[FM] FmpUpdateChangeResourceName: Unable to set name <%3!ws!> for resource <%1!ws!>, Status =%2!d!....\n",
  968. lpszResourceId,
  969. dwStatus,
  970. lpszNewName );
  971. LocalFree( pResChangeName );
  972. goto FnExit;
  973. }
  974. pResChangeName->pResource = pResource;
  975. lstrcpyW( pResChangeName->szNewResourceName, lpszNewName );
  976. //
  977. // The FM worker thread will free the memory for the pResChangeName
  978. // structure as well as dereference the pResource object.
  979. //
  980. FmpPostWorkItem( FM_EVENT_RESOURCE_NAME_CHANGE, pResChangeName, 0 );
  981. pResource = NULL;
  982. ClRtlLogPrint(LOG_NOISE,
  983. "[FM] FmpUpdateChangeResourceName: Successfully changed name of resource <%1!ws!> to <%2!ws!>...\n",
  984. lpszResourceId,
  985. lpszNewName);
  986. FnExit:
  987. if ( pResource != NULL )
  988. {
  989. OmDereferenceObject( pResource );
  990. }
  991. if ( hKey != NULL )
  992. {
  993. DmCloseKey( hKey );
  994. }
  995. if ( ( dwStatus == ERROR_SUCCESS ) && ( hXsaction ) )
  996. {
  997. DmCommitLocalUpdate( hXsaction );
  998. }
  999. else
  1000. {
  1001. if ( hXsaction ) DmAbortLocalUpdate( hXsaction );
  1002. }
  1003. ClRtlLogPrint(LOG_NOISE,
  1004. "[FM] FmpUpdateChangeResourceName: Exit for resource %1!ws!, Status=%2!u!...\n",
  1005. lpszResourceId,
  1006. dwStatus);
  1007. return( dwStatus );
  1008. }
  1009. /****
  1010. @func DWORD | FmpUpdatePossibleNodesForResType| This update is called to
  1011. update the possible nodes for a resource type.
  1012. @parm IN BOOL | SourceNode | set to TRUE, if the update originated at this
  1013. node.
  1014. @parm IN LPCWSTR | lpszResTypeName | The name of the resource type.
  1015. @parm IN DWORD | dwBufLength | The size of the multi-sz string pointed
  1016. to by pBuf
  1017. @parm IN PVOID | pBuf | A pointer to the buffer containing the names of
  1018. the nodes that support this resource type.
  1019. @comm The possible list of nodes that supports the given resource type is
  1020. updated with the list provided.
  1021. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1022. @xref <f FmpDecisionPossibleDmSwitchToNewQuorumLog>
  1023. ****/
  1024. DWORD
  1025. FmpUpdatePossibleNodeForResType(
  1026. IN BOOL SourceNode,
  1027. IN LPCWSTR lpszResTypeName,
  1028. IN LPDWORD pdwBufLength,
  1029. IN PVOID pBuf
  1030. )
  1031. {
  1032. PFM_RESTYPE pResType;
  1033. DWORD dwStatus;
  1034. HDMKEY hResTypeKey = NULL;
  1035. HLOCALXSACTION hXsaction = NULL;
  1036. LIST_ENTRY NewPosNodeList;
  1037. PLIST_ENTRY pListEntry;
  1038. PRESTYPE_POSSIBLE_ENTRY pResTypePosEntry = NULL;
  1039. //
  1040. // Chittur Subbaraman (chitturs) - 5/13/99
  1041. //
  1042. // Don't check for FmpFMGroupsInited condition since this GUM
  1043. // handler is called by the forming node before that variable
  1044. // is set to TRUE. This update always comes after the
  1045. // corresponding restypes have been created and is made
  1046. // internally by the clussvc following this order. Note that
  1047. // a joining node cannot receive this update until groups are
  1048. // inited since GUM receive updates are turned on only after
  1049. // the FmpFMGroupsInited variable is set to TRUE. Also, the
  1050. // intracluster RPC is fired up in a forming node only after
  1051. // the groups are inited. Hence, there is no major danger
  1052. // of this GUM handler being called if the corresponding
  1053. // restype is not created.
  1054. //
  1055. if ( FmpShutdown ) {
  1056. return(ERROR_SUCCESS);
  1057. }
  1058. InitializeListHead(&NewPosNodeList);
  1059. pResType = OmReferenceObjectById( ObjectTypeResType,
  1060. lpszResTypeName);
  1061. if (!pResType)
  1062. {
  1063. dwStatus = ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND;
  1064. goto FnExit;
  1065. }
  1066. dwStatus = FmpAddPossibleNodeToList(pBuf, *pdwBufLength, &NewPosNodeList);
  1067. if (dwStatus != ERROR_SUCCESS)
  1068. {
  1069. goto FnExit;
  1070. }
  1071. //writes to the old log file
  1072. hXsaction = DmBeginLocalUpdate();
  1073. if (!hXsaction)
  1074. {
  1075. dwStatus = GetLastError();
  1076. goto FnExit;
  1077. }
  1078. hResTypeKey = DmOpenKey(DmResourceTypesKey,
  1079. lpszResTypeName,
  1080. KEY_READ | KEY_WRITE);
  1081. if (hResTypeKey == NULL)
  1082. {
  1083. dwStatus = GetLastError();
  1084. goto FnExit;
  1085. }
  1086. //if there are no possible owners, delete the value
  1087. if (pBuf && *pdwBufLength)
  1088. {
  1089. dwStatus = DmLocalSetValue( hXsaction,
  1090. hResTypeKey,
  1091. CLUSREG_NAME_RESTYPE_POSSIBLE_NODES,
  1092. REG_MULTI_SZ,
  1093. (LPBYTE)pBuf,
  1094. *pdwBufLength);
  1095. }
  1096. else
  1097. {
  1098. dwStatus = DmLocalDeleteValue( hXsaction,
  1099. hResTypeKey,
  1100. CLUSREG_NAME_RESTYPE_POSSIBLE_NODES);
  1101. if (dwStatus == ERROR_FILE_NOT_FOUND)
  1102. {
  1103. dwStatus = ERROR_SUCCESS;
  1104. }
  1105. }
  1106. FnExit:
  1107. if (dwStatus == ERROR_SUCCESS)
  1108. {
  1109. //commit the update on the old log file,
  1110. //any nodes that were done, will get this change
  1111. //I cant delete this file
  1112. DmCommitLocalUpdate(hXsaction);
  1113. ACQUIRE_EXCLUSIVE_LOCK(gResTypeLock);
  1114. //free the old list
  1115. while (!IsListEmpty(&pResType->PossibleNodeList))
  1116. {
  1117. pListEntry = RemoveHeadList(&pResType->PossibleNodeList);
  1118. pResTypePosEntry = CONTAINING_RECORD(pListEntry, RESTYPE_POSSIBLE_ENTRY,
  1119. PossibleLinkage);
  1120. OmDereferenceObject(pResTypePosEntry->PossibleNode);
  1121. LocalFree(pResTypePosEntry);
  1122. }
  1123. //now switch the possible owners list for the
  1124. //resource type
  1125. while (!IsListEmpty(&(NewPosNodeList)))
  1126. {
  1127. //remove from the new prepared list and hang
  1128. //it of the restype structure
  1129. pListEntry = RemoveHeadList(&NewPosNodeList);
  1130. InsertTailList(&pResType->PossibleNodeList, pListEntry);
  1131. pResTypePosEntry = CONTAINING_RECORD(pListEntry, RESTYPE_POSSIBLE_ENTRY,
  1132. PossibleLinkage);
  1133. ClRtlLogPrint(LOG_NOISE,
  1134. "[FM] FmpUpdatePossibleNodesForRestype:Adding node %1!ws! to %2!ws! resource type's possible node list...\n",
  1135. OmObjectId(pResTypePosEntry->PossibleNode),
  1136. lpszResTypeName);
  1137. }
  1138. RELEASE_LOCK(gResTypeLock);
  1139. ClusterEvent( CLUSTER_EVENT_RESTYPE_PROPERTY_CHANGE,
  1140. pResType );
  1141. }
  1142. else
  1143. {
  1144. //free up the NewPostNodeList
  1145. if (hXsaction) DmAbortLocalUpdate(hXsaction);
  1146. //if a new list was prepared, free it
  1147. while (!IsListEmpty(&(NewPosNodeList)))
  1148. {
  1149. pListEntry = RemoveHeadList(&NewPosNodeList);
  1150. pResTypePosEntry = CONTAINING_RECORD(pListEntry, RESTYPE_POSSIBLE_ENTRY,
  1151. PossibleLinkage);
  1152. OmDereferenceObject(pResTypePosEntry->PossibleNode);
  1153. LocalFree(pResTypePosEntry);
  1154. }
  1155. }
  1156. if (hResTypeKey) DmCloseKey(hResTypeKey);
  1157. if (pResType) OmDereferenceObject(pResType);
  1158. return(dwStatus);
  1159. }
  1160. /****
  1161. @func DWORD | FmpDecidePossibleNodeForResType| When the quorum resource is changed,
  1162. the FM invokes this api on the owner node of the new quorum resource
  1163. to create a new quorum log file.
  1164. @parm IN PVOID | pResource | The new quorum resource.
  1165. @parm IN LPCWSTR | lpszPath | The path for temporary cluster files.
  1166. @parm IN DWORD | dwMaxQuoLogSize | The maximum size limit for the quorum log file.
  1167. @comm When a quorum resource is changed, the fm calls this funtion before it
  1168. updates the quorum resource. If a new log file needs to be created,
  1169. a checkpoint is taken.
  1170. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1171. @xref <f DmSwitchToNewQuorumLog>
  1172. ****/
  1173. DWORD FmpDecidePossibleNodeForResType
  1174. (
  1175. IN PGUM_VOTE_DECISION_CONTEXT pDecisionContext,
  1176. IN DWORD dwVoteBufLength,
  1177. IN PVOID pVoteBuf,
  1178. IN DWORD dwNumVotes,
  1179. IN BOOL bDidAllActiveNodesVote,
  1180. OUT LPDWORD pdwOutputBufSize,
  1181. OUT PVOID *ppOutputBuf
  1182. )
  1183. {
  1184. DWORD dwStatus = ERROR_SUCCESS;
  1185. DWORD i;
  1186. PFMP_VOTE_POSSIBLE_NODE_FOR_RESTYPE pFmpVote;
  1187. LPWSTR lpmszPossibleNodes = NULL;
  1188. DWORD dwlpmszLen = 0;
  1189. PVOID pGumBuffer = NULL;
  1190. DWORD dwNodeId;
  1191. WCHAR szNodeId[6];
  1192. LPWSTR lpmszCurrentPossibleNodes=NULL;
  1193. BOOL bChange = FALSE;
  1194. HDMKEY hResTypeKey = NULL;
  1195. DWORD dwSize;
  1196. DWORD dwStringBufSize = 0;
  1197. BOOL bAssumeSupported;
  1198. LPWSTR TypeName = NULL;
  1199. //First get the type name from pDecisionContext
  1200. TypeName=(LPWSTR)LocalAlloc(LMEM_FIXED,pDecisionContext->dwInputBufLength);
  1201. if(TypeName==NULL)
  1202. {
  1203. ClRtlLogPrint(LOG_ERROR,"[FM] FmpDecidePossibleNodeForResType: Not Enough Memory, error= %1!d!\r\n",
  1204. GetLastError());
  1205. goto FnExit;
  1206. }
  1207. CopyMemory(TypeName,pDecisionContext->pInputBuf,pDecisionContext->dwInputBufLength);
  1208. //initialize the out params
  1209. *ppOutputBuf = NULL;
  1210. *pdwOutputBufSize = 0;
  1211. bAssumeSupported= *((BOOL*)pDecisionContext->pContext);
  1212. if (bAssumeSupported)
  1213. {
  1214. hResTypeKey = DmOpenKey(DmResourceTypesKey,
  1215. TypeName,
  1216. KEY_READ | KEY_WRITE);
  1217. if (hResTypeKey == NULL)
  1218. {
  1219. dwStatus = GetLastError();
  1220. CL_LOGFAILURE(dwStatus);
  1221. goto FnExit;
  1222. }
  1223. //pass the current possible node list to the decider
  1224. dwStatus = DmQueryString(hResTypeKey,
  1225. CLUSREG_NAME_RESTYPE_POSSIBLE_NODES,
  1226. REG_MULTI_SZ,
  1227. &lpmszCurrentPossibleNodes,
  1228. &dwStringBufSize,
  1229. &dwSize);
  1230. if (dwStatus != ERROR_SUCCESS)
  1231. {
  1232. //if the possible node list is not found this is ok
  1233. //ie. only if there is some other error we give up
  1234. if ( dwStatus != ERROR_FILE_NOT_FOUND )
  1235. {
  1236. CL_LOGFAILURE(dwStatus);
  1237. goto FnExit;
  1238. }
  1239. }
  1240. DmCloseKey(hResTypeKey);
  1241. hResTypeKey = NULL;
  1242. }
  1243. //if the current list is passed in, dont remove any possible
  1244. //nodes from the list if they dont vote, simply add the new ones
  1245. if (lpmszCurrentPossibleNodes)
  1246. {
  1247. DWORD dwStrLen;
  1248. //make a copy of the multi-sz
  1249. dwlpmszLen = ClRtlMultiSzLength(lpmszCurrentPossibleNodes);
  1250. dwStrLen = dwlpmszLen * sizeof(WCHAR);
  1251. lpmszPossibleNodes = LocalAlloc(LMEM_FIXED, dwStrLen);
  1252. if (!lpmszPossibleNodes)
  1253. {
  1254. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  1255. CL_LOGFAILURE(dwStatus);
  1256. goto FnExit;
  1257. }
  1258. CopyMemory(lpmszPossibleNodes, lpmszCurrentPossibleNodes, dwStrLen);
  1259. }
  1260. for (i = 0; i< dwNumVotes; i++)
  1261. {
  1262. pFmpVote = (PFMP_VOTE_POSSIBLE_NODE_FOR_RESTYPE)
  1263. GETVOTEFROMBUF(pVoteBuf, pDecisionContext->dwVoteLength, i+1 , &dwNodeId);
  1264. //if not a valid vote, skip
  1265. if (!pFmpVote)
  1266. continue;
  1267. CL_ASSERT((PBYTE)pFmpVote <= ((PBYTE)pVoteBuf + dwVoteBufLength -
  1268. sizeof(FMP_VOTE_POSSIBLE_NODE_FOR_RESTYPE)));
  1269. wsprintfW(szNodeId, L"%d" , dwNodeId);
  1270. if (pFmpVote->bPossibleNode)
  1271. {
  1272. if (lpmszCurrentPossibleNodes)
  1273. {
  1274. //if the string is already there, dont append it again
  1275. if (ClRtlMultiSzScan(lpmszCurrentPossibleNodes, szNodeId))
  1276. continue;
  1277. }
  1278. dwStatus = ClRtlMultiSzAppend(&lpmszPossibleNodes,
  1279. &dwlpmszLen, szNodeId);
  1280. bChange = TRUE;
  1281. if (dwStatus != ERROR_SUCCESS)
  1282. goto FnExit;
  1283. }
  1284. else
  1285. {
  1286. //if a current list was specified
  1287. //this node is not a possible node anymore, remove it from the list
  1288. if (lpmszCurrentPossibleNodes)
  1289. {
  1290. ClRtlLogPrint(LOG_NOISE,
  1291. "[FM] FmpDecidePossibleNodesForRestype: Removing node %1!ws! from %2!ws! restype possibleowner list \r\n",
  1292. szNodeId,TypeName);
  1293. dwStatus = ClRtlMultiSzRemove(lpmszPossibleNodes, &dwlpmszLen, szNodeId);
  1294. if (dwStatus == ERROR_SUCCESS)
  1295. {
  1296. //if the node is successfully removed
  1297. bChange = TRUE;
  1298. }
  1299. else if (dwStatus != ERROR_FILE_NOT_FOUND)
  1300. {
  1301. //if the node exists but cannot be removed return with error
  1302. //if the node didnt exist, we dont do anything bChange remains
  1303. //set at FALSE
  1304. goto FnExit;
  1305. }
  1306. else
  1307. {
  1308. dwStatus = ERROR_SUCCESS;
  1309. }
  1310. }
  1311. }
  1312. }
  1313. //if nothing has changed dont issue a gum update
  1314. if (!bChange)
  1315. {
  1316. dwStatus = ERROR_ALREADY_EXISTS;
  1317. goto FnExit;
  1318. }
  1319. //dwlpmszLen contains the size of the multi-sz string in the
  1320. //number of characters, make it the number of bytes
  1321. dwlpmszLen *= sizeof(WCHAR);
  1322. pGumBuffer = GumMarshallArgs(pdwOutputBufSize, 3,
  1323. pDecisionContext->dwInputBufLength, pDecisionContext->pInputBuf,
  1324. sizeof(DWORD), &dwlpmszLen, dwlpmszLen, lpmszPossibleNodes);
  1325. *ppOutputBuf = pGumBuffer;
  1326. FnExit:
  1327. if (lpmszPossibleNodes) LocalFree(lpmszPossibleNodes);
  1328. if (hResTypeKey)
  1329. DmCloseKey(hResTypeKey);
  1330. if (lpmszCurrentPossibleNodes)
  1331. LocalFree(lpmszCurrentPossibleNodes);
  1332. if(TypeName)
  1333. LocalFree(TypeName);
  1334. return(dwStatus);
  1335. }
  1336. /****
  1337. @func DWORD | FmpUpdateChangeResourceNode| This update is called to
  1338. update the possible nodes for a resource.
  1339. @parm IN BOOL | SourceNode | set to TRUE, if the update originated at this
  1340. node.
  1341. @parm IN PFM_RESOURCE | pResource | A pointer to the resource whose
  1342. possible node list is being updated.
  1343. @parm IN PNM_NODE | pNode | A pointer to the node to be added/removed
  1344. from the possible node lis.
  1345. @parm IN DWORD | dwControlCode | If CLUSCTL_RESOURCE_ADD_OWNER then
  1346. the node is added to the possible node list, else it is removed.
  1347. @comm The possible list of nodes for a resource is updated.
  1348. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1349. ****/
  1350. DWORD
  1351. FmpUpdateChangeResourceNode(
  1352. IN BOOL SourceNode,
  1353. IN PFM_RESOURCE pResource,
  1354. IN PNM_NODE pNode,
  1355. IN DWORD dwControlCode
  1356. )
  1357. {
  1358. DWORD dwStatus;
  1359. HDMKEY hResKey = NULL;
  1360. HLOCALXSACTION hXsaction = NULL;
  1361. //Dont acquire the local resource lock since acquiring that
  1362. //within gum updates causes deadlock
  1363. //use the global resource lock to synchronize this call
  1364. //with the enumeration of possible nodes
  1365. FmpAcquireResourceLock();
  1366. //start a transaction
  1367. hXsaction = DmBeginLocalUpdate();
  1368. if (!hXsaction)
  1369. {
  1370. dwStatus = GetLastError();
  1371. goto FnExit;
  1372. }
  1373. if (dwControlCode == CLUSCTL_RESOURCE_ADD_OWNER)
  1374. {
  1375. dwStatus = FmpAddPossibleNode(pResource,
  1376. pNode);
  1377. } else
  1378. {
  1379. dwStatus = FmpRemovePossibleNode(pResource,
  1380. pNode,
  1381. FALSE);
  1382. }
  1383. if (dwStatus != ERROR_SUCCESS)
  1384. {
  1385. ClRtlLogPrint( LOG_NOISE,
  1386. "[FM] FmpUpdateChangeResourceNode, failed possible node updatefor resource <%1!ws!>, error %2!u!\n",
  1387. OmObjectName(pResource),
  1388. dwStatus );
  1389. goto FnExit;
  1390. }
  1391. //fix the registry
  1392. //SS - do we need to fix the preferred node list
  1393. hResKey = DmOpenKey(DmResourcesKey,
  1394. OmObjectId(pResource),
  1395. KEY_READ | KEY_WRITE);
  1396. if (hResKey == NULL)
  1397. {
  1398. dwStatus = GetLastError();
  1399. goto FnExit;
  1400. }
  1401. if (dwControlCode == CLUSCTL_RESOURCE_ADD_OWNER)
  1402. {
  1403. dwStatus = DmLocalAppendToMultiSz(
  1404. hXsaction,
  1405. hResKey,
  1406. CLUSREG_NAME_RES_POSSIBLE_OWNERS,
  1407. OmObjectId(pNode));
  1408. }
  1409. else
  1410. {
  1411. dwStatus = DmLocalRemoveFromMultiSz(
  1412. hXsaction,
  1413. hResKey,
  1414. CLUSREG_NAME_RES_POSSIBLE_OWNERS,
  1415. OmObjectId(pNode));
  1416. if (dwStatus == ERROR_FILE_NOT_FOUND)
  1417. {
  1418. DWORD i;
  1419. DWORD Result;
  1420. PNM_NODE pEnumNode;
  1421. //
  1422. // Possible nodes did not exist, so create a new entry
  1423. // with every possible node in it. FM will already have
  1424. // removed the passed in node from the possible node list.
  1425. //
  1426. i=0;
  1427. do {
  1428. Result = FmEnumResourceNode(pResource,
  1429. i,
  1430. &pEnumNode);
  1431. if (Result == ERROR_SUCCESS)
  1432. {
  1433. dwStatus = DmLocalAppendToMultiSz(
  1434. hXsaction,
  1435. hResKey,
  1436. CLUSREG_NAME_RES_POSSIBLE_OWNERS,
  1437. OmObjectId(pEnumNode));
  1438. OmDereferenceObject(pEnumNode);
  1439. }
  1440. else if ((Result == ERROR_NO_MORE_ITEMS) &&
  1441. (i == 0))
  1442. {
  1443. //
  1444. // This is a funny corner case where there is a one
  1445. // node cluster and a resource with no possibleowners
  1446. // entry, and somebody removes the only node in the cluster
  1447. // from the possible owners list. Set PossibleOwners to
  1448. // the empty set.
  1449. //
  1450. dwStatus = DmLocalSetValue(
  1451. hXsaction,
  1452. hResKey,
  1453. CLUSREG_NAME_RES_POSSIBLE_OWNERS,
  1454. REG_MULTI_SZ,
  1455. (CONST BYTE *)L"\0",
  1456. 2);
  1457. }
  1458. ++i;
  1459. } while ( Result == ERROR_SUCCESS );
  1460. //map the error to success
  1461. dwStatus = ERROR_SUCCESS;
  1462. }
  1463. }
  1464. DmCloseKey(hResKey);
  1465. FnExit:
  1466. //release the lock
  1467. FmpReleaseResourceLock();
  1468. if (dwStatus == ERROR_SUCCESS)
  1469. {
  1470. //commit the update on the old log file,
  1471. //any nodes that were done, will get this change
  1472. //I cant delete this file
  1473. DmCommitLocalUpdate(hXsaction);
  1474. }
  1475. else
  1476. {
  1477. //SS: BUGBUG :: validation for possible node should
  1478. //be done before the registry is switched
  1479. //the inmemory structure should be changed only on success
  1480. //if there is a failure in the registry apis..the
  1481. //in memory structure will be out of sync with registry
  1482. if (hXsaction) DmAbortLocalUpdate(hXsaction);
  1483. }
  1484. return(dwStatus);
  1485. }
  1486. /****
  1487. @func DWORD | FmpUpdateChangeResourceGroup| This update is called to
  1488. update the group to which the resource belongs.
  1489. @parm IN BOOL | bSourceNode | set to TRUE, if the update originated at this
  1490. node.
  1491. @parm IN PFM_RESOURCE | pResource | A pointer to the resource whose
  1492. possible node list is being updated.
  1493. @parm IN PFM_GROUP | pNewGroup | A pointer to the node to be added/removed
  1494. from the possible node lis.
  1495. @comm The possible list of nodes for a resource is updated.
  1496. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1497. ****/
  1498. DWORD FmpUpdateChangeResourceGroup(
  1499. IN BOOL bSourceNode,
  1500. IN PFM_RESOURCE pResource,
  1501. IN PFM_GROUP pNewGroup)
  1502. {
  1503. DWORD dwStatus = ERROR_SUCCESS;
  1504. PFM_GROUP pOldGroup;
  1505. PFM_DEPENDENCY_TREE pTree = NULL;
  1506. HLOCALXSACTION hXsaction = NULL;
  1507. HDMKEY hOldGroupKey = NULL;
  1508. HDMKEY hNewGroupKey = NULL;
  1509. PLIST_ENTRY pListEntry;
  1510. PFM_DEPENDTREE_ENTRY pEntry;
  1511. pOldGroup = pResource->Group;
  1512. //
  1513. // Check to make sure the resource is not already in the group.
  1514. //
  1515. if (pOldGroup == pNewGroup)
  1516. {
  1517. dwStatus = ERROR_ALREADY_EXISTS;
  1518. goto FnExit;
  1519. }
  1520. //
  1521. // Synchronize both the old and the new groups.
  1522. // Lock the lowest by lowest Group Id first - to prevent deadlocks!
  1523. // Note - the order of release is unimportant.
  1524. //
  1525. // strictly, the comparison below cannot be equal!
  1526. //
  1527. if ( lstrcmpiW( OmObjectId( pOldGroup ), OmObjectId( pNewGroup ) ) <= 0 )
  1528. {
  1529. FmpAcquireLocalGroupLock( pOldGroup );
  1530. FmpAcquireLocalGroupLock( pNewGroup );
  1531. }
  1532. else
  1533. {
  1534. FmpAcquireLocalGroupLock( pNewGroup );
  1535. FmpAcquireLocalGroupLock( pOldGroup );
  1536. }
  1537. //start a transaction
  1538. hXsaction = DmBeginLocalUpdate();
  1539. if (!hXsaction)
  1540. {
  1541. dwStatus = GetLastError();
  1542. goto FnUnlock;
  1543. }
  1544. //
  1545. // For now... both Groups must be owned by the same node.
  1546. //
  1547. if ( pResource->Group->OwnerNode != pNewGroup->OwnerNode )
  1548. {
  1549. dwStatus = ERROR_HOST_NODE_NOT_GROUP_OWNER;
  1550. goto FnUnlock;
  1551. }
  1552. //
  1553. // Create a full dependency tree,
  1554. //
  1555. pTree = FmCreateFullDependencyTree(pResource);
  1556. if ( pTree == NULL )
  1557. {
  1558. dwStatus = GetLastError();
  1559. goto FnUnlock;
  1560. }
  1561. //
  1562. // Add each resource in the dependency tree to its new group's list.
  1563. //
  1564. hNewGroupKey = DmOpenKey(DmGroupsKey,
  1565. OmObjectId(pNewGroup),
  1566. KEY_READ | KEY_WRITE);
  1567. if (hNewGroupKey == NULL) {
  1568. dwStatus = GetLastError();
  1569. goto FnUnlock;
  1570. }
  1571. hOldGroupKey = DmOpenKey(DmGroupsKey,
  1572. OmObjectId(pOldGroup),
  1573. KEY_READ | KEY_WRITE);
  1574. if (hOldGroupKey == NULL) {
  1575. dwStatus = GetLastError();
  1576. goto FnUnlock;
  1577. }
  1578. //
  1579. // For each resource in the dependency tree, remove it from the
  1580. // old group list and add it to the new group list
  1581. //
  1582. pListEntry = pTree->ListHead.Flink;
  1583. while (pListEntry != &pTree->ListHead) {
  1584. pEntry = CONTAINING_RECORD(pListEntry,
  1585. FM_DEPENDTREE_ENTRY,
  1586. ListEntry);
  1587. pListEntry = pListEntry->Flink;
  1588. dwStatus = DmLocalRemoveFromMultiSz(hXsaction,
  1589. hOldGroupKey,
  1590. CLUSREG_NAME_GRP_CONTAINS,
  1591. OmObjectId(pEntry->Resource));
  1592. if (dwStatus != ERROR_SUCCESS) {
  1593. goto FnUnlock;
  1594. }
  1595. dwStatus = DmLocalAppendToMultiSz(hXsaction,
  1596. hNewGroupKey,
  1597. CLUSREG_NAME_GRP_CONTAINS,
  1598. OmObjectId(pEntry->Resource));
  1599. if (dwStatus != ERROR_SUCCESS) {
  1600. goto FnUnlock;
  1601. }
  1602. }
  1603. //
  1604. // Passed all the checks, do the in-memorymove.
  1605. //
  1606. pListEntry = pTree->ListHead.Flink;
  1607. while (pListEntry != &pTree->ListHead)
  1608. {
  1609. pEntry = CONTAINING_RECORD(pListEntry,
  1610. FM_DEPENDTREE_ENTRY,
  1611. ListEntry);
  1612. pListEntry = pListEntry->Flink;
  1613. //
  1614. // Move this resource
  1615. //
  1616. RemoveEntryList(&pEntry->Resource->ContainsLinkage);
  1617. InsertHeadList(&pNewGroup->Contains,
  1618. &pEntry->Resource->ContainsLinkage);
  1619. OmReferenceObject(pNewGroup);
  1620. pEntry->Resource->Group = pNewGroup;
  1621. ++pEntry->Resource->StateSequence;
  1622. ClusterEvent(CLUSTER_EVENT_RESOURCE_CHANGE,pEntry->Resource);
  1623. OmDereferenceObject(pOldGroup);
  1624. }
  1625. FnUnlock:
  1626. //
  1627. // Now release all locks.
  1628. //
  1629. FmpReleaseLocalGroupLock( pNewGroup );
  1630. FmpReleaseLocalGroupLock( pOldGroup );
  1631. FnExit:
  1632. if (pTree) FmDestroyFullDependencyTree(pTree);
  1633. if (hOldGroupKey) DmCloseKey(hOldGroupKey);
  1634. if (hNewGroupKey) DmCloseKey(hNewGroupKey);
  1635. if (dwStatus == ERROR_SUCCESS)
  1636. {
  1637. ClusterEvent(CLUSTER_EVENT_GROUP_PROPERTY_CHANGE,pNewGroup);
  1638. ClusterEvent(CLUSTER_EVENT_GROUP_PROPERTY_CHANGE,pOldGroup);
  1639. DmCommitLocalUpdate(hXsaction);
  1640. }
  1641. else
  1642. {
  1643. if (hXsaction) DmAbortLocalUpdate(hXsaction);
  1644. }
  1645. return(dwStatus);
  1646. }
  1647. DWORD
  1648. FmpUpdateAddDependency(
  1649. IN BOOL SourceNode,
  1650. IN LPCWSTR ResourceId,
  1651. IN LPCWSTR DependsOnId
  1652. )
  1653. /*++
  1654. Routine Description:
  1655. GUM dispatch routine for adding a dependency
  1656. Arguments:
  1657. SourceNode - Supplies whether or not this node initiated the GUM update.
  1658. Not used.
  1659. ResourceId - Supplies the resource ID of the resource that should have a
  1660. dependency added.
  1661. DependsOnId - Supplies the resource ID of the resource that should provide
  1662. for ResourceId.
  1663. Return Value:
  1664. ERROR_SUCCESS if successful.
  1665. Win32 error code otherwise.
  1666. --*/
  1667. {
  1668. PFM_RESOURCE Resource;
  1669. PFM_RESOURCE DependsOn;
  1670. PDEPENDENCY dependency;
  1671. //
  1672. // Chittur Subbaraman (chitturs) - 4/18/99
  1673. //
  1674. // If FM groups are not fully initialized or FM is shutting down, then
  1675. // don't do anything.
  1676. //
  1677. if ( !FmpFMGroupsInited ||
  1678. FmpShutdown ) {
  1679. return(ERROR_SUCCESS);
  1680. }
  1681. dependency = LocalAlloc(LMEM_FIXED, sizeof(DEPENDENCY));
  1682. if (dependency == NULL) {
  1683. CsInconsistencyHalt( ERROR_NOT_ENOUGH_MEMORY );
  1684. return(ERROR_NOT_ENOUGH_MEMORY);
  1685. }
  1686. Resource = OmReferenceObjectById(ObjectTypeResource,
  1687. ResourceId);
  1688. if (Resource == NULL) {
  1689. CL_LOGFAILURE( ERROR_RESOURCE_NOT_FOUND );
  1690. LocalFree(dependency);
  1691. return(ERROR_RESOURCE_NOT_FOUND);
  1692. }
  1693. DependsOn = OmReferenceObjectById(ObjectTypeResource,
  1694. DependsOnId);
  1695. if (DependsOn == NULL) {
  1696. OmDereferenceObject(Resource);
  1697. LocalFree(dependency);
  1698. CL_LOGFAILURE( ERROR_DEPENDENCY_NOT_FOUND );
  1699. return(ERROR_DEPENDENCY_NOT_FOUND);
  1700. }
  1701. dependency->DependentResource = Resource;
  1702. dependency->ProviderResource = DependsOn;
  1703. FmpAcquireResourceLock();
  1704. InsertTailList( &DependsOn->ProvidesFor,
  1705. &dependency->ProviderLinkage );
  1706. InsertTailList( &Resource->DependsOn,
  1707. &dependency->DependentLinkage );
  1708. FmpReleaseResourceLock();
  1709. ClusterEvent( CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE,
  1710. Resource );
  1711. //SS: we leave the reference counts on both the objects
  1712. //as a dependency referrring to them has been created.
  1713. return(ERROR_SUCCESS);
  1714. } // FmpUpdateAddDependency
  1715. DWORD
  1716. FmpUpdateRemoveDependency(
  1717. IN BOOL SourceNode,
  1718. IN LPCWSTR ResourceId,
  1719. IN LPCWSTR DependsOnId
  1720. )
  1721. /*++
  1722. Routine Description:
  1723. GUM dispatch routine for adding a dependency
  1724. Arguments:
  1725. SourceNode - Supplies whether or not this node initiated the GUM update.
  1726. Not used.
  1727. ResourceId - Supplies the resource ID of the resource that should have a
  1728. dependency removed.
  1729. DependsOnId - Supplies the resource ID of the resource that provides
  1730. for ResourceId.
  1731. Return Value:
  1732. ERROR_SUCCESS if successful.
  1733. Win32 error code otherwise.
  1734. --*/
  1735. {
  1736. PFM_RESOURCE Resource;
  1737. PFM_RESOURCE DependsOn;
  1738. PDEPENDENCY dependency;
  1739. PLIST_ENTRY ListEntry;
  1740. DWORD Status=ERROR_SUCCESS;
  1741. //
  1742. // Chittur Subbaraman (chitturs) - 4/18/99
  1743. //
  1744. // If FM groups are not fully initialized or FM is shutting down, then
  1745. // don't do anything.
  1746. //
  1747. if ( !FmpFMGroupsInited ||
  1748. FmpShutdown ) {
  1749. return(ERROR_SUCCESS);
  1750. }
  1751. Resource = OmReferenceObjectById(ObjectTypeResource,
  1752. ResourceId);
  1753. if (Resource == NULL) {
  1754. CL_LOGFAILURE( ERROR_RESOURCE_NOT_FOUND );
  1755. return(ERROR_RESOURCE_NOT_FOUND);
  1756. }
  1757. DependsOn = OmReferenceObjectById(ObjectTypeResource,
  1758. DependsOnId);
  1759. if (DependsOn == NULL) {
  1760. OmDereferenceObject(Resource);
  1761. CL_LOGFAILURE( ERROR_RESOURCE_NOT_FOUND );
  1762. return(ERROR_RESOURCE_NOT_FOUND);
  1763. }
  1764. //
  1765. // Walk through the dependency list of the resource searching
  1766. // for a match.
  1767. //
  1768. FmpAcquireResourceLock();
  1769. ListEntry = Resource->DependsOn.Flink;
  1770. while (ListEntry != &Resource->DependsOn) {
  1771. dependency = CONTAINING_RECORD(ListEntry,
  1772. DEPENDENCY,
  1773. DependentLinkage);
  1774. CL_ASSERT(dependency->DependentResource == Resource);
  1775. if (dependency->ProviderResource == DependsOn) {
  1776. //
  1777. // Found a match. Remove it from its list and
  1778. // free it up.
  1779. //
  1780. RemoveEntryList(&dependency->ProviderLinkage);
  1781. RemoveEntryList(&dependency->DependentLinkage);
  1782. // dereference the providor and dependent resource
  1783. OmDereferenceObject(dependency->DependentResource);
  1784. OmDereferenceObject(dependency->ProviderResource);
  1785. LocalFree(dependency);
  1786. break;
  1787. }
  1788. ListEntry = ListEntry->Flink;
  1789. }
  1790. FmpReleaseResourceLock();
  1791. if (ListEntry != &Resource->DependsOn) {
  1792. //
  1793. // A match was found. Dereference the provider resource
  1794. // to account for the dependency removal and return success.
  1795. //
  1796. ClusterEvent( CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE,
  1797. Resource );
  1798. Status = ERROR_SUCCESS;
  1799. } else {
  1800. Status = ERROR_DEPENDENCY_NOT_FOUND;
  1801. }
  1802. //SS: dereference the objects earlier referenced
  1803. OmDereferenceObject(Resource);
  1804. OmDereferenceObject(DependsOn);
  1805. return(Status);
  1806. } // FmpUpdateRemoveDependency
  1807. DWORD
  1808. FmpUpdateDeleteGroup(
  1809. IN BOOL SourceNode,
  1810. IN LPCWSTR GroupId
  1811. )
  1812. /*++
  1813. Routine Description:
  1814. GUM dispatch routine for deleting a group.
  1815. Arguments:
  1816. SourceNode - Supplies whether or not this node initiated the GUM update.
  1817. Not used.
  1818. GroupId - Supplies the group ID.
  1819. Return Value:
  1820. ERROR_SUCCESS if successful.
  1821. Win32 error code otherwise.
  1822. --*/
  1823. {
  1824. DWORD dwStatus = ERROR_SUCCESS;
  1825. PFM_GROUP pGroup = NULL;
  1826. PLIST_ENTRY listEntry;
  1827. PPREFERRED_ENTRY preferredEntry;
  1828. BOOL bLocked = FALSE;
  1829. //
  1830. // Chittur Subbaraman (chitturs) - 4/18/99
  1831. //
  1832. // If FM groups are not fully initialized or FM is shutting down, then
  1833. // don't do anything.
  1834. //
  1835. if ( !FmpFMGroupsInited ||
  1836. FmpShutdown ) {
  1837. return(ERROR_SUCCESS);
  1838. }
  1839. //
  1840. // Find the specified Group.
  1841. //
  1842. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  1843. GroupId );
  1844. if ( pGroup == NULL ) {
  1845. dwStatus = ERROR_GROUP_NOT_FOUND;
  1846. return(dwStatus);
  1847. }
  1848. ClRtlLogPrint(LOG_NOISE,
  1849. "[FM] DeleteGroup %1!ws!, address = %2!lx!.\n",
  1850. OmObjectId(pGroup),
  1851. pGroup );
  1852. //
  1853. // Chittur Subbaraman (chitturs) - 1/12/99
  1854. //
  1855. // Try to acquire lock, and make sure the Contains list is empty.
  1856. //
  1857. // Most of the calls to manipulate groups make calls to the owner
  1858. // node of the group and this operation is serialized by GUM. So,
  1859. // there is no major danger if we do the operations in this function
  1860. // without holding the group lock. However, we can't rule out
  1861. // corruption 100% as of now.
  1862. //
  1863. // If you block within the GUM handler here, then no events in
  1864. // the cluster proceed forward and things come to a grinding halt.
  1865. //
  1866. // A case in point:
  1867. // (1) Thread 1 (the thread that calls this function) grabs the
  1868. // GUM lock and waits for the group lock.
  1869. // (2) Thread 2 (FmWorkerThread) grabs the group lock and calls
  1870. // resmon attempting to close a resource. It gets blocked on
  1871. // the resmon eventlist lock.
  1872. // (3) Thread 3 calls RmResourceControl to set the resource name
  1873. // which grabs the resmon eventlist lock and then in turn calls
  1874. // ClusterRegSetValue and then gets blocked on the GUM lock.
  1875. //
  1876. FmpTryAcquireLocalGroupLock( pGroup, bLocked );
  1877. if ( !IsListEmpty( &pGroup->Contains ) )
  1878. {
  1879. dwStatus = ERROR_DIR_NOT_EMPTY;
  1880. goto FnExit;
  1881. }
  1882. //
  1883. // Close the Group's registry key.
  1884. //
  1885. DmRundownList( &pGroup->DmRundownList );
  1886. if ( pGroup->RegistryKey != NULL ) {
  1887. DmCloseKey( pGroup->RegistryKey );
  1888. pGroup->RegistryKey = NULL;
  1889. }
  1890. //
  1891. // Remove from the node list
  1892. //
  1893. dwStatus = OmRemoveObject( pGroup );
  1894. ClusterEvent( CLUSTER_EVENT_GROUP_DELETED, pGroup );
  1895. //
  1896. // This dereference would normally cause the group to eventually disappear,
  1897. // however the event notification above will keep a ref on the object
  1898. // until all notifications have been delivered.
  1899. //
  1900. OmDereferenceObject( pGroup );
  1901. //
  1902. // Make sure the preferred owners list is drained.
  1903. //
  1904. while ( !IsListEmpty( &pGroup->PreferredOwners ) ) {
  1905. listEntry = RemoveHeadList(&pGroup->PreferredOwners);
  1906. preferredEntry = CONTAINING_RECORD( listEntry,
  1907. PREFERRED_ENTRY,
  1908. PreferredLinkage );
  1909. OmDereferenceObject( preferredEntry->PreferredNode );
  1910. LocalFree( preferredEntry );
  1911. }
  1912. //
  1913. // Free the string associated with the AntiAffinityClassName field.
  1914. //
  1915. LocalFree ( pGroup->lpszAntiAffinityClassName );
  1916. pGroup->dwStructState |= FM_GROUP_STRUCT_MARKED_FOR_DELETE;
  1917. FnExit:
  1918. if( bLocked )
  1919. {
  1920. FmpReleaseLocalGroupLock( pGroup );
  1921. }
  1922. //
  1923. // Dereference for reference above.
  1924. //
  1925. if (pGroup) OmDereferenceObject( pGroup );
  1926. return(dwStatus);
  1927. } // FmpUpdateDeleteGroup
  1928. /****
  1929. @func DWORD | FmpUpdateGroupIntendedOwner| This update is called on
  1930. a move just before the source node requests the target node
  1931. to take over the group.
  1932. @parm IN BOOL | bSourceNode | set to TRUE, if the update originated at
  1933. this
  1934. node.
  1935. @parm IN PFM_GROUP | pszGroupId | The ID of the group that is about
  1936. to move.
  1937. @parm IN PDWORD | pdwNodeId| A pointer to a DWORD that contains the
  1938. ID of the node that is the destination of this move. It is
  1939. set to ClusterInvalidNodeId by the destination node when it has
  1940. accepted the group.
  1941. @comm The purpose of this update is to let all nodes know that a move
  1942. is impending. If the source node dies while a move is in progress
  1943. then preference is given to the target of the move rather than the
  1944. node that is chosen by the FmpUpdateAssignOwnerToGroups
  1945. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1946. ****/
  1947. DWORD
  1948. FmpUpdateGroupIntendedOwner(
  1949. IN BOOL SourceNode,
  1950. IN LPCWSTR pszGroupId,
  1951. IN PDWORD pdwNodeId
  1952. )
  1953. {
  1954. PFM_GROUP pGroup = NULL;
  1955. DWORD dwStatus = ERROR_SUCCESS;
  1956. PNM_NODE pNode = NULL;
  1957. PNM_NODE pPrevNode;
  1958. WCHAR pszNodeId[6];
  1959. if ( !FmpFMGroupsInited )
  1960. {
  1961. return(ERROR_SUCCESS);
  1962. }
  1963. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  1964. pszGroupId );
  1965. if (pGroup == NULL)
  1966. {
  1967. dwStatus = ERROR_GROUP_NOT_FOUND;
  1968. goto FnExit;
  1969. }
  1970. if (*pdwNodeId != ClusterInvalidNodeId)
  1971. {
  1972. wsprintfW(pszNodeId, L"%u", *pdwNodeId);
  1973. pNode = OmReferenceObjectById(ObjectTypeNode,
  1974. pszNodeId);
  1975. if (pNode == NULL)
  1976. {
  1977. dwStatus = ERROR_CLUSTER_NODE_NOT_FOUND;
  1978. goto FnExit;
  1979. }
  1980. } else if (pGroup->pIntendedOwner == NULL)
  1981. {
  1982. dwStatus = ERROR_CLUSTER_INVALID_NODE;
  1983. ClRtlLogPrint(LOG_NOISE,
  1984. "[FM] FmpUpdateGroupIntendedOwner: Group <%1!ws!> intended owner is already invalid, not setting....\n",
  1985. pszGroupId);
  1986. goto FnExit;
  1987. }
  1988. //
  1989. // HACKHACK: Chittur Subbaraman (chitturs) - 5/20/99
  1990. // Comment out as a temporary solution to avoid deadlocks.
  1991. //
  1992. // FmpAcquireLocalGroupLock(pGroup);
  1993. pPrevNode = pGroup->pIntendedOwner;
  1994. //set the new owner node, incr ref count
  1995. if (pNode) OmReferenceObject(pNode);
  1996. pGroup->pIntendedOwner = pNode;
  1997. //decr ref count on previous owner
  1998. if (pPrevNode) OmDereferenceObject(pPrevNode);
  1999. //
  2000. // HACKHACK: Chittur Subbaraman (chitturs) - 5/20/99
  2001. // Comment out as a temporary solution to avoid deadlocks.
  2002. //
  2003. // FmpReleaseLocalGroupLock(pGroup);
  2004. FnExit:
  2005. if (pGroup) OmDereferenceObject(pGroup);
  2006. if (pNode) OmDereferenceObject(pNode);
  2007. return(dwStatus);
  2008. }
  2009. /****
  2010. @func DWORD | FmpUpdateAssignOwnerToGroups| This update is made when
  2011. a node goes down to take ownership of all the orphaned groups.
  2012. @parm IN BOOL | bSourceNode | set to TRUE, if the update originated at
  2013. this
  2014. node.
  2015. @parm IN LPCWSTR | pszGroupId | The ID of the group that is about
  2016. to move.
  2017. @parm IN PDWORD | pdwNodeId| A pointer to a DWORD that contains the
  2018. ID of the node that is the destination of this move. It is
  2019. set to ClusterInvalidNodeId by the destination node when it has
  2020. accepted the group.
  2021. @comm The purpose of this update is to let all nodes know that a move
  2022. is impending. If the source node dies while a move is in progress
  2023. ,
  2024. then preference is given to the target of the move rather than the
  2025. node that is chosen by the FmpClaimNodeGroups algorithm.
  2026. @rdesc returns ERROR_SUCCESS.
  2027. ****/
  2028. DWORD
  2029. FmpUpdateAssignOwnerToGroups(
  2030. IN BOOL SourceNode,
  2031. IN LPCWSTR pszNodeId
  2032. )
  2033. {
  2034. PNM_NODE pNode = NULL;
  2035. DWORD dwStatus = ERROR_SUCCESS;
  2036. //
  2037. // Chittur Subbaraman (chitturs) - 4/18/99
  2038. //
  2039. // If FM groups are not fully initialized or FM is shutting down, then
  2040. // don't do anything.
  2041. //
  2042. if ( !FmpFMGroupsInited || FmpShutdown )
  2043. {
  2044. return(ERROR_SUCCESS);
  2045. }
  2046. pNode = OmReferenceObjectById( ObjectTypeNode,
  2047. pszNodeId );
  2048. if (!pNode)
  2049. {
  2050. ClRtlLogPrint(LOG_CRITICAL,
  2051. "[FM] FmpUpdateAssignOwnersToGroups, %1!ws! node not found\n",
  2052. pszNodeId);
  2053. //should we return failure here
  2054. //is evict of a node synchronized with everything
  2055. goto FnExit;
  2056. }
  2057. //if this update has already been seen after the node down
  2058. //ignore this one
  2059. if (gFmpNodeArray[NmGetNodeId(pNode)].dwNodeDownProcessingInProgress == 0)
  2060. {
  2061. ClRtlLogPrint(LOG_CRITICAL,
  2062. "[FM] FmpUpdateAssignOwnersToGroups, %1!ws! node down has been processed already\n",
  2063. pszNodeId);
  2064. goto FnExit;
  2065. }
  2066. //
  2067. // Assign ownership to all groups owned by the dead node
  2068. //
  2069. dwStatus = FmpAssignOwnersToGroups(pNode, NULL, NULL);
  2070. if (dwStatus != ERROR_SUCCESS)
  2071. {
  2072. ClRtlLogPrint(LOG_CRITICAL,
  2073. "[FM] FmpUpdateAssignOwnersToGroups failed %1!d!\n",
  2074. dwStatus);
  2075. }
  2076. //mark that the node down processing has been done
  2077. gFmpNodeArray[NmGetNodeId(pNode)].dwNodeDownProcessingInProgress = 0;
  2078. FnExit:
  2079. if (pNode) OmDereferenceObject(pNode);
  2080. return(dwStatus);
  2081. }
  2082. /****
  2083. @func DWORD | FmpUpdateApproveJoin| The joining node
  2084. makes this update call.
  2085. @parm IN BOOL | bSourceNode | set to TRUE, if the update originated at
  2086. this
  2087. node.
  2088. @parm IN LPCWSTR | pszGroupId | The ID of the group that is about
  2089. to move.
  2090. @parm IN PDWORD | pdwNodeId| A pointer to a DWORD that contains the
  2091. ID of the node that is the destination of this move. It is
  2092. set to ClusterInvalidNodeId by the destination node when it has
  2093. accepted the group.
  2094. @comm The purpose of this update is to let all nodes know that a move
  2095. is impending. If the source node dies while a move is in progress
  2096. ,
  2097. then preference is given to the target of the move rather than the
  2098. node that is chosen by the FmpClaimNodeGroups algorithm.
  2099. @rdesc returns ERROR_SUCCESS.
  2100. ****/
  2101. DWORD
  2102. FmpUpdateApproveJoin(
  2103. IN BOOL SourceNode,
  2104. IN LPCWSTR pszNodeId
  2105. )
  2106. {
  2107. PNM_NODE pNode = NULL;
  2108. DWORD dwStatus = ERROR_SUCCESS;
  2109. //
  2110. // Chittur Subbaraman (chitturs) - 4/18/99
  2111. //
  2112. // If FM groups are not fully initialized or FM is shutting down, then
  2113. // don't do anything.
  2114. //
  2115. if ( !FmpFMGroupsInited || FmpShutdown )
  2116. {
  2117. return(ERROR_SUCCESS);
  2118. }
  2119. pNode = OmReferenceObjectById( ObjectTypeNode,
  2120. pszNodeId );
  2121. if (!pNode)
  2122. {
  2123. ClRtlLogPrint(LOG_CRITICAL,
  2124. "[FM] FmpUpdateAssignOwnersToGroups, %1!ws! node not found\n",
  2125. pszNodeId);
  2126. //should we return failure here
  2127. //is evict of a node synchronized with everything
  2128. goto FnExit;
  2129. }
  2130. if (pNode == NmLocalNode)
  2131. {
  2132. // SS: can I become the locker now
  2133. // If so, there what do I do
  2134. //i approve of my own join
  2135. goto FnExit;
  2136. }
  2137. //if a node is trying to join before the processing
  2138. //for its last death has been completed, ask it to retry
  2139. if (gFmpNodeArray[NmGetNodeId(pNode)].dwNodeDownProcessingInProgress == 1)
  2140. {
  2141. ClRtlLogPrint(LOG_CRITICAL,
  2142. "[FM] FmpUpdateApproveJoin, %1!ws! node down hasnt been processed as yet\n",
  2143. pszNodeId);
  2144. dwStatus = ERROR_RETRY;
  2145. goto FnExit;
  2146. }
  2147. FnExit:
  2148. if (pNode) OmDereferenceObject(pNode);
  2149. return(dwStatus);
  2150. }
  2151. /****
  2152. @func DWORD | FmpUpdateCreateGroup | GUM update handler for creating
  2153. a group.
  2154. @parm IN OUT PGUM_CREATE_GROUP | pGumGroup | Buffer containing group info
  2155. @parm IN BOOL | bSourceNode | Indicates whether this call originated
  2156. from this node.
  2157. @comm This GUM update creates a group and is structured as a local
  2158. transaction so that both registry entries and in-memory
  2159. structures are updated consistently.
  2160. @rdesc Returns ERROR_SUCCESS on success. A Win32 error code otherwise.
  2161. ****/
  2162. DWORD
  2163. FmpUpdateCreateGroup(
  2164. IN OUT PGUM_CREATE_GROUP pGumGroup,
  2165. IN BOOL bSourceNode
  2166. )
  2167. {
  2168. DWORD dwStatus = ERROR_SUCCESS;
  2169. HDMKEY hKey = NULL;
  2170. DWORD dwDisposition;
  2171. HLOCALXSACTION
  2172. hXsaction = NULL;
  2173. LPCWSTR lpszNodeId = NULL;
  2174. PNM_NODE pNode = NULL;
  2175. DWORD dwGroupIdLen = 0;
  2176. DWORD dwGroupNameLen = 0;
  2177. LPWSTR lpszGroupId = NULL;
  2178. LPCWSTR lpszGroupName = NULL;
  2179. BOOL bLocked = FALSE;
  2180. //
  2181. // Chittur Subbaraman (chitturs) - 5/27/99
  2182. //
  2183. // Restructure this GUM update as a local transaction.
  2184. //
  2185. dwGroupIdLen = pGumGroup->GroupIdLen;
  2186. dwGroupNameLen = pGumGroup->GroupNameLen;
  2187. lpszGroupId = pGumGroup->GroupId;
  2188. lpszGroupName = (PWSTR)((PCHAR)lpszGroupId +
  2189. dwGroupIdLen );
  2190. ClRtlLogPrint(LOG_NOISE,
  2191. "[FM] FmpUpdateCreateGroup: Entry for group %1!ws!...\n",
  2192. lpszGroupId);
  2193. //
  2194. // Start a transaction
  2195. //
  2196. hXsaction = DmBeginLocalUpdate();
  2197. if ( !hXsaction )
  2198. {
  2199. dwStatus = GetLastError();
  2200. ClRtlLogPrint(LOG_UNUSUAL,
  2201. "[FM] FmpUpdateCreateGroup, Failed in starting a transaction for group %1!ws!, Status =%2!d!....\n",
  2202. lpszGroupId,
  2203. dwStatus);
  2204. return( dwStatus );
  2205. }
  2206. //
  2207. // Create the new group key.
  2208. //
  2209. hKey = DmLocalCreateKey( hXsaction,
  2210. DmGroupsKey,
  2211. lpszGroupId,
  2212. 0,
  2213. KEY_READ | KEY_WRITE,
  2214. NULL,
  2215. &dwDisposition );
  2216. if ( hKey == NULL )
  2217. {
  2218. dwStatus = GetLastError();
  2219. ClRtlLogPrint(LOG_UNUSUAL,
  2220. "[FM] FmpUpdateCreateGroup, Failed in creating the group key for group %1!ws!, Status =%2!d!....\n",
  2221. lpszGroupId,
  2222. dwStatus);
  2223. goto FnExit;
  2224. }
  2225. if ( dwDisposition != REG_CREATED_NEW_KEY )
  2226. {
  2227. ClRtlLogPrint(LOG_CRITICAL,
  2228. "[FM] FmpUpdateCreateGroup used GUID %1!ws! that already existed! This is impossible.\n",
  2229. lpszGroupId);
  2230. dwStatus = ERROR_ALREADY_EXISTS;
  2231. goto FnExit;
  2232. }
  2233. CL_ASSERT( dwDisposition == REG_CREATED_NEW_KEY );
  2234. //
  2235. // Set the group name in the registry
  2236. //
  2237. dwStatus = DmLocalSetValue( hXsaction,
  2238. hKey,
  2239. CLUSREG_NAME_GRP_NAME,
  2240. REG_SZ,
  2241. ( CONST BYTE * ) lpszGroupName,
  2242. ( lstrlenW( lpszGroupName ) + 1 ) *
  2243. sizeof( WCHAR ) );
  2244. if( dwStatus != ERROR_SUCCESS )
  2245. {
  2246. ClRtlLogPrint(LOG_CRITICAL,
  2247. "[FM] FmpUpdateCreateGroup: DmLocalSetValue for group %1!ws! fails, Status = %2!d!...\n",
  2248. lpszGroupId,
  2249. dwStatus);
  2250. goto FnExit;
  2251. }
  2252. //
  2253. // We really shouldn't be acquiring locks here... but
  2254. // we'll try anyway. If we fail, we must return an error
  2255. // because we have nothing to return.
  2256. //
  2257. FmpTryAcquireGroupLock( bLocked, 500 );
  2258. if ( !bLocked )
  2259. {
  2260. pGumGroup->Group = NULL;
  2261. dwStatus = ERROR_SHARING_VIOLATION;
  2262. goto FnExit;
  2263. }
  2264. pGumGroup->Group = FmpCreateGroup( lpszGroupId, TRUE );
  2265. if ( pGumGroup->Group == NULL )
  2266. {
  2267. dwStatus = GetLastError();
  2268. ClRtlLogPrint(LOG_UNUSUAL,
  2269. "[FM] FmpUpdateCreateGroup, FmpCreateFroup failed for group %1!ws!, Status =%2!d!....\n",
  2270. lpszGroupId,
  2271. dwStatus);
  2272. goto FnExit;
  2273. } else
  2274. {
  2275. if ( bSourceNode )
  2276. {
  2277. OmReferenceObject( pGumGroup->Group );
  2278. OmReferenceObject( NmLocalNode );
  2279. pNode = NmLocalNode;
  2280. } else {
  2281. lpszNodeId = (PWSTR)((PCHAR)lpszGroupId +
  2282. dwGroupIdLen +
  2283. dwGroupNameLen );
  2284. pNode = OmReferenceObjectById( ObjectTypeNode, lpszNodeId );
  2285. if ( pNode == NULL )
  2286. {
  2287. CL_LOGFAILURE( ERROR_CLUSTER_NODE_NOT_FOUND );
  2288. dwStatus = ERROR_CLUSTER_NODE_NOT_FOUND;
  2289. ClRtlLogPrint(LOG_UNUSUAL,
  2290. "[FM] FmpUpdateCreateGroup, Could not find node for group %1!ws!, Status =%2!d!....\n",
  2291. lpszGroupId,
  2292. dwStatus);
  2293. CsInconsistencyHalt( ERROR_CLUSTER_NODE_NOT_FOUND );
  2294. }
  2295. }
  2296. CL_ASSERT( pGumGroup->Group->OwnerNode == NULL );
  2297. if ( !FmpInPreferredList( pGumGroup->Group, pNode , FALSE, NULL) )
  2298. {
  2299. ClRtlLogPrint(LOG_UNUSUAL,
  2300. "[FM] FmpUpdateCreateGroup, node %1!ws! is not in preferred list for group %2!ws!.\n",
  2301. OmObjectId( pNode ),
  2302. OmObjectId( pGumGroup->Group ));
  2303. }
  2304. pGumGroup->Group->OwnerNode = pNode;
  2305. if ( OmSetObjectName( pGumGroup->Group, lpszGroupName ) != ERROR_SUCCESS )
  2306. {
  2307. ClRtlLogPrint(LOG_UNUSUAL,
  2308. "[FM] FmpUpdateCreateGroup, Cannot set name for group %1!ws!...\n",
  2309. OmObjectId( pGumGroup->Group ));
  2310. }
  2311. ClusterEvent( CLUSTER_EVENT_GROUP_ADDED, pGumGroup->Group );
  2312. }
  2313. FnExit:
  2314. if ( bLocked )
  2315. {
  2316. FmpReleaseGroupLock( );
  2317. }
  2318. if ( hKey != NULL )
  2319. {
  2320. DmCloseKey( hKey );
  2321. }
  2322. if ( ( dwStatus == ERROR_SUCCESS ) &&
  2323. ( hXsaction != NULL ) )
  2324. {
  2325. DmCommitLocalUpdate( hXsaction );
  2326. }
  2327. else
  2328. {
  2329. if ( hXsaction ) DmAbortLocalUpdate( hXsaction );
  2330. }
  2331. ClRtlLogPrint(LOG_NOISE,
  2332. "[FM] FmpUpdateCreateGroup: Exit for group %1!ws!, Status=%2!u!...\n",
  2333. lpszGroupId,
  2334. dwStatus);
  2335. return( dwStatus );
  2336. }
  2337. /****
  2338. @func DWORD | FmpUpdateCompleteGroupMove | This update is made when
  2339. FmpTakeGroupRequest fails with an RPC error.
  2340. @parm IN BOOL | bSourceNode | Set to TRUE, if the update originated at
  2341. this node. Not used.
  2342. @parm IN LPCWSTR | pszNodeId | The ID of the dead node.
  2343. @parm IN LPCWSTR | pszGroupId | The ID of the group which was in the
  2344. middle of the move.
  2345. @comm The purpose of this update is to let the ownership of the
  2346. group which was in the middle of the move determined consistently.
  2347. @rdesc Returns ERROR_SUCCESS.
  2348. ****/
  2349. DWORD
  2350. FmpUpdateCompleteGroupMove(
  2351. IN BOOL bSourceNode,
  2352. IN LPCWSTR pszNodeId,
  2353. IN LPCWSTR pszGroupId
  2354. )
  2355. {
  2356. PNM_NODE pNode = NULL;
  2357. PFM_GROUP pGroup = NULL;
  2358. DWORD dwStatus = ERROR_SUCCESS;
  2359. //
  2360. // Chittur Subbaraman (chitturs) - 4/2/2000
  2361. //
  2362. // If FM groups are not fully initialized, then don't do anything.
  2363. // Don't check for shutdown since we need to handle take group
  2364. // exceptions for the quorum group even during a shutdown.
  2365. //
  2366. if ( !FmpFMGroupsInited )
  2367. {
  2368. return( ERROR_SUCCESS );
  2369. }
  2370. pNode = OmReferenceObjectById( ObjectTypeNode,
  2371. pszNodeId );
  2372. if ( !pNode )
  2373. {
  2374. ClRtlLogPrint(LOG_CRITICAL,
  2375. "[FM] FmpUpdateCompleteGroupMove, %1!ws! node not found\n",
  2376. pszNodeId);
  2377. goto FnExit;
  2378. }
  2379. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  2380. pszGroupId );
  2381. if ( !pGroup )
  2382. {
  2383. ClRtlLogPrint(LOG_CRITICAL,
  2384. "[FM] FmpUpdateCompleteGroupMove, %1!ws! group not found\n",
  2385. pszGroupId);
  2386. goto FnExit;
  2387. }
  2388. //
  2389. // Assign ownership to this group which was in the middle of a move
  2390. //
  2391. dwStatus = FmpAssignOwnersToGroups( pNode, pGroup, NULL );
  2392. if ( dwStatus != ERROR_SUCCESS )
  2393. {
  2394. ClRtlLogPrint(LOG_CRITICAL,
  2395. "[FM] FmpUpdateCompleteGroupMove failed with error %1!d!\n",
  2396. dwStatus);
  2397. }
  2398. FnExit:
  2399. if ( pNode ) OmDereferenceObject( pNode );
  2400. if ( pGroup ) OmDereferenceObject( pGroup );
  2401. return( dwStatus );
  2402. }
  2403. DWORD
  2404. FmpUpdateCheckAndSetGroupOwner(
  2405. IN BOOL bSourceNode,
  2406. IN LPCWSTR lpszGroupId,
  2407. IN LPCWSTR lpszNodeId
  2408. )
  2409. /*++
  2410. Routine Description:
  2411. GUM update handler called from FmpTakeGroupRequest for NT5 cluster
  2412. to set the group owner ONLY IF its intended owner is the future
  2413. owner node.
  2414. Arguments:
  2415. bSourceNode - Supplies whether or not this node was the source of the update
  2416. lpszGroupId - Supplies the id of the resource whose state is changing
  2417. lpszNodeId - Supplies the node id of the group owner.
  2418. Return Value:
  2419. ERROR_SUCCESS if successful
  2420. Win32 error code otherwise
  2421. --*/
  2422. {
  2423. PFM_GROUP pGroup = NULL;
  2424. DWORD dwStatus = ERROR_SUCCESS;
  2425. PNM_NODE pNode = NULL;
  2426. PNM_NODE pPrevNode = NULL;
  2427. //dont check for shutdown - we cant afford to lose ownership notifications
  2428. //while we are shutting down
  2429. //since we dont destroy any fm structures - there shouldnt be a problem in
  2430. //handling these
  2431. if ( !FmpFMGroupsInited )
  2432. {
  2433. return( ERROR_SUCCESS );
  2434. }
  2435. ClRtlLogPrint(LOG_NOISE,
  2436. "[FM] FmpUpdateCheckAndSetGroupOwner: Entry for Group = <%1!ws!>....\n",
  2437. lpszGroupId);
  2438. //
  2439. // Chittur Subbaraman (chitturs) - 7/27/99
  2440. //
  2441. // This GUM handler sets the group ownership only if the future owner
  2442. // node is the group's intended owner. If the intended owner is NULL,
  2443. // it means the node down processing GUM handler has taken charge
  2444. // of this group. If the intended owner is not NULL and not the
  2445. // future owner node, then it means that the node down processing
  2446. // GUM handler has assigned ownership to the group and the group
  2447. // started moving to a different target before the FmpTakeGroupRequest
  2448. // that issued this GUM due as a part of the first move operation
  2449. // got a chance to execute. In both cases, lay your hands off the
  2450. // group.
  2451. //
  2452. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  2453. lpszGroupId );
  2454. if ( pGroup == NULL )
  2455. {
  2456. ClRtlLogPrint(LOG_ERROR,
  2457. "[FM] FmpUpdateCheckAndSetGroupOwner: GroupID = %1!ws! could not be found...\n",
  2458. lpszGroupId);
  2459. dwStatus = ERROR_GROUP_NOT_FOUND;
  2460. goto FnExit;
  2461. }
  2462. pNode = OmReferenceObjectById( ObjectTypeNode,
  2463. lpszNodeId );
  2464. if ( pNode == NULL )
  2465. {
  2466. ClRtlLogPrint(LOG_ERROR,
  2467. "[FM] FmpUpdateCheckAndSetGroupOwner: NodeID = %1!ws! could not be found, Group = %2!ws!...\n",
  2468. lpszNodeId,
  2469. lpszGroupId);
  2470. dwStatus = ERROR_CLUSTER_NODE_NOT_FOUND;
  2471. goto FnExit;
  2472. }
  2473. if ( pGroup->pIntendedOwner != pNode )
  2474. {
  2475. ClRtlLogPrint(LOG_ERROR,
  2476. "[FM] FmpUpdateCheckAndSetGroupOwner: Group = <%1!ws!> intended owner is invalid, not setting group ownership...\n",
  2477. lpszGroupId);
  2478. dwStatus = ERROR_GROUP_NOT_AVAILABLE;
  2479. goto FnExit;
  2480. }
  2481. pPrevNode = pGroup->OwnerNode;
  2482. //
  2483. // Set the new owner node, incr ref count
  2484. //
  2485. OmReferenceObject( pNode );
  2486. pGroup->OwnerNode = pNode;
  2487. //
  2488. // Decrement the ref count on previous owner
  2489. //
  2490. OmDereferenceObject( pPrevNode );
  2491. //
  2492. // Generate an event to signify group owner node change
  2493. //
  2494. ClusterEvent( CLUSTER_EVENT_GROUP_CHANGE, pGroup );
  2495. FnExit:
  2496. if ( pGroup ) OmDereferenceObject( pGroup );
  2497. if ( pNode ) OmDereferenceObject( pNode );
  2498. ClRtlLogPrint(LOG_NOISE,
  2499. "[FM] FmpUpdateCheckAndSetGroupOwner: Exit for Group = <%1!ws!>, Status=%2!u!....\n",
  2500. lpszGroupId,
  2501. dwStatus);
  2502. return( dwStatus );
  2503. }
  2504. DWORD
  2505. FmpUpdateCreateResourceType(
  2506. IN PVOID Buffer
  2507. )
  2508. /*++
  2509. Routine Description:
  2510. GUM update handler called for creating a resource type. For
  2511. NT5.1 clusters, this GUM handler does both the registry and
  2512. in-memory updates as a local transaction.
  2513. Arguments:
  2514. Buffer - Buffer containing resource type information.
  2515. Return Value:
  2516. ERROR_SUCCESS if successful
  2517. Win32 error code otherwise
  2518. --*/
  2519. {
  2520. PFM_RESTYPE pResType = NULL;
  2521. LPWSTR lpszTypeName;
  2522. LPWSTR lpszDisplayName;
  2523. LPWSTR lpszDllName;
  2524. DWORD dwStatus = ERROR_SUCCESS;
  2525. DWORD dwLooksAlive;
  2526. DWORD dwIsAlive;
  2527. DWORD dwDllNameLen;
  2528. DWORD dwDisplayNameLen;
  2529. DWORD dwTypeNameLen;
  2530. DWORD dwClusterHighestVersion;
  2531. DWORD dwDisposition;
  2532. HLOCALXSACTION hXsaction = NULL;
  2533. HDMKEY hTypeKey = NULL;
  2534. //
  2535. // Chittur Subbaraman (chitturs) - 2/8/2000
  2536. //
  2537. // Rewrite this GUM handler as a local transaction (for NT5.1 only)
  2538. //
  2539. lpszTypeName = ( LPWSTR ) Buffer;
  2540. ClRtlLogPrint(LOG_NOISE,
  2541. "[FM] FmpUpdateCreateResourceType, Entry for resource type %1!ws!...\n",
  2542. lpszTypeName);
  2543. pResType = OmReferenceObjectById( ObjectTypeResType,
  2544. lpszTypeName );
  2545. if ( pResType )
  2546. {
  2547. dwStatus = ERROR_ALREADY_EXISTS;
  2548. ClRtlLogPrint(LOG_CRITICAL,
  2549. "[FM] FmpUpdateCreateResourceType, Resource type %1!ws! already exists, Status = %2!d!...\n",
  2550. lpszTypeName,
  2551. dwStatus);
  2552. OmDereferenceObject( pResType );
  2553. return( dwStatus );
  2554. }
  2555. dwTypeNameLen = ( lstrlenW( lpszTypeName ) + 1 ) * sizeof( WCHAR );
  2556. lpszDisplayName = ( LPWSTR ) ( ( PCHAR ) Buffer + dwTypeNameLen );
  2557. dwDisplayNameLen = ( lstrlenW( lpszDisplayName ) + 1 ) * sizeof( WCHAR );
  2558. lpszDllName = ( LPWSTR ) ( ( PCHAR ) Buffer +
  2559. dwTypeNameLen +
  2560. dwDisplayNameLen );
  2561. dwDllNameLen = ( lstrlenW( lpszDllName ) + 1 ) * sizeof( WCHAR );
  2562. NmGetClusterOperationalVersion( &dwClusterHighestVersion,
  2563. NULL,
  2564. NULL );
  2565. if ( CLUSTER_GET_MAJOR_VERSION( dwClusterHighestVersion ) <
  2566. NT51_MAJOR_VERSION )
  2567. {
  2568. goto skip_registry_updates;
  2569. }
  2570. dwLooksAlive = *( DWORD UNALIGNED * ) ( ( ( PCHAR ) Buffer +
  2571. dwTypeNameLen +
  2572. dwDisplayNameLen +
  2573. dwDllNameLen ) );
  2574. dwIsAlive = *( DWORD UNALIGNED * ) ( ( ( PCHAR ) Buffer +
  2575. dwTypeNameLen +
  2576. dwDisplayNameLen +
  2577. dwDllNameLen +
  2578. sizeof( DWORD ) ) );
  2579. //
  2580. // Start a transaction
  2581. //
  2582. hXsaction = DmBeginLocalUpdate();
  2583. if ( !hXsaction )
  2584. {
  2585. dwStatus = GetLastError();
  2586. ClRtlLogPrint(LOG_CRITICAL,
  2587. "[FM] FmpUpdateCreateResourceType, Failed in starting a transaction for resource type %1!ws!, Status =%2!d!....\n",
  2588. lpszTypeName,
  2589. dwStatus);
  2590. return( dwStatus );
  2591. }
  2592. hTypeKey = DmLocalCreateKey( hXsaction,
  2593. DmResourceTypesKey,
  2594. lpszTypeName,
  2595. 0,
  2596. KEY_READ | KEY_WRITE,
  2597. NULL,
  2598. &dwDisposition );
  2599. if ( hTypeKey == NULL )
  2600. {
  2601. dwStatus = GetLastError();
  2602. ClRtlLogPrint(LOG_CRITICAL,
  2603. "[FM] FmpUpdateCreateResourceType, Failed in creating the resource types key for resource type %1!ws!, Status =%2!d!....\n",
  2604. lpszTypeName,
  2605. dwStatus);
  2606. goto FnExit;
  2607. }
  2608. if ( dwDisposition != REG_CREATED_NEW_KEY )
  2609. {
  2610. dwStatus = ERROR_ALREADY_EXISTS;
  2611. ClRtlLogPrint(LOG_CRITICAL,
  2612. "[FM] FmpUpdateCreateResourceType, Duplicate resource types key exists for resource type %1!ws!, Status =%2!d!....\n",
  2613. lpszTypeName,
  2614. dwStatus);
  2615. goto FnExit;
  2616. }
  2617. dwStatus = DmLocalSetValue( hXsaction,
  2618. hTypeKey,
  2619. CLUSREG_NAME_RESTYPE_DLL_NAME,
  2620. REG_SZ,
  2621. ( CONST BYTE * )lpszDllName,
  2622. dwDllNameLen );
  2623. if ( dwStatus != ERROR_SUCCESS )
  2624. {
  2625. ClRtlLogPrint(LOG_CRITICAL,
  2626. "[FM] FmpUpdateCreateResourceType, Failed in setting the DLL name for resource type %1!ws!, Status =%2!d!....\n",
  2627. lpszTypeName,
  2628. dwStatus);
  2629. goto FnExit;
  2630. }
  2631. dwStatus = DmLocalSetValue( hXsaction,
  2632. hTypeKey,
  2633. CLUSREG_NAME_RESTYPE_IS_ALIVE,
  2634. REG_DWORD,
  2635. ( CONST BYTE * )&dwIsAlive,
  2636. sizeof( DWORD ) );
  2637. if ( dwStatus != ERROR_SUCCESS )
  2638. {
  2639. ClRtlLogPrint(LOG_CRITICAL,
  2640. "[FM] FmpUpdateCreateResourceType, Failed in setting the Is Alive interval for resource type %1!ws!, Status =%2!d!....\n",
  2641. lpszTypeName,
  2642. dwStatus);
  2643. goto FnExit;
  2644. }
  2645. dwStatus = DmLocalSetValue( hXsaction,
  2646. hTypeKey,
  2647. CLUSREG_NAME_RESTYPE_LOOKS_ALIVE,
  2648. REG_DWORD,
  2649. ( CONST BYTE * )&dwLooksAlive,
  2650. sizeof( DWORD ) );
  2651. if ( dwStatus != ERROR_SUCCESS )
  2652. {
  2653. ClRtlLogPrint(LOG_CRITICAL,
  2654. "[FM] FmpUpdateCreateResourceType, Failed in setting the Looks Alive interval for resource type %1!ws!, Status =%2!d!....\n",
  2655. lpszTypeName,
  2656. dwStatus);
  2657. goto FnExit;
  2658. }
  2659. dwStatus = DmLocalSetValue( hXsaction,
  2660. hTypeKey,
  2661. CLUSREG_NAME_RESTYPE_NAME,
  2662. REG_SZ,
  2663. ( CONST BYTE * )lpszDisplayName,
  2664. dwDisplayNameLen );
  2665. if ( dwStatus != ERROR_SUCCESS )
  2666. {
  2667. ClRtlLogPrint(LOG_CRITICAL,
  2668. "[FM] FmpUpdateCreateResourceType, Failed in setting the display name for resource type %1!ws!, Status =%2!d!....\n",
  2669. lpszTypeName,
  2670. dwStatus);
  2671. goto FnExit;
  2672. }
  2673. skip_registry_updates:
  2674. pResType = FmpCreateResType( lpszTypeName );
  2675. if ( pResType != NULL )
  2676. {
  2677. dwStatus = FmpRmLoadResTypeDll( pResType );
  2678. if ( dwStatus == ERROR_SUCCESS )
  2679. {
  2680. pResType->State = RESTYPE_STATE_LOADS;
  2681. } else
  2682. {
  2683. ClRtlLogPrint(LOG_NOISE,
  2684. "[FM] FmpUpdateCreateResourceType: Unable to load dll for resource type %1!ws!, Status=%2!u!...\n",
  2685. lpszTypeName,
  2686. dwStatus);
  2687. //
  2688. // Some nodes may not support this resource type. So, consider
  2689. // the loading failure as success. However, log the error.
  2690. //
  2691. dwStatus = ERROR_SUCCESS;
  2692. }
  2693. } else
  2694. {
  2695. dwStatus = GetLastError();
  2696. ClRtlLogPrint(LOG_NOISE,
  2697. "[FM] FmpUpdateCreateResourceType: Unable to create resource type %1!ws!, Status=%2!u!...\n",
  2698. lpszTypeName,
  2699. dwStatus);
  2700. }
  2701. FnExit:
  2702. if ( hTypeKey != NULL )
  2703. {
  2704. DmCloseKey( hTypeKey );
  2705. }
  2706. if ( ( dwStatus == ERROR_SUCCESS ) &&
  2707. ( hXsaction != NULL ) )
  2708. {
  2709. DmCommitLocalUpdate( hXsaction );
  2710. }
  2711. else
  2712. {
  2713. if ( hXsaction ) DmAbortLocalUpdate( hXsaction );
  2714. }
  2715. ClRtlLogPrint(LOG_NOISE,
  2716. "[FM] FmpUpdateCreateResourceType: Exit for resource type %1!ws!, Status=%2!u!...\n",
  2717. lpszTypeName,
  2718. dwStatus);
  2719. return( dwStatus );
  2720. }
  2721. DWORD
  2722. FmpUpdateCreateResource(
  2723. IN OUT PGUM_CREATE_RESOURCE pGumResource
  2724. )
  2725. {
  2726. /*++
  2727. Routine Description:
  2728. GUM update handler called for creating a resource. For
  2729. NT5.1 clusters, this GUM handler does both the registry and
  2730. in-memory updates as a local transaction.
  2731. Arguments:
  2732. pGumResource - Structure containing resource information.
  2733. Return Value:
  2734. ERROR_SUCCESS if successful
  2735. Win32 error code otherwise
  2736. --*/
  2737. DWORD dwStatus = ERROR_SUCCESS;
  2738. HDMKEY hResourceKey = NULL;
  2739. HDMKEY hGroupKey = NULL;
  2740. DWORD dwDisposition;
  2741. HLOCALXSACTION
  2742. hXsaction = NULL;
  2743. DWORD dwClusterHighestVersion;
  2744. PGUM_CREATE_RESOURCE GumResource;
  2745. LPWSTR lpszResourceId = NULL;
  2746. LPWSTR lpszResourceName = NULL;
  2747. LPWSTR lpszResourceType = NULL;
  2748. PFM_GROUP pGroup = NULL;
  2749. PFM_RESTYPE pResType = NULL;
  2750. DWORD dwpollIntervals = CLUSTER_RESOURCE_USE_DEFAULT_POLL_INTERVAL;
  2751. DWORD dwPersistentState = 0;
  2752. DWORD dwResourceTypeLen = 0;
  2753. DWORD dwFlags = 0;
  2754. HDMKEY hParamKey = NULL;
  2755. //
  2756. // Chittur Subbaraman (chitturs) - 1/30/2000
  2757. //
  2758. // Restructure this GUM update as a local transaction.
  2759. //
  2760. lpszResourceId = (LPWSTR)( (PCHAR) pGumResource->GroupId +
  2761. pGumResource->GroupIdLen );
  2762. lpszResourceName = (LPWSTR)( (PCHAR) pGumResource->GroupId +
  2763. pGumResource->GroupIdLen +
  2764. pGumResource->ResourceIdLen );
  2765. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  2766. pGumResource->GroupId );
  2767. if ( pGroup == NULL )
  2768. {
  2769. CL_LOGFAILURE( ERROR_GROUP_NOT_FOUND );
  2770. ClRtlLogPrint(LOG_CRITICAL,
  2771. "[FM] FmpUpdateCreateResource: Group for resource %1!ws! not found.\n",
  2772. lpszResourceId);
  2773. return( ERROR_GROUP_NOT_FOUND );
  2774. }
  2775. ClRtlLogPrint(LOG_NOISE,
  2776. "[FM] FmpUpdateCreateResource: Entry for resource %1!ws!...\n",
  2777. lpszResourceId);
  2778. //
  2779. // If we are dealing with the mixed mode cluster, don't bother to
  2780. // do these registry updates since the API layer would do it.
  2781. //
  2782. NmGetClusterOperationalVersion( &dwClusterHighestVersion,
  2783. NULL,
  2784. NULL );
  2785. if ( CLUSTER_GET_MAJOR_VERSION( dwClusterHighestVersion ) <
  2786. NT51_MAJOR_VERSION )
  2787. {
  2788. ClRtlLogPrint(LOG_NOISE,
  2789. "[FM] FmpUpdateCreateResource: Skipping registry updates for resource %1!ws!...\n",
  2790. lpszResourceId);
  2791. goto skip_registry_updates;
  2792. }
  2793. dwResourceTypeLen = *( DWORD UNALIGNED * )( (PCHAR) pGumResource->GroupId +
  2794. pGumResource->GroupIdLen +
  2795. pGumResource->ResourceIdLen +
  2796. (lstrlenW(lpszResourceName)+1) * sizeof(WCHAR) );
  2797. lpszResourceType = (LPWSTR)( (PCHAR) pGumResource->GroupId +
  2798. pGumResource->GroupIdLen +
  2799. pGumResource->ResourceIdLen +
  2800. (lstrlenW(lpszResourceName)+1) * sizeof(WCHAR) +
  2801. sizeof( DWORD ) );
  2802. dwFlags = *( DWORD UNALIGNED * )( (PCHAR) pGumResource->GroupId +
  2803. pGumResource->GroupIdLen +
  2804. pGumResource->ResourceIdLen +
  2805. (lstrlenW(lpszResourceName)+1) * sizeof(WCHAR) +
  2806. sizeof( DWORD ) +
  2807. dwResourceTypeLen );
  2808. //
  2809. // Start a transaction
  2810. //
  2811. hXsaction = DmBeginLocalUpdate();
  2812. if ( !hXsaction )
  2813. {
  2814. dwStatus = GetLastError();
  2815. ClRtlLogPrint(LOG_UNUSUAL,
  2816. "[FM] FmpUpdateCreateResource, Failed in starting a transaction for resource %1!ws!, Status =%2!d!....\n",
  2817. lpszResourceId,
  2818. dwStatus);
  2819. OmDereferenceObject( pGroup );
  2820. return( dwStatus );
  2821. }
  2822. //
  2823. // Create the new resources key.
  2824. //
  2825. hResourceKey = DmLocalCreateKey( hXsaction,
  2826. DmResourcesKey,
  2827. lpszResourceId,
  2828. 0,
  2829. KEY_READ | KEY_WRITE,
  2830. NULL,
  2831. &dwDisposition );
  2832. if ( hResourceKey == NULL )
  2833. {
  2834. dwStatus = GetLastError();
  2835. ClRtlLogPrint(LOG_UNUSUAL,
  2836. "[FM] FmpUpdateCreateResource, Failed in creating the resource key for resource %1!ws!, Status =%2!d!....\n",
  2837. lpszResourceId,
  2838. dwStatus);
  2839. goto FnExit;
  2840. }
  2841. if ( dwDisposition != REG_CREATED_NEW_KEY )
  2842. {
  2843. ClRtlLogPrint(LOG_CRITICAL,
  2844. "[FM] FmpUpdateCreateResource used GUID %1!ws! that already existed! This is impossible.\n",
  2845. lpszResourceId);
  2846. dwStatus = ERROR_ALREADY_EXISTS;
  2847. goto FnExit;
  2848. }
  2849. CL_ASSERT( dwDisposition == REG_CREATED_NEW_KEY );
  2850. //
  2851. // Set the resource name in the registry
  2852. //
  2853. dwStatus = DmLocalSetValue( hXsaction,
  2854. hResourceKey,
  2855. CLUSREG_NAME_RES_NAME,
  2856. REG_SZ,
  2857. (CONST BYTE *)lpszResourceName,
  2858. (lstrlenW(lpszResourceName)+1)*sizeof(WCHAR) );
  2859. if( dwStatus != ERROR_SUCCESS )
  2860. {
  2861. ClRtlLogPrint(LOG_CRITICAL,
  2862. "[FM] FmpUpdateCreateResource: DmLocalSetValue (resource name) for resource %1!ws! fails, Status = %2!d!...\n",
  2863. lpszResourceId,
  2864. dwStatus);
  2865. goto FnExit;
  2866. }
  2867. //
  2868. // Set the resource's type in the registry
  2869. // Note we reference the resource type and use its ID
  2870. // so that the case is correct.
  2871. //
  2872. pResType = OmReferenceObjectById( ObjectTypeResType, lpszResourceType );
  2873. CL_ASSERT( pResType != NULL );
  2874. dwStatus = DmLocalSetValue( hXsaction,
  2875. hResourceKey,
  2876. CLUSREG_NAME_RES_TYPE,
  2877. REG_SZ,
  2878. (CONST BYTE *) OmObjectId( pResType ),
  2879. (lstrlenW( lpszResourceType ) + 1 )*sizeof(WCHAR) );
  2880. OmDereferenceObject( pResType );
  2881. if ( dwStatus != ERROR_SUCCESS )
  2882. {
  2883. ClRtlLogPrint(LOG_CRITICAL,
  2884. "[FM] FmpUpdateCreateResource: DmLocalSetValue (resource type) for resource %1!ws! fails, Status = %2!d!...\n",
  2885. lpszResourceId,
  2886. dwStatus);
  2887. goto FnExit;
  2888. }
  2889. //
  2890. // Set the resource's poll intervals in the registry.
  2891. //
  2892. dwStatus = DmLocalSetValue( hXsaction,
  2893. hResourceKey,
  2894. CLUSREG_NAME_RES_LOOKS_ALIVE,
  2895. REG_DWORD,
  2896. (CONST BYTE *)&dwpollIntervals,
  2897. 4 );
  2898. if ( dwStatus != ERROR_SUCCESS )
  2899. {
  2900. ClRtlLogPrint(LOG_CRITICAL,
  2901. "[FM] FmpUpdateCreateResource: DmLocalSetValue (looks alive) for resource %1!ws! fails, Status = %2!d!...\n",
  2902. lpszResourceId,
  2903. dwStatus);
  2904. goto FnExit;
  2905. }
  2906. dwStatus = DmLocalSetValue( hXsaction,
  2907. hResourceKey,
  2908. CLUSREG_NAME_RES_IS_ALIVE,
  2909. REG_DWORD,
  2910. (CONST BYTE *)&dwpollIntervals,
  2911. 4);
  2912. if ( dwStatus != ERROR_SUCCESS )
  2913. {
  2914. ClRtlLogPrint(LOG_CRITICAL,
  2915. "[FM] FmpUpdateCreateResource: DmLocalSetValue (is alive) for resource %1!ws! fails, Status = %2!d!...\n",
  2916. lpszResourceId,
  2917. dwStatus);
  2918. goto FnExit;
  2919. }
  2920. //
  2921. // If this resource should be started in a separate monitor, set that
  2922. // parameter now.
  2923. //
  2924. if ( dwFlags & CLUSTER_RESOURCE_SEPARATE_MONITOR )
  2925. {
  2926. DWORD dwSeparateMonitor = 1;
  2927. dwStatus = DmLocalSetValue( hXsaction,
  2928. hResourceKey,
  2929. CLUSREG_NAME_RES_SEPARATE_MONITOR,
  2930. REG_DWORD,
  2931. (CONST BYTE *)&dwSeparateMonitor,
  2932. sizeof( dwSeparateMonitor ) );
  2933. if ( dwStatus != ERROR_SUCCESS)
  2934. {
  2935. ClRtlLogPrint(LOG_CRITICAL,
  2936. "[FM] FmpUpdateCreateResource: DmLocalSetValue (separate monitor) for resource %1!ws! fails, Status = %2!d!...\n",
  2937. lpszResourceId,
  2938. dwStatus);
  2939. goto FnExit;
  2940. }
  2941. }
  2942. //
  2943. // Create a Parameters key for the resource.
  2944. //
  2945. hParamKey = DmLocalCreateKey( hXsaction,
  2946. hResourceKey,
  2947. CLUSREG_KEYNAME_PARAMETERS,
  2948. 0,
  2949. KEY_READ,
  2950. NULL,
  2951. &dwDisposition );
  2952. if ( hParamKey == NULL )
  2953. {
  2954. dwStatus = GetLastError();
  2955. ClRtlLogPrint(LOG_CRITICAL,
  2956. "[FM] FmpUpdateCreateResource: DmLocalCreateKey (parameters) for resource %1!ws! fails, Status = %2!d!...\n",
  2957. lpszResourceId,
  2958. dwStatus);
  2959. CL_LOGFAILURE( dwStatus );
  2960. goto FnExit;
  2961. } else
  2962. {
  2963. DmCloseKey( hParamKey );
  2964. }
  2965. hGroupKey = DmOpenKey( DmGroupsKey,
  2966. OmObjectId(pGroup),
  2967. KEY_READ | KEY_WRITE);
  2968. if ( hGroupKey == NULL )
  2969. {
  2970. dwStatus = GetLastError();
  2971. ClRtlLogPrint(LOG_CRITICAL,
  2972. "[FM] FmpUpdateCreateResource: DmOpenKey (group key) for resource %1!ws! fails, Status = %2!d!...\n",
  2973. lpszResourceId,
  2974. dwStatus);
  2975. goto FnExit;
  2976. }
  2977. //
  2978. // Chittur Subbaraman (chitturs) - 5/25/99
  2979. //
  2980. // Make sure you set the persistent state of the resource to
  2981. // ClusterResourceOffline before you create the resource. If
  2982. // this is not done, if you create a resource in a group which
  2983. // is online, the group's persistent state value (i.e., 1 in
  2984. // this case) is inherited by the resource in FmpQueryResourceInfo
  2985. // (only the memory state is set and not the registry state and
  2986. // this was a problem as well) and if you move such a group to
  2987. // another node, it will bring the newly created resource online.
  2988. //
  2989. dwStatus = DmLocalSetValue( hXsaction,
  2990. hResourceKey,
  2991. CLUSREG_NAME_RES_PERSISTENT_STATE,
  2992. REG_DWORD,
  2993. ( CONST BYTE * )&dwPersistentState,
  2994. sizeof( DWORD ) );
  2995. if ( dwStatus != ERROR_SUCCESS )
  2996. {
  2997. ClRtlLogPrint(LOG_CRITICAL,
  2998. "[FM] FmpUpdateCreateResource: DmLocalSetValue (persistent state) for resource %1!ws! fails, Status = %2!d!...\n",
  2999. lpszResourceId,
  3000. dwStatus);
  3001. goto FnExit;
  3002. }
  3003. //
  3004. // Add the resource to the Contains value of the specified group.
  3005. //
  3006. dwStatus = DmLocalAppendToMultiSz( hXsaction,
  3007. hGroupKey,
  3008. CLUSREG_NAME_GRP_CONTAINS,
  3009. lpszResourceId );
  3010. if ( dwStatus != ERROR_SUCCESS )
  3011. {
  3012. ClRtlLogPrint(LOG_CRITICAL,
  3013. "[FM] FmpUpdateCreateResource: DmLocalAppendToMultiSz (contains key) for resource %1!ws! fails, Status = %2!d!...\n",
  3014. lpszResourceId,
  3015. dwStatus);
  3016. goto FnExit;
  3017. }
  3018. skip_registry_updates:
  3019. FmpAcquireResourceLock();
  3020. pGumResource->Resource = FmpCreateResource( pGroup,
  3021. lpszResourceId,
  3022. lpszResourceName,
  3023. FALSE );
  3024. if ( pGumResource->Resource == NULL )
  3025. {
  3026. dwStatus = GetLastError();
  3027. ClRtlLogPrint(LOG_CRITICAL,
  3028. "[FM] FmpUpdateCreateResource: FmpCreateResource for resource %1!ws! fails, Status = %2!d!...\n",
  3029. lpszResourceId,
  3030. dwStatus);
  3031. } else
  3032. {
  3033. ClusterEvent( CLUSTER_EVENT_GROUP_PROPERTY_CHANGE,
  3034. pGroup );
  3035. ClusterEvent( CLUSTER_EVENT_RESOURCE_ADDED,
  3036. pGumResource->Resource );
  3037. if ( pGumResource->Resource )
  3038. {
  3039. OmReferenceObject( pGumResource->Resource );
  3040. FmpPostWorkItem( FM_EVENT_RESOURCE_ADDED,
  3041. pGumResource->Resource,
  3042. 0 );
  3043. }
  3044. }
  3045. FmpReleaseResourceLock();
  3046. FnExit:
  3047. if ( pGroup != NULL )
  3048. {
  3049. OmDereferenceObject( pGroup );
  3050. }
  3051. if ( hResourceKey != NULL )
  3052. {
  3053. DmCloseKey( hResourceKey );
  3054. }
  3055. if ( hGroupKey != NULL )
  3056. {
  3057. DmCloseKey( hGroupKey );
  3058. }
  3059. if ( ( dwStatus == ERROR_SUCCESS ) &&
  3060. ( hXsaction != NULL ) )
  3061. {
  3062. DmCommitLocalUpdate( hXsaction );
  3063. }
  3064. else
  3065. {
  3066. if ( hXsaction ) DmAbortLocalUpdate( hXsaction );
  3067. }
  3068. ClRtlLogPrint(LOG_NOISE,
  3069. "[FM] FmpUpdateCreateResource: Exit for resource %1!ws!, Status=%2!u!...\n",
  3070. lpszResourceId,
  3071. dwStatus);
  3072. return( dwStatus );
  3073. }
  3074. DWORD
  3075. FmpUpdateDeleteResource(
  3076. IN BOOL bSourceNode,
  3077. IN LPCWSTR lpszResourceId
  3078. )
  3079. /*++
  3080. Routine Description:
  3081. GUM dispatch routine for deleting a resource. For NT5.1 clusters, this is structured as
  3082. as local transaction.
  3083. Arguments:
  3084. bSourceNode - Supplies whether or not this node initiated the GUM update.
  3085. Not used.
  3086. lpszResourceId - Supplies the resource ID.
  3087. Return Value:
  3088. ERROR_SUCCESS if successful.
  3089. Win32 error code otherwise.
  3090. --*/
  3091. {
  3092. PFM_RESOURCE pResource = NULL;
  3093. PFM_GROUP pGroup = NULL;
  3094. PLIST_ENTRY pListEntry = NULL;
  3095. PDEPENDENCY pDependency = NULL;
  3096. PPOSSIBLE_ENTRY pPossibleEntry = NULL;
  3097. DWORD dwStatus;
  3098. HLOCALXSACTION
  3099. hXsaction = NULL;
  3100. DWORD dwClusterHighestVersion;
  3101. HDMKEY pGroupKey;
  3102. //
  3103. // Chittur Subbaraman (chitturs) - 9/7/2000
  3104. //
  3105. // Structure this GUM update as a local transaction.
  3106. //
  3107. //
  3108. // If FM groups are not fully initialized or FM is shutting down, then
  3109. // don't do anything.
  3110. //
  3111. if ( !FmpFMGroupsInited || FmpShutdown )
  3112. {
  3113. return( ERROR_SUCCESS );
  3114. }
  3115. pResource = OmReferenceObjectById( ObjectTypeResource, lpszResourceId );
  3116. if ( pResource == NULL )
  3117. {
  3118. ClRtlLogPrint(LOG_UNUSUAL,
  3119. "[FM] FmpUpdateDeleteResource: Resource %1!ws! cannot be found....\n",
  3120. lpszResourceId );
  3121. return( ERROR_RESOURCE_NOT_FOUND );
  3122. }
  3123. ClRtlLogPrint(LOG_NOISE,
  3124. "[FM] FmpUpdateDeleteResource: Delete resource %1!ws!, address %2!lx!....\n",
  3125. lpszResourceId,
  3126. pResource );
  3127. //
  3128. // NOTE: It is difficult to include the checkpoint removal in a local transaction, so keep it
  3129. // out for now. Also, note that these functions MUST be called BEFORE the Resources key is
  3130. // deleted since they enumerate the values under "Resources\RegSync" and "Resources\CryptoSync".
  3131. //
  3132. if ( pResource->Group->OwnerNode == NmLocalNode )
  3133. {
  3134. CpckRemoveResourceCheckpoints( pResource );
  3135. CpRemoveResourceCheckpoints( pResource );
  3136. }
  3137. //
  3138. // Start a transaction
  3139. //
  3140. hXsaction = DmBeginLocalUpdate();
  3141. if ( !hXsaction )
  3142. {
  3143. dwStatus = GetLastError();
  3144. ClRtlLogPrint(LOG_CRITICAL,
  3145. "[FM] FmpUpdateDeleteResource: Failed in starting a transaction for resource %1!ws!, Status =%2!d!....\n",
  3146. lpszResourceId,
  3147. dwStatus);
  3148. goto FnExit;
  3149. }
  3150. //
  3151. // Cannot acquire group lock here to avoid deadlocks with this current design.
  3152. //
  3153. //
  3154. // Remove all registry entries corresponding to the DependsOn list.
  3155. //
  3156. pListEntry = pResource->DependsOn.Flink;
  3157. while ( pListEntry != &pResource->DependsOn )
  3158. {
  3159. pDependency = CONTAINING_RECORD( pListEntry,
  3160. DEPENDENCY,
  3161. DependentLinkage );
  3162. CL_ASSERT( pDependency->DependentResource == pResource );
  3163. pListEntry = pListEntry->Flink;
  3164. //
  3165. // Note that the removal of registry entries is done as a local transaction.
  3166. //
  3167. dwStatus = FmpRemoveResourceDependency( hXsaction,
  3168. pResource,
  3169. pDependency->ProviderResource );
  3170. if ( dwStatus != ERROR_SUCCESS )
  3171. {
  3172. ClRtlLogPrint(LOG_CRITICAL,
  3173. "[FM] FmpUpdateDeleteResource: Unable to remove 'DependsOn' registry entries for resource %1!ws!, Status =%2!d!....\n",
  3174. lpszResourceId,
  3175. dwStatus);
  3176. goto FnExit;
  3177. }
  3178. }
  3179. //
  3180. // Remove all registry entries corresponding to the ProvidesFor list.
  3181. //
  3182. pListEntry = pResource->ProvidesFor.Flink;
  3183. while ( pListEntry != &pResource->ProvidesFor )
  3184. {
  3185. pDependency = CONTAINING_RECORD( pListEntry,
  3186. DEPENDENCY,
  3187. ProviderLinkage );
  3188. CL_ASSERT( pDependency->ProviderResource == pResource );
  3189. pListEntry = pListEntry->Flink;
  3190. //
  3191. // Note that the removal of registry entries is done as a local transaction.
  3192. //
  3193. dwStatus = FmpRemoveResourceDependency( hXsaction,
  3194. pDependency->DependentResource,
  3195. pResource );
  3196. if ( dwStatus != ERROR_SUCCESS )
  3197. {
  3198. ClRtlLogPrint(LOG_CRITICAL,
  3199. "[FM] FmpUpdateDeleteResource: Unable to remove 'ProvidesFor' registry entries for resource %1!ws!, Status=%2!d!....\n",
  3200. lpszResourceId,
  3201. dwStatus);
  3202. goto FnExit;
  3203. }
  3204. }
  3205. //
  3206. // If we are dealing with a Whistler-Win2K cluster, don't bother to
  3207. // do these registry updates since the API layer would do it.
  3208. //
  3209. NmGetClusterOperationalVersion( &dwClusterHighestVersion,
  3210. NULL,
  3211. NULL );
  3212. if ( CLUSTER_GET_MAJOR_VERSION( dwClusterHighestVersion ) <
  3213. NT51_MAJOR_VERSION )
  3214. {
  3215. ClRtlLogPrint(LOG_NOISE,
  3216. "[FM] FmpUpdateDeleteResource: Skipping registry updates for resource %1!ws!...\n",
  3217. lpszResourceId);
  3218. goto skip_registry_updates;
  3219. }
  3220. dwStatus = DmLocalDeleteTree( hXsaction,
  3221. DmResourcesKey,
  3222. OmObjectId( pResource ) );
  3223. if ( ( dwStatus != ERROR_SUCCESS ) &&
  3224. ( dwStatus != ERROR_FILE_NOT_FOUND ) )
  3225. {
  3226. ClRtlLogPrint(LOG_CRITICAL,
  3227. "[FM] FmpUpdateDeleteResource: Unable to remove 'Resources' tree for resource %1!ws!, Status=%2!d!....\n",
  3228. lpszResourceId,
  3229. dwStatus);
  3230. goto FnExit;
  3231. }
  3232. pGroupKey = DmOpenKey( DmGroupsKey,
  3233. OmObjectId( pResource->Group ),
  3234. KEY_READ | KEY_SET_VALUE );
  3235. if ( pGroupKey == NULL )
  3236. {
  3237. dwStatus = GetLastError();
  3238. ClRtlLogPrint(LOG_CRITICAL,
  3239. "[FM] FmpUpdateDeleteResource: Unable to find 'Groups' key for resource %1!ws!, Status=%2!d!....\n",
  3240. lpszResourceId,
  3241. dwStatus);
  3242. goto FnExit;
  3243. }
  3244. dwStatus = DmLocalRemoveFromMultiSz( hXsaction,
  3245. pGroupKey,
  3246. CLUSREG_NAME_GRP_CONTAINS,
  3247. OmObjectId( pResource ) );
  3248. DmCloseKey( pGroupKey );
  3249. if ( dwStatus != ERROR_SUCCESS )
  3250. {
  3251. ClRtlLogPrint(LOG_CRITICAL,
  3252. "[FM] FmpUpdateDeleteResource: Unable to remove contains list for resource %1!ws! in group %2!ws!, Status=%3!d!....\n",
  3253. lpszResourceId,
  3254. OmObjectId( pResource->Group ),
  3255. dwStatus);
  3256. goto FnExit;
  3257. }
  3258. skip_registry_updates:
  3259. //
  3260. // Remove all list entries corresponding to the DependsOn list.
  3261. //
  3262. pListEntry = pResource->DependsOn.Flink;
  3263. while ( pListEntry != &pResource->DependsOn ) {
  3264. pDependency = CONTAINING_RECORD( pListEntry,
  3265. DEPENDENCY,
  3266. DependentLinkage );
  3267. pListEntry = pListEntry->Flink;
  3268. RemoveEntryList( &pDependency->ProviderLinkage );
  3269. RemoveEntryList( &pDependency->DependentLinkage );
  3270. OmDereferenceObject( pDependency->DependentResource );
  3271. OmDereferenceObject( pDependency->ProviderResource );
  3272. LocalFree( pDependency );
  3273. }
  3274. //
  3275. // Remove all list entries corresponding to the ProvidesFor list.
  3276. //
  3277. pListEntry = pResource->ProvidesFor.Flink;
  3278. while ( pListEntry != &pResource->ProvidesFor ) {
  3279. pDependency = CONTAINING_RECORD( pListEntry,
  3280. DEPENDENCY,
  3281. ProviderLinkage );
  3282. pListEntry = pListEntry->Flink;
  3283. RemoveEntryList( &pDependency->ProviderLinkage );
  3284. RemoveEntryList( &pDependency->DependentLinkage );
  3285. OmDereferenceObject( pDependency->DependentResource );
  3286. OmDereferenceObject( pDependency->ProviderResource );
  3287. LocalFree( pDependency );
  3288. }
  3289. //
  3290. // Remove all entries from the possible owners list.
  3291. //
  3292. while ( !IsListEmpty( &pResource->PossibleOwners ) )
  3293. {
  3294. pListEntry = RemoveHeadList( &pResource->PossibleOwners );
  3295. pPossibleEntry = CONTAINING_RECORD( pListEntry,
  3296. POSSIBLE_ENTRY,
  3297. PossibleLinkage );
  3298. OmDereferenceObject( pPossibleEntry->PossibleNode );
  3299. LocalFree( pPossibleEntry );
  3300. }
  3301. //
  3302. // Remove this resource from the Contains list.
  3303. //
  3304. RemoveEntryList( &pResource->ContainsLinkage );
  3305. OmDereferenceObject( pResource );
  3306. //
  3307. // Close the resource's registry key.
  3308. //
  3309. DmRundownList( &pResource->DmRundownList );
  3310. if ( pResource->RegistryKey != NULL )
  3311. {
  3312. DmCloseKey( pResource->RegistryKey );
  3313. pResource->RegistryKey = NULL;
  3314. }
  3315. //
  3316. // SS: we do not delete the reference to the resource here
  3317. // since we will shortly have to add one before posting a notification
  3318. // to the fm worker thread.
  3319. //
  3320. // Post a work item to close the resource in the resource handler.
  3321. // Note that this must be done asynchronously as we cannot call
  3322. // the resource monitor from a GUM handler. If we do, resources
  3323. // do funny things and make deadlocks.
  3324. //
  3325. FmpPostWorkItem( FM_EVENT_RESOURCE_DELETED, pResource, 0 );
  3326. //
  3327. // Decrement resource type reference.
  3328. //
  3329. if ( pResource->Type != NULL ) {
  3330. OmDereferenceObject( pResource->Type );
  3331. pResource->Type = NULL;
  3332. }
  3333. //
  3334. // Remove the resource from the resource list.
  3335. //
  3336. dwStatus = OmRemoveObject( pResource );
  3337. ClusterEvent( CLUSTER_EVENT_RESOURCE_DELETED, pResource );
  3338. ClusterEvent( CLUSTER_EVENT_GROUP_PROPERTY_CHANGE,
  3339. pResource->Group );
  3340. //
  3341. // Mark the resource as deleted
  3342. //
  3343. pResource->dwStructState = FM_RESOURCE_STRUCT_MARKED_FOR_DELETE;
  3344. FnExit:
  3345. OmDereferenceObject( pResource );
  3346. if ( ( dwStatus == ERROR_SUCCESS ) &&
  3347. ( hXsaction != NULL ) )
  3348. {
  3349. DmCommitLocalUpdate( hXsaction );
  3350. }
  3351. else
  3352. {
  3353. if ( hXsaction ) DmAbortLocalUpdate( hXsaction );
  3354. }
  3355. ClRtlLogPrint(LOG_NOISE,
  3356. "[FM] FmpUpdateDeleteResource: Exit for resource %1!ws!, Status=%2!u!...\n",
  3357. lpszResourceId,
  3358. dwStatus);
  3359. return( dwStatus );
  3360. } // FmpUpdateDeleteResource
  3361. DWORD
  3362. FmpUpdateUseRandomizedNodeListForGroups(
  3363. IN BOOL SourceNode,
  3364. IN LPCWSTR pszNodeId,
  3365. IN PFM_GROUP_NODE_LIST pGroupNodeList
  3366. )
  3367. /*++
  3368. Routine Description:
  3369. GUM dispatch routine for using a randomized preferred list for group ownership on
  3370. node down.
  3371. Arguments:
  3372. bSourceNode - Supplies whether or not this node initiated the GUM update.
  3373. Not used.
  3374. pszNodeId - Supplies the ID of the node that is down.
  3375. pGroupNodeList - Randomized preferred node list for groups.
  3376. Return Value:
  3377. ERROR_SUCCESS if successful.
  3378. Win32 error code otherwise.
  3379. --*/
  3380. {
  3381. PNM_NODE pNode = NULL;
  3382. DWORD dwStatus = ERROR_SUCCESS;
  3383. //
  3384. // Chittur Subbaraman (chitturs) - 4/19/2001
  3385. //
  3386. // If FM groups are not fully initialized or FM is shutting down, then
  3387. // don't do anything.
  3388. //
  3389. if ( !FmpFMGroupsInited || FmpShutdown )
  3390. {
  3391. return( ERROR_SUCCESS );
  3392. }
  3393. pNode = OmReferenceObjectById( ObjectTypeNode,
  3394. pszNodeId );
  3395. if ( !pNode )
  3396. {
  3397. ClRtlLogPrint(LOG_CRITICAL,
  3398. "[FM] FmpUpdateUseRandomizedNodeListForGroups: %1!ws! node not found...\n",
  3399. pszNodeId);
  3400. //
  3401. // Should we return failure here, is evict of a node synchronized with everything
  3402. //
  3403. goto FnExit;
  3404. }
  3405. //
  3406. // If this update has already been seen after the node down, ignore this one
  3407. //
  3408. if ( gFmpNodeArray[NmGetNodeId(pNode)].dwNodeDownProcessingInProgress == 0 )
  3409. {
  3410. ClRtlLogPrint(LOG_NOISE,
  3411. "[FM] FmpUpdateUseRandomizedNodeListForGroups: %1!ws! node down has been processed already...\n",
  3412. pszNodeId);
  3413. goto FnExit;
  3414. }
  3415. //
  3416. // Assign ownership to all groups owned by the dead node
  3417. //
  3418. dwStatus = FmpAssignOwnersToGroups( pNode,
  3419. NULL,
  3420. pGroupNodeList );
  3421. if ( dwStatus != ERROR_SUCCESS )
  3422. {
  3423. ClRtlLogPrint(LOG_CRITICAL,
  3424. "[FM] FmpUpdateUseRandomizedNodeListForGroups: FmpAssignOwnersToGroups failed %1!d!\n",
  3425. dwStatus);
  3426. }
  3427. //
  3428. // Mark that the node down processing has been done
  3429. //
  3430. gFmpNodeArray[NmGetNodeId(pNode)].dwNodeDownProcessingInProgress = 0;
  3431. FnExit:
  3432. if ( pNode ) OmDereferenceObject( pNode );
  3433. return( dwStatus );
  3434. }// FmpUpdateUseRandomizedNodeListForGroups