Sun Cluster Entwicklerhandbuch Datendienste für Solaris OS

Anhang C Auflistung von Beispielen für DSDL-Ressourcentypcode

Dieser Anhang listet den vollständigen Code für jede Methode im SUNW.xfnts-Ressourcentyp auf. Er enthält die Auflistung für xfnts.c mit Code für die Unterroutinen, die von den Rückmeldemethoden aufgerufen werden. Die Codeauflistungen in diesem Anhang sind folgende:

xfnts.c

Diese Datei implementiert die Unterroutinen, die von den SUNW.xfnts-Methoden aufgerufen werden.


Beispiel C–1 xfnts.c

/*
 * Copyright (c) 1998-2004 Sun Microsystems, Inc.
 * Alle Rechte vorbehalten.
 *
 * xfnts.c - Übliche Dienstprogramme für HA-XFS
 *
 * Dieses Dienstprogramm enthält die Methoden für das Validieren, Starten
 * und Stoppen des Datendienstes und Fehler-Monitors. Daneben enthält es
 * die Methodezum Testen der Fehlerfreiheit des Datendienstes. Das Testsignal gibt
 * entweder nur Erfolg oder Fehlschlag zurück. Aktionen werden basierend auf
 * diesem zurückgegebenen Wert über die Methode in der Datei
 * xfnts_probe.c ausgeführt.
 */

#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”

/*
 * Die anfängliche Zeitüberschreitung, die dem HAXFS-Datendienst
 * für den vollständigen Start und die Ausführung gewährt wird. 3 % (SVC_WAIT_PCT)
 * der start_timeout-Zeit wird vor Testen des Dienstes gewartet.
 */
#define   SVC_WAIT_PCT      3

/*
 * Es müssen 95% von probe_timeout für die Verbindung mit dem Port verwendet
 * werden, und die restliche Zeit dient zum Trennen der Verbindung in der
 * Funktion svc_probe.
 */
#define   SVC_CONNECT_TIMEOUT_PCT      95

/*
 * SVC_WAIT_TIME wird nur während des Starts in svc_wait() verwendet.
 * In svc_wait() muss vor der Rückgabe sichergestellt sein, dass der Dienst
 * läuft. Daher muss svc_probe() aufgerufen werden, um den
 * Dienst zu überwachen. SVC_WAIT_TIME ist die Zeit zwischen diesen
 * Testsignalen.
 */

#define   SVC_WAIT_TIME      5

/*
 * Dieser Wert wird als Zeitüberschreitung für die Verbindungstrennung
 * verwendet, wenn aus probe_timeout keine Zeit mehr übrig bleibt.
 */

#define   SVC_DISCONNECT_TIMEOUT_SECONDS      2


/*
 * svc_validate():
 *
 * Führt eine HA-XFS-spezifische Validierung der Ressourcenkonfiguration
 * durch.
 * svc_validate überprüft:
 * 1. Confdir_list-Erweiterungseigenschaft
 * 2. fontserver.cfg-Datei
 * 3. xfs-Binärdatei
 * 4. port_list-Eigenschaft
 * 5. Netzwerkressourcen
 * 6. sonstige Erweiterungseigenschaften
 *
 * Wenn eine der obigen Validierungen fehlschlägt, wird ein Wert von > 0
 * zurückgegeben, andernfalls wird 0 für Erfolg zurückgegeben
 */

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;

   /*
    * Konfigurationsverzeichnis für den XFS-Datendienst
    * aus der confdir_list-Erweiterungseigenschaft abrufen.
    */
   confdirs = scds_get_ext_confdir_list(scds_handle);

   /* Fehler zurückgeben, wenn keine confdir_list-Erweiterungseigenschaft vorhanden ist.*/
   if (confdirs == NULL || confdirs->array_cnt != 1) {
      scds_syslog(LOG_ERR,
          “Eigenschaft Confdir_list ist nicht korrekt eingestellt.”);
      return  (1); /* Validierungsfehlschlag */
   }

   /*
    * Pfad zur Konfigurationsdatei aus der Erweiterungseigenschaft
    * confdir_lis erstellen. Da HA-XFS nur eine Konfiguration hat,
    * muss der erste Eintrag der confdir_list-Eigenschaft verwendet werden.
    */
   (void) sprintf(xfnts_conf, “%s/fontserver.cfg”,confdirs->str_array[0]);

   /*
    * Prüfen, ob sich die HA-XFS-Konfigurationsdatei an der richtigen Stelle befindet.
    * Versuchen, auf die HA-XFS-Konfigurationsdatei zuzugreifen und sicherstellen,
    * dass die Berechtigungen richtig eingestellt sind.
    */
   if (stat(xfnts_conf, &statbuf) != 0) {
      /*
       * lint-Fehler unterdrücken, da im errno.h-Prototyp
       * void arg fehlt
       */
      scds_syslog(LOG_ERR,
          “Dateizugriff fehlgeschlagen <%s> : <%s>”,
          xfnts_conf, strerror(errno));   /*lint !e746 */
       return (1);
   }

   /*
    * Sicherstellen, dass die XFS-Binärdateien vorhanden und die Berechtigungen
    * korrekt sind. Die XFS-Binärdateien sollten sich auf dem lokalen Dateisystem
    * und nicht auf dem globalen Dateisystem befinden.
    */
   if (stat(“/usr/openwin/bin/xfs”, &statbuf) != 0) {
      scds_syslog(LOG_ERR,
          “Zugriff auf XFS-Binärdatei nicht möglich : <%s> “,
          strerror(errno));
      return (1);
   }

   /* HA-XFS hat nur Port */
   err = scds_get_port_list(scds_handle, &portlist);
   if (err != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “Zugriff auf Eigenschaft Port_list nicht möglich: %s.”,
         scds_error_string(err));
      return (1); /* Validierungsfehlschlag */
   }

