5.5.3 リクエストの転送
tpforward(3c)
関数を使用すると、サービスは他の処理を行うために別のサービスにリクエストを転送できます。
tpforward()
関数の呼出しには、次のシグネチャを使用します:
void
tpforward(char *svc, char *data, long len, long flags)
次の表は、tpreturn()
関数の引数を示しています。
表5-3 tpreturn()関数の引数
引数 | 説明 |
---|---|
svc
|
リクエストが転送されるサービス名を指す文字型のポインタ。 |
data
|
クライアント・プロセスに返される応答メッセージを指すポインタ。メッセージ・バッファは、tpalloc() を使用して事前に割り当てられていることが必要です。SVCINFO 構造体のサービスに渡されたバッファと同じものを使用する場合は、バッファの割当ておよび解放について意識する必要はありません。この2つの処理は、システムで提供されるmain() 関数で行われます。このバッファは、tpfree() コマンドを使用しても解放できません。このコマンドを使用してバッファの解放を試みると失敗します。tprealloc() 関数を使用すると、バッファのサイズを変更できます。サービス・ルーチンに渡されたバッファとは別のバッファを使ってメッセージを返す場合、自分でそのバッファを割り当てる必要があります。アプリケーション側でtpreturn() 関数が呼び出されると、バッファは自動的に解放されます。応答メッセージを返す必要がない場合は、この引数にNULLポインタを設定します。
ノート: クライアントに応答を返す必要がない場合、つまりTPNOREPLY が設定されている場合、tpreturn() 関数はdata とlen 引数を無視してmain() に制御を戻します。
|
len
|
応答バッファの長さ。アプリケーションはこの引数の値に、tpcall() 関数のolen パラメータ、またはtpgetrply() 関数のlen パラメータを使用してアクセスできます。クライアントとして動作するプロセスは、この戻り値を使用して、応答バッファのサイズが大きくなったかどうか調べることができます。クライアントが応答を要求していて応答バッファにデータが存在していない場合、つまりdata 引数にNULLポインタが設定されている場合、クライアントのバッファを変更せずに長さがゼロの応答が送信されます。data 引数が指定されていない場合、この引数の値は無視されます。
|
flag
|
現在使用されていません。 |
tpforward()
は、サービス呼出しとは異なります。つまり、リクエストの転送元サービスでは、応答はリクエストされていません。応答を返すのは、リクエストの転送先サービスです。 このサービスを転送されたサービスが、リクエストの発信元プロセスに応答を返します。後者のサービスが、リクエストの発信元プロセスに応答を送信します。転送が連鎖的に行われる場合、最後のサーバーがtpreturn()
を呼び出して、要求の発信元であるクライアントに応答を返します。
次の図は、あるサービスから別のサービスにリクエストを転送したときのイベントの流れを示しています。ここでは、クライアントはtpcall()
関数を使用してリクエストを開始し、連鎖の最後のサービス(サービスSVC_C
)がtpreturn()
関数を使用して応答を返しています。
図5-1 リクエストの転送

サービス・ルーチンはtpsprio()
関数を使用して、クライアント・プロセスがリクエストを送るのと同じように、指定された優先度に従ってリクエストを転送できます。
プロセスがtpforward()
を呼び出すと、システムで提供されたmain()
に制御が戻り、サーバー・プロセスは別のリクエストを処理できるようになります。
ノート: クライアントとして動作するサーバー・プロセスが応答をリクエストする場合、このサーバーが自分自身からサービスをリクエストすることはできません。つまり、必要なサービスの唯一のインスタンスがリクエストを行っているサーバー・プロセスからのみ提供される場合、その呼出しは失敗して再帰呼出しができないことが示されます。ただし、TPNOREPLY
通信フラグが設定された状態でサービス・ルーチンが自分宛てにリクエストを送信または転送した場合、サービスは自分からの応答を待機しないので、呼出しは失敗しません。
tpforward()
呼出しを使用して、その呼出しを行った時点まで要求の処理が成功していたことを示すことができます。アプリケーション・エラーが検出されなかった場合、tpforward()
を呼び出します。エラーが検出された場合、rval
にTPFAIL
を設定してtpreturn()
を呼び出します。
次のリストは、ACCT
サーバーの一部であるOPEN_ACCT
サービス・ルーチンから引用したものです。この例は、tpforward()
を呼び出して、サービスがそのデータ・バッファをDEPOSIT
サービスに送る方法を示しています。このコードは、SQLCODE
をテストして、口座の挿入が成功したかどうかを調べています。新規口座の追加が成功した場合、支店レコードが更新されてその口座が反映され、データ・バッファがDEPOSIT
サービスに転送されます。失敗した場合、rval
にTPFAIL
が設定されてtpreturn()
が呼び出され、失敗を示すメッセージがフォーム上のステータス行に出力されます。
tpforward( )関数のリスト
...
/* set pointer to TPSVCINFO data buffer */
transf = (FBFR *)transb->data;
...
/* Insert new account record into ACCOUNT*/
account_id = ++last_acct; /* get new account number */
tlr_bal = 0.0; /* temporary balance of 0 */
EXEC SQL insert into ACCOUNT (ACCOUNT_ID, BRANCH_ID, BALANCE,
ACCT_TYPE, LAST_NAME, FIRST_NAME, MID_INIT, ADDRESS, PHONE) values
(:account_id, :branch_id, :tlr_bal, :acct_type, :last_name,
:first_name, :mid_init, :address, :phone);
if (SQLCODE != SQL_OK) { /* Failure to insert */
(void)Fchg(transf, STATLIN, 0,
"Cannot update ACCOUNT", (FLDLEN)0);
tpreturn(TPFAIL, 0, transb->data, 0L, 0);
}
/* Update branch record with new LAST_ACCT */
EXEC SQL update BRANCH set LAST_ACCT = :last_acct where BRANCH_ID = :branch_id;
if (SQLCODE != SQL_OK) { /* Failure to update */
(void)Fchg(transf, STATLIN, 0,
"Cannot update BRANCH", (FLDLEN)0);
tpreturn(TPFAIL, 0, transb->data, 0L, 0);
}
/* up the priority of the deposit call */
if (tpsprio(PRIORITY, 0L) == -1)
(void)userlog("Unable to increase priority of deposit\n");
/* tpforward same buffer to deposit service to add initial balance */
tpforward("DEPOSIT", transb->data, 0L, 0);
親トピック: サービス・ルーチンの終了