Gestione di messaggi MRM di grandi dimensioni

Quando si analizza un flusso di bit di input e si crea una struttura ad albero logica, la rappresentazione ad albero di un messaggio MRM è in genere più grande e in alcuni casi molto più grande, del flusso di bit corrispondente. I motivi di questa variazione sono:
  • L'aggiunta dei puntatori che collegano gli oggetti.
  • La conversione dei dati carattere in Unicode che può raddoppiare le dimensioni originali.
  • L'inclusione di nomi campo che nel flusso di bit possono essere contenuti implicitamente.
  • La presenza dei dati di controllo associati all'operazione del broker

La manipolazione di una struttura ad albero del messaggio di grandi dimensioni può quindi richiedere una notevole quantità di memoria. Se si progetta un flusso di messaggi che gestisce messaggi di grandi dimensioni, costituiti di strutture che si ripetono, è possibile codificare istruzioni ESQL specifiche per ridurre il carico di memorizzazione nel broker. Tali istruzioni supportano l'accesso al messaggio sia casuale che sequenziale, ma presuppongono che non sia necessario accedere all'intero messaggio in una sola volta.

Queste istruzioni ESQL fanno in modo che il broker esegua un'analisi limitata del messaggio e conservi solo quella parte della struttura ad albero del messaggio che riflette un singolo record nella memoria alla volta. Se l'elaborazione richiede di conservare le informazioni da un record all'altro (ad esempio, per calcolare un prezzo totale da una struttura ripetuta di elementi in un ordine), è possibile dichiarare, inizializzare e conservare le variabili ESQL o salvare i valori in un'altra sezione della struttura ad albero del messaggio, ad esempio LocalEnvironment.

Questa tecnica riduce la memoria utilizzata dal broker a quella necessaria per mantenere i flussi di bit di input e di output completi, più quella richiesta per le strutture ad albero di un record. Essa consente di risparmiare memoria quando si incontra anche un numero ridotto di ripetizioni nel messaggio. Il broker utilizza l'analisi parziale e la capacità di analizzare sezioni specificate della struttura ad albero del messaggio, da e verso la parte corrispondente del flusso di bit.

Per utilizzare queste tecniche nel nodo Compute applicare queste tecniche generali:
  • Copiare il contenuto del messaggio di input come flusso di bit in una cartella speciale nel messaggio di output. In questo modo si crea una copia modificabile del messaggio di input che non è analizzata e che quindi utilizza una quantità di memoria minima.
  • Evitare qualsiasi ispezione del messaggio di input; in questo modo si elimina la necessità di analizzare il messaggio.
  • Utilizzare un loop e una variabile di riferimento per eseguire il messaggio un record alla volta. Per ogni record:
    • Utilizzare trasformazioni normali per creare una struttura ad albero secondaria di output corrispondente in una seconda cartella speciale.
    • Utilizzare la funzione ASBITSTREAM per creare un flusso di bit per la struttura ad albero secondaria di output memorizzata in un elemento BitStream, ubicato nella posizione nell'albero che corrisponde alla posizione richiesta nel flusso di bit finale.
    • Utilizzare l'istruzione DELETE per eliminare le strutture ad albero del messaggio del record di input e di output correnti una volta completata la manipolazione.
    • Quando si completa l'elaborazione di tutti i record, scollegare la cartella speciale in modo che non appaiano nel flusso di bit di output.

E' possibile variare queste tecniche per adattarle all'elaborazione richiesta per i propri messaggi. Il seguente ESQL fornisce un esempio di implementazione ed è una riscrittura dell'esempio di ESQL in Gestione di messaggi XML di grandi dimensioni che utilizza un'unica istruzione SET con funzioni SELECT nidificate per trasformare un messaggio che contiene strutture nidificate e ripetute.

L'ESQL dipende da una serie di messaggi denominata LargeMessageExanple che è stata creata per definire i messaggi per il formato di input Invoice e per il formato di output Statement. E' stato creato un messaggio denominato AllInvoices che contiene un elemento globale denominato Invoice che può ripetersi una o più volte e un messaggio denominato Data che contiene un elemento globale denominato Statement che può ripetersi una o più volte.

Alle definizioni degli elementi e degli attributi sono stati assegnati i tipi di dati corretti, quindi, le istruzioni CAST utilizzate da ESQL nell'esempio XML non sono più richieste. E' stato creato un formato fisico XML con nome XML1 nella serie di messaggi che consente ad un messaggio XML, corrispondente a questi messaggi, di essere analizzato da MRM.

Quando la struttura ad albero Statement è serializzata utilizzando la funzione ASBITSTREAM la Serie di messaggi, il Tipo messaggio e il Formato del messaggio sono specificati come parametri. Il parametro Tipo messaggio contiene il percorso dal messaggio all'elemento serializzato che, in questo caso, è Data/Statement poiché l'elemento Statement è un child diretto del messaggio Data.

Il messaggio di input nel flusso è lo stesso messaggio di esempio Invoice utilizzato in altre parti della documentazione tranne che è compreso tra due tag:
       <AllInvoices> ....  </AllInvoices>  

