Guide des développeurs pour les services de données Sun Cluster 3.1 10/03

Chapitre 8 Mise en oeuvre du type de ressource BDSD modèle

Ce chapitre décrit un type de ressource modèle, SUNW.xfnts, mis en oeuvre avec BDSD. Le service de données est rédigé en C. L'application sous-jacente est le serveur X Font, un service basé sur le protocole TCP/IP.

Les informations fournies dans ce chapitre sont les suivantes :

Serveur X Font

Le serveur X Font est un service simple, basé sur le protocole TCP/IP, servant des fichiers de police à ses clients. Les clients se connectent au serveur pour demander un jeu de polices et le serveur lit les fichiers de police à partir du disque avant de les servir aux clients. Le démon du serveur X Font se compose d'un binaire de serveur /usr/openwin/bin/xfs. Le démon est normalement démarré à partir de inetd. Toutefois, pour le modèle présenté, supposez que l'entrée appropriée du fichier /etc/inetd.conf a été désactivée (par exemple, par la commande fsadmin -d). Le démon est donc sous le seul contrôle de Sun Cluster.

Fichier de configuration du serveur X Font

Par défaut, le serveur X Font lit ses informations de configuration à partir du fichier /usr/openwin/lib/X11/fontserver.cfg. L'entrée de catalogue de ce fichier contient une liste des répertoires de police que peut servir le démon. L'administrateur du cluster peut localiser ces répertoires sur le système de fichiers global (afin d'optimiser l'utilisation du serveur X Font sur Sun Cluster en gérant une seule copie de la base de données des polices sur le système). Dans ce cas, l'administrateur doit éditer fontserver.cfg afin de refléter les nouveaux chemins des répertoires contenant les polices.

Pour faciliter la configuration, l'administrateur peut également placer le fichier de configuration lui-même dans le système de fichiers global. Le démon xfs propose des arguments de ligne de commande permettant d'ignorer l'emplacement intégré par défaut de ce fichier. Le type de ressource SUNW.xfnts utilise la commande suivante pour démarrer le démon sous le contrôle de Sun Cluster :


/usr/openwin/bin/xfs -config <emplacement_du_fichier_cfg>/fontserver.cfg \
-port <numéroport>

Dans la mise en oeuvre du type de ressource SUNW.xfnts, vous pouvez utiliser la propriété Liste_rép_conf pour gérer l'emplacement du fichier de configuration fontserver.cfg.

Numéro du port TCP

Le numéro du port TCP qu'écoute le démon du serveur xfs est normalement le port “fs” (généralement défini comme 7100 dans le fichier /etc/services). Toutefois, l'option -port de la ligne de commande xfs permet à l'administrateur système d'ignorer la valeur par défaut. Vous pouvez utiliser la propriété Liste_ports dans le type de ressource SUNW.xfnts pour définir la valeur par défaut et pour prendre en charge l'utilisation de l'option -port dans la ligne de commande xfs. Vous définissez la valeur par défaut de cette propriété comme 7100/tcp dans le fichier RTR. Dans la méthode SUNW.xfnts Démarrage, vous transmettez Liste_ports à l'option -port de la ligne de commande xfs. Par conséquent, un utilisateur de ce type de ressource n'est pas obligé de spécifier un numéro de port (le port par défaut est 7100/tcp) mais, s'il le souhaite, il peut en indiquer un autre lors de la configuration du type de ressource. Pour ce faire, il lui suffit d'entrer une valeur différente pour la propriété Liste_ports.

Conventions de dénomination

Vous pouvez identifier les différentes parties du code modèle en gardant les conventions suivantes à l'esprit :

Fichier RTR SUNW.xfnts

Cette rubrique décrit plusieurs propriétés clés du fichier RTR SUNW.xfnts. Elle ne décrit pas l'objectif de chaque propriété du fichier. Pour une telle description, reportez-vous à la rubrique Paramétrage des propriétés de ressources et de types de ressources.

