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ó Input em C

Crie um nó de entrada definido pelo usuário em C para receber mensagens em um fluxo de mensagens.

Antes de começar

Uma biblioteca de implementação carregável, ou uma LIL, é 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.

As funções de implementação gravadas para o nó são listadas em Funções de Implementação de Nó C. Você pode chamar as funções de utilitário, implementadas no intermediário de tempo de execução, para ajudar na operação do nó; essas funções são listadas em 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.

Declarando e Definindo o 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 seguintes etapas descrevem como o intermediário chama a função de inicialização e como sua função de inicialização declara e define o nó definido pelo usuário:

  1. A função de inicialização, bipGetMessageflowNodeFactory, é chamada pelo intermediário depois que sistema operacional carregou e inicializou a LIL. O broker chama essa função para compreender o que a LIL pode fazer e como o broker 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 depósito de informações do provedor exclusivo (ou um nome de grupo) para todos os nós que a LIL suporta. Cada nome de gerador (ou nome de grupo) retransmitido deve ser exclusivo por todos os LILs em um único 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ções virtuais dos endereços das funções de implementação.
    Por exemplo, o código a seguir declara e define um único nó chamado InputxNode:
    {
    	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.iFpRun = _run;
    
    	cniDefineNodeClass(0, factoryObject, L"InputxNode", &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 fornecendo os recursos de um nó de entrada implementando a função de implementação cniRun.

    Os nós definidos pelo usuário precisam implementar uma função de implementação cniRun ou cniEvaluate. Se não implementarem, 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.

    Por exemplo:
    int cniRun(                       
      CciContext* context,                
      CciMessage* localEnvironment,        
      CciMessage* exceptionList,          
      CciMessage* message
    ){          
      ...
      /* Obter dados de origem externa */
      return CCI_SUCCESS_CONTINUE;                                    
    }
    Utilize o valor de retorno periodicamente para retornar o controle ao intermediário.

    Quando um fluxo de mensagens que contém um nó de entrada definido pelo usuário é implementado com êxito, a função cniRun do nó é chamada repetidamente para ativar o nó para recuperar mensagens e propagá-las ao restante do fluxo de mensagens.

    Para obter o código mínimo necessário para compilar um nó definido pelo usuário de 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 deve alocar memória para essa instanciação do nó definido pelo usuário para conter os valores para os atributos configurados. Por exemplo:
    1. Chamar a função cniCreateNodeContext:
      CciContext* _createNodeContext(
        CciFactory* factoryObject,
        CciChar*    nodeName,
        CciNode*    nodeObject
      ){
        static char* functionName = (char *)"_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. Um nó de entrada tem um número de terminais de saída associados a ele, mas em geral não tem nenhum terminal de entrada. Utilize a função de utilitário cniCreateOutputTerminal para incluir terminais de saída em um nó input quando o nó for instanciado. Essas funções devem ser chamadas dentro da função de implementação cniCreateNodeContext. Por exemplo, para definir um nó input com três terminais de saída:
       {
          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) ;
        }    
        {
          const CciChar* ucsCatch = CciString("catch", BIP_DEF_COMP_CCSID) ;
          insOutputTerminalListEntry(p, (CciChar*)ucsCatch);
          free((void *)ucsCatch) ;    }
    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 o fluxo de mensagens com novos valores.

Em seguida à criação de terminais de saída, o intermediário chama a função cniSetAttribute para transmitir os valores dos atributos configurados 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ó definido pelo usuário não deve implementar um atributo que já está implementado como um atributo de configuração base. Os atributos base são:
  • label
  • userTraceLevel
  • traceLevel
  • userTraceFilter
  • traceFilter

Implementando a Funcionalidade do Nó

Quando o intermediário percebe que possui um nó input, ele chama a função cniRun desse nó a intervalos regulares. A função cniRun deve, então, decidir qual curso de ação deve ser tomado. Se os dados estiverem disponíveis para processamento, a função cniRun poderá propagar a mensagem. Se nenhum dado estiver disponível para processamento, a função cniRun deverá retornar com CCI_TIMEOUT para que o broker possa continuar as mudanças na configuração.

Por exemplo, para configurar o nó para chamar cniDispatchThread e processar a mensagem ou retornar com CCI_TIMEOUT:
If ( anything to do )
	CniDispatchThread;

   /* fazer o trabalho */

	If ( work done O.K.)
		Return CCI_SUCCESS_CONTINUE;
	Else
		Return CCI_FAILURE_CONTINUE;
Else
  Return CCI_TIMEOUT;

Substituindo os Atributos Padrão do Analisador de Mensagem (Opcional)

Uma implementação de nó de entrada geralmente determina que o analisador de mensagem examina inicialmente uma mensagem de entrada. Por exemplo, o nó MQInput dita que um analisador MQMD é necessário para analisar o cabeçalho MQMD. Um nó de entrada definido pelo usuário pode selecionar um analisador de cabeçalho ou de mensagem apropriado, e o modo no qual a análise é controlada, utilizando ou substituindo os seguintes atributos que são incluídos como padrão:

rootParserClassName
Define o nome do analisador raiz que analisa os formatos de mensagem suportados pelo nó de entrada definido pelo usuário. Seu padrão é GenericRoot, um analisador raiz fornecido que faz com que o intermediário aloque e encadeie analisadores juntos. É improvável que um nó precise modificar esse valor de atributo.
firstParserClassName
Define o nome do primeiro analisador, naquilo que pode ser uma cadeia de analisadores responsáveis pela análise do fluxo de bits. Seu padrão é XML.
messageDomainProperty
Um atributo opcional que define o nome do analisador de mensagem necessário para analisar a mensagem de entrada. Os valores suportados são os mesmos que os valores que são suportados pelo nó MQInput. (Consulte Nó MQInput para obter informações adicionais.)
messageSetProperty
Um atributo opcional que define o identificador do conjunto de mensagem, ou o nome do conjunto de mensagem, no campo Message Set, somente se o analisador MRM tiver sido especificado pelo atributo messageDomainProperty.
messageTypeProperty
Um atributo opcional que define o identificador da mensagem no campo MessageType, somente se o analisador MRM tiver sido especificado pelo atributo messageDomainProperty.
messageFormatProperty
Um atributo opcional que define o formato da mensagem no campo Message Format, somente se o analisador MRM tiver sido especificado pelo atributo messageDomainProperty.
Se tiver gravado um nó de entrada definido pelo usuário que sempre começa com dados de uma estrutura conhecida, você poderá assegurar que um analisador específico trate o início dos dados. Por exemplo, o nóMQInput lê dados apenas a partir das filas do WebSphere MQ, portanto, estes dados sempre possuem um MQMD no início e o nó MQInput configura firstParserClassName como MQHMD. Se seu nó definido pelo usuário sempre tratar dados que começam com uma estrutura que pode ser analisada por um analisador específico, por exemplo "MYPARSER", configure firstParserClassName como MYPARSER da seguinte maneira::
  1. Declare as funções de implementação:
    CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix bipGetMessageflowNodeFactory()
    {
      ....
      CciFactory*      factoryObject;
      ....
      factoryObject = cniCreateNodeFactory(0, (unsigned short *)constPluginNodeFactory);
      ...
      vftable.iFpCreateNodeContext = _createNodeContext;
      vftable.iFpSetAttribute      = _setAttribute;
      vftable.iFpGetAttribute      = _getAttribute;
      ...  
      cniDefineNodeClass(&rc, factoryObject, (CciChar*)constSwitchNode, &vftable);
      ...
      return(factoryObject);
    }
  2. Defina o atributo na função de implementação cniCreateNodeContext:
    CciContext* _createNodeContext(
      CciFactory* factoryObject,
      CciChar*    nodeName,
      CciNode*    nodeObject
    ){
      NODE_CONTEXT_ST* p;
      ...
    
        /* Alocar um ponteiro para o contexto local */
        p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST));
        /* Criar atributos e definir valores padrão */
        {
          const CciChar* ucsAttrName  = CciString("firstParserClassName", BIP_DEF_COMP_CCSID) ;
          const CciChar* ucsAttrValue = CciString("MYPARSER", BIP_DEF_COMP_CCSID) ;
          insAttrTblEntry(p, (CciChar*)ucsAttrName, CNI_TYPE_INTEGER);
          /*consulte a amostra BipSampPluginNode.c para a implementação
    de insAttrTblEntry*/
    
          _setAttribute(p, (CciChar*)ucsAttrName, (CciChar*)ucsAttrValue);
          free((void *)ucsAttrName) ;
          free((void *)ucsAttrValue) ;
        }
    No exemplo de código acima, o método insAttrTblEntry é chamado. Esse método é declarado nos nós definidos pelo usuário de amostra SwitchNode e TransformNode.

Excluindo uma Instância do Nó

Os nós são destruídos quando um fluxo de mensagens é reimplementado ou quando o processo do grupo de execução é parado (utilizando o comando mqsistop). Quando um nó é destruído, é necessário chamar a função cniDeleteNodeContext para liberar toda memória usada e liberar todos os recursos mantidos. Por exemplo:

void _deleteNodeContext(
  CciContext* context
){
  static char* functionName = (char *)"_deleteNodeContext()";

  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 | as09960_