Antes de começar
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 não tem a extensão de arquivo .dll, mas .lil.
As funções de implementação que precisam ser escritas pelo desenvolvedor estão relacionadas em Funções de Implementação de Nó em Linguagem C. As funções utilitárias fornecidas pelo para auxiliar esse processo estão relacionadas em Funções Utilitárias de Nó em Linguagem C.
oferece o código fonte de dois nós definidos pelo usuário chamados SwitchNode e TransformNode. Você pode utilizar esses nós em seus estados atuais ou poderá modificá-los.
Conceitualmente, um nó de processamento de mensagem é utilizado para processar uma mensagem de alguma forma, e um nó de saída é 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. É possível executar processamento de mensagem dentro de um nó de saída, e da mesma forma é possível enviar uma mensagem para a saída para um fluxo de bits utilizando um nó de processamento de mensagem. 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ó.
Em muitos casos, o nó definido pelo usuário necessita acessar o conteúdo da mensagem recebida em seu terminal de entrada. A mensagem é representada como uma árvore de elementos de sintaxe. Grupos de funções utilitárias são fornecidos para gerenciamento de mensagens, acesso a buffer de mensagem, navegação de elementos de sintaxe e acesso a elementos de sintaxe. (Consulte Funções Utilitárias de Nó em Linguagem C para obter detalhes sobre as funções de utilitário).
Por exemplo, para consultar o nome e o tipo do primeiro filho do corpo:
void cniEvaluate( ... ){ ... /* Navegar até o elemento de destino */ rootElement = cniRootElement(&rc, message); bodyElement = cniLastChild(&rc, rootElement); bodyFirstChild = cniFirstChild(&rc, bodyElement); /* Consultar o nome e o valor do elemento de destino */ cniElementName(&rc, bodyFirstChild, (CciChar*)&elementname, sizeof(elementName)); bytes = cniElementCharacterValue( &rc, bodyfirstChild, (CciChar*)&eValue, sizeof(eValue)); ... }
A mensagem de entrada recebida é somente leitura, portanto antes que uma mensagem possa ser transformada é preciso gravá-la para uma nova mensagem de saída utilizando a função cniCreateMessage. É possível copiar elementos da mensagem de entrada ou criar novos elementos e anexá-los á mensagem. Os novos elementos em geral estão no domínio de um analisador.
{ ... context = cniGetMessageContext(&rc, message)); outMsg = cniCreateMessage(&rc, context)); ... }
cniSetElementIntegerValue(&rc, targetElement, L"newValue", 8);
cniDeleteMessage(&rc, outMsg);
Os nós podem chamar expressões ESQL utilizando sintaxe ESQL de nó Compute. É possível criar e modificar os componentes da mensagem utilizando as expressões ESQL e referir-se a elementos da mensagem de entrada e aos dados de um banco de dados externo utilizando as funções cniSqlCreateStatement, cniSqlSelect, cniSqlDeleteStatement e cniSqlExecute.
Por exemplo, para ocupar o elemento Result do conteúdo de uma coluna em uma tabela de banco de dados:
{ ... sqlExpr = cniSqlCreateStatement(&rc, (NODE_CONTEXT_ST *)context->nodeObject, L"DB", CCI_SQL_TRANSACTION_AUTO, L"SET OutputRoot.XML.Result[] = (SELECT T.C1 AS Col1 FROM Database.TABLE AS T;"); ... cniSqlSelect(&rc, sqlExpr, destinationList, exceptionList, message, outMsg); cniSqlDeleteStatement(&rc, sqlExpr); ... }
Para obter informações adicionais sobre ESQL, consulte ESQL.
cniFinalize(&rc, outMsg, CCI_FINALIZE_NONE);
if (terminalObject) { if (cniIsTerminalAttached(&rc, terminalObject)) { if (rc == CCI_SUCCESS) { cniPropagate(&rc, terminalObject, destinationList, exceptionList, outMsg); } }
cniDeleteMessage(&rc, outMsg);
{ ... cniWriteBuffer(&rc, message); writeToDevice(cniBufferPointer(&rc, message), cniBufferSize(&rc, message)); ... }Uma mensagem somente pode ser serializada uma vez.
O procedimento a seguir mostra como declarar o nó ao intermediário:
CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix bipGetMessageflowNodeFactory()
{ CciFactory* factoryObject; int rc = 0; CciChar factoryName[] = L"SwitchNodeFactory"; CCI_EXCEPTION_ST exception_st; /* Criar a Fábrica de Nó para este nó */ factoryObject = cniCreateNodeFactory(0, factoryName); if (factoryObject == CCI_NULL_ADDR) { if (rc == CCI_EXCEPTION) { /* Obter detalhes da exceção */ cciGetLastExceptionData(&rc, &exception_st); /* Qualquer tratamento de erro local pode ir aqui */ /* Relançar a exceção */ cciRethrowLastException(&rc); } /* Qualquer tratamento de erro local adicional pode ir aqui */ } else { /* Definir os nós suportados por esta fábrica */ defineSwitchNode(factoryObject); } /* Retornar o endereço deste objeto de fábrica para o intermediário */ return(factoryObject); }
void defineSwitchNode(void* factoryObject){ 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.iFpGetAttributeName = _getAttributeName; vftable.iFpSetAttribute = _setAttribute; vftable.iFpGetAttribute = _getAttribute; vftable.iFpEvaluate = _evaluate; cniDefineNodeClass(0, factoryObject, L"SwitchNode", &vftable); return; }Ela é chamada a partir do encadeamento de configuração.
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 a cniRun, ou ambas, caso contrário, o intermediário não carrega o nó definido pelo usuário e a função de utilitário cniDefineNodeClass falha, retornando CCI_MISSING_IMPL_FUNCTION.
Quando um fluxo de mensagens contendo um nó de processamento de mensagem definido pelo usuário é implementado com êxito, a função cniEvaluate do nó é chamada para cada mensagem transmitida através do fluxo de mensagens.
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.
void cniEvaluate( CciContext* context, CciMessage* destinationList, CciMessage* exceptionList, CciMessage* message ){ ... }
O procedimento a seguir mostra como instanciar o nó:
CciContext* _Switch_createNodeContext( CciFactory* factoryObject, CciChar* nodeName, CciNode* nodeObject ){ static char* functionName = (char *)"_Switch_createNodeContext()"; NODE_CONTEXT_ST* p; CciChar buffer[256];
p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST)); if (p) { memset(p, 0, sizeof(NODE_CONTEXT_ST));
p->nodeObject = nodeObject;
CciCharNCpy((CciChar*)&p->nodeName, nodeName, MAX_NODE_NAME_LEN);
{ 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) ; }
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.
{ 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) ; }
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.
Para excluir uma instância de um nó, é utilizada a função cniDeleteNodeContext. Por exemplo:
void _deleteNodeContext( CciContext* context ){ static char* functionName = (char *)"_deleteNodeContext()"; return; }
A função cniDeleteNodeContext é fornecida pelo usuário e é chamada pelo intermediário quando um fluxo de mensagens é excluído.
Conceitos relacionados
ESQL
Planejando Extensões Definidas pelo Usuário
Extensões Definidas pelo Usuário no Ambiente de Tempo de Execução
Projetando Extensões Definidas pelo Usuário
Nós Input definidos pelo usuário
Tarefas relacionadas
Desenvolvendo Extensões Definidas pelo Usuário
Implementando as Amostras Fornecidas
Compilando uma Extensão Definida pelo Usuário em C
Referências relacionadas
API de Nó C Definido pelo Usuário
Avisos |
Marcas |
Downloads |
Biblioteca |
Suporte |
Feedback
![]() ![]() |
as09980_ |