3 Oracle Tuxedo /QのC言語プログラミング
このトピックには、次の項があります。
3.1 概要
ここでは、キューへのメッセージの登録とキューからのメッセージの取出しを行うATMI C言語関数tpenqueue(3c)、tpdequeue(3c)、およびいくつかの補助関数の使用方法について説明します。
親トピック: Oracle Tuxedo /QのC言語プログラミング
3.2 前提知識
キュー式メッセージ機能機能を使用するクライアント・プログラムまたはサーバー・プログラムをコーディングするOracle TUXEDOプログラマには、Oracle Tuxedo ATMIにバインドされたC言語についての知識が必要です。Oracle Tuxedoプログラミングに関する全般的な説明については、『C言語を使用したOracle Tuxedo ATMIアプリケーションのプログラミング』を参照してください。ATMI関数の詳細は、『Oracle Tuxedo ATMI C言語関数リファレンス』を参照してください。
親トピック: Oracle Tuxedo /QのC言語プログラミング
3.3 リクエストの発信元
Oracle Tuxedo /Qのキューにメッセージを登録する呼出しは、アプリケーションに関連付けられているあらゆるクライアント・プロセスまたはサーバー・プロセスから行うことができます。次のものが含まれます:
- キュー・スペースと同じマシン、またはネットワーク上の別のマシンにあるクライアントまたはサーバー。
- 会話型プログラム。ただし、キュー(または、TMQUEUE(5)サーバー)との会話接続は確立できません。
- サーバー側の代理プロセスを介するワークステーション・クライアント。管理インタフェースも完全にサーバー側にあります。
親トピック: Oracle Tuxedo /QのC言語プログラミング
3.4 デフォルトの場合の注意事項
ここでは、Oracle Tuxedo /Qプログラミングについて、図「キュー・サービスの呼出し」の主に左側部分について説明します。この図では、クライアント(または、クライアントとして機能するプロセス)はtpenqueue(3c)を呼び出し、TMQUEUE(5)サーバーを通して使用できるキュー・スペースを指定して、メッセージをキューに登録しています。クライアントは、その後、TMQUEUEへのtpdequeue(3c)呼出しを介して、応答を取得します。
図「キュー・サービスの呼出し」では、キューに入れられたメッセージが、サーバーTMQFORWARD(5)によってキューから取り出され、処理のためにtpcall(3c)を介してアプリケーション・サーバーに送信されています。tpcall()に対する応答が受信されると、TMQFORWARDは応答メッセージをキューに登録します。TMQFORWARDの主な目的は、キュー・スペースと既存のアプリケーション・サービスとの間にインタフェースを提供することです。そのため、アプリケーションにコードを追加する必要はありません。そのため、ここでは、クライアントとキュー・スペースとの間の処理を中心に説明します。
キュー機能の使い方を簡単に示すサンプルがソフトウェアに提供されています。詳細は、「サンプル・アプリケーション」を参照してください。
関連項目:
- 「第3c項 - C関数」のtpenqueue(3c)、tpdequeue(3c)、およびtpcall(3c)
- 「第5項 - ファイル形式、データ記述、MIBおよびシステム・プロセス・リファレンス」のTMQUEUE(5)およびTMQFORWARD(5)
親トピック: Oracle Tuxedo /QのC言語プログラミング
3.5 メッセージのキューへの登録
次は、tpenqueue()の構文です。
#include <atmi.h>
int tpenqueue(char *qspace, char *qname, TPQCTL *ctl,
char *data, long len, long flags)
tpenqueue()
が呼び出されると、qspace
で識別されるキュー・スペース内のqname
キューにメッセージを格納するようにシステムが指示されます。メッセージはdataが指すバッファ内にあり、その長さはlen
で示されます。flagsにビット設定を行うと、システムにtpenqueue()
呼出しの処理方法が通知されます。登録されたメッセージおよび応答の処理方法のさらに詳しい情報は、ctl
が指すTMQCTL
構造体で定義されます。
3.5.1 tpenqueue(3c)の引数
tpenqueue(3c)の処理を制御するいくつかの重要な引数があります。その一部について、以下に説明します。
- tpenqueue(): TPQUEDEF-REC引数内のQSPACE
- tpenqueue(): TPQUEDEF-REC引数内のQNAME
- tpenqueue(): TPTYPE-REC引数内のDATA-RECおよびLEN
- tpenqueue(): Flags引数
親トピック: メッセージのキューへの登録
3.5.1.1 tpenqueue(): TPQUEDEF-REC引数内のQSPACE
qspace
は、管理者によってすでに作成されたキュー・スペースを識別します。サーバーが構成ファイルのSERVERS
セクションで定義されている場合、そのサーバーが提供するサービス名は、実際のキュー・スペース名(GROUPS
セクションのOPENINFO
パラメータの一部として指定されます)の別名になります。たとえば、アプリケーションがサーバーTMQUEUE
を使用する場合、qspace
引数が指す値は、TMQUEUE
が通知するサービス名になります。サービス名の別名が何も定義されていない場合、デフォルトのサービス名はサーバー名TMQUEUE
と同じになります。その場合、構成ファイルには次の内容が記述されています。
TMQUEUE
SRVGRP = QUE1 SRVID = 1
GRACE = 0 RESTART = Y CONV = N
CLOPT = "-A"
または
CLOPT = "-s TMQUEUE"
サーバー・グループQUE1
のエントリには、OPENINFO
パラメータを使用して、リソース・マネージャ、デバイスのパス名、およびキュー・スペース名を指定します。クライアント・プログラムにおけるqspace
引数は、次のように記述されます。
if (tpenqueue("TMQUEUE", "STRING", (TPQCTL *)&qctl,
(char *)reqstr, 0,0) == -1) {
Error checking
}
「TMQUEUE(5)」リファレンス・ページの例では、サーバーを作成して構成ファイルで指定する際に、サービスの別名を指定する方法が示されています。「サンプル・アプリケーション」のサンプル・プログラムでも、サービスの別名が指定されています。
親トピック: tpenqueue(3c)の引数
3.5.1.2 tpenqueue(): TPQUEDEF-REC引数内のQNAME
キュー・スペース内で、キューを使用してサービスを呼び出している場合、メッセージ・キューはリクエストを処理できるアプリケーション・サービスに従って命名されます。qname
は、そのようなアプリケーション・サービスを指すポインタです。それ以外の場合、qname
は、アプリケーション(メッセージをキューに登録したアプリケーション、または別のアプリケーション)によってキューから取り出されるまで、メッセージを格納しておく場所を単に示す名前です。
親トピック: tpenqueue(3c)の引数
3.5.1.3 tpenqueue(): TPTYPE-REC引数内のDATA-RECおよびLEN
dataは、処理対象のメッセージが格納されたバッファを指すポインタです。そのバッファは、tpalloc(3c)を呼び出して割り当てられたものであることが必要です。len
は、メッセージの長さを指定します。Oracle Tuxedoのバッファ・タイプには、メッセージの長さを指定する必要がないもの(FMLなど)もあります。その場合、len
は無視されます。dataはNULLにすることもできます。その場合、len
は無視され、メッセージはデータ部分なしでキューに登録されます。
親トピック: tpenqueue(3c)の引数
3.5.1.4 tpenqueue(): Flags引数
flags
の値は、tpenqueue()
呼出しの処理方法をOracle Tuxedoシステムに通知するために使用されます。次は、有効なフラグです:
-
TPNOTRAN
- 呼出し側がトランザクション・モードにあり、このフラグが設定されていると、メッセージは呼出し側と同じトランザクション内ではキューに登録されません。このフラグを設定するトランザクション・モードの呼出し側は、メッセージをキューに登録するときに、やはりトランザクション・タイムアウトの影響を受けます(それ以外はなし)。キューへのメッセージの登録が失敗した場合、呼出し側のトランザクションは影響されません。
-
TPNOBLOCK
- ブロッキング状態が存在する場合、メッセージはキューに登録されません。このフラグが設定されていて、メッセージの転送先である内部バッファがいっぱいであるなどのブロッキング条件が存在する場合には、呼出しは異常終了し、tperrno(5)に
TPEBLOCK
が設定されます。このフラグが設定されていて、ターゲットのキューが別のアプリケーションによって排他的にオープンされているなどのブロッキング条件が存在する場合には、呼出しは失敗してtperrno()
にTPEDIAGNOSTIC
が設定され、TPQCTL
構造体の診断フィールドはQMESHARE
に設定されます。後者の場合、Oracle Tuxedoシステム以外のOracle製品に基づくほかのアプリケーションが、キューイング・サービスAPI (QSAPI)を使用して読取りと書き込み、またはそのいずれかを排他的に行うためにキューをオープンしています。 -
TPNOTIME
- このフラグを設定すると、呼出し側は無制限にブロックでき、ブロッキング・タイムアウトが適用されなくなります。ただし、トランザクション・タイムアウトは発生する可能性があります。
-
TPSIGRSTRT
- このフラグが設定されていると、基底のシステム・コールがシグナルによって中断された場合、中断されたシステム・コールが再度呼び出されます。このフラグが設定されていないときにシグナルによってシステム・コールが中断されると、呼出しは異常終了し、tperrno(5)は
TPGOTSIG
に設定されます。
ノート:
「第5項 - ファイル形式、データ記述、MIBおよびシステム・プロセス・リファレンス」のtperrno(5)親トピック: tpenqueue(3c)の引数
3.5.2 TPQCTL構造体
tpenqueue()の3番目の引数は、TPQCTL型の構造体へのポインタです。TPQCTL構造体には、アプリケーションで使用されるメンバーとOracle Tuxedoシステムで使用されるメンバーがあり、アプリケーション・プログラムとキュー式メッセージ機能間の両方向でパラメータがやり取りされます。tpenqueue()を呼び出すクライアントは、フラグを設定して、システム側で入力する必要のあるフィールドをマークします。この構造体は、tpdequeue()でも使用され、一部のフィールドは、アプリケーションがこの関数を呼び出すまで使用されません。この構造体全体を次のリストに示します:
リスト tpqctl_t構造体
#define TMQNAMELEN 127
#define TMMSGIDLEN 32
#define TMCORRIDLEN 32
struct tpqctl_t { /* control parameters to queue primitives */
long flags; /* indicates which of the values are set */
long deq_time; /* absolute/relative time for dequeuing */
long priority; /* enqueue priority */
long diagnostic; /* indicates reason for failure */
char msgid[TMMSGIDLEN]; /* ID of message before which to queue */
char corrid[TMCORRIDLEN]; /* correlation ID used to identify message */
char replyqueue[TMQNAMELEN+1]; /* queue name for reply message */
char failurequeue[TMQNAMELEN+1]; /* queue name for failure message */
CLIENTID cltid; /* client identifier for originating client */
long urcode; /* application user-return code */
long appkey; /* application authentication client key */
long delivery_qos; /* delivery quality of service */
long reply_qos; /* reply message quality of service */
long exp_time; /* expiration time */
};
typedef struct tpqctl_t TPQCTL;
以下は、tpenqueue()
の入力情報を制御するflagsパラメータの有効なフラグです。
-
TPNOFLAGS
- フラグおよび値は設定されません。制御構造体から情報は取得されません。構造体のフィールドに値を設定しないことは、
TPNOFLAGS
を設定することと同じです。 -
TPQTOP
- このフラグを設定すると、キューの順序付けは無効になり、メッセージはキューの先頭に登録されます。このリクエストは、順序付けを無効にしてメッセージをキューの先頭に登録するようにキューが設定されているかどうかによって、使用できない場合があります。
TPQTOP
とTPQBEFOREMSGID
は、相互に排他的なフラグです。 -
TPQBEFOREMSGID
- このフラグを設定すると、キューの順序付けが無効になり、メッセージは
ctl->msgid
によって識別されるメッセージの前に登録されます。このリクエストは、順序付けを無効にするようにキューが設定されているかどうかによって、使用できない場合があります。TPQTOP
とTPQBEFOREMSGID
は、相互に排他的なフラグです。メッセージ識別子の値は32バイト全体が意味を持つので、ctl->msgid
で識別される値は、たとえばNULL文字を埋め込むなどして、完全に初期化する必要があります。 -
TPQTIME_ABS
- このフラグが設定されていると、
ctl->deq_time
で指定された時間の経過後、メッセージが処理されます。deq_time
は絶対時間の値であり、time(2)、mktime(3C)
(アプリケーションで使用可能な場合)、あるいはgp_mktime(3c) (Oracle Tuxedoシステムに用意されている場合)によって生成されます。ctl->deq_time
に設定される値は、世界協定時(UTC) 1970年1月1日00:00:00から経過した秒数です。絶対時間は、キュー・マネージャ・プロセスが存在するマシン・クロックに基づいて設定されます。TPQTIME_ABS
とTPQTIME_REL
は、相互に排他的なフラグです。 -
TPQTIME_REL
- このフラグが設定されていると、キューへの登録が完了してからの相対時間の経過後、メッセージが処理されます。
ctl->deq_time
は、キューへの登録が完了してから、送信されたメッセージが処理されるまでの遅延秒数を指定します。TPQTIME_ABS
とTPQTIME_REL
は、相互に排他的なフラグです。 -
TPQPRIORITY
- このフラグが設定されていると、リクエストがキューに登録されるときの優先度が
ctl->priority
に格納されます。優先度は、1から100以下の範囲である必要があります。優先度によって順序付けられたキューでは、数値が高いほど優先度も高くなり、高い数値のメッセージが低い数値のメッセージより先にキューから取り出されます。優先度によって順序付けられていないキューの場合、値は情報にすぎません。 -
TPQCORRID
- このフラグが設定されている場合、リクエストがtpdequeue(3c)によってキューから取り出されるときに、
ctl->corrid
に指定された相関識別子の値を使用できます。この識別子は、キューに登録されたすべての応答メッセージまたは異常終了メッセージに付加されるので、アプリケーションは応答を特定のリクエストに結び付けることができます。相関識別子の値は32バイト全体が意味を持つので、ctl->corrid
に指定される値は、たとえばNULL文字を埋め込むなどして、完全に初期化する必要があります。 -
TPQREPLYQ
- このフラグが設定されていると、
ctl->replyqueue
に指定された応答キューが、キューに入れられたメッセージに関連付けられます。メッセージへの応答はすべて、リクエスト・メッセージと同じキュー・スペース内の、指定されたキューに登録されます。この文字列はNULLで終了する必要があります(長さは最大127文字)。サービスに対する応答が生成されても、応答キューが指定されていないか存在しない場合は、その応答は削除されます。 -
TPQFAILUREQ
- このフラグが設定されていると、
ctl->failurequeue
に指定されている異常終了キューが、キューに入れられたメッセージに関連付けられます。(1)キューに登録されたメッセージがTMQFORWARD()
によって処理され、(2)TMQFORWARD
が-dオプションで開始され、さらに(3)サービスが失敗してNULL以外の応答を戻す場合は、その応答と関連するtpurcode
によって構成される失敗メッセージが、元のリクエスト・メッセージと同じキュー・スペース内で指定されたキューに登録されます。この文字列はNULLで終了する必要があります(長さは最大127文字)。 -
TPQDELIVERYQOS、TPQREPLYQOS
TPQDELIVERYQOS
フラグが設定されていると、ctl‑>delivery_qos
で指定されたフラグにより、メッセージの配信サービスの品質が制御されます。その場合、相互に排他的な3つのフラグTPQQOSDEFAULTPERSIST、TPQQOSPERSISTENT
、TPQQOSNONPERSISTENT
のいずれかをctl‑>delivery_qos
に設定しなければなりません。TPQDELIVERYQOS
フラグが設定されていない場合、ターゲットのキューのデフォルトの配信ポリシーがメッセージに対するサービスの配信品質を指定します。-
TPQEXPTIME_ABS
- このフラグが設定されていると、メッセージに有効期限の絶対時間が適用されます。これは、キューからメッセージが削除される絶対時間です。
-
TPQEXPTIME_REL
- このフラグが設定されていると、メッセージに有効期限の相対時間が適用されます。これは、メッセージがキューに到達してから、キューから削除されるまでの秒数です。有効期限の相対時間は、
ctl‑>exp_time
に格納された値で示されます。 -
TPQEXPTIME_NONE
- このフラグが設定されていると、キューのデフォルトのポリシーに有効期限の時間が含まれている場合でも、メッセージの有効期限が切れることはありません。
また、TPQCTL
のurcode
フィールドにユーザー戻りコードを設定することができます。この値は、メッセージをキューから取り出すためにtpdequeue(3c)を呼び出すアプリケーションに返されます。
tpenqueue()からの出力では、次のフィールドがTPQCTL構造体に設定されます:
long flags; /* indicates which of the values are set */
char msgid[32]; /* ID of enqueued message */
long diagnostic; /* indicates reason for failure */
tpenqueue().からの出力情報を制御するflagsパラメータの有効なビットの一覧を次に示しますtpenqueue()の呼出し時にこのフラグがオンになっていると、/QサーバーTMQUEUE(5)は、構造体の対応する要素にメッセージ識別子を移入します。tpenqueue()
の呼出し時にこのフラグ・ビットをオフにしていると、TMQUEUE()
によって構造体の関連要素にメッセージ識別子は設定されません。
-
TPQMSGID
- このフラグが設定されている場合に、
tpenqueue()
の呼出しが成功すると、メッセージ識別子がctl->msgid
に格納されます。メッセージ識別子の値は32バイト全体が意味を持つので、ctl->msgid
に格納される値は、たとえばNULL文字を埋め込むなどして、完全に初期化する必要があります。初期化に使用される実際の埋め込み文字は、Oracle Tuxedo /Qコンポーネントのリリースによって異なります。
制御構造体の残りのメンバーは、tpenqueue()
への入力に使用されません。
tpenqueue()
の呼出しが異常終了してtperrno(5)にTPEDIAGNOSTIC
が設定された場合、失敗の原因を示す値がctl->diagnostic
に返されます。可能な値は次のとおりです:
-
[QMEINVAL]
- 無効なフラグ値が指定されています。
-
[QMEBADRMID]
- 無効なリソース・マネージャ識別子が指定されています。
-
[QMENOTOPEN]
- リソース・マネージャが現在オープンされていません。
-
[QMETRAN]
- トランザクション・モードで、または
TPNOTRAN
フラグを設定して呼出しが行われ、キューにメッセージを登録するトランザクションの開始を試みたときに、エラーが発生しました。この診断は、Oracle Tuxedoリリース7.1以降のキュー・マネージャからは返されません。 -
[QMEBADMSGID]
- 無効なメッセージ識別子が指定されています。
-
[QMESYSTEM]
- システム・エラーが発生しました。エラーの正確な性質がログ・ファイルに書き込まれます。
-
[QMEOS]
- オペレーティング・システムのエラーが発生しました。
-
[QMEABORTED]
- 操作が中断されました。中断された操作がグローバル・トランザクション内で実行されていた場合、グローバル・トランザクションは「ロールバックのみ」とマークされます。それ以外の場合、キュー・マネージャは操作を中断します。
-
[QMEPROTO]
- トランザクションの状態がアクティブではないときに、キューへの登録が行われました。
-
[QMEBADQUEUE]
- 無効または削除されたキューの名前が指定されています。
-
[QMENOSPACE]
- キュー上に領域がないなどリソース不足が原因で、サービスの品質(永続的な記憶域または非永続的な記憶域)が指定されたメッセージがキューに登録されませんでした。次のいずれかのリソース設定を超えると、
QMENOSPACE
が返されます。(1)キュー・スペースに割り当てられたディスク容量(永続的)、(2)キュー・スペースに割り当てられたメモリー容量(非永続的)、(3)同時にアクティブ状態になるトランザクションの最大数(キュー・スペースで許容される数であることが必要です)、(4)キュー・スペースに一度に入れることができる最大メッセージ数、(5)キューイング・サービス・コンポーネントが処理できる並列アクションの最大数、または(6)キューイング・サービス・コンポーネントを同時に使用できる認証されたユーザーの最大数。 -
[QMERELEASE]
- 新機能がサポートされていないバージョンのOracle Tuxedoシステムのキュー・マネージャに対して、メッセージのキューへの登録が試みられました。
-
[QMESHARE]
- 指定されたキューのメッセージの登録時に、そのキューが別のアプリケーションによって排他的にオープンされています。Oracle Tuxedoシステム以外のOracle製品ベースのアプリケーションが、キューイング・サービスAPI (QSAPI)を使用して読取りおよび書込みを排他的に行うため、キューをオープンしています。
関連項目:
- 「第3c項 - C関数」のgp_mktime(3c)、tpdequeue(3c)
- 「第5項 - ファイル形式、データ記述、MIBおよびシステム・プロセス・リファレンス」のTMQUEUE(5)およびtperrno(5)
親トピック: メッセージのキューへの登録
3.5.2.1 キューの順序の無効化
キューの作成時に、管理者がtpenqueue()
呼出しでキュー上のメッセージの順序を無効にできるようにした場合、次の2つの方法でこの機能を利用できます。この2つの方法は、相互に排他的です。メッセージをキューの先頭に配置するには、flagsがTPQTOP
を含むように設定します。または、メッセージを特定のメッセージの前に配置するには、flags
がTPQBEFOREMSGID
を含むように設定し、直後のメッセージのIDをctl->msgid
に設定します。これは、前の呼出しからのメッセージIDがここで使用できるように保存されたことが前提になります。管理者は、キューでサポートされている方法を通知する必要があります。キューは、この2つのいずれかまたは両方を使用できるように、あるいはどちらも使用できないように作成できます。
親トピック: TPQCTL構造体
3.5.2.2 キューの優先度の無効化
ctl->priority
に値を設定して、メッセージの優先度を指定することができます。この値は、1から100までの範囲でなければなりません。数値が高いほど優先度が高くなります。キューの順序付けパラメータの中にpriorityが含まれていない場合、ここで優先度を設定しても取出しの順序には影響しません。ただし、優先度の値は保持されるので、メッセージがキューから取り出されるときに検査されます。
親トピック: TPQCTL構造体
3.5.3 メッセージの使用可能時間の設定
deq_time
に、絶対時間またはキューへの登録が完了してからの相対時間として、メッセージが処理されるまで時間を指定できます。flagsに、TPQTIME_ABS
またはTPQTIME_REL
のいずれかを設定して、値の処理方法を指定できます。キューは、timeを順序付けの基準として作成することができます。その場合、メッセージは使用可能時間によって順序付けされます。
Oracle Tuxedo /Qには、gp_mktime(3c)
関数が用意されています。この関数は、tm
構造体の日付と時刻を1970年1月1日からの経過秒数に変換します。time(2)
およびmktime(3C)
関数をgp_mktime(3c)
のかわりに使用することもできます。値は、time_t
型(typedef'd
で指定されたlong型)で返されます。キューからメッセージが取り出される絶対時間を設定するには、次の手順に従います。ここでは、2001年12月9日正午12:00を使用します。
-
使用する日時の値を
tm
構造体に入力します。#include <stdio.h> #include <time.h> static char *const wday[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "-unknown-" }; struct tm time_str; /*...*/ time_str.tm_year = 2001 - 1900; time_str.tm_mon = 12 - 1; time_str.tm_mday = 9; time_str.tm_hour = 12; time_str.tm_min = 0; time_str.tm_sec = 1; time_str.tm_isdst = -1;
gp_mktime
を呼び出してdeq_time
に値を代入し、flagsを設定して絶対時間が提供されることを示します。#include <atmi.h> TPQCTL qctl; if ((qctl->deq_time = (long)gp_mktime(&time_str)) == -1) { /* check for errors */ } qctl->flags = TPQTIME_ABS
tpenqueue()
を呼び出しますif (tpenqueue(qspace, qname, qctl, *data,*len,*flags) == -1) { /* check for errors */ }
キューからメッセージを取り出す相対時間(たとえば、キューへの登録操作の完了後nnn
秒)を指定する場合、deq_time
に秒数を指定し、flagsにTPQTIME_REL
を設定します。
ノート:
「第3c項 - C関数」のgp_mktime(3c)親トピック: メッセージのキューへの登録
3.5.4 tpenqueue()とトランザクション
tpenqueue()
の呼出し側がトランザクション・モードにある場合に、TPNOTRAN
が設定されていないと、キューへの登録は呼出し側のトランザクション内で行われます。呼出し側は、tpenqueue()が成功したか失敗したかによって、メッセージがキューに登録されたかどうかを判断できます。呼出しが正常に行われると、メッセージがキューに登録されたことが保証されます。呼出しが失敗すると、メッセージがキューに登録された部分も含めて、トランザクションがロールバックされます。
tpenqueue()
の呼出し側がトランザクション・モードにない場合、またはTPNOTRAN
が設定されている場合、メッセージは呼出し側のトランザクションとは別のトランザクションでキューに登録されます。tpenqueue()への呼出しが正常な戻り値を返した場合、メッセージがキューに登録されたことが保証されます。tpenqueue()
の呼出しが通信エラーまたはタイムアウトによって失敗した場合は、その障害がメッセージ登録の前に発生したのか後に発生したのか、呼出し側には判断できません。
ノート:
呼出し側がトランザクション・モードにないときにTPNOTRAN
を指定しても意味がありません。
親トピック: メッセージのキューへの登録
3.6 メッセージのキューからの取出し
次は、tpdequeue()
の構文です。
#include <atmi.h>
int tpdequeue(char *qspace, char *qname, TPQCTL *ctl, \ char **data, long *len, long flags)
この呼出しが行われると、qspaceで識別されるキュー・スペース内のqname
キューからメッセージを取り出すようにシステムが指示されます。メッセージは、バッファ(tpalloc(3c)によって最初に割り当てられた)内の*data
によって指定されたアドレスに配置されます。lenはデータの長さを指定します。tpdequeue()
から返されたlen
が0の場合、そのメッセージにはデータ部分がないことを示します。flags
でビット設定を使用すると、システムにtpdequeue()
呼出しの処理方法が通知されます。ctl
が指すTPQCTL
構造体には、この呼出しの処理方法についての詳細な情報が記述されます。
- tpdequeue(3c)の引数
- TPQCTL構造体
- TPQWAITの使用
- TMQFORWARDサービス使用時のエラー処理
- TMQFORWARDを通して呼び出されたサービスからの応答をキューから取り出す手順
親トピック: Oracle Tuxedo /QのC言語プログラミング
3.6.1 tpdequeue(3c)の引数
tpdequeue(3c)の処理を制御するいくつかの重要な引数があります。その一部について、以下に説明します。
親トピック: メッセージのキューからの取出し
3.6.1.1 tpdequeue(): qspace引数
qspace
は、管理者によってすでに作成されたキュー・スペースを識別します。TMQUEUE
サーバーが構成ファイルのSERVERS
セクションで定義されている場合、そのサーバーが提供するサービス名は、実際のキュー・スペース名(GROUPS
セクションのOPENINFO
パラメータの一部として指定されます)の別名になります。たとえば、アプリケーションがサーバーTMQUEUE
を使用する場合、qspace
引数が指す値は、TMQUEUE
が通知するサービス名になります。サービス名の別名が何も定義されていない場合、デフォルトのサービス名はサーバー名TMQUEUE
と同じになります。その場合、構成ファイルには次が記述されています。
TMQUEUE
SRVGRP = QUE1 SRVID = 1
GRACE = 0 RESTART = Y CONV = N
CLOPT = "-A"
or
CLOPT = "-s TMQUEUE"
サーバー・グループQUE1
のエントリには、OPENINFO
パラメータを使用して、リソース・マネージャ、デバイスのパス名、およびキュー・スペース名を指定します。クライアント・プログラムにおけるqspace
引数は、次のように記述されます。
if (tpdequeue("TMQUEUE", "REPLYQ", (TPQCTL *)&qctl,
(char **)&reqstr, &len,TPNOTIME) == -1) {
Error checking
}
「TMQUEUE(5)」リファレンス・ページの例では、サーバーを作成して構成ファイルで指定する際に、サービスの別名を指定する方法が示されています。「サンプル・アプリケーション」のサンプル・プログラムでも、サービスまたはキュー・スペース名の別名が指定されています。
親トピック: tpdequeue(3c)の引数
3.6.1.2 tpdequeue(): qname引数
キュー・スペース内のキュー名は、そのキュー・スペースにアクセスするアプリケーション間で一貫していなければなりません。これは、応答キューでは特に重要です。qname
が応答キューを参照する場合、管理者はほかのキューと同じ方法で応答キュー、そして多くの場合、エラー・キューも作成します。qname
は、メッセージまたは応答を取り出すキューを指すポインタです。
親トピック: tpdequeue(3c)の引数
3.6.1.3 tpdequeue(): dataおよびlen引数
この2つの引数は、tpenqueue()で使用される場合と若干意味が異なります。*data
は、キューから取り出されたメッセージをシステムが格納するバッファのアドレスを指します。tpdequeue()
が呼び出された場合に、この値がNULLであることはエラーです。
tpdequeue()
が戻ると、len
は取り出されたデータのデータ長情報を持つlong型を指します。0は応答にデータがなかったことを示します。アプリケーションによっては、これは正当で正常な応答です。長さ0の応答を受信した場合でも、それをキューに登録された要求の正常処理を示すために使用できます。バッファがtpdequeue()
呼出しの前と比べて変更されているかどうかを確認する場合は、tpdequeue()
呼出しの前にデータ長を保存し、それを呼出しが終了した後でlen
と比較します。
親トピック: tpdequeue(3c)の引数
3.6.1.4 tpdequeue(): flags引数
flags
の値は、tpdequeue()
呼出しの処理方法をOracle Tuxedoシステムに通知するために使用されます。次は、有効なフラグです。
-
TPNOTRAN
- 呼出し側がトランザクション・モードにある場合に、このフラグが設定されていると、メッセージは呼出し側のトランザクション内ではキューから取り出されません。このフラグを設定するトランザクション・モードの呼出し側には、メッセージをキューから取り出すときにトランザクション・タイムアウトが適用され、それ以外は適用されません。キューからのメッセージの取出しが失敗した場合でも、呼出し側のトランザクションは影響されません。
-
TPNOBLOCK
- ブロッキング状態が存在すると、メッセージはキューから取り出されません。このフラグが設定されていて、メッセージの転送先である内部バッファがいっぱいであるなどのブロッキング条件が存在する場合には、呼出しは異常終了し、tperrno(5)に
TPEBLOCK
が設定されます。このフラグが設定されていて、ターゲットのキューが別のアプリケーションによって排他的にオープンされているなどのブロッキング条件が存在する場合には、呼出しは失敗してtperrno()
にTPEDIAGNOSTIC
が設定され、TPQCTL
構造体の診断フィールドはQMESHARE
に設定されます。後者の場合、Oracle Tuxedoシステム以外のOracle製品に基づくほかのアプリケーションが、キューイング・サービスAPI (QSAPI)を使用して読取りと書き込み、またはそのいずれかを排他的に行うためにキューをオープンしています。 -
TPNOTIME
- このフラグを設定すると、呼出し側は無制限にブロックでき、ブロッキング・タイムアウトが適用されなくなります。ただし、トランザクション・タイムアウトは発生する可能性があります。
-
TPNOCHANGE
- このフラグが設定されていると、
*data
が指すバッファのタイプを変更できません。デフォルトでは、*data
が指すバッファとは異なるタイプのバッファが受信されると、受信側が着信バッファのタイプを識別するかぎり、*data
のバッファ・タイプは、受信されたバッファのタイプに変更されます。つまり、受信されたバッファのタイプとサブタイプは、*data
が指すバッファのタイプとサブタイプと一致する必要があります。 -
TPSIGRSTRT
- このフラグが設定されていると、基底のシステム・コールがシグナルによって中断された場合、中断されたシステム・コールが再度呼び出されます。このフラグが設定されていないときにシグナルによってシステム・コールが中断されると、呼出しは異常終了し、tperrno(5)は
TPGOTSIG
に設定されます。
関連項目:
「第5項 - ファイル形式、データ記述、MIBおよびシステム・プロセス・リファレンス」のtperrno(5)親トピック: tpdequeue(3c)の引数
3.6.2 TPQCTL構造体
tpdequeue()
の3番目の引数は、TPQCTL
型の構造体へのポインタです。TPQCTL
構造体には、アプリケーションで使用されるメンバーとOracle Tuxedoシステムで使用されるメンバーがあり、アプリケーション・プログラムとキュー機能間の両方向でパラメータがやり取りされます。tpdequeue()
を呼び出すクライアントはフラグを設定して、システムで値が提供されるべきフィールドをマークします。前述のように、この構造体はtpenqueue()でも使用されます。一部のメンバーは、この関数のみに適用されます。この構造体全体のサンプル・コードは、「tpqctl_t構造体」に示されています。
tpdequeue()
への入力では、次のフィールドをTPQCTL
構造体に設定します。
long flags; /* indicates which of the values are set */
char msgid[32]; /* id of message to dequeue */
char corrid[32]; /* correlation identifier of message to dequeue */
次は、tpdequeue()
の入力として有効なフラグです。
-
TPNOFLAGS
- フラグは設定されません。制御構造体から情報は取得されません。
-
TPQGETBYMSGID
- このフラグが設定されていると、
ctl->msgid
で識別されるメッセージ識別子を持つメッセージが取り出されることがリクエストされます。メッセージ識別子は、以前に呼び出されたtpenqueue()
で決定されています。メッセージがあるキューから別のキューに移動された場合、メッセージ識別子は変更されます。メッセージ識別子の値は32バイト全体が意味を持つので、ctl->msgid
で識別される値は、たとえばNULL文字を埋め込むなどして、完全に初期化される必要があります。 -
TPQGETBYCORRID
- このフラグが設定されていると、
ctl->corrid
で指定された相関識別子を持つメッセージを取り出すことがリクエストされます。相関識別子は、アプリケーションがtpenqueue()
でキューにメッセージを登録したときに指定されます。相関識別子の値は32バイト全体が意味を持つので、ctl->corrid
に指定される値は、たとえばNULL文字を埋め込むなどして、完全に初期化する必要があります。 -
TPQWAIT
- このフラグが設定されていると、キューが空の場合はエラーが戻されません。かわりに、メッセージを取り出せるようになるまで、プロセスは待機する必要があります。
TPQWAIT
がTPQGETBYMSGID
またはTPQGETBYCORRID
とともに設定されている場合、指定されたメッセージ識別子または相関識別子を持つメッセージがキューに存在しないときは、エラーが戻されません。かわりに、基準を満たすメッセージを取り出せるようになるまで、プロセスは待機する必要があります。プロセスには呼出し側のトランザクション・タイムアウトが適用されますが、トランザクション・モードではない場合、TMQUEUE
プロセスで-tオプションで指定されたタイムアウトが適用されます。 -
TPQPEEK
- このフラグが設定されていると、指定されたメッセージが読み取られてもキューから削除されません。
TPNOTRAN
フラグも設定する必要があります。
tpdequeue()
からの出力情報を制御するflags
パラメータの有効なビットのの一覧を次に示します。どのフラグ・ビットでも、tpdequeue()の呼出し時にオンになっていると、メッセージがキューに登録されたときに提供された値が、構造体の対応するフィールド(「tpqctl_t構造体」を参照)に格納され、そのビットは設定されたままになります。値が使用できない(つまり、メッセージがキューに登録されたときに値が指定されなかった)場合、またはtpdequeue()
を呼び出したときにビットが設定されなかった場合、tpdequeue()
はフラグがオフの状態で完了します。
-
TPQPRIORITY
- このフラグが設定され、
tpdequeue()
の呼出しが成功し、メッセージが明示的な優先度でキューに登録された場合、その優先度はctl->priority
に格納されます。優先度は1以上100以内の範囲内で、数値が高いほど優先度も高くなります。つまり、高い数値のメッセージが低い数値のメッセージよりも先にキューから取り出されます。優先度によって順序付けられていないキューの場合、値は情報にすぎません。 -
TPQMSGID
- このフラグが設定されている場合に、
tpdequeue()
の呼出しが成功すると、メッセージ識別子がctl->msgid
に格納されます。メッセージ識別子の値は、32バイト全体が意味を持ちます。 -
TPQCORRID
- このフラグが設定され、
tpdequeue()
の呼出しが成功し、メッセージが相関識別子によってキューに登録されていた場合、相関識別子がctl->corrid
に格納されます。相関識別子の値は、32バイト全体が意味を持ちます。Oracle Tuxedo /Qが提供するメッセージの応答には、すべて元のリクエスト・メッセージの相関識別子が付いています。 -
TPQDELIVERYQOS
- このフラグが設定され、
tpdequeue()
の呼出しが成功し、メッセージがサービスの配信品質とともにキューに登録されていた場合、TPQQOSDEFAULTPERSIST
、TPQQOSPERSISTENT
、またはTPQQOSNONPERSISTENT
フラグがctl‑>delivery_qos
に格納されます。メッセージがキューに登録されたときに配信サービスの品質が明示的に指定されていない場合は、ターゲットとなるキューのデフォルトの配信ポリシーによってメッセージ配信の品質が決まります。 -
TPQREPLYQOS
- このフラグが設定され、
tpdequeue()
の呼出しが成功し、メッセージがサービスの応答品質とともにキューに登録されていた場合、TPQQOSDEFAULTPERSIST
、TPQQOSPERSISTENT
、またはTPQQOSNONPERSISTENT
フラグがctl‑>reply_qos
に格納されます。メッセージがキューに登録されていたときに応答のサービス品質が明示的に指定されていない場合、ctl‑>replyqueue
キューのデフォルトの配信ポリシーによって、すべての応答に対する配信サービスの品質が決まります。 -
TPQREPLYQ
- このフラグが設定され、
tpdequeue()
の呼出しが成功し、メッセージが応答キューと共にキューに登録されていた場合、その応答キューの名前がctl->replyqueue
に格納されます。メッセージへの応答は、リクエスト・メッセージと同じキュー・スペース内の指定された応答キューに登録されます。 -
TPQFAILUREQ
- このフラグが設定され、
tpdequeue()
の呼出しが成功し、メッセージが異常終了キューと共にキューに登録されていた場合、その異常終了キューの名前がctl->failurequeue
に格納されます。失敗メッセージは、リクエスト・メッセージと同じキュー・スペース内の指定された失敗キューに登録されます。
flags
パラメータの残りのビットは、tpdequeue()
が呼び出されるとクリア(0に設定)されます。これには、TPQTOP
、TPQBEFOREMSGID
、TPQTIME_ABS
、TPQTIME_REL
、TPQEXPTIME_ABS
、TPQEXPTIME_REL
、およびTPQEXPTIME_NONE
が含まれます。これらのビットは、tpenqueue().の入力情報を制御するflagsパラメータの有効なビットです
tpdequeue()
の呼出しが失敗し、tperrno(5)にTPEDIAGNOSTIC
が設定された場合は、失敗の原因を示す値がctl->diagnostic
に返されます。ctl->diagnostic
の有効なコードには、「TPQCTL構造体」に示されているtpenqueue()
の値(QMENOSPACE
とQMERELEASE
を除く)のほかに、次のものがあります。
-
[QMENOMSG]
- キューから取り出せるメッセージはありません。メッセージがキュー上に存在し、別のアプリケーション・プロセスがこのメッセージをキューから読み取った可能性があることに注意してください。この場合、その別のプロセスがトランザクションをロールバックしたときに、メッセージはキューに戻されます。
-
[QMEINUSE]
- メッセージ識別子または相関識別子を使用してメッセージをキューから取り出す際に、指定されたメッセージが別のトランザクションによって使用されています。それ以外の場合、現在キューにあるすべてのメッセージは、ほかのトランザクションによって使用されています。この診断は、Oracle Tuxedoリリース7.1以降のキュー・マネージャからは返されません。
親トピック: メッセージのキューからの取出し
3.6.3 TPQWAITの使用
TPQCTL
構造体のflagsにTPQWAIT
が設定されてtpdequeue()
が呼び出された場合に、メッセージをすぐに取り出すことができないと、tpdequeue()
が呼出し側に制御を戻す前に、TMQUEUE
サーバーはtpdequeue()
リクエストに一致するメッセージがキューに到着するのを待ちます。TMQUEUE
プロセスは待機中のリクエストを無視し、他のプロセスのリクエストを処理しながら、最初のリクエストの条件が満たされるのを待ちます。TPQGETBYMSGID
やTPQGETBYCORRID
も指定されている場合、サーバーは指定されたメッセージ識別子や相関識別子を持つメッセージをキューから取り出せるようになるまで待ちます。このどちらのフラグも設定されていない場合、サーバーは任意のメッセージがキューに登録されるまで待ちます。呼出し側がトランザクション・モードの場合、サーバーの待機時間は、呼出し側のトランザクション・タイムアウトによって制御されますが、呼出し側がトランザクション・モードでない場合、TMQUEUE
サーバーのCLOPT
パラメータに指定される-t
オプションで制御されます。
TMQUEUE
サーバーは、リクエストを処理するアクション・リソースを利用できるかぎり、複数の待機中tpdequeue()
リクエストを同時に処理できます。十分なアクション・リソースがキュー・スペースに対して設定されていない場合、tpdequeue()
は失敗します。使用しているシステムがこれに該当する場合は、キュー・スペースに対するアクション・リソースの数を増やしてください。
親トピック: メッセージのキューからの取出し
3.6.4 TMQFORWARDサービス使用時のエラー処理
キューからのメッセージの取出しで、エラー処理の最良の方法を考慮する場合、次の2種類のエラーを区別しておきます。
- リクエストされたサービスに転送するために、TMQFORWARD(5)がメッセージをキューから取り出すときに発生するエラー
- リクエストを処理するサービスに発生するエラー
デフォルトでは、メッセージがトランザクション内でキューから取り出され、そのトランザクションがロールバックされるとき(retryパラメータが0より大きい場合は)、メッセージがキューに戻されて、再度取出しと実行が可能になります。一時的な障害が解消されるように(たとえば、データベースのロックを別のトランザクションが解除するように)少し時間をおいてから、メッセージの取出しと実行を再度試みます。通常、再試行の回数に上限を設定することも、アプリケーション不備によってリソースを著しく浪費することを防ぐために有用です。管理者がキューを設定するときに、再試行の回数と遅延時間(秒単位)の両方を指定できます。再試行の回数0は、再試行が行われないことを示します。再試行の回数が上限に達すると、管理者がキュー・スペースに設定するエラー・キューにメッセージが移動されます。エラー・キューが構成されていない場合、再試行回数に達したメッセージは削除されます。エラー・キューのメッセージは管理者が処理する必要があります。このとき、アプリケーションの要件を満たすように発信元への通知方法を検討します。選択されたメッセージ処理方法は、メッセージをキューに登録した発信元プログラムにほとんど透過的です。メッセージは一度正常にキューに登録されると、tpenqueue()
のパラメータおよびキューの属性に従って処理されることが実質的には保証されます。メッセージがエラー・キューに移動されたことの通知は、キューのパラメータを適切に調整されたシステムではほとんどありません。
異常終了キュー(通常、キュー・スペースのエラー・キューとは異なります)は、キューに登録された各メッセージと関連付けられます。このキューは、異常終了メッセージを置く場所として、キューにメッセージを登録する呼出しで指定されます。特定のリクエストに対する異常終了メッセージは、アプリケーション生成の相関識別子で識別できます。相関識別子は、キューにメッセージを登録するときに、そのメッセージと関連付けられます。
成功するまで(または事前に定義された回数まで)再試行を繰り返すというデフォルトの動作は、時間が経過すれば解決されるような一時的な障害が失敗の原因であり、メッセージが後から適切に処理される場合は適しています。
障害が一時的なものではない場合もあります。たとえば、存在しないアカウントでの操作をリクエストするメッセージがキューに入れられている場合(アプリケーションも適当な時間に存在していない場合)です。その場合、再試行してリソースを浪費しないようにします。アプリケーション・プログラマまたは管理者が、特定の操作の失敗が一時的ではないと判断した場合、単に再試行回数を0に設定します。ただし、この場合、このようなメッセージが入るキュー・スペースのエラー・キューを継続的にクリアするメカニズム(キューを定期的に読み取るバックグラウンドのクライアントなど)が必要です。また、同じサービスに対する障害でも、一時的なもの(データベース・ロックの競合など)であったり、永続的なもの(アカウントが存在しないなど)であったりする場合が多くあります。
メッセージがTMQFORWARD
によって処理される(キューから取り出され、tpcall()
を介してアプリケーションに渡される)場合、tpcall()
が返す情報には、TPESVCFAIL
エラーが一時的な障害と永続的な障害のどちらによって生じたものであるかを示すメカニズムはありません。
キューからの取出しをアプリケーションが処理する場合、簡単な解決方法はたとえ操作が失敗しても、そのサービスに対して成功を返すことです。つまり、TPSUCCESS
を設定してtpreturn
を実行します。これにより、トランザクションはコミット可能になり、メッセージはキューから削除されます。応答メッセージが使用されている場合、サービスから返されるバッファの情報によって操作の失敗を示すことができ、メッセージが応答キューに登録されます。tpreturn
のrcode
引数も、アプリケーション固有の情報を返すために使用できます。
サービスが失敗し、トランザクションをロールバックする必要がある場合、TMQFORWARD
が処理をそれ以上行わずに、2番目のトランザクションを実行してキューからメッセージを削除するかどうかは明確ではありません。デフォルトでは、TMQFORWARD
は失敗したサービスに対するメッセージを削除しません。TMQFORWARD
のトランザクションはロールバックされ、メッセージはキューに格納されます。TMQFORWARD
にコマンド行オプションを指定すると、サービスが失敗して0より長い応答メッセージが返された場合に、メッセージがキューから削除されます。メッセージは、2番目のトランザクションで削除されます。この処理を行うには、キューに遅延時間および再試行回数を設定する必要があります。メッセージが失敗したキューに関連付けられている場合、メッセージがキューから削除されたトランザクションと同じトランザクションで、応答データが異常終了キューに登録されます。
親トピック: メッセージのキューからの取出し
3.6.5 TMQFORWARDを通して呼び出されたサービスからの応答をキューから取り出す手順
- 前提ステップとして、キュー・スペースに応答キューおよび異常終了キューがあることが必要です。アプリケーションは、相関識別子の内容について一貫していなければなりません。サービスは、論理的な失敗の場合に
TPSUCCESS
を返し、tpreturn
のrcode
引数に情報を示すコードを返すようにコーディングします tpenqueue()
を呼び出してキューにメッセージを登録する際に、次のフラグ・ビットがオンになるようにflagsを設定します。TPQCORRID TPQREPLYQ TPQFAILUREQ TPQMSGID
この呼出しを行う前に、
corrid
、replyqueue
、およびfailurequeue
の値を設定します。呼出しから制御が戻ったら、corrid
を保存します。tpdequeue()
を呼び出して応答を確認する際に、qname
引数に応答キューを指定し、次のフラグ・ビットがオンになるようにflagsを設定します:TPQFAILUREQ TPQMSGID
TPQGETCORRID
この呼出しを行う前に、保存した相関識別子を使用して
corrid
に入力します。tpdequeue()の呼出しが失敗し、tperrno(5)にTPEDIAGNOSTIC
が設定された場合、詳しい情報をdiagnosticから取得できます。エラー・コードQMENOMSG
を受信した場合、キューから取り出すことのできるメッセージがなかったことを示します。- もう1つの
tpdequeue()
呼出しを設定します。この呼出しでは、qname
が異常終了キューの名前を指し、次のフラグ・ビットがオンになるようにflagsを設定します。TPQCORRID TPQREPLYQ TPQFAILUREQ TPQMSGID TPQGETBYCORRID
corrid
に相関識別子を挿入します。呼出しから制御が戻ったら、len
を調べてデータが受信されたかどうかを確認し、また、urcode
を調べてサービスがユーザー戻りコードを返したかどうかを確認します。
親トピック: メッセージのキューからの取出し
3.7 メッセージの順次処理
メッセージの順次処理は、あるサービスがそのトランザクションがコミットされる前に、連鎖的に次のサービス用にメッセージをキューに登録することによって行われます。最初の発信元のプロセスは、reply_queue
に対する一連のtpdequeue()
呼出しによって順次処理の進行状況を追跡できます。ただし、各メンバーが同じ相関識別子を使用し、長さ0の応答を返すことが必要です。
また、非請求通知を使用して、順次処理全体が成功したという通知を最初の発信元に返すこともできます。順次処理の最後のトランザクションがtpcommit
で終了したことを確認するには、tpdequeue()
から戻されたTPQCTL
構造体、またはサービスに渡されたTPSVCINFO
構造体で渡されるクライアント識別子を使用して、tpnotify
を呼び出す操作を追加します。最初の発信元であるクライアントは、tpsetunsol
を呼び出して、使用されている非請求メッセージ・ハンドラを指定しておかなければなりません。
3.7.1 ピア・ツー・ピア通信でのキューの使用
キューへのメッセージの登録およびキューからのメッセージの取出しに関するこれまでの説明では、キューがリクエスト/レスポンスの一形態として使用されていることが暗黙の前提になっていました。メッセージ自体はサービス・リクエストである必要はありません。キュー式メッセージ機能は、あるプロセスから別のプロセスに、サービス・リクエストと同じように効果的にデータを転送できます。アプリケーション間またはクライアント間のこの通信方式は、ピア・ツー・ピア通信と呼ばれます。
使用するアプリケーションが、このような目的でOracle Tuxedo /Qを使用することに適している場合は、管理者に別のキューを作成してもらい、そのキューからメッセージを取り出す独自の受信用プログラムをコーディングします。
親トピック: メッセージの順次処理