#ifdef TEST
   if (portlist->num_ports != 1) {
      scds_syslog(LOG_ERR,
          “Eigenschaft Port_list darf nur einen Wert haben.”);
      scds_free_port_list(portlist);
      return (1); /* Validierungsfehlschlag */
   }
#endif

   /*
    * Fehler zurückgeben, wenn beim Versuch, die verfügbaren
    * Netzwerkadressressourcen für diese Ressource abzurufen, ein Fehler auftritt
    */
  if ((err = scds_get_rs_hostnames(scds_handle, &snrlp))
      != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “Keine Netzwerkadressressource in Ressourcengruppe: %s.”,
         scds_error_string(err));
      return (1); /* Validierungsfehlschlag */
   }

   /* Fehler zurückgeben, wenn keine Netzwerkadressressourcen vorhanden sind */
   if (snrlp == NULL || snrlp->num_netresources == 0) {
      scds_syslog(LOG_ERR,
          “Keine Netzwerkadressressource in Ressourcengruppe.”);
      rc = 1;
      goto finished;
   }

   /* Sicherstellen, dass sonstige wichtige Erweiterungseigenschaften
      eingestellt sind */
  if (scds_get_ext_monitor_retry_count(scds_handle) <= 0)
{
      scds_syslog(LOG_ERR,
          “Eigenschaft Monitor_retry_count ist nicht eingestellt.”);
      rc = 1; /* Validierungsfehlschlag */
      goto finished;
   }
   if (scds_get_ext_monitor_retry_interval(scds_handle) <= 0) {
      scds_syslog(LOG_ERR,
          “Eigenschaft Monitor_retry_interval ist nicht eingestellt.”);
      rc = 1; /* Validierungsfehlschlag */
      goto finished;
   }

   /* Alle Validierungsprüfungen waren erfolgreich */
   scds_syslog(LOG_INFO, “Validierung erfolgreich.”);
   rc = 0;

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

   return (rc); /* Validierungsergebnis zurückgeben */
}

/*
 * svc_start():
 *
 * Startet den X Font Server
 * Bei Erfolg wird 0, bei Fehlschlag >0 zurückgeben.
 *
 * Der XFS-Dienst wird durch Ausführen des folgenden Befehls gestartet:
 * /usr/openwin/bin/xfs -config <fontserver.cfg file> -port <port to listen>
 * XFS wird unter PMF gestartet. XFS wird als Dienst mit einer einzigen
 * Instanz gestartet. Das PMF-Tag für den Datendienst hat die Form
 * <resourcegroupname,resourcename,instance_name.svc>.
 * Da im Fall von XFS nur eine Instanz vorhanden ist, ist die instance_number
 * im Tag 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;

   /* Konfigurationsverzeichnis aus der confdir_list-Eigenschaft abrufen */
   confdirs = scds_get_ext_confdir_list(scds_handle);

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

   /* Den von XFS verwendeten Port aus der Port_list-Eigenschaft abrufen */
   err = scds_get_port_list(scds_handle, &portlist);
  if (err != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “Zugriff auf Eigenschaft Port_list nicht möglich.”);
      return (1);
   }

   /*
    * Befehl zum Starten von HA-XFS erstellen.
    * HINWEIS: XFS-Dämon druckt folgende Meldung beim Stoppen von XFS
    * “/usr/openwin/bin/xfs Hinweis: Wird beendet”
    * Um die Dämonmeldung zu unterdrücken, wird die
    * Ausgabe zu /dev/null umgeleitet.
    */
   (void) sprintf(cmd,
       “/usr/openwin/bin/xfs -config %s -port %d 2>/dev/null”,
       xfnts_conf, portlist->ports[0].port);

   /*
    * HA-XFS unter PMF starten. Hinweis: HA-XFS wird als Dienst mit einer einzigen
    * Instanz gestartet. Das letzte Argument der scds_pmf_start-Funktion gibt die
    * Ebene der zu überwachenden untergeordneten Prozesse an. Ein Wert von -1 für
    * diesen Parameter bedeutet, dass alle untergeordneten Prozesse zusammen
    * mit dem ursprünglichen Prozess überwacht werden müssen.
    */
   scds_syslog(LOG_INFO, “Startanforderung wird ausgegeben.”);
   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,
          “Startbefehl erfolgreich beendet.”);
   } else {
      scds_syslog(LOG_ERR,
          “HA-XFS-Start fehlgeschlagen “);
   }

   scds_free_port_list(portlist);
   return (err); /* Erfolg-/Fehlschlag-Status zurückgeben */
}


