C言語を使用したOracle Tuxedo ATMIアプリケーションのプログラミング

     前  次    新規ウィンドウで目次を開く    PDFとして表示 - 新規ウィンドウ  Adobe Readerを入手 - 新規ウィンドウ
コンテンツはここから始まります

クライアントおよびサーバーへのリクエスト/レスポンスのコーディング

このトピックには次の項が含まれます:

 


リクエスト/レスポンス通信の概要

リクエスト/レスポンス通信モードでは、あるソフトウェア・モジュールが別のソフトウェア・モジュールにリクエストを送り、レスポンスを待ちます。最初のソフトウェア・モジュールがクライアント、2番目のソフトウェア・モジュールがサーバーとして動作するため、このモードはクライアント/サーバー相互作用とも呼ばれます。オンラインの銀行業務の多くは、リクエスト/レスポンス・モードでプログラミングされます。たとえば、残高照会のリクエストは、図6-1ように行われます。

  1. 顧客(クライアント)は、口座レコード管理システム(サーバー)に、残高照会のリクエストを送信します。
  2. 口座レコード管理システム(サーバー)は、指定された口座の残高を応答として顧客(クライアント)に送ります。
  3. 図6-1 オンライン銀行業務でのリクエスト/レスポンス通信


    オンライン銀行業務でのリクエスト/レスポンス通信

クライアント・プロセスがアプリケーションに参加し、バッファを割り当て、入力データ・リクエストをバッファに格納すると、そのプロセスはリクエスト・メッセージをサービス・サブルーチンに送信したり、応答メッセージを受信することができるようになります。

 


同期メッセージの送信

tpcall(3c)関数は、サービス・サブルーチンにリクエストを送信し、同期的に応答を待ちます。tpcall()関数の呼出しには、次のシグネチャを使用します。

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

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

表6-1 tpcall( )関数の引数
引数
説明
svc
アプリケーションで提供されるサービス名を指すポインタ。
idata
リクエストのデータ部分のアドレスを含むポインタ。このポインタは、tpalloc()の以前の呼出しで割り当てられた型付きバッファを参照しなければなりません。idatatype (および指定されている場合はsubtype)は、サービス・ルーチンで使用できるtype (および指定されている場合はsubtype)と合致する必要があります。タイプが合致しない場合、tperrnoTPEITYPEが設定され、関数の呼出しが失敗します。
データがリクエストされていない場合、idataにNULLポインタを設定します。この設定は、パラメータが無視されうることを意味します。リクエストでデータが送信されない場合、idataのバッファを割り当てる必要はありません。
ilen
idataで参照されるバッファ内のリクエスト・データの長さ。バッファが自己記述型の場合、つまりFMLFML32VIEWVIEW32X_COMMONX_C_TYPE、またはSTRING型バッファの場合、この引数にゼロを設定すると引数が無視されます。
*odata
応答を受信する出力バッファを指すポインタのアドレス。tpalloc()関数を使用して、出力バッファを割り当てておく必要があります。tpcall()から正常に制御が戻ったときに、応答メッセージにデータが含まれていないと、*olenにゼロが設定されます。ポインタと出力バッファの内容は変更されません。
リクエスト・メッセージと応答メッセージの両方に同じバッファを使用できます。その場合、*odataには、入力バッファを割り当てたときに返されたポインタのアドレスを設定します。このパラメータがNULLを指している場合は、エラーになります。
olen
応答データの長さを指すポインタ。このパラメータがNULLを指している場合は、エラーになります。
flags
フラグのオプション。論理演算子ORを使用すると、複数のフラグをリストできます。この値にゼロを設定すると、デフォルトの方法で通信が行われます。有効なフラグとデフォルト値については、『Oracle Tuxedo ATMI C言語関数リファレンス』のtpcall(3c)を参照してください。

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

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

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

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

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

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

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

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

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

