大規模な MRM メッセージの処理

入力ビット・ストリームが構文解析され、論理ツリーが作成されるとき、通常、 対応するビット・ストリームに比べて MRM メッセージのツリー表記の方が大きくなります (場合によっては、はるかに大きくなります)。 その理由は、次のとおりです。
  • 複数のオブジェクトをリンクするポインターが追加されるため
  • 文字データが Unicode に変換され、元のサイズが倍増する可能性があるため
  • ビット・ストリーム内に暗黙に含まれる可能性のあるフィールド名が含まれるため
  • ブローカーの操作に関連した制御データの存在

そのため、大きなメッセージ・ツリーの操作には、大量の記憶域が必要となります。 繰り返し構造からなる大きなメッセージを扱うメッセージ・フローを設計するとき、 特定の ESQL ステートメントをコーディングすれば、ブローカーのストレージ・ロードを軽減することができます。 このステートメントはメッセージへのランダム・アクセスと順次アクセスの両方をサポートしますが、一度にメッセージ全体にアクセスする必要がないことを想定します。

このような ESQL ステートメントによって、 ブローカーはメッセージを限定的に構文解析して、 メッセージ・ツリー内の単一レコードを表す部分だけを一度にストレージ内に保持します。 処理で 1 つのレコードから次のレコードに移るときに情報を保持しなければならない場合 (例えば、 注文に含まれる各品目の繰り返し構造から合計価格を計算する場合)、 いくつかの ESQL 変数を宣言し、 初期化して保持することができます。あるいは、 メッセージ・ツリー内の他の場所 (例えば LocalEnvironment) に値を保存する方法もあります。

この技法によってブローカーによるメモリー使用量が減少し、入出力ビット・ストリームの全体と、 1 つのレコードのツリーを保持する容量だけが必要になります。 たとえメッセージ内で繰り返しの回数が少なくても、メモリーが節約されます。 ブローカーは限定的な構文解析を利用し、 メッセージ・ツリー内の指定された部分をビット・ストリームの対応する部分との間で解析する能力を利用します。

Compute ノードでこれらの技法を使用するには、 以下のような一般的な手順に従ってください。
  • 入力メッセージの本文を、 出力メッセージ内の特別なフォルダーにビット・ストリームとしてコピーします。 これによって、入力メッセージの変更可能なコピーが作成されます。 これは構文解析されないため、最小限のメモリーを使用します。
  • 入力メッセージの検査はいっさい行わないようにします。 これにより、メッセージを構文解析する必要がなくなります。
  • ループおよび参照変数を使って、一度に 1 レコードずつメッセージをステップスルーします。 各レコードごとに、以下を行います。
    • 通常の変換によって、 対応する出力サブツリーを 2 番目の特別なフォルダー内に作成します。
    • ASBITSTREAM 関数を使って、 出力サブツリーのビット・ストリームを生成します。さらに、 最終的なビット・ストリーム内の位置に対応するツリー内の位置を占める BitStream エレメントに、 これを保存します。
    • 現在の入出力レコード・メッセージ・ツリーの操作が終わったら、 DELETE ステートメントを使って入出力レコード・メッセージ・ツリーを削除します。
    • すべてのレコードの処理が終わったら、 特別なフォルダーを切り離して、 出力ビット・ストリーム内に表示されないようにします。

実際のメッセージ処理の必要に合わせて、 上記の手法を独自に変えることもできます。 以下の ESQL は 1 つの実装例です。『大規模な XML メッセージの処理』では、ESQL の例を示しましたが、以下の例はそれを書き直したものです。 ネストされた繰り返し構造を含むメッセージを変換するために、単一の SET ステートメントとネストされた 複数の SELECT 関数を使用します。

ESQL は、Invoice 入力フォーマットおよび Statement 出力フォーマットの 両方のメッセージを定義するために作成された、 LargeMessageExanple と呼ばれるメッセージ・セットに依存します。 1 回以上反復できる Invoice と呼ばれる グローバル・エレメントを含む AllInvoices と呼ばれるメッセージ、 および 1 回以上反復できる Statement と呼ばれる グローバル・エレメントを含む Data と呼ばれるメッセージが作成されます。

エレメントおよび属性の定義には正しいデータ・タイプが指定されているので、 XML の例で ESQL に使用された CAST ステートメントは必要なくなりました。 これらのメッセージに対応する XML メッセージを MRM が解析できるようにする、 XML1 という名前の XML 物理形式がメッセージ・セット内に作成されています。

Statement ツリーが ASBITSTREAM 関数によって直列化されるとき、 Message SetMessage Type、およぴ Message Format がパラメーターとして指定されます。 Message Type パラメーターには、メッセージから直列化されるエレメントへのパスが含まれます。 この例では、Statement エレメントは Data メッセージの直接の子なので、 その値は Data/Statement となります。

フローへの入力メッセージは、タグに囲まれていることを除いては、 文書の他の部分で使用される Invoice 例のメッセージと同じです。
       <AllInvoices> .... </AllInvoices>  

出力メッセージは、大規模な XML メッセージの処理の場合と同じです。

CREATE COMPUTE MODULE LargeMessageExampleFlow_Compute
CREATE FUNCTION Main() RETURNS BOOLEAN
	BEGIN