La propriété d'extension Liste_rép_conf identifie le répertoire de configuration (ou une liste de répertoires) de la manière suivante :


{
        PROPRIÉTÉ = Liste_rép_conf;
        EXTENSION;
        CHAÎNE;
        RÉGLABLE = À_LA_CRÉATION;
        DESCRIPTION = "Chemin(s) du répertoire de configuration";
}

La propriété Liste_rép_conf ne spécifie pas de valeur par défaut. L'administrateur du cluster doit indiquer un répertoire au moment de la création de la ressource. Cette valeur ne peut plus être modifiée ultérieurement parce que son paramétrage est limité à À_LA_CRÉATION.

La propriété Liste_ports identifie le port qu'écoute le démon du serveur de la manière suivante :


{
        PROPRIÉTÉ = Liste_ports;
        PAR DÉFAUT = 7100/tcp;
        RÉGLABLE = À_LA_CRÉATION;
}

La propriété déclarant une valeur par défaut, l'administrateur du cluster a la possibilité de spécifier une nouvelle valeur ou d'accepter la valeur par défaut au moment de la création de la ressource. Cette valeur ne peut plus être modifiée ultérieurement parce que son paramétrage est limité à À_LA_CRÉATION.

Fonction scds_initialize()

BDSD exige que chaque méthode de rappel appelle la fonction scds_initialize(3HA) au début de la méthode. Cette fonction exécute les opérations suivantes :

La fonction scds_close() vous permet de récupérer les ressources allouées par scds_initialize().

Méthode de démarrage_xfnts

Le RGM appelle la méthode de Démarrage sur un noeud du cluster lorsque le groupe contenant la ressource du service de données est mis en ligne sur ce noeud ou lorsque la ressource est activée. Dans le type de ressource modèle SUNW.xfnts, la méthode de démarrage_xfnts active le démon xfs sur ce noeud.

La méthode de démarrage_xfnts appelle scds_pmf_start () pour démarrer le démon sous le gestionnaire de processus. Celui-ci propose une notification automatique des pannes ainsi que des fonctions de redémarrage, de même qu'une intégration avec le détecteur de pannes.


Remarque :

le premier appel dans démarrage_xfnts est destiné à scds_initialize() qui effectue certaines fonctions de gestion interne nécessaires (les pages Fonction scds_initialize() et scds_initialize(3HA) du manuel contiennent plus de détails).


Validation du service avant démarrage

Avant de tenter de démarrer le serveur X Font, la méthode de démarrage_xfnts appelle svc_validate() pour vérifier si une configuration correcte est en place pour prendre en charge le démon xfs (reportez-vous à la rubrique Méthode de validation_xfnts pour de plus amples détails), de la manière suivante :


rc = svc_validate(scds_handle);
   if (rc != 0) {
      scds_syslog(LOG_ERR,
          "Failed to validate configuration.");
      return (rc);
   }

Démarrage du service

La méthode de démarrage_xfnts appelle la méthode de démarrage_svc(), définie dans xfnts.c pour démarrer le démon xfs. Cette rubrique décrit démarrage_svc().

La commande permettant de lancer le démon xfs est la suivante :


xfs -config répertoire_config/fontserver.cfg -port numéro_port

La propriété d'extension Liste_rép_conf identifie le répertoire_config alors que la propriété système Liste_port identifie le numéro_port. Lorsque l'administrateur du cluster configure le service de données, il fournit des valeurs spécifiques pour ces propriétés.

La méthode de démarrage_xfnts déclare ces propriétés comme tableaux de chaînes et obtient les valeurs définies par l'administrateur à l'aide des fonctions scds_get_ext_confdir_list() et scds_get_port_list() (décrites dans scds_property_functions(3HA)), de la manière suivante :


