English

実践習得 IBM MQの基本

メッセージ記述子(MQMD)(3)

※本連載は最新のmqpgf/mqpcfに基づいて改定されることがあります。常に最新バージョンをダウンロードしてご使用ください。

[ MsgId ]

タイプ: MQBYTE24
サイズ: 24バイト
初期値: MQMI_NONE(全てNULL(0x00))
入出力:入出力

MQメッセージを一意に示すIDです。 MQPUT()呼び出し時に、MQMI_NONE または MQPMO_NEW_MSG_ID を指定した場合、キューマネージャーが固有のIDを生成してメッセージに設定します。 MQMI_NONEはデフォルトですので、特に指定しない場合は毎回固有のメッセージIDが生成されます。 この時のIDは、4 バイトの製品 ID、キュー・マネージャー名の最初の 12 文字と、システム・クロックを元にした値から作成されます。 このことが、MQネットワーク内でキューマネージャー名をユニークにする必要のある一つの理由となっています。 運用中にシステムクロックを手動で変更する場合も含め、システムクロックが逆方向に戻される場合は、MsgIdの重複が発生する可能性があるので注意が必要です。 また、システムで作成した文字列を設定して利用するケースも見られますが、このフィールドはバイナリフィールドですので、異なる文字コードのプラットフォーム間での文字コードの変換はおこなわれないことにも注意してください。
MQGET()時にこの値を指定すると特定のMsgIdを持つメッセージのみを読み込むことができます。

[ CorrelId ]

タイプ: MQBYTE24
サイズ: 24バイト
初期値: MQCI_NONE(全てNULL(0x00))
入出力: MQGET()時:入出力、MQPUT()時:MQPMO_NEW_CORREL_ID 指定時:入力、指定なし:出力

MQPMO_NEW_CORREL_IDを指定した場合にのみ、キューマネージャーが固有のIDを生成します。
IDの生成方法はMsgIdと同様です。
MQGET()時にこの値を指定すると特定のCorrelIdを持つメッセージのみを読み込むことができます。
メッセージ間や処理の関連付け等に利用しますが、もっとも多い利用用途は要求メッセージとその応答メッセージの関連付けです。(後述)

下記はMsgIdとCorrelIdを16進表記で指定して、PUT/GETする例です。
※MQGMO_VERSION_2を使用する場合はMatchOption(MQMO_*)を使用することができますが、デフォルトはMQGMO_VERSION_1ですのでこのオプションは使用できません。 これについては詳細は改めてご説明します。


Ex. 3.1 特定のメッセージをGETする。

メッセージを3件PUTしてみます。 これらのMsgIdの下1桁は全て相違し、CorrelIdは最初の2件が同一です。
※-miと-ciに指定する値は、24バイト以内(16進表記では"0x"を除き24*2=48文字以内でかつ偶数)であることが必要です。24バイト以内で指定された場合は、mqpgfは後続をNULL(0x00)で埋めます。

$ mqpgf -qm SampleQM -q SampleQ -m "MsgId CorrelId Test1" -mi 0x414D512053616D706C65514D202020205ABC2DC820008811 -ci 0x414D512053616D706C65514D202020205ABC2DC82000881A
[18/04/09 11:50:06] 1: message length: 20 put message : MsgId CorrelId Test1

$ mqpgf -qm SampleQM -q SampleQ -m "MsgId CorrelId Test2" -mi 0x414D512053616D706C65514D202020205ABC2DC820008812 -ci 0x414D512053616D706C65514D202020205ABC2DC82000881A
[18/04/09 11:50:17] 1: message length: 20 put message : MsgId CorrelId Test2

$ mqpgf -qm SampleQM -q SampleQ -m "MsgId CorrelId Test3" -mi 0x414D512053616D706C65514D202020205ABC2DC820008813 -ci 0x414D512053616D706C65514D202020205ABC2DC82000881B
[18/04/09 11:50:21] 1: message length: 20 put message : MsgId CorrelId Test3

*オプションの説明
-mi: MQMD.MsgIdを指定(16進表記で指定する場合は、先頭に"0x"を付加する)
-ci: MQMD.CorrelIdを指定(16進表記で指定する場合は、先頭に"0x"を付加する)

いくつかのパターンでGETしてみます。いろいろと試して見てください。

テスト結果3.1

MsgIdとCorrelIdの両方指定してGETする場合は両方が一致している必要があります。

$ mqpgf -qm SampleQM -q SampleQ -br -mi 0x414D512053616D706C65514D202020205ABC2DC820008812 -ci 0x414D512053616D706C65514D202020205ABC2DC82000881A
message number: 1
*StrucId[MD ] .... MsgId[0x414D512053616D706C65514D202020205ABC2DC820008812] CorrelId[0x414D512053616D706C65514D202020205ABC2DC82000881A] ....
....
00000000: 4D73 6749 6420 436F 7272 656C 4964 2054 'MsgId CorrelId T'
00000010: 6573 7432 'est2

CorrelIdを指定して繰り返しオプション("-r")を指定してGETしてみます。2件のメッセージがマッチします。

$ mqpgf -qm SampleQM -q SampleQ -br -r -ci 0x414D512053616D706C65514D202020205ABC2DC82000881A
message number: 1
*StrucId[MD ] .... MsgId[0x414D512053616D706C65514D202020205ABC2DC820008811] CorrelId[0x414D512053616D706C65514D202020205ABC2DC82000881A] ....
....
data length: 20
00000000: 4D73 6749 6420 436F 7272 656C 4964 2054 'MsgId CorrelId T'
00000010: 6573 7431 'est1 '

