ここでは、キューへのメッセージの登録とキューからのメッセージの取出しを行うATMI C言語関数tpenqueue(3c)、tpdequeue(3c)、およびいくつかの補助関数の使用方法について説明します。
キュー機能を使用するクライアント・プログラムまたはサーバー・プログラムをコーディングするOracle TUXEDOプログラマには、Oracle Tuxedo ATMIにバインドされたC言語についての知識が必要です。Oracle Tuxedoプログラミングに関する全般的な説明については、『C言語を使用したOracle Tuxedo ATMIアプリケーションのプログラミング』を参照してください。ATMI関数の詳細は、『Oracle Tuxedo ATMI C言語関数リファレンス』を参照してください。
Oracle Tuxedo /Qのキューにメッセージを登録する呼出しは、アプリケーションに関連付けられているあらゆるクライアント・プロセスまたはサーバー・プロセスから行うことができます。たとえば、次の発信元があります。
ここでは、Oracle Tuxedo /Qプログラミングについて、図「キュー・サービスの呼出し」の主に左側部分について説明します。この図では、クライアント(または、クライアントとして機能するプロセス)はtpenqueue(3c)を呼び出し、TMQUEUE(5)サーバーを通して利用できるキュー・スペースを指定して、メッセージをキューに登録しています。クライアントは、その後、TMQUEUE
へのtpdequeue(3c)呼出しを介して、応答を取得します。
図「キュー・サービスの呼出し」では、キューに入れられたメッセージが、サーバーTMQFORWARD(5)によってキューから取り出され、処理のためにtpcall(3c)を介してアプリケーション・サーバーに送信されています。tpcall()
に対する応答が受信されると、TMQFORWARD
は応答メッセージをキューに登録します。TMQFORWARD
の主な目的は、キュー・スペースと既存のアプリケーション・サービスとの間にインタフェースを提供することです。そのため、アプリケーションにコードを追加する必要はありません。そのため、ここでは、クライアントとキュー・スペースとの間の処理を中心に説明します。
キュー機能の使い方を簡単に示すサンプルがソフトウェアに提供されています。詳細は、「サンプル・アプリケーション」を参照してください。
#include <atmi.h>
int tpenqueue(char *qspace
, char *qname
, TPQCTL *ctl
,
char *data
, longlen
, longflags
)
tpenqueue()
が呼び出されると、qspace
で識別されるキュー・スペース内のqname
キューにメッセージを格納するようにシステムが指示されます。メッセージはdata
が指すバッファ内にあり、その長さはlen
で示されます。flags
にビット設定を行うと、システムにtpenqueue()
呼出しの処理方法が通知されます。登録されたメッセージおよび応答の処理方法のさらに詳しい情報は、ctl
が指すTMQCTL
構造体で定義されます。
tpenqueue(3c)の処理を制御するいくつかの重要な引数があります。その一部について、以下に説明します。
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)リファレンス・ページの例では、サーバーを作成して構成ファイルで指定する際に、サービスの別名を指定する方法が示されています。「サンプル・アプリケーション」のサンプル・プログラムでも、サービスの別名が指定されています。
キュー・スペース内で、キューを使用してサービスを呼び出している場合、メッセージ・キューはリクエストを処理できるアプリケーション・サービスに従って命名されます。qname
は、そのようなアプリケーション・サービスを指すポインタです。それ以外の場合、qname
は、アプリケーション(メッセージをキューに登録したアプリケーション、または別のアプリケーション)によってキューから取り出されるまで、メッセージを格納しておく場所を単に示す名前です。
data
は、処理対象のメッセージが格納されたバッファを指すポインタです。そのバッファは、tpalloc(3c)を呼び出して割り当てられたものであることが必要です。len
は、メッセージの長さを指定します。Oracle Tuxedoのバッファ・タイプには、メッセージの長さを指定する必要がないもの(FMLなど)もあります。その場合、len
は無視されます。data
はNULLにすることもできます。その場合、len
は無視され、メッセージはデータ部分なしでキューに登録されます。
flags
の値は、tpenqueue()
呼出しの処理方法をOracle Tuxedoシステムに通知するために使用されます。次は、有効なフラグです。
TPNOTRAN
TPNOBLOCK
TPEBLOCK
が設定されます。このフラグが設定されていて、ターゲットのキューが別のアプリケーションによって排他的にオープンされているなどのブロッキング条件が存在する場合には、呼出しは失敗してtperrno()
にTPEDIAGNOSTIC
が設定され、TPQCTL
構造体の診断フィールドはQMESHARE
に設定されます。後者の場合、Oracle Tuxedoシステム以外のOracle製品に基づくほかのアプリケーションが、キューイング・サービスAPI (QSAPI)を使用して読取りと書き込み、またはそのいずれかを排他的に行うためにキューをオープンしています。
TPNOBLOCK
が設定されていない場合に、ブロッキング状態が存在すると、その状態が解消されるかタイムアウト(トランザクション・タイムアウトまたはブロッキング・タイムアウト)が発生するまで、呼出し側はブロックされます。タイムアウトが発生した場合、呼出しは失敗し、tperrno()
にTPETIME
が設定されます。
TPNOTIME
TPSIGRSTRT
TPGOTSIG
が設定されます。
tpenqueue()
の3番目の引数は、TPQCTL
型の構造体へのポインタです。TPQCTL
構造体には、アプリケーションで使用されるメンバーとOracle Tuxedoシステムで使用されるメンバーがあり、アプリケーション・プログラムとキュー機能間の両方向でパラメータがやり取りされます。tpenqueue()
を呼び出すクライアントは、フラグを設定して、システム側で入力する必要のあるフィールドをマークします。この構造体は、tpdequeue()
でも使用され、一部のフィールドは、アプリケーションがこの関数を呼び出すまで使用されません。コードリスト3-1は、この構造体全体を示しています。
#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
TPQTOP
TPQTOP
とTPQBEFOREMSGID
は、相互に排他的なフラグです。
TPQBEFOREMSGID
ctl->msgid
によって識別されるメッセージの前に登録されます。このリクエストは、順序付けを無効にするようにキューが設定されているかどうかによって、使用できない場合があります。TPQTOP
とTPQBEFOREMSGID
は、相互に排他的なフラグです。メッセージ識別子の値は32バイト全体が意味を持つので、ctl->msgid
で識別される値は、たとえばNULL文字を埋め込むなどして、完全に初期化する必要があります。
TPQTIME_ABS
ctl->deq_time
で指定された時間の経過後、メッセージが処理されます。deq_time
は、使用しているオペレーティング・システムで利用できる場合は、time(2)
またはmktime(3C)
、あるいはOracle Tuxedoシステムで提供されるgp_mktime(3c)によって生成される絶対時間です。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
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
フラグが設定されていない場合、ターゲットのキューのデフォルトの配信ポリシーがメッセージに対するサービスの配信品質を指定します。
TPQREPLYQOS
フラグが設定されていると、ctl->reply_qos
で指定されるフラグが、メッセージの応答に対するサービスの品質を制御します。その場合、相互に排他的な3つのフラグTPQQOSDEFAULTPERSIST
、TPQQOSPERSISTENT
、TPQQOSNONPERSISTENT
のいずれかをctl->reply_qos
に設定しなければなりません。TPQREPLYQOS
フラグは、TMQFORWARD
によって処理されるメッセージから応答が返されるときに使用されます。サービスを呼び出すときにTMQFORWARD
を使用しないアプリケーションでは、自身の応答メカニズムのヒントとしてTPQREPLYQOS
フラグを使用できます。 TPQREPLYQOSが設定されていない場合、ctl->replyqueue
キューのデフォルトの配信ポリシーが応答に対するサービスの配信品質を指定します。デフォルトの配信ポリシーは、メッセージに対する応答がキューに登録されるときに決定される点に注意してください。つまり、元のメッセージがキューに登録されてからメッセージに対する応答が登録されるまでの間に、応答キューのデフォルトの配信ポリシーが変更された場合、応答が最後に登録される時点で有効なポリシーが使用されます。 次は、ctl->delivery_qos
とctl->reply_qos
の有効なフラグです。
TPQEXPTIME_ABS
ctl->exp_time
に格納された値で示されます。ctl->exp_time
の値は、time(2)
、mktime(3C)
、またはgp_mktime(3c)によって生成された絶対時間、つまり世界協定時(UTC) 1970年1月1日00:00:00から経過した秒数に設定されなければなりません。 キューへの登録操作の時間より早い絶対時間が指定されると、操作は成功しますが、メッセージはしきい値の計算の対象になりません。有効期限の時間がメッセージの使用可能時間より前の場合、使用可能時間が有効期限の切れる時間より前になるようにいずれかの時間を変更しないかぎり、メッセージをキューから取り出すことはできません。また、これらのメッセージがキューからの取出しの対象になったことがなくても、有効期限が切れるとキューから削除されます。トランザクション内でメッセージの期限が切れた場合、それによってトランザクションが異常終了することはありません。トランザクション内でキューへの登録、またはキューからの取出し中に有効期限が切れたメッセージは、トランザクションが終了した時点でキューから削除されます。メッセージの有効期限が切れたことの通知は行われません。 TPQEXPTIME_ABS
、TPQEXPTIME_REL
、およびTPQEXPTIME_NONE
は、相互に排他的なフラグです。この3つのどのフラグも設定されていない場合、ターゲットのキューに対応しているデフォルトの有効期限の時間がメッセージに適用されます。
TPQEXPTIME_REL
ctl->exp_time
に格納された値で示されます。
TPQEXPTIME_ABS
、TPQEXPTIME_REL
、およびTPQEXPTIME_NONE
は、相互に排他的なフラグです。この3つのどのフラグも設定されていない場合、ターゲットのキューに対応しているデフォルトの有効期限の時間がメッセージに適用されます。
TPQEXPTIME_NONE
TPQEXPTIME_ABS
、TPQEXPTIME_REL
、およびTPQEXPTIME_NONE
は、相互に排他的なフラグです。この3つのどのフラグも設定されていない場合、ターゲットのキューに対応しているデフォルトの有効期限の時間がメッセージに適用されます。
また、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
]
QMESHARE
]
キューの作成時に、管理者がtpenqueue()
呼出しでキュー上のメッセージの順序を無効にできるようにした場合、次の2つの方法でこの機能を利用できます。この2つの方法は、相互に排他的です。flags
にTPQTOP
を設定すると、メッセージをキューの先頭に置くことができます。または、flags
にTPQBEFOREMSGID
、ctl->msgid
に既存のメッセージのIDを設定して、メッセージを特定の既存のメッセージの前に置くこともできます。これは、前の呼出しからのメッセージIDがここで使用できるように保存されたことが前提になります。管理者は、キューでサポートされている方法を通知する必要があります。キューは、この2つのいずれかまたは両方を使用できるように、あるいはどちらも使用できないように作成できます。
ctl->priority
に値を設定して、メッセージの優先度を指定することができます。この値は、1から100までの範囲でなければなりません。数値が高いほど優先度が高くなります。キューの順序付けパラメータの中にpriority
が含まれていない場合、ここで優先度を設定しても取出しの順序には影響しません。ただし、優先度の値は保持されるので、メッセージがキューから取り出されるときに検査されます。
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
を設定します。
tpenqueue()
の呼出し側がトランザクション・モードにある場合に、TPNOTRAN
が設定されていないと、キューへの登録は呼出し側のトランザクション内で行われます。呼出し側は、tpenqueue()
が成功したか失敗したかによって、メッセージがキューに登録されたかどうかを判断できます。呼出しが正常に行われると、メッセージがキューに登録されたことが保証されます。呼出しが失敗すると、メッセージがキューに登録された部分も含めて、トランザクションがロールバックされます。
tpenqueue()
の呼出し側がトランザクション・モードにない場合、またはTPNOTRAN
が設定されている場合、メッセージは呼出し側のトランザクションとは別のトランザクションでキューに登録されます。tpenqueue()
への呼出しが正常な戻り値を返した場合、メッセージがキューに登録されたことが保証されます。tpenqueue()
の呼出しが通信エラーまたはタイムアウトによって失敗した場合は、その障害がメッセージ登録の前に発生したのか後に発生したのか、呼出し側には判断できません。
呼出し側がトランザクション・モードにないときにTPNOTRAN
を指定しても意味がありません。
#include <atmi.h>
int tpdequeue(char *qspace, char *qname, TPQCTL *ctl, \
char **data, long *len, long flags)
この呼出しが行われると、qspace
で識別されるキュー・スペース内のqname
キューからメッセージを取り出すようにシステムが指示されます。メッセージは、*dataが指すアドレスにあるバッファ(tpalloc(3c)
によって割り当てられたもの)に挿入されます。len
はデータの長さを示します。tpdequeue()
から返されたlen
が0の場合、そのメッセージにはデータ部分がないことを示します。flags
にビット設定を行うと、システムにtpdequeue()
呼出しの処理方法が通知されます。ctl
が指すTPQCTL
構造体には、この呼出しの処理方法についての詳細な情報が記述されます。
tpdequeue(3c)の処理を制御するいくつかの重要な引数があります。その一部について、以下に説明します。
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)リファレンス・ページの例では、サーバーを作成して構成ファイルで指定する際に、サービスの別名を指定する方法が示されています。「サンプル・アプリケーション」のサンプル・プログラムでも、サービスまたはキュー・スペース名の別名が指定されています。
キュー・スペース内のキュー名は、そのキュー・スペースにアクセスするアプリケーション間で一貫していなければなりません。これは、応答キューでは特に重要です。qname
が応答キューを参照する場合、管理者はほかのキューと同じ方法で応答キュー、そして多くの場合、エラー・キューも作成します。qname
は、メッセージまたは応答を取り出すキューを指すポインタです。
この2つの引数は、tpenqueue()
で使用される場合と若干意味が異なります。*data
は、キューから取り出されたメッセージをシステムが格納するバッファのアドレスを指します。tpdequeue()
が呼び出された場合に、この値がNULLであることはエラーです。
tpdequeue()
が戻ると、len
は取り出されたデータのデータ長情報を持つlong
型を指します。0は応答にデータがなかったことを示します。アプリケーションによっては、これは正当で正常な応答です。長さ0の応答を受信した場合でも、それをキューに登録された要求の正常処理を示すために使用できます。バッファがtpdequeue()
呼出しの前と比べて変更されているかどうかを確認する場合は、tpdequeue()
呼出しの前にデータ長を保存し、それを呼出しが終了した後でlen
と比較します。
flags
の値は、tpdequeue()
呼出しの処理方法をOracle Tuxedoシステムに通知するために使用されます。次は、有効なフラグです。
TPNOTRAN
TPNOBLOCK
TPEBLOCK
が設定されます。このフラグが設定されていて、ターゲットのキューが別のアプリケーションによって排他的にオープンされているなどのブロッキング条件が存在する場合には、呼出しは失敗してtperrno()
にTPEDIAGNOSTIC
が設定され、TPQCTL
構造体の診断フィールドはQMESHARE
に設定されます。後者の場合、Oracle Tuxedoシステム以外のOracle製品に基づくほかのアプリケーションが、キューイング・サービスAPI (QSAPI)を使用して読取りと書き込み、またはそのいずれかを排他的に行うためにキューをオープンしています。
TPNOBLOCK
が設定されていない場合に、ブロッキング状態が存在すると、その状態が解消されるかタイムアウト(トランザクション・タイムアウトまたはブロッキング・タイムアウト)が発生するまで、呼出し側はブロックされます。(TPQCTL
構造体の) flags
にTPQWAIT
オプションが指定されている場合は、このブロッキング条件には、キュー自体のブロッキングは含まれません。
TPNOTIME
TPNOCHANGE
data
が指すバッファのタイプは変更されません。デフォルトでは、*data
が指すバッファとは異なるタイプのバッファが受信されると、受信側が着信バッファのタイプを識別するかぎり、*data
のバッファ・タイプは、受信されたバッファのタイプに変更されます。つまり、受信されたバッファのタイプとサブタイプは、*data
が指すバッファのタイプとサブタイプと一致する必要があります。
TPSIGRSTRT
TPGOTSIG
が設定されます。
tpdequeue()
の3番目の引数は、TPQCTL
型の構造体へのポインタです。TPQCTL
構造体には、アプリケーションで使用されるメンバーとOracle Tuxedoシステムで使用されるメンバーがあり、アプリケーション・プログラムとキュー機能間の両方向でパラメータがやり取りされます。tpdequeue()
を呼び出すクライアントはフラグを設定して、システムで値が提供されるべきフィールドをマークします。前述のように、この構造体はtpenqueue()
でも使用されます。一部のメンバーは、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 */
TPNOFLAGS
TPQGETBYMSGID
ctl->msgid
で識別されるメッセージ識別子を持つメッセージが取り出されることがリクエストされます。メッセージ識別子は、以前に呼び出されたtpenqueue()
で決定されています。メッセージがあるキューから別のキューに移動された場合、メッセージ識別子は変更されます。メッセージ識別子の値は32バイト全体が意味を持つので、ctl->msgid
で識別される値は、たとえばNULL文字を埋め込むなどして、完全に初期化される必要があります。
TPQGETBYCORRID
ctl->corrid
で指定された相関識別子を持つメッセージを取り出すことがリクエストされます。相関識別子は、アプリケーションがtpenqueue()
でキューにメッセージを登録したときに指定されます。相関識別子の値は32バイト全体が意味を持つので、ctl->corrid
に指定される値は、たとえばNULL文字を埋め込むなどして、完全に初期化する必要があります。
TPQWAIT
TPQWAIT
がTPQGETBYMSGID
またはTPQGETBYCORRID
とともに設定されている場合、指定されたメッセージ識別子または相関識別子を持つメッセージがキューに存在しないときは、エラーが戻されません。かわりに、基準を満たすメッセージを取り出せるようになるまで、プロセスは待機する必要があります。プロセスには呼出し側のトランザクション・タイムアウトが適用されますが、トランザクション・モードではない場合、TMQUEUE
プロセスで-t
オプションで指定されたタイムアウトが適用されます。
tpdequeue()
は -1を返しtperrno()
をTPEDIAGNOSTIC
に設定し、TPQCTL
構造体の診断フィールドをQMESYSTEM
に設定します。 TPQWAIT
制御パラメータを指定するtpdequeue()
の各リクエストでは、条件を満たすメッセージがすぐに利用できない場合、キュー・マネージャ(TMQUEUE
)のアクション・オブジェクトを使用できる必要があります。アクション・オブジェクトが使用できない場合、tpdequeue()
リクエストは失敗します。利用できるキュー・マネージャのアクション数は、キュー・スペースの作成時または変更時に指定されます。待機中のキューからの取出しリクエストが完了すると、対応するアクション・オブジェクトは別のリクエストに使用できるようになります。
TPQPEEK
TPQPEEK
を使用してメッセージを破棄せずにキューから取り出す場合、その取出しリクエストをシステムが処理している短時間の間、非ブロッキング状態の他のメッセージ取出し操作にメッセージが認識されないことがあります。たとえば、特定の選択基準(メッセージ識別子や相関識別子など)を使用してメッセージをキューから取り出す操作が、破棄せずに取出しが現在行われているメッセージを探している場合などがあります。
次は、tpdequeue()
からの出力情報を制御するflags
パラメータの有効なビットです。どのフラグ・ビットでも、tpdequeue()
の呼出し時にオンになっていると、メッセージがキューに登録されたときに提供された値が、構造体の対応するフィールド(「tpqctl_t構造体」を参照)に格納され、そのビットは設定されたままになります。値が使用できない(つまり、メッセージがキューに登録されたときに値が指定されなかった)場合、またはtpdequeue()
を呼び出したときにビットが設定されなかった場合、tpdequeue()
はフラグがオフの状態で完了します。
TPQPRIORITY
tpdequeue()
の呼出しが成功し、メッセージが明示的な優先度でキューに登録された場合、その優先度はctl->priority
に格納されます。優先度は1以上100以内の範囲内で、数値が高いほど優先度も高くなります。つまり、高い数値のメッセージが低い数値のメッセージよりも先にキューから取り出されます。優先度によって順序付けられていないキューの場合、値は情報にすぎません。
TPQMSGID
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
]
TPQCTL
構造体のflags
にTPQWAIT
が設定されてtpdequeue()
が呼び出された場合に、メッセージをすぐに取り出すことができないと、tpdequeue()
が呼出し側に制御を戻す前に、TMQUEUE
サーバーはtpdequeue()
リクエストに一致するメッセージがキューに到着するのを待ちます。TMQUEUE
プロセスは待機中のリクエストを無視し、他のプロセスのリクエストを処理しながら、最初のリクエストの条件が満たされるのを待ちます。TPQGETBYMSGID
やTPQGETBYCORRID
も指定されている場合、サーバーは指定されたメッセージ識別子や相関識別子を持つメッセージをキューから取り出せるようになるまで待ちます。このどちらのフラグも設定されていない場合、サーバーは任意のメッセージがキューに登録されるまで待ちます。呼出し側がトランザクション・モードの場合、サーバーの待機時間は、呼出し側のトランザクション・タイムアウトによって制御されますが、呼出し側がトランザクション・モードでない場合、TMQUEUE
サーバーのCLOPT
パラメータに指定される-t
オプションで制御されます。
TMQUEUE
サーバーは、リクエストを処理するアクション・リソースを利用できるかぎり、複数の待機中tpdequeue()
リクエストを同時に処理できます。十分なアクション・リソースがキュー・スペースに対して設定されていない場合、tpdequeue()
は失敗します。使用しているシステムがこれに該当する場合は、キュー・スペースに対するアクション・リソースの数を増やしてください。
キューからのメッセージの取出しで、エラー処理の最良の方法を考慮する場合、次の2種類のエラーを区別しておきます。
デフォルトでは、メッセージがトランザクション内でキューから取り出され、そのトランザクションがロールバックされるとき(retry
パラメータが0より大きい場合は)、メッセージがキューに戻されて、再度取出しと実行が可能になります。一時的な障害が解消されるように(たとえば、データベースのロックを別のトランザクションが解除するように)少し時間をおいてから、メッセージの取出しと実行を再度試みます。通常、再試行の回数に上限を設定することも、アプリケーション不備によってリソースを著しく浪費することを防ぐために有用です。管理者がキューを設定するときに、再試行の回数と遅延時間(秒単位)の両方を指定できます。再試行の回数0は、再試行が行われないことを示します。再試行の回数が上限に達すると、管理者がキュー・スペースに設定するエラー・キューにメッセージが移動されます。エラー・キューが構成されていない場合、再試行回数に達したメッセージは削除されます。エラー・キューのメッセージは管理者が処理する必要があります。このとき、アプリケーションの要件を満たすように発信元への通知方法を検討します。選択されたメッセージ処理方法は、メッセージをキューに登録した発信元プログラムにほとんど透過的です。メッセージは一度正常にキューに登録されると、tpenqueue()
のパラメータおよびキューの属性に従って処理されることが実質的には保証されます。メッセージがエラー・キューに移動されたことの通知は、キューのパラメータを適切に調整されたシステムではほとんどありません。
異常終了キュー(通常、キュー・スペースのエラー・キューとは異なります)は、キューに登録された各メッセージと関連付けられます。このキューは、異常終了メッセージを置く場所として、キューにメッセージを登録する呼出しで指定されます。特定のリクエストに対する異常終了メッセージは、アプリケーション生成の相関識別子で識別できます。相関識別子は、キューにメッセージを登録するときに、そのメッセージと関連付けられます。
成功するまで(または事前に定義された回数まで)再試行を繰り返すというデフォルトの動作は、時間が経過すれば解決されるような一時的な障害が失敗の原因であり、メッセージが後から適切に処理される場合は適しています。
障害が一時的なものではない場合もあります。たとえば、存在しないアカウントでの操作をリクエストするメッセージがキューに入れられている場合(アプリケーションも適当な時間に存在していない場合)です。その場合、再試行してリソースを浪費しないようにします。アプリケーション・プログラマまたは管理者が、特定の操作の失敗が一時的ではないと判断した場合、単に再試行回数を0に設定します。ただし、この場合、このようなメッセージが入るキュー・スペースのエラー・キューを継続的にクリアするメカニズム(キューを定期的に読み取るバックグラウンドのクライアントなど)が必要です。また、同じサービスに対する障害でも、一時的なもの(データベース・ロックの競合など)であったり、永続的なもの(アカウントが存在しないなど)であったりする場合が多くあります。
メッセージがTMQFORWARD
によって処理される(キューから取り出され、tpcall()
を介してアプリケーションに渡される)場合、tpcall()
が返す情報には、TPESVCFAIL
エラーが一時的な障害と永続的な障害のどちらによって生じたものであるかを示すメカニズムはありません。
キューからの取出しをアプリケーションが処理する場合、簡単な解決方法はたとえ操作が失敗しても、そのサービスに対して成功を返すことです。つまり、TPSUCCESS
を設定してtpreturn
を実行します。これにより、トランザクションはコミット可能になり、メッセージはキューから削除されます。応答メッセージが使用されている場合、サービスから返されるバッファの情報によって操作の失敗を示すことができ、メッセージが応答キューに登録されます。tpreturn
のrcode
引数も、アプリケーション固有の情報を返すために使用できます。
サービスが失敗し、トランザクションをロールバックする必要がある場合、TMQFORWARD
が処理をそれ以上行わずに、2番目のトランザクションを実行してキューからメッセージを削除するかどうかは明確ではありません。デフォルトでは、TMQFORWARD
は失敗したサービスに対するメッセージを削除しません。TMQFORWARD
のトランザクションはロールバックされ、メッセージはキューに格納されます。TMQFORWARD
にコマンド行オプションを指定すると、サービスが失敗して0より長い応答メッセージが返された場合に、メッセージがキューから削除されます。メッセージは、2番目のトランザクションで削除されます。この処理を行うには、キューに遅延時間および再試行回数を設定する必要があります。メッセージが失敗したキューに関連付けられている場合、メッセージがキューから削除されたトランザクションと同じトランザクションで、応答データが異常終了キューに登録されます。
アプリケーションがキューに登録されたメッセージに対する応答を要求している場合、次の手順に従います。
TPSUCCESS
を返し、tpreturn
のrcode
引数に情報を示すコードを返すようにコーディングします。 tpenqueue()
を呼び出してキューにメッセージを登録する際に、次のフラグ・ビットがオンになるようにflags
を設定します。 TPQCORRID TPQREPLYQ
TPQFAILUREQ TPQMSGID
この呼出しを行う前に、corrid
、replyqueue
、およびfailurequeue
の値を設定します。呼出しから制御が戻ったら、corrid
を保存します。
tpdequeue()
を呼び出して応答を確認する際に、qname
引数に応答キューを指定し、次のフラグ・ビットがオンになるようにflags
を設定します。 TPQCORRID TPQREPLYQ
TPQFAILUREQ TPQMSGID
TPQGETCORRID
この呼出しを行う前に、保存した相関識別子を使用してcorrid
に入力します。tpdequeue()
の呼出しが失敗し、tperrno(5)にTPEDIAGNOSTIC
が設定された場合、詳しい情報をdiagnostic
から取得できます。エラー・コードQMENOMSG
を受信した場合、キューから取り出すことのできるメッセージがなかったことを示します。
tpdequeue()
呼出しを設定します。この呼出しでは、qname
が異常終了キューの名前を指し、次のフラグ・ビットがオンになるようにflags
を設定します。 TPQCORRID TPQREPLYQ
TPQFAILUREQ TPQMSGID
TPQGETBYCORRID
corrid
に相関識別子を挿入します。呼出しから制御が戻ったら、len
を調べてデータが受信されたかどうかを確認し、また、urcode
を調べてサービスがユーザー戻りコードを返したかどうかを確認します。
メッセージの順次処理は、あるサービスがそのトランザクションがコミットされる前に、連鎖的に次のサービス用にメッセージをキューに登録することによって行われます。最初の発信元のプロセスは、reply_queue
に対する一連のtpdequeue()
呼出しによって順次処理の進行状況を追跡できます。ただし、各メンバーが同じ相関識別子を使用し、長さ0の応答を返すことが必要です。
また、非請求通知を使用して、順次処理全体が成功したという通知を最初の発信元に返すこともできます。順次処理の最後のトランザクションがtpcommit
で終了したことを確認するには、tpdequeue()
から戻されたTPQCTL
構造体、またはサービスに渡されたTPSVCINFO
構造体で渡されるクライアント識別子を使用して、tpnotify
を呼び出す操作を追加します。最初の発信元であるクライアントは、tpsetunsol
を呼び出して、使用されている非請求メッセージ・ハンドラを指定しておかなければなりません。
キューへのメッセージの登録およびキューからのメッセージの取出しに関するこれまでの説明では、キューがリクエスト/レスポンスの一形態として使用されていることが暗黙の前提になっていました。メッセージ自体はサービス・リクエストである必要はありません。キュー機能は、あるプロセスから別のプロセスに、サービス・リクエストと同じように効果的にデータを転送できます。アプリケーション間またはクライアント間のこの通信方式は、ピア・ツー・ピア通信と呼ばれます。
使用するアプリケーションが、このような目的でOracle Tuxedo /Qを使用することに適している場合は、管理者に別のキューを作成してもらい、そのキューからメッセージを取り出す独自の受信用プログラムをコーディングします。