scha_str_array_t *confdirs;
scds_port_list_t    *portlist;
scha_err_t   err;

   /* obtention du répertoire de configuration depuis la propriété liste_rép_conf  */
   confdirs = scds_get_ext_confdir_list(scds_handle);

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

   /* obtention du port à utiliser par XFS depuis la propriété Liste_port */
   err = scds_get_port_list(scds_handle, &portlist);
   if (err != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          "Could not access property Port_list.");
      return (1);
   }

Remarquez que la variable Rép_conf pointe vers le premier élément (0) du tableau.

La méthode de démarrage_xfnts utilise sprintf pour former la ligne de commande pour xfs de la manière suivante :


/* Construction de la commande pour démarrer le démon xfs. */
   (void) sprintf(cmd,
       "/usr/openwin/bin/xfs -config %s -port %d 2>/dev/null",
       xfnts_conf, portlist->ports[0].port);

Remarquez que la sortie est redirigée vers dev/null pour supprimer les messages générés par le démon.

La méthode de démarrage_xfnts transmet la ligne de commande xfs à scds_pmf_start() pour démarrer le service de données sous le contrôle du gestionnaire de processus, de la manière suivante :


scds_syslog(LOG_INFO, "Issuing a start request.");
   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,
          "Start command completed successfully.");
   } else {
      scds_syslog(LOG_ERR,
          "Failed to start HA-XFS ");
   }

Remarquez les points suivants relatifs à l'appel vers scds_pmf_start () :

Avant son retour, svc_pmf_start() libère la mémoire allouée à la structure liste_ports, de la manière suivante :


scds_free_port_list(portlist);
return (err);

Retour de démarrage_svc()

Même lorsque démarrage_svc() renvoie une réussite, il est possible que l'application sous-jacente n'arrive pas à démarrer. démarrage_svc() doit donc sonder l'application afin de vérifier qu'elle fonctionne avant de renvoyer un message de réussite. La sonde doit tenir compte du fait que l'application peut ne pas être immédiatement disponible parce que son démarrage prend un certain temps. La méthode démarrage_svc() appelle svc_wait(), définie dans xfnts.c, pour vérifier si l'application tourne, de la manière suivante :


/* Attendre que le service ait complètement démarré */
   scds_syslog_debug(DBG_LEVEL_HIGH,
       "Calling svc_wait to verify that service has started.");

   rc = svc_wait(scds_handle);

   scds_syslog_debug(DBG_LEVEL_HIGH,
       "Returned from svc_wait");

   if (rc == 0) {
      scds_syslog(LOG_INFO, "Successfully started the service.");
   } else {
      scds_syslog(LOG_ERR, "Failed to start the service.");
   }

La fonction svc_wait() appelle scds_get_netaddr_list(3HA) pour obtenir les ressources d'adresses réseau nécessaires pour sonder l'application, de la manière suivante :


/* Obtention de la ressource réseau à utiliser pour le sondage */
   if (scds_get_netaddr_list(scds_handle, &netaddr)) {
      scds_syslog(LOG_ERR,
          "No network address resources found in resource group.");
      return (1);
   }

   /* Renvoi d'une erreur en l'absence de ressources réseau */
   if (netaddr == NULL || netaddr->num_netaddrs == 0) {
      scds_syslog(LOG_ERR,
          "No network address resource in resource group.");
      return (1);
   }

Ensuite, svc_wait() obtient les valeurs de délai_démarrage et de délai_arrêt de la manière suivante :


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

Pour tenir compte du délai nécessaire au serveur pour démarrer, svc_wait() appelle scds_svc_wait() et transmet une valeur de délai imparti équivalant à trois pourcent de la valeur de délai_démarrage. Ensuite, svc_wait() appelle svc_probe() pour vérifier que l'application a démarré. La méthode svc_probe() établit une connexion de socket simple au serveur sur le port spécifié. En cas d'échec de la connexion au port, svc_probe() renvoie une valeur de 100, indiquant un échec total. Si la connexion s'établit mais que la déconnexion du port échoue, svc_probe() renvoie une valeur de 50.