/*
*svc_stop():
*
* Hält den XFS-Server an.
* Gibt 0 bei Erfolg, > 0 bei Fehlschlägen zurück.
*
* svc_stop stoppt den Server durch Aufrufen der toolkit-Funktion:
* scds_pmf_stop.
*/
int
svc_stop(scds_handle_t scds_handle)
{
   scha_err_t   err;

   /*
    * Der Zeitüberschreitungswert für einen Erfolg der Stopp-Methode ist in
    * der systemdefinierten Stop_Timeout-Eigenschaft eingestellt.
    */
   scds_syslog(LOG_ERR, “Stopp-Anforderung wird ausgegeben.”);
   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,
          “HA-XFS-Stopp fehlgeschlagen.”);
      return (1);
   }

   scds_syslog(LOG_INFO,
       “HA-XFS-Stopp erfolgreich.”);
   return (SCHA_ERR_NOERR); /* Erfolgreich gestoppt */
}

/*
 * svc_wait():
 *
 * Warten, bis der Datendienst vollständig gestartet ist und sicherstellen,
 * dass er fehlerfrei läuft
 */

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

   /* Netzwerkressource für das Testsignal abrufen */
   if (scds_get_netaddr_list(scds_handle, &netaddr)) {
      scds_syslog(LOG_ERR,
          “Keine Netzwerkadressressourcen in Ressourcengruppe gefunden.”);
      return (1);
   }

   /* Fehler zurückgeben, wenn keine Netzwerkressourcen vorhanden sind */
   if (netaddr == NULL || netaddr->num_netaddrs == 0) {
      scds_syslog(LOG_ERR,
          “Keine Netzwerkadressressource in Ressourcengruppe.”);
      return (1);
   }

   /*
    * Start-Methoden-Zeitüberschreitung, Port-Nummer für das Testsignal
    * und Testsignal-Zeitüberschreitungswert abrufen
    */
   svc_start_timeout = scds_get_rs_start_timeout(scds_handle);
   probe_timeout = scds_get_ext_probe_timeout(scds_handle);

   /*
    * Für SVC_WAIT_PCT Prozent der start_timeout-Zeit wird geruht,
    * bevor der Datendienst tatsächlich getestet wird. So hat der Datendienst
    * Zeit für ein vollständiges Hochfahren, um auf das Testsignal zu antworten.
    * HINWEIS: Der Wert für SVC_WAIT_PCT kann für verschiedene Datendienste
    * unterschiedlich sein.
    * Anstelle von sleep() den Befehl scd_svc_wait() aufrufen.
    * Wenn der Dienst zu häufig fehlschlägt, wird
    * aufgegeben, und es erfolgt eine schnelle Rückgabe.
    */
   if (scds_svc_wait(scds_handle, (svc_start_timeout * SVC_WAIT_PCT)/100)
      != SCHA_ERR_NOERR) {

      scds_syslog(LOG_ERR, “Starten des Dienstes fehlgeschlagen.”);
      return (1);
   }

   do {
      /*
       * Datendienst auf der IP-Adresse der
       * Netzwerkressource und dem Port-Namen testen.
       */
      rc = svc_probe(scds_handle,
          netaddr->netaddrs[0].hostname,
          netaddr->netaddrs[0].port_proto.port, probe_timeout);
      if (rc == SCHA_ERR_NOERR) {
         /* Erfolg. Ressourcen freigeben und zurückgeben */
         scds_free_netaddr_list(netaddr);
         return (0);
      }

      /*
       * Der Datendienst ist noch im Hochladevorgang. Eine Weile
       * ruhen lassen, bevor erneut getestet wird. Anstelle von sleep()
       * den Befehl cscds_svc_wait() aufrufen. Wenn der Dienst zu häufig
       * fehlschlägt, wird aufgegeben, und es erfolgt eine schnelle Rückgabe.
       */
      if (scds_svc_wait(scds_handle, SVC_WAIT_TIME)
         != SCHA_ERR_NOERR) {
         scds_syslog(LOG_ERR, “Starten des Dienstes fehlgeschlagen.”);
         return (1);
      }

   /* Auf RGM-Zeitüberschreitung verlassen und das Programm beenden */
   } while (1);

}

