Hitachi

OpenTP1 Version 7 OpenTP1 メッセージキューイング機能 TP1/Message Queue プログラム作成の手引


10.5.2 メッセージのセグメント分割

キューまたはキューマネジャにとってメッセージが長過ぎる場合には,メッセージをセグメント分割できます。セグメントの概要については,「3.6 メッセージグループ」を参照してください。

ここではセグメント分割メッセージの典型的な使用例について説明します。メッセージの登録と取り出し(削除)については,MQPUT命令とMQGET命令をトランザクション内で発行します。不完全なグループがネットワーク内でなくなるように,この方法をお勧めします。TP1/Message Queueではキューマネジャが二相コミットを実行します。

また,取り出しアプリケーションでは,サーバで必要なメッセージまたはセグメントを見つけるのに失敗することがないように,複数のサーバで同じキューを処理し,各サーバは同様のコードを実行します。MQGMO_ALL_MSGS_AVAILABLEまたはMQGMO_ALL_SEGMENTS_AVAILABLEを事前に指定します。

〈この項の構成〉

(1) キューマネジャによるセグメント分割と組み立て

一つのアプリケーションがメッセージを登録し,もう一方のアプリケーションで取り出すという簡単な例について説明します。メッセージは,アプリケーションが一つのバッファで処理できないほど長くはないが,メッセージが登録されるキューマネジャおよびキューにとっては長過ぎるとします。

登録アプリケーションについての変更点は,キューマネジャが必要に応じてセグメント分割を実行することを許可することです。

PMO.Options = (既存のオプション)
MQPUT MD.MsgFlags = MQMF_SEGMENTATION_ALLOWED

取り出しアプリケーションでは,セグメント分割されている場合にメッセージをキューマネジャで組み立てるように要求します。

GMO.Options = MQGMO_COMPLETE_MSG | (既存のオプション)
MQGET

アプリケーションバッファはMQGMO_ACCEPT_TRUNCATED_MSGが指定されていない場合に組み立て後のメッセージを格納するのに十分な長さが必要です。

データ変換が必要な場合には,取り出しアプリケーションでMQGMO_CONVERTを指定して実行してください。これはUOCを使用しない直接的な方法です。送信側チャネルでデータ変換を実行する場合は,メッセージがセグメント分割されていると失敗します。また,完全でないデータはデータ変換をUOCで実行できません。

(2) アプリケーションによるセグメント分割

アプリケーションによるセグメント分割を使用する場合を次に示します。

  1. アプリケーションの一つのバッファで処理するには長過ぎるので,キューマネジャによるセグメント分割だけでは不十分な場合

  2. データ変換を送信側チャネルで実行し,データの形式について登録アプリケーションで定義するように,各セグメントの変換が可能なセグメント境界を定義する場合

しかし,データ変換を実行しない場合,または取り出しアプリケーションで常にMQGMO_COMPLETE_MSGを指定する場合には,MQMF_SEGMENTATION_ALLOWEDの指定によってキューマネジャによるセグメント分割も許可できます。次に示す例では,メッセージを四つにセグメント分割します。

PMO.Options = MQPMO_LOGICAL_ORDER | MQPMO_SYNCPOINT
 
dc_trn_begin()
MQPUT MD.MsgFlags = MQMF_SEGMENT
MQPUT MD.MsgFlags = MQMF_SEGMENT
MQPUT MD.MsgFlags = MQMF_SEGMENT
MQPUT MD.MsgFlags = MQMF_LAST_SEGMENT
dc_trn_unchained_commit()

MQPMO_LOGICAL_ORDERを使用しない場合には,アプリケーションで各セグメントのオフセットと長さを設定してください。この場合,論理状態は自動的に設定されます。

取り出しアプリケーションでは,組み立て後のメッセージ全体を格納する領域は不要です。ただし,セグメントの個別な処理が必要です。

セグメント分割されたメッセージについては,論理メッセージを構成する全セグメントがそろうまでは,セグメントの処理をアプリケーションで開始したくないことがあります。その場合は,MQGMO_ALL_SEGMENTS_AVAILABLEを最初のセグメントに指定できます。MQGMO_LOGICAL_ORDERを指定する場合に,現在の論理メッセージがあるときには,MQGMO_ALL_SEGMENTS_AVAILABLEは無視されます。

