Sun Cluster: Guía del desarrollador de los servicios de datos del sistema operativo Solaris

Apéndice C Listado del código del tipo de recurso de ejemplo de la Biblioteca de desarrollo del servicio de datos

Este apéndice enumera el código completo de cada método del tipo de recurso SUNW.xfnts. Incluye la lista de xfnts.c, que contiene código para las subrutinas invocadas por los métodos de rellamada. Los listados del código de este apéndice son los siguientes.

xfnts.c

Este archivo implementa las subrutinas invocadas por los métodos SUNW.xfnts.


Ejemplo C–1 xfnts.c

/*
 * Copyright (c) 1998-2004 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 * xfnts.c - Utilidades comunes de HA-XFS
 *
 * Esta utilidad tiene los métodos para realizar la validación, iniciar
 * y detener el servicio de datos y el supervisor de fallos. Contiene
 * también el método para analizar el estado del servicio de datos. El
 * analizador sólo devuelve satisfactorio o no satisfactorio. La acción se
 * decide en función de este valor devuelto en el método encontrado en
 * el archivo xfnts_probe.c
 *
 */

#pragma ident “@(#)xfnts.c 1.47 01/01/18 SMI”

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <scha.h>
#include <rgm/libdsdev.h>
#include <errno.h>
#include “xfnts.h”

/*
 * El tiempo de espera inicial permitido para que el servicio de datos
 * HAXFS esté conectado y en ejecución. Se esperará un %
 * (SVC_WAIT_PCT) del tiempo start_timeout antes de analizar el
 * servicio.
 */
#define   SVC_WAIT_PCT      3

/*
 * Hay que usar 95% de probe_timeout para conectar al puerto y el
 * resto del tiempo se usa para desconectarse del puerto de la
 * función svc_probe.
 */
#define   SVC_CONNECT_TIMEOUT_PCT      95

/*
 * SVC_WAIT_TIME se usa sólo durante el inicio en svc_wait().
 * En svc_wait() hay que estar seguro de que el servicio esté activo
 * antes del retorno, por lo que hay que invocar a svc_probe() para
 * que supervise el servicio. SVC_WAIT_TIME es el tiempo que pasa
 * entre esos análisis.
 */

#define   SVC_WAIT_TIME      5

/*
 * Este valor se usará como tiempo de espera de desconexión, si no
 * queda tiempo de probe_timeout.
 */

#define   SVC_DISCONNECT_TIMEOUT_SECONDS      2


/*
 * svc_validate():
 *
 * Realizar una validación específica de HA-XFS de la configuración del
 * recurso.
 *
 * svc_validate comprobará:
 * 1. Propiedad de extensión Confdir_list
 * 2. Archivo fontserver.cfg
 * 3. Binario xfs
 * 4. Propiedad port_list
 * 5. Recursos de red
 * 6. Otras propiedades de extensión
 *
 * Si falla cualquiera de esas validaciones, devolver > 0; en caso
 * contrario, devolver 0 para indicar satisfactorio
 */

int
svc_validate(scds_handle_t scds_handle)
{
   char   xfnts_conf[SCDS_ARRAY_SIZE];
   scha_str_array_t *confdirs;
   scds_net_resource_list_t *snrlp;
   int rc;
   struct stat statbuf;
   scds_port_list_t   *portlist;
   scha_err_t   err;

   /*
    * Obtener el directorio de configuración del servicio de datos XFS
    * de la propiedad de extensión confdir_list.
    */
   confdirs = scds_get_ext_confdir_list(scds_handle);

   /* Devolver un error si no hay propiedad de extensión confdir_list */
   if (confdirs == NULL || confdirs->array_cnt != 1) {
      scds_syslog(LOG_ERR,
          “Propiedad Confdir_list no establecida adecuadamante.”);
      return (1); /* Fallo de validación */
   }

   /*
    * Construir la ruta al archivo de configuración desde la propiedad
    * de extensión confdir_list. Dado que HA-XFS sólo tiene una
    * configuración hay que usar la primera entrada de la propiedad
    * confdir_list.
    */
   (void) sprintf(xfnts_conf, “%s/fontserver.cfg”, confdirs->str_array[0]);

   /*
    * Comprobar si el archivo de configuración HA-XFS está en el lugar
    * correcto. Intentar acceder al archivo de configuración HA-XFS y
    * asegurarse de que se hayan configurado correctamente los
    * permisos
    */
   if (stat(xfnts_conf, &statbuf) != 0) {
      /*
       * suprimir error lint porque el prototipo errno.h
       * no tiene argumento vacío
       */
      scds_syslog(LOG_ERR,
          “No se ha podido acceder al archivo <%s> : <%s>”,
          xfnts_conf, strerror(errno));   /*lint !e746 */
      return (1);
   }

   /*
    * Asegurarse de que el binario xfs exista y de que los permisos
    * sean correctos. El binario XFS se supone que está en el sistema
    * local de archivos, no en el sistema global de archivos
    */
   if (stat(“/usr/openwin/bin/xfs”, &statbuf) != 0) {
      scds_syslog(LOG_ERR,
          “No se puede acceder al binario XFS: <%s> “, strerror(errno));
      return (1);
   }

   /* HA-XFS sólo tendrán puerto */
   err = scds_get_port_list(scds_handle, &portlist);
   if (err != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “No se puede acceder a la propiedad Port_list: %s.”,
         scds_error_string(err));
      return (1); /* Fallo de validación */
   }

