BEA Logo BEA Tuxedo Release 8.0

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

 

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

 


同期メッセージの送信

tpcall(3c) 関数は、サービス・サブルーチンに要求を送信し、同期的に応答を待ちます。tpcall() 関数の呼び出しには、次の文法を使用します。

int
tpcall(char *svc, char *idata, long ilen, char **odata, long *olen, long flags)

次の表は、tpcall() 関数の引数を示しています。

tpcall( ) 関数の引数

引数

説明

svc

アプリケーションで提供されるサービス名を指すポインタ。

idata

要求のデータ部分のアドレスを含むポインタ。このポインタは、tpalloc() の以前の呼び出しで割り当てられた型付きバッファを参照しなければなりません。idatatype (および指定されている場合は subtype) は、サービス・ルーチンで使用できる type (および指定されている場合は subtype) と合致する必要があります。タイプが合致しない場合、tperrnoTPEITYPE が設定され、関数の呼び出しが失敗します。

データが要求されていない場合、idata に NULL ポインタを設定します。NULL ポインタが設定されていると、パラメータは無視されます。要求でデータが送信されない場合、idata のバッファを割り当てる必要はありません。

ilen

idata で参照されるバッファ内の要求データの長さ。バッファが自己記述型の場合、つまり FMLFML32VIEWVIEW32X_COMMONX_C_TYPE、または STRING 型バッファの場合、この引数にゼロを設定すると引数が無視されます。

*odata

応答を受信する出力バッファを指すポインタのアドレス。tpalloc() 関数を使用して、出力バッファを割り当てておく必要があります。tpcall() から正常に制御が戻ったときに、応答メッセージにデータが含まれていないと、*olen にゼロが設定されます。ポインタと出力バッファの内容は変更されません。

要求メッセージと応答メッセージの両方に同じバッファを使用できます。その場合、*odata には、入力バッファを割り当てたときに返されたポインタのアドレスを設定します。このパラメータが NULL を指している場合は、エラーになります。

olen

応答データの長さを指すポインタ。このパラメータが NULL を指している場合は、エラーになります。

flags

フラグのオプション。論理演算子 OR を使用すると、複数のフラグをリストできます。この値にゼロを設定すると、デフォルトの方法で通信が行われます。有効なフラグとデフォルト値については、『BEA Tuxedo C リファレンス』 の tpcall(3c) を参照してください。

tpcall() は、応答を待ちます。

注記 tpcall() 関数の呼び出しは、tpacall() を呼び出した直後に tpgetrply() を呼び出すことと論理的には同じです。「非同期メッセージの送信」を参照してください。

要求は、svc で指定されたサービスの優先順位で送信されます。ただし、tpsprio() の呼び出しで明示的に異なる優先順位が設定されている場合は除きます。詳細については、「メッセージの優先順位の設定および取得」を参照してください。

tpcall() は整数を返します。失敗した場合、この整数値は -1 になり、tperrno(5)発生したエラー条件が返されます。有効なエラー・コードの詳細については、『BEA Tuxedo C リファレンス』の tpcall(3c) を参照してください。

注記 通信呼び出しはいろいろな原因で失敗します。そのほとんどは、アプリケーション・レベルで修正することができます。失敗の原因としては、アプリケーション定義のエラー (TPESVCFAIL)、戻り値の処理エラー (TPESVCERR)、型付きバッファのエラー (TPEITYPETPEOTYPE)、タイムアウト・エラー(TPETIME)、プロトコル・エラー (TPEPROTO) などがあります。エラーの詳細については、「エラーの管理」を参照してください。発生する可能性があるエラーについては、『BEA Tuxedo C リファレンス』の tpcall(3c) を参照してください。

BEA Tuxedo システムでは、割り当てられているバッファより大きなメッセージを受信した場合、メッセージ受信用バッファのサイズが自動的に変更されます。そのため、応答バッファのサイズが変更されたかどうかを確認する必要があります。

バッファの新しいサイズにアクセスするには、*olen パラメータに返されたアドレスを使用します。応答バッファのサイズが変更されたかどうかを確認するには、tpcall() を呼び出す前の応答バッファのサイズと、返された応答バッファの *olen の値とを比較します。*olen が元の値より大きい場合、バッファのサイズは大きくなっています。それ以外の場合、バッファのサイズは変更されていません。

呼び出しの後に odata に戻された値で、出力バッファを参照します。サイズの増加以外に、出力バッファが変更されている場合があるからです。要求バッファのサイズを確認する必要はありません。要求データは一度割り当てられると、調整されないからです。

注記 要求メッセージと応答メッセージに同じバッファを使用している場合に、バッファのサイズが変更されたために応答バッファを指すポインタが変更されたときは、入力バッファへのポインタは有効なアドレスを参照しなくなります。

例: 要求メッセージと応答メッセージに同じバッファを使用する

