Sun Cluster Entwicklerhandbuch Datendienste für Solaris OS

Kapitel 8 Beispielressourcentyp-Implementierung mit DSDL

In diesem Kapitel wird ein Beispielressourcentyp beschrieben, SUNW.xfnts, der mit der Data Service Development Library (DSDL) implementiert wird. Dieser Datendienst wird in C geschrieben. Die zugrunde liegende Anwendung ist X Font Server, ein TCP/IP-basierter Dienst. Anhang C, DSDL-Beispielressourcentyp-Codeliste enthält den gesamten Code der Methoden im SUNW.xfnts-Ressourcentyp.

Dieses Kapitel behandelt die folgenden Themen:

X Font Server

Der X Font Server ist ein TCP/IP-basierter Dienst, der seine Clients mit Schriftartendateien bedient. 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, die sich im Verzeichnis /usr/openwin/bin/xfs befindet. Der Dämon wird in der Regel aus der Datei inetd gestartet. Nehmen wir jedoch für das aktuelle Beispiel an, dass der richtige Eintrag in der Datei /etc/inetd.conf deaktiviert wurde (z.B. mit dem Befehl fsadmin -d), sodass der Dämon allein von der Sun Cluster-Software gesteuert wird.

X Font Server-Konfigurationsdatei

Standardmäßig liest der X Font Server seine Konfigurationsinformationen aus der Datei /usr/openwin/lib/X11/fontserver.cfg. Der Katalogeintrag in dieser Datei besteht aus einer Liste mit Schriftartenverzeichnissen, die dem Dämon zur Verfügung stehen. Der Cluster-Administrator kann die Schriftartenverzeichnisse im Cluster-Dateisystem finden. Dieser Speicherort optimiert die Verwendung von X Font Server unter Sun Cluster, indem eine einzelne Kopie der Schriftartendatenbank im System beibehalten wird. Wenn der Cluster-Administrator das Verzeichnis wechseln möchte, muss er die Datei fontserver.cfg so bearbeiten, dass sie die neuen Pfade der Schriftartenverzeichnisse enthält.

Für eine einfache Konfiguration kann der Cluster-Administrator auch die Konfigurationsdatei im Cluster-Dateisystem ablegen. Der xfs-Dämon liefert Befehlszeilenargumente, die das integrierte Standardverzeichnis dieser Datei überschreiben. Der SUNW.xfnts-Ressourcentyp verwendet zum Starten des Dämons mithilfe der Sun Cluster-Software den folgenden Befehl.

/usr/openwin/bin/xfs -config Verzeichnis-der-Konfigurationsdatei/fontserver.cfg \
-port Portnummer

In der SUNW.xfnts-Ressourcentypimplementierung können Sie die Confdir_list-Eigenschaft zur Verwaltung des Speicherorts der fontserver.cfg-Konfigurationsdatei verwenden.

TCP-Port-Nummer

Der TCP-Port, an dem der xfsServerdämon abhört, ist in der Regel der “fs”-Port, der normalerweise als 7100 in der Datei /etc/services definiert ist. Die -port-Option, die der Cluster-Administrator mit dem Befehl xfs angibt, ermöglicht dem Cluster-Administrator das Überschreiben der Standardeinstellung.

Sie können die Port_list-Eigenschaft im SUNW.xfnts -Ressourcentyp verwenden, um den Standardwert festzulegen und dem Cluster-Administrator die Verwendung der Option -port zusammen mit dem Befehl xfs zu ermöglichen. Der Standardwert dieser Eigenschaft wird in der RTR-Datei als 7100/tcp definiert. Bei der Start-Methode von SUNW.xfnts übergeben Sie Port_list in der xfs-Befehlszeile an die Option -port. Folglich muss ein Benutzer dieses Ressourcentyps keine Portnummer angeben (der Port lautet standardmäßig 7100/tcp). Der Cluster-Administrator kann bei der Konfiguration des Ressourcentyps einen anderen Wert für die Port_list-Eigenschaft angeben.

SUNW.xfnts-RTR-Datei