/*
 * Diese Funktion startet den Fehler-Monitor für eine HA-XFS-Ressource.
 * Dies geschieht, indem das Testsignal unter PMF gestartet wird. Das PMF-Tag
 * wird folgendermaßen abgeleitet: <RG-name,RS-name,instance_number.mon>.
 * Die Neustart-Option von PMF wird verwendet, aber nicht “infinite restart”.
 * Stattdessen wird interval/retry_time aus der RTR-Datei abgerufen.
 */

int
mon_start(scds_handle_t scds_handle)
{
   scha_err_t   err;

   scds_syslog_debug(DBG_LEVEL_HIGH,
      “MONITOR_START-Methode wird für Ressource aufgerufen <%s>.”,
      scds_get_resource_name(scds_handle));

   /*
    * Es wird davon ausgegangen, dass das Testsignal xfnts_probe in demselben
    * Unterverzeichnis verfügbar ist, in dem die anderen Rückmeldemethoden
    * für den RT installiert sind. Der letzte Parameter von scds_pmf_start gibt die
    * untergeordnete Überwachungsebene an. Da das Testsignal unter PMF gestartet
    * wird, muss nur der Testsignalprozess überwacht werden. Daher wird der Wert 0
    * verwendet.
    */
   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,
          “Starten des Fehler-Monitors fehlgeschlagen.”);
      return (1);
   }

   scds_syslog(LOG_INFO,
       “Fehler-Monitor gestartet.”);

   return (SCHA_ERR_NOERR); /* Monitor erfolgreich gestartet */
}


/*
 * Diese Funktion stoppt den Fehler-Monitor für eine HA-XFS-Ressource.
 * Dies geschieht über PMF. Das PMF-Tag für den Fehler-Monitor setzt sich aus
 * folgenden Elementen zusammen: <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,
      “scds_pmf_stop-Methode wird aufgerufen”);

   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,
          “Stoppen des Fehler-Monitors fehlgeschlagen.”);
      return (1);
   }

   scds_syslog(LOG_INFO,
       “Fehler-Monitor gestoppt.”);

   return (SCHA_ERR_NOERR); /* Monitor erfolgreich gestoppt */
}