#ifdef TEST
   if (portlist->num_ports != 1) {
      scds_syslog(LOG_ERR,
          “La propiedad Port_list sólo debe tener un valor.”);
      scds_free_port_list(portlist);
      return (1); /* Fallo de validación */
   }
#endif

   /*
    * Devolver un error si hay un error al intentar obtener los recursos
    * de dirección de red disponibles para este recurso
    */
   if ((err = scds_get_rs_hostnames(scds_handle, &snrlp))
      != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “No hay recursos de dirección de red en el grupo de recursos: %s.”,
         scds_error_string(err));
      return (1); /* Fallo de validación */
   }

   /* Devolver un error si no hay recursos de dirección de red */
   if (snrlp == NULL || snrlp->num_netresources == 0) {
      scds_syslog(LOG_ERR,
          “No hay recursos de dirección de red en el grupo de recursos.”);
      rc = 1;
      goto finished;
   }

   /* Comprobar si hay otras propiedades de extensión importantes
    * establecidas */
   if (scds_get_ext_monitor_retry_count(scds_handle) <= 0)
   {
      scds_syslog(LOG_ERR,
          “La propiedad Monitor_retry_count no está establecida.”);
      rc = 1; /* Fallo de validación */
      goto finished;
   }
   if (scds_get_ext_monitor_retry_interval(scds_handle) <= 0) {
      scds_syslog(LOG_ERR,
          “La propiedad Monitor_retry_interval no está establecida.”);
      rc = 1; /* Fallo de validación */
      goto finished;
   }

   /* Todas las comprobaciones han sido satisfactorias */
   scds_syslog(LOG_INFO, “Validación satisfactoria.”);
   rc = 0;

finished:
   scds_free_net_list(snrlp);
   scds_free_port_list(portlist);

   return (rc); /* devolver resultado de validación */
}

/*
 * svc_start():
 *
 * Iniciar el servidor de fuentes X
 * Devolver 0 si es satisfactorio, > 0 si hay fallos.
 *
 * El servicio XFS se iniciará al ejecutar la orden /usr/openwin/bin/xfs
 *  -config <archivo fontserver.cfg> -port <puerto para escuchar>.
 * XFS se iniciará bajo PMF. XFS se iniciará como servicio de instancia
 * única. La etiqueta de PMF para el servicio de datos tendrá el formato
 * <nombre_grupo_recurso,nombre_recurso,número_instancia.svc>. En el caso
 * de XFS, dado que sólo habrá una instancia, instance_number de la etiqueta
 * tag será 0.
 */

int
svc_start(scds_handle_t scds_handle)
{
   char    xfnts_conf[SCDS_ARRAY_SIZE];
   char   cmd[SCDS_ARRAY_SIZE];
   scha_str_array_t *confdirs;
   scds_port_list_t    *portlist;
   scha_err_t   err;

   /* obtener el directorio de configuración de la propiedad confdir_list */
   confdirs = scds_get_ext_confdir_list(scds_handle);

   (void) sprintf(xfnts_conf, “%s/fontserver.cfg”, confdirs->str_array[0]);

   /* obtener el puerto que debe usar XFS de la propiedad Port_list */
   err = scds_get_port_list(scds_handle, &portlist);
   if (err != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “No se ha podido acceder a la propiedad Port_list.”);
      return (1);
   }

   /*
    * Construir la orden para iniciar HA-XFS.
    * NOTA: el daemon de XFS imprime el siguiente mensaje mientras
    * detiene XFS “/usr/openwin/bin/xfs notice: finalizando”
    * Para suprimir el mensaje del daemon, la salida se redirige a /dev/null.
    */
   (void) sprintf(cmd,
       “/usr/openwin/bin/xfs -config %s -port %d 2>/dev/null”,
       xfnts_conf, portlist->ports[0].port);

   /*
    * Iniciar HA-XFS bajo PMF. Observar que HA-XFS se inicia como un
    * servicio de instancia única. El último argumento de la función
    * scds_pmf_start denota el nivel de los secundarios que hay que supervisar.
    * Un valor de -1 para este parámetro significa que todos los secundarios
    * y el proceso original deben supervisarse.
    */
   scds_syslog(LOG_INFO, “Emitir una solicitud de inicio.”);
   err = scds_pmf_start(scds_handle, SCDS_PMF_TYPE_SVC,
      SCDS_PMF_SINGLE_INSTANCE, cmd, -1);

   if (err == SCHA_ERR_NOERR) {
      scds_syslog(LOG_INFO,
          “Orden de inicio completada satisfactoriamente.”);
   } else {
      scds_syslog(LOG_ERR,
          “No se ha podido iniciar HA-XFS “);
   }

   scds_free_port_list(portlist);
   return (err); /* devolver estado satisfactorio/no satisfactorio */
}


