Sun Cluster Entwicklerhandbuch Datendienste für Solaris OS

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().