message number: 2
*StrucId[MD ] .... MsgId[0x414D512053616D706C65514D202020205ABC2DC820008812] CorrelId[0x414D512053616D706C65514D202020205ABC2DC82000881A] ....
....
data length: 20
00000000: 4D73 6749 6420 436F 7272 656C 4964 2054 'MsgId CorrelId T'
00000010: 6573 7432 'est2 '

fig 3.1

[ BackoutCount ]

タイプ: MQLONG
サイズ: 4バイト
初期値: 0
入出力:出力

メッセージがバックアウトした回数が設定されます。 MQGMO_SYNCPOINTが指定され、作業単位内でMQGET()が呼び出された場合に、アプリケーションがMQBACK()を呼び出すか、MQCMIT()が呼び出される前にアプリケーションが異常終了した場合にカウントアップされます。 MQGMO_SYNCPOINTが指定された場合は、作業単位内で呼び出されたMQGET()は、MQCMIT()が発行するまでコミットされません。 Windows, Linux, UNIXのデフォルトはMQGMO_NO_SYNCPOINTで、MQPUT()/MQGET()は作業単位内で呼び出されませんが、MQ for HP NonStopの場合はデフォルトがMQGMO_SYNCPOINTであることにご注意ください。 また、MQGET()呼び出し自体が失敗し、メッセージのGETそのものができなかった場合はカウントアップされません。
カウントの正確さに影響するHardenGetBackoutキュー属性は、z/OSにのみ有効で、分散プラットフォームやHP NonStopでは無効です。


Ex. 3.2 メッセージのバックアウト

いくつかのパターンでテストします。 15KのメッセージをPUTします。

$ mqpgf -qm SampleQM -q SampleQ -m "backout test" -l 15000
[18/04/09 16:04:49] 1: message length: 15000 put message : backout test....................................................................................................................

*オプションの説明
-l: PUTするメッセージのサイズ。指定されたメッセージの長さより小さい場合は残りを切り捨て、大きい場合はNULL(0x00)を指定サイズ分付加します。


テスト結果3.2

mqpgfのデフォルトの受信バッファサイズは12Kなので、受信バッファサイズを"-sz"で拡張しない限り、理由コード 2080: MQRC_TRUNCATED_MSG_FAILEDでMQGET()呼び出しが失敗します。 この時BackoutCountはカウントアップしません。

$ mqpgf -qm SampleQM -q SampleQ MQGMO_SYNCPOINT
MQGET with warning : SampleQ CompCd=01 ReasonCd=2080 len=15000
MQBACK success : CompCd=00 ReasonCd=00

$ mqpgf -qm SampleQM -q SampleQ -br -sz 15000
message number: 1
*StrucId[MD ] .... BackoutCount[0] .... ※この場合はカウントアップされない。
....

mqpgfは、MQGMO_SYNCPOINTまたはMQPMO_SYNCPOINTが指定されると、MQCMIT()を自動的に呼び出します。もしエラーが発生した場合はMQBACK()を呼びします。 "-b"を指定すると、処理が正常な場合でも、MQCMIT()を呼び出さず、MQBACK()を呼び出して強制的にバックアウトできます。

$ mqpgf -qm SampleQM -q SampleQ MQGMO_SYNCPOINT -sz 15000 -b
[18/04/09 16:38:08] 1: message length: 15000 get message : backout test....................................................................................................................
MQBACK success : CompCd=00 ReasonCd=00

$ mqpgf -qm SampleQM -q SampleQ -br -sz 15000
message number: 1
*StrucId[MD ] .... BackoutCount[1] ....
....

"-s"オプションの後に呼び出される任意のMQのAPI(MQI)名を指定すると、そのAPIが呼び出される前で処理を停止します。 (任意のKey入力で後続の処理を再開します。) "-s"の後に"MQCMIT"と指定して、MQGET()が成功後、MQCMIT()呼び出し前で処理を停止しプロセスを強制終了させます。 Windowsの場合はタスクマネージャーから"Windows コマンドプロセッサ"を展開し、"mqpgf.exe(32ビット)"を選んで「タスクの終了」を選択します。 (Windows版ではCtl-Cでは強制終了されずコミットされます。) Unix系のOSやHP NonStopのOSSの場合は、killコマンドまたはCTL-Cでプロセスを強制終了させます。

$ mqpgf -qm SampleQM -q SampleQ MQGMO_SYNCPOINT -sz 15000 -s MQCMIT
[18/04/09 16:42:52] 1: message length: 15000 get message : backout test....................................................................................................................
stop before calling MQCMIT().
Hit Any Key!!!
※ここで強制終了

ここで、キューマネージャーがアプリケーションの異常終了を検知しメッセージをバックアウトするまでに一定の時間がかかります。 10秒ほど待ってください。
※この時間はプラットフォームによって違いが見られ、こちらでテストした結果では特にMQ9.0 for Linuxでの検証で顕著に確認されています。 WindowsやHP NonStopでは、目立った遅延は確認されませんでした。
$ mqpgf -qm SampleQM -q SampleQ -br -sz 15000
message number: 1
*StrucId[MD ] .... BackoutCount[2] ....
....

*オプションの説明
MQGMO_SYNCPOINT: MQGMO.OptionsにMQGMO_SYNCPOINTを設定します。
-sz: 受信バッファのサイズ
-b: 強制バックアウト
-s: 指定MQIの呼び出し前で停止

fig 3.2

[ ReplyToQ ]

