next up previous contents
Next: Graphische Aufbereitung der Managementdaten Up: Programmierung mit den SPECTRUM Previous: Übersicht über die Level-II

Inference Handler Application Programming Interface

Im folgenden wird anhand eines Beispiels das Verfahren erläutert, das die Erweiterung der Virtual Network Machine um neues prozedurales Wissen zuläßt. Vererbung von Modelltypen und Inference Handlernmtihder

Wie in Abschnitt 3.3 beschrieben, sind Inference Handler Teile von Modelltypen. Ebenso wie das deklarative Wissen (Attribute, Relationen,...) eines Modelltyps kann auch das prozedurale Wissen an davon abgeleitete Modelltypen vererbt werden. Abbildung 6.7 stellt die Vererbungshierarchie von Modelltypen der Klassenhierarchie der allgemeinen (general purpose) Inference Handler gegenüber.
Die allgemeinen Inference Handler stellen dem Entwickler eine Vielzahl von Methoden zur Verfügung, die aufgrund ihrer Vielseitigkeit auf allen Attributen von Modelltypen arbeiten. In erster Linie werden Methoden angeboten, die arithmetische Operationen ermöglichen:

Zusätzlich gibt es Methoden zur Schwellwertüberwachung (CsIHThreshold).

Es ist wichtig, sich vor Augen zu führen, daß die allgemeinen Inference Handler nur ein sehr kleiner Teil der insgesamt vorhandenen Inference Handler sind. Sie stellen Hilfsfunktionen dar, die an keine spezifischen Modelltypen gebunden sind und erscheinen in einem eigenständigen Ast des Vererbungsbaumes.
CsIHBase [*] ist die Basisklasse für alle, d.h. sowohl für allgemeine als auch für spezielle, an Modelltypen gebundene, Inference Handler.

Auf den ersten Blick mag es merkwürdig erscheinen, daß die Darstellung der Inference Handler Klassenhierarchie lediglich eine geringe Anzahl umfaßt und Modelltyp-bezogene Inference Handler (d.h. Inference Handler, die für einen konkreten Modelltyp Funktionalität erbringen) nicht erfaßt sind.
Der Grund hierfür ist, daß Cabletron Modelltyp-spezifische Inference Handler grundsätzlich nicht publiziert, da dringend davon abgeraten wird, Vielfachvererbung im Zusammenhang mit Inference Handlern zu verwenden. Daher wird Multiple Inheritance auch nicht unterstützt und eine Veröffentlichung der Inference Handler unterbleibt, so daß neue Inference Handler lediglich von CsIHBase abgeleitet werden können. Die Erfahrung hat gezeigt, daß Vielfachvererbung, obwohl programmiertechnisch ohne weiteres möglich, äußerst komplexe Seiteneffekte auf Attribute (die unter Umständen von anderen Inference Handlern überwacht werden) zur Folge hat und daher eine häufige, kaum entdeckbare Ursache für schwerwiegende Fehler ist.

Die Folge ist, daß eine der wichtigsten Eigenschaften des objektorientierten Paradigmas, die Multiple Inheritance, eingebüßt wird und jeder neu erzeugte Inference Handler auf der gleichen Stufe wie CsIHFunction und CsIHAsserter in der Klassenhierarchie steht.

In Abbildung 6.7 sind nur die allgemeinen Inference Handler dargestellt, da die Hierarchie aller Inference Handler aus den oben erwähnten Gründen flach und damit sehr breit wäre, da eine Ableitungstiefe, wie sie bei der Vererbungshierarchie für Modelltypen vorkommt, hier nicht existieren darf.

Aufgrund der großen Anzahl an Modelltypen konnte in Abbildung 6.7 lediglich der oberste Teil der Hierarchie berücksichtigt werden.

Die vier von Root direkt abgeleiteten Modelltypen stellen einen allgemeinen Beschreibungsrahmen auf, indem die folgenden Fragenkomplexe durch jeweils eine Klasse repräsentiert werden:

