![]() |
![]() |
|
|
サービスの定義
すべてのサービス・ルーチンは、1 つの引数、つまり TPSVCINFO 構造体を指すポインタを受け取る関数として定義する必要があります。TPSVCINFO 構造体は、atmi.h ヘッダ・ファイルに定義され、次の情報が含まれています。
char name[32];
long flags;
char *data;
long len;
int cd;
int appkey;
CLIENTID cltid;
次の表は、TPSVCINFO データ構造体を示しています。
TPSVCINFO データ構造体
プロセスが TPSVCINFO 構造体の data フィールドにアクセスする場合、次のバッファ・タイプが合致する必要があります。
次のコード例は、一般的なサービス定義を示しています。このコードは、BEA Tuxedo ソフトウェアで提供される銀行業務アプリケーションの ABAL (残高照会) サービス・ルーチンから引用したものです。ABAL サービスは BAL サーバの一部です。
一般的なサービス定義
#include <stdio.h> /* UNIX */
#include <atmi.h> /* BEA Tuxedo システム */
#include <sqlcode.h> /* BEA Tuxedo システム */
#include "bank.flds.h" /* bankdb フィールド */
#include "aud.h" /* 銀行業務アプリケーションの VIEW 定義 */
EXEC SQL begin declare section;
static long branch_id; /* 支店番号 */
static float bal; /* 残高 */
EXEC SQL end declare section;
/*
* あるサイトの口座残高の合計を算出するサービス
*/
void
#ifdef __STDC__
ABAL(TPSVCINFO *transb)
#else
ABAL(transb)
TPSVCINFO *transb;
#endif
{
struct aud *transv; /* 復号化されたメッセージの VIEW */
/* tpsvcinfo データ・バッファへのポインタの設定 */
transv = (struct aud *)transb->data;
set the consistency level of the transaction
/* メッセージから支店番号を受け取り、照会を行います。 */
EXEC SQL declare acur cursor for
select SUM(BALANCE) from ACCOUNT;
EXEC SQL open acur; /* オープン */
EXEC SQL fetch acur into :bal; /* フェッチ */
if (SQLCODE != SQL_OK) { /* 何もありません。 */
(void)strcpy (transv->ermsg,"abal failed in sql aggregation");
EXEC SQL close acur;
tpreturn(TPFAIL, 0, transb->data, sizeof(struct aud), 0);
}
EXEC SQL close acur;
transv->balance = bal;
tpreturn (TPSUCCESS, 0, transb->data, sizeof(struct aud), 0);
}
この例では、アプリケーションがクライアント側に要求バッファを割り当てるために、tpalloc() の呼び出しで type パラメータに VIEW、subtype に aud が設定されています。ABAL サービスは、VIEW 型バッファをサポートするサービスとして定義されています。ABAL には BUFTYPE パラメータは指定されてなく、デフォルト値の ALL が使用されます。ABAL サービスは VIEW 型バッファを割り当て、このバッファへのポインタに ABAL サブルーチンが渡された TPSVCINFO 構造体の data メンバを割り当てます。ABAL サーバは、前述のコード例に示してあるように、対応する data メンバにアクセスして適切なデータ・バッファを取得します。
注記 このバッファが取得された後、データベースへの最初のアクセスを行う前に、サービスでトランザクションの整合性レベルを指定する必要があります。トランザクションの整合性レベルの詳細については、「グローバル・トランザクションのコーディング」を参照してください。
例:バッファ・タイプの確認
ここで示すコード例は、サービスが TPSVCINFO 構造体に定義されているデータ・バッファにアクセスし、tptypes() 関数を使ってそのタイプを確認する方法を示しています。この処理については、「バッファ・タイプの確認」を参照してください。また、このサービスはバッファの最大サイズを確認して、そのバッファに領域を再割り当てするかどうかを判定します。
このコード例は、BEA Tuxedo ソフトウェアで提供される銀行業務アプリケーションの ABAL サービスから引用したものです。このコードでは、aud VIEW または FML のいずれかのバッファとして要求を受け入れるサービスをコーディングする方法を示しています。メッセージ・タイプの確認が失敗した場合、エラー・メッセージの文字列と戻りコードが返されます。成功した場合、バッファ・タイプに合致したコードが実行されます。tpreturn() 関数の詳細については、「サービス・ルーチンの終了」を参照してください。
バッファ・タイプの確認
#define TMTYPERR 1 /* tptypes が失敗したことを示す戻りコード */
#define INVALMTY 2 /* 無効なメッセージ・タイプであること示す戻りコード */
void
ABAL(transb)
TPSVCINFO *transb;
{
struct aud *transv; /* VIEW メッセージ */
FBFR *transf; /* フィールド化バッファ・メッセージ */
int repc; /* tpgetrply の戻りコード */
char typ[TMTYPELEN+1], subtyp[TMSTYPELEN+1]; /* メッセージのタイプとサブタイプ */
char *retstr; /* tptypes が失敗した場合に返される文字列 */
/* 送信されたバッファ・タイプを確認します。 */
if (tptypes((char *)transb->data, typ, subtyp) == -1) {
retstr=tpalloc("STRING", NULL, 100);
(void)sprintf(retstr,
"Message garbled; tptypes cannot tell what type message\n");
tpreturn(TPFAIL, TMTYPERR, retstr, 100, 0);
}
/* タイプに基づいてサービス要求を処理する方法を決定します。 */
if (strcmp(typ, "FML") == 0) {
transf = (FBFR *)transb->data;
... フィールド化バッファのための abal サービスを実行するコード ...
tpreturn が成功し、応答として FML バッファを送信します。
}
else if (strcmp(typ, "VIEW") == 0 && strcmp(subtyp, "aud") == 0) {
transv = (struct aud *)transb->data;
... aud 構造体のための abal サービスを実行するコード ...
tpreturn の実行が成功し、応答として aud VIEW バッファを送信します。
}
else {
retstr=tpalloc("STRING", NULL, 100);
(void)sprintf(retstr,
"Message garbled; is neither FML buffer nor aud view\n");
tpreturn(TPFAIL, INVALMTY, retstr, 100, 0);
}
}
例:サービス要求の優先順位の確認
注記 優先順位を取得する tpgprio()、および優先順位を設定する tpsprio() 関数の詳細については、「メッセージの優先順位の設定および取得」を参照してください。
ここで示すコード例は、PRINTER サービスが tpgprio() ルーチンを使用して、受信したばかりの要求の優先順位を確認する方法を示しています。その後、その優先順位に基づいて印刷ジョブが適切なプリンタに送られ、そのプリンタに pbuf->data の内容がパイプされています。
アプリケーションは pbuf->flags を照会し、応答が必要かどうかを判定します。応答が必要な場合は、プリンタ名をクライアントに返します。tpreturn() 関数の詳細については、「サービス・ルーチンの終了」を参照してください。
受信した要求の優先順位の確認
#include <stdio.h>
#include "atmi.h"
char *roundrobin();
PRINTER(pbuf)
TPSVCINFO *pbuf; /* 印刷バッファ */
{
char prname[20], ocmd[30]; /* プリンタ名、出力コマンド */
long rlen; /* 応答バッファの長さ */
int prio; /* 要求の優先順位 */
FILE *lp_pipe; /* パイプ・ファイルへのポインタ */
prio=tpgprio();
if (prio <= 20)
(void)strcpy(prname,"bigjobs"); /* 優先順位の低い (冗長的) ジョブを
大型コンピュータの中央
レーザ・プリンタに送信します。そこで
出力をソートし、
bin に保存します。 */
else if (prio <= 60)
(void)strcpy(prname,roundrobin()); /* ローカルの小型レーザ・プリンタの 1 つに
プリンタを順に割り当てます。
そのプリンタで直ちに出力されます。
プリンタの
リストに従って、roundrobin() が
実行されます。 */
else
(void)strcpy(prname,"hispeed");
/* ジョブを高速レーザ・
プリンタに割り当てます。
冗長出力を毎日行う人のために
予約されています。 */
(void)sprintf(ocmd, "lp -d%s", prname); /* lp(1) 出力コマンド */
lp_pipe = popen(ocmd, "w"); /* コマンドへのパイプの作成 */
(void)fprintf(lp_pipe, "%s", pbuf->data); /* 出力の印刷 */
(void)pclose(lp_pipe); /* パイプのクローズ */
if ((pbuf->flags & TPNOREPLY))
tpreturn(TPSUCCESS, 0, NULL, 0, 0);
rlen = strlen(prname) + 1;
pbuf->data = tprealloc(pbuf->data, rlen); /* 名前のために十分な領域を確保します。 */
(void)strcpy(pbuf->data, prname);
tpreturn(TPSUCCESS, 0, pbuf->data, rlen, 0);
char *
roundrobin()
{
static char *printers[] = {"printer1", "printer2", "printer3", "printer4"};
static int p = 0;
if (p > 3)
p=0;
return(printers[p++]);
}
![]() |
![]() |
![]() |
|
Copyright © 2001 BEA Systems, Inc. All rights reserved.
|