/*
 * svc_stop():
 *
 * Detener el servidor XFS
 * Devolver 0 si es satisfactorio,> 0 si hay fallos.
 *
 * svc_stop detendrá el servidor, invocando la función toolkit:
 * scds_pmf_stop.
 */
int
svc_stop(scds_handle_t scds_handle)
{
   scha_err_t   err;

   /*
    * El valor de tiempo de espera necesario para que el método de parada
    * sea satisfactorio se define en la propiedad Stop_Timeout (definida
    * por el sistema)
    */
   scds_syslog(LOG_ERR, “Emitir una solicitud de parada.”);
   err = scds_pmf_stop(scds_handle,
       SCDS_PMF_TYPE_SVC, SCDS_PMF_SINGLE_INSTANCE, SIGTERM,
       scds_get_rs_stop_timeout(scds_handle));

   if (err != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “No se ha podido detener HA-XFS.”);
      return (1);
   }

   scds_syslog(LOG_INFO,
       “Se ha detenido satisfactoriamente HA-XFS.”);
   return (SCHA_ERR_NOERR); /* Se ha detenido satisfactoriamente */
}

/*
 * svc_wait():
 *
 * esperar que el servicio de datos se inicie por completo y asegurarse
 * de que se ejecute correctamente
 */

int
svc_wait(scds_handle_t scds_handle)
{
   int rc, svc_start_timeout, probe_timeout;
   scds_netaddr_list_t   *netaddr;

   /* obtener el recurso de red que hay que usar para analizar */
   if (scds_get_netaddr_list(scds_handle, &netaddr)) {
      scds_syslog(LOG_ERR,
          “No se ha encontrado recurso de dirección de red en el grupo de recursos.”);
      return (1);
   }

   /* Devolver un error si no hay recursos de red */
   if (netaddr == NULL || netaddr->num_netaddrs == 0) {
      scds_syslog(LOG_ERR,
          “No se ha encontrado recurso de dirección de red en el grupo de recursos.”);
      return (1);
   }

   /*
    * Obtener el tiempo de espera del método Start, número de puerto en
    * el que analizar, el valor de tiempo de espera de Probe
    */
   svc_start_timeout = scds_get_rs_start_timeout(scds_handle);
   probe_timeout = scds_get_ext_probe_timeout(scds_handle);

   /*
    * reposar durante un porcentaje de SVC_WAIT_PCT del tiempo
    * start_timeout antes de analizar efectivamente el servicio de datos.
    * Así se permite que el servicio de datos esté totalmente activo para
    * responder al análisis.
    * NOTA: el valor de SVC_WAIT_PCT puede variar según el servicio de datos.
    * En lugar de invocar sleep(), invocar scds_svc_wait() para que si el
    * servicio falla demasiadas veces, se deje de intentar y se dé antes
    * una respuesta.
    */
   if (scds_svc_wait(scds_handle, (svc_start_timeout * SVC_WAIT_PCT)/100)
      != SCHA_ERR_NOERR) {

      scds_syslog(LOG_ERR, “No se ha podido iniciar el servicio.”);
      return (1);
   }

   do {
      /*
       * analizar el servicio de datos en la dirección IP del
       * recurso de red y el nombre de puerto
       */
      rc = svc_probe(scds_handle,
          netaddr->netaddrs[0].hostname,
          netaddr->netaddrs[0].port_proto.port, probe_timeout);
      if (rc == SCHA_ERR_NOERR) {
         /* Satisfactorio. Liberar recursos y retornar */
         scds_free_netaddr_list(netaddr);
         return (0);
      }

      /*
       * El servicio de datos sigue intentando activarse. Reposar antes de
       * volver a analizar. En lugar de invocar sleep(), invocar scds_svc_wait()
       * para que si el servicio falla demasiadas veces, se deje de intentar
       * y se dé una respuesta antes.
       */
      if (scds_svc_wait(scds_handle, SVC_WAIT_TIME)
         != SCHA_ERR_NOERR) {
         scds_syslog(LOG_ERR, “No se ha podido iniciar el servicio.”);
         return (1);
      }

   /* RGM debe agotar el tiempo de espera y terminar el programa */
   } while (1);

}

