C H A P T E R  7

Processor Management Services

This chapter describes the processor management services (PMS) application programming interface (API). This chapter contains the following sections:


PMS Software Overview

The processor management services (PMS) software is an extension to the Netra CT platform services software that addresses the requirements of high-availability (HA) application frameworks. The PMS software enables client applications to manage the operation of the processor nodes within a single Netra CT system or within a cluster of multiple Netra CT systems. A processor node is a combination of CPU blade hardware, CPU memory, I/O interfaces, the operating system that runs on them, and select applications. A PMS cluster can include the alarm card and all of the CPU cards in a single Netra CT system, or it can include a defined group of alarm cards and CPU cards located in multiple systems.

The PMS software provides distributed CPU board resource management infrastructure for clusters of CPU boards. This infrastructure includes low-level administrative control and monitoring, high-level configuration, fault recovery, and user-interface functionality. FIGURE 7-1 identifies the architectural components of the Netra CT software services.

  FIGURE 7-1 Netra CT Software Services

Diagram showing the division of customer services and platform services.[ D ]

In a Netra CT cluster, the PMS software runs on both the alarm cards and the CPU boards. The PMS software running on alarm cards provides local and remote service connections for managing the CPU cards in its system. The PMS software running on CPU cards provides local and remote service connections for managing the resources running on the board, and the software provides remote access for managing resources running on other CPU cards in a PMS cluster.

  FIGURE 7-2 PMS Software Services and Interfaces

Netra CT processor management software (PMS) services and interfaces.[ D ]

FIGURE 7-2 indicates the internal interfaces of the processor services.

The PMS software organizes the CPU resources it manages into the following three groups:

The PMS software that runs on both alarm cards and the CPU cards divides its functionality along client-side and server-side (daemon-side) lines. The common client-side function provides a shared API for up to eight simultaneous application service processes. The core API functionality includes API control, PMS daemon control, application PMS connectivity, and application message send and receive with function execution. The API provides per-process serialization and separate threads for message reception and user-defined function execution, and messaging process timing.

In a typical example, a PMS client detects resource failures remotely and then remotely activates replacement resources such as those found in high-availability applications. The common daemon function provides server-side control and monitoring functionality for up to 16 remote CPUs. The daemon function also provides client-side functionality for controlling and monitoring up to 16 remote CPUs simultaneously with minimized latency by way of per-remote-CPU threading, as well as daemon control and performance monitoring and resource group monitoring and control.

From the client side, the alarm card function available by way of the send and receive messaging API is broken into management and drawer blocks. (The PMS software refers to Netra CT systems as drawers.) The CPU cards are divided into management node and remote node drawer (RND) views. The management view on both the alarm card and the CPU board provides administrative control and status over the PMS daemon as a whole. The management view also monitors the PMS software's performance.

The drawer (system) view by means of the alarm card provides the following administrative controls and monitors of the RG2 (hardware) resources: Core power down, power up, and reset. For RG1 (operating system) resources, this view also provides the following administrative controls and monitors: core shutdown, boot, and reboot. For RG0 (application services), this view provides off-line and active administrative controls. Finally, for the combined resource groups, this view provides the following administrative controls and monitors: Core maintenance, and operational configuration, five recovery processes, and the graceful reboot of the group.

The node view, by way of the CPU card itself, provides a much reduced set of administrative controls and monitors relative to the drawer view of the hardware, operating system, and the same administrative controls and monitors of the application services. In RG2 only reset administrative controls exists, but no monitors. Likewise, in RG1 only reboot administrative controls exist, but no monitors. In this view, there is no administrative control over the combined resource groups.

The CPU card RND view provides remote system view administrative controls and monitors to all the resource groups, with the exception of an alarm card failure. In this failure case, a reduced remote node view is used.

The PMS software execution performance is targeted by scheduling optimizations as well as using lightweight, proprietary messaging protocols, intersystem data encoding, and packetization protocols. The PMS software scalability due to CPU card growth is addressed by a per-CPU multithreading of up to 16 remote CPU cards per CPU. Application client growth is addressed by way of per-process multi-threading with up to eight client processes per PMS daemon.

The PMS software performance and reliability in cluster communication is also addressed with a messaging infrastructure that supports unidirectional and bidirectional point-to-point and unidirectional point-multipoint channels. This infrastructure includes source time-stamping available to the client for latency detection, call and return time-out for failure detection, and interprocess and intersystem TCP/IP socket streams for connection control, reachability determination, and reliable transport.


PMS Man Pages

The PMS software application programming interface (API) has been documented completely in the UNIX man pages included with the Netra CT software. TABLE 7-1 lists the man pages included with the Netra CT PMS software:

 

TABLE 7-1 Processor Management Services Man Pages

Man page

Description

pms(1M)

Provides an overview of the PMS software.

pmsd(1M)

Describes how to start and stop the CPU board PMS daemon (pmsd) and lists the daemon's command line options.

pmsd_ac(1M)

Describes how to start and stop the alarm card PMS daemon (pmsd_ac) from the command line interface, and lists all the daemon's other command-line functions.

pms_apistart(1M)

Describes the PMS API functions used to initialize (pms_apistart) and to free up (pms_apistop) PMS API resources in a PMS process. The man page also documents the functions used to take PMS out of an inactive state (pms_start) and to return it to an inactive state (pms_stop).

pms_connect(1M)

Documents the PMS API functions used to create (pms_connect) and destroy (pms_disconnect) a PMS daemon interface session.

pms_send(1M)

Describes the PMS API functions that enable PMS clients to send (pms_send) and receive (pms_receive) messages with other PMS clients or clusters.

pms_usermgmt_message_payloads(1M)

Describes the payloads for the user and management PMS function groups.

pms_node_message_payloads(1M)

Defines the payloads for the node PMS function group.

pms_rnd_message_payloads(1M)

Describes the payloads for the remote node drawer (system) PMS function group.


If you cannot view these man pages, add the PMS man page directory location to your $MANPATH environment variable. By default, the PMS man pages are installed in the following directory: /opt/SUNWnetract/mgmt2.0/man. Depending on the UNIX shell you are using, this variable might be defined in a shell startup file. Refer to the Solaris documentation for instructions on adding the PMS man page directory to a UNIX shell startup file on your system.


PMS Examples

The following examples show how to initialize a PMS client, the structure of the main thread, asynchronous messaging, scheduling, and the PMS client's user and management, node, and RND interfaces.

CODE EXAMPLE 7-1 begins by initializing the main thread for a PMS client.

CODE EXAMPLE 7-1 PMS Client Initialization Example
#include <sys/types.h>          /* socketpair() */
#include <sys/socket.h>         /* socketpair() */
 
#include <unistd.h>             /* write(), read() */
 
#include <signal.h>             /* sigemptyset(), sigaddset(), sigaction() */
#include <time.h>               /* timer_create(), timer_settime() */
 
#include <stdio.h>              /* printf(), scanf() */
 
 
#include "pms.h"
 
 
/*      Application State Machine Example Overview:
      1) PMS API initialization and usage.
      2) PMS Daemon connectivity and availability management.
      3) Named application synchronization and behavior.
      4) Remote Node Drawer address list synchronization and monitoring.
      5) Basic example data caching synchronization on the client side for PMS
         items a particular application's intent/design makes it interested in.
      6) Basic asynchronous message handling infrastructure for the application.
      7) Remote monitoring of remote node drawer's.
      8) Example Control of a pair of remote node drawer's(not implemented yet).
*/
 
 
 
void*   app_hasim_thread(void*);
 
 
/* Event message handlers.. */
 
/* This mechanism registers one receive handler with PMS for all messages, which
   simply posts the messages to the client thread's processing queue to have them
   handled synchronously.  Alternatively, handlers can be registered with PMS
   individually in which case they will execute asynchronous to the client thread
   in the context of the PMS API receive thread. */
 
void    app_hasim_receive_post(struct pms_receive *pr);
int     app_hasim_receive_dispatch(struct pms_receive* pr);
 
void    app_hasim_receive_user_status(struct pms_receive *pr);
void    app_hasim_receive_mgmt_status(struct pms_receive *pr);
void    app_hasim_receive_node_rg0_status(struct pms_receive *pr);
void    app_hasim_receive_node_rg0_app_state_set_execute\
           (struct pms_receive *pr);
void    app_hasim_receive_rnd_status(struct pms_receive *pr);
void    app_hasim_receive_rnd_md0_status(struct pms_receive *pr);
 
void    app_hasim_receive_time_status(void);
 
/* Convenient state machine process sub-groupings.. */
 
void    app_hasim_user_process(void);
void    app_hasim_mgmt_process(void);
void    app_hasim_node_process(void);
void    app_hasim_rnd_process(void);
void    app_hasim_process(void);
 
/* Timer signal handler.. */
 
void    app_hasim_sigusr1_signal_handler(int);
 
 
/* Interval's currently set for example convenience.. */
 
#define HASIM_CHECK_INTERVAL                                    2
#define HASIM_SYNCCHECK_INTERVAL                                600
#define HASIM_CHECK_VALID_INTERVAL                              1800
#define HASIM_CHECK_INVALID_INTERVAL                            3600
 
