Nachrichtenverarbeitungs- oder Sendeknoten in C erstellen

Vorbereitungen

WebSphere Message Broker stellt die Quelle für die zwei benutzerdefinierten Beispielknoten 'Umschaltungsknoten' und 'Umsetzungsknoten' bereit. Sie können diese Knoten in ihrem aktuellen Zustand verwenden oder sie ändern. Des Weiteren können Sie das Beispiel zur benutzerdefinierten Erweiterung anzeigen, in dem die Verwendung benutzerdefinierter Knoten einschließlich eines in C geschriebenen Nachrichtenverarbeitungsknotens veranschaulicht wird.

Eine ladbare Implementierungsbibliothek (Loadable Implementation Library, LIL) ist das Implementierungsmodul für einen C-Knoten (oder -Parser). Eine LIL ist als DLL-Datei implementiert. Sie hat die Dateierweiterung '.lil', nicht '.dll'.

Die Implementierungsfunktionen, die vom Entwickler geschrieben werden müssen, sind unter Implementierungsfunktionen für C-Knoten aufgelistet. Die Dienstprogrammfunktionen, die von WebSphere Message Broker bereitgestellt werden, um diesen Prozess zu unterstützen, sind unter Dienstprogrammfunktionen für C-Knoten aufgelistet.

WebSphere Message Broker stellt die Quelle für die zwei benutzerdefinierten Beispielknoten 'Umschaltungsknoten' und 'Umsetzungsknoten' bereit. Sie können diese Knoten in ihrem aktuellen Zustand verwenden oder sie ändern. Sie können auch das Beispiel für Beispielprogramm 'User-defined Extension' verwenden.

Konzeptionell wird ein Nachrichtenverarbeitungsknoten zur Verarbeitung einer Nachricht und ein Sendeknoten zur Ausgabe einer Nachricht als Bitstrom verwendet. Wenn Sie jedoch einen Nachrichtenverarbeitungsknoten oder einen Sendeknoten codieren, sind diese im Wesentlichen identisch. Sie können an einem Sendeknoten Nachrichten verarbeiten, und ebenso können Sie mit einem Nachrichtenverarbeitungsknoten eine Nachricht als Bitstrom ausgeben. Der Einfachheit halber wird der Knoten in diesem Abschnitt hauptsächlich als Nachrichtenverarbeitungsknoten bezeichnet, es werden jedoch die Funktionen beider Knotentypen beschrieben.

Dieser Abschnitt enthält Informationen zu den Funktionen beider Knotentypen. Folgende Schritte werden erläutert:
  1. Knoten deklarieren und definieren
  2. Instanz des Knotens erstellen
  3. Attribute festlegen
  4. Knotenfunktionen implementieren
  5. Instanz des Knotens löschen

Knoten deklarieren und definieren