タイプ: MQCHAR48
サイズ: 48バイト
初期値: NULLストリング(C言語)
入出力: MQGET()時:出力、MQPUT()時:入力

前述のReportフィールドやMsgTypeフィールドでご説明したレポートメッセージ(MQMT_REPORT)、応答メッセージ(MQMT_REPLY)を送る際の宛先のキューです。 テスト結果1.3.1テスト結果1.3.2テスト結果2.2で、レポートメッセージの送信先としてMQMD.ReplyToQ、MQMD.RepyToQMgrが使用されることを確認済みです。

[ ReplyToQMgr ]

タイプ: MQCHAR48
サイズ: 48バイト
初期値: NULLストリング(C言語)
入出力: MQGET()時:出力、MQPUT()時:入力

応答メッセージまたはレポート・メッセージを送信する宛先のキュー・マネージャーの名前です。 関連情報として、Reportフィールドのご説明でも少し触れましたが、リモート・キュー・マネージャーにメッセージを送信する時には、下記順序で伝送キューが選択されますので、キューマネージャーがレポート・メッセージを自動で生成して送信する際等には必ずしもリモート・キューのローカル定義は必要ありません。 また、リモート・キュー・マネージャーと同じ名前で伝送キュー名を作成していれば、リモート・キューのローカル定義のXMITQパラメータの指定は不要です。

  1. 1. リモート・キューのローカル定義のXMITQに指定された伝送キュー
  2. 2. リモート・キュー・マネージャーと同じ名前を持つ伝送キュー
  3. 3. キュー・マネージャーのDEFXMITQに指定された伝送キュー
このテストではSampleQMからRemoteQMに要求メッセージを送信し、RemoteQMから応答メッセージをアプリケーション(mqpgf)で送信しますので、RemoteQM側にSampleQM側の応答受信キューであるRemoteQMからみたリモート・キューであるSampleQへのローカル定義を作成します。

mqpcf mqsc -qm RemoteQM -s "def qr('SampleQ') rname('SampleQ') rqmname('SampleQM')"
1: AMQ8006: IBM MQ queue created.

*オプションの説明
mqsc: MQSCコマンドの実行
-s : MQSCコマンド文字列

それでは、要求メッセージを送信後、ReplyToQ/ReplyToQMgr宛に返信された応答メッセージを受信するテストをしてみます。
この時、送信したMsgIdと同じ値のCorrelIdを持つメッセージのみを受信します。 このテストではmqpgfを要求側と応答側にひとつづつ下記オプションで起動します。 それぞれの起動オプションについて説明します。

SampleQM側で起動する要求送信/応答受信コマンド:
$ mqpgf -qm SampleQM -q RemoteQ -m "request reply test" -iq SampleQ -rm SampleQM -rq SampleQ MQMT_REQUEST MQPMO_NO_SYNCPOINT -n 3 -i 1000 -ss MQGMO_WAIT MQWI_UNLIMITED MQGMO_NO_SYNCPOINT -dp -mc

*オプションの説明
-iq: 入力キュー名
-rm: MQMD.ReplyToQMgrに設定する値を指定します。
-rq: MQMD.ReplyToQに設定する値を指定します。
MQMT_REQUEST: MQMD.MsgTypeにMQMT_REQUESTを設定します。
MQPMO_NO_SYNCPOINT: MQPMO.OptionsにMQPMO_NO_SYNCPOINTを設定します。
-n: put/getする回数を指定します。
-i: put/getを繰り返す間隔をms単位で指定します。
-ss: 以降のオプション/パラメータを入力側(2次側)に切り替えます。
MQGMO_WAIT: MQGMO.OptionsにMQGMO_WAITを設定します。
MQWI_UNLIMITED: MQGMO.WaitIntervalにMQWI_UNLIMITEDを設定します。
MQGMO_NO_SYNCPOINT: MQGMO.OptionsにMQGMO_NO_SYNCPOINTを設定します。
-dp: メッセージをGETし、"-br"と同様の形式でメッセージをダンプします。
-mc: 送信メッセージのMsgIdと同じCorrelIdを持つメッセージを受信します。


オプションの詳細を説明します。
 "-iq"で応答を受信するキュー名を指定します。
 "-rm"でMQMD.ReplyToQMgrに設定するキューマネージャー名を指定します。 指定しない場合のデフォルトはローカル・キューマネージャー名なので省略可能です。 MQMD.ReplyToQMgrはMQOD.ObjectQMgrNameに設定されます。
 "-rq"でMQMD.ReplyToQに設定するキュー名を指定します。
 MQMT_REQUESTは送信メッセージのMQMD.MsgTypeに設定されます。
 MQPMO_NO_SYNCPOINTはMQPUT()を作業単位内で呼び出さないようにします。
 "-ss"は"-iq"、"-oq"と共に使用し、後続のオプション/パラメータを"-q"で指定したキュー(1次側)ではなく"-iq"、"-oq"で指定したキュー(2次側)の為のものに切り替えます。
 MQGMO_WAITを指定すると、MQGET()はメッセージが到着するまで待機します。
 MQWI_UNLIMITEDは、MQGMO_WAITでの待機時間を無期限にします。
 MQGMO_NO_SYNCPOINTはMQGET()を作業単位内で呼び出さないようにします。
 "-dp"はブラウズ・オプションを指定しない(メッセージを読み込んだ後、キューからメッセージを消去する)こと以外は"-br"と同じです。
 "-mc"を指定すると、送信メッセージのMsgIdと同じCorrelIdを持つメッセージのみを待機します。 これにより要求と応答の紐づけが行われます。