In diesem Abschnitt werden mehrere Schlüsseleigenschaften der SUNW.xfnts-RTR-Datei beschrieben. Der Zweck der einzelnen Eigenschaften in der Datei wird nicht beschrieben. Eine derartige Beschreibung finden Sie unter Einstellen der Ressourcen- und Ressourcentypeigenschaften.

Die Confdir_list-Erweiterungseigenschaft identifiziert das Konfigurationsverzeichnis (bzw. eine Verzeichnisliste) wie folgt:

{
        PROPERTY = Confdir_list;
        EXTENSION;
        STRINGARRAY;
        TUNABLE = AT_CREATION;
        DESCRIPTION = "The Configuration Directory Path(s)";
}

Die Confdir_list-Eigenschaft gibt keinen Standardwert an. Der Cluster-Administrator muss beim Erstellen der Ressource einen Verzeichnisnamen angeben. Dieser Wert kann später nicht mehr geändert werden, weil die Optimierbarkeit auf AT_CREATION beschränkt ist.

Die Eigenschaft Port_list identifiziert den Port, der vom Server-Dämon abgehört wird, wie folgt:

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

Weil die Eigenschaft einen Standardwert deklariert, kann der Cluster-Administrator einen neuen Wert angeben oder beim Erstellen der Ressource den Standardwert übernehmen. Keine Person kann diesen Wert zu einem späteren Zeitpunkt ändern, weil die Optimierbarkeit auf AT_CREATION beschränkt ist.

Benennungskonventionen für Funktionen und Rückrufmethoden

Sie können die verschiedenen Bestandteile des Beispielcodes anhand dieser Konventionen identifizieren:

scds_initialize()-Funktion

Die DSDL setzt voraus, dass jede Rückrufmethode die scds_initialize ()-Funktion zu Beginn der Methode aufruft. Diese Funktion führt folgende Vorgänge aus:

Verwenden Sie die scds_close()-Funktion, um die Ressourcen wiederzuverwenden, die von scds_initialize() zugewiesen werden.

xfnts_start-Methode

RGM führt die Start-Methode an einem Cluster-Knoten aus, wenn die Ressourcengruppe, die die Datendienstressource enthält, an diesem Knoten in den Online-Modus versetzt oder die Ressource aktiviert wird. Im SUNW.xfnts-Beispielressourcentyp aktiviert die xfnts_start-Methode den xfs-Dämon an diesem Knoten.

Die xfnts_start-Methode ruft scds_pmf_start() auf, um den Dämon unter PMF zu starten. PMF bietet die automatische Fehlerbenachrichtigung und Neustartfunktionen sowie die Integration mit dem Fehler-Monitor.


Hinweis –

Der erste Aufruf in xfnts_start findet an scds_initialize () statt, das einige erforderliche housekeeping-Funktionen ausführt. Der Abschnitt scds_initialize()-Funktion und die Online-Dokumentation zu scds_initialize(3HA) enthalten weitere Informationen.


Dienstvalidierung vor dem Starten von X Font Server

Bevor die xfnts_start-Methode versucht, X Font Server zu starten, ruft sie svc_validate() auf, um zu prüfen, ob eine ordnungsgemäße Konfiguration zur Unterstützung des xfs-Dämons vorhanden ist.

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

Weitere Informationen finden Sie unter xfnts_validate-Methode.

Starten des Dienstes mit svc_start()

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

Der Befehl zum Starten des xfs-Dämons lautet wie folgt:


# xfs -config Konfigurationsverzeichnis/fontserver.cfg -port Portnummer

Die Confdir_list-Erweiterungseigenschaft identifiziert das Konfigurationsverzeichnis während die Port_list-Eigenschaft die Portnummer identifiziert. Der Cluster-Administrator gibt für diese Eigenschaften bei der Konfiguration des Datendienstes bestimmte Werte an.

Die xfnts_start-Methode deklariert diese Eigenschaften als Zeichenketten-Arrays. Die xfnts_start-Methode erhält die Werte, die der Cluster-Administrator unter Verwendung der Funktionen scds_get_ext_confdir_list() und scds_get_port_list() festlegt. Diese Funktionen werden in der Online-Dokumentation zu scds_property_functions(3HA) beschrieben.

