Antes de empezar
Una biblioteca de implementación cargable, o LIL, es el módulo de implementación para un nodo (o analizador) C. Una LIL se implementa como una biblioteca de enlaces dinámicos (DLL). No tiene la extensión de archivo .dll sino .lil.
Las funciones de implementación que el desarrollador debe escribir se listan en el apartado Funciones de implementación de nodo en C. Las funciones de programa de utilidad que WebSphere Message Broker proporciona para ayudar en este proceso se listan en el apartado Funciones de programa de utilidad de nodo en C.
WebSphere Message Broker proporciona el origen de dos nodos de ejemplo definidos por el usuario denominados SwitchNode y TransformNode. Puede utilizar estos nodos en su estado actual o puede modificarlos.
Para declarar y definir un nodo definido por el usuario en el intermediario, debe incluir una función de inicialización bipGetMessageflowNodeFactory, en su LIL. Los pasos siguientes indican cómo llama el intermediario a su función de inicialización y cómo esa función declara y define el nodo definido por el usuario:
El procedimiento siguiente muestra cómo crear instancias del nodo:
Se establecen atributos siempre que se inicia el intermediario o cuando se vuelve a desplegar el flujo de mensajes con valores nuevos.
{ 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) ; }
Cuando el intermediario sabe que tiene un nodo de entrada, invoca la función cniRun de este nodo a intervalos regulares. Entonces la función cniRun debe decidir qué acción debe realizar. Si hay datos disponibles para procesar, la función cniRun debe intentar propagar el mensaje. Si no hay datos disponibles para procesar, la función cniRun debe volver con CCI_TIMEOUT para que el intermediario pueda seguir con los cambios de configuración.
If ( algo para hacer ) CniDispatchThread; /* realizar el trabajo */ If ( trabajo realizado satisfactoriamente) Return CCI_SUCCESS_CONTINUE; Else Return CCI_FAILURE_CONTINUE; Else Return CCI_TIMEOUT;
Normalmente una implementación de nodo de entrada determina qué analizador de mensajes analiza inicialmente un mensaje de entrada. Por ejemplo, el nodo MQInput primitivo indica que se necesita un analizador MQMD para analizar la cabecera MQMD. Un nodo de entrada definido por el usuario puede seleccionar un analizador de mensajes o cabeceras apropiado y la modalidad en la que se controla el análisis, utilizando los atributos siguiente que se incluyen como valores por omisión y que se pueden alterar temporalmente:
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; ... /* Asignar un puntero al contexto local */ p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST)); /* Crear atributos y establecer valores por omisión */ { 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); /*ver BipSampPluginNode.c de ejemplo para la implementación de insAttrTblEntry*/ _setAttribute(p, (CciChar*)ucsAttrName, (CciChar*)ucsAttrValue); free((void *)ucsAttrName) ; free((void *)ucsAttrValue) ; }En el código de ejemplo anterior, se invoca al método insAttrTblEntry. Este método se declara en los nodos de ejemplo definidos por el usuario SwitchNode y TransformNode.
Los nodos se destruyen cuando se vuelve a desplegar un flujo de mensajes o cuando se detiene el proceso de grupo de ejecución (utilizando el mandato mqsistop). Cuando un nodo se destruye, debe liberar la memoria utilizada así como los recursos retenidos. Para ello, utilice la función cniDeleteNodeContext. Por ejemplo:
void _deleteNodeContext( CciContext* context ){ static char* functionName = (char *)"_deleteNodeContext()"; return; }