RemoteQM側で起動する要求受信/応答送信コマンド:
$ mqpgf -qm RemoteQM -q RemoteQ -oq "*" MQGMO_WAIT MQWI_UNLIMITED MQGMO_NO_SYNCPOINT -dp -n 3 -ss MQMT_REPLY MQPMO_NO_SYNCPOINT -im

*オプションの説明
-oq: 出力キュー名
MQGMO_WAIT: MQGMO.OptionsにMQGMO_WAITを設定します。
MQWI_UNLIMITED: MQGMO.WaitIntervalにMQWI_UNLIMITEDを設定します。
MQGMO_NO_SYNCPOINT: MQGMO.OptionsにMQGMO_NO_SYNCPOINTを設定します。
-dp: メッセージをGETし、"-br"と同様の形式でメッセージをダンプします。
-n: PUT/GET処理を指定回数実行します。
-ss: 以降のオプション/パラメータを出力側(2次側)に切り替えます。
MQMT_REPLY: MQMD.MsgTypeにMQMT_REPLYを設定します。
MQPMO_NO_SYNCPOINT: MQPMO.OptionsにMQPMO_NO_SYNCPOINTを設定します。
-im: 受信メッセージのMQMDを送信メッセージへコピーします。


オプションの詳細をご説明します。
 "-oq"で受信したメッセージの転送先のキュー名を指定します。 "*"の指定は特別な意味を持ち、MQMD.ReplyToQおよびMQMD.ReplyToQMgrが参照されます。
MQMD.ReplyToQMgrはMQOD.ObjectQMgrNameに設定されます。
 MQGMO_WAITを指定すると、MQGET()はメッセージが到着するまで待機します。
 MQWI_UNLIMITEDは、MQGMO_WAITでの待機時間を無期限にします。
 MQGMO_NO_SYNCPOINTはMQGET()を作業単位内で呼び出さないようにします。 MQ for HP NonStopの場合はデフォルトで作業単位内で呼び出されるので動作が変わります。
 "-dp"はブラウズ・オプションを指定しない(メッセージを読み込んだ後、キューからメッセージを消去する)こと以外は"-br"と同じです。
 "-n"はメッセージの受信からメッセージの転送(送信)までを指定回数繰り返します。
 "-ss"は"-iq"、"-oq"と共に使用し、後続のオプション/パラメータを"-q"で指定したキュー(1次側)ではなく"-iq"、"-oq"で指定したキュー(2次側)の為のものに切り替えます。
 MQMT_REPLYは"-ss"以降に指定しているので転送(送信)メッセージのMQMD.MsgTypeに設定されます。
 MQPMO_NO_SYNCPOINTはMQPUT()を作業単位内で呼び出さないようにします。 MQ for HP NonStopの場合はデフォルトで作業単位内で呼び出されるので動作が変わります。
 "-im"を指定すると、受信メッセージのMQMDを送信メッセージへコピーします。 但し、コピーしただけでは引き継がれないフィールドもありますが、それらについては後程改めてご説明します。
 また、mqpgfはコマンドラインの2次側(出力側)引数にMQMT_REPORTまたはMQMT_REPLYが指定されており、かつMQRO_PASS_CORREL_IDが指定されていない場合、MQMD.MsgIdをMQMD.CorrelIdにコピーします。


Ex. 3.3 要求メッセージを送信後に対応する応答メッセージを受信する。

それでは、テストを実施してみます。


テスト結果3.3

まず、要求電文に関連するメッセージのみが受信されることを確認する為に、送受信するメッセージと関連のないダミーのメッセージをキューにPUTし、そのMsgIdを確認しておきます。

$ mqpgf -qm SampleQM -q SampleQ -m "dummy message" -n 3
[18/04/13 11:08:56] 1: message length: 13 put message : dummy message
[18/04/13 11:08:56] 2: message length: 13 put message : dummy message
[18/04/13 11:08:56] 3: message length: 13 put message : dummy message

$ mqpgf -qm SampleQM -q SampleQ -br -r
message number: 1
.... MsgId[0x414D512053616D706C65514D20202020A90ED05A23013202] CorrelId[0x000000000000000000000000000000000000000000000000] ....

message number: 2
.... MsgId[0x414D512053616D706C65514D20202020A90ED05A23013203] CorrelId[0x000000000000000000000000000000000000000000000000] ....

message number: 3
.... MsgId[0x414D512053616D706C65514D20202020A90ED05A23013204] CorrelId[0x000000000000000000000000000000000000000000000000] ....

要求送信/応答受信コマンドを起動します。
$ mqpgf -qm SampleQM -q RemoteQ -m "request reply test" -iq SampleQ -rm SampleQM -rq SampleQ MQMT_REQUEST MQPMO_NO_SYNCPOINT -n 3 -i 1000 -ss MQGMO_WAIT MQWI_UNLIMITED MQGMO_NO_SYNCPOINT -dp -mc
[18/04/13 11:46:12] 1: message length: 18 put message : request reply test

別のターミナル/コマンドプロンプトで、要求受信/応答送信コマンドを実行します。
$ mqpgf -qm RemoteQM -q RemoteQ -oq "*" MQGMO_WAIT MQWI_UNLIMITED MQGMO_NO_SYNCPOINT -dp -n 3 -ss MQMT_REPLY MQPMO_NO_SYNCPOINT -im
message number: 1
.... MsgId[0x414D512053616D706C65514D20202020A90ED05A23013502] CorrelId[0x000000000000000000000000000000000000000000000000] ....

