C H A P T E R  5

Understanding Change Notifications

This chapter describes how the CLM API indicates changes in the state of the cluster by sending notifications to system services and applications.


Introduction to Change Notifications

Notifications are information messages sent by the nhcmmd daemon on a node to services or applications registered to receive them. Notifications are sent when there is a change in the membership of the cluster.

Cluster notifications enable a service or application to maintain an accurate view of the state of the cluster and of the state of any peer node. An application or service can use notifications to coordinate changes in system services when a peer node joins or leaves the cluster.

To verify that the nhcmmd daemon is running on your peer nodes, see the Netra High Availability Suite 3.0 1/08 Foundation Services Cluster Administration Guide. For information about the nhcmmd daemon, see the nhcmmd1M (Solaris) or nhcmmd8(Linux) man page.

Understanding the Structure of Notifications

Applications that you write can register a callback function to handle notification messages. The callback function SaClmClusterTrackCallbackT must be used and is registered during the library initialization. Notification tracking is started by calling the function saClmClusterTrack() with either the SA_TRACK_CHANGES or SA_TRACK_CHANGES_ONLY flag. The first flag requires notification including information about all the cluster members, including those that left the cluster after the last notification. The second flag asks for notifications including information about only the nodes that suffered any change. The flags are mutually exclusive.The callback function receives the following three parameters.


TABLE 5-1   Parameters of SaClmClusterTrackCallbackT Function 
Parameter Description
error The error code returned by the nhcmmd daemon. This field is not used for notifications.
notificationBuffer A pointer to a notification buffer structure (SaClmClusterNotificationBufferT).
numberOfMembers The current number of members in the cluster.

The notification buffer has the following members.


TABLE 5-2   Members of the SaClmClusterNotificationBufferT Structure 
Member Description
viewNumber The current view number of the cluster membership.
notification An array of notifications.
numberOfItems The number of notifications in the array.

Each element of the notification array is of the structure type SaClmClusterNotification with the following fields.


TABLE 5-3   Fields of SaClmClusterNotification Structure 
Fields Description
clusterNode A structure with node information as described in Using the saClmClusterNodeT Structure for Information About Cluster Nodes.
clusterChange The change in the cluster membership related to the node in clusterNode.

Nodes can be changed as follows:

The following example presents a simple application showing all the notifications received:


EXAMPLE 5-1   Application With All Notifications Provided  
#include <stdio.h>
#include <stdlib.h>
#include <saClm.h>
 
#include "common.h"
 
 
static void notif_callback(
                          const SaClmClusterNotificationBufferT 
                          *notificationBuffer,
                          SaUint32T numberOfMembers,
                          SaAisErrorT error)
{
      if (error != SA_AIS_OK) {
	    printf("Callback received error %s\n", 
           errString(error));
	    return;
      }
 
	print_notif_buffer(notificationBuffer);
}
 
int main(void)
{
	SaClmHandleT       clmHandle;
	SaAisErrorT        res;
	SaVersionT         version;
	SaClmCallbacksT    callbacks;
 
	version.releaseCode  = VERSION_RELEASE;
	version.majorVersion = VERSION_MAJOR;
	version.minorVersion = VERSION_MINOR;
 
	callbacks.saClmClusterNodeGetCallback = NULL;
	callbacks.saClmClusterTrackCallback = notif_callback;
 
	res = saClmInitialize(&clmHandle, &callbacks, &version);
	if (res != SA_AIS_OK) {
		printf("Failed to initialize the library: %s\n",
		       errString(res));
		exit(1);
	}
 
	res = saClmClusterTrack(clmHandle, SA_TRACK_CHANGES_ONLY, 
           NULL);
	if (res != SA_AIS_OK) {
		printf("Track call failed: %s\n", errString(res));
		exit(1);
	}
 
	res = saClmDispatch(clmHandle, SA_DISPATCH_BLOCKING);
	if (res != SA_AIS_OK) {
 
		printf("Dispatch failed: %s\n", errString(res));
		exit(1);
	}
 
	          (void) saClmFinalize(clmHandle);
 
 
	return 0;
}

In this example, the selection object is not used to poll for data. Instead, saClmDispatch() is called with the flag SA_DISPATCH_BLOCKING. Any thread calling saClmDispatch() with this flag remains within dispatch and executes the callbacks as they become pending. The thread does not return until the corresponding saClmFinalize() function is executed by another thread. Because this example has no other thread, this situation would require you to kill the process.Applications that are configured to keep track of the cluster's state must rely on the notifications. To initially get the state of the cluster, the track function must be called with the SA_DISPATCH_CURRENT flag. However, between both calls, some notification could be missed. To avoid this, combine both flags in the same call to the track function.