BEA Logo BEA Tuxedo Release 8.0

  BEA ホーム  |  イベント  |  ソリューション  |  パートナ  |  製品  |  サービス  |  ダウンロード  |  ディベロッパ・センタ  |  WebSUPPORT

 

   Tuxedo ホーム   |   C 言語を使用した BEA Tuxedo アプリケーションのプログラミング   |   先頭へ   |   前へ   |   次へ   |   目次

 


サービスの定義

すべてのサービス・ルーチンは、1 つの引数、つまり TPSVCINFO 構造体を指すポインタを受け取る関数として定義する必要があります。TPSVCINFO 構造体は、atmi.h ヘッダ・ファイルに定義され、次の情報が含まれています。

char      name[32];
long flags;
char *data;
long len;
int cd;
int appkey;
CLIENTID cltid;

次の表は、TPSVCINFO データ構造体を示しています。

TPSVCINFO データ構造体

フィールド

説明

name

要求元プロセスがサービスの呼び出しに使用した名前。この名前は、サービス・ルーチンに対して指定されます。

flags

サービスがトランザクション・モードであるかどうか、または呼び出し元が応答を要求しているかどうかをサービスに通知するための値。サービスをトランザクション・モードにする方法については、「グローバル・トランザクションのコーディング」を参照してください。

TPTRAN フラグは、サービスがトランザクション・モードであることを示します。tpcall() または tpacall()flags パラメータに TPNOTRAN を設定してサービスを呼び出した場合、サービスは現在のトランザクションに参加できません。ただし、トランザクション・モードでサービスを実行することはできます。つまり、呼び出し元によって TPNOTRAN 通信フラグが設定されていても、TPTRANsvcinfo->flags に設定できます。このような状況の例については、「グローバル・トランザクションのコーディング」を参照してください。

tpacall()TPNOREPLY 通信フラグが設定されてサービスが呼び出された場合、flags メンバは TPNOREPLY に設定されます。ただし、呼び出されたサービスが、呼び出し元プロセスと同じトランザクションに含まれる場合、呼び出し元に応答を返す必要があります。

data

main() 内で tpalloc() を使用して既に割り当てられているバッファを指すポインタ。このバッファは、要求メッセージの受信に使用されます。応答メッセージの返信や要求メッセージの転送にも、このバッファを使用することをお勧めします。

len

data フィールドによって参照されるバッファ内の要求データの長さ。

cd

会話型通信での接続記述子。

appkey

アプリケーションで使用するために予約された値。アプリケーション固有の認証が設計に含まれている場合、認証サーバによって認証の成功または失敗を示す値、およびクライアント認証キーが返される必要があります。認証サーバは、クライアントがアプリケーションに参加するときに呼び出されます。BEA Tuxedo システムは、appkey をクライアントのために保持し、このフィールドに格納して以降のサービス要求に情報を渡します。appkey がサービスに渡されたときは、クライアントの認証は終了しています。ただし、サービス内で appkey フィールドを使用して、サービスを呼び出したユーザ、またはそのユーザに関するそのほかのパラメータを識別できます。

このフィールドが使用されていない場合、デフォルト値の -1 が割り当てられます。

cltid

クライアントの識別子が保持された CLIENTID 型の構造体。この構造体は変更できません。

プロセスが 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 パラメータに VIEWsubtypeaud が設定されています。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++]);
}

 

先頭へ戻る 前のトピックへ 次のトピックへ