message number: 2
.... MsgId[0x414D512053616D706C65514D20202020A90ED05A23013504] CorrelId[0x000000000000000000000000000000000000000000000000] ....

message number: 3
.... MsgId[0x414D512053616D706C65514D20202020A90ED05A23013506] CorrelId[0x000000000000000000000000000000000000000000000000] ....

受信した要求メッセージがダンプされます。
要求送信/応答受信コマンドを実行したターミナル/コマンドプロンプトにも、受信した応答メッセージがダンプされるはずです。
message number: 1
.... MsgId[0x414D512052656D6F7465514D202020204607D05A24B42602] CorrelId[0x414D512053616D706C65514D20202020A90ED05A23013502] ....

.... MsgId[0x414D512052656D6F7465514D202020204607D05A24B42604] CorrelId[0x414D512053616D706C65514D20202020A90ED05A23013504] ....

.... MsgId[0x414D512052656D6F7465514D202020204607D05A24B42606] CorrelId[0x414D512053616D706C65514D20202020A90ED05A23013506] ....

要求電文のMsgIdと同じ値をCorrelIdに持つメッセージがGETされていることが確認できます。

事前にダミーでPUTしておいたメッセージはそのままGETされずに残っています。
$ mqpgf -qm SampleQM -q SampleQ -r
[18/04/13 11:09:09] 1: message length: 13 get message : dummy message
[18/04/13 11:09:09] 2: message length: 13 get message : dummy message
[18/04/13 11:09:09] 3: message length: 13 get message : dummy message
no message available : SampleQ CompCd=02 ReasonCd=2033

fig 3.3

[ UserIdentifier ]

タイプ: MQCHAR12
サイズ: 12バイト
初期値: NULLストリング(C言語)
入出力: MQPUT()時: MQPMO_SET_IDENTITY_CONTEXTまたはMQPMO_SET_ALL_CONTEXT指定時は入出力、それ以外は出力、MQGET()時:出力

MQは3種類のメッセージ・コンテキスト情報をもっています。
識別コンテキスト情報、起点コンテキスト情報、およびユーザー・コンテキスト情報です。
このうち、ユーザー・コンテキストはメッセージ・プロパティーに設定するものですので、後ほど改めてご説明します。

MQMDの下記フィールが識別コンテキスト(IDコンテキスト)です。

UserIdentifier ユーザーID
AccountingToken アカウンティング・トークン
ApplIdentityData IDに関連する任意のデータ

このフィールドの値をキューマネージャーが生成(デフォルト)する場合には、ログオン・ユーザー名(Windows)、ログオン名または実効ユーザーID(Unix)等が設定されます。 詳細はプラットフォームにより異なりますので製品のマニュアルを参照してください。
注意点としては、メッセージ・チャネル間で大文字小文字の変換が発生する点です。分散系プラットフォームでは送信時にすべて大文字に変換され、受信時に小文字に変換されます。メインフレームの場合はすべて大文字で受信されます。ただしチャネルがメッセージExitを使用している場合、これらの変換は発生しません。また、クライアント接続時は、大文字小文字は変換されず、そのまま設定されていた通りに受信されます。

[ AccountingToken ]

