Sun Cluster Entwicklerhandbuch Datendienste für Solaris OS

Kapitel 8 Beispielressourcentyp-Implementierung mit DSDL

Dieses Kapitel beschreibt einen Beispielressourcentyp, SUNW.xfnts, der mit der DSDL implementiert wird. Der Datendienst ist in C geschrieben. Die zugrunde liegende Anwendung ist X Font Server, ein TCP/IP-basierter Dienst.

In diesem Kapitel finden Sie folgende Informationen:

X Font Server

X Font Server ist ein einfacher, TCP/IP-basierter Dienst, der seinen Clients Schriftdateien zustellt. Clients stellen eine Verbindung mit dem Server her, um einen Schriftsatz anzufordern. Der Server liest die Schriftdateien von der Platte und stellt sie den Clients zu. Der X Font Server-Dämon besteht aus einer Server-Binärdatei, /usr/openwin/bin/xfs. Der Dämon wird in der Regel von inetd aus gestartet. In diesem Beispiel wird jedoch angenommen, dass der entsprechende Eintrag in der /etc/inetd.conf-Datei deaktiviert wurde (zum Beispiel durch den Befehl fsadmin -d). Daher befindet sich der Dämon unter alleiniger Steuerung durch Sun Cluster.

X Font Server-Konfigurationsdatei

Standardmäßig liest X Font Server die Konfigurationsinformationen aus der Datei /usr/openwin/lib/X11/fontserver.cfg. Der Katalogeintrag in diese Datei enthält eine Liste der Schriftverzeichnisse, die dem Dämon zur Verfügung stehen. Der Cluster-Verwalter kann die Schriftverzeichnisse im globalen Dateisystem ablegen. Dadurch wird die Verwendung von X Font Server unter Sun Cluster optimiert, da im System nur eine einzige Kopie der Schriftdatenbank verwaltet wird. Dann muss der Verwalter fontserver.cfg dahingehend bearbeiten, dass die neuen Pfade für die Schriftverzeichnisse enthalten sind.

Zur Vereinfachung der Konfiguration kann der Verwalter auch die Konfigurationsdatei selbst im globalen Dateisystem ablegen. Der xfs-Dämon stellt Befehlszeilenargumente bereit, mit denen der vorgegebene Standardspeicherort dieser Datei übersteuert wird. Der SUNW.xfnts-Ressourcentyp verwendet den folgenden Befehl zum Starten des Dämons unter Sun Cluster-Steuerung:


/usr/openwin/bin/xfs -config <Speicherort_der_CFG_Datei>/fontserver.cfg \
-port <Port-Nummer>

In der SUNW.xfnts-Ressourcentypimplementierung können Sie die Confdir_list-Eigenschaft zum Verwalten des Speicherortes der fontserver.cfg-Konfigurationsdatei verwenden.

TCP-Port-Nummer

Die TCP-Port-Nummer, die der xfs-Serverdämon abhört, ist normalerweise der “fs”-Port (üblicherweise als 7100 in der /etc/services-Datei definiert). Mit der Option -port an der xfs-Befehlszeile kann der Systemverwalter jedoch die Standardeinstellung übersteuern. Sie können die Port_list-Eigenschaft im SUNW.xfnts-Ressourcentyp verwenden, um den Standardwert einzustellen und um die Verwendung der Option -port an der xfs-Befehlszeile zu unterstützen. Der Standardwert dieser Eigenschaft wird als 7100/tcp in der RTR-Datei definiert. In der SUNW.xfnts Start-Methode wird Port_list an die Option -port an der xfs-Befehlszeile übergeben. Daher muss der Benutzer dieses Ressourcentyps keine Port-Nummer angeben—der Standard-Port ist 7100/tcp—, er hat jedoch die Möglichkeit, bei der Konfiguration des Ressourcentyps einen anderen Port anzugeben, indem er einen anderen Wert für die Port_list-Eigenschaft angibt.

Namenskonventionen

Sie können die verschiedenen Teile des Beispielcodes identifizieren, indem Sie auf folgende Konventionen achten.

SUNW.xfnts-RTR-Datei

Dieser Abschnitt beschreibt mehrere Schlüsseleigenschaften in der SUNW.xfnts-RTR-Datei. Der Zweck der einzelnen Eigenschaften in der Datei wird nicht beschrieben. Diese Beschreibung finden Sie unter Einstellen der Ressourcen- und Ressourcentypeigenschaften.