論理メッセージの最初のセグメントをいったん取り出したら,論理メッセージの残りのセグメントを順に取り出すためにMQGMO_LOGICAL_ORDERを指定できます。

異なるグループ内のメッセージについての配慮は不要です。そのようなメッセージが発生した場合は,キューで各メッセージの最初のセグメントが出現する順に処理されます。

GMO.Options = MQGMO_SYNCPOINT | MQGMO_LOGICAL_ORDER
            | MQGMO_ALL_SEGMENTS_AVAILABLE | MQGMO_WAIT
dc_trn_begin()
while ( SegmentStatus == MQSS_SEGMENT ) {
  MQGET
  /* 論理メッセージの残りのセグメントを処理 */
  ...
}
dc_trn_unchained_commit()

(3) アプリケーションによる論理メッセージのセグメント分割

メッセージのグループ内での論理的順序を保持する必要があり,かつ,メッセージがアプリケーションによるセグメント分割を必要とするほど長大である場合について説明します。

ここでは,四つの論理メッセージグループを登録します。三つのメッセージが長大であり,登録アプリケーションによるセグメント分割を必要とします。

PMO.Options = MQPMO_LOGICAL_ORDER | MQPMO_SYNCPOINT
 
dc_trn_begin()
 
MQPUT MD.MsgFlags = MQMF_MSG_IN_GROUP | MQMF_SEGMENT
MQPUT MD.MsgFlags = MQMF_MSG_IN_GROUP | MQMF_SEGMENT
MQPUT MD.MsgFlags = MQMF_MSG_IN_GROUP | MQMF_LAST_SEGMENT
 
MQPUT MD.MsgFlags = MQMF_MSG_IN_GROUP | MQMF_SEGMENT
MQPUT MD.MsgFlags = MQMF_MSG_IN_GROUP | MQMF_LAST_SEGMENT
 
MQPUT MD.MsgFlags = MQMF_MSG_IN_GROUP
 
MQPUT MD.MsgFlags = MQMF_LAST_MSG_IN_GROUP | MQMF_SEGMENT
MQPUT MD.MsgFlags = MQMF_LAST_MSG_IN_GROUP | MQMF_SEGMENT
MQPUT MD.MsgFlags = MQMF_LAST_MSG_IN_GROUP | MQMF_LAST_SEGMENT
 
dc_trn_unchained_commit()

取り出しアプリケーションでは,MQGMO_ALL_MSGS_AVAILABLEを最初のMQGET命令に指定します。これはグループ全体が利用できるようになるまではグループのメッセージもセグメントも取り出さないようにする指定です。グループの最初の物理メッセージを取り出したら,グループの残りのセグメントとメッセージを順に取り出すためにMQGMO_LOGICAL_ORDERを使用できます。

GMO.Options = MQGMO_SYNCPOINT | MQGMO_LOGICAL_ORDER
            | MQGMO_ALL_MSGS_AVAILABLE | MQGMO_WAIT
 
dc_trn_begin()
while ( (GroupStatus != MQGS_LAST_MSG_IN_GROUP) ||
           (SegmentStatus != MQSS_LAST_SEGMENT) ) {
  MQGET
  /* セグメントまたは完全な論理メッセージの処理
     返却値を調べるにはGroupStatusとSegmentStatusを使用
     してください。 */
  ...
}
  dc_trn_unchained_commit()
注意

MQGMO_LOGICAL_ORDER指定時に現在のグループがある場合には,MQGMO_ALL_MSGS_AVAILABLEは無視されます。

(4) 複数トランザクションにわたるセグメント分割メッセージの登録と取り出し

複数トランザクションにわたるセグメント分割メッセージの登録と取り出しは,グループ化したメッセージの処理の場合と同様です。詳細については,「10.3.2(2) 複数トランザクションにわたるグループの登録と取り出し」を参照してください。

MQMF_SEGMENTATION_ALLOWEDを指定するメッセージの登録,およびMQGMO_COMPLETE_MSGを指定するメッセージの取り出しは,トランザクション内で実行してください。トランザクション外で実行した場合,エラーが発生します。