Beginn der ÄnderungSie müssen zum Deklarieren und Definieren eines benutzerdefinierten Knotens für den Broker eine Initialisierungsfunktion, bipGetMessageflowNodeFactory, in Ihrer LIL einfügen. Im Folgenden wird erläutert, wie die Initialisierungsfunktion vom Broker aufgerufen wird und wie durch diese Funktion der benutzerdefinierte Knoten deklariert und definiert wird:Ende der Änderung

  1. Die Initialisierungsfunktion bipGetMessageflowNodeFactory wird vom Broker aufgerufen, nachdem die LIL vom Betriebssystem geladen und initialisiert wurde. Diese wird vom Konfigurations-Thread des Brokers aus ausgerufen. Der Broker ruft diese Funktion auf, um zu erkennen, wozu Ihre LIL in der Lage ist und wie der Broker die LIL aufrufen soll. Beispiel:
    CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix
    bipGetMessageflowNodeFactory()
  2. Durch die Funktion bipGetMessageflowNodeFactory wird anschließend die Dienstprogrammfunktion cniCreateNodeFactory aufgerufen. Diese Funktion gibt einen Factory-Namen (oder Gruppennamen) für alle Knoten zurück, die Ihre LIL unterstützt. Jeder Factory-Name (oder Gruppenname) muss für alle LIL-Dateien im Broker eindeutig sein.
  3. Anschließend muss die LIL die Dienstprogrammfunktion cniDefineNodeClass aufrufen, um die eindeutigen Namen der einzelnen Knoten und eine virtuelle Funktionstabelle der Adressen der Implementierungsfunktionen zu übergeben.
    Der folgende Code deklariert und definiert beispielsweise einen einzelnen Knoten namens 'MessageProcessingxNode':
    {
    CciFactory*      factoryObject;
    int                rc = 0;
    	CciChar factoryName[] = L"MyNodeFactory";
    	CCI_EXCEPTION_ST exception_st;
    	/* Create the Node Factory for this node */
    	factoryObject = cniCreateNodeFactory(0, factoryName);
    if (factoryObject == CCI_NULL_ADDR) {
    			/* Any local error handling can go here */
    }
    else {
    		/* Define the nodes supported by this factory */
    	static CNI_VFT vftable = {CNI_VFT_DEFAULT};
    	/* Definition der Funktionstabelle mit Zeigern zu Funktionen für Knotenimplementierung */
    vftable.iFpCreateNodeContext = _createNodeContext;
    vftable.iFpDeleteNodeContext = _deleteNodeContext;
    vftable.iFpGetAttributeName2 = _getAttributeName2;
    vftable.iFpSetAttribute      = _setAttribute;
    vftable.iFpGetAttribute2     = _getAttribute2;
    	vftable.iFpEvaluate = _evaluate;
    	cniDefineNodeClass(0, factoryObject, L"MessageProcessingxNode", &vftable);
    }
    /* Rückkehradresse dieses Factory-Objekts zum Broker */
    return(factoryObject);
    }

    Ein benutzerdefinierter Knoten identifiziert sich selbst als Nachrichtenverarbeitungsknoten oder Sendeknoten, indem er die Funktion cniEvaluate implementiert. Benutzerdefinierte Knoten müssen entweder eine cniEvaluate- oder eine cniRun-Implementierungsfunktion implementieren, ansonsten lädt der Broker den benutzerdefinierten Knoten nicht, und die Dienstprogrammfunktion cniDefineNodeClass schlägt mit dem Rückkehrcode CCI_MISSING_IMPL_FUNCTION fehl.

    Nach dem erfolgreichen Einsetzten eines Nachrichtenflusses mit benutzerdefiniertem Nachrichtenverarbeitungsknoten wird die Funktion cniEvaluate des Knotens für jede Nachricht aufgerufen, die an den Knoten weitergegeben wird.

    Nachrichtenflussdaten, d. h. die Nachricht, die globale Umgebung, die lokale Umgebung und die Ausnahmeliste, werden am Eingabeterminal des Knotens empfangen.

    Beispiel:
    void cniEvaluate(                
    CciContext* context,                
    CciMessage* destinationList,        
    CciMessage* exceptionList,          
    CciMessage* message                 
    ){
    ...
    }
    Beginn der ÄnderungInformationen zum Code, der mindestens erforderlich ist, um einen benutzerdefinierten Knoten in C zu kompilieren, finden Sie unter Basiscode für C-Knoten. Ende der Änderung

Instanz des Knotens erstellen