En cas d'échec total ou partiel de svc_probe(), svc_wait() appelle scds_svc_wait() avec un délai imparti de 5. La méthode scds_svc_wait() limite la fréquence des sondages à un intervalle de 5 secondes. Cette méthode comptabilise également le nombre de tentatives de démarrage du service. Si le nombre de tentatives dépasse la valeur de la propriété Nombre_nouvelles_tentatives de la ressource dans la période spécifiée par la propriété Intervalle_nouvelles_tentatives de la ressource, la fonction scds_svc_wait() renvoie un échec. Dans ce cas, la fonction démarrage_svc() renvoie également un échec.


#définir    SVC_CONNECT_TIMEOUT_PCT    95
#définir    SVC_WAIT_PCT       3
   if (scds_svc_wait(scds_handle, (svc_start_timeout * SVC_WAIT_PCT)/100)
      != SCHA_ERR_NOERR) {

      scds_syslog(LOG_ERR, "Service failed to start.");
      return (1);
   }

   do {
      /*
       * Sondage du service de données sur l'adresse IP de la
       * ressource réseau et du nom du port
       */
      rc = svc_probe(scds_handle,
          netaddr->netaddrs[0].hostname,
          netaddr->netaddrs[0].port_proto.port, probe_timeout);
      if (rc == SCHA_ERR_NOERR) {
         /* Success. Free up resources and return */
         scds_free_netaddr_list(netaddr);
         return (0);
      }

       /* Appel de scds_svc_wait() au cas où le service échoue également
      if (scds_svc_wait(scds_handle, SVC_WAIT_TIME)
         != SCHA_ERR_NOERR) {
         scds_syslog(LOG_ERR, "Service failed to start.");
         return (1);
      }

   /* Appui sur le RGM pour arrêter le programme en cas de dépassement du délai imparti */
   } while (1);


Remarque :

avant sa fermeture, la fonction démarrage_xfnts appelle scds_close() de manière à récupérer les ressources allouées par scds_initialize (). Reportez-vous à la rubrique Fonction scds_initialize() et à la page scds_close (3HA) du manuel pour plus de détails.


Méthode d'arrêt_xfnts

La méthode de démarrage_xfnts utilisant scds_pmf_start() pour démarrer le service sous le gestionnaire de processus, arrêt_xfnts emploie scds_pmf_stop() pour arrêter celui-ci.


Remarque :

le premier appel d'arrêt_xfnts est destiné à la fonction scds_initialize() exécutant des fonctions de gestion interne nécessaires (pour plus de détails, reportez-vous à la rubrique Fonction scds_initialize() et à la page scds_initialize(3HA) du manuel).


La méthode d'arrêt_xfnts appelle la méthode arrêt_svc(), définie dans xfnts.c de la manière suivante :


scds_syslog(LOG_ERR, "Issuing a stop request.");
   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,
          "Failed to stop HA-XFS.");
      return (1);
   }

   scds_syslog(LOG_INFO,
       "Successfully stopped HA-XFS.");
   return (SCHA_ERR_NOERR); /* Successfully stopped */

Remarquez les points suivants concernant l'appel d'arrêt_svc() destiné à la fonction scds_pmf_stop() :


Remarque :

avant sa fermeture, la méthode d'arrêt_xfnts appelle scds_close() afin de récupérer les ressources réparties par scds_initialize (). Reportez-vous à la rubrique Fonction scds_initialize() et à la page scds_close (3HA) du manuel pour plus de détails.


Méthode de démarrage_détecteur_xfnts

Le RGM appelle la méthode de Démarrage_détecteur sur un noeud pour démarrer le détecteur de pannes une fois une ressource démarrée sur le noeud. La méthode démarrage_détecteur_xfnts utilise scds_pmf_start() pour démarrer le démon du détecteur sous le gestionnaire de processus.