scha_str_array_t *confdirs;
scds_port_list_t    *portlist;
scha_err_t   err;

   /* get the configuration directory from the confdir_list property */
   confdirs = scds_get_ext_confdir_list(scds_handle);

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

   /* obtain the port to be used by XFS from the Port_list property */
   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);
   }

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.

/* Construct the command to start the xfs daemon. */
   (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 weitergeleitet wird, um vom Dämon generierte Meldungen zu unterdrücken.

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

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

Beachten Sie die folgenden Punkte zum Aufruf von scds_pmf_start():

Vor der Rückgabe setzt svc_pmf_start() den Speicher frei, der für die portlist-Struktur zugewiesen wird.

scds_free_port_list(portlist);
return (err);

Rückgabe von svc_start()

Selbst wenn svc_start() eine erfolgreiche Rückgabe durchführt, konnte die zugrunde liegende Anwendung eventuell nicht gestartet werden. Daher muss svc_start() die Anwendung testen, um sicherzustellen, dass sie läuft, bevor eine Erfolgsmeldung zurückgegeben wird. Das Testsignalverfahren muss auch berücksichtigen, dass die Anwendung eventuell nicht sofort zur Verfügung steht, da sie einige Zeit zum Starten benötigt. Die svc_start()-Methode ruft svc_wait() auf, definiert in der Datei xfnts.c, um zu prüfen, ob die Anwendung ausgeführt wird.

/* Wait for the service to start up fully */
   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.");
   }

Die svc_wait()-Funktion ruft scds_get_netaddr_list () auf, um die Netzwerkadressressourcen zu erhalten, die zum Testen der Anwendung benötigt werden.

/* obtain the network resource to use for probing */
   if (scds_get_netaddr_list(scds_handle, &netaddr)) {
      scds_syslog(LOG_ERR,
          "No network address resources found in resource group.");
      return (1);
   }

   /* Return an error if there are no network resources */
   if (netaddr == NULL || netaddr->num_netaddrs == 0) {
      scds_syslog(LOG_ERR,
          "No network address resource in resource group.");
      return (1);
   }

Die svc_wait()-Funktion erhält die Werte Start_timeout und Stop_timeout.

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 eventuell zum Starten benötigt, ruft svc_wait() scds_svc_wait() auf und übergibt einen Zeitüberschreitungswert, der drei Prozent des Start_timeout-Werts entspricht. Die svc_wait()-Funktion ruft die svc_probe()-Funktion auf, um zu prüfen, ob die Anwendung gestartet wurde. Die svc_probe()-Methode stellt eine einfache Socketverbindung mit dem Server auf dem angegebenen Port her. Wenn keine Verbindung mit dem Port hergestellt werden konnte, gibt svc_probe() einen Wert von 100 zurück, was auf einen kompletten Fehlschlag hinweist. Wenn die Vebindung hergestellt wurde, die Trennung der Verbindung mit dem Port jedoch fehlgeschlagen ist, gibt svc_probe() einen Wert von 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-Eigenschaft der Ressource innerhalb des Zeitraums, der von der Retry_interval -Eigenschaft der Ressource angegeben wird, überschreitet, gibt die scds_svc_wait()-Funktion einen Fehler aus. 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, "Service failed to start.");
      return (1);
   }

   do {
      /*
       * probe the data service on the IP address of the
       * network resource and the portname
       */
      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);
      }

       /* Call scds_svc_wait() so that if service fails too
      if (scds_svc_wait(scds_handle, SVC_WAIT_TIME)
         != SCHA_ERR_NOERR) {
         scds_syslog(LOG_ERR, "Service failed to start.");
         return (1);
      }

   /* Rely on RGM to timeout and terminate the program */
   } while (1);

Hinweis –

Vor der Beendigung ruft die xfnts_start-Methode scds_close() auf, um Ressourcen wiederzuverwenden, die von scds_initialize () zugewiesen wurden. Weitere Informationen finden Sie im Abschnitt scds_initialize()-Funktion sowie in der Online-Dokumentation zu scds_close(3HA).


xfnts_stop-Methode

Da die xfnts_start-Methode scds_pmf_start() zum Starten des Dienstes unter PMF verwendet, verwendet xfnts_stop zum Stoppen des Dienstes scds_pmf_stop().