以下のコード例は、クライアント・プログラム audit.c で、要求メッセージと応答メッセージに同じバッファを使用して、同期呼び出しを行う方法を示しています。この例では、*audv メッセージ・バッファは要求情報と応答情報の両方を格納するように設定されているので、同じバッファを使用することができます。このコードでは、次の処理が行われます。

  1. サービスは b_id フィールドを照会します。ただし、このフィールドを上書きし ません。

  2. アプリケーションは、bal フィールドをゼロ、ermsg フィールドを NULL 文字列 に初期化して、サービスから返される値を受け取る準備をします。

  3. svc_name 変数は要求されたサービス名、hdr_type 変数は要求された残高のタ イプを示しします。この例では、口座残高と窓口残高が示されます。

    要求メッセージと応答メッセージに同じバッファを使用する

    . . .
    /* バッファを作成し、データ・ポインタを設定します。 */

    audv = (struct aud *)tpalloc("VIEW", "aud", sizeof(struct aud));

    /* aud 構造体を用意します。 */

    audv->b_id = q_branchid;
    audv->balance = 0.0;
    (void)strcpy(audv->ermsg, "");

    /* tpcall の実行 */

    if (tpcall(svc_name,(char *)audv,sizeof(struct aud),
    (char **)&audv,(long *)&audrl,0)== -1){
    (void)fprintf (stderr, "%s service failed\n %s:%s\n",
    svc_name, svc_name, audv->ermsg);
    retc = -1;
    }
    else
    (void)printf ("Branch %ld %s balance is $%.2f\n",
    audv->b_id, hdr_type, audv->balance);
    . . .

例: 応答バッファのサイズ変更の確認

次のコード例は、tpcall() を呼び出した後、アプリケーションでバッファのサイズが変更されたかどうかを確認する方法を示しています。この例では、入力バッファと出力バッファは同じサイズでなければなりません。

応答バッファのサイズ変更の確認

char *svc, *idata, *odata;
long ilen, olen, bef_len, aft_len;
. . .
if (idata = tpalloc("STRING", NULL, 0) == NULL)
error

if (odata = tpalloc("STRING", NULL, 0) == NULL)
error

place string value into idata buffer

ilen = olen = strlen(idata)+1;
. . .
bef_len = olen;
if (tpcall(svc, idata, ilen, &odata, &olen, flags) == -1)
error

aft_len = olen;

if (aft_len > bef_len){ /* メッセージ・バッファのサイズが大きくなっている場合 */

if (idata = tprealloc(idata, olen) == NULL)
error
}

例:TPSIGRSTRT フラグを設定した同期メッセージの送信

以下のコード例は、bankappXFER サーバ・プロセスの一部である TRANSFER サービスに基づいています。bankapp は、BEA Tuxedo システムに提供されている銀行業務のサンプル・アプリケーションです。TRANSFER サービスは、クライアントとして WITHDRAWAL および DEPOSIT サービスを呼び出します。アプリケーションはこの 2 つのサービスを呼び出すときに通信フラグを TPSIGRSTRT に設定して、トランザクションをコミットしやすいようにします。TPSIGRSTRT フラグは、シグナルの割り込みがあった場合に行う処理を指定します。通信フラグの詳細については『BEA Tuxedo C リファレンス』の tpcall(3c) を参照してください。

TPSIGRSTRT フラグを設定した同期メッセージの送信

     /* tpcall を実行して、振替元の口座から引き出します。 */

if (tpcall("WITHDRAWAL", (char *)reqfb,0, (char **)&reqfb,
(long *)&reqlen,TPSIGRSTRT) == -1) {
(void)Fchg(transf, STATLIN, 0,
"Cannot withdraw from debit account", (FLDLEN)0);
tpfree((char *)reqfb);
}
...
/* tpcall を実行して、振替先口座に振替金額を移動します。 */

if (tpcall("DEPOSIT", (char *)reqfb, 0, (char **)&reqfb,
(long *)&reqlen, TPSIGRSTRT) == -1) {
(void)Fchg(transf, STATLIN, 0,
"Cannot deposit into credit account", (FLDLEN)0);
tpfree((char *)reqfb);
}

例:TPNOTRAN フラグを設定した同期メッセージの送信

以下のコード例は、トランザクション・モードではない通信呼び出しを示しています。この呼び出しは、リソース・マネージャに関連していないサービスに対して行われます。サービスがトランザクションに参加するとエラーになります。アプリケーションは、データベース accounts から取得した情報に基づいて生成された売掛金勘定レポート accrcv を出力します。

サービス・ルーチン REPORT は指定されたパラメータを解釈し、完了したレポートのバイト・ストリームを応答として送信します。クライアントは、tpcall() を使用して PRINTER サービスにバイト・ストリームを送信します。PRINTER は、クライアントに近いプリンタにバイト・ストリームを送信します。そして、応答が印刷されます。最後に、PRINTER サービスはハードコピーの印刷が終了したことをクライアントに通知します。