/*
 * svc_probe(): Gibt ein datendienstspezifisches Testsignal aus. Ein Gleitkommawert
 * zwischen 0 (Erfolg) und 100 (Totalfehlschlag) wird zurückgegeben.
 *
 * Das Testsignal stellt eine einfache Socket-Verbindung mit dem XFS-Server am
 * angegebenen Port her, der als Ressourcenerweiterungseigenschaft (Port_list)
 * konfiguriert ist und den Datendienst testet. Wenn das Testsignal keine
 * Verbindung mit dem Port herstellen kann, wird ein Wert von 100 für Totalfehlschlag
 * zurückgegeben.
 * Wenn die Verbindung durchgeht und die Verbindungstrennung vom Port
 * fehlschlägt, wird ein Wert von 50 für Teilfehlschlag zurückgegeben.
 *
 */
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;


   /*
    * Datendienst durch Herstellen einer Socketverbindung über
    * den Port, der in der port_list-Eigenschaft angegeben ist, mit dem Host
    * für den XFS-Datendienst testen. Wenn der für das Abhören am angegebenen
    * Port konfigurierte XFS-Dienst auf die Verbindung antwortet, ist der Test
    * erfolgreich. Andernfalls wird für die in der probe_timeout-Eigenschaft
    * angegebene Zeit gewartet und dann geschlossen, dass der Test
    * fehlgeschlagen ist.
    */

   /*
    * Den Prozentsatz der Zeitüberschreitung aus SVC_CONNECT_TIMEOUT_PCT
    * für die Verbindung mit dem Port verwenden.
    */
   connect_timeout = (SVC_CONNECT_TIMEOUT_PCT * timeout)/100;
   t1 = (hrtime_t)(gethrtime()/1E9);

   /*
    * Das Testsignal stellt eine Verbindung mit dem angegebenen Hostnamen und
    * Port her.
    * Die Verbindungsdauer ist für 95% des ganzen probe_timeout-Wertes ausgelegt.
    */
   rc = scds_fm_tcp_connect(scds_handle, &sock, hostname, port,
       connect_timeout);
   if (rc) {
      scds_syslog(LOG_ERR,
          “Verbindung mit Port <%d> der Ressource <%s> fehlgeschlagen.”,
          port, scds_get_resource_name(scds_handle));
      /* Dies ist ein Totalfehlschlag */
      return (SCDS_PROBE_COMPLETE_FAILURE);
   }

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

   /*
    * Den tatsächlichen Zeitaufwand für die Verbindungsherstellung berechnen.
    * Er sollte weniger oder gleich connect_timeout sein, der für die Verbindung
    * zugewiesenen Zeit.
    * Wenn der Verbindungsvorgang die gesamte zugewiesene Zeit verbraucht,
    * wird der restliche Wert aus probe_timeout, der an diese Funktion übergeben
    * wird, als Verbindungstrennungs-Zeitüberschreitung verwendet. Andernfalls wird
    * die restliche Zeit aus dem Verbindungsaufruf ebenfalls zur Verbindungstrennungs-
    * Zeitüberschreitung hinzugerechnet.
    *
    */

   time_used = (int)(t2 - t1);

   /*
    * Die restliche Zeit (timeout - time_took_to_connect) zur Verbindungstrennung
    * verwenden.
    */

   time_remaining = timeout - (int)time_used;

   /*
    * Wenn die gesamte Zeit verbraucht ist, eine kleine fest codierte
    * Zeitüberschreitung für einen weiteren Trennversuch verwenden. So wird
    * der fd-Leak verhindert.
    */
   if (time_remaining <= 0) {
      scds_syslog_debug(DBG_LEVEL_LOW,
          “svc_probe hat während des Verbindungsvorgangs den gesamten Zeitüberschreitungswert “
          “von %d Sekunden verbraucht und die Zeitüberschreitung um %d Sekunden “
          “ überschritten. Es wird versucht, mit Zeitüberschreitung %d zu trennen“, ”
          connect_timeout,
          abs(time_used),
          SVC_DISCONNECT_TIMEOUT_SECONDS);

      time_remaining = SVC_DISCONNECT_TIMEOUT_SECONDS;
   }

   /*
    * Bei Fehlschlagen der Verbindungstrennung Teilfehlschlag zurückgeben.
    * Grund: der Verbindungsaufruf ist erfolgreich, was bedeutet, dass die
    * Anwendung aktiv ist. Ein Fehlschlagen der Verbindungstrennung kann
    * durch eine hängende Anwendung oder Überlastung verursacht werden.
    * Wenn Letzteres der Fall ist, darf die Anwendung nicht als beendet deklariert und
    * Totalfehlschlag zurückgeben werden. Es muss stattdessen ein Teilfehlschlag
    * deklariert werden. Wenn diese Situation anhält, schlägt der Trennvorgang erneut
    * fehl, und die Anwendung wird neu gestartet.

    */
   rc = scds_fm_tcp_disconnect(scds_handle, sock, time_remaining);
   if (rc != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “Verbindungstrennung an Port %d für Ressource %s fehlgeschlagen.”,
          port, scds_get_resource_name(scds_handle));
      /* Dies ist ein Teilfehlschlag */
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

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

   /*
    * Wenn keine Zeit übrig bleibt, nicht den vollständigen Test mit fsinfo
    * ausführen. Stattdessen SCDS_PROBE_COMPLETE_FAILURE/2
    * zurückgeben. So wird sichergestellt, dass bei Andauern dieser
    * Zeitüberschreitung der Server neu gestartet wird.
    */
   if (time_remaining <= 0) {
      scds_syslog(LOG_ERR, “Zeitüberschreitung für Testsignal.”);
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

   /*
    * Die Verbindung mit und Verbindungstrennung vom Port ist erfolgreich.
    * Den fsinfo-Befehl ausführen, um einen vollständigen Gesundheits-Check
    * des Servers auszuführen.
    * stdout  umleiten; andernfalls gelangt die Ausgabe von fsinfo
    * an die Konsole.
    */
   (void) sprintf(testcmd,
       “/usr/openwin/bin/fsinfo -server %s:%d> /dev/null”,
       hostname, port);
   scds_syslog_debug(DBG_LEVEL_HIGH,
       “Serverstatus wird mit %s überprüft.”, testcmd);
   if (scds_timerun(scds_handle, testcmd, time_remaining,
      SIGKILL, &rc) != SCHA_ERR_NOERR || rc != 0) {

      scds_syslog(LOG_ERR,
         “Serverstatusprüfung mit Befehl <%s> fehlgeschlagen”,
         testcmd);
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }
   return (0);
}

xfnts_monitor_check-Methode

Diese Methode überprüft, ob die Basiskonfiguration des Ressourcentyps gültig ist.


Beispiel C–2 xfnts_monitor_check.c