タイプ: MQBYTE32
サイズ: 32バイト
初期値: MQACT_NONE_ARRAY(全てNULL(0x00)
入出力: MQPUT()時: MQPMO_SET_IDENTITY_CONTEXTまたはMQPMO_SET_ALL_CONTEXT指定時は入出力、それ以外は出力、MQGET()時:出力

UserIdentifierを補足する情報で、先頭に情報のバイト数、2バイト目以降にUNIXでは、数値文字列のユーザー ID、Windows では、セキュリティーID(SID)が設定されます(プラットフォームにより詳細は相違)。 最終バイトには下記のAccountingToken(会計トークン)のタイプを示すIDが設定されます。

MQACTT_CICS_LUOW_ID CICS LUOW ID
MQACTT_NT_SECURITY_ID Windows セキュリティー ID
MQACTT_OS400_ACCOUNT_TOKEN IBM i 会計トークン
MQACTT_UNIX_NUMERIC_ID UNIX システムの数値 ID
MQACTT_USER ユーザー定義の会計トークン
MQACTT_UNKNOWN 不明な会計トークン・タイプ

同名で再作成されたユーザーIDなども区別されるため、課金の目的などに利用できます。 Unix、Linux、Windowsの場合、キューマネージャーは上記値を設定しますが、MQ for HP NonStopではこのフィールドには全てNULLが設定されます。

[ ApplIdentityData ]

タイプ: MQCHAR32
サイズ: 32バイト
初期値: NULLストリング(C言語)
入出力: MQPUT()時: MQPMO_SET_IDENTITY_CONTEXTまたはMQPMO_SET_ALL_CONTEXT指定時は入出力、それ以外は出力、MQGET()時:出力

メッセージや発信元の追加情報など、任意の文字列を設定できます。デフォルトではキューマネージャーは全てブランク(" ")でこのフィールドを埋めます。

識別情報をアプリケーションから設定するには、MQPMO_SET_IDENTITY_CONTEXTまたはMQPMO_SET_ALL_CONTEXTを指定する必要があります。 また、MQPMO_SET_IDENTITY_CONTEXTを指定する場合はオープン・オプションのMQOO_SET_IDENTITY_CONTEXT、MQPMO_SET_ALL_CONTEXTを指定する場合はオープン・オプションのMQOO_SET_ALL_CONTEXTの指定が必要です。


Ex. 3.4 識別コンテキストの設定

UserIdentifierに"testuser"、AccountingTokenに任意の15バイトの値"6163636F756E74696E67746F6B656E"(16進表記)(先頭は情報のバイト数なので15の16進表記"0x0E"を指定)、会計トークン・タイプにMQACTT_USER(0x19)、ApplIdentityDataに"Application Identity Data"を設定してみます。


テスト結果3.4

$ mqpgf -qm SampleQM -q SampleQ -m "Set ID Context" -ui testuser -at 0x0E6163636F756E74696E67746F6B656E -ap "Application Identity Data" MQPMO_SET_IDENTITY_CONTEXT MQOO_SET_IDENTITY_CONTEXT MQACTT_USER
[18/04/13 16:36:15] 1: message length: 14 put message : Set ID Context

$ mqpgf -qm SampleQM -q SampleQ -dp
message number: 1
.... UserIdentifier[testuser ] AccountingToken[0x0E6163636F756E74696E67746F6B656E00000000000000000000000000000019] ApplIdentityData[Application Identity Data ] ....

data length: 14
00000000: 5365 7420 4944 2043 6F6E 7465 7874 'Set ID Context '

*オプションの説明
-ui: MQMD.UserIdentifierを指定します。
-at: MQMD.AccountingTokenを指定します。
-ap: MQMD.ApplIdentityDataを指定します。
MQPMO_SET_IDENTITY_CONTEXT: MQPMO.OptionsにMQPMO_SET_IDENTITY_CONTEXTを設定します。
MQOO_SET_IDENTITY_CONTEXT: MQOPEN()の引数OptionsにMQOO_SET_IDENTITY_CONTEXTを指定します。
MQACTT_USER: MQMD.AccountingTokenの最終バイトの会計トークン・タイプにMQACTT_USER(0x19)を設定します。


MQPMO_SET_ALL_CONTEXT、MQOO_SET_ALL_CONTEXTを指定した場合や、何も指定しない場合の結果なども確認してみてください。

fig 3.4

[ PutApplType ]

タイプ: MQLONG
サイズ: 4バイト
初期値: MQAT_NO_CONTEXT(0)
入出力: MQPUT()時: MQPMO_SET_ALL_CONTEXT指定時は入出力、それ以外は出力、MQGET()時:出力

このフィールドは起点コンテキスト情報で、メッセージを書き込むアプリケーションのタイプを示します。

MQMDの下記フィールが起点コンテキスト(Originコンテキスト)です。

PutApplType メッセージを書き込むアプリケーションのタイプ
PutApplName メッセージを書き込むアプリケーションの名前
PutDate メッセージが書き込まれたときの日付
PutTime メッセージが書き込まれたときの時刻
ApplOriginData 起点に関連する任意のデータ

MQPMO_SET_IDENTITY_CONTEXTが指定されていない場合、このフィールドの値をキューマネージャーが生成します。 設定されるデフォルトの値はプラットフォームによっても異なります。 種類も多く、代表的なものを下記に挙げます。

MQAT_AIX(6) AIXアプリケーション(MQAT_UNIX と同じ)
MQAT_GUARDIAN(13) Tandem Guardianアプリケーション(MQAT_NSKと同じ)
MQAT_JAVA(28) Java
MQAT_NSK(13) HP NonStop Serverアプリケーション
MQAT_OS390(2) OS/390アプリケーション(MQAT_ZOSと同じ)
MQAT_OS400(8) IBM iアプリケーション
MQAT_QMGR(7) キュー・マネージャー
MQAT_UNIX(6) UNIXアプリケーション
MQAT_WINDOWS_NT(11) 32ビットWindows アプリケーション
MQAT_ZOS(2) z/OSアプリケーション
MQAT_UNKNOWN(-1) アプリケーション・タイプが不明
MQAT_USER_FIRST(65536) ユーザー定義のアプリケーション・タイプの最低の値
MQAT_USER_LAST(999999999) ユーザー定義のアプリケーション・タイプの最高の値

例えばHP NonStopのOSS C言語アプリケーションの場合は、MQAT_NSK(13)が設定されます。 上記の事前定義の値をアプリケーションから指定することもできます。 また、MQAT_USER_FIRSTからMQAT_USER_LASTの範囲内でユーザー定義の値を設定することも可能です。

[ PutApplName ]

タイプ: MQCHAR28
サイズ: 28バイト
初期値: NULLストリング(C言語)
入出力: MQPUT()時: MQPMO_SET_ALL_CONTEXT指定時は入出力、それ以外は出力、MQGET()時:出力

メッセージを書き込むアプリケーションの名前を示します。 MQPMO_SET_IDENTITY_CONTEXTが指定されていない場合、このフィールドの値をキューマネージャーが生成します。 設定される内容の詳細はプラットフォームによっても異なりますので、詳細は製品マニュアルや実機検証で確認してください。 例えばWindowsではフルパスが入りますが、Unixではプログラム名のみが設定されます。

[ PutDate ]

タイプ: MQCHAR8
サイズ: 8バイト
初期値: NULLストリング(C言語)
入出力: MQPUT()時: MQPMO_SET_ALL_CONTEXT指定時は入出力、それ以外は出力、MQGET()時:出力

メッセージが書き込まれた日付を示します。 MQPMO_SET_IDENTITY_CONTEXTが指定されていない場合、このフィールドの値をキューマネージャーが生成します。 その場合はYYYYMMDDの形式でGMT(グリニッジ標準時)で設定されます。 システムは通常 JST(日本標準時)で運用する場合が多いですが、JSTに変換する場合は、後続のフィールドPutTimeに9時間を加算します。

JST=GMT+9h

コミットされた時刻ではなく、メッセージが書き込まれた時間(MQPUT()が呼び出された時間)であることに注意してください。

[ PutTime ]

タイプ: MQCHAR8
サイズ: 8バイト
初期値: NULLストリング(C言語)
入出力: MQPUT()時: MQPMO_SET_ALL_CONTEXT指定時は入出力、それ以外は出力、MQGET()時:出力

メッセージが書き込まれた時刻を示します。 MQPMO_SET_IDENTITY_CONTEXTが指定されていない場合、このフィールドの値をキューマネージャーが生成します。 その場合はHHMMSSTHの形式でGMT(グリニッジ標準時)で設定されます。 "T"は100ms、"H"は10msを示します。 "SS"は秒を示し、通常"00"から"59"が設定されますが、うるう秒が発生した場合は"60"または"61"という値が設定される場合があります。 前述の"PutDate"でご説明しましたが、JST(日本標準時)に変換する場合は9時間を加算します。
"PutDate"同様、コミットされた時刻ではなく、メッセージが書き込まれた時間(MQPUT()が呼び出された時間)が設定されます。

[ ApplOriginData ]

タイプ: MQCHAR4
サイズ: 4バイト
初期値: NULLストリング(C言語)
入出力: MQPUT()時: MQPMO_SET_IDENTITY_CONTEXTまたはMQPMO_SET_ALL_CONTEXT指定時は入出力、それ以外は出力、MQGET()時:出力

起点についての任意の追加情報を設定します。デフォルトではキューマネージャーは全てブランク(" ")でこのフィールドを埋めます。

起点情報をアプリケーションから設定するには、MQPMO_SET_ALL_CONTEXTを指定する必要があります。 また、MQPMO_SET_ALL_CONTEXTを指定する場合はオープン・オプションのMQOO_SET_ALL_CONTEXTの指定が必要です。


Ex. 3.5 起点コンテキストの設定

PutApplTypeにMQAT_JAVA(28)、PutApplNameに"testapl"、PutDateに"20140101"、PutTimeに"00112233"、ApplOriginDataに"orig"を設定してみます。


テスト結果3.5

$ mqpgf -qm SampleQM -q SampleQ -m "Set Origin Context" MQAT_JAVA -pn testapl -pd 20140101 -pt 00112233 -ao orig MQPMO_SET_ALL_CONTEXT MQOO_SET_ALL_CONTEXT
[18/04/16 14:59:26] 1: message length: 18 put message : Set Origin Context

$ mqpgf -qm SampleQM -q SampleQ -dp
message number: 1
.... PutApplType[28] PutApplName[testapl ] PutDate[20140101] PutTime[00112233] ApplOriginData[orig] ....

*オプションの説明
MQAT_JAVA: MQMD.PutApplTypeにMQAT_JAVA(28)を設定します。
-pn: MQMD.PutApplNameを指定します。
-pd: MQMD.PutDateを指定します。
-pt: MQMD.PutTimeを指定します。
-ao: MQMD.ApplOriginDataを設定します。


MQPMO_SET_ALL_CONTEXT、MQOO_SET_ALL_CONTEXTを指定した場合や、何も指定しない場合の結果なども確認してみてください。

fig 3.5

識別コンテキストと起点コンテキストのご説明の最後に、メッセージ間でのコンテキストの引継ぎについてご説明します。 ReplyToQMgrのご説明で、"-im: 受信メッセージのMQMDを送信メッセージへコピーする"というオプションについてご紹介し、そしてテスト結果3.3で使用しました。 -imを指定した時、識別、起点コンテキストに関して引き継がれたかどうかを確認してみます。


Ex. 3.6 メッセージ間でのコンテキスト情報の引継ぎ

分かりやすいように、送信側でコンテキスト情報を任意の値に設定します。

SampleQM側で起動する要求送信/応答受信コマンド:
$ mqpgf -qm SampleQM -q RemoteQ -m "test context" -iq SampleQ -rm SampleQM -rq SampleQ MQMT_REQUEST MQPMO_NO_SYNCPOINT -ui testuser -at 0x0E6163636F756E74696E67746F6B656E -ap "Application Identity Data" MQACTT_USER MQAT_JAVA -pn testapl -pd 20140101 -pt 00112233 -ao orig MQPMO_SET_ALL_CONTEXT MQOO_SET_ALL_CONTEXT -ss MQGMO_WAIT MQWI_UNLIMITED MQGMO_NO_SYNCPOINT -dp -mc

RemoteQM側で起動する要求受信/応答送信コマンド:
$ mqpgf -qm RemoteQM -q RemoteQ -oq "*" MQGMO_WAIT MQWI_UNLIMITED MQGMO_NO_SYNCPOINT -dp -ss MQMT_REPLY MQPMO_NO_SYNCPOINT -im


テスト結果3.6

RemoteQM側で受信したメッセージ:
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[1] Expiry[-1] Feedback[0] Encoding[546] CodedCharSetId[932] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D202020208C0ED45A2586B602] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[SampleQ ] ReplyToQMgr[SampleQM ] UserIdentifier[testuser ] AccountingToken[0x0E6163636F756E74696E67746F6B656E00000000000000000000000000000019] ApplIdentityData[Application Identity Data ] PutApplType[28] PutApplName[testapl ] PutDate[20140101] PutTime[00112233] ApplOriginData[orig]

GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]

data length: 12
00000000: 7465 7374 2063 6F6E 7465 7874 'test context '

[18/04/16 15:57:28] 1: message length: 12 put message : test context

SampleQM側で受信したメッセージ:
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[2] Expiry[-1] Feedback[0] Encoding[546] CodedCharSetId[932] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512052656D6F7465514D202020204746D45A223AE402] CorrelId[0x414D512053616D706C65514D202020208C0ED45A2586B602] BackoutCount[0] ReplyToQ[SampleQ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x16010515000000DBEB0C50B47B733407E53B2B8433260000000000000000000B] ApplIdentityData[ ] PutApplType[11] PutApplName[am\win\mqpgf\Debug\mqpgf.exe] PutDate[20180416] PutTime[06572870] ApplOriginData[ ]

GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]

data length: 12
00000000: 7465 7374 2063 6F6E 7465 7874 'test context '

識別コンテキスト情報も、起点コンテキスト情報も全く引き継がれていないことが確認できると思います。 実は、コンテキスト情報を引き継ぐ場合、MQMDのコンテキスト情報のフィールドのコピーは必要はなく、"-im"オプションの指定も必要ありません。
識別/起点コンテキスト情報は下記の手順でのみ次のメッセージへ引き継がれます。

  1. 1. 受信キューのオープン時にMQOO_SAVE_ALL_CONTEXTを指定します。
  2. 2. 送信キューのオープン時にMQOO_PASS_ALL_CONTEXTを指定します。
  3. 3. 受信キューをオープン時のオプジェクトハンドル(pHobj引数)を、MQPMO.Contextに設定します。
  4. 4. MQPUT時にMQPMO_PASS_ALL_CONTEXTを指定します。
