Manejar mensajes MRM grandes

Cuando se analiza una corriente de bits de entrada y se crea un árbol lógico, la representación de árbol de un mensaje MRM es normalmente más grande y, en algunos casos, mucho más grande que la corriente de bits correspondiente. Los motivos son los siguientes:
  • La adición de los punteros que enlazan los objetos entre sí
  • La conversión de datos de tipo carácter a Unicode que puede duplicar el tamaño original.
  • La inclusión de nombres de campo que se pueden obtener implícitamente en la corriente de bits.
  • La presencia de datos de control asociados al funcionamiento del intermediario

Por consiguiente, la manipulación de un árbol de mensaje grande puede requerir una gran cantidad de almacenamiento. Si diseña un flujo de mensajes que maneja mensajes grandes formados por estructuras de repetición, puede codificar sentencias ESQL específicas que ayuden a reducir la carga de almacenamiento en el intermediario. Estas sentencias permiten acceder al mensaje de forma aleatoria y secuencial, pero presuponga que no necesita acceder a todo el mensaje de una vez.

Estas sentencias ESQL hacen que el intermediario efectúe un análisis limitado del mensaje y guarde solamente esa parte del árbol de mensaje que refleje un registro individual del almacenamiento cada vez. Si el proceso requiere que retenga la información de registro a registro, por ejemplo, para calcular un precio total de una estructura de elementos repetitivos dentro de un orden, puede declarar, inicializar y mantener variables ESQL o puede guardar los valores en otra parte del árbol de mensaje, por ejemplo, en LocalEnvironment.

Esta técnica reduce la memoria utilizada por el intermediario a la necesaria para contener las corrientes de bits de entrada y salida completas, más la necesaria para los árboles de un registro. Proporciona ahorro de memoria incluso cuando se encuentra un pequeño número de repeticiones en el mensaje. El intermediario utiliza el análisis parcial y la posibilidad de analizar partes específicas del árbol de mensaje en y desde la parte correspondiente de la corriente de bits.

Para utilizar estas técnicas en el nodo Compute, aplique estas técnicas generales:
  • Copie el texto del mensaje de entrada como una corriente de bits en una carpeta especial del mensaje de salida. Esto crea una copia modificable del mensaje de entrada que no se analiza y que, por consiguiente, utiliza una cantidad mínima de memoria.
  • Evite inspeccionar el mensaje de entrada; esto evita la necesidad de analizar el mensaje.
  • Utilice un bucle y una variable de referencia para recorrer el mensaje de registro en registro. Para cada registro:
    • Utilice las transformaciones normales para crear un subárbol de salida en una segunda carpeta especial.
    • Utilice la función ASBITSTREAM para generar una corriente de bits para el subárbol de salida que se almacena en un elemento BitStream, colocado en la posición del árbol que corresponde a la posición necesaria en la corriente de bits final.
    • Utilice la sentencia DELETE para suprimir ambos árboles de mensajes de registro de entrada y de salida actuales cuando haya completado la manipulación.
    • Cuando haya terminado el proceso de todos los registros, desconecte las carpetas especiales para que no aparezcan en la corriente de bits de salida.

Puede variar estas técnicas para adaptarlas al proceso necesario para los mensajes. El ESQL siguiente proporciona un ejemplo de una implementación y es una reescritura del ejemplo de ESQL del apartado Manejar mensajes XML grandes que utiliza una sola sentencia SET con funciones SELECT anidadas para transformar un mensaje que contiene estructuras anidadas repetidas.

El ESQL es dependiente de un conjunto de mensajes denominado LargeMessageExanple que se ha creado para definir mensajes para el formato de entrada de Invoice y el formato de salida de Statement. Se ha creado un mensaje denominado AllInvoices que contiene un elemento global denominado Invoice que se puede repetir una o varias veces y un mensaje denominado Data que contiene un elemento global denominado Statement que se puede repetir una o varias veces.

Puesto que a las definiciones de los elementos y atributos se les han dado los tipos de datos correctos, las sentencias CAST utilizadas por el ESQL en el ejemplo de XML ya no son necesarias. Se ha creado un formato físico XML con el nombre XML1 en el conjunto de mensajes que permite que el MRM analice un mensaje XML correspondiente a estos mensajes.

Cuando se serializa el árbol Statement utilizando la función ASBITSTREAM, se especifican el Conjunto de mensajes, el Tipo de mensajes y el Formato del mensaje como parámetros. El parámetro Tipo de mensaje contiene la vía de acceso del mensaje al elemento que se está serializando que, en este caso, es Data/Statement porque el elemento Statement es un hijo directo del mensaje Data.

El mensaje de entrada en el flujo es el mismo mensaje de ejemplo Invoice utilizado en otras partes de la documentación excepto que está contenido entre los códigos:
       <AllInvoices> ....  </AllInvoices>  