Die Confdir_list-Erweiterungseigenschaft identifiziert das Konfigurationsverzeichnis (bzw. eine Verzeichnisliste) folgendermaßen:


{
        PROPERTY = Confdir_list;
        EXTENSION;
        STRINGARRAY;
        TUNABLE = AT_CREATION;
        DESCRIPTION = "Pfad(e) zum Konfigurationsverzeichnis;
}

Die Confdir_list-Eigenschaft gibt keinen Standardwert an. Der Cluster-Verwalter muss zum Zeitpunkt der Ressourcenerstellung ein Verzeichnis angeben. Dieser Wert kann später nicht mehr geändert werden, da seine Einstellbarkeit auf AT_CREATION beschränkt ist.

Die Port_list-Eigenschaft identifiziert folgendermaßen den Port, den der Serverdämon abhört:


{
        PROPERTY = Port_list;
        DEFAULT = 7100/tcp;
        TUNABLE = AT_CREATION;
}

Da für die Eigenschaft ein Standardwert deklariert wird, kann der Cluster-Verwalter zum Zeitpunkt der Ressourcenerstellung entscheiden, ob er einen neuen Wert angibt oder den Standardwert akzeptiert. Dieser Wert kann später nicht mehr geändert werden, da seine Einstellbarkeit auf AT_CREATION beschränkt ist.

scds_initialize()-Funktion

Die DSDL erfordert, dass jede Rückmeldemethode zu Methodenbeginn die scds_initialize(3HA)-Funktion aufruft. Diese Funktion führt folgende Vorgänge aus:

Sie verwendet die scds_close()-Funktion, um die Ressourcen zurückzufordern, die von scds_initialize() zugewiesen wurden.

xfnts_start-Methode

RGM ruft die Start-Methode auf einem Cluster-Knoten auf, wenn die Ressourcengruppe mit der Datendienstressource auf diesem Knoten online gebracht wird bzw. wenn die Ressource aktiviert wird. Im SUNW.xfnts-Beispielressourcentyp aktiviert die xfnts_start-Methode den xfs-Dämon auf diesem Knoten.

Die xfnts_start-Methode ruft scds_pmf_start() auf, um den Dämon unter PMF zu starten. PMF verfügt über automatische Fehlerbenachrichtigungs- und Neustartfunktionen und ist in den Fehler-Monitor integriert.


Hinweis –

Der erste Aufruf in xfnts_start erfolgt an scds_initialize(). Diese Funktion führt einige wichtige Systemverwaltungs-Funktionen aus (weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_initialize(3HA)).


Validieren des Dienstes vor dem Start

Vor dem Versuch, X Font Server zu starten, ruft die xfnts_start-Methode svc_validate() auf, um zu überprüfen, ob eine geeignete Konfiguration zur Unterstützung des xfs-Dämons eingerichtet ist (weitere Einzelheiten hierzu finden Sie unter xfnts_validate-Methode):


rc = svc_validate(scds_handle);
   if (rc != 0) {
      scds_syslog(LOG_ERR,
          "Konfigurationsvalidierung fehlgeschlagen.");
      return (rc);
   }

Starten des Dienstes

Die xfnts_start-Methode ruft die svc_start()-Methode auf, die in xfnts.c definiert ist, um den xfs-Dämon zu starten. Dieser Abschnitt beschreibt svc_start().

Folgender Befehl startet den xfs-Dämon:


xfs -config Konfig_verzeichnis/fontserver.cfg -port Port_Nummer

Die Confdir_list-Erweiterungseigenschaft identifiziert Konfig_verzeichnis, während die Port_list-Systemeigenschaft Port_Nummer identifiziert. Beim Konfigurieren des Datendienstes stellt der Cluster-Verwalter spezifische Werte für diese Eigenschaften bereit.

Die xfnts_start-Methode deklariert diese Eigenschaften als Zeichenketten-Arrays und ruft die Werte ab, die der Verwalter mit den Funktionen scds_get_ext_confdir_list() und scds_get_port_list() einstellt (beschrieben unter scds_property_functions(3HA)):


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]);

   /* Von XFS zu verwendenden Port aus der Port_list-Eigenschaft abrufen */
   err = scds_get_port_list(scds_handle, &portlist);
   if (err != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          "Auf die Port_list-Eigenschaft konnte nicht zugegriffen werden.");
      return (1);
   }