/*
 * Copyright (c) 1998-2004 Sun Microsystems, Inc.
 * Alle Rechte vorbehalten.
 *
 * xfnts_monitor_check.c - Monitor-Prüfmethode für HA-XFS
 */

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

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

/*
 * Eine einfache Validierungsprüfung für den Dienst ausführen.
 */

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

   /* Von RGM übergebene Argumente verarbeiten und syslog initialisieren */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “Initialisierung des Handles fehlgeschlagen.”);
      return (1);
   }

   rc =  svc_validate(scds_handle);
   scds_syslog_debug(DBG_LEVEL_HIGH,
       “monitor_check-Methode “
       “wurde aufgerufen und <%d> zurückgegeben.”, rc);

   /* Gesamten von scds_initialize zugewiesenen Speicherplatz freigeben */
   scds_close(&scds_handle);

   /* Ergebnis der validate-Methode als Teil der Monitor-Prüfung zurückgeben*/
   return (rc);
}

xfnts_monitor_start-Methode

Diese Methode startet die xfnts_probe-Methode.


Beispiel C–3 xfnts_monitor_start.c

/*
 * Copyright (c) 1998-2004 Sun Microsystems, Inc.
 * Alle Rechte vorbehalten.
 *
 * xfnts_monitor_start.c - Monitor-Start-Methode für HA-XFS
 */

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

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

/*
 * Diese Methode startet den Fehler-Monitor für eine HA-XFS-Ressource.
 * Dafür wird das Testsignal unter PMF gestartet. Das PMF-Tag
 * wird als RG-name,RS-name.mon abgeleitet. Die Neustartoption von PMF
 * wird verwendet; jedoch nicht “infinite restart”. Stattdessen
 * wird interval/retry_time aus der RTR-Datei abgerufen.
 */

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

   /* Von RGM übergebene Argumente verarbeiten und syslog initialisieren */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “Initialisierung des Handles fehlgeschlagen.”);
      return (1);
   }

   rc = mon_start(scds_handle);

   /* Den gesamten von scds_initialize zugewiesenen Speicherplatz freigeben */
   scds_close(&scds_handle);

   /* Ergebnis der monitor_start-Methode zurückgeben */
   return (rc);
}

xfnts_monitor_stop-Methode

Diese Methode stoppt die xfnts_probe-Methode.


Beispiel C–4 xfnts_monitor_stop.c

/*
 * Copyright (c) 1998-2004 Sun Microsystems, Inc.
 * Alle Rechte vorbehalten.
 *
 * xfnts_monitor_stop.c - Monitor-Stopp-Methode für HA-XFS
 */

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

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

/*
 * Diese Methode stoppt den Fehler-Monitor für eine HA-XFS-Ressource.
 * Dies geschieht über PMF. Das PMF-Tag für den Fehler-Monitor ist auf
 * RG-name_RS-name.mon basierend aufgebaut.
 */

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

   scds_handle_t   scds_handle;
   int    rc;

   /* Von RGM übergebene Argumente verarbeiten und syslog initialisieren */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “Initialisierung des Handle fehlgeschlagen.”);
      return (1);
   }
   rc = mon_stop(scds_handle);

   /* Den gesamten von scds_initialize zugewiesenen Speicherplatz freigeben */
   scds_close(&scds_handle);

   /* Ergebnis der Monitor-Stopp-Methode zurückgeben */
   return (rc);
}

xfnts_probe-Methode

Die xfnts_probe-Methode prüft die Verfügbarkeit der Anwendung und entscheidet, ob ein Failover ausgeführt oder der Datendienst neu gestartet wird. Die Rückmeldemethode xfnts_monitor_start startet dieses Programm, und die Rückmeldemethode xfnts_monitor_stop stoppt es.


Beispiel C–5 xfnts_probe.c+