Remarque :

le premier appel de démarrage_détecteur_xfnts est adressé à scds_initialize() exécutant des fonctions de gestion interne nécessaires (pour plus de détails, reportez-vous à la rubrique Fonction scds_initialize() et à la page scds_initialize(3HA) du manuel).


La méthode de démarrage_détecteur_xfnts appelle la méthode de démarrage_mon, définie dans xfnts.c de la manière suivante :


scds_syslog_debug(DBG_LEVEL_HIGH,
      "Calling Monitor_start method for resource <%s>.",
      scds_get_resource_name(scds_handle));

    /* Appel de scds_pmf_start et transmission du nom de la sonde. */
   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,
          "Failed to start fault monitor.");
      return (1);
   }

   scds_syslog(LOG_INFO,
       "Started the fault monitor.");

   return (SCHA_ERR_NOERR); /* Successfully started Monitor */
}

Remarquez les points suivants sur l'appel de svc_mon_start() adressé à la fonction scds_pmf_start() :


Remarque :

avant sa fermeture, la méthode de démarrage_détecteur_xfnts appelle scds_close() pour récupérer les ressources allouées par scds_initialize(). Reportez-vous à la rubrique Fonction scds_initialize() et à la page scds_close(3HA) du manuel pour plus de détails.


Méthode d'arrêt_détecteur_xfnts

La méthode de démarrage_détecteur_xfnts utilisant scds_pmf_start() pour démarrer le démon du détecteur sous le gestionnaire de processus, arrêt_détecteur_xfnts utilise scds_pmf_stop() pour l'arrêter.


Remarque :

le premier appel d'arrêt_détecteur_xfnts est destiné à scds_initialize() effectuant les fonctions de gestion interne nécessaires (pour plus de détails, consultez la rubrique Fonction scds_initialize() et la page scds_initialize(3HA) du manuel.)


La méthode d'arrêt_détecteur_xfnts() appelle la méthode mon_stop, définie dans xfnts.c, de la manière suivante :


scds_syslog_debug(DBG_LEVEL_HIGH,
      "Calling scds_pmf_stop method");

   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,
          "Failed to stop fault monitor.");
      return (1);
   }

   scds_syslog(LOG_INFO,
       "Stopped the fault monitor.");

   return (SCHA_ERR_NOERR); /* Successfully stopped monitor */
}

Remarquez les points suivants concernant l'appel de svc_mon_stop() destiné à la fonction scds_pmf_stop() :


Remarque :

avant sa fermeture, la méthode d'arrêt_détecteur_xfnts appelle scds_close() pour récupérer les ressources allouées par scds_initialize(). Reportez-vous à la rubrique Fonction scds_initialize() et à la page scds_close(3HA) du manuel pour plus de détails.


Méthode de contrôle_détecteur_xfnts

Le RGM appelle la méthode Contrôle_détecteur lorsque le détecteur de pannes tente de basculer le groupe contenant la ressource sur un autre noeud. La méthode de contrôle_détecteur_xfnts appelle la méthode svc_validate() pour vérifier qu'une configuration est en place pour prendre en charge le démon xfs (reportez-vous à la rubrique Méthode de validation_xfnts pour plus de détails). Le code de contrôle_détecteur_xfnts est le suivant :


   /* Traitement des arguments transmis par le RGM et initialisation de syslog */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, "Failed to initialize the handle.");
      return (1);
   }

   rc =  svc_validate(scds_handle);
   scds_syslog_debug(DBG_LEVEL_HIGH,
       "monitor_check method "
       "was called and returned <%d>.", rc);

   /* Libération de la mémoire allouée par scds_initialize */
   scds_close(&scds_handle);

   /* Renvoi du résultat de la méthode de "Validation" dans le cadre du contrôle du détecteur */
   return (rc);
}

