WebSphere Message Broker, Versão 8.0.0.5 Sistemas operacionais: AIX, HP-Itanium, Linux, Solaris, Windows, z/OS

Consulte as informações sobre a versão mais recente do produto em IBM Integration Bus, Versão 9.0

Criando um Nó de Processamento de Mensagem ou de Saída em C

Um nó de processamento de mensagem é usado para processar uma mensagem de alguma maneira e um nó de saída é usado para produzir uma mensagem como um fluxo de bits.

Antes de começar

Ao codificar um nó de processamento de mensagens ou um nó de saída, os nós fornecem essencialmente os mesmos serviços. É possível executar o processamento de mensagens em um nó de saída e enviar uma mensagem para um fluxo de bits usando um nó de processamento de mensagens. Para simplificar, este tópico refere-se principalmente ao nó como um nó de processamento de mensagens, mas também contém informações sobre as funções de dois tipos de nó.

Uma LIL (Biblioteca de Implementação Carregável) é o módulo de implementação para um nó em C. Uma LIL é implementada como uma DLL (Biblioteca de Links Dinâmicos) ou biblioteca compartilhada, mas tem a extensão de arquivo .lil, não .dll.

Para obter informações adicionais sobre as funções de implementação do nó C que você grava para o nó, consulte Funções de Implementação de Nó C. Você pode chamar funções de utilitário do nó C, implementadas no broker de tempo de execução, para ajudar na operação do nó; consulte Funções de Utilitários de Nó C.

O WebSphere Message Broker fornece a origem para dois nós de amostra definidos pelo usuário chamados SwitchNode e TransformNode. Você pode utilizar esses nós em seus estados atuais ou poderá modificá-los. Além disso, você pode visualizar a seguinte amostra, que demonstra a utilização de nós definidos pelo usuário, incluindo um nó de processamento de mensagens gravado em C.

Você só pode visualizar informações sobre amostras quando usa o centro de informações que está integrado ao WebSphere Message Broker Toolkit ou o centro de informações on-line. Você só poderá executar amostras quando usar o centro de informações que está integrado ao WebSphere Message Broker Toolkit.

Declarando e Definindo Seu Nó

Para declarar e definir um nó definido pelo usuário para o intermediário, inclua uma função de inicialização, bipGetMessageflowNodeFactory, na LIL. As etapas a seguir devem ser realizadas no encadeamento de configuração, devem esboçar como o intermediário chama sua função de inicialização e como sua função de inicialização declara e define o nó definido pelo usuário:

  1. O intermediário chama a função de inicialização bipGetMessageflowNodeFactory depois que o sistema operacional carregou e inicializou a LIL. O intermediário chama essa função para compreender o que a LIL pode fazer e como o intermediário pode chamar a LIL. Por exemplo:
    CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix
    bipGetMessageflowNodeFactory()
  2. A função bipGetMessageflowNodeFactory deve chamar a função de utilitário cniCreateNodeFactory. Essa função transmite de volta um nome de fábrica (ou nome de grupo) para todos os nós que a LIL suporta. O nome de depósito de informações (ou nome de grupo) deve ser exclusivo por todas as LILs em um só intermediário de tempo de execução.
  3. O LIL deve chamar a função de utilitário cniDefineNodeClass para transmitir o nome exclusivo de cada nó e uma tabela de função virtual dos endereços das funções de implementação.
    Por exemplo, o código a seguir declara e define um único nó chamado MessageProcessingxNode:
    {
    	CciFactory* factoryObject;
    	int rc = 0;
    	CciChar factoryName[] = L"MyNodeFactory";
    	CCI_EXCEPTION_ST exception_st;
    
    	/* Criar a Fábrica de Nó para este nó */
    	factoryObject = cniCreateNodeFactory(0, factoryName);
    	if (factoryObject == CCI_NULL_ADDR) {
    		/* Qualquer tratamento de erro local pode ir aqui */
    	}
    	else {
    		/* Definir os nós suportados por esta fábrica */
    	static CNI_VFT vftable = {CNI_VFT_DEFAULT};
    
    	/* Configurar tabela de funções com ponteiros para funções de
    implementação do nó */
    	vftable.iFpCreateNodeContext = _createNodeContext;
    	vftable.iFpDeleteNodeContext = _deleteNodeContext;
    	vftable.iFpGetAttributeName2 = _getAttributeName2;
    	vftable.iFpSetAttribute = _setAttribute;
    	vftable.iFpGetAttribute2     = _getAttribute2;
    	vftable.iFpEvaluate = _evaluate;
    
    	cniDefineNodeClass(0, factoryObject, L"MessageProcessingxNode", &vftable);
    
    	}
    
    	/* Retornar o endereço deste objeto de fábrica para o intermediário */
    	return(factoryObject);
    }

    Um nó definido pelo usuário se identifica como um nó de processamento de mensagem ou de saída implementando a função cniEvaluate. Os nós definidos pelo usuário devem implementar uma função de implementação cniEvaluate ou cniRun; caso contrário, o intermediário não carregará o nó definido pelo usuário e a função de utilitário cniDefineNodeClass falhará, retornando CCI_MISSING_IMPL_FUNCTION.

    Quando um fluxo de mensagens que contém um nó de processamento de mensagens definido pelo usuário é implementado com êxito, a função cniEvaluate do nó é chamada para cada mensagem propagada para o nó.

    Os dados do fluxo de mensagens são recebidos no terminal de entrada do nó, ou seja, a mensagem, Environment, LocalEnvironment e ExceptionList.

    Por exemplo:
    void cniEvaluate(                
      CciContext* context,                
      CciMessage* localEnvironment,        
      CciMessage* exceptionList,          
      CciMessage* message                 
    ){                                    
      ...
    }
    Para obter o código mínimo necessário para compilar um nó definido pelo usuário C, consulte código de estrutura C.