Beachten Sie, dass die confdirs-Variable auf das erste Element (0) im Array zeigt.

Die xfnts_start-Methode verwendet sprintf, um die Befehlszeile für xfs zu bilden:


/* Befehl zum Starten des XFS-Dämons erstellen. */
   (void) sprintf(cmd,
       "/usr/openwin/bin/xfs -config %s -port %d 2>/dev/null",
       xfnts_conf, portlist->ports[0].port);

Beachten Sie, dass die Ausgabe an dev/null umgeleitet wird, um die vom Dämon generierten Meldungen zu unterdrücken.

Die xfnts_start-Methode übergibt die xfs-Befehlszeile an scds_pmf_start(), um den Datendienst unter PMF-Steuerung zu starten:


scds_syslog(LOG_INFO, "Start-Anforderung 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,
          "Start-Befehl erfolgreich beendet.");
   } else {
      scds_syslog(LOG_ERR,
          "HA-XFS konnte nicht gestartet werden ");
   }

Beachten Sie folgende Punkte bezüglich des Aufrufs an scds_pmf_start().

Vor der Rückgabe gibt svc_pmf_start() den der portlist-Struktur zugewiesenen Speicherplatz frei:


scds_free_port_list(portlist);
return (err);

Rückgabe von svc_start()

Auch wenn svc_start() Erfolg zurückgibt, kann es sein, dass die zugrunde liegende Anwendung nicht gestartet wurde. Daher muss svc_start() die Anwendung testen, um sicherzustellen, dass sie läuft, bevor eine Erfolgsmeldung zurückgegeben wird. Beim Testen muss beachtet werden, dass die Anwendung eventuell nicht sofort zur Verfügung steht, weil sie einige Zeit zum Starten benötigt. Die svc_start()-Methode ruft die in xfnts.c definierte svc_wait()-Funktion auf, um zu überprüfen, ob die Anwendung läuft:


/* Warten, bis der Dienst vollständig gestartet wurde */
   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 wurde erfolgreich gestartet.");
   } else {
      scds_syslog(LOG_ERR, "Dienst konnte nicht gestartet werden.");
   }

Die svc_wait()-Funktion ruft scds_get_netaddr_list(3HA) auf, um die für das Testen der Anwendung erforderlichen Netzwerkadressressourcen abzurufen:


/* 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);
   }

Dann ruft svc_wait() die start_timeout- und stop_timeout-Werte ab:


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

Um die Zeit zu berücksichtigen, die der Server zum Starten benötigt, ruft svc_wait() die scds_svc_wait()-Methode auf und übergibt einen Zeitüberschreitungswert, der drei Prozent des start_timeout-Wertes entspricht. Dann ruft svc_wait() die svc_probe()-Methode auf, um zu überprüfen, ob die Anwendung gestartet wurde. Die svc_probe()-Methode stellt eine einfache Socketverbindung mit dem Server auf dem angegebenen Port her. Wenn die Verbindung mit dem Port fehlschlägt, gibt svc_probe() den Wert 100 für Totalfehlschlag zurück. Wenn die Verbindung hergestellt werden kann, aber die Verbindungstrennung vom Port fehlschlägt, gibt svc_probe() den Wert 50 zurück.

Bei Fehlschlag oder Teilfehlschlag von svc_probe() ruft svc_wait() die scds_svc_wait()-Methode mit einem Zeitüberschreitungswert von 5 auf. Die scds_svc_wait()-Methode beschränkt die Testhäufigkeit auf ein Testsignal alle fünf Sekunden. Diese Methode zählt auch die Anzahl der Startversuche für den Dienst. Wenn die Anzahl der Versuche den Wert der Retry_count-Ressourceneigenschaft innerhalb des von der Retry_interval-Ressourceneigenschaft angegebenen Zeitraums überschreitet, gibt die scds_svc_wait()-Funktion Fehlschlag zurück. In diesem Fall gibt die svc_start()-Funktion ebenfalls Fehlschlag zurück.


#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, "Dienst konnte nicht gestartet werden.");
      return (1);
   }

   do {
      /*
       * Datendienst an der IP-Adresse der Netzwerkressource
       * sowie 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 Rückgabe */
         scds_free_netaddr_list(netaddr);
         return (0);
      }

       /* scds_svc_wait() aufrufen, falls der Dienst zu oft
      if (scds_svc_wait(scds_handle, SVC_WAIT_TIME)
         != SCHA_ERR_NOERR) {
         scds_syslog(LOG_ERR, "Dienst konnte nicht gestartet werden.");
         return (1);
      }

   /* RGM die Zeitüberschreitung überlassen und Programm beenden */
   } while (1);


