sun.com | docs.sun.com | How To Buy | My Sun | Worldwide Sites |  |

| Previous Contents Index Next
### Registering to Receive Notifications To receive notifications, applications or services can use the `cmm_cmc_register()` function to register a callback with the `nhcmmd` daemon. When a membership change occurs in the cluster, the `nhcmmd` daemon notifies the application or service through the callback function by sending a notification. Applications or services receive notifications by polling, using a function such as the `poll()` function. For more information, see the `poll`(2) man page. To change a registration, an application or service must first cancel the existing registration by using the `cmm_cmc_unregister()` function, and then register a new notification by using the `cmm_cmc_register()` function. For an example of how to use these functions, see Example 7-2. For further information, see the `cmm_cmc_register`(3CMM) and `cmm_cmc_unregister`(3CMM) man pages. ### Filtering Notifications By default, when an application registers to receive notifications, the application receives a notification for every change in the cluster state. These notifications can be filtered by using the `cmm_cmc_filter()` function. For each notification present in the filter, as selected by using the `cmm_cmc_filter()` function, the registered callback is invoked. The defined filter is applied for further calls to the `cmm_notify_dispatch()` function. For an example of how to use these functions, see Example 7-2. For further information about how to use the `cmm_cmc_filter()` function, see the `cmm_cmc_filter`(3CMM) man page. ### Receiving and Dispatching Notifications Applications or services that are registered to receive notifications can use the `cmm_notify_getfd()` function. This function returns the file descriptor through which the notifications are delivered. An application uses a polling function, such as `poll()`, to monitor the file descriptors returned by `cmm_notify_getfd()`. When the polling function indicates activity on this file descriptor, `cmm_notify_dispatch()` must be called. For each pending notification, before invoking the callback, the CMM API checks that this notification is present in the filter (as selected with `cmm_cmc_filter()`). The callback is invoked with the notification and the client_data argument passed to the `cmm_cmc_register()` function. For an example of how to use these functions, see Example 7-2. For further information see the `cmm_cmc_register`(3CMM), `cmm_notify_getfd`(3CMM), `cmm_notify_dispatch`(3CMM) and `poll`(2) man pages. ### Retrieving Change Notifications The following example demonstrates how to use the functions that enable you to filter, receive and dispatch notifications: Example 7-2 Retrieving Change Notifications
    #include <cmm.h>
    #include <stdio.h>
    #include <stdlib.h>        /* for exit() */
    #include <strings.h>        /* for strcpy */
    #include "common.h"

    /*******************************************************************/
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    void CMM_notify_cb(const cmm_cmc_notification_t *change_notification,
        void *client_data)
    {
        cmm_member_t member ;

            switch (change_notification->cmchange)
        {
            case CMM_MASTER_ELECTED:
                    printf("[USER CB] master elected = %d\n",
                change_notification->nodeid) ;
                    if (cmm_master_getinfo(&member) == CMM_OK)
                print_member(&member) ;
                    break ;
            case CMM_MASTER_DEMOTED:
                    printf("[USER CB] master demoted = %d\n",
                change_notification->nodeid) ;
                    break ;
            case CMM_VICEMASTER_ELECTED:
                    printf("[USER CB] vicemaster elected = %d\n",
                change_notification->nodeid) ;
                    break ;
            case CMM_VICEMASTER_DEMOTED:
                    printf("[USER CB] vicemaster demoted = %d\n",
                change_notification->nodeid) ;
                    break ;
            case CMM_MEMBER_JOINED:
                    if (cmm_member_getinfo(change_notification->nodeid,
                &member) == CMM_OK)
                print_member(&member) ;
                    break ;
            case CMM_MEMBER_LEFT:
                    printf("[USER CB] member left cluster = %d\n",
                change_notification->nodeid) ;
                    break ;
            case CMM_INVALID_CLUSTER:
                    printf("[USER CB] INVALID CLUSTER\n") ;
                    break ;
            case CMM_STALE_CLUSTER:
                    printf("[USER CB] STALE CLUSTER\n") ;
                    break ;
            case CMM_VALID_CLUSTER:
                    printf("[USER CB] VALID CLUSTER\n") ;
                    break ;
            }
    }

    /********************************************************************/
    /********************************************************************/
    /********************************************************************/
    /********************************************************************/
    int main(int P_argc, char *P_argv[])
    {
            uint32_t        L_node_count ;
            cmm_error_t     result ;
            struct pollfd   fifo_poll ;
        boolean_t       go_on_poll = B_TRUE ;

        /* FILTERING PART */
        cmm_cmchanges_t L_notify[2] = { CMM_MASTER_ELECTED,
                        CMM_INVALID_CLUSTER } ;

        cmm_cmc_filter(CMM_CMC_NOTIFY_SET, L_notify, 2) ;

        result = cmm_cmc_register(CMM_notify_cb, (void *) NULL) ;
        if (result != CMM_OK)
        {
            fprintf(stderr,
                " register error (%s) => EXIT\n",
                cmm_strerror(result)) ;
            exit(1) ;
        }

        result = cmm_notify_getfd(&fifo_poll.fd) ;
        if (result != CMM_OK) {
            fprintf(stderr,
                " getfd error (%s) => EXIT\n",
                cmm_strerror(result)) ;
            exit(1) ;
        }

        printf("file descriptor to poll = %d\n", fifo_poll.fd) ;
        fifo_poll.events
            = (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI);
        fifo_poll.revents = 0 ;

        while (1) {
            /* this loop ends when exit asked or poll succeeded */
            go_on_poll = B_TRUE ;
            while (go_on_poll == B_TRUE) {
                result = cmm_notify_getfd(&fifo_poll.fd) ;
                switch (poll(&fifo_poll, 1, 2500) )
                {
                case -1:
                    puts("error on poll") ;
                    break ;
                case 0:
                    /* time-out */
                    break ;
                default:
                    go_on_poll = B_FALSE ;
                }

                if ((fifo_poll.revents & POLLHUP) ||
                    (fifo_poll.fd == -1))
                {
                    printf("reconnection required\n") ;
                    result = cmm_cmc_unregister() ;
                    result = cmm_cmc_register(CMM_notify_cb,
                        (void *) NULL) ;
                    result = cmm_notify_getfd(&fifo_poll.fd) ;
                    poll(NULL, 0 , 500) ;
                }
            }
            cmm_notify_dispatch() ;
        }
    }
Previous Contents Index Next

Copyright 1994-2004 Sun Microsystems