Beim Durchlaufen der baumartigen Hierarchie von Root abwärts werden die Modelltypen immer konkreter, bis auf der untersten Stufe Modelltypen wie ,,SNMP-Workstation`` oder ,,Coax-Segment`` stehen. Hersteller- und produktspezifische Modelltypen können davon ohne großen Aufwand abgeleitet werden.

Von großem Interesse für die vorliegende Arbeit ist die Fragestellung, wie man neue Inference Handler in bestehende Modelltypen einbringen kann.

Das anschließende Beispiel geht von folgendem Szenario aus:
Für einen CABLETRON-Sternkoppler mit der Typenbezeichnung IRM2 soll das Attribut ,,DeviceCRC``, ein Zähler für MAC-Frames, bei denen ein Prüfsummenfehler festgestellt wurde, überwacht werden und bei einer Änderung dieses Attributs der vorherige sowie der neue Wert am Bildschirm ausgegeben werden.

Zur Erläuterung des Verfahrens sind jeweils nach der Beschreibung der Teilschritte die entsprechenden C++-Codefragmente aufgeführt. Der vollständige Abdruck der für den neuen Inference Handler erforderlichen Quelltextdateien befindet sich in Anhang B.

Zuerst muß man sich Klarheit darüber verschaffen, wie man auf einen Modelltyp und seine Attribute zugreifen kann:
Jeder Modelltyp und jedes seiner Attribute sind eindeutig durch einen Model Type Handle bzw. einen Attribute-Identifier, beides Hexadezimalziffern, identifizierbar. Im vorliegenden Fall hat der Modelltyp CS_IRM2_HUB (CS {großes ,,S``} steht hier für ,,Cabletron Systems`` und nicht etwa für ,,Class``) den Model Type Handle 10059; der Attribute-Identifier für ,,DeviceCRC`` lautet 10e33.

Diese Werte müssen in einem Header-File dem zu entwickelnden Inference Handler bekanntgemacht werden, was durch die nachfolgenden Zeilen geschieht:

class CsIRM2Hub
{
        public:
                enum
                {
                  DeviceCRC                     =       0x10e33
                };
};

// Model Type Handle
#define IRM2_TEST_MTYPE         0x10059

Der Entwurf des eigentlichen Inference Handlers folgt immer dem nachstehend angegebenen Ablauf:

1.
Jeder Inference Handler muß von CsIHBase abgeleitet werden, damit er mittels Vererbung mit der benötigten Grundmenge von Methoden ausgestattet wird.
Im folgenden Beispiel lautet der neue Inference Handler CsIHTest und wird in der Kopfzeile seines Constructors von CsIHBase abgeleitet:
    CsIHTest::CsIHTest( CsMTypeHandle& in_m_t_handle )
   : CsIHBase ( in_m_t_handle )
2.
Zuerst muß geprüft werden, ob das zu überwachende Attribut auch tatsächlich im ausgewählten Model Type vorkommt. Im Fehlerfalle wird eine Meldung ausgegeben.

    CsVnmMTypeHandle *vmth = new CsVnmMTypeHandle( in_m_t_handle );

    // Verify that the model type contains the attribute DeviceCRC.

    if ( ! vmth->has_attr ( CsIRM2Hub::DeviceCRC ))
    {
        eout( "No such attribute: DeviceCRC" << endl );
          set_error( CsError::FAILURE );
    }
3.
Ist das Attribut Teil des Modelltypen, läßt sich der Inference Handler durch reg_attr_change registrieren, um von Änderungen des Attributes zu erfahren. Scheitert die Registrierung, wird eine Fehlermeldung ausgegeben.

        // Register to receive changes in DeviceCRC

        if (!reg_attr_change( CsIRM2Hub::DeviceCRC ))
    {
       eout( "Couldn't register for changes in DeviceCRC." << endl);
       eout( "m_t_handle = " << hex << m_t_handle << dec << endl );
       set_error( CsError::FAILURE );
       return;
    }
    else
    {
       tout( "Registered for CsIRM2Hub::DeviceCRC change" << endl);
    }