#define HASIM_RND_ADDRESS_AUDIT_ENTRYS                          2
 
 
struct hasim_info
        {
        int                                     sockfd[2];
        struct
                {
                char                            node_ip_address[20];
                char                            drawer_ip_address[20];
                int                             node_slot_number;
                } rnd_address[HASIM_RND_ADDRESS_AUDIT_ENTRYS];
 
        struct
                {
#define HASIM_USER_RECEIVE_UNREGISTERED                         0x00
#define HASIM_USER_RECEIVE_REGISTERED                           0x01
                int                             receive_state;
#define HASIM_USER_PMS_VIEW_REACHABLE                           0x00
#define HASIM_USER_PMS_VIEW_UNREACHABLE                         0x01
                int                             pms_view;
 
                int                             view_cache;
                } user_info;
 
        struct
                {
#define HASIM_MGMT_RECEIVE_UNREGISTERED                         0x00
#define HASIM_MGMT_RECEIVE_REGISTERED                           0x01
                int                             receive_state;
#define HASIM_MGMT_PMS_STATE_UNAVAILABLE                        0x00
#define HASIM_MGMT_PMS_STATE_AVAILABLE                          0x01
                int                             pms_state;
#define HASIM_MGMT_RND_ADDRESS_UNVERIFIED                       0x00
#define HASIM_MGMT_RND_ADDRESS_VERIFIED                         0x01
                int                             rnd_address_state;
                int                             rnd_address_identifier[16];
 
#define HASIM_MGMT_CACHE_INVALID                                0x00
#define HASIM_MGMT_CACHE_OLD                                    0x01
#define HASIM_MGMT_CACHE_VALID                                  0x02
                int                             cache_state;
                int                             last_update;
                int                             last_sync_check;
 
                int                             mgmt_state_cache;
                struct
                        {
                        int                     identifier;
                        char                    node_ip_address[20];
                        char                    drawer_ip_address[20];
                        int                     node_slot_number;
                        } rnd_address_cache[16];
                } mgmt_info;
 
        struct
                {
#define HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED                        0x02
#define HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED         0x04
#define HASIM_NODE_GROUP_RECEIVE_UNREGISTERED                           0x00
#define HASIM_NODE_GROUP_RECEIVE_REGISTERED                             0x06
                int                             receive_state;
#define HASIM_NODE_RG0_APP_NAME_UNREGISTERED                    0x00
#define HASIM_NODE_RG0_APP_NAME_REGISTERED                      0x01
                int                             rg0_app_name_state;
#define HASIM_NODE_SERVICE_STATE_OFFLINE                        0x00
#define HASIM_NODE_SERVICE_STATE_ACTIVE                         0x01
                int                             service_state;
 
#define HASIM_NODE_CACHE_INVALID                                0x00
#define HASIM_NODE_CACHE_OLD                                    0x01
#define HASIM_NODE_CACHE_VALID                                  0x02
                int                             cache_state;
                int                             last_update;
                int                             last_sync_check;
 
                int                             rg0_state_cache;
                } node_info;
 
        struct
                {
#define HASIM_RND_RECEIVE_REGISTERED                            0x01
#define HASIM_RND_MD0_RECEIVE_REGISTERED                        0x20
#define HASIM_RND_GROUP_RECEIVE_UNREGISTERED                    0x00
#define HASIM_RND_GROUP_RECEIVE_REGISTERED                      0x21
                int                             receive_state;
 
#define HASIM_RND_CACHE_INVALID                                 0x00
#define HASIM_RND_CACHE_OLD                                     0x01
#define HASIM_RND_CACHE_VALID                                   0x02
                int                             cache_state;
                int                             last_update;
                int                             last_sync_check;
 
                int                             view_cache;
                int                             md0_config_cache;
                } rnd_info[16];
 
        };
 
static struct hasim_info                        mdi;
 
 
int
main(int argc, char *argv[])
{
 
  struct pms_receive    pr;
  struct sigaction      sigusr1_signal_handler_info;
  struct sigevent       evp;
  timer_t               timerid;
  struct itimerspec     val;
  struct itimerspec     oval;
 
  int                   i;
 
 
  if (argc != 1)
    {
    printf("Invalid Arguments\n");
 
    exit(1);
    }
 
 
  /* Start/Initialize the PMS API before using any further calls.. */
 
  if (pms_apistart() == -1)
    exit(2);
 
 
  /* Create message queue.. */
 
  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, mdi.sockfd) == -1)
    {
    exit(3);
    }
 
 
 
 
 
 
 
  /* Setup defaults.. */
 
  /* Audit DB hardcoding for this example.. */
 
  strcpy(&mdi.rnd_address[0].node_ip_address[0], "129.150.94.70");
  strcpy(&mdi.rnd_address[0].drawer_ip_address[0], "129.150.151.140");
  mdi.rnd_address[0].node_slot_number = 2;
  strcpy(&mdi.rnd_address[1].node_ip_address[0], "129.150.94.58");
  strcpy(&mdi.rnd_address[1].drawer_ip_address[0], "129.150.151.143");
  mdi.rnd_address[1].node_slot_number = 3;
 
 
  mdi.user_info.receive_state = HASIM_USER_RECEIVE_UNREGISTERED;
  mdi.user_info.pms_view = HASIM_USER_PMS_VIEW_UNREACHABLE;
 
  mdi.mgmt_info.receive_state = HASIM_MGMT_RECEIVE_UNREGISTERED;
  mdi.mgmt_info.pms_state = HASIM_MGMT_PMS_STATE_UNAVAILABLE;
  mdi.mgmt_info.rnd_address_state = HASIM_MGMT_RND_ADDRESS_UNVERIFIED;
  for(i=0;i<16;i++)
    mdi.mgmt_info.rnd_address_identifier[i] = -1;
  mdi.mgmt_info.cache_state = HASIM_MGMT_CACHE_INVALID;
  mdi.mgmt_info.last_update = HASIM_CHECK_INVALID_INTERVAL;
  mdi.mgmt_info.last_sync_check = HASIM_SYNCCHECK_INTERVAL;
 
  mdi.node_info.receive_state = HASIM_NODE_GROUP_RECEIVE_UNREGISTERED;
  mdi.node_info.rg0_app_name_state = HASIM_NODE_RG0_APP_NAME_UNREGISTERED;
  mdi.node_info.service_state = HASIM_NODE_SERVICE_STATE_OFFLINE;
  mdi.node_info.cache_state = HASIM_NODE_CACHE_INVALID;
  mdi.node_info.last_update = HASIM_CHECK_INVALID_INTERVAL;
  mdi.node_info.last_sync_check = HASIM_SYNCCHECK_INTERVAL;
 
  for(i=0;i<16;i++)
    {
    mdi.rnd_info[i].receive_state = HASIM_RND_GROUP_RECEIVE_UNREGISTERED;
    mdi.rnd_info[i].cache_state = HASIM_RND_CACHE_INVALID;
    mdi.rnd_info[i].last_update = HASIM_CHECK_INVALID_INTERVAL;
    mdi.rnd_info[i].last_sync_check = HASIM_SYNCCHECK_INTERVAL;
    }
 
 
  /* Setup timer.. */
 
  sigemptyset(&sigusr1_signal_handler_info.sa_mask);
  sigaddset(&sigusr1_signal_handler_info.sa_mask, SIGUSR1);
  sigusr1_signal_handler_info.sa_flags = 0;
  sigusr1_signal_handler_info.sa_handler = app_hasim_sigusr1_signal_handler;
  sigaction(SIGUSR1, &sigusr1_signal_handler_info, NULL);
 
  evp.sigev_notify = SIGEV_SIGNAL;
  evp.sigev_signo = SIGUSR1;
 
  if (timer_create(CLOCK_REALTIME, &evp, &timerid) == -1)
    exit(4);
 
  val.it_value.tv_sec = HASIM_CHECK_INTERVAL;
  val.it_value.tv_nsec = 0;
  val.it_interval.tv_sec = HASIM_CHECK_INTERVAL;
  val.it_interval.tv_nsec = 0;
 
  if (timer_settime(timerid, TIMER_RELTIME,  &val, NULL) == -1)
    exit(4);
 
 
  /* Don't bother creating another thread, run in context of main default.. */
  app_hasim_thread(0);
 
 
}
 

 

CODE EXAMPLE 7-2 PMS Client Main Thread

void*
app_hasim_thread(void* arg)
{
 
  char                  receivebuffer[256];
  int                   receivestatus;
 
  fd_set                readfds;
  int                   select_return;
  struct timeval        timeout;
 
  struct pms_send       ps;
  struct pms_receive    pr;
 
  int                   i;
 
 
  printf("*** HA Client Application Simulation ***\n");
 
 
  /* Presuming PMS will have been started at boot or by another app.. */
 
 
  timeout.tv_sec = HASIM_CHECK_INTERVAL;
  timeout.tv_usec = 0;
 
 
  while(1)
    {
 
    FD_ZERO(&readfds);
 
    FD_SET(mdi.sockfd[1], &readfds);
 
    /* Wait for event messages.. */
 
    select_return = select(64, &readfds, NULL, NULL, &timeout);
 
    if (select_return > 0)
      {
      if (FD_ISSET(mdi.sockfd[1], &readfds) != 0)
        {
 
        receivestatus = read(mdi.sockfd[1], &receivebuffer[0], 256);
 
        if (receivestatus <= 0)
          {
 
          /* Handle Error.. */
 
          }
        else
          {
 
          /* Handle Message.. */
 
          app_hasim_receive_dispatch((struct pms_receive*)&receivebuffer[0]);
 
          }
        }
      }
    else if (select_return == 0)
      {
 
      /* Handle Timeout.. */
 
      }
    else
      {
 
      /* Handle Error.. */
 
      }
 
    }
 
 
}
 
 
void
app_hasim_sigusr1_signal_handler(int signal)
{
 
  struct pms_receive    pr;
 
 
  pr.session.type = PMS_SR_CALL_NO_RETURN;
  pr.payload.type = PMS_PD_PAYLOAD_TYPE_MAX+1;
 
 
  app_hasim_receive_post(&pr);
 
}
 

The following example sets up a PMS client to handle asynchronous messages.

 

CODE EXAMPLE 7-3 PMS Client Asynchronous Message Handling
void
app_hasim_receive_post(struct pms_receive* pr)
{
 
 
  int                   status;
 
 
  /* Write for reading in context of main thread.. */
 
  status = write(mdi.sockfd[0], pr, sizeof(struct pms_receive));
 
  if (status < 0)
    {
    }
 
 
}
 
 
 
int
app_hasim_receive_dispatch(struct pms_receive* pr)
{
 
 
  switch(pr->payload.type)
    {
    case PMS_PD_USER_STATUS:
 
      app_hasim_receive_user_status(pr);
 
    break;
 
    case PMS_PD_MGMT_STATUS:
 
      app_hasim_receive_mgmt_status(pr);
 
    break;
 
    case PMS_PD_NODE_RG0_STATUS:
 
      app_hasim_receive_node_rg0_status(pr);
 
    break;
 
    case PMS_PD_NODE_RG0_APP_STATE_SET_EXECUTE:
 
      app_hasim_receive_node_rg0_app_state_set_execute(pr);
 
    break;
    case PMS_PD_RND_STATUS:
 
      app_hasim_receive_rnd_status(pr);
 
    break;
    case PMS_PD_RND_MD0_STATUS:
 
      app_hasim_receive_rnd_md0_status(pr);
 
    break;
    case PMS_PD_PAYLOAD_TYPE_MAX+1:
 
      app_hasim_receive_time_status();
 
    break;
    }
 
 
  return(0);
 
}
 
 
void
app_hasim_receive_user_status(struct pms_receive* pr)
{
 
 
  switch(pr->payload.data.user_status.code)
    {
    case PMS_PD_USER_STATUS_PMS_REACHABLE:
 
      printf("hasim :        received USER_STATUS PMS_REACHABLE..\n");
 
 
      mdi.user_info.view_cache = PMS_PD_USER_STATUS_PMS_REACHABLE;
 
      /* Run state machine.. */
 
      app_hasim_process();
 
    break;
    case PMS_PD_USER_STATUS_PMS_UNREACHABLE:
 
      printf("hasim :        received USER_STATUS PMS_UNREACHABLE..\n");
 
 
      mdi.user_info.view_cache = PMS_PD_USER_STATUS_PMS_UNREACHABLE;
 
 
      app_hasim_process();
 
    break;
    }
 
 
}
 
 
 