/*
 * Copyright (c) 1998-2004 Sun Microsystems, Inc.
 * Alle Rechte vorbehalten.
 *
 * xfnts_probe.c - Testsignal für 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():
 * Einfach eine Endlosschleife, die manchmal ruht (sleep()) und
 * auf das PMF-Aktionsskript wartet, das sleep() unterbricht. Bei
 * Unterbrechung wird die Start-Methode für HA-XFS aufgerufen, um
 * sie neu zu starten.
 */

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, “Initialisierung des Handles fehlgeschlagen.”);
      return (1);
   }


   /* Für diese Ressource verfügbare IP-Adressen abrufen */
   if (scds_get_netaddr_list(scds_handle, &netaddr)) {
      scds_syslog(LOG_ERR,
          “Keine Netzwerkadressressource in Ressourcengruppe.”);
      scds_close(&scds_handle);
      return (1);
   }

   /* Fehler zurückgeben, wenn keine Netzwerkressourcen vorhanden sind */
   if (netaddr == NULL || netaddr->num_netaddrs == 0) {
      scds_syslog(LOG_ERR,
          “Keine Netzwerkadressressource in Ressourcengruppe.”);
      return (1);
   }


   /*
    * Zeitüberschreitung aus den X-Eigenschaften einstellen.
    * Das bedeutet, dass jede Testsignalwiederholung eine volle Zeitüberschreitung
    * für jede Netzwerkressource erhält, ohne die Zeitüberschreitung unter allen für
    * diese Ressource konfigurierten Netzwerkressourcen aufzuteilen.
    */
   timeout = scds_get_ext_probe_timeout(scds_handle);

   for (;;) {

      /*
       * Für die Dauer von thorough_probe_interval zwischen den
       *  einzelnen Testsignalen ruhen.
       */
      (void) scds_fm_sleep(scds_handle,
          scds_get_rs_thorough_probe_interval(scds_handle));

      /*
       * Jetzt alle verwendeten IP-Adressen testen. Schleife über:
       * 1. Allen verwendeten Netzwerkressourcen.
       * 2. Allen IP-Adressen einer bestimmten Ressource.
       * Für jede geprüfte IP-Adresse die Fehlschlaghistorie berechnen.
       */
      probe_result = 0;
      /*
       * Für alle Ressourcen wiederholen, um alle IP-Adressen
       * abzurufen, die für das Aufrufen von svc_probe() verwendet werden sollen.
       */
      for (ip = 0; ip < netaddr->num_netaddrs; ip++) {
         /*
          * Hostnamen und Port erfassen, deren
          * Fehlerfreiheit überwacht werden soll.
          */
         hostname = netaddr->netaddrs[ip].hostname;
         port = netaddr->netaddrs[ip].port_proto.port;
         /*
          * HA-XFS unterstützt nur einen Port. Daher muss
          * der Port-Wert aus dem ersten Eintrag im
          * Port-Array abgerufen werden.
          */
         ht1 = gethrtime(); /* Testsignal-Startzeit festhalten*/
         scds_syslog(LOG_INFO, “Dienst wird auf “
             “Port: %d getestet.”, port);

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

         /*
          * Diensttestsignalhistorie aktualisieren, und
          * bei Bedarf Aktionen einleiten.
          * Testsignal-Endzeit festhalten.
          */
         ht2 = gethrtime();

         /* In Millisekunden umrechnen */
         dt = (ulong_t)((ht2 - ht1) / 1e6);

         /*
          * Fehlschlaghistorie berechnen und
          * bei Bedarf Aktionen einleiten.
          */
         (void) scds_fm_action(scds_handle,
             probe_result, (long)dt);
      }   /* Jede Netzwerkressource */
   }    /* Endlos weitertesten */
}

xfnts_start-Methode

RGM ruft die Start-Methode auf einem Cluster-Knoten auf, wenn die Ressourcengruppe, die den Datendienst enthält, auf diesem Knoten online gebracht wird bzw. wenn die Ressource aktiviert wird. Die xfnts_start-Methode aktiviert den xfs-Dämon auf diesem Knoten.


Beispiel C–6 xfnts_start.c

/*
 * Copyright (c) 1998-2004 Sun Microsystems, Inc.
 * Alle Rechte vorbehalten.
 *
 * xfnts_svc_start.c - Start-Methode für HA-XFS
 */

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

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

/*
 * Start-Methode für HA-XFS. Sie führt einige Kontrollprüfungen bei
 * den Ressourceneinstellungen aus und startet dann HA-XFS unter PMF mit
 * einem Aktionsskript.
 */

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

   /*
    * Alle von RGM übergebenen Argumente verarbeiten und syslog
    * initialisieren
    */

   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “Initialisierung des Handles fehlgeschlagen.”);
      return (1);
   }

   /* Konfiguration validieren und bei Fehler zurückgehen */
   rc = svc_validate(scds_handle);
   if (rc != 0) {
      scds_syslog(LOG_ERR,
          “Konfigurationsvalidierung fehlgeschlagen.”);
      return (rc);
   }

   /* Datendienst starten und bei Fehlschlag Fehler zurückgeben */
   rc = svc_start(scds_handle);
   if (rc != 0) {
      goto finished;
   }

   /* Warten, bis der Dienst vollständig gestartet ist. */
   scds_syslog_debug(DBG_LEVEL_HIGH,
       “svc_wait wird aufgerufen, um zu überprüfen, ob der Dienst gestartet wurde.”);

   rc = svc_wait(scds_handle);

   scds_syslog_debug(DBG_LEVEL_HIGH,
       “Rückgabe von svc_wait”);

   if (rc == 0) {
      scds_syslog(LOG_INFO, “Dienst erfolgreich gestartet.”);
   } else {
      scds_syslog(LOG_ERR, “Starten des Dienstes fehlgeschlagen.”);
   }