Hinweis –

Vor der Beendigung ruft die xfnts_start-Methode scds_close() auf, um die von scds_initialize () zugewiesenen Ressourcen zurückzufordern. Weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_close(3HA).


xfnts_stop-Methode

Da die xfnts_start-Methode scds_pmf_start() verwendet, um den Dienst unter PMF zu starten, verwendet die xfnts_stop-Methode scds_pmf_stop() zum Stoppen des Dienstes.


Hinweis –

Der erste Aufruf in xfnts_stop erfolgt an scds_initialize(), um einige erforderliche Systemverwaltungs-Funktionen auszuführen (weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_initialize(3HA)).


Die xfnts_stop-Methode ruft die in xfnts.c definierte svc_stop()-Methode folgendermaßen auf.


scds_syslog(LOG_ERR, "Stop-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 konnte nicht gestoppt werden.");
      return (1);
   }

   scds_syslog(LOG_INFO,
       "HA-XFS erfolgreich gestoppt.");
   return (SCHA_ERR_NOERR); /* Erfolgreich gestoppt */

Bezüglich des Aufrufs in svc_stop() an die scds_pmf_stop()-Funktion ist Folgendes zu beachten.


Hinweis –

Vor der Beendigung ruft die xfnts_stop-Methode scds_close() auf, um die von scds_initialize() zugewiesenen Ressourcen zurückzufordern. Weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_close(3HA).


xfnts_monitor_start-Methode

RGM ruft die Monitor_start-Methode auf einem Knoten auf, um den Fehler-Monitor zu starten, nachdem eine Ressource auf diesem Knoten gestartet wurde. Die xfnts_monitor_start-Methode verwendet scds_pmf_start(), um den Monitor-Dämon unter PMF zu starten.


Hinweis –

Der erste Aufruf in xfnts_monitor_start erfolgt an scds_initialize(). Diese Funktion führt einige wichtige Systemverwaltungs-Funktionen aus (weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_initialize(3HA)).


Die xfnts_monitor_start-Methode ruft die in xfnts.c definierte mon_start-Methode folgendermaßen auf:


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

    /* scds_pmf_start aufrufen und den Testsignalnamen übergeben. */
   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,
          "Fehler-Monitor konnte nicht gestartet werden.");
      return (1);
   }

   scds_syslog(LOG_INFO,
       "Fehler-Monitor gestartet.");

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

Bezüglich des Aufrufs in svc_mon_start() an die scds_pmf_start()-Funktion ist Folgendes zu beachten.


Hinweis –

Vor der Beendigung ruft die xfnts_monitor_start-Methode scds_close() auf, um die von scds_initialize() zugewiesenen Ressourcen zurückzufordern. Weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_close(3HA).


xfnts_monitor_stop-Methode

Da die xfnts_monitor_start-Methode scds_pmf_start() zum Starten des Monitor-Dämons unter PMF verwendet, setzt xfnts_monitor_stop die scds_pmf_stop()-Methode zum Stoppen des Monitor-Dämons ein.


Hinweis –

Der erste Aufruf in xfnts_monitor_stop erfolgt an scds_initialize(). Diese Funktion führt einige wichtige Systemverwaltungs-Funktionen aus (weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_initialize(3HA)).


Die xfnts_monitor_stop()-Methode ruft die in xfnts.c definierte mon_stop-Methode folgendermaßen auf:


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,
          "Fehler-Monitor konnte nicht gestoppt werden.");
      return (1);
   }

   scds_syslog(LOG_INFO,
       "Fehler-Monitor gestoppt.");

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

Bezüglich des Aufrufs in svc_mon_stop() an die scds_pmf_stop()-Funktion ist Folgendes zu beachten.


Hinweis –

Vor der Beendigung ruft die xfnts_monitor_stop-Methode scds_close() auf, um die von scds_initialize() zugewiesenen Ressourcen zurückzufordern. Weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_close(3HA).