Criando uma Instância do Nó

Para instanciar seu nó:

  1. Quando o intermediário tiver recebido a tabela de ponteiros de função, ele chamará a função cniCreateNodeContext para cada instanciação do nó definido pelo usuário. Por exemplo, se houver três fluxos de mensagens que estejam utilizando o nó definido pelo usuário, a função cniCreateNodeContext será chamada para cada um deles. Esta função aloca memória para essa instanciação do nó definido pelo usuário para reter os valores para os atributos configurados. Por exemplo:
    1. A função de usuário cniCreateNodeContext é chamada:
      CciContext* _Switch_createNodeContext(
        CciFactory* factoryObject,
        CciChar*    nodeName,
        CciNode*    nodeObject
      ){
        static char* functionName = (char *)"_Switch_createNodeContext()";
        NODE_CONTEXT_ST* p;
        CciChar          buffer[256];
      
    2. Alocar um ponteiro para o contexto local e limpar a área do contexto:
        p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST));
      
        if (p) {
           memset(p, 0, sizeof(NODE_CONTEXT_ST));
    3. Salvar o ponteiro do objeto do nó no contexto:
         p->nodeObject = nodeObject;
    4. Salvar o nome do nó:
       CciCharNCpy((CciChar*) &p->nodeName, nodeName,
      MAX_NODE_NAME_LEN);
    5. Retorne o contexto do nó:
      return (CciContext*) p;
  2. O intermediário chama as funções utilitárias apropriadas para localizar sobre os terminais de entrada e de saída do nó. Um nó tem um número de terminais de entrada e de terminais de saída associados a ele. Com a função do usuário cniCreateNodeContext, as chamadas devem ser feitas para cniCreateInputTerminal e cniCreateOutputTerminal para definir os terminais de nó do usuário. Estas funções devem ser iniciadas na função de implementação cniCreateNodeContext. Por exemplo, para definir um nó com um terminal de entrada e dois terminais de saída:
        {
          const CciChar* ucsIn = CciString("in", BIP_DEF_COMP_CCSID) ;
          insInputTerminalListEntry(p, (CciChar*)ucsIn);
          free((void *)ucsIn) ;
        }
        {
          const CciChar* ucsOut = CciString("out", BIP_DEF_COMP_CCSID) ;
          insOutputTerminalListEntry(p, (CciChar*)ucsOut);
          free((void *)ucsOut) ;
        }
        {
          const CciChar* ucsFailure = CciString("failure", BIP_DEF_COMP_CCSID) ;
          insOutputTerminalListEntry(p, (CciChar*)ucsFailure);
          free((void *)ucsFailure) ;
        }

    O código anterior inicia as funções insInputTerminalListEntry e insOutputTerminalListEntry. É possível localizar essas funções no código de amostra Common.c; consulte Arquivos de Nós de Amostra. Estas funções definem os terminais para o intermediário e armazenam identificadores para os terminais. Os identificadores são armazenados na estrutura mencionada pelo valor retornado em CciContext*. Em seguida, o nó pode acessar os identificadores de terminal de dentro das outras funções de implementação (por exemplo, CciEvaluate), porque CciContext é transmitida para essas funções de implementação.

    O código a seguir mostra a definição de insInputTerminalListEntry:

    TERMINAL_LIST_ENTRY *insInputTerminalListEntry( 
      NODE_CONTEXT_ST* context, 
      CciChar*         terminalName 
    ){ 
      static char* functionName = (char *)"insInputTerminalListEntry()"; 
      TERMINAL_LIST_ENTRY* entry; 
      int             rc; 
     
      entry = (TERMINAL_LIST_ENTRY *)malloc(sizeof(TERMINAL_LIST_ENTRY)); 
      if (entry) { 
     
        /* Esta entrada é o fim atual da lista */ 
        entry->next = 0; 
     
        /* Armazenar o nome do terminal */ 
        CciCharCpy(entry->name, terminalName); 
     
        /* Criar terminal e salvar seu identificador */ 
        entry->handle = cniCreateInputTerminal(&rc, context->nodeObject, (CciChar*)terminalName); 
     
        /* Vincular um elemento anterior existente a este */ 
        if (context->inputTerminalListPrevious) context->inputTerminalListPrevious->next = entry; 
        else if ((context->inputTerminalListHead) == 0) context->inputTerminalListHead = entry; 
     
        /* Salvar o ponteiro para o elemento anterior */ 
        context->inputTerminalListPrevious = entry; 
      } 
      else { 
        /* Erro: Incapaz de alocar memória */ 
      } 
     
      return(entry); 
    } 

    O exemplo a seguir mostra o código para insOutputTerminalListEntry:

    TERMINAL_LIST_ENTRY *insOutputTerminalListEntry( 
      NODE_CONTEXT_ST* context, 
      CciChar*         terminalName 
    ){ 
      static char* functionName = (char *)"insOutputTerminalListEntry()"; 
      TERMINAL_LIST_ENTRY* entry; 
      int             rc; 
     
      entry = (TERMINAL_LIST_ENTRY *)malloc(sizeof(TERMINAL_LIST_ENTRY)); 
      if (entry) { 
     
        /* Esta entrada é o fim atual da lista */ 
        entry->next = 0; 
     
        /* Armazenar o nome do terminal */ 
        CciCharCpy(entry->name, terminalName); 
     
        /* Criar terminal e salvar seu identificador */ 
        entry->handle = cniCreateOutputTerminal(&rc, context->nodeObject, (CciChar*)terminalName); 
     
        /* Vincular um elemento anterior existente a este */ 
        if (context->outputTerminalListPrevious) context->outputTerminalListPrevious->next = entry; 
        else if ((context->outputTerminalListHead) == 0) context->outputTerminalListHead = entry; 
     
        /* Salvar o ponteiro para o elemento anterior */ 
        context->outputTerminalListPrevious = entry; 
      } 
      else { 
        /* Erro: Incapaz de alocar memória */ 
      } 
     
      return(entry); 
    } 
    Para obter o código mínimo necessário para compilar um nó definido pelo usuário C, consulte código de estrutura C.

Definindo Atributos

Os atributos são definidos sempre que se inicia o intermediário, ou quando se reimplementa um fluxo de mensagens com novos valores. Os atributos são definidos pelo intermediário, chamando o código do usuário a partir do encadeamento de configuração. Seu código precisa armazenar esses atributos em sua área de contexto do nó, para utilização no processamento de mensagens posterior.

Em seguida à criação de terminais de entrada e de saída, o intermediário chama a função cniSetAttribute para transmitir os valores dos atributos configurados para esta instanciação do nó definido pelo usuário. Por exemplo:
    {
      const CciChar* ucsAttr = CciString("nodeTraceSetting", BIP_DEF_COMP_CCSID) ;
      insAttrTblEntry(p, (CciChar*)ucsAttr, CNI_TYPE_INTEGER);
      _setAttribute(p, (CciChar*)ucsAttr, (CciChar*)constZero);
      free((void *)ucsAttr) ;
    }
    {
      const CciChar* ucsAttr = CciString("nodeTraceOutfile", BIP_DEF_COMP_CCSID) ;
      insAttrTblEntry(p, (CciChar*)ucsAttr, CNI_TYPE_STRING);
      _setAttribute(p, (CciChar*)ucsAttr, (CciChar*)constSwitchTraceLocation);
      free((void *)ucsAttr) ;
    }
O número de atributos de configuração que um nó pode ter é ilimitado. No entanto, um nó não deve implementar um atributo que já esteja implementado como um atributo de configuração base. A lista a seguir mostra os atributos base:
  • label
  • userTraceLevel
  • traceLevel
  • userTraceFilter
  • traceFilter

Implementando a Funcionalidade do Nó

Quando o intermediário recupera uma mensagem da fila e essa mensagem chega no terminal de entrada do nó de processamento de mensagens ou de saída definido pelo usuário, o intermediário chama a função de implementação cniEvaluate. Esta função é chamada no encadeamento de processamento de mensagens e deve decidir o que fazer com a mensagem. Essa função pode ser chamada em vários encadeamentos, principalmente, se instâncias adicionais forem utilizadas.

Excluindo uma Instância do Nó

Se um nó for excluído, o intermediário chamará a função cniDeleteNodeContext. Esta função é iniciada no mesmo encadeamento que cniCreateNodeContext. Utilize essa função para liberar os recursos utilizados pelo nó definido pelo usuário. Por exemplo:

void _deleteNodeContext(
  CciContext* context
){
  static char* functionName = (char *)"_deleteNodeContext()";
  free ((void*) context);
  return;
}
Avisos | Marcas Registradas | Downloads | Biblioteca | Suporte | Feedback

Copyright IBM Corporation 1999, 2014Copyright IBM Corporation 1999, 2014.

        
        Última atualização:
        
        Última atualização: 2015-02-28 18:30:26


Tópico de TarefaTópico de Tarefa | Versão 8.0.0.5 | as09980_