例: リクエスト・メッセージと応答メッセージに同じバッファの使用

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

  1. サービスはb_idフィールドに対して問合せを実行します。ただし、このフィールドを上書きしません。
  2. アプリケーションは、balフィールドをゼロ、ermsgフィールドをNULL文字列に初期化して、サービスから返される値を受け取る準備をします。
  3. svc_name変数はリクエストされたサービス名、hdr_type変数はリクエストされた残高のタイプを示します。この例では、口座残高と窓口残高が示されます。
  4. リスト6-1 リクエスト・メッセージと応答メッセージに同じバッファの使用
    . . .
    /* Create buffer and set data pointer */

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

           /* Prepare aud structure */

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

           /* Do 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);
    . . .

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

リスト6-2は、tpcall()を呼び出した後、アプリケーションでバッファのサイズが変更されたかどうかを確認する一般的な方法を示しています。この例では、入力バッファと出力バッファは同じサイズである必要があります。

リスト6-2 応答バッファのサイズ変更の確認
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){ /* message buffer has grown */

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

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

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

リスト6-3 TPSIGRSTRTフラグを設定した同期メッセージの送信
     /* Do a tpcall to withdraw from first account */

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);
}
...
     /* Do a tpcall to deposit to second account */

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フラグを設定した同期メッセージの送信

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

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

注: 「TPNOTRANとTPNOREPLYフラグを設定した非同期メッセージの送信」では、同じ例を使用して非同期メッセージの呼出しを行っています。
リスト6-4 TPNOTRANフラグを設定した同期メッセージの送信
#include <stdio.h>
#include "atmi.h"

main()