MQOO_SAVE_ALL_CONTEXT オプションを指定しない場合は、元のメッセージのコンテキスト情報は保管されません。 識別コンテキストのみ引き継ぐ場合は、MQOO_PASS_ALL_CONTEXTの代わりにMQOO_PASS_IDENTITY_CONTEXT、MQPMO_PASS_ALL_CONTEXTの代わりにMQPMO_PASS_IDENTITY_CONTEXTを指定します。 mqpgfはMQPMO_PASS_*が指定されている場合、自動的に入力キューのハンドルをMQPMO.Contextに設定します。

これらのオプションを「RemoteQM側で起動する要求受信/応答送信コマンド」に追加して実行してみます。

RemoteQM側で起動する要求受信/応答送信コマンド:
$ mqpgf -qm RemoteQM -q RemoteQ -oq "*" MQGMO_WAIT MQWI_UNLIMITED MQGMO_NO_SYNCPOINT MQOO_SAVE_ALL_CONTEXT -dp -ss MQMT_REPLY MQPMO_NO_SYNCPOINT MQOO_PASS_ALL_CONTEXT MQPMO_PASS_ALL_CONTEXT


テスト結果3.7

$ mqpgf -qm SampleQM -q RemoteQ -m "test context" -iq SampleQ -rm SampleQM -rq SampleQ MQMT_REQUEST MQPMO_NO_SYNCPOINT -ui testuser -at 0x0E6163636F756E74696E67746F6B656E -ap "Application Identity Data" MQACTT_USER MQAT_JAVA -pn testapl -pd 20140101 -pt 00112233 -ao orig MQPMO_SET_ALL_CONTEXT MQOO_SET_ALL_CONTEXT -ss MQGMO_WAIT MQWI_UNLIMITED MQGMO_NO_SYNCPOINT -dp -mc
[18/04/17 17:06:57] 1: message length: 12 put message : test context
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[2] Expiry[-1] Feedback[0] Encoding[546] CodedCharSetId[932] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512052656D6F7465514D20202020499FD55A2501E402] CorrelId[0x414D512053616D706C65514D202020203B9FD55A211D8602] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[RemoteQM ] UserIdentifier[testuser ] AccountingToken[0x0E6163636F756E74696E67746F6B656E00000000000000000000000000000019] ApplIdentityData[Application Identity Data ] PutApplType[28] PutApplName[testapl ] PutDate[20140101] PutTime[00112233] ApplOriginData[orig]

GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]

data length: 12 00000000: 7465 7374 2063 6F6E 7465 7874 'test context '

$ mqpgf -qm RemoteQM -q RemoteQ -oq "*" MQGMO_WAIT MQWI_UNLIMITED MQGMO_NO_SYNCPOINT MQOO_SAVE_ALL_CONTEXT -dp -ss MQMT_REPLY MQPMO_NO_SYNCPOINT MQOO_PASS_ALL_CONTEXT MQPMO_PASS_ALL_CONTEXT
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[1] Expiry[-1] Feedback[0] Encoding[546] CodedCharSetId[932] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D202020203B9FD55A211D8602] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[SampleQ ] ReplyToQMgr[SampleQM ] UserIdentifier[testuser ] AccountingToken[0x0E6163636F756E74696E67746F6B656E00000000000000000000000000000019] ApplIdentityData[Application Identity Data ] PutApplType[28] PutApplName[testapl ] PutDate[20140101] PutTime[00112233] ApplOriginData[orig]

GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]

data length: 12 00000000: 7465 7374 2063 6F6E 7465 7874 'test context '

[18/04/17 17:07:03] 1: message length: 12 put message : test context

識別/起点コンテキスト情報の全てが引き継がれてることが確認できます。

fig 3.6

以上で、MQMDのVersion 1のフィールドについての説明は終わりです。次回は、MQMD Version 2で追加されたフィールドについてご説明します。

このページの先頭へ

このページの先頭へ