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-Datei wird als DLL-Datei (Dynamic Link Library) 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. Beim Codieren eines Nachrichtenverarbeitungsknotens und eines Sendeknotens handelt es sich jedoch um das Gleiche. Sie können an einem Sendeknoten Nachrichten verarbeiten, und ebenso können Sie mit einem Nachrichtenverarbeitungsknoten eine Nachricht als Bitstrom ausgeben. Zur Vereinfachung wird in diesem Abschnitt von einem Nachrichtenverarbeitungsknoten gesprochen, auch wenn die Funktionen beider Knotentypen erläutert werden.

Dieser Abschnitt umfasst die Funktionen beider Knotentypen. Sie finden darin die folgenden Themen:
  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

Sie müssen zum Deklarieren und Definieren eines benutzerdefinierten Knotens für den Broker eine Initialisierungsfunktion, bipGetMessageflowNodeFactory, in Ihrer LIL einfügen. Die folgenden Schritte werden im Konfigurations-Thread ausgeführt und legen fest, wie die Initialisierungsfunktion vom Broker aufgerufen wird und wie durch diese Funktion der benutzerdefinierte Knoten deklariert und definiert wird:

  1. Die Funktion bipGetMessageflowNodeFactory zur Initialisierung wird aufgerufen, nachdem die LIL-Datei vom Betriebssystem geladen und initialisiert wurde. Der Broker ruft diese Funktion auf, um die Möglichkeiten der LIL-Datei zu überprüfen und um herauszufinden, wie die LIL-Datei vom Broker aufgerufen werden soll. Beispiel:
    CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix
    bipGetMessageflowNodeFactory()
  2. Durch die Funktion bipGetMessageflowNodeFactory wird anschließend die Dienstprogrammfunktion cniCreateNodeFactory aufgerufen. Diese Funktion gibt für alle Knoten, die von der LIL-Datei unterstützt werden, einen Factory-Namen (oder Gruppennamen) zurück. 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};
    
    	/* Setup function table with pointers to node implementation functions */
    	vftable.iFpCreateNodeContext = _createNodeContext;
    	vftable.iFpDeleteNodeContext = _deleteNodeContext;
    	vftable.iFpGetAttributeName2 = _getAttributeName2;
    	vftable.iFpSetAttribute = _setAttribute;
    	vftable.iFpGetAttribute2     = _getAttribute2;
    	vftable.iFpEvaluate = _evaluate;
    
    	cniDefineNodeClass(0, factoryObject, L"MessageProcessingxNode", &vftable);
    
    	}
    
    	/* Return address of this factory object to the broker */
    	return(factoryObject);
    }

    Ein benutzerdefinierter Knoten stellt die Funktion eines Nachrichtenverarbeitungsknotens oder Sendeknotens bereit, 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.

    Die Nachrichtenflussdaten (d. h. Nachricht, globale Umgebung, lokale Umgebung und Ausnahmeliste) werden auf dem Eingabeterminal des Knotens empfangen.

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

Instanz des Knotens erstellen

In der folgenden Prozedur wird beschrieben, wie Sie für Ihren Knoten eine Instanz erstellen können:

  1. Wenn der Broker die Zeiger der Funktionstabelle erhalten hat, ruft er für jede Erstellung einer Instanz des benutzerdefinierten Knotens die Funktion cniCreateNodeContext auf. Wenn drei Nachrichtenflüsse vorhanden sind, die Ihren benutzerdefinierten Knoten verwenden, wird die Funktion cniCreateNodeContext für jeden dieser Knoten aufgerufen. Durch diese Funktion soll Speicher für die Instanzerstellung der benutzerdefinierten Knoten reserviert werden, damit dort die Werte der konfigurierten Attribute gespeichert werden können. 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 Zeiger des Knotenobjekts im Kontext:
         p->nodeObject = nodeObject;
    4. Speichern Sie den Knotennamen:
       CciCharNCpy((CciChar*) &p->nodeName, nodeName, MAX_NODE_NAME_LEN);
    5. Geben Sie den Knotenkontext zurück:
      return (CciContext*) p;
  2. Der Broker ruft die entsprechenden Dienstprogrammfunktionen auf, um die Eingabe- und Ausgabeterminals des Knotens zu überprüfen. Ein Knoten enthält eine Reihe von Eingabe- und Ausgabeterminals, die dem Knoten zugeordnet sind. In der Benutzerfunktion cniCreateNodeContext sollten die Funktionen cniCreateInputTerminal und cniCreateOutputTerminal aufgerufen werden, um die Terminals des Benutzerknotens zu definieren. Diese Funktionen müssen innerhalb der Implementierungsfunktion cniCreateNodeContext aufgerufen werden. Gehen Sie beispielweise bei der Definition eines Knotens mit einem Eingabeterminal und zwei Ausgabeterminals folgendermaßen vor:
        {
          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) ;
        }
    Informationen zum Code, der mindestens erforderlich ist, um einen benutzerdefinierten Knoten in C zu kompilieren, finden Sie unter Basiscode für C-Knoten.

Attribute festlegen

Attribute werden festgelegt, wenn Sie den Broker starten oder einen Nachrichtenfluss mit neuen Werten erneut einsetzen. Die Attribute werden von dem Broker festgelegt, der den Benutzercode im Konfigurations-Thread aufruft. Diese Attribute müssen im Bereich des Knotenkontexts des Benutzercodes gespeichert werden, damit sie später bei der Verarbeitung der Nachrichten verwendet werden können.

Nach der Erstellung von Eingabe- und Ausgabeterminals wird vom Broker die Funktion cniSetAttribute aufgerufen, um die Werte der konfigurierten Attribute für diese Instanzerstellung 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) ;
    }
Beginn der ÄnderungDie Anzahl der Konfigurationsattribute in einem Knoten ist nicht begrenzt. Ein Plug-in-Knoten darf jedoch kein Attribut implementieren, das bereits als Basiskonfigurationsattribut implementiert ist. Zu diesen Basisattributen zählen:
  • label
  • userTraceLevel
  • traceLevel
  • userTraceFilter
  • traceFilter
Ende der Änderung

Knotenfunktionen implementieren

Wenn der Broker eine Nachricht aus der Warteschlange empfängt und diese Nachricht den Eingabeterminal Ihres benutzerdefinierten Nachrichtenverarbeitungs- oder Sendeknoten erreicht, wird vom Broker die Implementierungsfunktion cniEvaluate aufgerufen. Diese Funktion wird im Thread zur Nachrichtenverarbeitung aufgerufen und sollte entscheiden, auf welche Weise die Nachricht verarbeitet wird. Möglicherweise wird diese Funktion in mehreren Threads aufgerufen, besonders bei Verwendung von zusätzlichen Instanzen.

Instanz des Knotens löschen

Wird 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:

void _deleteNodeContext(
  CciContext* context
){
  static char* functionName = (char *)"_deleteNodeContext()";
  free ((void*) context);  return;
}
Bemerkungen | Marken | Downloads | Bibliothek | Unterstützung | Rückmeldung
Copyright IBM Corporation 1999, 2006 Letzte Aktualisierung: 23. Aug. 2006
as09980_