finished:
   /* Zugewiesene Umgebungsressourcen freigeben */
   scds_close(&scds_handle);

   return (rc);
}

Die xfnts_stop-Methode

RGM ruft die Stop-Methode auf einem Cluster-Knoten auf, wenn die Ressourcengruppe mit der HA-XFS-Ressource auf diesem Knoten offline gebracht wird oder wenn die Ressource deaktiviert wird. Diese Methode stoppt den xfs-Dämon auf diesem Knoten.


Beispiel C–7 xfnts_stop.c

/*
 * Copyright (c) 1998-2004 Sun Microsystems, Inc.
 * Alle Rechte vorbehalten.
 *
 * xfnts_svc_stop.c - Stopp-Methode für HA-XFS
 */

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

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

/*
 * Stoppt den HA-XFS-Prozess unter Verwendung von PMF
 */

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

   scds_handle_t   scds_handle;
   int      rc;

   /* Von RGM übergebene Argumente verarbeiten und syslog initialisieren */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “Initialisierung des Handles fehlgeschlagen.”);
      return (1);
   }

   rc = svc_stop(scds_handle);

   /* Gesamten von scds_initialize zugewiesenen Speicherplatz freigeben */
   scds_close(&scds_handle);

   /* Ergebnis der svc_stop-Methode zurückgeben */
   return (rc);
}

Die xfnts_update-Methode

RGM ruft die Update-Methode auf, um eine laufende Ressource von der Änderung ihrer Eigenschaften zu benachrichtigen. Das Programm ruft Update auf, nachdem eine Verwaltungsaktion erfolgreich die Eigenschaften einer Ressource bzw. deren Gruppe eingestellt hat.


Beispiel C–8 xfnts_update.c

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

/*
 * Copyright (c) 1998-2004 Sun Microsystems, Inc.
 * Alle Rechte vorbehalten.
 *
 * xfnts_update.c - Update-Methode für HA-XFS
 */

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

/*
 * Einige Ressourceneigenschaften sind möglicherweise aktualisiert worden. All diese
 * aktualisierbaren Eigenschaften beziehen sich auf den Fehler-Monitor. Daher sollte
 * es genügen, einfach den Monitor neu zu starten.
 */

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

   /* Von RGM übergebene Argumente verarbeiten und syslog initialisieren */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “Initialisierung des Handles fehlgeschlagen.”);
      return (1);
   }

   /*
    * Prüfen, ob der Fehler-Monitor bereits läuft. Falls ja, stoppen und neu starten.
    * Der zweite Parameter von scds_pmf_restart_fm() identifiziert
    * eindeutig die Instanz des Fehler-Monitors, die neu gestartet werden
    * muss.
    */

   scds_syslog(LOG_INFO, “Fehler-Monitor wird neu gestartet.”);
   result = scds_pmf_restart_fm(scds_handle, 0);
   if (result != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          “Neustart des Fehler-Monitors fehlgeschlagen.”);
      /* Gesamten von scds_initialize zugewiesenen Speicherplatz freigeben */
      scds_close(&scds_handle);
      return (1);
   }

   scds_syslog(LOG_INFO,
       “Erfolgreich beendet.”);

   /* Gesamten von scds_initialize zugewiesenen Speicherplatz freigeben */
   scds_close(&scds_handle);

   return (0);
}

Codeauflistung für die xfnts_validate-Methode

Diese Methode überprüft das Vorhandensein des Verzeichnisses, auf das die Confdir_list-Eigenschaft zeigt. RGM ruft diese Methode auf, wenn der Datendienst erstellt wird und wenn der Cluster-Verwalter Datendiensteigenschaften aktualisiert. Die Monitor_check-Methode ruft diese Methode immer dann auf, wenn der Fehler-Monitor ein Failover für den Datendienst auf einen neuen Knoten ausführt.


Beispiel C–9 xfnts_validate.c

/*
 * Copyright (c) 1998-2004 Sun Microsystems, Inc.
 * Alle Rechte vorbehalten.
 *
 * xfnts_validate.c - Validate-Methode für HA-XFS
 */

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

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

/*
 * Sicherstellen, dass die Eigenschaften korrekt eingestellt wurden.
 */

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

   /* Von RGM übergebene Argumente verarbeiten und syslog initialisieren*/
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, “Initialisierung des Handles fehlgeschlagen.”);
      return (1);
   }
   rc = svc_validate(scds_handle);

   /* Gesamten von scds_initialize zugewiesenen Speicherplatz freigeben */
   scds_close(&scds_handle);

   /* Ergebnis der Validate-Methode zurückgeben*/
   return (rc);

}