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 User-defined Extension sample 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ó output, 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ó

Início da mudançaPara 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 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:Fim da mudança

  1. A função de inicialização, bipGetMessageflowNodeFactory, é chamada pelo intermediário depois que a LIL tiver sido carregada e inicializada pelo sistema operacional. Ela é chamada a partir do encadeamento de configuração do intermediário. 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 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 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
    ){
    ...
    }
    Início da mudançaPara obter o código mínimo necessário para compilar um nó definido pelo usuário C, consulte código de estrutura C.Fim da mudança

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. Início da mudançaRetorne o contexto do nó:
      return (CciContext*) p;
      Fim da mudança
  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) ;
    }
    Início da mudançaPara obter o código mínimo necessário para compilar um nó definido pelo usuário C, consulte código de estrutura C.Fim da mudança

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) ;
}

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ó

Início da mudançaNo 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:Fim da mudança

void _deleteNodeContext(
  CciContext* context
){
  static char* functionName = (char *)"_deleteNodeContext()";
Início da mudançafree ((viod*) context);Fim da mudança return;
}
Notices | Trademarks | Downloads | Library | Support | Feedback
Copyright IBM Corporation 1999, 2006 Last updated: 5월 25, 2006
as09980_