Prima di iniziare
Una libreria di implementazione caricabile, o LIL (Loadable Implementation Library), è il modulo di implementazione di un nodo C (o programma di analisi). Una LIL è implementata come una DLL (Dynamic Link Library). La sua estensione file non è .dll, ma .lil.
Le funzioni di implementazione che devono essere scritte dallo sviluppatore sono riportate in Funzioni di implementazione del nodo in C. Le funzioni di utilità che sono fornite da WebSphere Message Broker per facilitare questa elaborazione sono riportate in Funzioni di utilità del nodo in C.
WebSphere Message Broker fornisce l'origine per due nodi definiti dall'utente di esempio denominati SwitchNode e TransformNode. E' possibile utilizzare tali nodi nel loro stato attuale oppure modificarli.
Per dichiarare e definire un nodo definito dall'utente al broker è necessario includere una funzione di inizializzazione, bipGetMessageflowNodeFactory nella LIL. I passi seguenti evidenziano il modo in cui il broker chiama la funzione di inizializzazione e come tale funzione dichiara e definisce il nodo definito dall'utente:
Gli attributi vengono impostati ogni volta che viene avviato il broker oppure quando il flusso di messaggi viene ridistribuito con nuovi valori.
{ 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 il broker sa di disporre di un nodo di input, richiama ad intervalli regolari la funzione cniRun di questo nodo. La funzione cniRun decide quindi l'azione da intraprendere. Se i dati sono disponibili per l'elaborazione, la funzione cniRun deve cercare di propagare il messaggio. Se i dati non sono invece disponibili, la funzione cniRun deve restituire CCI_TIMEOUT in modo che il broker possa continuare le modifiche di configurazione.
If ( anything to do ) CniDispatchThread; /* esegue il lavoro */ If ( work done O.K.) Return CCI_SUCCESS_CONTINUE; Else Return CCI_FAILURE_CONTINUE; Else Return CCI_TIMEOUT;
L'implementazione di un nodo di input determina normalmente il programma di analisi che inizialmente analizza un messaggio di input. Ad esempio, il nodo MQInput primitivo richiede che per analizzare l'intestazione MQMD venga utilizzato un programma di analisi MQMD. Un nodo di input definito dall'utente può selezionare un programma di analisi del messaggio o un'intestazione appropriata, e la modalità secondo cui viene gestita l'analisi, utilizzando i seguenti attributi inclusi come impostazione predefinita, che è comunque possibile sovrascrivere:
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; ... /* Assegna un puntatore al contesto locale */ p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST)); /* Crea attributi e imposta i valori predefiniti */ { 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); /*fare riferimento all'esempio BipSampPluginNode.c per l'implementazione di insAttrTblEntry*/ _setAttribute(p, (CciChar*)ucsAttrName, (CciChar*)ucsAttrValue); free((void *)ucsAttrName) ; free((void *)ucsAttrValue) ; }Nell'esempio di codice precedente, viene richiamato il metodo insAttrTblEntry. Questo metodo è dichiarato nei nodi definiti dall'utente di esempio SwitchNode e TransformNode.
I nodi vengono eliminati quando viene ridistribuito un flusso di messaggi oppure quando viene arrestata l'elaborazione del gruppo di esecuzione (utilizzando il comando mqsistop). Quando un nodo viene eliminato, deve liberare la memoria utilizzata e rilasciare le eventuali risorse impegnate. A tal fine, utilizzare la funzione cniDeleteNodeContext. Ad esempio:
void _deleteNodeContext( CciContext* context ){ static char* functionName = (char *)"_deleteNodeContext()"; return; }