xfnts_monitor_check-Methode

RGM ruft die Monitor_check-Methode immer dann auf, wenn der Fehler-Monitor versucht, für die Ressourcengruppe der Ressorce ein Failover auf einen anderen Knoten auszuführen. Die xfnts_monitor_check-Methode ruft die svc_validate()-Methode auf, um zu überprüfen, ob eine geeignete Konfiguration zum Unterstützen des xfs-Dämons vorhanden ist (Einzelheiten finden Sie unter xfnts_validate-Methode). Der Code für xfnts_monitor_check sieht folgendermaßen aus:


   /* Von RGM übergebene Argumente verarbeiten und syslog initialisieren */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, "Handle konnte nicht initialisiert werden.");
      return (1);
   }

   rc =  svc_validate(scds_handle);
   scds_syslog_debug(DBG_LEVEL_HIGH,
       "monitor_check-Methode "
       "wurde aufgerufen und gab <%d> zurück.", rc);

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

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

SUNW.xfnts-Fehler-Monitor

RGM ruft die PROBE-Methode nicht direkt auf. Es wird vielmehr die Monitor_start-Methode aufgerufen, um den Monitor zu starten, nachdem eine Ressource auf einem Knoten gestartet wurde. Die xfnts_monitor_start-Methode startet den Fehler-Monitor unter PMF-Steuerung. Die xfnts_monitor_stop-Methode stoppt den Fehler-Monitor.

Der SUNW.xfnts-Fehler-Monitor führt folgende Aufgaben aus:

xfonts_probe-Hauptschleife

Die xfonts_probe-Methode implementiert eine Schleife. Vor dem Implementieren der Schleife führt xfonts_probe folgende Aktionen aus:

Die xfnts_probe-Methode implementiert die Schleife folgendermaßen:


for (ip = 0; ip < netaddr->num_netaddrs; ip++) {
         /*
          * Hostname und Port für Überwachung der
          * Fehlerfreiheit erfassen.
          */
         hostname = netaddr->netaddrs[ip].hostname;
         port = netaddr->netaddrs[ip].port_proto.port;
         /*
          * HA-XFS unterstützt nur einen Port. Daher den Port-Wert
          * aus dem ersten Eintrag im Port-Array abrufen.
          */
         ht1 = gethrtime(); /* Testsignal-Startzeit festhalten */
         scds_syslog(LOG_INFO, "Dienst auf Port: %d. testen", port);

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

         /*
          * Testsignalhistorie des Dienstes aktualisieren,
          * bei Bedarf Aktionen ausführen.
          * Testsignal-Endzeit festhalten.
          */
         ht2 = gethrtime();

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

         /*
          * Fehlschlaghistorie berechnen und
          * bei Bedarf Aktionen ausführen
          */
         (void) scds_fm_action(scds_handle,
             probe_result, (long)dt);
      }   /* Jede Netzressource */
   }    /* Endlos weitertesten */

Die svc_probe()-Funktion implementiert die Testsignallogik. Der Rückgabewert von svc_probe() wird an scds_fm_action() übergeben. Diese Funktion entscheidet, ob die Anwendung neu gestartet, ein Failover der Ressourcengruppe ausgeführt werden oder nichts geschehen soll.

svc_probe()-Funktion

Die svc_probe()-Funktion stellt eine einfache Socketverbindung mit dem angegebenen Port her, indem sie scds_fm_tcp_connect() aufruft. Wenn die Verbindung fehlschlägt, gibt svc_probe() den Wert 100 für Totalfehlschlag zurück. Wenn die Verbindung hergestellt werden kann, aber die Verbindungstrennung fehlschlägt, gibt svc_probe() den Wert 50 für Teilfehlschlag zurück. Wenn sowohl die Verbindung als auch die Verbindungstrennung erfolgreich verlaufen, gibt svc_probe() den Wert 0 für Erfolg zurück.