{
char *rbuf; /* report buffer */
long r1len, r2len, r3len; /* buffer lengths of send, 1st reply,
and 2nd reply buffers for report */
join application

if (rbuf = tpalloc("STRING", NULL, 0) == NULL) /* allocate space for report */
   leave application and exit program
(void)strcpy(rbuf,
   "REPORT=accrcv DBNAME=accounts"); /* send parms of report */
r1len = strlen(rbuf)+1; /* length of request */

start transaction

if (tpcall("REPORT", rbuf, r1len, &rbuf,
   &r2len, 0) == -1) /* get report print stream */
   error routine
if (tpcall("PRINTER", rbuf, r2len, &rbuf,
   &r3len, TPNOTRAN) == -1) /* send report to printer */
   error routine
(void)printf("Report sent to %s printer\n",
   rbuf); /* indicate which printer */

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

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

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

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

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

リスト6-5 TPNOCHANGEフラグを設定した同期メッセージの送信
#include <stdio.h>
#include "atmi.h"
#include "rview1.h"

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

{
char *rbuf; /* report buffer */
struct rview1 *rrbuf; /* report reply buffer */
long rlen, rrlen; /* buffer lengths of send and reply
                          buffers for report */
if (tpinit((TPINIT *) tpinfo) == -1)
   fprintf(stderr, "%s: failed to join application\n", argv[0]);

if (rbuf = tpalloc("STRING", NULL, 0) == NULL) { /* allocate space for report */
   tpterm();
   exit(1);
}
                       /* allocate space for return buffer */
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; /* length of request */
                           /* get report in rview1 struct */
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();
}

 


非同期メッセージの送信

この項では、次の操作を行う方法について説明します。

この項で説明する非同期の処理は、ファンアウト並列処理と呼ばれます。クライアントのリクエストが複数のサービスに同時に分散(ファンアウト)されて処理が行われるからです。

このほかに、Oracle Tuxedoシステムでは、非同期処理としてパイプライン並列処理もサポートされています。この処理では、tpforward()関数を使用して1つのサービスから別のサービスに処理が渡されます(転送されます)。tpforward()関数については、「サーバーのコーディング」を参照してください。

非同期リクエストの送信

tpacall(3c)関数は、サービス・リクエストを送信し、直ちに制御を戻します。tpacall()関数の呼出しには、次のシグネチャを使用します。

int
tpacall(char *svc, char *data, long len, long flags)

表6-2は、tpacall()関数の引数を示しています。

表6-2 tpacall()関数の引数
引数
説明
svc
アプリケーションで提供されるサービス名を指すポインタ。
data
リクエストのデータ部分のアドレスを含むポインタ。このポインタは、tpalloc()の以前の呼出しで割り当てられた型付きバッファを参照しなければなりません。idatatype (および指定されている場合はsubtype)は、サービス・ルーチンで使用できるtype (および指定されている場合はsubtype)と合致する必要があります。タイプが合致しない場合、tperrnoTPEITYPEが設定され、関数の呼出しが失敗します。
データがリクエストされていない場合、dataにNULLポインタを設定します。この設定は、パラメータが無視されうることを意味します。リクエストでデータが信されていない場合は、dataのバッファを割り当てる必要はありません。
len
dataで参照されるバッファ内のリクエスト・データの長さ。バッファが自己記述型の場合、つまりFMLFML32VIEWVIEW32X_COMMONX_C_TYPE、またはSTRING型バッファの場合、この引数にゼロを設定すると引数が無視されます。
flags
フラグのオプション。論理演算子ORを使用すると、複数のフラグをリストできます。この値にゼロを設定すると、デフォルトの方法で通信が行われます。有効なフラグとデフォルト値については、『Oracle Tuxedo ATMI C言語関数リファレンス』の「tpacall(3c)」を参照してください。

tpacall()関数は、svcパラメータに指定されたサービスにリクエスト・メッセージを送信し、直ちに制御を戻します。呼出しが正常に終了すると、tpacall()関数は整数値を返します。この値は、関連する要求に対する正しい応答にアクセスするための記述子として使用されます。tpacall()がトランザクション・モードで実行されている場合(「グローバル・トランザクションのコーディング」を参照)、トランザクションのコミット時に未処理の応答が存在することはありません。つまり、あるトランザクションの範囲内では、リクエストごとにその応答が返されるので、最終的には対応する応答を必ず受信することになります。

flags引数にTPNOREPLYが設定されると、応答が必要ないことがtpacall()に通知されます。このフラグが設定されている場合、tpacall()の処理が正常に終了すると、応答記述子として0が返されます。以降の処理で、この値がtpgetrply()関数に渡されると、この値は無効になります。プロセスがトランザクション・モードのときにこのフラグを正しく使用するためのガイドラインについては、「グローバル・トランザクションのコーディング」を参照してください。

エラーが発生した場合、tpacall()-1を返し、tperrno(5)には発生したエラー条件が返されます。tpacall()が返すエラー・コードの多くは、tpcall()が返すエラー・コードと同じです。これらの関数のエラー・コードは、一方が同期呼出し、もう一方が非同期呼出しに基づいているという点が異なります。これらのエラーについては、「エラーの管理」を参照してください。

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

リスト6-6は、tpacall()TPNOTRANTPNOREPLYフラグを使用する方法を示しています。このコードは、「例: TPNOTRANフラグを設定した同期メッセージの送信」のコードと同じです。ただし、この場合は、PRINTERサービスからの応答は要求されていません。TPNOREPLYフラグとTPNOREPLYフラグの両方を設定することで、クライアントが応答を要求していないこと、およびPRINTERサービスが現在のトランザクションに参加しないことを示します。詳細は、「エラーの管理」を参照してください。

リスト6-6 TPNOTRANとTPNOREPLYフラグを設定した非同期メッセージの送信
#include <stdio.h>
#include "atmi.h"

main()

{
char *rbuf; /* report buffer */
long rlen, rrlen; /* buffer lengths of send, reply buffers for report */

join application

if (rbuf = tpalloc("STRING", NULL, 0) == NULL) /* allocate space for report */
error
(void)strcpy(rbuf, "REPORT=accrcv DBNAME=accounts");/* send parms of report */
rlen = strlen(rbuf)+1; /* length of request */

start transaction

if (tpcall("REPORT", rbuf, rlen, &rbuf, &rrlen, 0)
   == -1) /* get report print stream */
   error
if (tpacall("PRINTER", rbuf, rrlen, TPNOTRAN|TPNOREPLY)
   == -1) /* send report to printer */
   error

. . .
commit transaction
free buffer
leave application
}

例: 非同期リクエストの送信

以下のサンプル・コードは、銀行の総残高照会を行う非同期呼出しを示しています。銀行業務アプリケーションのデータは、複数のデータベース・サイトに分散されているので、各サイトに対してSQL問合せを実行する必要があります。その場合、データベース・サイトごとに支店番号が1つ選択され、そのサイトに対してABALまたはTBALサービスが呼び出されます。支店番号は実際のSQL問合せでは使用されませんが、この番号によってOracle Tuxedoシステムが適切なサイトにリクエストを送ることができるようになります。次のコードでは、サイトごとにforループがtpacall()を一度呼び出しています。

リスト6-7 非同期リクエストの送信
audv->balance = 0.0;
(void)strcpy(audv->ermsg, "");

for (i=0; i<NSITE; i++) {

  /* Prepare aud structure */

  audv->b_id = sitelist[i]; /* routing done on this field */

  /* Do tpacall */

  if ((cd[i]=tpacall(sname, (char *)audv, sizeof(struct aud), 0))
     == -1) {
     (void)fprintf (stderr,
        "%s: %s service request failed for site rep %ld\n",
        pgmname, sname, sitelist[i]);
        tpfree((char *)audv);
        return(-1);
  }
}

非同期応答の受信

サービス呼出しに対する応答は、tpgetrply(3c)関数を呼び出すと非同期的に受信できます。tpgetrply()関数は、tpacall()が以前に送信したリクエストに対する応答をキューから取り出します。

tpgetrply()関数の呼出しには、次のシグネチャを使用します。

int
tpgetrply(int *cd, char **data, long *len, long flags)

表6-3は、tpgetrply()関数の引数を示しています。

表6-3 tpgetrply( )関数の引数
引数
説明
cd
tpacall()が返す呼出し記述子を指すポインタ。
*data
応答を受信する出力バッファを指すポインタのアドレス。tpalloc()関数を使用して、出力バッファを割り当てておく必要があります。tpcall()から正常に制御が戻ったときに、応答メッセージにデータが含まれていないと、*dataにゼロが設定されます。ポインタと出力バッファの内容は変更されません。
リクエスト・メッセージと応答メッセージの両方に同じバッファを使用できます。その場合、odataには、入力バッファを割り当てたときに返されたポインタのアドレスを設定します。このパラメータがNULLを指している場合は、エラーになります。
len
応答データの長さを指すポインタ。このパラメータがNULLを指している場合は、エラーになります。
flags
フラグのオプション。論理演算子ORを使用すると、複数のフラグをリストできます。この値にゼロを設定すると、デフォルトの方法で通信が行われます。有効なフラグとデフォルト値については、『Oracle Tuxedo ATMI C言語関数リファレンス』の「tpcall(3c)」を参照してください。

デフォルトでは、この関数は、cdパラメータが参照する値に対応した応答を待ちます。応答を待っている間に、ブロッキング・タイムアウトが発生する場合があります。タイムアウトが発生するのは、tpgetrply()が失敗し、tperrno(5)TPETIMEが設定された場合です。ただし、flagsパラメータにTPNOTIMEが設定されている場合は除きます。

 


メッセージの優先度の設定および取得

2つのATMI呼び出し、tpsprio(3c)およびtpgprio(3c)を使用して、メッセージ要求の優先度を決定したり設定したりできます。この優先度に従って、サーバーがキューからリクエストを取り出します。つまり、最も優先度の高いリクエストが最初に取り出されます。

この項では、次の内容について説明します。

メッセージの優先度の設定

tpsprio(3c)関数を使用すると、メッセージ・リクエストの優先度を設定できます。

tpsprio()関数で優先度を設定できるのは、1つのリクエストだけです。つまり、tpcall()またはtpacall()によって次に送信されるリクエスト、またはサービス・サブルーチンによって次に転送されるリクエストだけです。

tpsprio()関数の呼出しには、次のシグネチャを使用します。

int
tpsprio(int prio, long flags);

表6-4は、tpsprio()関数の引数を示しています。

表6-4 tpsprio()関数の引数
引数
説明
prio
新しい優先度を示す整数値。この引数の持つ意味は、flagsパラメータによって異なります。flagsにゼロが設定されている場合、prioは相対値を示し、値の符号は現在の優先度を上げることまたは下げることを示します。ほかの値が設定されている場合、指定された値は絶対値を示し、prioには0 - 100の範囲の値を設定する必要があります。この範囲外の値を設定すると、値は50に設定されます。
flags
prioの値を相対値(0)または絶対値(TPABSOLUTE)のどちらの値として処理するのかを示すフラグ。デフォルトは相対値です。

以下のサンプル・コードは、TRANSFERサービスから引用したものです。このコードでは、TRANSFERサービスはクライアントとして動作し、tpcall()を使用してWITHDRAWALサービスに同期要求を送信しています。TRANSFERtpsprio()を呼び出してWITHDRAWALに対するリクエスト・メッセージの優先度を上げます。また、TRANSFERのキューを待機した後で、WITHDRAWALサービス(その後DEPOSITサービス)に対するリクエストがキューに格納されないようにします。

リスト6-8 リクエスト・メッセージの優先度の設定
/* increase the priority of withdraw call */
if (tpsprio(PRIORITY, 0L) == -1)
   (void)userlog("Unable to increase priority of withdraw\n");

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);
   tpreturn(TPFAIL, 0,transb->data, 0L, 0);
}