Il messaggio di output è identico a quello in Gestione di messaggi XML di grandi dimensioni.

CREATE COMPUTE MODULE LargeMessageExampleFlow_Compute
CREATE FUNCTION Main() RETURNS BOOLEAN
	BEGIN
CALL CopyMessageHeaders();
  -- Creare una cartella speciale nel messaggio di output per contenere la struttura ad albero di input
  		-- Nota : SourceMessageTree è l'elemento root di un programma di analisi MRM
  		CREATE LASTCHILD OF OutputRoot.MRM DOMAIN 'MRM' NAME 'SourceMessageTree';

  -- Copiare il messaggio di input in una cartella speciale nel messaggio di output
  -- Nota : questa è una copia da root a root che quindi non crea strutture ad albero
  		SET OutputRoot.MRM.SourceMessageTree = InputRoot.MRM;

  -- Creare una cartella speciale nel messaggio di output per contenere la struttura ad albero di output
  		CREATE FIELD OutputRoot.MRM.TargetMessageTree;

  -- Prepararsi ad eseguire il loop degli articoli acquistati
  		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;

  -- Creare un blocco in modo che sia facile interrompere l'elaborazione
  ProcessInvoice: BEGIN
    -- Se non esistono fatture nel messaggio di input, non vi sono operazioni da compiere
    IF NOT LASTMOVE(sourceCursor) THEN
      LEAVE ProcessInvoice;
    END IF;

    -- Eseguire il loop delle fatture nella struttura ad albero di origine
    InvoiceLoop : LOOP
      -- Controllare la fattura corrente e creare un'istruzione corrispondente
      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'
       				 );

      -- Trasformare l'istruzione corrente in un flusso di bit
      		-- Il parametro SET è impostato sul nome della serie di messaggi 
         -- che contiene la definizione MRM
      		-- Il parametro TYPE contiene il percorso dal messaggio 
         -- all'elemento serializzato
      		-- Il parametro FORMAT contiene il nome del formato fisico 
         -- definito nel messaggio   
      DECLARE StatementBitStream BLOB
        		CAST(ASBITSTREAM(targetCursor.Statement 
        			OPTIONS FolderBitStream
        			SET 'LargeMessageExample'
        			TYPE 'Data/Statement'
        		 FORMAT 'XML1') AS BLOB);
                
      		-- Se SELECT ha prodotto un risultato (cioè, non è stata filtrata
         -- dalla clausola WHERE), elaborare l'istruzione
      IF StatementBitStream IS NOT NULL THEN
        -- creare un campo per contenere il flusso di bit nella struttura ad albero dei risultati
        		-- Il valore Type dell'elemento è impostato su MRM.BitStream per indicare
           -- al programma di analisi MRM che si tratta di un flusso di bit 
        CREATE LASTCHILD OF resultCursor
          			Type  MRM.BitStream
          			NAME  'Statement'
          VALUE StatementBitStream;

        -- Aggiungere l'ammontare del rendiconto corrente all'importo totale
        		SET grandTotal = grandTotal + targetCursor.Statement.Amount;
      END IF;

      -- Eliminare l'albero reale del rendiconto lasciando solo la versione del flusso di bit
      DELETE FIELD targetCursor.Statement;

      -- Passare alla fattura successiva, rimuovendo la fattura precedente e tutti
      -- gli elementi di testo che potrebbero essere distribuiti nelle fatture
      		REPEAT
        MOVE sourceCursor NEXTSIBLING;
        DELETE PREVIOUSSIBLING OF sourceCursor;
      UNTIL (FIELDNAME(sourceCursor) = 'Invoice') OR (LASTMOVE(sourceCursor) = FALSE)
      END REPEAT;

      -- Se non ci sono altre fatture da elaborare, interrompere il loop
      IF NOT LASTMOVE(sourceCursor) THEN
        LEAVE InvoiceLoop;
      END IF;

    END LOOP InvoiceLoop;
  END ProcessInvoice;

  -- Rimuovere l'origine temporanea e le cartelle di destinazione
  		DELETE FIELD OutputRoot.MRM.SourceMessageTree;
  		DELETE FIELD OutputRoot.MRM.TargetMessageTree;

  -- Infine aggiungere l'importo totale
  		SET resultCursor.GrandTotal = grandTotal;
  		
  		-- Impostare la proprietà MessageType di output su '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;
Concetti correlati
Panoramica dei flussi di messaggi
Panoramica di ESQL
Creazione di modelli di messaggio
Attività correlate
Progettazione di un flusso di messaggi
Definizione del contenuto del flusso di messaggi
Gestione dei file ESQL
Sviluppo di modelli di messaggio
Gestione di messaggi XML di grandi dimensioni
Riferimenti correlati
Nodo Compute
Nodo Database
Nodo Filter
Funzione ASBITSTREAM
Istruzione CREATE
Istruzione SET
Informazioni particolari | Marchi | Download | Libreria | Supporto | Commenti
Copyright IBM Corporation 1999, 2006 Ultimo aggiornamento: ago 17, 2006
ac20702_