Der Code für svc_probe() sieht folgendermaßen aus:


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;


   /*
    * Den Datendienst anhand einer Socketverbindung über den Port, */
    * der in der port_list-Eigenschaft angeben ist, zum Host für den XFS-Datendienst
    * testen. Wenn der XFS-Dienst, der zum Abhören des angegebenen
    * Ports konfiguriert ist, auf die Verbindung antwortet, ist der Test erfolgreich
    * verlaufen. Andernfalls wird für den in der probe_timeout-Eigenschaft
    * festgesetzten Zeitraum gewartet, bevor geschlossen wird, dass der Test
    * fehlgeschlagen ist.
    */

   /*
    * Den Zeitüberschreitungs-Prozentsatz 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 den angegebenen Hostnamen und
    * Port her. Die Zeitdauer für die Verbindung beträgt 95% des probe_timeout-
    * Wertes.
    */
   rc = scds_fm_tcp_connect(scds_handle, &sock, hostname, port,
       connect_timeout);
   if (rc) {
      scds_syslog(LOG_ERR,
          "Verbindung mit Port <%d> für Ressource <%s> konnte nicht hergestellt werden.",
          port, scds_get_resource_name(scds_handle));
      /* Dies ist ein Totalfehlschlag */
      return (SCDS_PROBE_COMPLETE_FAILURE);
   }

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

   /*
    * Tatsächliche Zeit für die Verbindungsherstellung berechnen. Der Wert sollte
    * kleiner oder gleich connect_timeout sein, der dem Verbindungsversuch
    * zugewiesenen Zeit. Wenn der Verbindungsversuch 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 der
    * Verbindungstrennungs-Zeitüberschreitung hinzugerechnet.
    *
    */

   time_used = (int)(t2 - t1);

   /*
    * Restliche Zeit (timeout - time_took_to_connect) für die
    * Verbindungstrennung verwenden
    */

   time_remaining = timeout - (int)time_used;

   /*
    * Wenn die gesamte Zeit verbraucht wurde, einen kleinen festen
    * Zeitüberschreitungswert für einen weiteren Trennversuch verwenden.
    * So wird fd-Leak vermieden.
    */
   if (time_remaining <= 0) {
      scds_syslog_debug(DBG_LEVEL_LOW,
          "svc_probe hat die gesamte Zeitüberschreitung von "
          "%d Sekunden während des Verbindungsvorgangs verbraucht und die"
          "Zeitüberschreitung um %d Sekunden überschritten. Trennversuch mit"
          " Zeitüberschreitung %d ",
          connect_timeout,
          abs(time_used),
          SVC_DISCONNECT_TIMEOUT_SECONDS);

      time_remaining = SVC_DISCONNECT_TIMEOUT_SECONDS;
   }

   /*
    * Bei Fehlschlag der Verbindungstrennung Teilfehlschlag zurückgeben.
    * Grund: Der Verbindungsaufruf ist erfolgreich, was bedeutet, dass die
    * Anwendung läuft. Ein Verbindungstrennungsfehlschlag kann durch
    * eine hängende Anwendung oder hohe Belastung verursacht werden.
    * In letzterem Fall die Anwendung nicht durch Rückgabe von Totalfehlschlag
    * als ausgefallen deklarieren. Stattdessen Teilfehlschlag deklarieren.
    * Wenn diese Situation anhält, schlägt der Verbindungstrennungsaufruf
    * 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,
          "Verbindung mit Port %d von Ressource %s konnte nicht getrennt werden.",
          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 ist, nicht den vollständigen Test
    * mit fsinfo ausführen. Stattdessen SCDS_PROBE_COMPLETE_FAILURE/2
    * zurückgeben. So wird sichergestellt, dass der Server bei
    * Weiterbestehen dieser Zeitüberschreitung neu gestartet wird.
    */
   if (time_remaining <= 0) {
      scds_syslog(LOG_ERR, "Testsignal-Zeitüberschreitung.");
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

   /*
    * Die Verbindung und Verbindungstrennung zum Port sind erfolgreich.
    * Den fsinfo-Befehl für einen vollständigen Gesundheits-Check
    * des Servers ausfü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,
       "Prüfung des Serverstatus mit %s.", testcmd);
   if (scds_timerun(scds_handle, testcmd, time_remaining,
      SIGKILL, &rc) != SCHA_ERR_NOERR || rc != 0) {

      scds_syslog(LOG_ERR,
         "Serverstatus konnte mit Befehl <%s> nicht geprüft werden",
         testcmd);
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }
   return (0);
}

Nach Beendigung gibt svc_probe() einen Wert für Erfolg (0), Teilfehlschlag (50), oder Totalfehlschlag (100) zurück. Die xfnts_probe-Methode übergibt diesen Wert an scds_fm_action().

Festlegen der Fehler-Monitor-Aktion

Die xfnts_probe-Methode ruft scds_fm_action() auf, um die auszuführende Aktion festzulegen. Die Logik in scds_fm_action() sieht folgendermaßen aus:

Angenommen, das Testsignal stellt eine Verbindung mit dem XFS-Server her, kann die Verbindung jedoch nicht trennen. Das bedeutet, dass der Server läuft, aber vielleicht hängt oder nur momentan überlastet ist. Bei Fehlschlag der Verbindungstrennung wird ein Teilfehlschlag (50) an scds_fm_action() gesendet. Dieser Wert liegt unter dem Schwellenwert für das Neustarten des Datendienstes. Der Wert wird jedoch in der Fehlerhistorie festgehalten.

Wenn während des nächsten Tests die Verbindungstrennung vom Server erneut fehlschlägt, wird ein Wert von 50 der von scds_fm_action() verwalteten Fehlschlaghistorie hinzugefügt. Der kumulative Fehlschlagwert beträgt nun 100, so dass scds_fm_action() den Datendienst neu startet.

xfnts_validate-Methode

RGM ruft die Validate-Methode auf, wenn eine Ressource erstellt wird und wenn eine Verwaltungsaktion die Eigenschaften der Ressource bzw. deren Gruppe aktualisiert. RGM ruft Validate auf, bevor die Erstellung bzw. Aktualisierung angewendet wird. Ein Fehlerbeendigungscode der Methode auf einem Knoten führt zum Abbruch der Erstellung bzw. Aktualisierung.

RGM ruft Validate nur dann auf, wenn Ressourcen- bzw. Gruppeneigenschaften über eine Verwaltungsaktion geändert werden, und nicht, wenn RGM Eigenschaften einstellt oder wenn ein Monitor die Ressourceneigenschaften Status und Status_msg einstellt.


Hinweis –

Die Monitor_check-Methode ruft auch ausdrücklich jedes Mal dann die Validate-Methode auf, wenn die PROBE-Methode versucht, ein Failover für den Datendienst auf einen neuen Knoten auszuführen.


RGM ruft Validate mit zusätzlichen Argumenten zu denjenigen auf, die von anderen Methoden übergeben wurden, einschließlich der aktualisierten Eigenschaften und Werte. Bei Aufruf von scds_initialize() zu Beginn von xfnts_validate werden alle Argumente analysiert, die RGM an xfnts_validate übergibt, und die Informationen werden im scds_handle-Parameter gespeichert. Die Unterroutinen, die xfnts_validate aufruft, verwenden diese Informationen.

Die xfnts_validate-Methode ruft svc_validate() auf, um Folgendes zu prüfen:

Vor der Rückgabe gibt svc_validate() alle zugewiesenen Ressourcen frei.


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

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


Hinweis –

Vor der Beendigung ruft die xfnts_validate-Methode scds_close() auf, um die von scds_initialize() zugewiesenen Ressourcen zurückzufordern. Weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_close(3HA).


xfnts_update-Methode

RGM ruft die Update-Methode auf, um eine laufende Ressource darüber zu benachrichtigen, dass ihre Eigenschaften geändert wurden. Die einzigen Eigenschaften des xfnts-Datendienstes, die geändert werden können, betreffen den Fehler-Monitor. Wenn daher eine Eigenschaft aktualisiert wird, ruft die xfnts_update-Methode scds_pmf_restart_fm() auf, um den Fehler-Monitor neu zu starten.


* Prüfen, ob der Fehler-Monitor bereits läuft und ihn ggf.
   * 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,
          "Fehler-Monitor konnte nicht neu gestartet werden.");
      /* Gesamten von scds_initialize zugewiesenen Speicher freigeben*/
      scds_close(&scds_handle);
      return (1);
   }

   scds_syslog(LOG_INFO,
   "Erfolgreich beendet.");


Hinweis –

Der zweite Parameter von scds_pmf_restart_fm() identifiziert eindeutig die Instanz des Fehler-Monitors, die neu gestartet werden muss, wenn mehrere Instanzen vorhanden sind. Der Wert 0 im Beispiel gibt an, dass nur eine Instanz des Fehler-Monitors vorhanden ist.