Hinweis –

Der erste Aufruf in xfnts_stop findet an scds_initialize () statt, das einige erforderliche housekeeping-Funktionen ausführt. Der Abschnitt scds_initialize()-Funktion und die Online-Dokumentation zu scds_initialize(3HA) enthalten weitere Informationen.


Die xfnts_stop-Methode ruft die svc_stop()-Methode, die in der Datei xfnts.c definiert ist, wie folgt auf:

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 */

Beachten Sie folgende Punkte beim Aufruf in svc_stop() an die scds_pmf_stop()-Funktion:


Hinweis –

Vor der Beendigung ruft die xfnts_stop-Methode scds_close() auf, um Ressourcen wiederzuverwenden, die von scds_initialize () zugewiesen wurden. Weitere Informationen finden Sie im Abschnitt scds_initialize()-Funktion sowie in der Online-Dokumentation zu scds_close(3HA).


xfnts_monitor_start-Methode

RGM ruft die Monitor_start-Methode an einem Knoten auf, um den Fehler-Monitor zu starten, nachdem an dem Knoten eine Ressource 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 findet an scds_initialize() statt, das einige erforderliche housekeeping-Funktionen ausführt. Der Abschnitt scds_initialize()-Funktion und die Online-Dokumentation zu scds_initialize(3HA) enthalten weitere Informationen.


Die xfnts_monitor_start-Methode ruft die mon_start -Methode auf, die in der Datei xfnts.c wie folgt definiert ist:

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

    /* Call scds_pmf_start and pass the name of the probe. */
   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 */
}

Beachten Sie die folgenden Punkte zum Aufruf in svc_mon_start() der scds_pmf_start()-Funktion:


Hinweis –

Vor der Beendigung ruft die xfnts_monitor_start-Methode scds_close() auf, um Ressourcen wiederzuverwenden, die von scds_initialize () zugewiesen werden. Im Abschnitt scds_initialize()-Funktion und in der Online-Dokumentation zu scds_close(3HA) finden Sie weitere Informationen.


xfnts_monitor_stop-Methode

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


Hinweis –

Der erste Aufruf in xfnts_monitor_stop findet an scds_initialize() statt, das einige erforderliche housekeeping-Funktionen ausführt. Der Abschnitt scds_initialize()-Funktion und die Online-Dokumentation zu scds_initialize(3HA) enthalten weitere Informationen.


Die xfnts_monitor_stop()-Methode ruft die mon_stop -Methode auf, die in der Datei xfnts.c wie folgt definiert ist:

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

Beachten Sie folgende Punkte zum Aufruf in svc_mon_stop() der scds_pmf_stop()-Funktion:


Hinweis –

Vor der Beendigung ruft die xfnts_monitor_stop-Methode scds_close() auf, um Ressourcen wiederzuverwenden, die von scds_initialize () zugewiesen wurden. Im Abschnitt scds_initialize()-Funktion und in der Online-Dokumentation zu scds_close(3HA) finden Sie weitere Informationen.


xfnts_monitor_check-Methode

RGM ruft die Monitor_check-Methode auf, wenn der Fehler-Monitor einen Failover-Versuch der Ressourcengruppe, die die Ressource enthält, an einem anderen Knoten durchführt. Die xfnts_monitor_check-Methode ruft die svc_validate()-Methode auf, um zu prüfen, ob eine ordnungsgemäße Konfiguration zur Unterstützung des xfs-Dämons vorhanden ist. Weitere Informationen finden Sie unter xfnts_validate-Methode. Der Code für xfnts_monitor_check lautet wie folgt:

/* Process the arguments passed by RGM and initialize 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);

   /* Free up all the memory allocated by scds_initialize */
   scds_close(&scds_handle);

   /* Return the result of validate method run as part of monitor check */
   return (rc);
}

SUNW.xfnts-Fehler-Monitor

RGM ruft die PROBE-Methode nicht direkt auf, sondern ruft stattdessen die Monitor_start-Methode zum Starten des Monitors auf, nachdem eine Ressource an einem Knoten gestartet wurde. Die xfnts_monitor_start-Methode startet den Fehler-Monitor unter der Steuerung von PMF. 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 der Implementierung der Schleife führt xfonts_probe die folgenden Operationen aus:

Die xfnts_probe-Method implementiert die folgende Schleife:

for (ip = 0; ip < netaddr->num_netaddrs; ip++) {
         /*
          * Grab the hostname and port on which the
          * health has to be monitored.
          */
         hostname = netaddr->netaddrs[ip].hostname;
         port = netaddr->netaddrs[ip].port_proto.port;
         /*
          * HA-XFS supports only one port and
          * hence obtain the port value from the
          * first entry in the array of 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);

         /*
          * Update service probe history,
          * take action if necessary.
          * Latch probe end time.
          */
         ht2 = gethrtime();

         /* Convert to milliseconds */
         dt = (ulong_t)((ht2 - ht1) / 1e6);

         /*
          * Compute failure history and take
          * action if needed
          */
         (void) scds_fm_action(scds_handle,
             probe_result, (long)dt);
      }   /* Each net resource */
   }    /* Keep probing forever */

Die svc_probe()-Funktion implementiert die Testsignallogik. Der Rückgabewert von svc_probe() wird an scds_fm_action () übergeben, wodurch festgelegt wird, ob ein Neustart oder Failover der Ressourcengruppe durchgeführt wird oder ob nichts geschieht.

svc_probe()-Funktion

Die svc_probe ()-Funktion stellt eine einfache Socket-Verbindung mit dem angegebenen Port her, indem scds_fm_tcp_connect() aufgerufen wird. Wenn die Verbindung fehlschlägt, gibt svc_probe() einen Wert von 100 zurück, was auf einen kompletten Fehlschlag hinweist. Ist die Verbindung erfolgreich, die Trennung der Verbindung jedoch fehlerhaft, gibt svc_probe() einen Wert von 50 zurück, was auf einen Teilfehler hinweist. Wenn sowohl das Herstellen als auch das Trennen der Verbindung erfolgreich sind, gibt svc_probe() einen Wert von 0 aus, was auf Erfolg hinweist.