Im Folgenden wird die Vorgehensweise bei der Erstellung einer Instanz des Knotens beschrieben:

  1. Wenn der Broker die Tabelle mit den Funktionszeigern empfangen hat, ruft er für jede Instanzerstellung des benutzerdefinierten Knotens die Funktion cniCreateNodeContext auf. Wenn Sie über drei Nachrichtenflüsse verfügen, die Ihren benutzerdefinierten Knoten verwenden, wird Ihre Funktion cniCreateNodeContext für jeden Nachrichtenfluss aufgerufen. Diese Funktion sollte Speicher für diese Instanzerstellung des benutzerdefinierten Knotens reservieren, um die Werte für die konfigurierten Attribute zu speichern. Beispiel:
    1. Die Benutzerfunktion cniCreateNodeContext wird aufgerufen:
      CciContext* _Switch_createNodeContext(
      CciFactory* factoryObject,
      CciChar*    nodeName,
      CciNode*    nodeObject
      ){
      static char* functionName = (char *)"_Switch_createNodeContext()";
      NODE_CONTEXT_ST* p;
      CciChar          buffer[256];
    2. Ordnen Sie dem lokalen Kontext einen Zeiger zu, und löschen Sie den Kontextbereich:
      p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST));
      if (p) {
      memset(p, 0, sizeof(NODE_CONTEXT_ST));
    3. Speichern Sie den Knotenobjektzeiger im Kontext:
      p->nodeObject = nodeObject;
    4. Speichern Sie den Knotennamen:
      CciCharNCpy((CciChar*) &p->nodeName, nodeName, MAX_NODE_NAME_LEN);
    5. Beginn der ÄnderungGeben Sie den Knotenkontext zurück:
      return (CciContext*) p;
      Ende der Änderung
  2. Der Broker ruft die entsprechenden Dienstprogrammfunktionen auf, um die Eingabe- und Ausgabeterminals des Knotens zu ermitteln: Einem Knoten sind eine Reihe von Eingabeterminals und Ausgabeterminals zugeordnet. In der Benutzerfunktion cniCreateNodeContext sollten cniCreateInputTerminal und cniCreateOutputTerminal aufgerufen werden, um die Terminals des Benutzerknotens zu definieren. Diese Funktionen müssen in der Implementierungsfunktion cniCreateNodeContext aufgerufen werden. Im Folgenden finden Sie ein Beispiel für die Definition eines Knotens mit einem Eingabeterminal und zwei Ausgabeterminals:
    {
    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) ;
    }
    Beginn der ÄnderungInformationen zum Code, der mindestens erforderlich ist, um einen benutzerdefinierten Knoten in C zu kompilieren, finden Sie unter Basiscode für C-Knoten. Ende der Änderung

Attribute festlegen

Attribute werden festgelegt, wenn Sie den Broker starten oder wenn Sie einen Nachrichtenfluss mit neuen Werten erneut implementieren. Attributes werden vom Broker durch Aufrufen von Benutzercode im Konfigurations-Thread festgelegt. Der Benutzercode muss diese Attribute zur späteren Verwendung bei der Verarbeitung von Nachrichten im Knotenkontextbereich speichern.

Nach der Erstellung von Eingabe- und Ausgabeterminals ruft der Broker die Funktion cniSetAttribute auf, um die Werte für die konfigurierten Attribute für diese Instanzerstellung des des benutzerdefinierten Knotens zu übergeben. Beispiel:
{
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) ;
}

Knotenfunktionen implementieren

Wenn der Broker eine Nachricht aus der Warteschlange abruft und diese Nachricht am Eingabeterminal Ihres benutzerdefinierten Nachrichtenverarbeitungs- oder Sendeknotens eingeht, ruft der Broker die Implementierungsfunktion cniEvaluate auf. Diese Funktion wird im Nachrichtenverarbeitungs-Thread aufgerufen und sollte entscheiden, welche Maßnahmen für die Nachricht ergriffen werden. Diese Funktion kann in mehreren Threads aufgerufen werden, vor allem, wenn zusätzliche Instanzen verwendet werden.

Instanz des Knotens löschen

Beginn der ÄnderungWird ein Knoten gelöscht, ruft der Broker die Funktion cniDeleteNodeContext auf. Von dieser Funktion müssen alle Ressourcen freigegeben werden, die von Ihrem benutzerdefinierter Knoten verwendet werden. Beispiel: Ende der Änderung

void _deleteNodeContext(
CciContext* context
){
static char* functionName = (char *)"_deleteNodeContext()";
Beginn der Änderungfree ((viod*) context);Ende der Änderung return;
}
Bemerkungen | Marken | Downloads | Bibliothek | Unterstützung | Rückmeldung
Copyright IBM Corporation 1999, 2006 Letzte Aktualisierung: 18.05.2006
as09980_