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