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

Antes de começar

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 amostra User-defined Extension que demonstra a utilização de nós definidos pelo usuário, incluindo um nó de processamento de mensagens gravado no C.

Uma biblioteca de implementação carregável, ou uma LIL, é o módulo de implementação para um nó (ou analisador) em C.Uma LIL é implementada como uma DLL (Dynamic Link Library). Ela possui a extensão de arquivo .lil, não .dll.

As funções de implementação que precisam ser escritas pelo desenvolvedor estão relacionadas em Funções de Implementação de Nó C.As funções utilitárias fornecidas pelo WebSphere Message Broker para auxiliar esse processo estão relacionadas 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. Existe também a amostra do Amostra User-defined Extension para ser utilizada.

Conceitualmente, um nó de processamento de mensagem é utilizado para processar uma mensagem de alguma forma e um nó output é utilizado para enviar uma mensagem para a saída como um fluxo de bits. Entretanto, quando se codifica um nó de processamento de mensagem ou um nó de saída, eles são essencialmente a mesma coisa. Você pode desempenhar o processamento de mensagens em um nó output e, de forma semelhante, pode exibir uma mensagem para um fluxo de bits utilizando um nó do processamento de mensagens. Para simplificar, este tópico refere-se principalmente ao nó como um nó de processamento de mensagem, no entanto, ele discute a funcionalidade dos dois tipos de nó.

As funções de ambos os tipos de nós são cobertas neste tópico. Ele esboça as seguintes etapas:
  1. Declarando e Definindo Seu Nó
  2. Criando uma Instância do Nó
  3. Definindo Atributos
  4. Implementando a Funcionalidade do Nó
  5. Excluindo uma Instância do Nó

Declarando e Definindo Seu Nó

Para declarar e definir um nó definido pelo usuário para o intermediário, é necessário incluir uma função de inicialização, bipGetMessageflowNodeFactory, no 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. A função de inicialização, bipGetMessageflowNodeFactory, é chamada pelo intermediário depois que a LIL tiver sido carregada e inicializada pelo sistema operacional. O intermediário chama essa função para compreender o que a LIL é capaz de fazer e como o intermediário deve 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 do depósito de informações do provedor (ou nome de grupo) deve ser exclusivo por todas as LILs no intermediário.
  3. A LIL deve em seguida 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 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 fornecendo a capacidade de um nó de processamento de mensagem ou de saída implementando a função cniEvaluate. Os nós definidos pelo usuário precisam implementar uma função de implementação cniEvaluate ou cniRun, caso contrário, o intermediário não carrega o nó definido pelo usuário e a função do utilitário cniDefineNodeClass falha, 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 através do terminal de entrada do nó, ou seja, a mensagem, o ambiente global, o ambiente local e a lista de exceções.

    Por exemplo:
    void cniEvaluate(
      CciContext* context,
      CciMessage* destinationList,
      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ó

O procedimento a seguir mostra como instanciar o 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. 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. Essa função deve alocar memória para essa instanciação do nó definido pelo usuário para conter os valores dos 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. Na função de usuário cniCreateNodeContext, as chamadas devem ser feitas a cniCreateInputTerminal e cniCreateOutputTerminal para definir os terminais do nó do usuário. Essas funções devem ser chamadas dentro da 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) ;
        }
    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. O código do usuário 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) ;
    }
Início da mudançaNão existe limite para o número de atributos de configuração que um nó pode ter. No entanto, um nó de plug-in não deve implementar um atributo que já está implementado como um atributo de configuração base. Esses atributos base são:
  • label
  • userTraceLevel
  • traceLevel
  • userTraceFilter
  • traceFilter
Fim da mudança

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 mensagem ou de saída definido pelo usuário, o intermediário chama a função de implementação cniEvaluate. Essa função é chamada a partir do encadeamento de processamento de mensagens e ela 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ó

No caso de um nó que está sendo excluído, o intermediário chama a função cniDeleteNodeContext. Essa função deve liberar todos 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
Direitos Autorais IBM Corporation 1999, 2006 Última Atualização: 1 Sep 2006
as09980_