/*
 * Esta función inicia el supervisor de fallos para un recurso de HA-XFS.
 * Esto se realiza iniciando el análisis bajo PMF. La etiqueta PMF
 * se deriva como <RG-name,RS-name,instance_number.mon>.
 * La opción de reinicio de PMF se usa pero no el “reinicio infinito”.
 * En su lugar, se obtiene interval/retry_time del archivo RTR.
 */

int
mon_start(scds_handle_t scds_handle)
{
   scha_err_t   err;

   scds_syslog_debug(DBG_LEVEL_HIGH,
      “Invocando método MONITOR_START del recurso <%s>.”,
      scds_get_resource_name(scds_handle));

   /*
    * El analizador xfnts_probe se supone disponible en el mismo
    * subdirectorio en el que hay instalados otros métodos de rellamada
    * para el TR. El último parámetro de scds_pmf_start indica el nivel
    * de supervisión de secundarios. Dado que el análisis se inició bajo PMF,
    * hay que supervisar sólo el proceso de análisis, por lo que se usa
    * un valor de 0.
    */
   err = scds_pmf_start(scds_handle, SCDS_PMF_TYPE_MON,
       SCDS_PMF_SINGLE_INSTANCE, “xfnts_probe”, 0);

   if (err != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “No se ha podido iniciar el supervisor de fallos.”);
      return (1);
   }

   scds_syslog(LOG_INFO,
       “Se ha iniciado el supervisor de fallos.”);

   return (SCHA_ERR_NOERR); /* Supervisor iniciado satisfactoriamente */
}


/*
 * Esta función detiene el supervisor de fallos de un recurso HA-XFS.
 * Esto se hace a través de PMF. La etiqueta de PMF para el supervisor
 * de fallos se construye basándose en <RG-name_RS-name,instance_number.mon>.
 */

int
mon_stop(scds_handle_t scds_handle)
{

   scha_err_t   err;

   scds_syslog_debug(DBG_LEVEL_HIGH,
      “Invocando método scds_pmf_stop”);

   err = scds_pmf_stop(scds_handle, SCDS_PMF_TYPE_MON,
       SCDS_PMF_SINGLE_INSTANCE, SIGKILL,
       scds_get_rs_monitor_stop_timeout(scds_handle));

   if (err != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “No se ha podido detener el supervisor de fallos.”);
      return (1);
   }

   scds_syslog(LOG_INFO,
       “Se ha detenido el supervisor de fallos.”);

   return (SCHA_ERR_NOERR); /* Supervisor detenido satisfactoriamente */
}

/*
 * svc_probe(): realizar análisis específico de servicio de datos.
 * Devolver un valor flotante entre 0 (satisfactorio) y 100 (fallo total).
 *
 * El análisis realiza una conexión de zócalo simple al servidor XFS en el
 * puerto especificado, que se configura como la propiedad de extensión de
 * recurso (Port_list) y realiza un pulso de sondeo del servicio de datos.
 * Si el análisis no puede conectarse al puerto, se devuelve un valor de 100,
 * que indica que el fallo es total. Si la conexión se realiza y falla
 * la desconexión del puerto, se devuelve un valor de 50, que indica un
 * fallo parcial.
 */
