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

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 del servicio de datos se pone en línea en ese nodo o cuando se habilita el nodo. En el tipo de recurso de ejemplo, SUNW.xfnts, el método xfnts_start activa el daemon xfs en ese nodo.

El método xfnts_start invoca scds_pmf_start() para iniciar el daemon en PMF. PMF proporciona funciones automáticas de notificación de fallo y reinicio, además de integración con el supervisor de fallos.


Nota –

La primera llamada de xfnts_start se realiza a scds_initialize(), que ejecuta ciertas tareas domésticas necesarias (Función scds_initialize() y la página de comando man scds_initialize(3HA) ofrecen información más detallada).


Validación del servicio antes de empezar

Antes de iniciar el servidor de fuentes X, el método xfnts_start invoca svc_validate() para verificar que haya una configuración adecuada para admitir el daemon xfs (consulte Método xfnts_validate para obtener más detalles), como se indica a continuación:


rc = svc_validate(scds_handle);
   if (rc != 0) {
      scds_syslog(LOG_ERR,
          "No se ha podido validar la configuración.");
      return (rc);
   }

Inicio del servicio

El método xfnts_start invoca el método svc_start(), definido en xfnts.c para iniciar el daemon xfs. Esta sección describe svc_start().

El comando para ejecutar el daemon xfs es el siguiente:


xfs -config directorio_config/fontserver.cfg -port número_puerto

La propiedad de extensión Confdir_list identifica el directorio_config y la propiedad de sistema Port_list identifica el número_puerto. Cuando el administrador del clúster configura el servicio de datos, proporciona valores específicos para estas propiedades.

El método xfnts_start declara estas propiedades como matrices de secuencias y obtiene los valores que fija el administrador con las funciones scds_get_ext_confdir_list() y scds_get_port_list() (descritas en scds_property_functions(3HA)), como sigue:


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 va a 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 puede acceder a la propiedad Port_list.");
      return (1);
   }

Observe que la variable confdirs apunta al primer elemento (0) de la matriz.

El método xfnts_start utiliza sprintf para formar la línea de comandos para xfs como se muestra a continuación.


/* Construir la orden para que inicie el daemon xfs. */
   (void) sprintf(cmd,
       "/usr/openwin/bin/xfs -config %s -port %d 2>/dev/null",
       xfnts_conf, portlist->ports[0].port);

Observe que la salida se redirige a dev/null para suprimir los mensajes que genera el daemon.

El método xfnts_start pasa la línea de comandos xfs a scds_pmf_start() para iniciar el servicio de datos controlado por PMF, como se indica a continuación.


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 ");
   }

Observe los siguientes aspectos de la llamada a scds_pmf_start().

Antes de volver, svc_pmf_start() libera la memoria asignada para la estructura portlist como se muestra a continuación.


scds_free_port_list(portlist);
return (err);

Retorno desde svc_start()

Aún cuando la función svc_start() dé un retorno satisfactorio, es posible que la aplicación subyacente no se haya iniciado correctamente. Por tanto, svc_start() debe analizar la aplicación para verificar si se está ejecutando antes de devolver un mensaje satisfactorio. El análisis debe tener en cuenta también que es posible que la aplicación no esté disponible inmediatamente porque tarda un tiempo en iniciarse. El método svc_start() invoca svc_wait(), que se define en xfnts.c, para verificar que la aplicación está en ejecución, como se indica a continuación:


/* Esperar a que el servicio se inicie completamente */
   scds_syslog_debug(DBG_LEVEL_HIGH,
       "Llamar a svc_wait para verificar que se haya iniciado el servicio.");

   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.");
   }

La función svc_wait() invoca scds_get_netaddr_list(3HA) para obtener los recursos de dirección de red necesarios para analizar la aplicación, como se indica a continuación:


/* obtener el recurso de red para el análisis */
   if (scds_get_netaddr_list(scds_handle, &netaddr)) {
      scds_syslog(LOG_ERR,
          "No se han encontrado recursos de dirección de red en 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 hay recursos de dirección de red en el grupo de recursos.");
      return (1);
   }

Después, svc_wait() obtiene los valores start_timeout y stop_timeout como se indica a continuación.


svc_start_timeout = scds_get_rs_start_timeout(scds_handle)
   probe_timeout = scds_get_ext_probe_timeout(scds_handle)

Para justificar el tiempo que puede tardar en iniciarse el servidor, svc_wait() invoca scds_svc_wait() y pasa un valor de tiempo de espera equivalente a un tres por ciento del valor start_timeout. A continuación, svc_wait() invoca svc_probe() para verificar si la aplicación se ha iniciado. El método svc_probe() realiza una conexión de zócalo sencilla con el servidor en el puerto especificado. Si no puede conectarse con el puerto, svc_probe() devuelve un valor de 100, que indica un fallo total. Si la conexión pasa, pero la desconexión del puerto falla, svc_probe() devuelve un valor de 50.

Cuando se produce un fallo parcial o total de svc_probe(), svc_wait() invoca scds_svc_wait() con un valor de tiempo de espera de 5. El método scds_svc_wait() limita la frecuencia de los análisis a cada 5 segundos. Este método cuenta también el número de intentos hechos para iniciar el servicio. Si el número de intentos supera el valor de la propiedad Retry_count del recurso en el periodo especificado por la propiedad Retry_interval del recurso, la función scds_svc_wait() devuelve un fallo. En ese caso, la función svc_start() también devuelve un fallo.


#define    SVC_CONNECT_TIMEOUT_PCT    95
#define    SVC_WAIT_PCT       3
   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);
      }

       /* Invocar scds_svc_wait() por si el servicio también falla */
      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);
      }

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


Nota –

Antes de salir, el método xfnts_start invoca scds_close() para reclamar recursos asignados por scds_initialize(). Consulte Función scds_initialize() y la página de comando man scds_close(3HA) para obtener más detalles.