Détecteur de pannes SUNW.xfnts

Le RGM n'appelle pas directement la méthode de SONDE, mais plutôt la méthode de Démarrage_détecteur pour démarrer le détecteur une fois une ressource démarrée sur un noeud. La méthode de démarrage_détecteur_xfnts démarre le détecteur de pannes sous le contrôle du gestionnaire de processus. La méthode d'arrêt_détecteur_xfnts arrête le détecteur de pannes.

Le détecteur de pannes SUNW.xfnts effectue les opérations suivantes :

Boucle principale xfonts_probe

La méthode xfonts_probe met une boucle en oeuvre. Avant cela, xfonts_probe :

La méthode xfnts_probe met la boucle en oeuvre de la manière suivante :


for (ip = 0; ip < netaddr->num_netaddrs; ip++) {
         /*
          * Obtention du nom d'hôte et du port sur lesquels
          * la santé a été surveillée.
          */
         hostname = netaddr->netaddrs[ip].hostname;
         port = netaddr->netaddrs[ip].port_proto.port;
         /*
          * HA-XFS ne prend en charge qu'un seul port
          * et obtient la valeur du port depuis la
          * première entrée du tableau des ports.
          */
         ht1 = gethrtime(); /* Latch probe start time */
         scds_syslog(LOG_INFO, "Probing the service on port: %d.", port);

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

         /*
          * Mise à jour de l'historique des sondages du service,
          * action si nécessaire.
          * Blocage du délai de fin du sondage.
          */
         ht2 = gethrtime();

         /* Conversion en millisecondes */
         dt = (ulong_t)((ht2 - ht1) / 1e6);

         /*
          * Calcul de l'historique des pannes
          * et action si nécessaire
          */
         (void) scds_fm_action(scds_handle,
             probe_result, (long)dt);
      }   /* Chaque ressource réseau */
   }    /* Toujours continuer le sondage */

La fonction svc_probe() met la logique de sondage en oeuvre. La valeur retournée par svc_probe() est transmise à scds_fm_action() qui détermine s'il convient de redémarrer l'application, de basculer le groupe de ressources ou de ne rien faire.

Fonction svc_probe()

La fonction svc_probe() établit une connexion de socket simple au port spécifié en appelant scds_fm_tcp_connect(). Si la connexion échoue, svc_probe() renvoie une valeur de 100 indiquant un échec total. Si la connexion s'établit, mais que la déconnexion échoue, svc_probe() renvoie une valeur de 50 indiquant un échec partiel. Si la connexion et la déconnexion réussissent, svc_probe() renvoie une valeur de 0, indiquant une réussite.