int
svc_probe(scds_handle_t scds_handle, char *hostname, int port, int
timeout)
{
   int  rc;
   hrtime_t   t1, t2;
   int    sock;
   char   testcmd[2048];
   int    time_used, time_remaining;
   time_t      connect_timeout;


   /*
    * Analizar el servicio de datos con una conexión de zócalo al puerto
    * especificado en la propiedad port_list del sistema que sirve al
    * servicio de datos XFS. Si el servicio XFS configurado para
    * recibir en el puerto especificado responde a la conexión, el
    * análisis es satisfactorio. En caso contrario, se esperará durante un
    * tiempo definido en la propiedad probe_timeout antes de concluir
    * que el análisis ha fallado.
    */

   /*
    * Utilizar el porcentaje SVC_CONNECT_TIMEOUT_PCT del tiempo de
    * espera para conectarse al puerto
    */
   connect_timeout = (SVC_CONNECT_TIMEOUT_PCT * timeout)/100;
   t1 = (hrtime_t)(gethrtime()/1E9);

   /*
    * el analizador establece una conexión al puerto y nombre de sistema
    * especificados. La conexión debe ocupar un 95% del probe_timeout real.
    */
   rc = scds_fm_tcp_connect(scds_handle, &sock, hostname, port,
       connect_timeout);
   if (rc) {
      scds_syslog(LOG_ERR,
          “No se ha podido conectar con el puerto <%d> del recurso <%s>.”,
          port, scds_get_resource_name(scds_handle));
      /* es un fallo total */
      return (SCDS_PROBE_COMPLETE_FAILURE);
   }

   t2 = (hrtime_t)(gethrtime()/1E9);

   /*
    * Calcular el tiempo real que tardó la conexión. Debe ser inferior o igual
    * a connect_timeout, el tiempo asignado para la conexión. Si la conexión
    * emplea todo el tiempo que se le ha asignado, el valor restante de
    * probe_timeout pasado a esta función se utilizará como tiempo de espera
    * de desconexión. En caso contrario, el tiempo restante de la llamada de
    * conexión se agregará también al tiempo de espera de desconexión.
    *
    */

   time_used = (int)(t2 - t1);

   /*
    * Utilizar el tiempo restante (tiempo de espera - time_took_to_connect)
    * para la desconexión
    */

   time_remaining = timeout - (int)time_used;

   /*
    * Si se usa todo el tiempo, utilizar un tiempo de espera estático reducido
    * para intentar la desconexión. Así se evitan fugas de fd.
    */
   if (time_remaining <= 0) {
      scds_syslog_debug(DBG_LEVEL_LOW,
         “svc_probe ha utilizado el tiempo de espera completo de”
         “%d segundos durante la operacion de conexion y ha superado el”
         “tiempo de espera en %d segundos. Intentando desconectar con”
         “un tiempo de espera de %d”,
          connect_timeout,
          abs(time_used),
          SVC_DISCONNECT_TIMEOUT_SECONDS);

      time_remaining = SVC_DISCONNECT_TIMEOUT_SECONDS;
   }

   /*
    * Devolver fallo parcial en caso de un fallo de desconexión.
    * Motivo: la llamada de conexión ha sido satisfactoria, lo que significa
    * que la aplicación está activa. Un fallo de desconexión puede
    * deberse a una aplicación bloqueada o a una carga pesada. Si es éste
    * el caso, no declarar la aplicación terminada devolviendo un fallo total.
    * Declarar un fallo parcial en su lugar. Si la situación persiste, la
    * llamada de desconexión fallará otra vez y se reiniciará la aplicación.
    */
   rc = scds_fm_tcp_disconnect(scds_handle, sock, time_remaining);
   if (rc != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “No se ha podido desconectar el puerto %d del recurso %s.”,
          port, scds_get_resource_name(scds_handle));
      /* es un fallo parcial */
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

   t2 = (hrtime_t)(gethrtime()/1E9);
   time_used = (int)(t2 - t1);
   time_remaining = timeout - time_used;

   /*
    * Si no hay tiempo, no realizar la comprobación total con
    * fsinfo. Devolver SCDS_PROBE_COMPLETE_FAILURE/2. Así, si
    * persiste el tiempo de espera agotado, el servidor se reiniciará.
    */
   if (time_remaining <= 0) {
      scds_syslog(LOG_ERR, “Tiempo de espera de análisis excedido.”);
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

   /*
    * La conexión y desconexión del puerto son satisfactorias,
    * Ejecutar la orden fsinfo para realizar una comprobación total
    * del estado del servidor. Redirigir stdout, si no, la salida de
    * fsinfo terminará en la consola.
    */
   (void) sprintf(testcmd,
       “/usr/openwin/bin/fsinfo -server %s:%d > /dev/null”,
       hostname, port);
   scds_syslog_debug(DBG_LEVEL_HIGH,
       “Comprobar el estado del servidor con %s.”, testcmd);
   if (scds_timerun(scds_handle, testcmd, time_remaining,
      SIGKILL, &rc) != SCHA_ERR_NOERR || rc != 0) {

      scds_syslog(LOG_ERR,
         “No se pudo comprobar estado del servidor con la orden <%s>”,
         testcmd);
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }
   return (0);
}

Método xfnts_monitor_check

Este método verifica si la configuración básica del tipo de recurso es válida.


Ejemplo C–2 xfnts_monitor_check.c

/*
 * Copyright (c) 1998-2004 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 * xfnts_monitor_check.c - Método del comprobación del supervisor para HA-XFS
 */

#pragma ident “@(#)xfnts_monitor_check.c 1.11 01/01/18
SMI”

#include <rgm/libdsdev.h>
#include “xfnts.h”

/*
 * Realizar una comprobación de validez sencilla del servicio
 */

int
main(int argc, char *argv[])
{
   scds_handle_t   scds_handle;
   int   rc;

   /* Procesar los argumentos que pasa RGM e inicializar syslog */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “No se ha podido inicializar el manejo.”);
      return (1);
   }

   rc =  svc_validate(scds_handle);
   scds_syslog_debug(DBG_LEVEL_HIGH,
       “método monitor_check “
       “se ha llamado y ha devuelto <%d>.”, rc);

   /* Liberar toda la memoria asignada por scds_initialize */
   scds_close(&scds_handle);

   /* Devolver el resultado del método Validate ejecutado en la
    * comprobación del supervisor */
   return (rc);
}