Der Registrierungsmechanismus zeichnet die Inference Handler API gegenüber allen anderen SPECTRUM-Programmierschnittstellen aus:
Mit seiner Hilfe kann man ohne großen Programmieraufwand sicherstellen, daß während der gesamten Laufzeit des Inference Handlers (bzw. solange, bis man im Programmtext explizit die Registrierung aufhebt) Änderungen des überwachten Datenobjekts automatisch von der VNM [*] an den Inference Handler gemeldet werden.
Anders ausgedrückt, legt die Registrierungsmethode, die vom Inference Handler aufgerufen wird, fest, welche Änderungen innerhalb des Netzmodells der VNM die Ausführung des Inference Handlers veranlassen [SPEC IHC].

4.
Eng damit verbunden ist der Trigger-Mechanismus:
Hiermit kann vom Entwickler veranlaßt werden, daß eine vordefinierte Funktion bei einer bestimmten Konstellation (im hier behandelten Fall: bei der Änderung des Attributes DeviceCRC) getriggert wird.

Trigger-Funktionen müssen außerhalb des Constructors als eigenständige Methoden implementiert sein. Obwohl alle Trigger-Methoden bereits in CsIHBase als virtual definiert sind und mittels Vererbung auch dem Inference Handler zur Verfügung stehen, müssen sie vom Entwickler unbedingt neu definiert werden, da ihr Rumpf leer ist. Ihr Wesen entspricht daher dem rein virtueller (pure virtual) Methoden.

Die folgende Methode trig_attr_change wird vom Notification Manager der VNM angestoßen, falls das Attribut DeviceCRC sich ändert. Daraufhin werden der aktuelle und der vorherige Wert gelesen und anschließend ausgegeben. Dies geschieht durch direktes Abstützen auf die Funktionalität von CsChangeNode; im Change Node sind der aktuelle und der vorherige Wert eines Attributes zusammen mit der Attribute ID gespeichert.