void
app_hasim_receive_mgmt_status(struct pms_receive* pr)
{
 
  struct pms_send       ps;
  struct pms_receive    prs;
 
  int                   info_get_fail;
 
  int                   rnd_address_identifier[16];
  char                  rnd_address_node_ip_address[16][20];
  char                  rnd_address_drawer_ip_address[16][20];
  int                   rnd_address_node_slot_number[16];
 
  int                   i, j;
 
 
  switch(pr->payload.data.mgmt_status.code)
    {
    case PMS_PD_MGMT_STATUS_PMS_STATE_AVAILABLE:
 
      printf("hasim :        received MGMT_STATUS PMS STATE AVAILABLE..\n");
 
      /* Update cached data and set update time.. */
 
      mdi.mgmt_info.mgmt_state_cache = PMS_PD_MGMT_INFO_GET_STATUS_AVAILABLE;
      mdi.mgmt_info.last_update = 0;
 
      app_hasim_process();
 
    break;
    case PMS_PD_MGMT_STATUS_PMS_STATE_UNAVAILABLE:
 
      printf("hasim :        received MGMT_STATUS PMS STATE UNAVAILABLE..\n");
 
      mdi.mgmt_info.mgmt_state_cache = PMS_PD_MGMT_INFO_GET_STATUS_UNAVAILABLE;
      mdi.mgmt_info.last_update = 0;
 
      app_hasim_process();
 
    break;
    case PMS_PD_MGMT_STATUS_PMS_ADMIN_STATE_FORCE_UNAVAILABLE:
 
      printf("hasim :        received MGMT_STATUS PMS ADMIN STATE FORCE\
         UNAVAILABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_MGMT_STATUS_PMS_ADMIN_STATE_VOTE_AVAILABLE:
 
      printf("hasim :        received MGMT_STATUS PMS ADMIN STATE VOTE AVAILABLE\
        ..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_MGMT_STATUS_PMS_ADMIN_STATE_FORCE_AVAILABLE:
 
      printf("hasim :        received MGMT_STATUS PMS ADMIN STATE FORCE \
        AVAILABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_MGMT_STATUS_PMS_PERFORMANCE_DEGRADED:
 
      printf("hasim :        received MGMT_STATUS PMS PERFORMANCE DEGRADED..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_MGMT_STATUS_RND_ADDRESS_ADD:
    case PMS_PD_MGMT_STATUS_RND_ADDRESS_DELETE:
 
      if (pr->payload.data.mgmt_status.code == \
        PMS_PD_MGMT_STATUS_RND_ADDRESS_ADD)
        printf("hasim :        received MGMT_STATUS RND ADDRESS ADD..\n");
      else
        printf("hasim :        received MGMT_STATUS RND ADDRESS DELETE..\n");
 
 
      info_get_fail = 0;
 
 
      /* Get MGMT rnd address information.. */
 
      ps.session.type = PMS_SR_CALL_RETURN_TIMED;
      ps.session.info.crt.time = 0;
      ps.payload.type = PMS_PD_MGMT_RND_ADDRESS_INFO_GET_EXECUTE;
 
      for(i=0;i<16;i++)
        {
        ps.payload.data.mgmt_rnd_address_info_get_execute.index = i;
 
        if (pms_send(&ps, &prs) == 0)
          {
          if (prs.payload.data.mgmt_rnd_address_info_get_status.err == \
            PMS_PD_MGMT_RND_ADDRESS_INFO_GET_STATUS_ERR_NONE)
            {
            rnd_address_identifier[i] = \
              prs.payload.data.mgmt_rnd_address_info_get_status.identifier;
            strncpy(&rnd_address_node_ip_address[i][0], \
              &prs.payload.data.mgmt_rnd_address_info_get_status.node_ip_address[0], 20);
            strncpy(&rnd_address_drawer_ip_address[i][0], \
              &prs.payload.data.mgmt_rnd_address_info_get_status.drawer_ip_address[0], 20);
            rnd_address_node_slot_number[i] = \
              prs.payload.data.mgmt_rnd_address_info_get_status.node_slot_number;
            }
          else
            {
            info_get_fail = 1;
            }
          }
        else
          {
          info_get_fail = 1;
          }
        }
 
 
      if (info_get_fail == 0)
        {
 
 
 
 
 
 
        for(i=0;i<16;i++)
          {
          mdi.mgmt_info.rnd_address_cache[i].identifier = \
            rnd_address_identifier[i];
          strncpy(&mdi.mgmt_info.rnd_address_cache[i].node_ip_address[0], \
            &rnd_address_node_ip_address[i][0], 20);
          strncpy(&mdi.mgmt_info.rnd_address_cache[i].drawer_ip_address[0], \
            &rnd_address_drawer_ip_address[i][0], 20);
          mdi.mgmt_info.rnd_address_cache[i].node_slot_number = \
            rnd_address_node_slot_number[i];
          }
 
        mdi.mgmt_info.last_update = 0;
        }
 
 
      app_hasim_process();
 
    break;
    case PMS_PD_MGMT_STATUS_PMS_ADMIN_STATE_AV_RG0VA_DELAY:
 
      printf("hasim :        received MGMT_STATUS PMS ADMIN STATE AV RG0VA \
         DELAY..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    }
 
}
 
 
 
void
app_hasim_receive_node_rg0_status(struct pms_receive* pr)
{
 
 
  switch(pr->payload.data.node_rg0_status.code)
    {
    case PMS_PD_NODE_RG0_STATUS_STATE_ACTIVE:
 
      printf("hasim :        received NODE_RG0_STATUS STATE ACTIVE..\n");
 
      mdi.node_info.rg0_state_cache = PMS_PD_NODE_RG0_INFO_GET_STATUS_ACTIVE;
      mdi.node_info.last_update = 0;
 
      app_hasim_process();
 
    break;
    case PMS_PD_NODE_RG0_STATUS_STATE_OFFLINE:
 
      printf("hasim :        received NODE_RG0_STATUS STATE OFFLINE..\n");
 
      mdi.node_info.rg0_state_cache = PMS_PD_NODE_RG0_INFO_GET_STATUS_OFFLINE;
      mdi.node_info.last_update = 0;
 
      app_hasim_process();
 
    break;
    case PMS_PD_NODE_RG0_STATUS_ADMIN_STATE_FORCE_OFFLINE:
 
      printf("hasim :        received NODE_RG0_STATUS ADMIN STATE FORCE \
         OFFLINE ..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_NODE_RG0_STATUS_ADMIN_STATE_VOTE_ACTIVE:
 
      printf("hasim :        received NODE_RG0_STATUS ADMIN STATE VOTE \
         ACTIVE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_NODE_RG0_STATUS_ADMIN_STATE_FORCE_ACTIVE:
 
      printf("hasim :        received NODE_RG0_STATUS ADMIN STATE FORCE \
         ACTIVE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_NODE_RG0_STATUS_APP_STATE_SET_FAULT:
 
      printf("hasim :        received NODE_RG0_STATUS APP STATE SET FAULT..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_NODE_RG0_STATUS_ADOPER_STATUSMASK_SET:
 
      printf("hasim :        received NODE_RG0_STATUS ADOPER STATUSMASK SET..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    }
 
}
 
 
 
void
app_hasim_receive_node_rg0_app_state_set_execute(struct pms_receive* pr)
{
 
  struct pms_send               ps;
 
 
  switch(pr->payload.data.node_rg0_app_state_set_execute.state)
    {
    case PMS_PD_NODE_RG0_APP_STATE_SET_EXECUTE_ACTIVE:
 
      printf("hasim :        received NODE_RG0_APP_STATE_SET_EXECUTE ACTIVE..\n");
 
 
      /* Do whatever, within pr->session.info.crt.time if possible.. */
 
 
      /* Send return message indicating successful reception.. */
 
      ps.session.type = PMS_SR_RETURN;
      ps.session.info.r.return_identifier = \
        pr->session.info.crt.call_identifier;
      ps.session.info.r.return_priority = pr->session.info.crt.return_priority;
 
      ps.payload.type = PMS_PD_NODE_RG0_APP_STATE_SET_STATUS;
      ps.payload.data.node_rg0_app_state_set_status.err = \
        PMS_PD_NODE_RG0_APP_STATE_SET_STATUS_SUCCESS;
 
 
      if (pms_send(&ps, 0) != 0)
        {
        }
 
    break;
    case PMS_PD_NODE_RG0_APP_STATE_SET_EXECUTE_OFFLINE:
 
      printf("hasim :        received NODE_RG0_APP_STATE_SET_EXECUTE OFFLINE\         ..\n");
 
 
      /* Do whatever, within pr->session.info.crt.time if possible.. */
 
 
      ps.session.type = PMS_SR_RETURN;
      ps.session.info.r.return_identifier = \
          pr->session.info.crt.call_identifier;
      ps.session.info.r.return_priority = pr->session.info.crt.return_priority;
 
      ps.payload.type = PMS_PD_NODE_RG0_APP_STATE_SET_STATUS;
      ps.payload.data.node_rg0_app_state_set_status.err = \
        PMS_PD_NODE_RG0_APP_STATE_SET_STATUS_SUCCESS;
 
 
      if (pms_send(&ps, 0) != 0)
        {
        }
 
    break;
    };
 
}
 
 
 
void
app_hasim_receive_rnd_status(struct pms_receive* pr)
{
 
 
  printf("hasim :        rs.identifier=%.8X\n", \
     pr->payload.data.rnd_status.identifier);
 
 
  switch(pr->payload.data.rnd_status.code)
    {
    case PMS_PD_RND_STATUS_VIEW_NODE_REACHABLE_DRAWER_REACHABLE:
 
      printf("hasim :        received RND_STATUS NODE REACHABLE DRAWER \
         REACHABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_STATUS_VIEW_NODE_REACHABLE_DRAWER_UNREACHABLE:
 
      printf("hasim :        received RND_STATUS NODE REACHABLE DRAWER\
         UNREACHABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_STATUS_VIEW_NODE_UNREACHABLE_DRAWER_REACHABLE:
 
      printf("hasim :        received RND_STATUS NODE UNREACHABLE DRAWER\
         REACHABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_STATUS_VIEW_NODE_UNREACHABLE_DRAWER_UNREACHABLE:
 
      printf("hasim :        received RND_STATUS NODE UNREACHABLE DRAWER\         UNREACHABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_STATUS_ADOPER_FORCE_UNAVAILABLE:
 
      printf("hasim :        received RND_STATUS ADOPER FORCE UNAVAILABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_STATUS_ADOPER_VOTE_AVAILABLE:
 
      printf("hasim :        received RND_STATUS ADOPER VOTE AVAILABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_STATUS_ADOPER_FORCE_AVAILABLE:
 
      printf("hasim :        received RND_STATUS ADOPER FORCE AVAILABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_STATUS_ADOPER_STATUSMASK_SET:
 
      printf("hasim :        received RND_STATUS ADOPER STATUSMASK SET..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_STATUS_STATE_UNAVAILABLE:
 
      printf("hasim :        received RND_STATUS STATE UNAVAILABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_STATUS_STATE_AVAILABLE:
 
      printf("hasim :        received RND_STATUS STATE AVAILABLE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    }
 
}
 
 
 
void
app_hasim_receive_rnd_md0_status(struct pms_receive* pr)
{
 
 
  printf("hasim :        rms.identifier=%.8X\n", \
     pr->payload.data.rnd_md0_status.identifier);
 
 
  switch(pr->payload.data.rnd_md0_status.code)
    {
    case PMS_PD_RND_MD0_STATUS_ADOPER_CONFIG_MAINTENANCE:
 
      printf("hasim :        received RND_MD0_STATUS ADOPER CONFIG \
         MAINTENANCE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_ADOPER_CONFIG_OPERATIONAL:
 
      printf("hasim :        received RND_MD0_STATUS ADOPER CONFIG \
         OPERATIONAL..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_ADOPER_GRACEFUL_REBOOT:
 
      printf("hasim :        received RND_MD0_STATUS ADOPER GRACEFUL REBOOT..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_ADOPER_STATUSMASK_SET:
 
      printf("hasim :        received RND_MD0_STATUS ADOPER STATUSMASK SET..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_ADOPER_RECOVERY_PC:
 
      printf("hasim :        received RND_MD0_STATUS ADOPER RECOVERY PC..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_ADOPER_RECOVERY_RST:
 
      printf("hasim :        received RND_MD0_STATUS ADOPER RECOVERY RST..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_ADOPER_RECOVERY_RSTPC:
 
      printf("hasim :        received RND_MD0_STATUS ADOPER RECOVERY RSTPC..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_ADOPER_RECOVERY_PD:
      printf("hasim :        received RND_MD0_STATUS ADOPER RECOVERY PD..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_ADOPER_RECOVERY_RB:
 
      printf("hasim :        received RND_MD0_STATUS ADOPER RECOVERY RB..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_ADOPER_RECOVERYAUTOMODE_SET:
 
      printf("hasim :        received RND_MD0_STATUS ADOPER RECOVERYAUTOMODE\
         SET..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_ADOPER_SCDM_TIMEOUT:
 
      printf("hasim :        received RND_MD0_STATUS ADOPER SCDM TIMEOUT..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_CONFIG_MAINTENANCE:
 
      printf("hasim :        received RND_MD0_STATUS CONFIG MAINTENANCE..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    case PMS_PD_RND_MD0_STATUS_CONFIG_OPERATIONAL:
 
      printf("hasim :        received RND_MD0_STATUS CONFIG OPERATIONAL..\n");
 
      /* Doing nothing at the moment.. */
 
    break;
    }
 
}
 

 

The following example shows a PMS client's scheduling.

CODE EXAMPLE 7-4 PMS Client Scheduling Example

void
app_hasim_receive_time_status(void)
{
 
  int                   i;
  mdi.mgmt_info.last_update += HASIM_CHECK_INTERVAL;
  mdi.mgmt_info.last_sync_check += HASIM_CHECK_INTERVAL;
 
  mdi.node_info.last_update += HASIM_CHECK_INTERVAL;
  mdi.node_info.last_sync_check += HASIM_CHECK_INTERVAL;
 
  for(i=0;i<16;i++)
    {
    mdi.rnd_info[i].last_update += HASIM_CHECK_INTERVAL;
    mdi.rnd_info[i].last_sync_check += HASIM_CHECK_INTERVAL;
    }
 
 
  app_hasim_process();
 
 
}
 
 
 
void
app_hasim_process(void)
{
 
 
  /* Run state machine sub-groupings.. */
 
  app_hasim_user_process();
 
  app_hasim_mgmt_process();
 
  app_hasim_node_process();
 
  app_hasim_rnd_process();
 
 
}

 

The following example shows the PMS client's user management interface.

 

CODE EXAMPLE 7-5 PMS Client User and Management Interface

void
app_hasim_user_process(void)
{
 
  struct pms_receive    pr;
 
  int                   i;
 
 
 
 
 
  /* PMS View check */
 
  /* Periodically attempt to connect if unreachable. Return to initial
     state variable settings on reachable to unreachable transition.. */
 
  if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_UNREACHABLE)
    {
    if (pms_connect(PMS_SERVER_PORT_NUMBER_DEFAULT) != 0)
      {
      }
    else
      {
      mdi.user_info.pms_view = HASIM_USER_PMS_VIEW_REACHABLE;
      mdi.user_info.view_cache = PMS_PD_USER_STATUS_PMS_REACHABLE;
      }
    }
  else /* mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE */
    {
    if (mdi.user_info.view_cache == PMS_PD_USER_STATUS_PMS_UNREACHABLE)
      {
 
      /* RND */
 
      for(i=0;i<16;i++)
        {
 
        mdi.rnd_info[i].cache_state = HASIM_RND_CACHE_INVALID;
        mdi.rnd_info[i].last_update = HASIM_CHECK_INVALID_INTERVAL;
 
        if ((mdi.rnd_info[i].receive_state & HASIM_RND_RECEIVE_REGISTERED) != 0)
          {
          pr.session.type = PMS_SR_CALL_NO_RETURN;
          pr.payload.type = PMS_PD_RND_STATUS;
          pr.payload.data.rnd_status.identifier = \
            mdi.mgmt_info.rnd_address_identifier[i];
          pms_receive(&pr, 0, 0);
          mdi.rnd_info[i].receive_state &= !HASIM_RND_RECEIVE_REGISTERED;
          }
 
        if ((mdi.rnd_info[i].receive_state & HASIM_RND_MD0_RECEIVE_REGISTERED)\  
              != 0)
          {
          pr.session.type = PMS_SR_CALL_NO_RETURN;
          pr.payload.type = PMS_PD_RND_MD0_STATUS;
          pr.payload.data.rnd_status.identifier = \
            mdi.mgmt_info.rnd_address_identifier[i];
          pms_receive(&pr, 0, 0);
          mdi.rnd_info[i].receive_state &= !HASIM_RND_MD0_RECEIVE_REGISTERED;
 }
 
        }
 
 
      /* NODE */
 
      mdi.node_info.cache_state = HASIM_NODE_CACHE_INVALID;
      mdi.node_info.last_update = HASIM_CHECK_INVALID_INTERVAL;
 
      if (mdi.node_info.service_state == HASIM_NODE_SERVICE_STATE_ACTIVE)
        {
        mdi.node_info.service_state = HASIM_NODE_SERVICE_STATE_OFFLINE;
        }
 
      if (mdi.node_info.rg0_app_name_state ==\ 
            HASIM_NODE_RG0_APP_NAME_REGISTERED)
        {
        mdi.node_info.rg0_app_name_state = HASIM_NODE_RG0_APP_NAME_UNREGISTERED;
        }
 
      if ((mdi.node_info.receive_state &\   
             HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED) != 0)
        {
        pr.session.type = PMS_SR_CALL_NO_RETURN;
        pr.payload.type = PMS_PD_NODE_RG0_STATUS;
        pms_receive(&pr, 0, 0);
        mdi.node_info.receive_state &=\          
          !HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED;
        }
 
      if ((mdi.node_info.receive_state & \
        HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED) != 0)
        {
        pr.session.type = PMS_SR_CALL_RETURN_TIMED;
        pr.payload.type = PMS_PD_NODE_RG0_APP_STATE_SET_EXECUTE;
        pms_receive(&pr, 0, 0);
        mdi.node_info.receive_state &= \          
          !HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED;
        }
 
 
      /* MGMT */
 
      mdi.mgmt_info.cache_state = HASIM_MGMT_CACHE_INVALID;
      mdi.mgmt_info.last_update = HASIM_CHECK_INVALID_INTERVAL;
 
      for(i=0;i<16;i++)
        mdi.mgmt_info.rnd_address_identifier[i] = -1;
 
      if (mdi.mgmt_info.rnd_address_state == HASIM_MGMT_RND_ADDRESS_VERIFIED)
        {
        mdi.mgmt_info.rnd_address_state = HASIM_MGMT_RND_ADDRESS_UNVERIFIED;
        }
 
      if (mdi.mgmt_info.pms_state == HASIM_MGMT_PMS_STATE_AVAILABLE)
        {
        mdi.mgmt_info.pms_state = HASIM_MGMT_PMS_STATE_UNAVAILABLE;
        }
 
      if (mdi.mgmt_info.receive_state == HASIM_MGMT_RECEIVE_REGISTERED)
        {
        pr.session.type = PMS_SR_CALL_NO_RETURN;
        pr.payload.type = PMS_PD_MGMT_STATUS;
        pms_receive(&pr, 0, 1);
 
        mdi.mgmt_info.receive_state = HASIM_MGMT_RECEIVE_UNREGISTERED;
        }
 
 
      /* USER */
 
      if (mdi.user_info.receive_state == HASIM_USER_RECEIVE_REGISTERED)
        {
        pr.session.type = PMS_SR_CALL_NO_RETURN;
        pr.payload.type = PMS_PD_USER_STATUS;
        pms_receive(&pr, 0, 0);
 
        mdi.user_info.receive_state = HASIM_USER_RECEIVE_UNREGISTERED;
        }
 
      if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
        {
        pms_disconnect();
 
        mdi.user_info.pms_view = HASIM_USER_PMS_VIEW_UNREACHABLE;
        }
 
      }
    }
 
 
  /* Receive Check */
 
  /* If USER messages are not receive registered, attempt to register if PMS
     is reachable.. */
 
  if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
    {
    if (mdi.user_info.receive_state != HASIM_USER_RECEIVE_REGISTERED)
      {
      pr.session.type = PMS_SR_CALL_NO_RETURN;
      pr.payload.type = PMS_PD_USER_STATUS;
      if (pms_receive(&pr, app_hasim_receive_post, 0) != -1)
        mdi.user_info.receive_state = HASIM_USER_RECEIVE_REGISTERED;
      }
    }
 
 
}
 
 
 
void
app_hasim_mgmt_process(void)
{
 
  struct pms_send       ps;
  struct pms_receive    pr;
 
  int                   info_get_fail;
 
  int                   match[HASIM_RND_ADDRESS_AUDIT_ENTRYS];
 
  int                   mgmt_state;
  int                   rnd_address_identifier[16];
  char                  rnd_address_node_ip_address[16][20];
  char                  rnd_address_drawer_ip_address[16][20];
  int                   rnd_address_node_slot_number[16];
 
  int                   i, j;
 
 
  /* Receive Check */
 
  /* If MGMT messages are not receive registered, attempt to register if PMS
     is reachable and USER receive messages are registered.  If registration
     is successful, force an initial cache update.. */
 
  if (mdi.mgmt_info.receive_state != HASIM_MGMT_RECEIVE_REGISTERED)
    {
    if (mdi.user_info.receive_state == HASIM_USER_RECEIVE_REGISTERED)
      {
      if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
        {
        pr.session.type = PMS_SR_CALL_NO_RETURN;
        pr.payload.type = PMS_PD_MGMT_STATUS;
        if (pms_receive(&pr, app_hasim_receive_post, 1) != -1)
          mdi.mgmt_info.receive_state = HASIM_MGMT_RECEIVE_REGISTERED;
 
        /* Force an info_get immediately after registering.. */
        mdi.mgmt_info.last_sync_check = HASIM_SYNCCHECK_INTERVAL;
        }
      }
    }
 
 
  /* PMS State check */
 
  /* Process PMS state transitions.  On an available to unavailable transition
     return to pre-NODE and RND operational state variable settings.. */
 
  if (mdi.mgmt_info.pms_state == HASIM_MGMT_PMS_STATE_UNAVAILABLE)
    {
    if (mdi.mgmt_info.cache_state != HASIM_MGMT_CACHE_INVALID)
      {
      if (mdi.mgmt_info.mgmt_state_cache != \
            PMS_PD_MGMT_INFO_GET_STATUS_UNAVAILABLE)
        {
        mdi.mgmt_info.pms_state = HASIM_MGMT_PMS_STATE_AVAILABLE;
        }
      }
    }
  else /* mdi.mgmt_info.pms_state == HASIM_MGMT_PMS_STATE_AVAILABLE */
    {
    if (mdi.mgmt_info.cache_state != HASIM_MGMT_CACHE_INVALID)
      {
      if (mdi.mgmt_info.mgmt_state_cache == \
            PMS_PD_MGMT_INFO_GET_STATUS_UNAVAILABLE)
        {
 
        /* RND */
 
        for(i=0;i<16;i++)
          {
 
          if ((mdi.rnd_info[i].receive_state & \
                 HASIM_RND_RECEIVE_REGISTERED) != 0)
            {
            pr.session.type = PMS_SR_CALL_NO_RETURN;
            pr.payload.type = PMS_PD_RND_STATUS;
            pr.payload.data.rnd_status.identifier = \
              mdi.mgmt_info.rnd_address_identifier[i];
            pms_receive(&pr, 0, 0);
            mdi.rnd_info[i].receive_state &= !HASIM_RND_RECEIVE_REGISTERED;
            }
 
 
 
 
 
 
          if ((mdi.rnd_info[i].receive_state & HASIM_RND_MD0_RECEIVE_REGISTERED)\ 
               != 0)
            {
            pr.session.type = PMS_SR_CALL_NO_RETURN;
            pr.payload.type = PMS_PD_RND_MD0_STATUS;
            pr.payload.data.rnd_status.identifier = \
              mdi.mgmt_info.rnd_address_identifier[i];
            pms_receive(&pr, 0, 0);
            mdi.rnd_info[i].receive_state &= !HASIM_RND_MD0_RECEIVE_REGISTERED;
            }
 
          }
 
 
        /* NODE */
 
      if (mdi.node_info.service_state == HASIM_NODE_SERVICE_STATE_ACTIVE)
        {
        mdi.node_info.service_state = HASIM_NODE_SERVICE_STATE_OFFLINE;
        }
 
      if (mdi.node_info.rg0_app_name_state == \
            HASIM_NODE_RG0_APP_NAME_REGISTERED)
        {
        mdi.node_info.rg0_app_name_state = HASIM_NODE_RG0_APP_NAME_UNREGISTERED;
        }
 
 
      if ((mdi.node_info.receive_state &\              
             HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED) != 0)
        {
        pr.session.type = PMS_SR_CALL_NO_RETURN;
        pr.payload.type = PMS_PD_NODE_RG0_STATUS;
        pms_receive(&pr, 0, 0);
        mdi.node_info.receive_state &=\ 
          !HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED;
        }
 
      if ((mdi.node_info.receive_state & \
        HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED) != 0)
        {
        pr.session.type = PMS_SR_CALL_RETURN_TIMED;
        pr.payload.type = PMS_PD_NODE_RG0_APP_STATE_SET_EXECUTE;
        pms_receive(&pr, 0, 0);
        mdi.node_info.receive_state &= \
          !HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED;
        }
 
 
        mdi.mgmt_info.pms_state = HASIM_MGMT_PMS_STATE_UNAVAILABLE;
        }
      }
    }
 
 
 
  /* RND Address Check */
 
  /* Check once at startup if the RND address pairs currently in the list
     are the same as this control application's defaults.  If not, remove
     any that differ and add any that are missing.  This is a bit contrived
     to demonstrate interaction via the address list messages.  No point
     in starting processing if cache is invalid and PMS is not reachable
     and USER registration is not completed.. */
 
  if (mdi.mgmt_info.rnd_address_state != HASIM_MGMT_RND_ADDRESS_VERIFIED)
    {
    if (mdi.mgmt_info.cache_state != HASIM_MGMT_CACHE_INVALID)
      {
      if (mdi.user_info.receive_state == HASIM_USER_RECEIVE_REGISTERED)
        {
        if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
          {
 
          match[0] = 0;
          match[1] = 0;
 
          /* Search RND address list for entries not in the app's verify list.. */
 
          for(i=0;i<16;i++)
            {
            if (mdi.mgmt_info.rnd_address_cache[i].identifier != -1)
              {
              for(j=0;j<HASIM_RND_ADDRESS_AUDIT_ENTRYS;j++)
                {
                if (match[j] == 0)
                  {
                  /* Use strcmp() for the moment. Use sockaddr_in when \
                     I get around to it.. */
                  if \  
           (strcmp(&mdi.mgmt_info.rnd_address_cache[i].node_ip_address[0], \
                    &mdi.rnd_address[j].node_ip_address[0]) == 0)
                    {
                    if\ 
           (strcmp(&mdi.mgmt_info.rnd_address_cache[i].drawer_ip_address[0], \
                      &mdi.rnd_address[j].drawer_ip_address[0]) == 0)
                      {
                      if (mdi.mgmt_info.rnd_address_cache[i].node_slot_number == \
                        mdi.rnd_address[j].node_slot_number)
                        {
                        match[j] = 1;
 
                        break;
                        }
                      }
                    }
                  }
                }
 
              /* Delete entries not in the app's verify list.. */
 
              if (j == HASIM_RND_ADDRESS_AUDIT_ENTRYS)
                {
                ps.session.type = PMS_SR_CALL_RETURN_TIMED;
                ps.session.info.crt.time = 0;
                ps.payload.type = PMS_PD_MGMT_RND_ADDRESS_DELETE_EXECUTE;
 
                ps.payload.data.mgmt_rnd_address_delete_execute.identifier = \
                  mdi.mgmt_info.rnd_address_cache[i].identifier;
                  
                if (pms_send(&ps, &pr) == 0)
                  {
                  if (pr.payload.data.mgmt_rnd_address_delete_status.err == \
                    PMS_PD_MGMT_RND_ADDRESS_DELETE_STATUS_ERR_NONE)
                    {
                    }
                  }
                }
 
              }
            }
 
          /* Add any missing entries.. */
 
          for(i=0;i<HASIM_RND_ADDRESS_AUDIT_ENTRYS;i++)
            {
            if (match[i] == 0)
              {
              ps.session.type = PMS_SR_CALL_RETURN_TIMED;
              ps.session.info.crt.time = 0;
              ps.payload.type = PMS_PD_MGMT_RND_ADDRESS_ADD_EXECUTE;
 
 strncpy(&ps.payload.data.mgmt_rnd_address_add_execute.node_ip_address[0], \
                &mdi.rnd_address[i].node_ip_address[0], 20);
 strncpy(&ps.payload.data.mgmt_rnd_address_add_execute.drawer_ip_address[0], \
                &mdi.rnd_address[i].drawer_ip_address[0], 20);
              ps.payload.data.mgmt_rnd_address_add_execute.node_slot_number = \
                mdi.rnd_address[i].node_slot_number;
                  
              if (pms_send(&ps, &pr) == 0)
                {
                if (pr.payload.data.mgmt_rnd_address_add_status.err == \
                  PMS_PD_MGMT_RND_ADDRESS_ADD_STATUS_ERR_NONE)
                  {
                  }
                }
              }
            }
 
 
          mdi.mgmt_info.rnd_address_state = HASIM_MGMT_RND_ADDRESS_VERIFIED;
          }
        }
      }
    }
 
 
  /* RND Address Identifier check */
 
  /* Process RND address identifier transitions.  On in-use to not-in-use
     transitions, return state variables to pre-RND initialized state for that
     identifier.  Check whether any list entries have been deleted and re-added
     since last processing and do an available->unavailable->available      transition.. */
 
  for(i=0;i<16;i++)
    {
 
    if (mdi.mgmt_info.rnd_address_identifier[i] == -1)
      {
 
      if (mdi.mgmt_info.cache_state != HASIM_MGMT_CACHE_INVALID)
        {
        if (mdi.mgmt_info.rnd_address_cache[i].identifier != -1)
          {
          mdi.mgmt_info.rnd_address_identifier[i] =\ 
             mdi.mgmt_info.rnd_address_cache[i].identifier;
          }
        }
 
      }
    else /* mdi.mgmt_info.rnd_address_identifier[i] != -1 */
      {
 
      if (mdi.mgmt_info.cache_state != HASIM_MGMT_CACHE_INVALID)
        {
 
        if (mdi.mgmt_info.rnd_address_cache[i].identifier == -1)
          {
 
          /* RND */
 
          if ((mdi.rnd_info[i].receive_state & HASIM_RND_RECEIVE_REGISTERED)\
               != 0)
            {
            pr.session.type = PMS_SR_CALL_NO_RETURN;
            pr.payload.type = PMS_PD_RND_STATUS;
            pr.payload.data.rnd_status.identifier = \
              mdi.mgmt_info.rnd_address_identifier[i];
            pms_receive(&pr, 0, 0);
            mdi.rnd_info[i].receive_state &= !HASIM_RND_RECEIVE_REGISTERED;
            }
 
          if ((mdi.rnd_info[i].receive_state & HASIM_RND_MD0_RECEIVE_REGISTERED)\ 
               != 0)
            {
            pr.session.type = PMS_SR_CALL_NO_RETURN;
            pr.payload.type = PMS_PD_RND_MD0_STATUS;
            pr.payload.data.rnd_status.identifier = \
              mdi.mgmt_info.rnd_address_identifier[i];
            pms_receive(&pr, 0, 0);
            mdi.rnd_info[i].receive_state &= !HASIM_RND_MD0_RECEIVE_REGISTERED;
            }
 
 
          mdi.mgmt_info.rnd_address_identifier[i] = -1;
          }
        else
          {
          if (mdi.mgmt_info.rnd_address_identifier[i] != \
            mdi.mgmt_info.rnd_address_cache[i].identifier)
            {
            /* RND */
 
            if ((mdi.rnd_info[i].receive_state & HASIM_RND_RECEIVE_REGISTERED)\ 
                  != 0)
              {
              pr.session.type = PMS_SR_CALL_NO_RETURN;
              pr.payload.type = PMS_PD_RND_STATUS;
              pr.payload.data.rnd_status.identifier = \
                mdi.mgmt_info.rnd_address_identifier[i];
              pms_receive(&pr, 0, 0);
              mdi.rnd_info[i].receive_state &= !HASIM_RND_RECEIVE_REGISTERED;
              }
 
            if ((mdi.rnd_info[i].receive_state & \
                   HASIM_RND_MD0_RECEIVE_REGISTERED) != 0)
              {
              pr.session.type = PMS_SR_CALL_NO_RETURN;
              pr.payload.type = PMS_PD_RND_MD0_STATUS;
              pr.payload.data.rnd_status.identifier = \
                mdi.mgmt_info.rnd_address_identifier[i];
              pms_receive(&pr, 0, 0);
              mdi.rnd_info[i].receive_state &= !HASIM_RND_MD0_RECEIVE_REGISTERED;
              }
 
            mdi.mgmt_info.rnd_address_identifier[i] =\ 
               mdi.mgmt_info.rnd_address_cache[i].identifier;
            }
          }
 
        }
 
      }
 
    }
 
 
  /* Sync Check */
 
  /* Policy: Sync update checked every SYNCCHECK_INTERVAL seconds.. */
  if (mdi.mgmt_info.last_sync_check > HASIM_SYNCCHECK_INTERVAL)
    {
    /* Policy:  Don't attempt a sync update if any async partial updates have
       been received within SYNCCHECK_INTERVAL.. */
    if (mdi.mgmt_info.last_update > HASIM_SYNCCHECK_INTERVAL)
      {
      /* Policy:  Don't attempt a sync update if registration for async
         updates have not succeeded.. */
      if (mdi.mgmt_info.receive_state == HASIM_MGMT_RECEIVE_REGISTERED)
        {
        if (mdi.user_info.receive_state == HASIM_USER_RECEIVE_REGISTERED)
          {
          if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
            {
            mdi.mgmt_info.last_sync_check = 0;
 
            info_get_fail = 0;
 
            /* Get MGMT base information.. */
            ps.session.type = PMS_SR_CALL_RETURN_TIMED;
            ps.session.info.crt.time = 0;
            ps.payload.type = PMS_PD_MGMT_INFO_GET_EXECUTE;
 
            if (pms_send(&ps, &pr) == 0)
              {
              if (pr.payload.data.mgmt_info_get_status.err == \
                PMS_PD_MGMT_INFO_GET_STATUS_SUCCESS)
                {
                mgmt_state = pr.payload.data.mgmt_info_get_status.state;
                }
              else
                {
                info_get_fail = 1;
                }
              }
            else
              {
              info_get_fail = 1;
              }
 
 
            /* Get MGMT rnd address information.. */
 
            ps.session.type = PMS_SR_CALL_RETURN_TIMED;
            ps.session.info.crt.time = 0;
            ps.payload.type = PMS_PD_MGMT_RND_ADDRESS_INFO_GET_EXECUTE;
 
            for(i=0;i<16;i++)
              {
              ps.payload.data.mgmt_rnd_address_info_get_execute.index = i;
 
              if (pms_send(&ps, &pr) == 0)
                {
                if (pr.payload.data.mgmt_rnd_address_info_get_status.err == \
                  PMS_PD_MGMT_RND_ADDRESS_INFO_GET_STATUS_ERR_NONE)
                  {
                  rnd_address_identifier[i] = \
                    pr.payload.data.mgmt_rnd_address_info_get_status.identifier;
                  strncpy(&rnd_address_node_ip_address[i][0], \
 &pr.payload.data.mgmt_rnd_address_info_get_status.node_ip_address[0], 20);
                  strncpy(&rnd_address_drawer_ip_address[i][0], \
 &pr.payload.data.mgmt_rnd_address_info_get_status.drawer_ip_address[0], 20);
                  rnd_address_node_slot_number[i] = \
 pr.payload.data.mgmt_rnd_address_info_get_status.node_slot_number;
                  }
                else
                  {
                  info_get_fail = 1;
                  }
                }
              else
                {
                info_get_fail = 1;
                }
              }
 
            /* Only mark MGMT update as successful if all pieces of data
               were received successfully.. */
 
            if (info_get_fail == 0)
              {
              mdi.mgmt_info.mgmt_state_cache = mgmt_state;
 
              for(i=0;i<16;i++)
                {
                mdi.mgmt_info.rnd_address_cache[i].identifier = \
                  rnd_address_identifier[i];
                strncpy(&mdi.mgmt_info.rnd_address_cache[i].node_ip_address[0], \
                  &rnd_address_node_ip_address[i][0], 20);
 strncpy(&mdi.mgmt_info.rnd_address_cache[i].drawer_ip_address[0],\
                  &rnd_address_drawer_ip_address[i][0], 20);
                mdi.mgmt_info.rnd_address_cache[i].node_slot_number = \
                  rnd_address_node_slot_number[i];
                }
 
              mdi.mgmt_info.last_update = 0;
              }
 
            }
          }
        }
      }
    else
      {
      mdi.mgmt_info.last_sync_check = 0;
      }
    }
 
 
  /* Validity Check */
 
  /* Process cache state validity transitions.  The policy is on a MGMT cache
     transition to invalid, return state variables to initial configuration.. */
 
  if(mdi.mgmt_info.last_update < HASIM_CHECK_VALID_INTERVAL)
    {
    if (mdi.mgmt_info.cache_state != HASIM_MGMT_CACHE_VALID)
      mdi.mgmt_info.cache_state = HASIM_MGMT_CACHE_VALID;
    }
  else if((mdi.mgmt_info.last_update >= HASIM_CHECK_VALID_INTERVAL && \
    mdi.mgmt_info.last_update < HASIM_CHECK_INVALID_INTERVAL))
    {
    if (mdi.mgmt_info.cache_state == HASIM_MGMT_CACHE_VALID)
      mdi.mgmt_info.cache_state = HASIM_MGMT_CACHE_OLD;
    }
  else if(mdi.mgmt_info.last_update >= HASIM_CHECK_INVALID_INTERVAL)
    {
    if (mdi.mgmt_info.cache_state == HASIM_MGMT_CACHE_OLD)
      {
 
      /* RND */
 
      for(i=0;i<16;i++)
        {
 
        mdi.rnd_info[i].cache_state = HASIM_RND_CACHE_INVALID;
        mdi.rnd_info[i].last_update = HASIM_CHECK_INVALID_INTERVAL;
 
        if ((mdi.rnd_info[i].receive_state & HASIM_RND_RECEIVE_REGISTERED) != 0)
          {
          pr.session.type = PMS_SR_CALL_NO_RETURN;
          pr.payload.type = PMS_PD_RND_STATUS;
          pr.payload.data.rnd_status.identifier = \
            mdi.mgmt_info.rnd_address_identifier[i];
          pms_receive(&pr, 0, 0);
          mdi.rnd_info[i].receive_state &= !HASIM_RND_RECEIVE_REGISTERED;
          }
 
        if ((mdi.rnd_info[i].receive_state & HASIM_RND_MD0_RECEIVE_REGISTERED)\  
              != 0)
          {
          pr.session.type = PMS_SR_CALL_NO_RETURN;
          pr.payload.type = PMS_PD_RND_MD0_STATUS;
          pr.payload.data.rnd_status.identifier = \
            mdi.mgmt_info.rnd_address_identifier[i];
          pms_receive(&pr, 0, 0);
          mdi.rnd_info[i].receive_state &= !HASIM_RND_MD0_RECEIVE_REGISTERED;
          }
 
        }
 
 
      /* NODE*/
 
      mdi.node_info.cache_state = HASIM_NODE_CACHE_INVALID;
      mdi.node_info.last_update = HASIM_CHECK_INVALID_INTERVAL;
 
      if (mdi.node_info.service_state == HASIM_NODE_SERVICE_STATE_ACTIVE)
        {
        mdi.node_info.service_state = HASIM_NODE_SERVICE_STATE_OFFLINE;
        }
 
      if (mdi.node_info.rg0_app_name_state ==\             HASIM_NODE_RG0_APP_NAME_REGISTERED)
        {
        mdi.node_info.rg0_app_name_state = HASIM_NODE_RG0_APP_NAME_UNREGISTERED;
        }
 
      if ((mdi.node_info.receive_state &\ 
             HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED) != 0)
        {
        pr.session.type = PMS_SR_CALL_NO_RETURN;
        pr.payload.type = PMS_PD_NODE_RG0_STATUS;
        pms_receive(&pr, 0, 0);
        mdi.node_info.receive_state &=\           !HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED;
        }
 
      if ((mdi.node_info.receive_state & \
        HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED) != 0)
        {
        pr.session.type = PMS_SR_CALL_RETURN_TIMED;
        pr.payload.type = PMS_PD_NODE_RG0_APP_STATE_SET_EXECUTE;
        pms_receive(&pr, 0, 0);
        mdi.node_info.receive_state &=\  
         !HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED;
        }
 
 
      /* MGMT */
 
      mdi.mgmt_info.cache_state = HASIM_MGMT_CACHE_INVALID;
 
      for(i=0;i<16;i++)
        mdi.mgmt_info.rnd_address_identifier[i] = -1;
 
      if (mdi.mgmt_info.rnd_address_state == HASIM_MGMT_RND_ADDRESS_VERIFIED)
        {
        mdi.mgmt_info.rnd_address_state = HASIM_MGMT_RND_ADDRESS_UNVERIFIED;
        }
 
      if (mdi.mgmt_info.pms_state == HASIM_MGMT_PMS_STATE_AVAILABLE)
        {
        mdi.mgmt_info.pms_state = HASIM_MGMT_PMS_STATE_UNAVAILABLE;
        }
 
      if (mdi.mgmt_info.receive_state == HASIM_MGMT_RECEIVE_REGISTERED)
        {
        pr.session.type = PMS_SR_CALL_NO_RETURN;
        pr.payload.type = PMS_PD_MGMT_STATUS;
        pms_receive(&pr, 0, 1);
 
        mdi.mgmt_info.receive_state = HASIM_MGMT_RECEIVE_UNREGISTERED;
        }
 
 
      /* USER */
 
      if (mdi.user_info.receive_state == HASIM_USER_RECEIVE_REGISTERED)
        {
        pr.session.type = PMS_SR_CALL_NO_RETURN;
        pr.payload.type = PMS_PD_USER_STATUS;
        pms_receive(&pr, 0, 0);
 
        mdi.user_info.receive_state = HASIM_USER_RECEIVE_UNREGISTERED;
        }
 
      if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
        {
        pms_disconnect();
 
        mdi.user_info.pms_view = HASIM_USER_PMS_VIEW_UNREACHABLE;
        }
      }
    }
}

The following example shows the PMS client node interface.

CODE EXAMPLE 7-6 PMS Client Node Interface
void
app_hasim_node_process(void)
{
 
  struct pms_send       ps;
  struct pms_receive    pr;
 
  int                   info_get_fail;
 
  int                   rg0_state;
 
  int                   i;
 
 
  /* Receive Check */
 
  /* If NODE messages are not receive registered, attempt to register them if PMS
     is in the available state and reachable, and if USER receive messages are
     registered.  If registration is successful, force an initial cache
     update.. */
 
  if (mdi.node_info.receive_state != HASIM_NODE_GROUP_RECEIVE_REGISTERED)
    {
    if (mdi.mgmt_info.pms_state == HASIM_MGMT_PMS_STATE_AVAILABLE)
      {
      if (mdi.user_info.receive_state == HASIM_USER_RECEIVE_REGISTERED)
        {
        if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
          {
 
          if ((mdi.node_info.receive_state & \
             HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED) == 0)
            {
            pr.session.type = PMS_SR_CALL_NO_RETURN;
            pr.payload.type = PMS_PD_NODE_RG0_STATUS;
            if (pms_receive(&pr, app_hasim_receive_post, 0) != -1)
              mdi.node_info.receive_state |= \
                 HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED;
            }
 
          if ((mdi.node_info.receive_state & \
            HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED) == 0)
            {
            pr.session.type = PMS_SR_CALL_RETURN_TIMED;
            pr.session.info.crt.time = 50;
            pr.payload.type = PMS_PD_NODE_RG0_APP_STATE_SET_EXECUTE;
            if (pms_receive(&pr, app_hasim_receive_post, 0) != -1)
              mdi.node_info.receive_state |= \
                 HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED;
            }
 
          /* Force an info_get immediately after registering.. */
          mdi.node_info.last_sync_check = HASIM_SYNCCHECK_INTERVAL;
          }
        }
      }
    }
 
 
  /* Name Check */
 
  /* If this application's name is not registered, register it if PMS is
     available and reachable, and if USER registration is complete.. */
 
  if (mdi.node_info.rg0_app_name_state != HASIM_NODE_RG0_APP_NAME_REGISTERED)
    {
    if (mdi.mgmt_info.pms_state == HASIM_MGMT_PMS_STATE_AVAILABLE)
      {
      if (mdi.user_info.receive_state == HASIM_USER_RECEIVE_REGISTERED)
        {
        if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
          {
 
          /* Set NODE RG0 application name.. */
 
          ps.session.type = PMS_SR_CALL_RETURN_TIMED;
          ps.session.info.crt.time = 0;
          ps.payload.type = PMS_PD_NODE_RG0_APP_NAME_EXECUTE;
          strcpy(&ps.payload.data.node_rg0_app_name_execute.name[0], \
            "hasim");
          ps.payload.data.node_rg0_app_name_execute.command = \
            PMS_PD_NODE_RG0_APP_NAME_EXECUTE_ADD;
 
          if (pms_send(&ps, &pr) == 0)
            {
            if (pr.payload.data.node_rg0_app_name_status.err == \
              PMS_PD_NODE_RG0_APP_NAME_STATUS_ERR_NONE)
              {
              mdi.node_info.rg0_app_name_state = \
                 HASIM_NODE_RG0_APP_NAME_REGISTERED;
              }
            }
 
          }
        }
      }
    }
 
 
  /* Service State check */
 
  /* Process application service state transitions.  On an active-to-offline
     transition, return state variables to a pre-RND configuration.  This
     example's applications policy does not monitor RND pairs
     if it is offline.. */
 
  if (mdi.node_info.service_state == HASIM_NODE_SERVICE_STATE_OFFLINE)
    {
    if (mdi.node_info.cache_state != HASIM_NODE_CACHE_INVALID)
      {
      if (mdi.node_info.rg0_state_cache != \
          PMS_PD_NODE_RG0_INFO_GET_STATUS_OFFLINE)
        {
        mdi.node_info.service_state = HASIM_NODE_SERVICE_STATE_ACTIVE;
        }
      }
    }
  else /* mdi.node_info.service_state == HASIM_NODE_SERVICE_STATE_ACTIVE */
    {
    if (mdi.node_info.cache_state != HASIM_NODE_CACHE_INVALID)
      {
      if (mdi.node_info.rg0_state_cache == \          
          PMS_PD_NODE_RG0_INFO_GET_STATUS_OFFLINE)
        {
 
        /* RND */
 
        for(i=0;i<16;i++)
          {
 
          if ((mdi.rnd_info[i].receive_state & \
               HASIM_RND_RECEIVE_REGISTERED) != 0)
            {
            pr.session.type = PMS_SR_CALL_NO_RETURN;
            pr.payload.type = PMS_PD_RND_STATUS;
            pr.payload.data.rnd_status.identifier = \
              mdi.mgmt_info.rnd_address_identifier[i];
            pms_receive(&pr, 0, 0);
            mdi.rnd_info[i].receive_state &= !HASIM_RND_RECEIVE_REGISTERED;
            }
 
          if ((mdi.rnd_info[i].receive_state & HASIM_RND_MD0_RECEIVE_REGISTERED)\
             != 0)
            {
            pr.session.type = PMS_SR_CALL_NO_RETURN;
            pr.payload.type = PMS_PD_RND_MD0_STATUS;
            pr.payload.data.rnd_status.identifier = \
              mdi.mgmt_info.rnd_address_identifier[i];
            pms_receive(&pr, 0, 0);
            mdi.rnd_info[i].receive_state &= !HASIM_RND_MD0_RECEIVE_REGISTERED;
            }
 
          }
 
 
        mdi.node_info.service_state = HASIM_NODE_SERVICE_STATE_OFFLINE;
        }
      }
    }
 
 
  /* Sync Check */
 
  /* Policy: Sync update checked every SYNCCHECK_INTERVAL seconds.. */
  if (mdi.node_info.last_sync_check > HASIM_SYNCCHECK_INTERVAL)
    {
    /* Policy:  Don't attempt a sync update if any async partial updates have
       been received within SYNCCHECK_INTERVAL.. */
    if (mdi.node_info.last_update > HASIM_SYNCCHECK_INTERVAL)
      {
      /* Policy:  Don't attempt a sync update if registration for async
         updates have not succeeded.. */
      if (mdi.node_info.receive_state == HASIM_NODE_GROUP_RECEIVE_REGISTERED)
        {
        if (mdi.user_info.receive_state == HASIM_USER_RECEIVE_REGISTERED)
          {
          if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
            {
            mdi.node_info.last_sync_check = 0;
 
            info_get_fail = 0;
 
            /* Get NODE RG0 information.. */
            ps.session.type = PMS_SR_CALL_RETURN_TIMED;
            ps.session.info.crt.time = 0;
            ps.payload.type = PMS_PD_NODE_RG0_INFO_GET_EXECUTE;
 
            if (pms_send(&ps, &pr) == 0)
              {
              if (pr.payload.data.node_rg0_info_get_status.err == \
                PMS_PD_NODE_RG0_INFO_GET_STATUS_SUCCESS)
                {
                rg0_state = pr.payload.data.node_rg0_info_get_status.state;
                }
              else
                {
                info_get_fail = 1;
                }
              }
            else
              {
              info_get_fail = 1;
              }
 
 
            /* Get any other NODE info? */
 
 
            /* Only mark NODE update as successful if all pieces of data gotten
               were received successfully.. */
 
            if (info_get_fail == 0)
              {
              mdi.node_info.rg0_state_cache = rg0_state;
 
              mdi.node_info.last_update = 0;
              }
 
            }
          }
        }
      }
    else
      {
      mdi.node_info.last_sync_check = 0;
      }
    }
 
 
  /* Validity Check */
 
  /* Process cache state validity transitions.  The policy is that on a NODE cache
     transition to invalid, NODE AND RND state variables are returned to an 
     initial configuration.. */
 
  if(mdi.node_info.last_update < HASIM_CHECK_VALID_INTERVAL)
    {
    if (mdi.node_info.cache_state != HASIM_NODE_CACHE_VALID)
      mdi.node_info.cache_state = HASIM_NODE_CACHE_VALID;
    }
  else if((mdi.node_info.last_update >= HASIM_CHECK_VALID_INTERVAL && \
    mdi.node_info.last_update < HASIM_CHECK_INVALID_INTERVAL))
    {
    if (mdi.node_info.cache_state == HASIM_NODE_CACHE_VALID)
      mdi.node_info.cache_state = HASIM_NODE_CACHE_OLD;
    }
  else if(mdi.node_info.last_update >= HASIM_CHECK_INVALID_INTERVAL)
    {
    if (mdi.node_info.cache_state == HASIM_NODE_CACHE_OLD)
      {
 
      /* RND */
 
      for(i=0;i<16;i++)
        {
 
        if ((mdi.rnd_info[i].receive_state & HASIM_RND_RECEIVE_REGISTERED) != 0)
          {
          pr.session.type = PMS_SR_CALL_NO_RETURN;
          pr.payload.type = PMS_PD_RND_STATUS;
          pr.payload.data.rnd_status.identifier = \
            mdi.mgmt_info.rnd_address_identifier[i];
          pms_receive(&pr, 0, 0);
          mdi.rnd_info[i].receive_state &= !HASIM_RND_RECEIVE_REGISTERED;
          }
 
        if ((mdi.rnd_info[i].receive_state & HASIM_RND_MD0_RECEIVE_REGISTERED)\
            != 0)
          {
          pr.session.type = PMS_SR_CALL_NO_RETURN;
          pr.payload.type = PMS_PD_RND_MD0_STATUS;
          pr.payload.data.rnd_status.identifier = \
            mdi.mgmt_info.rnd_address_identifier[i];
          pms_receive(&pr, 0, 0);
          mdi.rnd_info[i].receive_state &= !HASIM_RND_MD0_RECEIVE_REGISTERED;
          }
 
        }
 
 
      /* NODE*/
 
      if (mdi.node_info.service_state == HASIM_NODE_SERVICE_STATE_ACTIVE)
        {
        mdi.node_info.service_state = HASIM_NODE_SERVICE_STATE_OFFLINE;
        }
 
      if (mdi.node_info.rg0_app_name_state == \
          HASIM_NODE_RG0_APP_NAME_REGISTERED)
        {
        mdi.node_info.rg0_app_name_state = HASIM_NODE_RG0_APP_NAME_UNREGISTERED;
        }
 
      if ((mdi.node_info.receive_state & \
          HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED) != 0)
        {
        pr.session.type = PMS_SR_CALL_NO_RETURN;
        pr.payload.type = PMS_PD_NODE_RG0_STATUS;
        pms_receive(&pr, 0, 0);
        mdi.node_info.receive_state &= \
         !HASIM_NODE_RG0_STATUS_RECEIVE_REGISTERED;
        }
 
      if ((mdi.node_info.receive_state & \
          HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED) != 0)
        {
        pr.session.type = PMS_SR_CALL_RETURN_TIMED;
        pr.payload.type = PMS_PD_NODE_RG0_APP_STATE_SET_EXECUTE;
        pms_receive(&pr, 0, 0);
        mdi.node_info.receive_state &= \
          !HASIM_NODE_RG0_APP_STATE_SET_EXECUTE_RECEIVE_REGISTERED;
        }
 
      }
    }
 
 
}

The following example shows a PMS client RND interface.

CODE EXAMPLE 7-7 PMS Client RND Interface

void
app_hasim_rnd_process(void)
{
 
  struct pms_send       ps;
  struct pms_receive    pr;
 
  int                   info_get_fail;
 
  int                   view;
  int                   md0_config;
 
  int                   i;
 
 
  /* Receive Check */
 
  /* If RND messages are not receive registered, attempt to register for
     in-use RND address list entries if the service state is active, if
     PMS is in the available state and reachable, and if USER receive messages
     are registered.  If registration is successful, force an initial cache
     update.. */
 
  for(i=0;i<16;i++)
    {
    if (mdi.rnd_info[i].receive_state != HASIM_RND_GROUP_RECEIVE_REGISTERED)
      {
      if (mdi.node_info.service_state == HASIM_NODE_SERVICE_STATE_ACTIVE)
        {
        if (mdi.mgmt_info.rnd_address_identifier[i] != -1)
          {
          if (mdi.mgmt_info.pms_state == HASIM_MGMT_PMS_STATE_AVAILABLE)
            {
            if (mdi.user_info.receive_state == HASIM_USER_RECEIVE_REGISTERED)
              {
              if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
                {
 
                if ((mdi.rnd_info[i].receive_state & \
                     HASIM_RND_RECEIVE_REGISTERED) == 0)
                  {
                  pr.session.type = PMS_SR_CALL_NO_RETURN;
                  pr.payload.type = PMS_PD_RND_STATUS;
                  pr.payload.data.rnd_status.identifier = \
                    mdi.mgmt_info.rnd_address_cache[i].identifier;
                  if (pms_receive(&pr, app_hasim_receive_post, 0) != -1)
                    mdi.rnd_info[i].receive_state |= HASIM_RND_RECEIVE_REGISTERED;
                  }
 
                if ((mdi.rnd_info[i].receive_state & \           
                     HASIM_RND_MD0_RECEIVE_REGISTERED) == 0)
                  {
                  pr.session.type = PMS_SR_CALL_NO_RETURN;
                  pr.payload.type = PMS_PD_RND_MD0_STATUS;
                  pr.payload.data.rnd_md0_status.identifier = \
                    mdi.mgmt_info.rnd_address_cache[i].identifier;
                  if (pms_receive(&pr, app_hasim_receive_post, 0) != -1)
                    mdi.rnd_info[i].receive_state |= \
                     HASIM_RND_MD0_RECEIVE_REGISTERED;
                  }
 
                /* Force an info_get immediately after registering.. */
                mdi.rnd_info[i].last_sync_check = HASIM_SYNCCHECK_INTERVAL;
                }
              }
            }
          }
        }
      }
    }
 
 
 
  /* Sync Check */
 
  for(i=0;i<16;i++)
    {
    /* Policy:  Sync update checked every SYNCCHECK_INTERVAL seconds.. */
    if (mdi.rnd_info[i].last_sync_check > HASIM_SYNCCHECK_INTERVAL)
      {
      /* Policy:  Don't attempt a sync update if any async partial updates have
         been received within SYNCCHECK_INTERVAL.. */
      if (mdi.rnd_info[i].last_update > HASIM_SYNCCHECK_INTERVAL)
        {
        /* Policy:  Don't attempt a sync update if registration for async
           updates have not succeeded.. */
        if (mdi.rnd_info[i].receive_state == HASIM_RND_GROUP_RECEIVE_REGISTERED)
          {
          if (mdi.user_info.receive_state == HASIM_USER_RECEIVE_REGISTERED)
            {
            if (mdi.user_info.pms_view == HASIM_USER_PMS_VIEW_REACHABLE)
              {
              mdi.rnd_info[i].last_sync_check = 0;
 
              info_get_fail = 0;
 
              /* Get RND information.. */
              ps.session.type = PMS_SR_CALL_RETURN_TIMED;
              ps.session.info.crt.time = 0;
              ps.payload.type = PMS_PD_RND_INFO_GET_EXECUTE;
              ps.payload.data.rnd_info_get_execute.identifier = \
                mdi.mgmt_info.rnd_address_identifier[i];
 
              if (pms_send(&ps, &pr) == 0)
                {
                if (pr.payload.data.rnd_info_get_status.err == \
                  PMS_PD_RND_INFO_GET_STATUS_ERR_NONE)
                  {
                  view = pr.payload.data.rnd_info_get_status.view;
                  }
                else
                  {
                  info_get_fail = 1;
                  }
                }
              else
                {
                info_get_fail = 1;
                }
 
              /* Get RND MD0 information.. */
              ps.session.type = PMS_SR_CALL_RETURN_TIMED;
              ps.session.info.crt.time = 0;
              ps.payload.type = PMS_PD_RND_MD0_INFO_GET_EXECUTE;
              ps.payload.data.rnd_md0_info_get_execute.identifier = \
                mdi.mgmt_info.rnd_address_identifier[i];
 
              if (pms_send(&ps, &pr) == 0)
                {
                if (pr.payload.data.rnd_md0_info_get_status.err == \
                  PMS_PD_RND_MD0_INFO_GET_STATUS_ERR_NONE)
                  {
                  md0_config = pr.payload.data.rnd_md0_info_get_status.config;
                  }
                else
                  {
                  info_get_fail = 1;
                  }
                }
              else
                {
                info_get_fail = 1;
                }
 
 
              /* Only mark MGMT update as successful if all pieces of data
                 were received successfully.. */
 
              if (info_get_fail == 0)
                {
                mdi.rnd_info[i].view_cache = view;
 
                mdi.rnd_info[i].md0_config_cache = md0_config;
 
                mdi.rnd_info[i].last_update = 0;
                }
 
              }
            }
          }
        }
      else
        {
        mdi.rnd_info[i].last_sync_check = 0;
        }
      }
    }
 
 
  /* Validity Check */
 
  /* Process cache state validity transitions.  The policy is on a RND cache
     transition to invalid, return RND state variables for the pair to an initial
     configuration.. */
 
  for(i=0;i<16;i++)
    {
    if(mdi.rnd_info[i].last_update < HASIM_CHECK_VALID_INTERVAL)
      {
      if (mdi.rnd_info[i].cache_state != HASIM_RND_CACHE_VALID)
        mdi.rnd_info[i].cache_state = HASIM_RND_CACHE_VALID;
      }
    else if((mdi.rnd_info[i].last_update >= HASIM_CHECK_VALID_INTERVAL && \
      mdi.rnd_info[i].last_update < HASIM_CHECK_INVALID_INTERVAL))
      {
      if (mdi.rnd_info[i].cache_state == HASIM_RND_CACHE_VALID)
        mdi.rnd_info[i].cache_state = HASIM_RND_CACHE_OLD;
      }
    else if(mdi.rnd_info[i].last_update >= HASIM_CHECK_INVALID_INTERVAL)
      {
      if (mdi.rnd_info[i].cache_state == HASIM_RND_CACHE_OLD)
        {
 
        /* RND */
 
        if ((mdi.rnd_info[i].receive_state & HASIM_RND_RECEIVE_REGISTERED) != 0)
          {
          pr.session.type = PMS_SR_CALL_NO_RETURN;
          pr.payload.type = PMS_PD_RND_STATUS;
          pr.payload.data.rnd_status.identifier = \
            mdi.mgmt_info.rnd_address_identifier[i];
          pms_receive(&pr, 0, 0);
          mdi.rnd_info[i].receive_state &= !HASIM_RND_RECEIVE_REGISTERED;
          }
 
        if ((mdi.rnd_info[i].receive_state & \
            HASIM_RND_MD0_RECEIVE_REGISTERED) != 0)
          {
          pr.session.type = PMS_SR_CALL_NO_RETURN;
          pr.payload.type = PMS_PD_RND_MD0_STATUS;
          pr.payload.data.rnd_status.identifier = \
            mdi.mgmt_info.rnd_address_identifier[i];
          pms_receive(&pr, 0, 0);
          mdi.rnd_info[i].receive_state &= !HASIM_RND_MD0_RECEIVE_REGISTERED;
          }
 
        }
      }
    }
}