Método xfnts_monitor_start

Este método inicia el método xfnts_probe.


Ejemplo C–3 xfnts_monitor_start.c

/*
 * Copyright (c) 1998-2004 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 * xfnts_monitor_start.c - Método para iniciar el supervisor para HA-XFS
 */

#pragma ident “@(#)xfnts_monitor_start.c 1.10 01/01/18
SMI”

#include <rgm/libdsdev.h>
#include “xfnts.h”

/*
 * Este método inicia el supervisor de fallos para el recurso HA-XFS.
 * Esto se hace iniciando el análisis bajo PMF. La etiqueta PMF se
 * deriva como RG-name,RS-name.mon. La opción de reinicio de PMF
 * se usa, pero no el "reinicio infinito". En su lugar,
 * se obtiene interval/retry_time del archivo RTR.
 */

int
main(int argc, char *argv[])
{
   scds_handle_t   scds_handle;
   int   rc;

   /* Procesar argumentos que pasa RGM e inicializar syslog */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “No se ha podido inicializar el manejo.”);
      return (1);
   }

   rc = mon_start(scds_handle);

   /* Liberar toda la memoria asignada por scds_initialize */
   scds_close(&scds_handle);

   /* Devolver el resultado del método monitor_start */
   return (rc);
}

Método xfnts_monitor_stop

Este método detiene el método xfnts_probe.


Ejemplo C–4 xfnts_monitor_stop.c

/*
 * Copyright (c) 1998-2004 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 * xfnts_monitor_stop.c - Método para detener el supervisor para HA-XFS
 */

#pragma ident “@(#)xfnts_monitor_stop.c 1.9 01/01/18 SMI”

#include <rgm/libdsdev.h>
#include “xfnts.h”

/*
 * Este método detiene el supervisor de fallos del recurso HA-XFS.
 * Esto se hace mediante PMF. La etiqueta PMF para el supervisor de
 * fallos se construye basándose en RG-name_RS-name.mon.
 */

int
main(int argc, char *argv[])
{

   scds_handle_t   scds_handle;
   int    rc;

   /* Procesar argumentos que pasa RGM e inicializar syslog */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “No se ha podido inicializar el manejo.”);
      return (1);
   }
   rc = mon_stop(scds_handle);

   /* Liberar toda la memoria asignada por scds_initialize */
   scds_close(&scds_handle);

   /* Devolver el resultado del método para detener el supervisor */
   return (rc);
}

Método xfnts_probe

El método xfnts_probe comprueba la disponibilidad de la aplicación y decide si debe realizar una operación de recuperación de fallos o reiniciar el servicio de datos. El método de rellamada xfnts_monitor_start inicia este programa y el método de rellamada xfnts_monitor_stop lo detiene.


Ejemplo C–5 xfnts_probe.c+

/*
 * Copyright (c) 1998-2004 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 * xfnts_probe.c - Análisis de HA-XFS
 */

#pragma ident “@(#)xfnts_probe.c 1.26 01/01/18 SMI”

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <strings.h>
#include <rgm/libdsdev.h>
#include “xfnts.h”


/*
 * main():
 * Sólo un bucle infinito que permanece en sleep()s durante un tiempo,
 * a la espera de que la secuencia de acciones de PMF lo interrumpa.
 * Cuando eso ocurre, invoca el método de inicio para que HA-XFS lo reinicie.
 */

