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ó 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.
Um nó definido pelo usuário se identifica como fornecendo a capacidade de um nó de entrada implementando a função de implementação cniRun. Os nós de entrada definidos pelo usuário precisam implementar uma função 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 contendo um nó de entrada definido pelo usuário é implementado com sucesso, o intermediário chama a função de implementação cniRun do nó em intervalos regulares.
int cniRun( CciContext* context, CciMessage* destinationList, CciMessage* exceptionList, CciMessage* message ){ ... /* Obter dados de origem externa */ return CCI_SUCCESS_CONTINUE; }O valor de retorno deve ser utilizado para retornar o controle periodicamente ao intermediário.
Quando um fluxo de mensagens contendo um nó de entrada definido pelo usuário é implementado com êxito, a função cniRun do nó é chamada para cada mensagem transmitida através do fluxo de mensagens.
Os nós de entrada também podem implementar cniEvaluate, porém isso não é recomendado.
Os atributos são definidos sempre que se inicia o intermediário, ou quando se reimplementa o fluxo de mensagens com novos valores.
{ 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 percebe que possui um nó de entrada, ele chama a função cniRun desse nó a intervalos regulares. A função cniRun deve então decidir que curso de ação tomar. Se houver dados disponíveis para processamento, a função cniRun deve chamar cniDispatchThread e processar a mensagem, ou retornar com CCI_TIMEOUT para que o intermediário possa continuar a processar outras mensagens em outros encadeamentos. Se um encadeamento não for despachado, o intermediário passará todo o tempo dentro desse encadeamento, o que o impedirá de fazer qualquer outra coisa.
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;
Uma implementação de nó de entrada em geral determina que analisador de mensagem analisa inicialmente uma mensagem de entrada. Por exemplo, o nó MQInput primitivo dita que um analisador de 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, pela utilização dos seguintes atributos que são incluídos como padrão e que podem ser substituídos:
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); }
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) ; }
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, ele deve liberar qualquer memória utilizada e quaisquer recursos retidos. Isso é feito utilizando a função cniDeleteNodeContext. Por exemplo:
void _deleteNodeContext( CciContext* context ){ static char* functionName = (char *)"_deleteNodeContext()"; return; }