メッセージの優先度の取得

tpgprio(3c)関数を使用すると、メッセージ・リクエストの優先度を取得できます。

tpgprio()関数の呼出しには、次のシグネチャを使用します。

int
tpgprio();

リクエスタは、tpcall()またはtpacall()関数を呼び出した後にtpgprio()関数を呼び出して、リクエスト・メッセージの優先度を取得できます。リクエスタが関数を呼び出したがリクエストが送信されていない場合、関数は失敗して-1が返され、tperrno(5)TPENOENTが設定されます。tpgprio()の処理が成功すると、1 - 100の範囲内の整数値が返されます。100が最も高い優先度です。

tpsprio()関数を使用して優先度が明示的に設定されていない場合、メッセージの優先順として、要求を処理するサービス・ルーチンの優先度が設定されます。アプリケーション内では、リクエストを処理するサービスの優先度にデフォルト値の50が設定されます。ただし、システム管理者が別の値を指定している場合は除きます。

次のサンプル・コードは、非同期呼出しによって送信されたメッセージの優先度を確認する方法を示しています。

リスト6-9 送信後のリクエストの優先度の確認
#include <stdio.h>
#include "atmi.h"

main ()
{
int cd1, cd2; /* call descriptors */
int pr1, pr2; /* priorities to two calls */
char *buf1, *buf2; /* buffers */
long buf1len, buf2len; /* buffer lengths */

join application

if (buf1=tpalloc("FML", NULL, 0) == NULL)
   error
if (buf2=tpalloc("FML", NULL, 0) == NULL)
   error

populate FML buffers with send request

if ((cd1 = tpacall("service1", buf1, 0, 0)) == -1)
   error
if ((pr1 = tpgprio()) == -1)
   error
if ((cd2 = tpacall("service2", buf2, 0, 0)) == -1)
   error
if ((pr2 = tpgprio()) == -1)\
   error

if (pr1 >= pr2) { /* base the order of tpgetrplys on priority of calls */
        if (tpgetrply(&cd1, &buf1, &buf1len, 0) == -1)
           error
        if (tpgetrply(&cd2, &buf2, &buf2len, 0) == -1)
           error
}
else {
        if (tpgetrply(&cd2, &buf2, &buf2len, 0) == -1)
           error
        if (tpgetrply(&cd1, &buf1, &buf1len, 0) == -1)
           error
}
. . .
}

  先頭に戻る       前  次