Le code de svc_probe() est le suivant :


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;


   /*
    * Sondage du service de données par le biais d'une connexion de socket au port */
    * spécifié dans la propriété liste_port de l'hôte alimentant le service
    * de données XFS. Si le service XFS configuré pour écouter le port
    * spécifié répond à la connexion, le sondage est réussi.
    * Dans le cas contraire, nous attendons pendant une période définie
    * dans la propriété délai_sonde avant de conclure à l'échec du sondage.
    */

   /*
    * Utilisez le pourcentage SVC_CONNECT_TIMEOUT_PCT du délai imparti
    * pour vous connecter au port
    */
   connect_timeout = (SVC_CONNECT_TIMEOUT_PCT * timeout)/100;
   t1 = (hrtime_t)(gethrtime()/1E9);

   /*
    * la sonde établit une connexion au nom d'hôte et au port spécifiés.
    * La connexion reçoit 95% du délai_sonde effectif.
    */
   rc = scds_fm_tcp_connect(scds_handle, &sock, hostname, port,
       connect_timeout);
   if (rc) {
      scds_syslog(LOG_ERR,
          "Failed to connect to port <%d> of resource <%s>.",
          port, scds_get_resource_name(scds_handle));
      /*il s'agit d'un échec total */
      return (SCDS_PROBE_COMPLETE_FAILURE);
   }

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

   /*
    * Calculez le temps réel requis pour la connexion. Il doit être inférieur
    * ou égal à délai_connexion, le temps alloué à la connexion.
    * Si la connexion utilise tout le délai qui lui est imparti,
    * la valeur restante de délai_sonde transmise à cette fonction
    * est utilisée comme délai imparti à la déconnexion. Sinon, le
    * temps restant de l'appel de connexion est ajouté au délai
    * de déconnexion.
    *
    */

   time_used = (int)(t2 - t1);

   /*
    * Utilisez le temps restant (timeout - time_took_to_connect) pour la déconnexion
    */

   time_remaining = timeout - (int)time_used;

   /*
    * Si tout le délai est écoulé, utilisez un délai imparti court à code permanent
    * pour essayer une nouvelle fois de provoquer la déconnexion. Ceci évite la fuite fd.
    */
   if (time_remaining <= 0) {
      scds_syslog_debug(DBG_LEVEL_LOW,
          "svc_probe used entire timeout of "
          "%d seconds during connect operation and exceeded the "
          "timeout by %d seconds. Attempting disconnect with timeout"
          " %d ",
          connect_timeout,
          abs(time_used),
          SVC_DISCONNECT_TIMEOUT_SECONDS);

      time_remaining = SVC_DISCONNECT_TIMEOUT_SECONDS;
   }

   /*
    * Renvoi d'un échec partiel en cas d'échec à la déconnexion.
    * Motif : l'appel de connexion réussit, ce qui signifie que
    * l'application vit. Un échec à la déconnexion peut
    * être dû à une application bloquée ou à une lourde charge.
    * Dans ce dernier cas, ne déclarez pas que l'application
    * est morte en renvoyant un échec total. Au lieu de cela, déclarez
    * qu'il s'agit d'un échec partiel. Si cette situation perdure, l'appel
    * de déconnexion échoue une nouvelle fois et l'application est
    * redémarrée.
    */
   rc = scds_fm_tcp_disconnect(scds_handle, sock, time_remaining);
   if (rc != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          "Failed to disconnect to port %d of resource %s.",
          port, scds_get_resource_name(scds_handle));
      /* il s'agit d'un échec partiel */
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

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

   /*
    * S'il ne reste pas de temps, n'effectuez pas le test complet avec
    * fsinfo. Au lieu de cela, renvoyez SCDS_PROBE_COMPLETE_FAILURE/2
    * Cette opération garantit que si le dépassement du délai
    * imparti persiste, le serveur sera redémarré.
    */
   if (time_remaining <= 0) {
      scds_syslog(LOG_ERR, "Probe timed out.");
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

   /*
    * La connexion et la déconnexion au port ont réussi.
    * Exécutez la commande fsinfo pour effectuer un contrôle total de
    * la santé du serveur.
    * Redirigez stdout, sans quoi la sortie de fsinfo
    * se retrouve sur la console.
    */
   (void) sprintf(testcmd,
       "/usr/openwin/bin/fsinfo -server %s:%d> /dev/null",
       hostname, port);
   scds_syslog_debug(DBG_LEVEL_HIGH,
       "Checking the server status with %s.", testcmd);
   if (scds_timerun(scds_handle, testcmd, time_remaining,
      SIGKILL, &rc) != SCHA_ERR_NOERR || rc != 0) {

      scds_syslog(LOG_ERR,
         "Failed to check server status with command <%s>",
         testcmd);
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }
   return (0);
}

Après avoir terminé, svc_probe() renvoie une valeur indiquant une réussite (0), un échec partiel (50) ou un échec total (100). La méthode xfnts_probe transmet cette valeur à scds_fm_action().

Détermination de l'action du détecteur de pannes

La méthode xfnts_probe appelle scds_fm_action() pour déterminer la mesure à prendre. La logique scds_fm_action() est la suivante :