int
main(int argc, char *argv[])
{
   int         timeout;
   int         port, ip, probe_result;
   scds_handle_t      scds_handle;

   hrtime_t      ht1, ht2;
   unsigned long      dt;

   scds_netaddr_list_t *netaddr;
   char   *hostname;

   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “No se ha podido inicializar el manejo.”);
      return (1);
   }

   /* Obtener la dirección IP disponible para este recurso */
   if (scds_get_netaddr_list(scds_handle, &netaddr)) {
      scds_syslog(LOG_ERR,
          “No hay recurso de dirección de red en el grupo de recursos.”);
      scds_close(&scds_handle);
      return (1);
   }

   /* Devolver un error si no hay recursos de red */
   if (netaddr == NULL || netaddr->num_netaddrs == 0) {
      scds_syslog(LOG_ERR,
          “No hay recurso de dirección de red en el grupo de recursos.”);
      return (1);
   }

   /*
    * Establecer el tiempo de espera de las propiedades de X. Esto significa
    * que cada iteración de análisis recibirá un tiempo de espera completo
    * en cada recurso de red, sin necesidad de dividir el tiempo de espera
    * entre todos los recursos de red configurados para este recurso.
    */
   timeout = scds_get_ext_probe_timeout(scds_handle);

   for (;;) {

      /*
       * Reposar durante un tiempo thorough_probe_interval entre
       * análisis sucesivos.
       */
      (void) scds_fm_sleep(scds_handle,
          scds_get_rs_thorough_probe_interval(scds_handle));

      /*
       * Ahora, analizar todas las direcciones IP que se usan. Recorrer
       * 1. Todos los recursos de red que se emplean.
       * 2. Todas las direcciones IP de un recurso determinado.
       * Para cada dirección IP analizada, calcular
       * el historial de fallos.
       */
      probe_result = 0;
      /*
       * Repetir con todos los recursos para obtener todas
       * las direcciones IP que hay que usar para invocar svc_probe()
       */
      for (ip = 0; ip < netaddr->num_netaddrs; ip++) {
         /*
          * Obtener el nombre de sistema y puerto en los que hay que
          * supervisar el estado.
          */
         hostname = netaddr->netaddrs[ip].hostname;
         port = netaddr->netaddrs[ip].port_proto.port;
         /*
          * HA-XFS sólo admite un puerto, por lo que
          * se debe obtener el valor del puerto de la
          * primera entrada de la matriz de puertos.
          */
         ht1 = gethrtime(); /* Bloquear la hora de inicio del análisis */
         scds_syslog(LOG_INFO, “Analizar el servicio en “
             “puerto: %d.”, port);

         probe_result =
         svc_probe(scds_handle, hostname, port, timeout);

         /*
          * Actualizar el historial de análisis del servicio,
          * y actuar si es necesario.
          * Bloquear la hora de finalización del análisis.
          */
         ht2 = gethrtime();

         /* Convertir a milisegundos */
         dt = (ulong_t)((ht2 - ht1) / 1e6);

         /*
          * Calcular el historial de fallos y
          * actuar si es necesario
          */
         (void) scds_fm_action(scds_handle,
             probe_result, (long)dt);
      }   /* Todos los recursos de red */
   }    /* Continuar analizando indefinidamente */
}

Método xfnts_start

RGM invoca el método Start en un nodo del clúster cuando el grupo de recursos que contiene el recurso de servicio de datos se pone en línea en ese nodo o cuando se habilita el recurso. El método xfnts_start activa el daemon xfs en ese nodo.


Ejemplo C–6 xfnts_start.c

/*
 * Copyright (c) 1998-2004 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 * xfnts_svc_start.c - Método de inicio para HA-XFS
 */

#pragma ident “@(#)xfnts_svc_start.c 1.13 01/01/18 SMI”

#include <rgm/libdsdev.h>
#include “xfnts.h”

/*
 * El método de inicio de HA-XFS. Realiza comprobaciones de estado
 * en los valores de recurso e inicia el HA-XFS bajo PMF con una
 * secuencia de acciones.
 */

int
main(int argc, char *argv[])
{
   scds_handle_t   scds_handle;
   int rc;

   /*
    * Procesar todos los argumentos que ha pasado de RGM
    * y realizar una inicialización para syslog
    */

   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “No se ha podido inicializar el manejo.”);
      return (1);
   }

   /* Validar la configuración; si hay un error, volver atrás */
   rc = svc_validate(scds_handle);
   if (rc != 0) {
      scds_syslog(LOG_ERR,
          “No se ha podido validar la configuración.”);
      return (rc);
   }

   /* Iniciar el servicio de datos; si falla, volver con un error */
   rc = svc_start(scds_handle);
   if (rc != 0) {
      goto finished;
   }

   /* Esperar que el servicio se inicie por completo */
   scds_syslog_debug(DBG_LEVEL_HIGH,
       “Llamar a svc_wait para comprobar que el servicio se haya iniciado.”);

   rc = svc_wait(scds_handle);

   scds_syslog_debug(DBG_LEVEL_HIGH,
       “Devuelto desde svc_wait”);

   if (rc == 0) {
      scds_syslog(LOG_INFO, “El servicio se ha iniciado satisfactoriamente.”);
   } else {
      scds_syslog(LOG_ERR, “No se ha podido iniciar el servicio.”);
   }


