Nachrichtenverarbeitungs- oder Sendeknoten in C erstellen

Vorbereitungen

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 jedoch nicht die Dateierweiterung .dll, sondern .lil.

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 'TransformNode' bereit. Sie können diese Knoten in ihrem aktuellen Zustand verwenden, oder Sie können sie ändern. Sie können auch das Beispiel für Benutzerdefinierte Erweiterung 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 sie 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.

Knoten beim Broker deklarieren

Im Folgenden wird die Vorgehensweise bei der Deklaration des Knotens beim Broker beschrieben:

  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. Die Funktion bipGetMessageflowNodeFactory ruft dann die Dienstprogrammfunktion cniCreateNodeFactory auf. Diese Funktion gibt einen Factory-Namen (oder Gruppennamen) für alle Knoten zurück, die Ihre LIL unterstützt. Beispiel:
    {
    	CciFactory* factoryObject;
    	int rc = 0;
    	CciChar factoryName[] = L"SwitchNodeFactory";
    	CCI_EXCEPTION_ST exception_st;
    
    	/* Create the Node Factory for this node */
    	factoryObject = cniCreateNodeFactory(0, factoryName);
    	if (factoryObject == CCI_NULL_ADDR) {
    		if (rc == CCI_EXCEPTION) {
    			/* Get details of the exception */
    			cciGetLastExceptionData(&rc, &exception_st);
    
    			/* Any local error handling can go here */
    
    			/* Rethrow the exception */
    			cciRethrowLastException(&rc);
    		}
    
    		/* Any further local error handling can go here */
    	}
    	else {
    		/* Define the nodes supported by this factory */
    		defineSwitchNode(factoryObject);
    	}
    
    	/* Return address of this factory object to the broker */
    	return(factoryObject);
    }

    Werden in diesem Beispiel Trace-Information im Format UTF-16 erforderlich, müssen Sie CCI_EXCEPTION_ST durch CCI_EXCEPTION_WIDE_ST und cciGetLastExceptionData durchcciGetLastExceptionDataW ersetzen.

Knoten als Nachrichtenverarbeitungsknoten definieren

Anschließend sollte die LIL die Dienstprogrammfunktion cniDefineNodeClass aufrufen, um die Namen der einzelnen Knoten und eine virtuelle Funktionstabelle der Adressen der Implementierungsfunktionen zu übergeben. So definieren Sie beispielsweise einen einzelnen Knoten mit dem Namen 'Umschaltungsknoten' und dessen Funktionstabelle:
void defineSwitchNode(void* factoryObject){
	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"SwitchNode", &vftable);

	return;
}
Diese Funktion wird vom Konfigurations-Thread aus ausgerufen.

Ein benutzerdefinierter Knoten identifiziert sich selbst als Nachrichtenverarbeitungsknoten oder Sendeknoten, indem er die Funktion cniEvaluate implementiert. Benutzerdefinierte Empfangsknoten müssen eine cniEvaluate- und/oder 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.

Wenn ein Nachrichtenfluss, der einen benutzerdefinierten Nachrichtenverarbeitungsknoten enthält, erfolgreich implementiert wird, wird die Funktion cniEvaluate des Knotens für jede Nachricht, die den Nachrichtenfluss durchläuft, aufgerufen.

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                 
){                                    
  ...
}

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);
  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) ;
        }

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 Nachrichtenverarbeitungsknotens löschen

Zum Löschen einer Instanz eines Knotens verwenden Sie die Funktion cniDeleteNodeContext. Beispiel:

void _deleteNodeContext(
  CciContext* context
){
  static char* functionName = (char *)"_deleteNodeContext()";

  return;
}

Die Funktion cniDeleteNodeContext wird vom Benutzer bereitgestellt und wird vom Broker aufgerufen, wenn ein Nachrichtenfluss gelöscht wird.

Zugehörige Verweise
Benutzerdefinierte C-Knoten-API
Bemerkungen | Marken | Downloads | Bibliothek | Unterstützung | Rückmeldung
Copyright IBM Corporation 1999, 2005 Letzte Aktualisierung: Nov 17, 2005
as09980_