C H A P T E R  4

Retrieving Node Information Using the CLM API

This chapter describes how to use the functions of the CLM API to retrieve information about nodes. For more information, see the following topics:


Retrieving Information About a Node

The functions saClmClusterNodeGet() and saClmClusterNodeGetAsync() retrieve information about the node specified. The node is specified by providing its node id. The special node id, SA_CLM_LOCAL_NODE_ID, can be used to specify the local node without knowing the local node’s node id. When run successfully, the functions return a SaClmClusterNodeT structure that contains information about the requested node. For information about this structure, refer to Using the saClmClusterNodeT Structure for Information About Cluster Nodes.For an example, refer to EXAMPLE 3-3.The asynchronous version of the function returns immediately, but the request will be processed asynchronously by the nhcmmd daemon. When the results are ready, the callback specified during the initialization of the library will be executed.For the callback to be called, you must obtain a selection object, which you can do using the saClmSelectionObjectGet() function, you must use the selection object to know when a callback is pending, and you must call the saClmDispatch() function so callbacks are executed, as explained in Library Life Cycle.The following example shows the usage of the saClmClusterNodeGetAsync() function:


EXAMPLE 4-1   Retrieving Information About the Local Node Using the saClmClusterNodeGetAsync Function  
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#include <saClm.h>
 
#include "common.h"
 
 
static void node_callback(SaInvocationT invocation,
                          const SaClmClusterNodeT *clusterNode,
                          SaAisErrorT error)
{
       if (error != SA_AIS_OK) {
           printf("Callback received error %s\n", 
           errString(error));
           return;
       }
 
       printf("Callback\n--------\nInvocation: %llu\n", 
               invocation);
       print_node(clusterNode);
}
 