finished:
   /* Liberar los recursos de entorno asignados */
   scds_close(&scds_handle);

   return (rc);
}

El método xfnts_stop

RGM invoca el método Stop en un nodo del clúster cuando el grupo de recursos que contiene el recurso de HA-XFS se pone fuera de línea en ese nodo o cuando se inhabilita el recurso. Este método detiene el daemon xfs en ese nodo.


Ejemplo C–7 xfnts_stop.c

/*
 * Copyright (c) 1998-2004 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 * xfnts_svc_stop.c - Método de parada para HA-XFS
 */

#pragma ident “@(#)xfnts_svc_stop.c 1.10 01/01/18 SMI”

#include <rgm/libdsdev.h>
#include “xfnts.h”

/*
 * Detiene el proceso de HA-XFS con PMF
 */

int
main(int argc, char *argv[])
{

   scds_handle_t   scds_handle;
   int      rc;

   /* Procesar los argumentos pasados por RGM e inicializar syslog */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “No se ha podido inicializar el manejo.”);
      return (1);
   }

   rc = svc_stop(scds_handle);

   /* Liberar toda la memoria asignada por scds_initialize */
   scds_close(&scds_handle);

   /* Devolver el resultado del método svc_stop */
   return (rc);
}

El método xfnts_update

RGM invoca el método Update para notificar a un recurso en ejecución que sus propiedades han cambiado. RGM invoca Update después de que una acción administrativa logre establecer satisfactoriamente las propiedades de un recurso o su grupo.


Ejemplo C–8 xfnts_update.c

#pragma ident “@(#)xfnts_update.c  1.10     01/01/18 SMI”

/*
 * Copyright (c) 1998-2004 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 * xfnts_update.c - Método de actualización para HA-XFS
 */

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <rgm/libdsdev.h>

/*
 * Es posible que se hayan actualizado algunas propiedades del recurso.
 * Todas las propiedades actualizables y actualizadas están relacionadas
 * con el supervisor de fallos. Por tanto, debería bastar con reiniciar éste.
 */

int
main(int argc, char *argv[])
{
   scds_handle_t   scds_handle;
   scha_err_t   result;

   /* Procesar los argumentos que ha pasado RGM e inicializar syslog */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “No se ha podido inicializar el manejo.”);
      return (1);
   }

   /*
    * Comprobar si el supervisor de fallos ya está en ejecución. Si es así,
    * detenerlo y reiniciarlo. El segundo parámetro de scds_pmf_restart_fm()
    * sólo identifica la instancia del supervisor de fallos que hay que
    * reiniciar.
    */

   scds_syslog(LOG_INFO, “Reinicio del supervisor de fallos.”);
   result = scds_pmf_restart_fm(scds_handle, 0);
   if (result != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “No se ha podido reiniciar el supervisor de fallos.”);
      /* Liberar toda la memoria asignada por scds_initialize */
      scds_close(&scds_handle);
      return (1);
   }

   scds_syslog(LOG_INFO,
       “Terminado satisfactoriamente.”);

   /* Liberar toda la memoria asignada por scds_initialize */
   scds_close(&scds_handle);

   return (0);
}

El listado del código del método xfnts_validate

Este método verifica la existencia del directorio al que apunta la propiedad Confdir_list. RGM invoca este método cuando se crea el servicio de datos y cuando el administrador del clúster actualiza las propiedades del servicio de datos. El método Monitor_check invoca este método cuando el supervisor de fallos realiza una operación de recuperación de fallos del servicio de datos a otro nodo.


Ejemplo C–9 xfnts_validate.c

/*
 * Copyright (c) 1998-2004 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 * xfnts_validate.c - Método de validación para HA-XFS
 */

#pragma ident “@(#)xfnts_validate.c 1.9 01/01/18 SMI”

#include <rgm/libdsdev.h>
#include “xfnts.h”

/*
 * Comprobar si las propiedades se han establecido correctamente.
 */

int
main(int argc, char *argv[])
{
   scds_handle_t   scds_handle;
   int   rc;

   /* Procesar los argumentos que ha pasado RGM e inicializar syslog */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “No se ha podido inicializar el manejo.”);
      return (1);
   }
   rc = svc_validate(scds_handle);

   /* Liberar toda la memoria asignada por scds_initialize */
   scds_close(&scds_handle);

   /* Devolver el resultado del método de validación */
   return (rc);

}