この付録では、SUNW.xfnts リソースタイプの各メソッドの完全なコード例を示します。また、コールバックメソッドが呼び出すサブルーチンのコードを含む、 xfntc.c のコード例を示します。この付録に含まれるコードリストは、次のとおりです。
「xfnts_monitor_stop メソッドのコードリスト」 のコードリスト
「xfnts_probe メソッドのコードリスト」 のコードリスト
「xfnts_start メソッドのコードリスト」 のコードリスト
「xfnts_stop メソッドのコードリスト」 のコードリスト
「xfnts_update メソッドのコードリスト」 のコードリスト
「xfnts_validate メソッドのコードリスト」 のコードリスト
このファイルは、SUNW.xfnts メソッドが呼び出すサブルーチンを実装します。
/*
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts.c - HA-XFS 用の一般的なユーティリティ
*
* このユーティリティは、データサービスと障害モニターの妥当性検査、
* 起動、および停止を実行するメソッドを持つ。また、データサービスの
* 状態を検証するメソッドも持つ。検証機能は、成功または失敗だけを戻す。
* xfnts_probe.c ファイル
* 内のメソッドで戻された値に基づいて、アクションが行われる。
*
*/
#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"
/*
* HA-XFS データサービスが完全に起動して動作するまでの
* 初期タイムアウト。サービスを検証する前に、start_timeout
* 時間の 3% (SVC_WAIT_PCT) だけ待つ。
*/
#define SVC_WAIT_PCT 3
/*
* probe_timeout の 95% の時間でポートと接続する必要がある。
* また、svc_probe 関数は、残りの時間を使用して、ポートとの接続を切断する。 */
#define SVC_CONNECT_TIMEOUT_PCT 95
/*
* SVC_WAIT_TIME は、svc_wait() で起動している間だけ使用される。
* svc_wait() では、サービスが起動していることを確認してから戻る必要がある。
* そのため、svc_probe() を呼び出し、サービスを監視する必要がある。
* SVC_WAIT_TIME はこのような検証を繰り返す時間間隔である。
*/
#define SVC_WAIT_TIME 5
/*
* この値は、probe_timeout に時間が残っていない場合に、
* 切断タイムアウトとして使用される。
*/
#define SVC_DISCONNECT_TIMEOUT_SECONDS 2
/*
* svc_validate():
*
* リソース構成に対して、HA-XFS 固有の妥当性検査を行う。
*
* svc_validate は、次の妥当性を検査する。
* 1. Confdir_list 拡張プロパティ
* 2. fontserver.cfg ファイル
* 3. xfs バイナリ
* 4. port_list プロパティ
* 5. ネットワークリソース
* 6. 他の拡張プロパティ
*
* 上記の妥当性検査のいずれかが失敗した場合、0 以上の値を戻す。
* それ以外の場合、成功を示す 0 を戻す。
*/
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;
/*
* XFS データサービス用の構成ディレクトリを confdir_list
* 拡張プロパティから取得する。
*/
confdirs = scds_get_ext_confdir_list(scds_handle);
/* confdir_list 拡張プロパティが存在しない場合、エラーを戻す。
*/
if (confdirs == NULL || confdirs->array_cnt != 1) {
scds_syslog(LOG_ERR,
"Property Confdir_list is not set properly.");
return (1); /* 妥当性検査は失敗。*/
}
/*
* 構成ファイルへのパスを confdir_list 拡張プロパティから構築する。
* HA-XFS が持つ構成は 1 つだけなので、confdir_list
* プロパティの最初のエントリを使用する必要がある。
*/
(void) sprintf(xfnts_conf, "%s/fontserver.cfg",
confdirs->str_array[0]);
/*
* HA-XFS の構成ファイルが適切な場所に存在することを確認する。
* HA-XFS 構成ファイルにアクセスして、アクセス権が
* 適切に設定されていることを確認する。
*/
if (stat(xfnts_conf, &statbuf) != 0) {
/*
* errno.h プロトタイプには void 引数がないので、
* lint エラーが抑制される。
*/
scds_syslog(LOG_ERR,
"Failed to access file <%s> : <%s>",
xfnts_conf, strerror(errno)); /*lint !e746 */
return (1);
}
/*
* XFS バイナリが存在し、アクセス権が正しいことを確認する。
* XFS バイナリは、広域ファイルシステムではなく、
* ローカルファイルシステム上にあるものと想定する。
*/
if (stat("/usr/openwin/bin/xfs", &statbuf)
!= 0) {
scds_syslog(LOG_ERR,
"Cannot access XFS binary : <%s> ",
strerror(errno));
return (1);
}
/* HA-XFS はポートを 1 つだけ持つ。*/
err = scds_get_port_list(scds_handle, &portlist);
if (err != SCHA_ERR_NOERR) {
scds_syslog(LOG_ERR,
"Could not access property Port_list: %s.",
scds_error_string(err));
return (1); /* 妥当性検査は失敗。*/
}
#ifdef TEST
if (portlist->num_ports != 1) {
scds_syslog(LOG_ERR,
"Property Port_list must have only one value.");
scds_free_port_list(portlist);
return (1); /* 妥当性検査は失敗。 */
}
#endif
/*
* 当該リソースが利用できるネットワークアドレスリソースを
* 取得しようとして失敗した場合、エラーを戻す。
*/
if ((err = scds_get_rs_hostnames(scds_handle, &snrlp))
!= SCHA_ERR_NOERR) {
scds_syslog(LOG_ERR,
"No network address resource in resource group: %s.",
scds_error_string(err));
return (1); /* 妥当性検査は失敗。*/
}
/* ネットワークアドレスリソースが存在しない場合、エラーを戻す。*/
if (snrlp == NULL || snrlp->num_netresources == 0) {
scds_syslog(LOG_ERR,
"No network address resource in resource group.");
rc = 1;
goto finished;
}
/* 他の重要な拡張プロパティが設定されていることを確認する。*/
if (scds_get_ext_monitor_retry_count(scds_handle) <= 0)
{
scds_syslog(LOG_ERR,
"Property Monitor_retry_count is not set.");
rc = 1; /* 妥当性検査は失敗。*/
goto finished;
}
if (scds_get_ext_monitor_retry_interval(scds_handle) <=
0) {
scds_syslog(LOG_ERR,
"Property Monitor_retry_interval is not set.");
rc = 1; /* 妥当性検査は失敗。*/
goto finished;
}
/* すべての妥当性検査は成功した。*/
scds_syslog(LOG_INFO, "Successful validation.");
rc = 0;
finished:
scds_free_net_list(snrlp);
scds_free_port_list(portlist);
return (rc); /* 妥当性検査の結果を戻す。*/
}
/*
* svc_start():
*
* X フォントサーバーを起動する。
* 成功したときは 0 を戻し、失敗したときは 0 以上の値を戻す。
*
* XFS サービスを起動するには、/usr/openwin/bin/xfs -config
* <fontserver.cfg file> -port <port to listen> コマンドを実行する。
* XFS は PMF の制御下で起動する。XFS は単一インスタンスのサービスとして起動する。
* データサービス用の PMF タグの形式は、
* <resourcegroupname, resourcename, instance_number.svc> である。
* XFS の場合、インスタンスは 1 つだけなので、
* タグ内の instance_number は 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;
/* 構成ディレクトリを confdir_list プロパティから取得する。
*/
confdirs = scds_get_ext_confdir_list(scds_handle);
(void) sprintf(xfnts_conf, "%s/fontserver.cfg",
confdirs->str_array[0]);
/* XFS が使用するポートを Port_list プロパティから取得する。
*/
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);
}
/*
* HA-XFS を起動するためのコマンドを構築する。
* 注: XFS を停止している間、XFS デーモンは
* 次のメッセージを出力する。
* 「/usr/openwin/bin/xfs notice: terminating」
* このデーモンメッセージを抑制するには、
* 出力を /dev/null にリダイレクトする。
*/
(void) sprintf(cmd,
"/usr/openwin/bin/xfs -config %s -port %d 2>/dev/null",
xfnts_conf, portlist->ports[0].port);
/*
* HA-XFS を PMF の制御下で起動する。HA-XFS は単一インスタンスの
* サービスとして起動される。scds_pmf_start 関数の最後の引数は、
* 監視する子プロセスのレベルを示す。このパラメータが
* -1 である場合、すべての子プロセスを親
* プロセスと同様に監視することを示す。
*/
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 ");
}
scds_free_port_list(portlist);
return (err); /* 成功または失敗の状態を戻す。 */
}
/*
* svc_stop():
*
* XFS サーバーを停止する。
* 成功したときは 0 を戻し、失敗したときは 0 以上の値を戻す。
*
* svc_stop は、scds_pmf_stop ツールキット関数を呼び出すことによって、
* サーバーを停止する。
*/
int
svc_stop(scds_handle_t scds_handle)
{
scha_err_t err;
/*
* 停止メソッドが成功できるタイムアウト値を Stop_Timeout
* (システム定義) プロパティに設定する。
*/
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); /* 停止は成功。 */
}
/*
* svc_wait():
*
* データサービスが完全に起動するまで待ち、動作状態を確認する。
*/
int
svc_wait(scds_handle_t scds_handle)
{
int rc, svc_start_timeout, probe_timeout;
scds_netaddr_list_t *netaddr;
/* 検証に使用するネットワークリソースを取得する。*/
if (scds_get_netaddr_list(scds_handle, &netaddr)) {
scds_syslog(LOG_ERR,
"No network address resources found in resource group.");
return (1);
}
/* ネットワークリソースが存在しない場合、エラーを戻す。*/
if (netaddr == NULL || netaddr->num_netaddrs == 0) {
scds_syslog(LOG_ERR,
"No network address resource in resource group.");
return (1);
}
/*
* 起動メソッドのタイムアウト、検証を行うポート番号、
* および検証用のタイムアウト値を取得する。
*/
svc_start_timeout = scds_get_rs_start_timeout(scds_handle);
probe_timeout = scds_get_ext_probe_timeout(scds_handle);
/*
* データサービスを実際に検証する前に、start_timeout の
* SVC_WAIT_PCT (%) だけ休止状態になる。これによって、データサービスが
* 完全に起動し、検証に応答できるようになる。
* 注: SVC_WAIT_PCT の値はデータサービス
* ごとに異なる可能性がある。
* sleep() ではなく scds_svc_wait() を
* 呼び出すと、サービスが繰り返して失敗する場合には中断して、
* すぐに戻ることができる。
*/
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 {
/*
* ネットワークリソースの IP アドレスとポート名で、
* データサービスを検証する。
*/
rc = svc_probe(scds_handle,
netaddr->netaddrs[0].hostname,
netaddr->netaddrs[0].port_proto.port, probe_timeout);
if (rc == SCHA_ERR_NOERR) {
/* 成功。リソースを解放して戻る。*/
scds_free_netaddr_list(netaddr);
return (0);
}
/*
* データサービスはまだ起動しようとする。しばらくの
* 間休止状態になり、もう一度検証を行う。sleep() ではなく
* scds_svc_wait() を呼び出すと、サービスが
* 繰り返して失敗する場合には中断して、すぐに戻ることができる。
*/
if (scds_svc_wait(scds_handle, SVC_WAIT_TIME)
!= SCHA_ERR_NOERR) {
scds_syslog(LOG_ERR, "Service failed to start.");
return (1);
}
/* RGM がタイムアウトするのを待って、プログラムを終了する。 */
} while (1);
}
/*
* この関数は、HA-XFS リソース用の障害モニターを起動する。
* そのためには、検証機能を PMF の制御下で起動する。PMF タグの形式は <RG-name,
* RS-name, instance_number.mon> である。
* PMF の再起動オプションを使用するが、
* 無限に再起動しない。代わりに、interval/retry_time を
* RTR ファイルから取得する。
*/
int
mon_start(scds_handle_t scds_handle)
{
scha_err_t err;
scds_syslog_debug(DBG_LEVEL_HIGH,
"Calling MONITOR_START method for resource <%s>.",
scds_get_resource_name(scds_handle));
/*
* xfnts_probe 検証機能は、他の RT 用のコールバックメソッドが
* インストールされているのと同じサブディレクトリにあるものと想定する。
* scds_pmf_start の最後のパラメータは、
* 監視する子プロセスのレベルを示す。検証機能は PMF の制御下で
* 起動しているので、監視する必要があるのは検証プロセスだけである。
* したがって、この値は 0 である。
*/
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 */
}
/*
* この関数は、HA-XFS リソース用の障害モニターを停止する。
* これは PMF 経由で行われる。障害モニター用の PMF タグの形式は、
* <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,
"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); /* モニターの停止は成功。*/
}
/*
* svc_probe(): データサービスに固有な検証を行う。
* 0 (成功) から 100 (致命的な障害) の範囲の整数値を戻す。
*
* 検証機能は、リソースの Port_list 拡張プロパティで指定されたポート上で、
* XFS サーバーとの単純ソケット接続を行い、データサービスを ping する。
* ポートとの接続に失敗した場合、100 の値を戻して、
* 致命的な障害であることを示す。ポートとの接続は成功したが、
* 切断が失敗した場合、50 の値を戻して、部分的な障害であることを示す。
*
*/
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;
/*
* データサービスを検証するには、
* port_list プロパティで指定されている、XFS データサービスを
* 提供するホスト上のポートとソケット接続を行う。
* 指定されたポート上でリスンするように構成された
* tXFS サービスが接続に応答した場合、検証が成功したと判断する。
* probe_timeout プロパティに設定された時間だけ待っても
* 応答がない場合、検証に失敗したと判断する。
*/
/*
* SVC_CONNECT_TIMEOUT_PCT をタイムアウトの
* 百分率として使用し、ポートと接続する。
*/
connect_timeout = (SVC_CONNECT_TIMEOUT_PCT * timeout)/100;
t1 = (hrtime_t)(gethrtime()/1E9);
/*
* 検証機能は、指定されたホスト名とポートを使用して接続を行う。
* 実際には、接続は probe_timeout の 95% の時間でタイムアウトする。
*/
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));
/* これは致命的な障害である。*/
return (SCDS_PROBE_COMPLETE_FAILURE);
}
t2 = (hrtime_t)(gethrtime()/1E9);
/*
* 接続にかかる実際の時間を計算する。この値は、
* 接続に割り当てられた時間を示す connect_timeout 以下である
* 必要がある。接続に割り当てられた時間をすべて使い切った場合、
* probe_timeout に残った値が当該関数に渡され、
* 切断タイムアウトとして 使用される。そうでなければ、
* 接続呼び出しで残った時間は切断タイムアウトに追加される。
*
*/
time_used = (int)(t2 - t1);
/*
* 残った時間 (タイムアウトから接続にかかった時間を引いた値) を切断に使用する。
*/
time_remaining = timeout - (int)time_used;
/*
* すべての時間を使い切った場合、ハードコーディングされた小さな
* タイムアウトを使用して、切断しようとする。
* これによって、fd リークを防ぐ。
*/
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;
}
/*
* 切断に失敗した場合、部分的な障害を戻す。
* 理由: 接続呼び出しは成功した。これは、アプリケーションが
* 動作していることを意味する。切断が失敗した原因は、
* アプリケーションがハングしたか、負荷が高いためである。
* 後者の場合、アプリケーションが停止したとは宣言しない
* (つまり、致命的な障害を戻さない)。その代わりに、
* 部分的な障害であると宣言する。この状態が続く場合、
* 切断呼び出しは再び失敗し、アプリケーションは
* 再起動される。
*/
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));
/* これは部分的な障害である。*/
return (SCDS_PROBE_COMPLETE_FAILURE/2);
}
t2 = (hrtime_t)(gethrtime()/1E9);
time_used = (int)(t2 - t1);
time_remaining = timeout - time_used;
/*
* 時間が残っていない場合、fsinfo による完全なテストを
* 行わない。その代わりに、SCDS_PROBE_COMPLETE_FAILURE/2
* を戻す。これによって、このタイムアウトが続く場合、
* サーバーは再起動される。
*/
if (time_remaining <= 0) {
scds_syslog(LOG_ERR, "Probe timed out.");
return (SCDS_PROBE_COMPLETE_FAILURE/2);
}
/*
* ポートとの接続と切断は成功した。fsinfo コマンドを実行して、
* サーバーの状態を完全に検査する。stdout をリダイレクトする。
* そうしなければ、fsinfo からの出力はコンソールに送られる。
*/
(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);
}
|
このメソッドは、基本的なリソースタイプ構成が有効であることを確認します。
/*
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_monitor_check.c - Monitor Check method for HA-XFS
*/
#pragma ident "@(#)xfnts_monitor_check.c 1.11 01/01/18
SMI"
#include <rgm/libdsdev.h>
#include "xfnts.h"
/*
* サービスに対して簡単な妥当性検査を行う。
*/
int
main(int argc, char *argv[])
{
scds_handle_t scds_handle;
int rc;
/* RGM から渡された引数を処理して、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);
/* scds_initialize が割り当てたすべてのメモリーを解放する。*/
scds_close(&scds_handle);
/* モニター検査の一環として実行した検証メソッドの結果を戻す。*/
return (rc);
}
|
このメソッドは、xfnts_probe メソッドを起動します。
/*
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_monitor_start.c - Monitor Start method for HA-XFS
*/
#pragma ident "@(#)xfnts_monitor_start.c 1.10 01/01/18
SMI"
#include <rgm/libdsdev.h>
#include "xfnts.h"
/*
* このメソッドは、HA-XFS リソース用の障害モニターを起動する。
* そのためには、検証機能を PMF の制御下で起動する。PMF タグの形式は
* <RG-name, RS-name.mon> である。PMF の再起動オプションを
* 使用するが、無限に再起動しない。その代わりに、
* interval/retry_time を RTR ファイルから取得する。
*/
int
main(int argc, char *argv[])
{
scds_handle_t scds_handle;
int rc;
/* RGM から渡された引数を処理して、syslog を初期化する。 */
if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
scds_syslog(LOG_ERR, "Failed to initialize the handle.");
return (1);
}
rc = mon_start(scds_handle);
/* scds_initialize が割り当てたすべてのメモリーを解放する。*/
scds_close(&scds_handle);
/* monitor_start メソッドの結果を戻す。 */
return (rc);
}
|
このメソッドは、xfnts_probe メソッドを停止します。
/*
* Copyright (c) 2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_monitor_stop.c - Monitor Stop method for HA-XFS
*/
#pragma ident "@(#)xfnts_monitor_stop.c 1.9 01/01/18 SMI"
#include <rgm/libdsdev.h>
#include "xfnts.h"
/*
* このメソッドは、HA-XFS リソース用の障害モニターを停止する。
* この処理は PMF 経由で行われる。障害モニター用の
* PMF タグの形式は <RG-name_RS-name.mon> である。
*/
int
main(int argc, char *argv[])
{
scds_handle_t scds_handle;
int rc;
/* RGM から渡された引数を処理して、syslog を初期化する。*/
if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
scds_syslog(LOG_ERR, "Failed to initialize the handle.");
return (1);
}
rc = mon_stop(scds_handle);
/* scds_initialize が割り当てたすべてのメモリーを解放する。*/
scds_close(&scds_handle);
/* monitor_stop メソッドの結果を戻す。*/
return (rc);
}
|
xfnts_probe メソッドは、アプリケーションの可用性を検査して、データサービスをフェイルオーバーするか、再起動するかを決定します。xfnts_probe メソッドは、xfnts_monitor_start コールバックメソッドによって起動され、xfnts_monitor_stop コールバックメソッドによって停止されます。
/*
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_probe.c - Probe for 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():
* sleep() を実行して、PMF アクションスクリプトが sleep() に割り込むのを待機する
* 無限ループ。sleep() への割り込みが発生すると、HA-XFS 用の起動メソッドを
* 呼び出して、再起動する。
*
*/
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, "Failed to initialize the handle.");
return (1);
}
/* 当該リソースに利用できる IP アドレスを取得する。*/
if (scds_get_netaddr_list(scds_handle, &netaddr)) {
scds_syslog(LOG_ERR,
"No network address resource in resource group.");
scds_close(&scds_handle);
return (1);
}
/* ネットワークリソースが存在しない場合、エラーを戻す。*/
if (netaddr == NULL || netaddr->num_netaddrs == 0) {
scds_syslog(LOG_ERR,
"No network address resource in resource group.");
return (1);
}
/*
* X プロパティからタイムアウト値を設定する。つまり、
* 当該リソース用に構成されたすべてのネットワークリソース間で
* タイムアウト値を分割するのではなく、検証を行うたびに、
* 各ネットワークリソースに設定されているタイムアウト値を
* 取得することを意味する。
*/
timeout = scds_get_ext_probe_timeout(scds_handle);
for (;;) {
/*
* 連続する検証の間、Throrough_probe_interval
* の期間、休止状態になる。
*/
(void) scds_fm_sleep(scds_handle,
scds_get_rs_thorough_probe_interval(scds_handle));
/*
* 使用するすべての IP アドレスを検証する。
* 以下をループで検証する。
* 1. 使用するすべてのネットワークリソース
* 2. 指定されたリソースのすべての IP アドレス
* 検証する IP アドレスごとに、障害履歴を計算する。
*/
probe_result = 0;
/*
* すべてのリソースを繰り返し検証して、svc_probe() の
* 呼び出しに使用する各 IP アドレスを取得する。
*/
for (ip = 0; ip < netaddr->num_netaddrs; ip++) {
/*
* 状態を監視するホスト名とポートを取得する。
*/
hostname = netaddr->netaddrs[ip].hostname;
port = netaddr->netaddrs[ip].port_proto.port;
/*
* HA-XFS がサポートするポートは 1 つだけなので、
* ポート値はポートの配列の最初の
* エントリから取得する。
*/
ht1 = gethrtime(); /* 検証開始時間を取得する。*/
scds_syslog(LOG_INFO, "Probing the service on "
"port: %d.", port);
probe_result =
svc_probe(scds_handle, hostname, port, timeout);
/*
* サービス検証履歴を更新し、
* 必要に応じて、アクションを実行する。
* 検証終了時間を取得する。
*/
ht2 = gethrtime();
/* ミリ秒に変換する。*/
dt = (ulong_t)((ht2 - ht1) / 1e6);
/*
* 障害の履歴を計算し、
* 必要に応じて、アクションを実行する。
*/
(void) scds_fm_action(scds_handle,
probe_result, (long)dt);
} /* ネットワークリソースごと */
} /* 検証を永続的に繰り返す。 */
}
|
データサービスリソースを含むリソースグループがクラスタのノード上でオンラインになったとき、あるいは、リソースが有効になったとき、RGM はそのクラスタノード上で START メソッドを呼び出します。xfnts_start メソッドはそのノード上で xfs デーモンを起動します。
/*
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_svc_start.c - Start method for HA-XFS
*/
#pragma ident "@(#)xfnts_svc_start.c 1.13 01/01/18 SMI"
#include <rgm/libdsdev.h>
#include "xfnts.h"
/*
* HA-XFS 用の起動メソッド。リソース設定に対していくつかの
* サニティ検査を行った後、アクションスクリプトを使用して HA-XFS を
* PMF の制御下で起動する。
*/
int
main(int argc, char *argv[])
{
scds_handle_t scds_handle;
int rc;
/*
* RGM から渡された引数を処理して、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);
if (rc != 0) {
scds_syslog(LOG_ERR,
"Failed to validate configuration.");
return (rc);
}
/* データサービスを起動する。失敗した場合、エラーで戻る。*/
rc = svc_start(scds_handle);
if (rc != 0) {
goto finished;
}
/* サービスが完全に起動するまで待つ。*/
scds_syslog_debug(DBG_LEVEL_HIGH,
"Calling svc_wait to verify that sevice 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.");
}
finished:
/* 割り当てられた環境リソースを解放する。*/
scds_close(&scds_handle);
return (rc);
}
|
HA-XFS リソースを含むリソースグループがクラスタのノード上でオフラインになったとき、あるいは、リソースが無効になったとき、RGM はそのクラスタノード上で STOP メソッドを呼び出します。xfnts_stop メソッドはそのノード上で xfs デーモンを停止します。
/*
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_svc_stop.c - Stop method for HA-XFS
*/
#pragma ident "@(#)xfnts_svc_stop.c 1.10 01/01/18 SMI"
#include <rgm/libdsdev.h>
#include "xfnts.h"
/*
* PMF を使用して HA-XFS プロセスを停止する。
*/
int
main(int argc, char *argv[])
{
scds_handle_t scds_handle;
int rc;
/* RGM から渡された引数を処理して、syslog を初期化する。*/
if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
scds_syslog(LOG_ERR, "Failed to initialize the handle.");
return (1);
}
rc = svc_stop(scds_handle);
/* scds_initialize が割り当てたすべてのメモリーを解放する。*/
scds_close(&scds_handle);
/* svc_stop メソッドの結果を戻す。*/
return (rc);
}
|
RGM は UPDATE メソッドを呼び出して、プロパティが変更されたことを動作中のリソースに通知します。RGM が UPDATE メソッドを呼び出すのは、管理アクションによってリソースまたはリソースグループのプロパティの設定が成功したときです。
#pragma ident "@(#)xfnts_update.c 1.10 01/01/18 SMI"
/*
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_update.c - Update method for HA-XFS
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <rgm/libdsdev.h>
/*
* リソースのプロパティが更新された可能性がある。
* このような更新可能なプロパティはすべて障害モニターに関連するものであるため、
* 障害モニターを再起動する必要がある。
*/
int
main(int argc, char *argv[])
{
scds_handle_t scds_handle;
scha_err_t result;
/* RGM から渡された引数を処理して、syslog を初期化する。*/
if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
scds_syslog(LOG_ERR, "Failed to initialize the handle.");
return (1);
}
/*
* 障害モニターがすでに動作していることを検査し、
* 動作している場合、障害モニターを停止および再起動する。
* scds_pmf_restart_fm() への 2 番目のパラメータは、再起動する
* 必要がある障害モニターのインスタンスを一意に識別する。
*/
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.");
/* scds_initialize が割り当てたすべてのメモリーを解放する。*/
scds_close(&scds_handle);
return (1);
}
scds_syslog(LOG_INFO,
"Completed successfully.");
/* scds_initialize が割り当てたすべてのメモリーを解放する。*/
scds_close(&scds_handle);
return (0);
}
|
xfnts_validate メソッドは、Confdir_list プロパティが示すディレクトリの存在を確認します。RGM がこのメソッドを呼び出すのは、クラスタ管理者がデータサービスを作成したときと、データサービスのプロパティを更新したときです。障害モニターがデータサービスを新しいノードにフェイルオーバーしたときは、MONITOR_CHECK メソッドは常にこのメソッドを呼び出します。
/*
* Copyright (c) 1998-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_validate.c - validate method for HA-XFS
*/
#pragma ident "@(#)xfnts_validate.c 1.9 01/01/18 SMI"
#include <rgm/libdsdev.h>
#include "xfnts.h"
/*
* プロパティが正しく設定されていることを確認する。
*/
int
main(int argc, char *argv[])
{
scds_handle_t scds_handle;
int rc;
/* RGM から渡された引数を処理して、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_initialize が割り当てたすべてのメモリーを解放する。*/
scds_close(&scds_handle);
/* 検証メソッドの結果を戻す。*/
return (rc);
}
|