void CsIHTest::trig_attr_change( const CsModelHandle& mh,
                  const CsChangeNode * change )
{
        tout("CsIHTest::trig_attr_change() mh=("<< hex << mh << dec <<
        ") activated." << endl );

        int errors = * (int *)(change->get_cur_value());
        int prev_errors = * (int *)(change->get_prev_value());

        // if DeviceCRC has not changed, do nothing

        if (errors != prev_errors)
                {
            switch( change->get_attr_id())
                        {
                        case CsIRM2Hub::DeviceCRC:
                                {
                                 iout("CsIHTest:trig_attr_change() 
                     mh=(" << hex << mh << dec << ") Errors changed
                     from "<< prev_errors << " to " << errors << endl);
                                 break;
                                }
                        default:
                                {
                                eout( "Model with mh=(" << hex << mh 
                                 << dec << ") is only registered for 
                                 DeviceCRC " << endl );
                                }
                        }
                }
        tout( "CsIHTest::trig_attr_change() ending."  << endl );
}
Damit ist die Implementierung des Kernstücks des Szenarios, der Inference Handler CsIHTest, abgeschlossen.
Abblauffähig ist er allerdings noch nicht, da CsIHTest noch nicht in den Modelltyp IRM2_TEST_MTYPE integriert ist.

5.
Um den Inference Handler instantiieren zu können, muß innerhalb des Model Intelligence Node, dessen Funktionsweise weiter unten erläutert wird, folgende Funktion definiert werden:

static void CsIRM2HubMI( CsMTypeHandle& m_t_handle )
{
    // Attach CsIHTest IH to IRM2Hub Model Type
    // and if unsuccessful, unattach CsIHTest IH.

    CsIHTest * test_ih = new CsIHTest( m_t_handle ) ;
    if ( test_ih->get_error() == CsError::FAILURE )
    {
        CsDelete( test_ih );
    }
}
Zu beachten ist, daß ein Inference Handler gelöscht werden muß, sobald ein Fehler bei seiner Integration in den Modelltyp auftritt. Das darf jedoch ausschließlich in der Funktion des MI-Nodes geschehen; ein Löschen des Inference Handlers an einer anderen Stelle (zum Beispiel in einer Trigger-Methode des Inference Handlers) führt zu einem Systemabsturz der VNM (coredump) und impliziert den Verlust der Datenbank.
Entsprechende Vorsichtsmaßnahmen (Sicherung der Datenbank, Anlegen einer Kopie des SpectroSERVER) sind daher unbedingt einzuhalten.

6.
Schließlich ist ein global definierter Model Intelligence Node (MI-Node) zu erzeugen, um den neuen Inference Handler in den existierenden Modelltyp zu integrieren. Im Beispiel lautet der neue Inference Handler CsIHTest, der Modelltyp IRM2_TEST_MTYPE.
Ein MI-Node dafür lautet:
static CsMINode mi_node ( IRM2_TEST_MTYPE, CsIRM2HubMI ) ;

Um Namenskonflikte zu vermeiden, sollte der MI-Node die Speicherklasse ,,static`` haben.

Erweiterung eines Modelltypen um neues prozedurales Wissenminode Abbildung 6.8 zeigt die technische Sichtweise d.h. die Rolle des MI-Nodes als Bindeglied zwischen dem neuen Inference Handler und dem Modelltyp sowie die Benutzersicht. Für den Benutzer erscheint das Einbringen des Inference Handlers transparent, er kann nicht feststellen, ob der Inference Handler bereits Bestandteil des Modelltyps war oder erst im nachhinein integriert wurde.

Ähnlich verhält es sich mit Modelltypen, die von dem erweiterten Modelltyp abgeleitet werden: Der neue Inference Handler erscheint nun als deren integraler Bestandteil.

7.
Zuletzt wird der Inference Handler compiliert und zusammen mit den Quelldateien für die VNM gelinkt, um eine neue Virtual Network Machine zu generieren.
Das Makefile [ORAM 91] ist zusammen mit anderen Konfigurationsdateien in Anhang A abgedruckt.

Dem Verständnis der in dieser Arbeit verwendeten C++-Ausgabebefehle dient die folgende Anmerkung:
Gerade in der Testphase eines Inference Handlers ist es sehr wichtig, über jeden Schritt informiert zu werden, der von dem Inference Handler vollzogen wird. Im obenstehenden (und insbesondere in dem in den Anhängen abgedruckten) Programmcode kommen daher Begriffe wie ,,iout``, ,,tout`` oder ,,eout`` vor; dies sind einfache Makros, die von Cabletron speziell zum Testen von Inference Handlern entwickelt wurden. Sie ersetzen den in C++ gebräuchlichen iostream-Befehl cout und können bedarfsspezifisch verwandt werden:

Zur Laufzeit des fertig compilierten und gebundenen Programms werden, entsprechend der auf der Kommandozeile angegebenen Optionen, die jeweiligen Ausgabeoperationen ausgeführt bzw. unterdrückt. Der Entwickler kann also eine Selektion der Ausgaben vornehmen, die mit cout nicht möglich wäre.
Zu beachten ist, daß dieser Ausgabemechanismus nur für selbst geschriebene Funktionen gilt und im Inference Handler mit define MY_DEBUG 1 das Debug-Flag gesetzt werden muß; Hoffnungen, durch Angabe entsprechender Optionen nachträglich Informationen über das ,,Innenleben`` der VNM zur Laufzeit zu erhalten, erfüllen sich nicht, da Cabletron diese Makros bei der Entwicklung der VNM nicht aktiviert hat.

Informationen zur Syntax der Makros, die leicht von der des cout-Befehls abweicht, sowie detaillierte Ausführungen zu den Debug-Makros findet man in Anhang B von [SPEC IHA] sowie in der Datei Spectrum/GLOBL/include/CsDebug.h.

Die folgende Abbildung 6.9 faßt die Schritte, die zur Instantiierung eines neuen Inference Handlers erforderlich sind, zusammen und skizziert die Interaktionen zwischen dem Inference Handler, dem Modell und dem Notification Manager innerhalb der Virtual Network Machine. Verhalten eines Inference Handlers zur Laufzeitruntime


next up previous contents
Next: Graphische Aufbereitung der Managementdaten Up: Programmierung mit den SPECTRUM Previous: Übersicht über die Level-II
Copyright Munich Network Management Team