注記 「TPNOTRAN と TPNOREPLY フラグを設定した非同期メッセージの送信」では、同じ例を使用して非同期メッセージの呼び出しを行っています。

TPNOTRAN フラグを設定した同期メッセージの送信

#include <stdio.h>
#include "atmi.h"

main()

{
char *rbuf; /* レポート用バッファ */
long r1len, r2len, r3len; /* レポート用の送信バッファ、最初の応答バッファ、
および 2 番目の応答バッファの長さ */
join application

if (rbuf = tpalloc("STRING", NULL, 0) == NULL) /* レポート用の領域の割り当て */
leave application and exit program
(void)strcpy(rbuf,
"REPORT=accrcv DBNAME=accounts"); /* レポートのパラメータの送信 */
r1len = strlen(rbuf)+1; /* 要求の長さ */

start transaction

if (tpcall("REPORT", rbuf, r1len, &rbuf,
&r2len, 0) == -1) /* レポート印刷ストリームの取得 */
error routine
if (tpcall("PRINTER", rbuf, r2len, &rbuf,
&r3len, TPNOTRAN) == -1) /* プリンタへのレポートの送信 */
error routine
(void)printf("Report sent to %s printer\n",
rbuf); /* プリンタの識別 */

terminate transaction
free buffer
アプリケーションを終了
}

注記 この例の error routine は、エラー・メッセージの出力、トランザクションの中止、割り当てられたバッファの解放、クライアントのアプリケーションからの分離、およびプログラムの終了が行われることを示しています。

例:TRNOCHANGE フラグを設定した同期メッセージの送信

以下のコード例では、最初に割り当てられたバッファ・タイプと同じタイプで応答メッセージを返す必要があることを示して、TPNOCHANGE 通信フラグを使用して厳密なタイプ・チェックを行う方法を示しています。この例では、REPORT というサービス・ルーチンを参照します。REPORT サービスは、「例:TPNOTRAN フラグを設定した同期メッセージの送信」でも使用されています。

このコード例では、クライアントが応答を VIEW 型バッファ rview1 で受信し、printf() 文でその内容を出力しています。厳密なタイプ・チェックのフラグ TPNOCHANGE が設定されているので、タイプ VIEW およびサブタイプ rview1 のバッファに応答が返されます。

厳密なタイプ・チェックを行うのは、REPORT サービス・サブルーチンでエラーが発生して、不適切なタイプの応答バッファが使用されることを防ぐためです。もう 1 つの理由は、依存関係にあるすべてのエリアで一貫していない変更が行わることを防ぐためです。たとえば、あるプログラマが REPORT サービスを変更してすべての応答を別の VIEW 形式で標準化したが、それを反映するためにクライアント・プロセスを変更しなかった場合などがあります。

TRNOCHANGE フラグを設定した同期メッセージの送信

#include <stdio.h>
#include "atmi.h"
#include "rview1.h"

main(argc, argv)
int argc;
char *argv[];

{
char *rbuf; /* レポート用バッファ */
struct rview1 *rrbuf; /* 応答バッファの通知 */
long rlen, rrlen; /* レポート用の送信バッファと
受信バッファの長さ */
if (tpinit((TPINIT *) tpinfo) == -1)
fprintf(stderr, "%s:failed to join application\n", argv[0]);

if (rbuf = tpalloc("STRING", NULL, 0) == NULL) { /* レポート用の領域の割り当て */
tpterm();
exit(1);
}
/* 応答バッファ用の領域の割り当て */
if (rrbuf = (struct rview1 *)tpalloc("VIEW", "rview1", sizeof(struct rview1)) \ == NULL{
tpfree(rbuf);
tpterm();
exit(1);
}
(void)strcpy(rbuf, "REPORT=accrcv DBNAME=accounts FORMAT=rview1");
rlen = strlen(rbuf)+1; /* 要求の長さ */
/* rview1 構造体でのレポートの取得 */
if (tpcall("REPORT", rbuf, rlen, (char **)&rrbuf, &rrlen, TPNOCHANGE) == -1) {
fprintf(stderr, "accounts receivable report failed in service call\n");
if (tperrno == TPEOTYPE)
fprintf(stderr, "report returned has wrong view type\n");
tpfree(rbuf);
tpfree(rrbuf);
tpterm();
exit(1);
}
(void)printf("Total accounts receivable %6d\n", rrbuf->total);
(void)printf("Largest three outstanding %-20s %6d\n", rrbuf->name1, rrbuf->amt1);
(void)printf("%-20s %6d\n", rrbuf->name2, rrbuf->amt2);
(void)printf("%-20s %6d\n", rrbuf->name3, rrbuf->amt3);
tpfree(rbuf);
tpfree(rrbuf);
tpterm();
}

 

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