イベント・ベースの通信では、特定の状況(イベント)が発生すると、Oracle Tuxedoシステムのプロセスに通知されます。
Oracle Tuxedoシステムには、次の2種類のイベント・ベースの通信があります。
非請求イベントは、メッセージを待たないクライアント・プログラム、またはメッセージを要求しないクライアント・プログラムとの通信に使用されるメッセージです。
ブローカ・イベントを使用すると、メッセージの受信と配信を行う無名ブローカを介して、クライアントとサーバーが透過的に通信できるようになります。このようなブローカを使用した通信は、Oracle Tuxedoシステムの基本要素であるクライアント/サーバーのコミュニケーション・パラダイムの1つです。
イベント・ブローカは、イベント・ポスト・メッセージを受信してフィルタ処理し、それらのメッセージをサブスクライバに配布するOracle Tuxedoのサブシステムです。 ポスト元とは、特定のイベントが発生したときにそれをイベント・ブローカに報告(ポスト)するOracle Tuxedoシステムのプロセスです。 サブスクライバとは、特定のイベントがポストされたときに常に通知する必要があるOracle Tuxedoシステムのプロセスです。
Oracle Tuxedoシステムでは、サービスのリクエスト側と提供側の数の比率が一定である必要はなく、任意の数のポスト元が任意の数のサブスクライバに対してメッセージ・バッファをポストできます。ポスト元は単にイベントをポストするだけで、情報を受信するプロセスや、情報の処理方法については関知しません。サブスクライバには指定されたイベントが通知されますが、その情報のポスト元は通知されません。このように、イベント・ブローカでは位置透過性が実現されます。
通常、イベント・ブローカ・アプリケーションは、例外イベントを処理します。 アプリケーションの設計者は、アプリケーション内でどのイベントを例外イベントとして定義して監視する必要があるのかを決定しなければなりません。 たとえば、銀行業務アプリケーションでは、高額な引出しがあったときにイベントがポストされるように設定し、すべての引出しに対してイベントがポストされる必要はありません。 また、すべてのユーザーがそのイベントをサブスクライブする必要はありません。支店長だけに通知すれば十分です。
イベントがポストされると、EventBrokerはイベントをサブスクライブしているクライアントまたはサーバー(あるいは両方)に対して、1つ以上の通知処理を実行します。表8-1は、EventBrokerが実行する通知処理の種類を示しています。
クライアントは、tpnotify()で送信された場合と同じように、クライアントの非請求メッセージ処理ルーチンでイベント通知メッセージを受信します。
|
|
サーバーは、tpacall()によって送信された場合と同じように、サービス・ルーチンに対する入力としてイベント通知メッセージを受け取ります。
|
|
イベント通知メッセージは、tpenqueue(3c)関数を使用して、Oracle Tuxedoシステムの信頼性の高いキューに格納されます。イベント通知バッファは、バッファ内容がリクエストされるまで格納されます。Oracle Tuxedoシステムのクライアントまたはサーバー・プロセスでtpdequeue(3c)関数を呼び出して、この通知バッファを取り出すことができます。または、TMQFORWARD(5)を構成して、通知バッファを取り出すOracle Tuxedoシステムのサービス・ルーチンを自動的にディスパッチすることもできます。
|
アプリケーション管理者は、Oracle Tuxedoの管理用APIを使用して、次の通知処理を行うEVENT_MIB(5)エントリを作成できます。
注意: | EVENT_MIB(5)エントリを作成できるのは、Oracle Tuxedoアプリケーション管理者だけです。 |
EVENT_MIB(5)の詳細は、『ファイル形式、データ記述、MIBおよびシステム・プロセス・リファレンス』を参照してください。
TMUSREVT
はOracle Tuxedoシステムで提供されるサーバーで、ユーザー定義のイベントに対するイベント・ブローカとして動作します。 TMUSREVT
はイベント・レポート用のメッセージ・バッファを処理し、それらのバッファをフィルタ処理して配信します。 イベントのブローカ処理を行うには、Oracle Tuxedoアプリケーション管理者がこれらのサーバーを1つ以上起動する必要があります。
TMSYSEVT
はOracle Tuxedoシステムで提供されるサーバーで、システム定義のイベントに対するイベント・ブローカとして動作します。TMSYSEVT
とTMUSREVT
は似ています。ただし、別個のサーバーが提供されているので、アプリケーション管理者はこの2種類のイベント通知に対して異なる処理方法を取り入れることができます。詳細は、『Oracle Tuxedoアプリケーションの設定』を参照してください。
Oracle Tuxedoシステムでは、システムの警告と障害に関連する定義済みの特定のイベントが検出されてポストされます。これらの処理はイベント・ブローカによって行われます。たとえば、システム定義のイベントには、設定の変更、状態の変更、接続の障害、マシンの分断などがあります。イベント・ブローカによって検出されるシステム定義のイベントの全リストについては、『ファイル形式、データ記述、MIBおよびシステム・プロセス・リファレンス』の「EVENTS(5)」を参照してください。
システム定義のイベントは、Oracle Tuxedoシステム・コードで定義されているため、ポストする必要はありません。システム定義のイベント名は、アプリケーション定義のイベント名とは異なり、必ずドット(.)で始まります。アプリケーション定義のイベント名をドットで始めることはできません。
クライアントとサーバーは、システム定義のイベントをサブスクライブできます。 ただし、システム定義のイベントは、アプリケーション内のすべてのクライアントが使用するのではなく、主にアプリケーション管理者が使用します。
イベント・ブローカをアプリケーションに組み込む場合、イベント・ブローカが多数のサブスクライバに大量の配信を行うためのシステムではないことを考慮してください。 発生するすべての動作に対してイベントをポストしないでください。また、すべてのクライアントとサーバーがイベントをサブスクライブする必要はありません。 イベント・ブローカに負荷がかかると、システムのパフォーマンスに影響し、通知が行われなくなる場合があります。 負荷を最小限にするには、『Oracle Tuxedoシステムのインストール』で説明するように、アプリケーション管理者がオペレーティング・システムのIPCリソースを慎重に調整する必要があります。
イベント・ブローカ・プログラミング・インタフェースは、ワークステーションを含むすべてのOracle Tuxedoシステムのサーバー・プロセスおよびクライアント・プロセスに対してC言語およびCOBOL言語で使用できます。
サブスクライバへの通知方法には様々な方法(「通知処理」を参照)があり、イベントはフィルタ処理されます。通知処理とフィルタ処理は、プログラミング・インタフェースとOracle Tuxedoシステムの管理用APIを使用して設定します。
非請求メッセージ・ハンドラ関数を定義するには、次の文法を使用してtpsetunsol(3c)関数を呼び出します。
int
tpsetunsol(*myfunc
)
Windowsベースのオペレーティング・システムを実行している場合、以下のような非請求メッセージ・ハンドラ関数を宣言する必要があります。
void _TMDLLENTRY CustomerUnsolFunc(char *data, long len, long flags)
Windowsベースのオペレーティング・システムでは、Tuxedoライブラリと使用するコード間で適切な呼出し規約を適用するために_TMDLLENTRY
マクロが必要になります。
Unixシステムの場合は、_TMDLLENTRY
マクロはNULL文字列に展開するため必要ありません。
表8-2は、tpsetunsol()
関数に渡すことができる唯一の引数を示してます。
クライアントが非請求メッセージを受信すると、そのメッセージと共にコールバック関数がディスパッチされます。できるかぎりタスクが中断されないようにするには、非請求メッセージのハンドラ関数で最小限の処理しか行われないようにコーディングします。このようにすると、ハンドラ関数が待機中のプロセスにすぐに戻ることができます。
Oracle Tuxedoシステムでは、リクエスト/レスポンス型呼び出しまたは会話型通信の処理を妨げずに、クライアント・プロセスに非請求メッセージを送信できます。
非請求メッセージは、名前、または以前に処理されたメッセージと共に受信した識別子を使用して、クライアント・プロセスに送信できます。名前による送信にはtpbroadcast(3c)、識別子による送信にはtpnotify(3c)を使用します。 tpbroadcast
()で送信されるメッセージの発信元は、サービスまたは別のクライアントです。 tpnotify
()で送信されるメッセージの発信元は、サービスだけです。
tpbroadcast(3c)を使用すると、アプリケーションの登録されたクライアントにメッセージが送信されます。 TPBROADCASTルーチンは、サービスまたは別のクライアントから呼び出すことができます。 登録されたクライアントとは、tpinit()を呼び出したものの、まだtpterm()を呼び出してはいないクライアントのことです。
tpbroadcast
()関数の呼出しには、次の文法を使用します。
int
tpbroadcast(char *lmid, char *usrname, char *cltname, char *data, long len, long flags)
表8-3は、tpbroadcast()
関数の引数を示しています。
フラグのオプション。使用できるフラグについては、『Oracle Tuxedo ATMI C関数リファレンス』の「tpbroadcast(3c)」を参照してください。
|
リスト8-1は、すべてのクライアントを送信先としてtpbroadcast
()を呼び出す方法を示しています。送信メッセージは、STRING
バッファ内にあります。
char *strbuf;
if ((strbuf = tpalloc("STRING", NULL, 0)) == NULL) {
error routine
}
(void) strcpy(strbuf, "hello, world");
if (tpbroadcast(NULL, NULL, NULL, strbuf, 0, TPSIGRSTRT) == -1)
error routine
tpnotify(3c)関数を使用すると、以前に処理されたメッセージと共に受信した識別子を使用してメッセージがブロードキャストされます。 TPNOTIFYルーチンは、サービスからのみ呼び出すことができます。
tpnotify
()関数の呼出しには、次の文法を使用します。
int
tpnotify(CLIENTID *clientid, char *data, long len, long flags)
表8-4は、tpnotify()
関数の引数を示しています。
フラグのオプション。使用できるフラグについては、『Oracle Tuxedo ATMI C関数リファレンス』の「tpnotify(3c)」を参照してください。
|
クライアントがディップ・イン通知モードで実行されている場合に非請求メッセージがあるかどうかを確認するには、次のシグネチャを使用してtpchkunsol(3c)関数を呼び出します。
int
tpchkunsol()
未処理のメッセージがある場合、tpsetunsol()で指定された非請求メッセージ処理関数が呼び出されます。 処理が終了すると、この関数は処理した非請求メッセージの数、またはエラーを示す-1
を返します。
クライアントがシグナルベースまたはスレッド・ベースの通知モードで実行されている場合、またはクライアントが非請求メッセージを無視している場合にこの関数を呼び出すと、関数は何も処理を行わずにすぐに制御を戻します。
tpsubscribe(3c)関数を使用すると、Oracle Tuxedoシステムのクライアントまたはサーバーがイベントをサブスクライブできるようになります。
サブスクライバは、非請求通知メッセージ、サービス呼び出し、高い信頼性のキュー、またはアプリケーション管理者が設定する別の通知方法によって、通知を受け取ります。 別の通知方法の設定については、『Oracle Tuxedoアプリケーションの設定』を参照してください。
tpsubscribe()
関数の呼出しには、次の文法を使用します。
long handle
tpsubscribe (char *eventexpr
, char *filter
, TPEVCTL *ctl
, longflags
)
表8-5は、tpsubscribe()
関数の引数を示しています。
プロセスがサブスクライブする1つ以上のイベントを指すポインタ。正規表現を含み、NULL文字で終了する最大255文字の文字列を指定します。正規表現は、tpsubscribe(3c)で指定された形式です(『Oracle Tuxedo ATMI C関数リファレンス』を参照)。 たとえば、次のように
eventexpr を設定します。
|
|
EventBrokerがイベントをポストする前に、評価する必要があるブール型のフィルタ規則を含む文字列を指すポインタ。ポストするイベントを受け取ると、EventBrokerはそのイベントのデータにフィルタ規則(存在する場合)を適用します。データが正しく評価された場合、EventBrokerは指定された通知方法を呼び出し、正しく評価されなかった場合、EventBrokerは指定された通知方法を無視します。呼出し側は、異なるフィルタ規則を利用して同じイベントを何度でもサブスクライブできます。
イベント・フィルタ機能を使用すると、サブスクライバは通知されるイベントを限定できます。たとえば、$10,000を超える額の引出しがあった場合に、イベントがポストされるとします。その場合、サブスクライバがもっと高い額(たとえば$50,000)の通知だけを必要とすることがあります。または、特定の顧客による高額の引出しの通知だけを必要とする場合があります。 フィルタ・ルールは、それが適用される型付きバッファに固有なものです。フィルタ規則の詳細は、『Oracle Tuxedo ATMI C関数リファレンス』の「tpsubscribe(3c)」を参照してください。
|
|
|
|
フラグのオプション。使用可能なフラグ・オプションの詳細は、『Oracle Tuxedo ATMI C関数リファレンス』の「tpsubscribe(3c)」を参照してください。
|
システム定義のイベントとアプリケーション定義のイベントは、tpsubscribe
()関数を使用してサブスクライブできます。
サブスクリプション、およびMIB
を更新するためにOracle Tuxedoシステムのサーバー・プロセスで実行されるサービス・ルーチンは、信頼されたコードとみなされます。
サブスクライバがOracle Tuxedoシステムのクライアント・プロセスであり、ctl
にNULLが設定されている場合、クライアントがサブスクライブしているイベントがポストされると、イベント・ブローカは次のようにサブスクライバに非請求メッセージを送ります。 eventexpr
に対して正常に評価されたイベント名がポストされると、イベント・ブローカは対応付けられたフィルタ規則でポストされたデータを確認します。 データがフィルタ規則で正しく評価された場合(またはイベントにフィルタ規則がない場合)、サブスクライバはイベントと共にポストされたデータと非請求メッセージを受信します。
非請求メッセージを受け取るには、クライアントはtpsetunsol()関数を使用して、非請求メッセージ処理ルーチンを登録しておく必要があります。
クライアントが非請求メッセージによってイベント通知を受け取った場合、終了する前にイベント・ブローカのアクティブなサブスクリプションのリストからそのサブスクリプションを削除する必要があります。 サブスクリプションの削除にはtpunsubscribe()関数を使用します。
サービス呼出しを使用したイベント通知では、アプリケーションの特定の条件に対して自動的に応答するようにプログラミングできます。 高い信頼性のキューを使用したイベント通知では、イベント・データが損失しないことが保証されます。 また、サブスクライバがいつでもイベント・データを取り出せるという柔軟性があります。
サブスクライバ(クライアント・プロセスまたはサーバー・プロセス)がイベント通知をサービス・ルーチンまたは安定記憶領域のキューに送信する場合、tpsubscribe()
のctl
パラメータが有効なTPEVCTL
構造体を指していることが必要です。
longflags
;
charname1
[127];
charname2
[127];
TPQCTL qctl;
表8-6は、TPEVCTL
型バッファのデータ構造体を示しています。
フラグのオプション。フラグの詳細は、『Oracle Tuxedo ATMI C関数リファレンス』の「tpsubscribe(3c)」を参照してください。
|
|
tpunsubscribe(3c)関数を使用すると、Oracle Tuxedoシステムのクライアントまたはサーバーがイベントに対するサブスクリプションを削除できます。
tpunsubscribe()
関数の呼出しには、次の文法を使用します。
int
tpunsubscribe (long subscription, long flags)
表8-7は、tpunsubscribe()
関数の引数を示しています。
tpsubscribe()への呼出しで返されるサブスクリプション・ハンドル。
|
|
フラグのオプション。使用可能なフラグ・オプションの詳細は、『Oracle Tuxedo ATMI C関数リファレンス』の「tpunsubscribe(3c)」を参照してください。
|
tppost(3c)関数を使用すると、Oracle Tuxedoのクライアントまたはサーバーがイベントをポストできます。
tppost(char *eventname
, char *data
, longlen
, longflags
)
表8-8は、tppost()
関数の引数を示しています。
tpalloc()関数ですでに割り当てられているバッファを指すポインタ。
|
|
フラグのオプション。使用可能なフラグ・オプションの詳細は、『Oracle Tuxedo ATMI C関数リファレンス』の「tppost(3c)」を参照してください。
|
リスト8-2は、Oracle Tuxedoシステムの銀行業務のサンプル・アプリケーションbankapp
から引用したイベント・ポストを示しています。この例は、WITHDRAWAL
サービスの一部です。WITHDRAWAL
サービスは、$10,000を超える引出しかどうかを確認し、またBANK_TLR_WITHDRAWAL
イベントをポストします。
.
.
.
/* Event logic related */
static float evt_thresh = 10000.00 ; /* default for event threshold */
static char emsg[200] ; /* used by event posting logic */
.
.
.
/* Post a BANK_TLR_WITHDRAWAL event ? */
if (amt < evt_thresh) {
/* no event to post */
tpreturn(TPSUCCESS, 0,transb->data , 0L, 0);
}
/* prepare to post the event */
if ((Fchg (transf, EVENT_NAME, 0, "BANK_TLR_WITHDRAWAL", (FLDLEN)0) == -1) ||
(Fchg (transf, EVENT_TIME, 0, gettime(), (FLDLEN)0) == -1) ||
(Fchg (transf, AMOUNT, 0, (char *)&amt, (FLDLEN)0) == -1)) {
(void)sprintf (emsg, "Fchg failed for event fields: %s",
Fstrerror(Ferror)) ;
}
/* post the event */
else if (tppost ("BANK_TLR_WITHDRAWAL", /* event name */
(char *)transf, /* data */
0L, /* len */
TPNOTRAN | TPSIGRSTRT) == -1) {
/* If event broker is not reachable, ignore the error */
if (tperrno != TPENOENT)
(void)sprintf (emsg, "tppost failed: %s", tpstrerror (tperrno));
}
このサンプル・コードでは、アプリケーションで目立った状況が発生したことを示すために、イベントをイベント・ブローカにポストしているだけです。 特定のイベントに関心を持つクライアント(必要に応じて処理を行うクライアント)のイベントへのサブスクリプションは、別にコーディングします。
次のサンプル・コードは、bankapp
アプリケーション・サーバーの一部であり、このサーバーはBANK_TLR_.*
イベントをサブスクライブしています。この例には、前述の例のBANK_TLR_WITHDRAWAL
イベントと、BANK_TLR_
で始まるそのほかのイベント名が含まれています。 合致するイベントがポストされると、WATCHDOG
サービスへの呼出しを使用して、アプリケーションからサブスクライバにイベントが通知されます。
.
.
.
/* Event Subscription handles */
static long sub_ev_largeamt = 0L ;
.
.
.
/* Preset default for option 'w' - watchdog threshold */
(void)strcpy (amt_expr, "AMOUNT > 10000.00") ;
.
.
.
/*
* Subscribe to the events generated
* when a "large" amount is transacted.
*/
evctl.flags = TPEVSERVICE ;
(void)strcpy (evctl.name1, "WATCHDOG") ;
/* Subscribe */
sub_ev_largeamt = tpsubscribe ("BANK_TLR_.*",amt_expr,&evctl,TPSIGRSTRT) ;
if (sub_ev_largeamt == -1L) {
(void)userlog ("ERROR: tpsubscribe for event BANK_TLR_.* failed: %s",
tpstrerror(tperrno)) ;
return -1 ;
}
.
.
.
{
/* Unsubscribe to the subscribed events */
if (tpunsubscribe (sub_ev_largeamt, TPSIGRSTRT) == -1)
(void)userlog ("ERROR: tpunsubscribe to event BANK_TLR_.* failed: %s",
tpstrerror(tperrno)) ;
return ;
}
/*
* Service called when a BANK_TLR_.* event is posted.
*/
void
#if defined(__STDC__) || defined(__cplusplus)
WATCHDOG(TPSVCINFO *transb)
#else
WATCHDOG(transb)
TPSVCINFO *transb;
#endif
{
FBFR *transf; /* fielded buffer of decoded message */
/* Set pointr to TPSVCINFO data buffer */
transf = (FBFR *)transb->data;
/* Print the log entry to stdout */
(void)fprintf (stdout, "%20s|%28s|%8ld|%10.2f\n",
Fvals (transf, EVENT_NAME, 0),
Fvals (transf, EVENT_TIME, 0),
Fvall (transf, ACCOUNT_ID, 0),
*( (float *)CFfind (transf, AMOUNT, 0, NULL, FLD_FLOAT)) );
/* No data should be returned by the event subscriber's svc routine */
tpreturn(TPSUCCESS, 0,NULL, 0L, 0);
}