実践習得 IBM MQの基本
メッセージ記述子(MQMD)(2)
※本連載は最新のmqpgf/mqpcfに基づいて改定されることがあります。 常に最新バージョンをダウンロードしてご使用ください。
[ Expiry ]
タイプ: MQLONG
サイズ: 4バイト
初期値: MQEI_UNLIMITED(-1)
入出力: MQGET()時:出力、MQPUT()時:入力
メッセージの持続時間です。
MQPUT()時に100ms単位で指定します。
デフォルトではMQEI_UNLIMITED(-1)が設定され、持続時間は無期限です。
MQGET()時に得られる値は、減算された有効期限の残り時間です。
メッセージを中継する場合、MQGET()で受信した値をMQPUT()時に引き継ぐ様にすると、そのメッセージがシステムを流れる期間の有効期限として使用できます。
(参考までに、設計によりますが、MQMDの各値は中継するプロセスが引き継ぐようにする場合が多いです。)
Ex. 2.1 持続時間経過後のメッセージ削除のタイミング確認
SampleQMからMQPUT()時にExpiryを設定し、RemoteQMでその値を確認してみます。
"-ex"の後に100ms単位の値を設定します。
※これ以降、コマンドの実行場所は省略します。
SampleQMとRemoteQMが別々のマシンまたは別々のインストール環境にある場合は、コマンドの実行場所は"-qm"に指定しているキューマネージャー名で適切に判断してください。
テスト結果2.1.1
$ mqpgf -qm SampleQM -q RemoteQ -m "expiry test message" -ex 100
[18/02/20 18:56:52] 1: message length: 19 put message : expiry test message
$ mqpgf -qm RemoteQM -q RemoteQ -br
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[47] ....
....
$ mqpgf -qm RemoteQM -q RemoteQ -br
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[16] ....
....
$ mqpgf -qm RemoteQM -q RemoteQ -br
no message available : RemoteQ CompCd=02 ReasonCd=2033
*オプションの説明
-ex: メッセージの持続時間(100ms単位)
メッセージの内容をブラウズする度にExpiryの値が減算され、10秒経過後にメッセージが消去され参照できなくなることが確認できます。 理由コード"2033"はMQRC_NO_MSG_AVAILABLEの意味で、MQGET()が発行されたときにメッセージがキュー上になかったことを示します。 この時完了コードが"2"(MQCC_FAILED)に設定されるので、なにか異常が発生したと誤解されることがありますが、取得するメッセージがなかったこと以上を示すものではありません。 有効期限が切れたメッセージが消去されずにキューに残っている状態でMQGET()を発行しても、それ以外の特別な状態が発生することはありません。
持続時間が満了したメッセージのキュー上から廃棄されるタイミングに注意してください。
簡単にはMQGET()が発行されたタイミングで削除されますが、MQGET()が実行されない場合は、キューマネージャーによって一定周期で持続時間が満了したメッセージがチェックされ削除されます。
この周期は持続時間が満了してからの時間ではなく、キューマネージャー内部でもっている周期です。
例えば、MQ9.0 for Windowsの場合は5分周期(0~5分)、MQ5.3 for HPNonStopの場合は1分周期(0~1分)で削除されます。
この様子を簡単に確認してみます。
テスト結果2.1.2
まず、mqpcfのques(Inquire Queue Status)コマンドを10秒間隔で連続実行("-i 10")、実行時間の表示("-t")、CURDEPTHの表示を指定して起動しておきます。
$ mqpcf ques -qm SampleQM -q SampleQ -i 10 -t CURDEPTH
[18/02/20 19:53:51] 1: QUEUE(SampleQ) TYPE(QUEUE) CURDEPTH(0)
[18/02/20 19:54:01] 1: QUEUE(SampleQ) TYPE(QUEUE) CURDEPTH(0)
....
他のターミナル/コマンドプロンプトから先ほどと同様に10秒のExpiryを指定してメッセージをPUTします。
$ mqpgf -qm SampleQM -q SampleQ -m "expiry test message" -ex 100
[18/02/20 19:54:04] 1: message length: 19 put message : expiry test messagee
mqpcfの出力から5分以内(MQ9.0 for Windowsの場合)にCURDEPTHが"0"になることが確認できます。
[18/02/20 19:54:11] 1: QUEUE(SampleQ) TYPE(QUEUE) CURDEPTH(1)
....
[18/02/20 19:57:42] 1: QUEUE(SampleQ) TYPE(QUEUE) CURDEPTH(1)
[18/02/20 19:57:52] 1: QUEUE(SampleQ) TYPE(QUEUE) CURDEPTH(0)
*オプションの説明(mqpcf)
-i: 繰り返し実行の間隔(秒)
-t: 実行時間の表示
[ Feedback ]
タイプ: MQLONG
サイズ: 4バイト
初期値: MQFB_NONE(0)
入出力: MQGET()時:出力、MQPUT()時:入力
このフィールドについては、Reportフィールドで簡単にご説明し、「テスト結果1.3.2」でMQFB_COAおよびMQFB_CODが設定されるケースについて確認しました。
FeedbackフィールドはMQMD.MsgTypeがMQMT_REPORTの場合に使用されますが、例外レポートの場合などはMQの理由コードが設定され、状況により様々な値が設定されます。
発生した問題の原因を示すものですので、原因調査の為に必ずアプリケーションのログ等に出力する様にします。
理由コードの詳細については製品のマニュアルをご確認ください。
Ex. 2.2 例外レポートでFeedbackに理由コードが設定されるケースの確認
例外レポートで理由コードが設定されるケースを確認します。
テスト結果2.2
送信先のキューを書き込み禁止に設定します。
$ mqpcf put disable -qm RemoteQM -q RemoteQ
Put Disabled : RemoteQ
書込みが禁止になっていることを確認します。
$ mqpcf que -qm RemoteQM -q RemoteQ PUT
1: QUEUE(RemoteQ) TYPE(QLOCAL) PUT(DISABLED)
書込み禁止になっているキューにメッセージを送信します。
$ mqpgf -qm SampleQM -q RemoteQ -m "mqmd.Feadback test" -rq ReportQ MQRO_EXCEPTION MQMT_REQUEST
[18/02/21 19:00:09] 1: message length: 18 put message : mqmd.Feadback test
ReplyToQに設定したキューに戻されたレポート・メッセージを確認します。
$ mqpgf -qm SampleQM -q ReportQ -br
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[4] Expiry[-1] Feedback[2051] ....
....
mqrcコマンドを使用して、Feedbackに設定された理由コードの意味を確認します。
MQRC_PUT_INHIBITEDは書き込み禁止であったためにPUTできなかったことを示します。
$ mqrc 2051
2051 0x00000803 MQRC_PUT_INHIBITED
テストが終わったら、書き込みを許可に戻しておきます。
$ mqpcf put enable -qm RemoteQM -q RemoteQ
Put Enabled : RemoteQ
*オプションの説明(mqpcf)
put {enable | disable}: "Change Queue"コマンドを実行し、書き込みを禁止または許可に設定
que: "Inquire Queue"コマンドを実行
PUT: PUTフィールドを表示
*オプションの説明(mqpgf)
MQRO_EXCEPTION: 例外レポーを生成
[ Encoding ]
タイプ: MQLONG
サイズ: 4バイト
初期値: MQENC_NATIVE(システムに依存)
入出力: MQGET()時:出力(但し、MQGMO_CONVERT オプションを指定する場合は入出力フィールド)、MQPUT()時:入力
エンコーディングは、4bit毎に下位から"Binary Integers"、"Packed Decimal Integers"、"Floating Point Numbers"が割り当てられています。 そして、それらのそれぞれについて"NORMAL"か"REVERSED"であるかが示されます。 ただ、通常はこの3つの数値の形式を意識することはほとんどありません。 システム毎に異なるエンコーディング方式を表す値がデフォルトのMQENC_NATIVEに設定されています。 例えば、Windowsなどx86系のCPUのシステムの場合は、MQENC_NATIVEは0x00000222(10進数の546)で全てREVERSED。 HPNonStopの場合は、0x00000111(10進数の273)で全てNORMALです。 この様に異なるシステム間でメッセージを交換する際にエンコーディングの変換が必要になる場合があります。 (エンコーディングの変換については後述します。)
[ CodedCharSetId ]
タイプ: MQLONG
サイズ: 4バイト
初期値: MQCCSI_Q_MGR(キューマネージャーのCCSIDフィールドの値、MQクライアント・アプリケーションの場合はシステムのロケール)
入出力: MQGET()時:出力(但し、MQGMO_CONVERT オプションを指定する場合は入出力フィールド)、MQPUT()時:入力
デフォルトのMQCCSI_Q_MGRをこのフィールドに指定した場合は、キュー・マネージャーのCCSIDプロパティに設定されているCCSIDが設定されます。
キューマネージャーを作成した時、この値はそのシステムのロケールに従って設定されます。
キューマネージャーのCCSIDはそのプラットフォームがサポートする他のCCSIDに変更することも可能です。
MQクライアント・アプリケーションの場合は、そのアプリケーションが稼働しているシステムのロケールから決定されます。
(MQクライアントについては別途ご説明します。)
MQMDのCodedCharSetIdフィールドの値は、メッセージ本体の最初のヘッダまたはデータの文字コードを示します。
よく誤解されますが、MQMD自体の文字コードを示すものではありません。
MQGET()やMQPUT()に指定するMQMDの文字コードは、MQMDのCodedCharSetIdの設定値に関わらず、キュー・マネージャーのCCSIDに設定している文字コードを使用する必要があります。
例えば、Shift-JIS(コードページ932)で運用しているWindowsで、例外的にEBCDICのメッセージを送信する場合、MQMDはコードページ932で作成してMQPUT()へ渡し、そのMQMDのCodedCharSetIdには例えば日本語のEBCDICを示す930を設定します。
異なるシステム間でメッセージを交換する際に文字コードの変換が必要になる場合があります。
(文字コードの変換については後述します。)
[ Format ]
タイプ: MQCHAR8
サイズ: 8バイト
初期値: MQFMT_NONE(8Byteのスペース)
入出力: MQGET()時:出力(但し、MQGMO_CONVERT オプションを指定する場合は入出力フィールド)、MQPUT()時:入力
メッセージのフォーマットを示す任意の名前を半角のアルファベットの大文字および数字で設定することができます。 但し、"MQ"で始まる文字列はQmgrで事前に定義されたものに限って使用できます。 ユーザーが作成した"データ変換出口"のオブジェクトの名前にすることもできます。 事前定義の名前を使用する場合は、メッセージ本体の最初のヘッダやデータのフォーマットの形式を正しく示すものを指定します。 事前定義の名前の中には、通常キューマネージャーが作成するメッセージやフォーマットを示すものもあります。 よく使用する(される)フォーマットは下記です。
フォーマット名 | フォーマットの説明 | データ変換 |
---|---|---|
MQFMT_NONE | データの性質は未定義(デフォルト) | × |
MQFMT_STRING | 文字列 | 〇 |
MQFMT_ADMIN | コマンドサーバーへの要求 | 〇 |
MQFMT_DEAD_LETTER_HEADER | 送達不能ヘッダー | 〇 |
MQFMT_EVENT | イベント・メッセージ | 〇(Ver2はz/OSのみ) |
MQFMT_MD_EXTENSION | 拡張メッセージ記述子 | 〇 |
MQFMT_PCF | ユーザー定義PCFメッセージ | 〇 |
MQFMT_RF_HEADER_2 | RFヘッダー・バージョン 2 | 〇 |
MQFMT_TRIGGER | トリガー・メッセージ | 〇 |
この表にあるように、文字列のみのデータ、定義済みヘッダ、MQFMT_ADMIN、MQFMT_EVENTなどのPCF形式のメッセージでデータ変換が可能です。
データ変換の対象は数値のエンコーディングと文字コードの両方です。
ユーザー定義のPCFで複数の文字コードが混在する場合などでもコード変換が可能です。
MQでのコード変換はMQGET()呼び出し時にMQGMO_CONVERTオプションを指定してデータ変換される方法と、送信側チャネルのCONVERTプロパティに"YES"を設定して送信側チャネルで変換させる方法があります。
チャネルでのデータ変換の場合はメッセージの送信前(チャネルプログラムが伝送キューからメッセージをGETした時)にデータ変換が行われます。
その為、送信元、送信先のどちらのキュー上にも(可読性がない)相手先の文字コードのメッセージは表れません。
これは、障害時等のキュー上のメッセージの内容の確認に、相手先の文字コードを意識する(取り扱う)必要がないことを意味しますので、可能なかぎり送信側チャネルの変換を検討します。
MQクライアント・アプリケーションからサーバー側とことなる文字コードでメッセージが渡される場合は、サーバー側のアプリケーションで変換することが必要になります。
MQGET()時のMQGMO_CONVERTで変換させる場合は、MQMDのCodedCharSetIdとMQGET()時に入力として指定したMQMDのCodedCharSetIdの間で変換が行われます。
チャネルのCONVERT(YES)プロパティで変換させる場合は、組み込みMQMD(後述)のCodedCharSetIdと相手先(送信先)キューマネージャーのCCSIDプロパティ間で変換が行われます。
それでは、この2つの方法を簡単な例でテストしてみます。
Ex. 2.3 チャネルでのデータ変換
まず、チャネルで変換させてみます。
キューマネージャーのCCSIDをテストの為に下記の様に設定します。
SampleQM: | 932(Shift-JIS) |
RemoteQM: | 1208(UTF-8) |
※ご利用の環境によっては上記のCCSDが設定できない場合があります。
例えばオープン系のマシン上のキューマネージャーにEBCDICのCCSIDを設定する場合等です。
また、コード変換がサポートされていない場合は、チャネルが接続できない場合もあります。
使用可能なCCSIDとコード変換のサポートについては、MQのKnowledge Centerで詳細を確認してください。
テストするデータは全角の"ABC"を使用します。
Shift-JIS | UTF-8 | |
---|---|---|
A: | 0x8260 | 0xEFBCA |
B: | 0x8261 | 0xEFBCA2 |
C: | 0x8262 | 0xEFBCA3 |
キューマネージャーのCCSIDを設定します。
<< SampleQMでの作業 >>
alter qmgr ccsid(932) 2 : alter qmgr ccsid(932) AMQ8005: IBM MQ キュー・マネージャーが変更されました。 dis qmgr ccsid 15 : dis qmgr ccsid AMQ8408: キュー・マネージャーの内容を表示します。 QMNAME(SampleQM)
<< RemoteQMでの作業 >>
MQSC > alter qmgr ccsid(1208)
6 : alter qmgr ccsid(1208)
AMQ8005: IBM MQ queue manager changed.
AMQ8408: Display Queue Manager details.
QMNAME(RemoteQM) CCSID(1208)
今回のテストとは直接関係がありませんが、キューマネージャーのCCSIDを変更した場合は、コマンドサーバーは再起動が必要です。
$ endmqcsv
IBM MQ command server ending.
IBM MQ command server ended.
$ strmqcsv
IBM MQ command server started.
※念のため、変更を完全に有効にするためにキューマネージャーを再起動しても構いません。
チャネルのCONVERTプロパティをYESに設定します。 有効にするにはチャネルの再起動が必要です。
$ mqpcf stp -qm SampleQM -c SampleQM.TO.RemoteQM
Channel Stop Success. Channel Name : SampleQM.TO.RemoteQM Connection Name : Queue Manager :
alter chl('SampleQM.TO.RemoteQM') chltype(sdr) convert(yes)
3 : alter chl('SampleQM.TO.RemoteQM') chltype(sdr) convert(yes)
AMQ8016: IBM MQ チャネルが変更されました。
dis chl('SampleQM.TO.RemoteQM') convert
4 : dis chl('SampleQM.TO.RemoteQM') convert
AMQ8414: チャネルの内容を表示します。
CHANNEL(SampleQM.TO.RemoteQM) CHLTYPE(SDR)
CONVERT(YES)
コード変換前のデータを伝送キュー上で確認する為に、チャネルは停止したままにします。
全角の"ABC"をShit-JISの16進表記でPUTします。
$ mqpgf -qm SampleQM -q RemoteQ -mx 826082618262 MQFMT_STRING
[18/02/28 16:12:21] 1: message length: 6 put message : 0x826082618262
*オプションの説明
-mx: 入力メッセージ(16進表記)
伝送キュー上のPUTされたメッセージを確認します。 伝送キューは通常読み込みが禁止に設定されているので、読み込み許可に変更してからブラウズします。
$ mqpcf get enable -qm SampleQM -q RemoteQM
Get Enabled : RemoteQM
$ mqpgf -qm SampleQM -q RemoteQM -brv
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[546] CodedCharSetId[932] Format[MQXMIT ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D20202020CA52965A258FD603] CorrelId[0x414D512053616D706C65514D20202020CA52965A258FD602] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x16010515000000DBEB0C50B47B733407E53B2B8433260000000000000000000B] ApplIdentityData[ ] PutApplType[7] PutApplName[SampleQM ] PutDate[20180228] PutTime[07122197] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
*StrucId[XQH ] Version[1] RemoteQName[RemoteQ ] RemoteQMgrName[RemoteQM ]
*StrucId[MD ] Version[1] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[546] CodedCharSetId[932] Format[MQSTR ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D20202020CA52965A258FD602] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x16010515000000DBEB0C50B47B733407E53B2B8433260000000000000000000B] ApplIdentityData[ ] PutApplType[11] PutApplName[\cprog\win\mqpgf14\mqpgf.exe] PutDate[20180228] PutTime[07122197] ApplOriginData[ ]
data length: 434
00000000: 8260 8261 8262 'ABC '
伝送キュー内のメッセージは下記の形式になっています。
[独立MQMD(separate MQMD)] (+) [伝送キューヘッダ] + [組み込みMQMD(embedded MQMD)] + [ユーザー・メッセージ]
独立メッセージ記述子は、キュー・マネージャーにより生成されるもので、組み込みメッセージ記述子はアプリケーションが指定したMQMDです。
組み込みMQMD(2番目のMQMD)のEncoding、CodedCharSetId、Formatおよびデータを確認します。 サンプルのテストでは下記の様になっています。
Encoding: | 546(REVERCED)(x86系のCPUの場合) | |
CodedCharSetId: | 932(Shift-JIS) | |
Format: | MQSTR(文字列) | |
data: | 0x8260 8261 8262 | (Shift-JISの全角"ABC") |
※data lengthは下記の合計です。
伝送キューヘッダ: | 104Byte |
組み込みMQMD(V1)の長さ: | 324Byte |
メッセージ長(3(文字)*2(DBCS)): | 6Byte |
チャネルを開始し、伝送キュー上のメッセージを送信させます。
$ mqpcf sta -qm SampleQM -c SampleQM.TO.RemoteQM
Channel Start Success. Channel Name : SampleQM.TO.RemoteQM
転送先でメッセージをブラウズモードで表示させます。
テスト結果2.3
$ mqpgf -qm RemoteQM -q RemoteQ -br
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[1208] Format[MQSTR ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D20202020CA52965A258FD602] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x16010515000000DBEB0C50B47B733407E53B2B8433260000000000000000000B] ApplIdentityData[ ] PutApplType[11] PutApplName[\cprog\win\mqpgf14\mqpgf.exe] PutDate[20180228] PutTime[07122197] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
data length: 9
00000000: EFBC A1EF BCA2 EFBC A3 '......... '
MQMDのEncoding、CodedCharSetIdの値、およびデータが変換されていることを確認します。 サンプルのテストでは下記の様になっています。
Encoding: | 273(NORMAL) | |
CodedCharSetId: | 1208(UTF-8) | |
data: | 0xEFBCA1 EFBCA2 EFBCA3 | (UTF-8の全角"ABC") |
テストが終わったらチャネルのCONVERTプロパティをNOに戻し、チャネルを再起動します。
alter chl('SampleQMW.RemoteQM') chltype(sdr) convert(no) 2 : alter chl('SampleQMW.RemoteQM') chltype(sdr) convert(no) AMQ8016: IBM MQ チャネルが変更されました。
必要に応じてキューマネージャーのCCSIDも元に戻します。
Ex. 2.4 MQRFH2を持つメッセージをMQGET時にデータ変換する。
次に、MQGET()時にMQGMO_CONVERTを指定してデータ変換してみます。
RFH2ヘッダーとユーザーデータを同時にデータ変換する例です。
先ほどはエンコーディングの変換は確認しませんでしたが、今回はRFH2ヘッダーのエンコーディングも変換してみます。
このテストでは変換元、返還後共のEncoding、CodedCharSetIdを指定しますので、キューマネージャーのCCSIDやシステムのエンコーディングに依存しません。
下記を指定してメッセージをPUTします。
MQMD.Encoding: | 273(Big Endian) | |
MQMD.CharSetId: | 943(SHIFT_JIS:新JIS) | |
MQRFH2.CodedCharSetId: | 5050(eucJP) | |
MQRFH2.NameValueData: | 任意の半角英数字 | Ascii相当 |
data: | 0x8eb1 8eb2 8eb3 | eucJPの半角"アイウ"に相当する16進表記の文字列 |
※MQMD.EncodingおよびMQMD.CharSetIdは、MQMDではなくRFH2のエンコーディング、文字コードを表します。
※MQRFH2.CodedCharSetIdは、RFH2自体やMQRFH2.NameValueDataではなく、NameValuDataにつづくユーザー・データの文字コードを表します。
多少長いですが、下記の引数でメッセージをPUTします。
$ mqpgf -qm SampleQM -q SampleQ -ec 273 -cc 943 -mx 8eb18eb28eb3 -rf MQFMT_STRING -nd "test1,test2ru2,test333" MQFMT_RF_HEADER_2 -rc 5050
[18/02/28 19:57:35] 1: message length: 6 put message : 0x8EB18EB28EB3
*オプションの説明
-ec: MQMD.Encoding
-cc: MQMD.CodedCharSetId
-rf: MQRFH2.Format
-nd: MQRFH2.NameValueData
-rc: MQRFH2.CodedCharSetId
MQFMT_RF_HEADER_2: MQRFH2を付加
データ変換せずにPUTしたメッセージの内容を確認します。 後で比較しやすいように"-brv"と"-br"の両方でダンプしてみます。
$ mqpgf -qm SampleQM -q SampleQ -brv
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[943] Format[MQHRF2 ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A9637CC2000290B] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180228] PutTime[10573561] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
*StrucId[RFH ] Version[2] StrucLength[72] Encoding[273] CodedCharSetId[5050] Format[MQSTR ] Flags[0] NameValueCCSID[1208]
NameValueLength[8] NameValueData[test1 ]
NameValueLength[8] NameValueData[test22 ]
NameValueLength[8] NameValueData[test333 ]
data length: 78
00000000: 8EB1 8EB2 8EB3 '...... '
$ mqpgf -qm SampleQM -q SampleQ -br
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[943] Format[MQHRF2 ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A9637CC2000290B] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180228] PutTime[10573561] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
data length: 78
00000000: 5246 4820 0000 0002 0000 0048 0000 0111 'RFH .......H....'
00000010: 0000 13BA 4D51 5354 5220 2020 0000 0000 '....MQSTR ....'
00000020: 0000 04B8 0000 0008 7465 7374 3120 2020 '........test1 '
00000030: 0000 0008 7465 7374 3232 2020 0000 0008 '....test22 ....'
00000040: 7465 7374 3333 3320 8EB1 8EB2 8EB3 'test333 ......
それではMQGET()時に、MQMD.Encoding=546(Little Endian)、MQMD.CharSetId=930(EBCDIC)を指定してコード変換を実行してみます。
テスト結果2.4
$ mqpgf -qm SampleQM -q SampleQ -br MQGMO_CONVERT -ec 546 -cc 930
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[546] CodedCharSetId[930] Format[MQHRF2 ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A9637CC2000290B] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180228] PutTime[10573561] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
data length: 75
00000000: D9C6 C840 0200 0000 4800 0000 2202 0000 '...@....H..."...'
00000010: A203 0000 D4D8 E2E3 D940 4040 0000 0000 '.........@@@....'
00000020: B804 0000 0800 0000 7465 7374 3120 2020 '........test1 '
00000030: 0800 0000 7465 7374 3232 2020 0800 0000 '....test22 ....'
00000040: 7465 7374 3333 3320 8182 83 'test333 ... '
*オプションの説明
MQGMO_CONVERT: MQGMO.Optionsに設定します。
それでは、変換された内容を細かく確認してみます。
00000000-00000003 : D9C6 C840 (StrucIdの"RFH ")
MQRFH2自体の文字コードが、SHIFTJIS(CCSID 943)からEBCDIC(CCSID 930)に変換されている。
00000004-00000007 : 0200 0000 (MQRFH_VERSION_2(2) Big Endianの場合 0000 0002)
MQRFH2自体のエンコードが、Little Endianに変換されている。
0000000C-0000000F : 2202 0000 (MQRFH2.Encoding(546) Big Endianの場合 0000 0222)
MQRFH2.Encodingが546(Little Endian)に設定されている。
00000010-00000011 : A203 0000 (MQRFH2.CodedCharSetId(930) Big Endianの場合 0000 03A2)
MQRFH2.CodedCharSetIdがEBCDIC(CCSID 930)に設定されている。
00000020-00000023 : B804 0000 (MQRFH2.NameValueCCSID(1208) Big Endianの場合 0000 04B8
MQRFH2.NameValueCCSIDはUTF-8(CCSID 1208)のまま(NameValueDataはUTF-8固定でデータ変換の対象にならない)。
00000048-0000004a : 8182 83 (日本語EBCDICの半角"アイウ")
ユーザーデータがeucJPから日本語EBCDICにに変換されている。
(16進ダンプの右側の文字表記はプログラム(mqpgf)を実行した環境のロケールの可視文字を表示しています。
今回変換先の文字コードとして指定したEBCDICでの文字表記を示していないのでご注意ください。)
[ Priority ]
タイプ: MQLONG
サイズ: 4バイト
初期値: MQPRI_PRIORITY_AS_Q_DEF(-1)
入出力: MQGET()時:出力、MQPUT()時:入力
メッセージをキューに書き込むとき、メッセージの優先順位を (MQMD 構造体の Priority フィールドに) 設定することができます。 MQPRI_PRIORITY_AS_Q_DEF(デフォルト)を指定した場合、キューのDEFPRTYで設定されている値(デフォルトの'0')が設定されます。 優先順位は 0-9 で最高の優先順位は"9"で、キューマネージャーのMAXPRTYで定義されています。このプロパティは固定で変更できません。 キューのMSGDLVSQプロパティでキュー上のをFIFO(先入れ先出し)で格納するか、または優先順位に従うか(同じ優先順位のメッセージはFIFO の順序)をキューのプロパティで指定することもできます。
Ex. 2.5 GET時の優先順位
それでは、キューのMSGDLVSQの値をPRIORITY、FIFOそれぞれに設定した場合の様子について簡単に確認してみます。
MSGDLVSQを確認します。MSGDLVSQのデフォルトはPRIORITYです。
$ mqpcf que -qm SampleQM -q SampleQ MSGDLVSQ
1: QUEUE(SampleQ) TYPE(QLOCAL) MSGDLVSQ(PRIORITY)
*オプションの説明
MSGDLVSQ: MSGDLVSQフィールドの表示
優先順位を変えたメッセージをランダムにPUTします。
$ mqpgf -qm SampleQM -q SampleQ -m "priority 3" -pr 3
[18/03/07 18:53:52] 1: message length: 10 put message : priority 3
$ mqpgf -qm SampleQM -q SampleQ -m "priority default"
[18/03/07 18:54:10] 1: message length: 16 put message : priority default
$ mqpgf -qm SampleQM -q SampleQ -m "priority 8" -pr 8
[18/03/07 18:54:16] 1: message length: 10 put message : priority 8
*オプションの説明
-pr: MQMD.Priorityを指定
優先順位に従ってメッセージGETされることを確認します。
テスト結果2.5.1
$ mqpgf -qm SampleQM -q SampleQ -br -r
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[943] Format[ ] Priority[8] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A9FB6A820001A06] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180307] PutTime[09541668] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
data length: 10
00000000: 7072 696F 7269 7479 2038 'priority 8 '
message number: 2
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[943] Format[ ] Priority[3] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A9FB6A820001A02] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180307] PutTime[09535298] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
data length: 10
00000000: 7072 696F 7269 7479 2033 'priority 3 '
message number: 3
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[943] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A9FB6A820001A04] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180307] PutTime[09541028] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
data length: 16
00000000: 7072 696F 7269 7479 2064 6566 6175 6C74 'priority default'
一旦、キューをクリアします。
$ mqpcf clr -qm SampleQM -q SampleQ
Clear Queue Success. Queue Name : SampleQ
MSGDLVSQプロパティでキューの配布シーケンスをFIFO(先入れ先出し)に変更します。
MQSC > alter ql('SampleQ') msgdlvsq(fifo)
1 : alter ql('SampleQ') msgdlvsq(fifo)
AMQ8008: IBM MQ queue changed.
先ほどと同じ優先順位を変えたメッセージをPUTしてGETされる順序を確認します。
テスト結果2.5.2
$ mqpgf -qm SampleQM -q SampleQ -br -r
message number: 1
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[943] Format[ ] Priority[3] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A9FB6A820002505] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180307] PutTime[10042898] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
data length: 10
00000000: 7072 696F 7269 7479 2033 'priority 3 '
message number: 2
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[943] Format[ ] Priority[0] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A9FB6A820002507] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180307] PutTime[10043442] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
data length: 16
00000000: 7072 696F 7269 7479 2064 6566 6175 6C74 'priority default'
message number: 3
*StrucId[MD ] Version[2] Report[0] MsgType[8] Expiry[-1] Feedback[0] Encoding[273] CodedCharSetId[943] Format[ ] Priority[8] Persistence[0] MsgId[0x414D512053616D706C65514D202020205A9FB6A820002509] CorrelId[0x000000000000000000000000000000000000000000000000] BackoutCount[0] ReplyToQ[ ] ReplyToQMgr[SampleQM ] UserIdentifier[mqm ] AccountingToken[0x0534343033310000000000000000000000000000000000000000000000000006] ApplIdentityData[ ] PutApplType[13] PutApplName[mqpgf ] PutDate[20180307] PutTime[10043964] ApplOriginData[ ]
GroupId[0x000000000000000000000000000000000000000000000000] MsgSeqNumber[1] Offset[0] MsgFlags[0] OriginalLength[-1]
data length: 10
00000000: 7072 696F 7269 7479 2038 'priority 8 '
メッセージの優先順位に関わらず、PUTした順にメッセージがGETできることが確認できると思います。
テスト後は、MSGDLVSQの設定をデフォルトに戻しておきます。
[ Persistence ]
タイプ: MQLONG
サイズ: 4バイト
初期値: MQPER_PERSISTENCE_AS_Q_DEF(2)
入出力: MQGET()時:出力、MQPUT()時:入力
メッセージの持続性を示します。 下記の種類があります。
MQPER_NOT_PERSISTENT | 0 | 非持続メッセージ。 |
MQPER_PERSISTENT | 1 | 持続メッセージ。 |
MQPER_PERSISTENCE_AS_Q_DEF | 2 | キューのDEFPSISTプロパティに従って設定されます。 |
非持続メッセージは、システムの障害およびキュー・マネージャーの再始動の後は存続しません。
但し、キューのNPMCLASSプロパティを'HIGH'に設定した場合、キュー・マネージャーの通常の再起動後も存続します。
持続メッセージは、システム障害およびキュー・マネージャーの再始動後も存続します。
但し、メッセージがトランザクションで管理されるログファイルに書き込まれるため、非持続メッセージを使用時に比べてパフォーマンスは低下します。
デフォルトでは、メッセージが書き込まれた時にキューのDEFPSISTプロパティに従ってMQPER_PERSISTENTまたはMQPER_NOT_PERSISTENTがメッセージに設定されます。
mqpgfから指定する場合は、上記のコンスタントのいずれかを直接引数に指定します。
コマンド例のみ示しておきます。
$ mqpcf que -qm SampleQM -q SampleQ DEFPSIST NPMCLASS
1: QUEUE(SampleQ) TYPE(QLOCAL) DEFPSIST(NO) NPMCLASS(NORMAL)
*オプションの説明
DEFPSIST: DEFPSIST(デフォルトの持続性)フィールドの表示
NPMCLASS: NPMCLASS(非持続メッセージ速度)フィールドの表示
$ mqpgf -qm SampleQM -q SampleQ -m "non-persistent" MQPER_NOT_PERSISTENT
$ mqpgf -qm SampleQM -q SampleQ -m "persistent" MQPER_PERSISTENT
*オプションの説明
MQPER_PERSISTENT: MQMD.Persistenceに'1'を設定します。
MQPER_NOT_PERSISTENT: MQMD.Persistenceに'0'を設定します。