CALL CopyMessageHeaders();
  -- Create a special folder in the output message to hold the input tree
  -- Note : SourceMessageTree is the root element of an MRM parser
  CREATE LASTCHILD OF OutputRoot.MRM DOMAIN 'MRM' NAME 'SourceMessageTree';

  -- Copy the input message to a special folder in the output message
  -- Note : This is a root to root copy which will therefore not build trees
  SET OutputRoot.MRM.SourceMessageTree = InputRoot.MRM;

  -- Create a special folder in the output message to hold the output tree
  CREATE FIELD OutputRoot.MRM.TargetMessageTree;

  -- Prepare to loop through the purchased items
  DECLARE sourceCursor REFERENCE TO OutputRoot.MRM.SourceMessageTree.Invoice;
  DECLARE targetCursor REFERENCE TO OutputRoot.MRM.TargetMessageTree;
  DECLARE resultCursor REFERENCE TO OutputRoot.MRM;
  DECLARE grandTotal FLOAT 0.0e0;

  -- Create a block so that it's easy to abandon processing
  ProcessInvoice: BEGIN
    -- If there are no Invoices in the input message, there is nothing to do
    IF NOT LASTMOVE(sourceCursor) THEN
      LEAVE ProcessInvoice;
    END IF;

    -- Loop through the invoices in the source tree
    InvoiceLoop : LOOP
      -- Inspect the current invoice and create a matching Statement
      SET targetCursor.Statement =
        		THE ( 
          			SELECT
            'Monthly' AS Type,
            'Full' AS Style,
            I.Customer.FirstName AS Customer.Name,
            I.Customer.LastName AS Customer.Surname,
            I.Customer.Title AS Customer.Title,
            			(SELECT 
              FIELDVALUE(II.Title) AS Title,
              II.UnitPrice * 1.6 AS Cost,
              II.Quantity AS Qty
            FROM I.Purchases.Item[] AS II
            WHERE II.UnitPrice > 0.0 ) AS Purchases.Article[],
            			(SELECT
              SUM( II.UnitPrice *
                   			     II.Quantity  *
                   				 1.6                          )
            FROM I.Purchases.Item[] AS II ) AS Amount,
            'Dollars' AS Amount.Currency
          FROM sourceCursor AS I
          WHERE I.Customer.LastName <> 'White'
       				 );

      -- Turn the current Statement into a bit stream
      -- The SET parameter is set to the name of the message set
         -- containing the MRM definition
      -- The TYPE parameter contains the path from the from the message
         -- to element being serialized
      -- The FORMAT parameter contains the name of the physical format
         -- name defined in the message
      DECLARE StatementBitStream BLOB
        CAST(ASBITSTREAM(targetCursor.Statement
        			OPTIONS FolderBitStream
        			SET 'LargeMessageExample'
        			TYPE 'Data/Statement'
        			FORMAT 'XML1') AS BLOB);
                
      -- If the SELECT produced a result (that is, it was not filtered
         -- out by the WHERE clause), process the Statement
      IF StatementBitStream IS NOT NULL THEN
        -- create a field to hold the bit stream in the result tree
        		-- The Type of the element is set to MRM.BitStream to indicate
           -- to the MRM Parser that this is a bitstream
        CREATE LASTCHILD OF resultCursor
          			Type  MRM.BitStream
          			NAME  'Statement'
          VALUE StatementBitStream;

        -- Add the current Statement's Amount to the grand total
        SET grandTotal = grandTotal + targetCursor.Statement.Amount;
      END IF;

      -- Delete the real Statement tree leaving only the bit stream version
      DELETE FIELD targetCursor.Statement;

      -- Step onto the next Invoice, removing the previous invoice and any
      -- text elements that might have been interspersed with the Invoices
      		REPEAT
        MOVE sourceCursor NEXTSIBLING;
        DELETE PREVIOUSSIBLING OF sourceCursor;
      UNTIL (FIELDNAME(sourceCursor) = 'Invoice') OR (LASTMOVE(sourceCursor) = FALSE)
END REPEAT;

      -- If there are no more invoices to process, abandon the loop
      IF NOT LASTMOVE(sourceCursor) THEN
        LEAVE InvoiceLoop;
      END IF;

    END LOOP InvoiceLoop;
  END ProcessInvoice;

  -- Remove the temporary source and target folders
  DELETE FIELD OutputRoot.MRM.SourceMessageTree;
  DELETE FIELD OutputRoot.MRM.TargetMessageTree;

  -- Finally add the grand total
  		SET resultCursor.GrandTotal = grandTotal;
  		
  -- Set the output MessageType property to be 'Data'
  		SET OutputRoot.Properties.MessageType = 'Data'; 
 
RETURN TRUE; 
	END;

CREATE PROCEDURE CopyMessageHeaders() BEGIN
DECLARE I INTEGER 1;
DECLARE J INTEGER CARDINALITY(InputRoot.*[]);
WHILE I < J DO
SET OutputRoot.*[I] = InputRoot.*[I];
SET I = I + 1;
END WHILE;
	END;

END MODULE;
関連概念
メッセージ・フローの概要
ESQL の概要
メッセージのモデル化
関連タスク
メッセージ・フローの設計
メッセージ・フローの内容の定義
ESQL ファイルの管理
メッセージ・モデルの開発
大規模な XML メッセージの処理
関連資料
Compute ノード
Database ノード
Filter ノード
ASBITSTREAM 関数
CREATE ステートメント
SET ステートメント
特記事項 | 商標 | ダウンロード | ライブラリー | サポート | フィードバック
Copyright IBM Corporation 1999, 2006 最終更新: 08/21/2006
ac20702_