Par exemple, supposons que la sonde établisse une connexion au serveur xfs, mais ne puisse pas se déconnecter. Ceci indique que le serveur tourne mais qu'il peut être bloqué ou être provisoirement soumis à une forte charge. Un échec de la déconnexion renvoie une erreur partielle (50) à scds_fm_action(). Cette valeur se situe sous le seuil de redémarrage du service de données, mais la valeur est gérée dans l'historique des pannes.

Si, pendant le sondage suivant, le serveur n'arrive à nouveau pas à se déconnecter, une valeur 50 est ajoutée à l'historique des pannes géré par scds_fm_action(). La valeur cumulée des pannes est à présent de 100 . Par conséquent, scds_fm_action() redémarre le service de données.

Méthode de validation_xfnts

Le RGM appelle la méthode de Validation quand une ressource est créée et quand une opération de l'administrateur met à jour les propriétés de la ressource ou du groupe la contenant. Le RGM appelle Validation avant la création ou la mise à jour, et un code de sortie avec échec issu de la méthode sur un noeud entraîne l'annulation de la création ou de la mise à jour.

Il n'appelle Validation que lorsque les propriétés de la ressource ou du groupe sont modifiées par une opération de l'administrateur, et non lorsque le RGM définit des propriétés, ou lorsqu'un détecteur définit les propriétés Statut et msg_statut de la ressource.


Remarque :

la méthode Contrôle_détecteur appelle aussi explicitement la méthode de Validation lorsque la méthode de SONDE tente de basculer le service de données sur un autre noeud.


Le RGM appelle Validation avec des arguments différents de ceux transmis aux autres méthodes, y compris les propriétés et valeurs mises à jour. L'appel destiné à scds_initialize() au début de validation_xfnts analyse tous les arguments que le RGM transmet à validation_xfnts et enregistre les informations dans le paramètre scds_handle. Les sous-routines appelées par validation_xfnts utilisent ces informations.

La méthode de validation_xfnts appelle validation_svc() qui vérifie les éléments suivants :

Avant son renvoi, validation_svc() libère toutes les ressources allouées.


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

   return (rc); /* renvoi du résultat de la validation */


Remarque :

avant sa fermeture, la méthode de validation_xfnts appelle scds_close() pour récupérer les ressources allouées par scds_initialize(). Reportez-vous à la rubrique Fonction scds_initialize() et à la page scds_close(3HA) du manuel pour plus de détails.


Méthode de mise_à_jour_xfnts

Le RGM appelle la méthode de Mise_à_jour pour notifier à la ressource en cours d'exécution que ses propriétés ont changé. Les seules propriétés pouvant être modifiées par le service de données xfnts concernent le détecteur de pannes. C'est la raison pour laquelle, lorsqu'une propriété est mise à jour, la méthode de mise_à_jour_xfnts appelle scds_pmf_restart_fm () pour redémarrer le détecteur de pannes.


* vérifier si le détecteur de pannes tourne déjà et, dans ce cas, l'arrêter
   * et le redémarrer. Le second paramètre pour scds_pmf_restart_fm()
   * identifie de manière unique l'instance du détecteur de pannes
   * à redémarrer.
   */

   scds_syslog(LOG_INFO, "Restarting the fault monitor.");
   result = scds_pmf_restart_fm(scds_handle, 0);
   if (result != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          "Failed to restart fault monitor.");
      /* Libère toute la mémoire allouée par scds_initialize */
      scds_close(&scds_handle);
      return (1);
   }

   scds_syslog(LOG_INFO,
   "Completed successfully.");


Remarque :

le second paramètre destiné à scds_pmf_restart_fm() identifie de manière unique l'instance du détecteur de pannes à redémarrer s'il en existe plusieurs. La valeur 0 de l'exemple indique qu'il n'existe qu'une seule instance du détecteur de pannes.