Der Code für svc_probe() lautet wie folgt:

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;


   /*
    * probe the data service by doing a socket connection to the port
    * specified in the port_list property to the host that is
    * serving the XFS data service. If the XFS service which is configured
    * to listen on the specified port, replies to the connection, then
    * the probe is successful. Else we will wait for a time period set
    * in probe_timeout property before concluding that the probe failed.
    */

   /*
    * Use the SVC_CONNECT_TIMEOUT_PCT percentage of timeout
    * to connect to the port
    */
   connect_timeout = (SVC_CONNECT_TIMEOUT_PCT * timeout)/100;
   t1 = (hrtime_t)(gethrtime()/1E9);

   /*
    * the probe makes a connection to the specified hostname and port.
    * The connection is timed for 95% of the actual probe_timeout.
    */
   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));
      /* this is a complete failure */
      return (SCDS_PROBE_COMPLETE_FAILURE);
   }

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

   /*
    * Compute the actual time it took to connect. This should be less than
    * or equal to connect_timeout, the time allocated to connect.
    * If the connect uses all the time that is allocated for it,
    * then the remaining value from the probe_timeout that is passed to
    * this function will be used as disconnect timeout. Otherwise, the
    * the remaining time from the connect call will also be added to
    * the disconnect timeout.
    *
    */

   time_used = (int)(t2 - t1);

   /*
    * Use the remaining time(timeout - time_took_to_connect) to disconnect
    */

   time_remaining = timeout - (int)time_used;

   /*
    * If all the time is used up, use a small hardcoded timeout
    * to still try to disconnect. This will avoid the fd leak.
    */
   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;
   }

   /*
    * Return partial failure in case of disconnection failure.
    * Reason: The connect call is successful, which means
    * the application is alive. A disconnection failure
    * could happen due to a hung application or heavy load.
    * If it is the later case, don't declare the application
    * as dead by returning complete failure. Instead, declare
    * it as partial failure. If this situation persists, the
    * disconnect call will fail again and the application will be
    * restarted.
    */
   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));
      /* this is a partial failure */
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

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

   /*
    * If there is no time left, don't do the full test with
    * fsinfo. Return SCDS_PROBE_COMPLETE_FAILURE/2
    * instead. This will make sure that if this timeout
    * persists, server will be restarted.
    */
   if (time_remaining <= 0) {
      scds_syslog(LOG_ERR, "Probe timed out.");
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

   /*
    * The connection and disconnection to port is successful,
    * Run the fsinfo command to perform a full check of
    * server health.
    * Redirect stdout, otherwise the output from fsinfo
    * ends up on the 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);
}

Bei Beendigung gibt svc_probe() einen Wert aus, der auf Erfolg (0), Teilfehler (50) oder Totalfehlschlag (100) hinweist. Die xfnts_probe-Methode übergibt diesen Wert an scds_fm_action().

Festlegen der Fehler-Monitor-Aktion

Die xfnts_probe -Methode ruft scds_fm_action() zum Festlegen der zu unternehmenden Aktion auf. Die Logik in scds_fm_action() lautet wie folgt:

Angenommen, der Test 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. Der Fehler beim Trennen der Verbindung sendet einen Teilfehler ( 50) an scds_fm_action(). Dieser Wert liegt unter dem Schwellenwert für das Neustarten des Datendienstes. Der Wert wird jedoch in der Fehlerhistorie festgehalten.

Wenn der Server während des nächsten Tests die Verbindung erneut nicht trennen kann, wird dem Fehlerprotokoll von scds_fm_action () ein Wert von 50 hinzugefügt. Der kumulative Fehlerwert beträgt jetzt 100, sodass scds_fm_action() den Datendienst neu startet.

xfnts_validate-Methode

RGM ruft beim Erstellen einer Ressource oder beim Aktualisieren der Eigenschaften der Ressource oder der enthaltenen Gruppe durch den Cluster-Administrator die Validate-Methode auf. 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 auf, wenn ein Cluster-Administrator die Ressourcen- ode Ressourcengruppeneigenschaften ändert oder wenn ein Monitor die Ressourceneigenschaften Status und Status_msg festlegt. RGM ruft Validate nicht auf, wenn RGM Eigenschaften festlegt.


Hinweis –

Die Monitor_check-Methode ruft auch die Validate-Methode explizit auf, wenn die PROBE-Methode einen Failover-Versuch des Datendienstes an einen neuen Knoten unternimmt.


RGM ruft Validate mit zusätzlichen Argumenten zu denjenigen auf, die an andere Methoden übergeben werden, einschließlich der Eigenschaften und Werte, die aktualisiert werden. Der Aufruf von scds_initialize() am Anfang von xfnts_validate parst alle Argumente, die von RGM an xfnts_validate übergeben werden und speichert die Informationen im scds_handle-Argument. Die Subroutinen, die von xfnts_validate aufgerufen werden, verwenden diese Informationen.

Die xfnts_validate-Methode ruft svc_validate() auf, wodurch folgende Bedingungen geprüft werden:

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

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

   return (rc); /* return result of validation */

Hinweis –

Vor der Beendigung ruft die xfnts_validate-Methode scds_close() auf, um Ressourcen wiederzuverwenden, die von scds_initialize () zugewiesen wurden. Im Abschnitt scds_initialize()-Funktion und in der Online-Dokumentation zu scds_close(3HA) finden Sie weitere Informationen.


xfnts_update-Methode

RGM ruft die Update-Methode auf, um einer laufenden Ressource mitzuteilen, dass sich ihre Eigenschaften geändert haben. Die einzigen Eigenschaften des xfnts-Datendienstes, die geändert werden können, betreffen den Fehler-Monitor. Wenn eine Eigenschaft aktualisiert wird, ruft die xfnts_update-Methode scds_pmf_restart_fm() zum Neustarten des Fehler-Monitors auf.

  /* check if the Fault monitor is already running and if so stop
   * and restart it. The second parameter to scds_pmf_restart_fm()
   * uniquely identifies the instance of the fault monitor that needs
   * to be restarted.
   */

   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.");
      /* Free up all the memory allocated by scds_initialize */
      scds_close(&scds_handle);
      return (1);
   }

   scds_syslog(LOG_INFO,
   "Completed successfully.");

Hinweis –

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