El mensaje de salida es el mismo que el del apartado Manejar mensajes XML grandes.

CREATE COMPUTE MODULE LargeMessageExampleFlow_Compute
CREATE FUNCTION Main() RETURNS BOOLEAN
	BEGIN
CALL CopyMessageHeaders();
  -- Crear una carpeta especial en el mensaje de salida que contenga el árbol de entrada
  		-- Nota : SourceMessageTree es el elemento raíz de un analizado MRM
  		CREATE LASTCHILD OF OutputRoot.MRM DOMAIN 'MRM' NAME 'SourceMessageTree';

  -- Copiar el mensaje de entrada en una carpeta especial del mensaje de salida
  -- Nota : Esta es una copia de raíz a raíz que, por lo tanto, no creará árboles
  		SET OutputRoot.MRM.SourceMessageTree = InputRoot.MRM;

  -- Crear una carpeta especial en el mensaje de salida que contenga el árbol de salida
  		CREATE FIELD OutputRoot.MRM.TargetMessageTree;

  -- Preparar el bucle a través de los elementos adquiridos
  		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;

  -- Crear un bloque que facilite el abandono del proceso
  ProcessInvoice: BEGIN
    -- Si no hay facturas (Invoices) en el mensaje de entrada, no hay nada que hacer
    IF NOT LASTMOVE(sourceCursor) THEN
      LEAVE ProcessInvoice;
    END IF;

    -- Crear un bucle por las facturas del árbol de origen
    InvoiceLoop : LOOP
      -- Inspeccionar la factura actual y crear una sentencia coincidente
      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'
       				 );

      -- Convertir la sentencia actual en una corriente de bits
      		-- El parámetro SET se establece en el nombre del conjunto de mensajes 
         -- que contiene la definición de MRM
      		-- El parámetro TYPE contiene la vía de acceso del mensaje 
         -- al elemento que se está serializando
      		-- El parámetro FORMAT contiene el nombre del formato físico 
         -- definido en el mensaje   
      DECLARE StatementBitStream BLOB
        		CAST(ASBITSTREAM(targetCursor.Statement 
        			OPTIONS FolderBitStream
        			SET 'LargeMessageExample'
        			TYPE 'Data/Statement'
        			FORMAT 'XML1') AS BLOB);
                
      -- Si SELECT ha generado un resultado (es decir, si la cláusula WHERE no la
         -- ha filtrado), procese la sentencia
      IF StatementBitStream IS NOT NULL THEN
        -- crear un campo que contenga la corriente de bits del árbol de resultados
        		-- El Type del elemento se establece en MRM.BitStream para indicar
           -- al analizador MRM que se trata de una corriente de bits 
        CREATE LASTCHILD OF resultCursor
          			Type  MRM.BitStream
          			NAME  'Statement'
          VALUE StatementBitStream;

        -- Añadir el importe de la sentencia actual al total
        		SET grandTotal = grandTotal + targetCursor.Statement.Amount;
      		END IF;

      -- Suprimir el árbol de sentencia real dejando solo la versión de la corriente de bits
      DELETE FIELD targetCursor.Statement;

      -- Pasar a la siguiente factura y suprimir la factura anterior y cualquier
      -- elemento de texto que se haya propagado con las facturas
      		REPEAT
        MOVE sourceCursor NEXTSIBLING;
        DELETE PREVIOUSSIBLING OF sourceCursor;
      UNTIL (FIELDNAME(sourceCursor) = 'Invoice') OR (LASTMOVE(sourceCursor) = FALSE)
      END REPEAT;

      -- Si no hay más facturas que procesar, abandonar el bucle
      IF NOT LASTMOVE(sourceCursor) THEN
        LEAVE InvoiceLoop;
      		END IF;

    END LOOP InvoiceLoop;
  END ProcessInvoice;

  -- Suprimir las carpetas de origen y destino temporales
  		DELETE FIELD OutputRoot.MRM.SourceMessageTree;
  		DELETE FIELD OutputRoot.MRM.TargetMessageTree;

  -- Finalmente añadir el total
  		SET resultCursor.GrandTotal = grandTotal;
  		
  		-- Establecer la propiedad MessageType de salida en '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;
Conceptos relacionados
Visión general de flujos de mensajes
Visión general de ESQL
Modelado de mensajes
Tareas relacionadas
Diseñar un flujo de mensajes
Definir el contenido del flujo de mensajes
Gestión de archivos ESQL
Desarrollo de modelos de mensaje
Manejar mensajes XML grandes
Referencia relacionada
Nodo Compute
Nodo Database
Nodo Filter
Función ASBITSTREAM
Sentencia CREATE
Sentencia SET
Avisos | Marcas registradas | Descargas | Biblioteca | Soporte | Su opinión
Copyright IBM Corporation 1999, 2006 Última actualización: 22/08/2006
ac20702_