int main(void)
{
	SaClmHandleT       clmHandle;
	SaClmClusterNodeT  clusterNode;
	SaAisErrorT        res;
	SaVersionT         version;
	SaClmCallbacksT    callbacks;
	struct pollfd      fds[1];
	SaSelectionObjectT selObj;
 
	version.releaseCode  = VERSION_RELEASE;
	version.majorVersion = VERSION_MAJOR;
	version.minorVersion = VERSION_MINOR;
 
	callbacks.saClmClusterNodeGetCallback = node_callback;
	callbacks.saClmClusterTrackCallback = NULL;
 
	res = saClmInitialize(&clmHandle, &callbacks, &version);
	if (res != SA_AIS_OK) {
		printf("Failed to initialize the library: %s\n",
		       errString(res));
		exit(1);
	}
	res = saClmClusterNodeGetAsync(clmHandle, 1,
                                      SA_CLM_LOCAL_NODE_ID);
	if (res != SA_AIS_OK) {
		printf("Failed to launch NodeGetAsync: %s\n",
                   errString(res));
		exit(1);
	}
	res = saClmSelectionObjectGet(clmHandle, &selObj);
	if (res != SA_AIS_OK) {
		printf("SelectionObjectGet failed: %s\n",
		        errString(res));
		exit(1);
	}
	fds[0].fd = (int) selObj;
	fds[0].events = POLLIN;
	fds[0].revents = 0;
 
	if (poll(fds, 1, -1) != 1)
		printf("Poll failed\n");
 
	res = saClmDispatch(clmHandle, SA_DISPATCH_ONE);
	if (res != SA_AIS_OK) {
		printf("Dispatch failed: %s\n", errString(res));
		exit(1);
 
	      (void) saClmFinalize(clmHandle);
 
	return 0;
}



Note - For more information about the functions referenced in this section, refer to the corresponding man pages associated with these functions.




Retrieving Information About All Nodes in the Cluster

When called with the flag SA_TRACK_CURRENT, the function saClmClusterTrack() will retrieve information about all the cluster nodes. If the parameter notificationBuffer is a NULL pointer, the function will run asynchronously and the results will be provided to the Track callback function. If the pointer is not NULL, then the function will behave synchronously and the results will be stored in the provided buffer. In this latter case, if the notification field of the provided structure is a NULL pointer, then enough memory will be allocated to store the information. The user is responsible for freeing this memory.In the following example, the synchronous version of the call is used and the memory is allocated by the library.


EXAMPLE 4-2   Synchronous saClmClusterTrack Function  
#include <stdio.h>
#include <stdlib.h> 
#include <saClm.h>
 
#include "common.h"
 
int main(void)
{
	SaClmHandleT                    clmHandle;
	SaAisErrorT                     res;
	SaVersionT                      version;
	SaClmClusterNotificationBufferT notifBuffer;
 
	version.releaseCode  = VERSION_RELEASE;
	version.majorVersion = VERSION_MAJOR;
	version.minorVersion = VERSION_MINOR;
 
	res = saClmInitialize(&clmHandle, NULL, &version);
	if (res != SA_AIS_OK) {
 		printf("Failed to initialize the library: %s\n",
                  errString(res));
 		exit 1 ;
       }
 
	/* Let the library allocate the memory */
	notifBuffer.numberOfItems = 0;
	notifBuffer.notification = NULL;
 
	res = saClmClusterTrack(clmHandle, SA_TRACK_CURRENT,
                               &notifBuffer);
	if (res != SA_AIS_OK) {
		printf("Track call failed: %s\n", errString(res));
		exit(1);
}
	if (notifBuffer.notification != NULL) {
		print_notif_buffer(&notifBuffer);
 
		/* Free the memory allocated by the library */
		saClmClusterNotificationFree(clmHandle,
                                      notifBuffer.notification);
	}
 
	(void) saClmFinalize(clmHandle);
 
	return 0;
}

The function print_notif_buffer() is not part of the SA Forum/CLM API and can be found in the common.c file. The following example shows the use of the print_notif_buffer() function, which shows how to print the information on a SaClmClusterNotificationBufferT structure:


EXAMPLE 4-3   The print_notif_buffer function  
void print_notification(const SaClmClusterNotificationT *notif)
{
     printf("change: %s\n", changeString(notif->clusterChange));
     print_node(&notif->clusterNode);
}
 
void print_notif_buffer(const SaClmClusterNotificationBufferT 
*notif)
{
 
      int i;
 
	printf("Notification buffer\n"
	       "-------------------\n");
	printf("View Number: %llu\nNumber of Items: %u\n",
	       notif->viewNumber, notif->numberOfItems);
	if (notif->notification == NULL)
		printf("notification: NULL\n");
	else
		for (i = 0; i < notif->numberOfItems; i++) {
			printf("notification: %2i\n----------------\n", i);
			print_notification(&notif->notification[i]);
		}
}

The following example shows the asynchronous version of the call:


EXAMPLE 4-4   The saClmClusterTrackAsync Function  
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#include <saClm.h>
 
#include "common.h"
 
 
static void track_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;
	struct pollfd      fds[1];
	SaSelectionObjectT selObj;
 
	version.releaseCode  = VERSION_RELEASE;
	version.majorVersion = VERSION_MAJOR;
	version.minorVersion = VERSION_MINOR;
 
	callbacks.saClmClusterNodeGetCallback = NULL;
	callbacks.saClmClusterTrackCallback = track_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_CURRENT, NULL);
	if (res != SA_AIS_OK) {
		printf("Failed to launch async Track: %s\n",
                  errString(res));
		exit(1);
	}
 
	res = saClmSelectionObjectGet(clmHandle, &selObj);
	if (res != SA_AIS_OK) {
		printf("SelectionObjectGet failed: %s\n",
                   errString(res));
		exit(1);
	}
 
	fds[0].fd = (int) selObj;
	fds[0].events = POLLIN;
	fds[0].revents = 0;
 
	if (poll(fds, 1, -1) != 1)
		printf("Poll failed\n");
 
	res = saClmDispatch(clmHandle, SA_DISPATCH_ONE);
	if (res != SA_AIS_OK) {
		printf("Dispatch failed: %s\n", errString(res));
		exit(1);
	}
 
	            (void) saClmFinalize(clmHandle);
 
	return 0;
}


Using the saClmClusterNodeT Structure for Information About Cluster Nodes

The saClmClusterNodeT structure, contained within the SA Forum/CLM API, is an important source of information about member nodes. This structure contains the following fields:


nodeId The unique identifier of a node.
nodeName The user-visible string that identifies a node and is used to format display messages.
nodeAddress Stores the dotted-decimal notation of the node Carrier Grade Transport Protocol (CGTP) address in a string that can be used as a parameter on any architecture.
bootTimestamp The instance of the last reboot expressed as the number of nanoseconds elapsed since 00:00:00 UTC, January 1, 1970. Nodes use this field to detect whether another node has rebooted within an interval of time.
member A Boolean value indicating whether or not the node is a cluster member.
initialViewNumber The view number when the node joined the cluster.