Sprachunabhängige Verwaltung von atomaren Objekten des RelaX-Objektraums


Diplomarbeit, 1993

181 Seiten, Note: Sehr gut


Leseprobe


Inhaltsverzeichnis

Abbildungsverzeichnis

1. Einleitung
1.1. Verteilte Systeme
1.2. Fehlertoleranz
1.3. Objektkonzept
1.4. Systemarchitektur
1.5. Der RelaX Transactional Object Manager
1.6. Inhaltlicher Überblick

2. Entwurf des AOM
2.1. Einleitung
2.2. Anforderungen an den AOM
2.2.1. Funktionale Anforderungen
2.2.2. Nichtfunktionale Anforderungen
2.3. Die Basisschnittstelle des AOM
2.3.1. Virtual Segment Manager VSM
2.3.2. Generische Transaktionsunterstützung GTU
2.4. Grobentwurf
2.5. Atomare Segmente
2.6. Objektrepräsentation
2.6.1. Langobjekte
2.6.2. Cluster
2.6.3. Kurzobjekte
2.7. Aktive Objekte
2.7.1. Aktivieren eines Objektes
2.7.2. Passivieren eines Objektes
2.7.3. Erzeugen eines Objektes
2.7.4. Zerstören eines Objektes
2.8. Objektaufruf
2.9. Naming
2.10. Der aktive Objektraum

3. Implementierung
3.1. Implementierungsumgebung
3.2. Modulstruktur
3.3. Initialisierung
3.4. Repräsentierung der Detailstrukturen
3.5. Bereitstellung eindeutiger Identifikatoren
3.6. Beispiel
3.7. Testhilfen
3.8. Größe der Moduln

4. Vergleich mit anderen Konzepten
4.1. Extended C++
4.2. Avalon/C++
4.3. SOS
4.4. Amadeus
4.5. Der AOM im Vergleich

5. Zusammenfassung und Ausblick

6. Literaturverzeichnis

Abbildungsverzeichnis

Abb. 1: Schichten eines verteilten Systems

Abb. 2: Struktur eines allgemeinen verteilten Systems

Abb. 3: Zustandsdiagramm von Transaktionen

Abb. 4: Zwei-Phasen-Sperrprotokoll

Abb. 5: Hierarchie objektbasierter Sprachen

Abb. 6: Beispiele zur Einordnung objektorientierter Sprachen

Abb. 7: Speicheraufbau und Fluß der Objektversionen

Abb. 8: Architektur eines modernen verteilten Systems

Abb. 9: RelaX-Architektur

Abb. 10: Logische Struktur eines Ressource-Managers

Abb. 11: Zugriffs- und Commit Folge

Abb. 12: Struktur des RelaX Transactional Object Managers TOM

Abb. 13: Anforderungsmodell für den AOM

Abb. 14: Lebenszyklus eines Objektes

Abb. 15: Charakterisierung eines atomaren Objektes

Abb. 16: Referenzen auf atomare Objekte

Abb. 17: Adressierung im aktivem Speicher

Abb. 18: Avalon-Klassen für persistente Objekte

Abb. 19: Lebenszyklus eines persistenten Objektes

Abb. 20: Klassen von Schnittstellen des AOM

Abb. 21: Durchschnittliche Objektgröße

Abb. 22: AOM Grobstruktur

Abb. 23: Implementierungsarchitektur des AOM

Abb. 24: Allgemeines passives Objektformat

Abb. 25: Abstrakte Struktur eines Langobjekt-Headers

Abb. 26: Objektstatusfeld

Abb. 27: Cluster mit Listenstruktur

Abb. 28: Cluster mit Feldstruktur

Abb. 29: Cluster mit dynamischer Struktur

Abb. 30: Slots als lineare Liste

Abb. 31: Slots als Hash-Tabelle

Abb. 32: Slots als B-Baum

Abb. 33: Mögliche Strukturen eines Slots

Abb. 34: Grobstruktur des Cluster-Datenbereichs

Abb. 35: Aufbau eines Cluster-Header

Abb. 36. Clusterstatusfeld

Abb. 37: Clusterseiten im aktiven Speicher

Abb. 38: Clusterseiten im aktiven Speicher

Abb. 39: Adreßraum mit aktiven Clustern

Abb. 40: Struktur der Clusterebene

Abb. 41: Struktur aktiver Objekte

Abb. 42: Varianten der Objektreferenz

Abb. 43: Code Hash Eintrag

Abb. 44: Aufbau UID

Abb. 45: Adressierungspfad kurzer Objekte

Abb. 46: Verfeinerung des aktiven Objektraums

Abb. 47: Prototyp der Invoke-Funktion

Abb. 48: Die wichtigsten Moduln des AOM

Abb. 49: Repräsentierung des Objektstatusfeldes

Abb. 50: Implementierungsstruktur des Objektstatusfeldes

Abb. 51: Repräsentierung der Objektnamen

Abb. 52: Implementierungsstruktur des Objektstatusfeldes

Abb. 53: Implementierungsstruktur eines Langobjekt-Headers

Abb. 54: Implementierungsstruktur eines Cluster-Header

Abb. 55: Größen der PC++-Beispielklassen

Abb. 56: Repräsentierung des PC++-Beispiels

Abb. 57: Beispiel DCL-Datei

Abb. 58: Aktivierte PC++-Objekte

Abb. 59: Größe der Moduln

1. Einleitung

Die vorliegende Diplomarbeit wurde im Rahmen des Projekts RelaX (Reliable distributed applications support on UNIX) der Gesellschaft für Mathematik und Datenverarbeitung mbH (GMD) in Sankt Augustin angefertigt. Inhalt des Projekts ist die Entwicklung von Konzepten, Prototypen und Evaluationswerkzeugen, die die Erstellung verläßlicher, verteilter Applikationen erleichtern und beim Auftreten von Hardware- und Kommunikationsfehlern sowie bei bestimmten logischen Fehlern flexibel reagieren [KMSL90]. RelaX ist eine Weiterentwicklung des PROFEMO Projektes [NGJK85]. Als wesentliche Anwendungsgebiete von RelaX sind integrierte Informationssysteme in Bereichen wie CAD, Software Engineering, Bürosysteme und CIM anzusehen. Durch einen innovativen Ansatz werden Konzepte aus den Bereichen Betriebssysteme, Programmiersprachen und Datenbanken in RelaX vereint. Die Entwicklung neuer Anwendungen wird durch persistente Objekte unterstützt, die auf mehreren Stellen verteilt sein können und mittels Transaktionen bearbeitet werden, um gemeinsame Objektbenutzung und Fehlersituationen einfach und sicher handhaben zu können.

Im folgenden wird der Entwurf und die prototypische Implementierung des Active Object Managers AOM beschrieben, der sowohl den sprachunabhängigen Zugriff auf langlebige, synchronisierte und recoveryfähige Objekte implementiert und koordiniert als auch den Transfer von Objekten zwischen dem aktiven und dem permanenten Speicher verwaltet.

1.1. Verteilte Systeme

Die letzten Jahrzehnte lassen einen deutlichen Wandel der Mikroelektronik sichtbar werden, der sich sowohl in einem stetig fallenden Preis-Leistungsverhältnis als auch in einer veränderten Sicht von Rechensystemen manifestiert. Ständige Neuerungen in der Halbleiter- und Kommunikationstechnologie sowie veränderte Anwenderbedürfnisse führen nicht nur zu neuen Anwendungsbereichen, sondern auch zu neuen Forderungen an heutige und zukünftige Betriebssysteme [Mull89]. Die frühen Batch-Systeme sind Time-Sharing-Anlagen gewichen, die wiederum von den heute verwendeten Workstations und Personal Computern verdrängt werden.

Dezentralisierte Strukturen mit erhöhten Forderungen an die Wirtschaftlichkeit führen unter anderem zu Zielsetzungen wie erhöhter Parallelarbeit, gemeinsamer Benutzung von Ressourcen und verbesserter Verfügbarkeit. Nicht zuletzt dieses Anforderungsprofil hat zur Entwicklung von Netzwerkbetriebssystemen beigetragen, welche sich dadurch auszeichnen, daß Rechner mit lokalen Betriebssystemen, erweitert durch eine Netzwerkfunktionalität, durch ein geeignetes Kommunikationsmedium verbunden sind. Netzwerke fallen also in die Klasse der sogenannten lose gekoppelten Systeme, die keinen gemeinsamen Adreßraum besitzen und nur durch Nachrichtenaustausch kommunizieren. In der Regel ist es bei diesen Systemen so, daß der Benutzer eine Menge von Einzelrechnern sieht und daher zwischen lokalen Operationen, also solchen auf den eigenen Betriebsmitteln, und entfernten oder auch remote Operationen auf entfernten Betriebsmitteln unterscheiden kann oder sogar muß. Trotz der steigenden Popularität dieser Systeme erhöht sich die Komplexität der Programmerstellung unter anderem durch zusätzliche, aus der räumlichen Trennung resultierenden Fehlersituationen. Es können einzelne Rechner ausfallen, ohne daß dies einen Gesamtsystemausfall zur Folge haben muß, und es können bei der notwendigen Kommunikation Nachrichten verloren gehen.

Die beschriebene Charakterisierung führt schnell zu einer weiteren fundamentalen Forderung an Betriebssysteme: Transparenz. Allgemein versteht man unter dem Begriff der Transparenz die Fähigkeit oder Eigenschaft, die interne Beschaffenheit eines Gegenstandes oder einer Sache nach außen zu verbergen. Im Bereich der Rechensysteme werden verschiedene Formen der Transparenz unterschieden. Die Zugriffstransparenz ermöglicht mit identischen Operationen ganz allgemein den Zugriff sowohl auf lokale als auch auf entfernte Objekte. Durch die Ortstransparenz kann auf Objekte ohne Kenntnisse des Aufenthaltsortes zugegriffen werden. Die Eigenschaft der Transparenz ermöglicht es, dem Benutzer die Sicht eines einheitlichen, zentralen Systems zu vermitteln und damit das Vorhandensein einer Menge von vernetzten Rechnern zu verbergen.

Es stellt sich die Frage, welche Eigenschaften eine Menge vernetzter Rechner von einem verteilten System unterscheiden. Nach Tanenbaum [Tane90] zeichnet sich ein verteiltes Betriebssystem dadurch aus, daß der Benutzer eines solchen die Sicht eines einheitlichen konventionellen Systems hat, obwohl dieses auf mehreren unabhängigen Zentraleinheiten oder Rechnern läuft. Der Anwender sieht also ein virtuelles Uniprozessorsystem (siehe dazu auch Abbildung 2). Mullender [Mull89; SPG91] erweitert diese Definition und gibt eine Liste von Symptomen an, die für ein verteiltes System charakteristisch sind. Danach besteht ein verteiltes System aus bestimmten Komponenten mit definierenden Eigenschaften: Mehrere, unabhängige Prozessorelemente, im folgenden auch als Knoten oder Stellen bezeichnet, bilden ein Gesamtsystem. Eine Kommunikationseinrichtung verbindet die Knoten und ermöglicht damit den Austausch von Nachrichten und die Synchronisation zwischen parallel ablaufenden Prozessen. Das Gesamtsystem muß so konstruiert sein, daß der Ausfall einer einzelnen Komponente (Prozessor, Speicher etc.) nicht den Ausfall des ganzen Systems zur Folge hat1. Eng gekoppelte Systeme, also solche, die über einen gemeinsamen Speicher kommunizieren, bilden kein verteiltes System, da der Ausfall des Speichers zu einem Ausfall des Gesamtsystems führt. Weiterhin muß gesichert sein, daß die Stellen eines verteilten Systems unabhängig voneinander ausfallen können. Das bedeutet, daß der Ausfall einer Stelle nicht den Ausfall einer anderen Stelle induziert, sondern es vielmehr so ist, daß die überlebenden Stellen weiterarbeiten2.

Die logische Verteiltheit eines verteilten Systems äußert sich in der Aufteilung von Funktionen unter den Prozessen des Systems. Zum Erbringen dieser Funktionen benötigen Prozesse Kenntnisse über den Zustand des System oder zumindest über einen Teil davon.

Dieser Zustand eines verteilten Systems zu einer bestimmten Zeit ergibt sich aus den Zuständen all seiner Komponenten zu diesem Zeitpunkt, also den Zuständen der Prozesse und der Kommunikationskanäle. Es ist die Eigenart verteilter Systeme, daß es auf Dauer keine zwei Prozesse gibt, die zur gleichen Zeit die gleiche, zutreffende Sicht des Systems haben. Ein Prozeß innerhalb des Systems verfügt entweder über unvollständige, aktuelle oder über vollständige, überholte Zustandsinformationen. Diese Art eines Heisenbergschen Unschärfeprinzips für verteilte Systeme rührt daher, daß der Austausch von Nachrichten zwischen Prozessen eine nicht vernachlässigbare und oft nicht vorhersagbare Zeit benötigt.

Um einen anderen Prozeß des verteilten Systems über den eigenen momentanen Zustand zu informieren, muß ein Prozeß diese Zustandsinformation über einen Kommunikationskanal senden. Der informierte Prozeß empfängt die Information erst nach geraumer Zeit, wenn sich der Zustand des anderen Prozesses bereits wieder verändert haben kann. Zum wesentlichen Charakteristikum eines verteilten Systems kann man also die Ungewißheit erheben, der Entscheidungen von Prozessen aufgrund möglicherweise unzutreffender und voneinander abweichender Zustandsinformationen unterliegen [HeHo89]. Zur Durchsetzung der beschriebenen Eigenschaften ist eine verteilten Kontrolle notwendig, d.h. daß (bestimmte) Betriebssystemfunktionen durch Kooperation mehrerer Prozesse erbracht werden, von denen jeder aber nur einen Teil des für die Kontrolle notwendigen Gesamtzustandes kennt.

Insbesondere sind die auftretenden komplexen Fehlersituationen in einem verteilten System durch das System selbst zu behandeln, so daß dadurch die Vorteile solcher Systeme nutzbar gemacht werden, ohne dabei aber die Komplexität einer Anwendung zu erhöhen. Im allgemeinen lassen sich in einem verteilten System vier unterschiedliche Schichten identifizieren, wobei jede ihrerseits in mehrere Teilschichten aufgegliedert sein kann. Abbildung 1 verdeutlicht den Sachverhalt:

Abbildung in dieser Leseprobe nicht enthalten

Abb. 1: Schichten eines verteilten Systems

Das Anwendungssystem ist jene Software, mit der man bei der Lösung eines bestimmten Anwendungsproblems direkt in Kontakt kommt. Beim Programmieren einer Applikation entspricht z.B. der Editor und der Übersetzer dem Anwendungssystem. Verteilte Anwendungssysteme nennt man auch verteilte Applikationen.

Das Programmiersystem sorgt für die Verarbeitung und Ausführung der Anwendungsprogramme. Abstrakt gesehen wird dieses System durch die Programmiersprache charakterisiert, in der die Anwendungsprogramme erstellt sind. Konkret manifestiert es sich durch die vom Übersetzer und Laufzeitsystem dieser Sprache (oder Interpreter) bereitgestellten Mechanismen.

Dem Programmiersystem liegt auf jedem Rechner ein Betriebssystem zugrunde, daß für die Ausführung der Prozesse sorgt und im allgemeinen auch die rechnerinterne Kommunikation unter Prozessen regelt.

Das Kommunikationssystem schließlich ist für den rechnerübergreifenden Austausch von Nachrichten verantwortlich.

Man kann alle Schichten zusammengefaßt als ein verteiltes System betrachten. Wie die Verteiltheit auf den verschiedenen Ebenen eines Systems durchgesetzt ist, wird durch die oben aufgeführten Symptome aber nicht definiert. So ist es in der Regel üblich, daß für das Kommunikationssystem die Charakterisierung eines verteilten Systems nicht anwendbar ist, da hier die einzelnen Stellen sichtbar sind und der Ausfall einer Komponente erkannt werden kann bzw. muß. Eigentlich bildet aber bereits jede einzelne Schicht für sich ein verteiltes System, in dem Prozesse dieser Schicht auf einem Rechner mit denen der gleichen Schicht auf einem anderen Rechner anhand eines gemeinsamen Protokolls zusammenarbeiten, was in Abbildung 1 durch die horizontalen Pfeile ausgedrückt werden soll.

Ein Netzwerkbetriebssystem kann als ein mehr oder weniger reiner Datenverbund angesehen werden, während die Kooperation der Stellen zur Erbringung einer Dienstleistung, also eines sogenannten Funktionsverbundes, als eines der hauptsächlichen Ziele von verteilten Systeme anzusehen ist. Eine weitere wichtige Zielsetzung besteht darin, daß die Vorteile verteilter Systeme bereitgestellt werden, ohne jedoch die Komplexität der Applikationen zu erhöhen. Die Transparenzeigenschaft verteilter Systeme verbirgt dabei die gestiegene Komplexität des Systems nach außen und bietet dem Benutzer eine Schnittstelle, die vom Vorhandensein mehrerer vernetzter Rechner abstrahiert [Schu92]. Abbildung 2 veranschaulicht die Struktur eines allgemeinen verteilten Systems.

Abbildung in dieser Leseprobe nicht enthalten

Abb. 2: Struktur eines allgemeinen verteilten Systems

1.2. Fehlertoleranz

Neben der erwähnten Transparenz wird in verteilten Systemen vor allem auch die Möglichkeit der gemeinsamen und eventuell auch der parallelen Benutzung von Daten als wesentlicher Vorteil empfunden. Diese Fähigkeiten werfen aber auch Probleme auf: es gilt zum einen, die Zugriffe auf gemeinsam benutzbare Daten von nebenläufigen Prozessen zu synchronisieren, und zum anderen muß in einem Fehlerfall die Konsistenz der durch den (oder die) Fehler betroffenen Daten gewährleistet bleiben. Dies entspricht den oben beschriebenen Symptomen und wird allgemein als ein Aspekt der Fehlertoleranz bezeichnet. Man kann dies auch als Fehlertransparenz definieren und meint damit das Verbergen von Fehlern und die Beendigung von Anwendungen trotz des Ausfalls oder des Fehlverhaltens von Soft- bzw. Hardwarekomponenten.

Historisch gesehen lag das Hauptaugenmerk auf der Klasse der Hardwarefehler, hier vor allem in der Fehlertoleranz einzelner Komponenten. Diese Sicht hat sich gewandelt, da heute Systemmodelle zur gleichartigen Behandlung von Soft- und Hardwarefehlern Ziel der Forschung sind. Insbesondere ist das Design der Kontrolltechniken einem Zielkonflikt zwischen erhöhter Leistung und erhöhtem Nutzungsgrad der vorhandenen Ressourcen auf der einen Seite sowie einer erhöhten Zuverlässigkeit und Verfügbarkeit auf der anderen Seite unterworfen. Ein prominentes frühes Beispiel eines fehlertoleranten Systems ist das Tandem NonStop System mit dem Guardian/Expand Betriebssystem; siehe dazu auch [Tane90; Mull89].

Die gemeinsam benutzbaren Daten spiegeln in einem verteilten System den Zustand der Anwendungen wider. Auf diesen Daten sind zwei Arten von anwendungsspezifischen Konsistenzbedingungen definiert, die für Applikationen im allgemeinen als kritisch angesehen werden und daher auf jeden Fall einzuhalten sind. Die eine Art dieser Bedingungen basiert auf dem Umstand, daß die betrachteten Daten in einer Relation zueinander stehen. Ein Lagerverwaltungsprogramm ist ein typisches Beispiel, bei welchem die Konsistenzbedingung z.B. darin besteht, daß die Läger ausgeglichen sind, d.h. die Summe der Abgänge überschreitet nie die Summe aus aktuellem Bestand und allen Zugängen. Ein korrektes Programm muß also einen vorgefundenen konsistenten Systemzustand in einen neuen, ebenfalls konsistenten Zustand überführen, obwohl solche Bedingungen üblicherweise nicht explizit durch den Programmierer angegeben werden. Dabei ist zu berücksichtigen, daß eine Berechnung oft aus einer Abfolge von Operationen besteht, die die Konsistenz des Systemzustand während des Ablaufs der Berechnung möglicherweise verletzen. Es wird im folgenden angenommen, daß der Programmierer dafür Rechnung trägt, daß eine erfolgreich beendete Berechnung bezüglich den Konsistenzbedingungen, die die Relation der Daten betreffen, konsistenzerhaltend und damit korrekt ist. Die Einhaltung der anderen Art der Konsistenzbedingungen sichert zu, daß die Daten auch die beabsichtigte Wirkung von korrekten Berechnungen darstellen. Der Unterschied zur erstgenannten Konsistenzbedingung wird deutlich, wenn man eine Berechnung betrachtet, die mehrere Mengen von Operationen enthält, die jede für sich betrachtet die Konsistenz der Daten erhält. Wird jedoch nur ein Teil dieser Operationen ausgeführt, so erfüllen die Daten zwar die mit ihnen verbundenen Konsistenzbedingungen, sind aber in einem Zustand, der nicht die gewünschte Wirkung der gesamten Berechnung widerspiegelt. Die Konsistenz kann also allgemein als ein Maß der Fähigkeit aufgefaßt werden, mit der ein System während Berechnungen die Einhaltung des zugrundeliegenden Datenmodells durchsetzt. Ein Datenmodell modelliert hierbei im weitesten Sinne genau die Menge der Zustände, die das System auf Grund von Berechnungen einnehmen darf [OMG90].

Um ein System als fehlertolerant einstufen zu können bzw. um auf höheren Ebenen durch geeignete Algorithmen die Eigenschaft der Fehlertoleranz zu erreichen, ist zunächst eine feinere Charakterisierung der zugrundeliegenden Hardware nötig. Dabei ist insbesondere zu unterscheiden, ob ein Fehler seitens des Systems eine Fehlfunktion, d.h. eine zeitlich beschränkte Unterbrechung oder ein Breakdown, d.h. eine definitive Unterbrechung hervorruft. Die folgenden Begriffe kennzeichnen die Eigenschaften von Hardware bzgl. möglichen Fehlern:

- Remanenz: Auftretende Fehlfunktionen des Rechners werden innerhalb einer tole- rierbaren Zeit beseitigt, und es kommt dabei zu keinem Fehlverhalten des Gesamt- systems.
- Integrität: Die Ausgaben eines Rechners sind immer korrekt, ein Fehlverhalten führt jedoch zu einem Stop des Rechners (Fail-Stop Verhalten).
- Sicherheit: Kein Zustand des Rechners führt zu einem schwerwiegenden Schaden des Gesamtsystems (Fail-Safe Verhalten).

Zur Erzielung der Fehlertoleranz wird die Bereitstellung und Ausnutzung von Redundanz als ein grundsätzlich notwendiger Mechanismus betrachtet [Mull89; Gosc91; Tane90]. Unter dem Begriff der Redundanz wird das Vorhandensein von mehr als für die Ausführung der vorgesehenen Aufgaben an sich notwendigen Mittel verstanden [Görk89]. Die Anwendung von Redundanz führt dazu, daß eine Betrachtungseinheit ihre vorgesehene Aufgabe auch bei einer begrenzten Anzahl von Ausfällen weiterhin ausführen kann. Betrachtungseinheiten, die diese Eigenschaften besitzen, heißen fehlertolerant. Die funktionsbeteiligte (aktive, hei ß e) Redundanz ist eine Untergliederung der Redundanz, bei der zusätzliche Einheiten nicht nur ständig in Betrieb, sondern auch an der Ausführung der vorgesehenen Aufgabe beteiligt sind [Görk89]. Dabei geht man in der Regel von der Vervielfachung von Hardwarekomponenten aus, so daß im Falle normaler Systemtätigkeit (wenn also kein Fehler vorliegt), durch Parallelarbeit ein höherer Durchsatz erreicht werden kann. So werden z.B. häufig Spiegelplatten zur Realisierung von stabilen Speichern herangezogen. Bei der nicht funktionsbeteiligten (passiven) Redundanz sind zusätzliche Einheiten zwar eingeschaltet, werden aber erst bei einer Störung oder einem Ausfall an der Ausführung der vorgesehenen Aufgabe beteiligt. Eine mögliche Variante, um ein gültiges Resultat zu erhalten, ist die Fähigkeit der Einheiten zum Voting. Dabei wird dasjenige Resultat verwendet, welches von der Mehrheit der Einheiten geliefert wurde. In diesem Fall wird also eine Fehlermaskierung durch die Fähigkeit der Einheiten zum Voting erreicht. Dieses Verfahren fällt in die Klasse der NMR (N-fach modulare Redundanz) Verfahren. Denkbar sind aber auch dynamische Strategien, wie z.B. das Recoveryblockverfahren [Rand75]. Auf der Softwareebene wird die Strategie der NMR Verfahren in der sogenannten N-Versionen Programmierung (auch Multiversions-Software) angewandt. Eine Software-Fehlertoleranz ist durch Fehlermaskierungen zu erreichen, indem N³3 funktional äquivalente Programme (Versionen), die derselben Spezifikation genügen, mit verschiedenen Algorithmen in unterschiedlichen Programmiersprachen implementiert werden. In kritischen Anwendungsbereichen, z.B. in der Raumfahrt, können durch den Einsatz solch einer Software Fehlfunktionen eines Systems auf Grund von Entwurfsfehlern stark reduziert werden.

Die Konsistenz des Systemzustandes wird im allgemeinen durch das nicht vermeidbare Auftreten von Fehlern verletzt, die damit letztlich die Ursache für Inkonsistenzen der Daten eines verteilten Systems sind. Dieses Inkonsistenzen können dazu führen, daß sich das System nicht mehr gemäß seiner Spezifikation bzw. seines Datenmodells verhält und damit evtl. neue Fehler produziert, was insgesamt ein Systemversagen hervorrufen kann. Weiterhin kann die Konsistenz der (globalen) Daten durch lediglich partiell ausgeführte Berechnungen und durch den Verlust von Ergebnissen aus schon beendeten Berechnungen verletzt werden. Diese Inkonsistenzen zu vermeiden ist ein wesentliches Ziel eines fehlertoleranten Systems. Aus der Verteiltheit resultieren vielfältige, im Vergleich zu zentralen Systemen zusätzliche Probleme, wodurch die Komplexität der Programmierung verteilter Berechnungen erheblich steigt. Unter anderem erhöht sich die Komplexität einer verteilten Anwendung dadurch, daß durch den Ausfall einzelner Systemkomponenten und dem gleichzeitigen Vorhandensein anderer, funktionierender Einheiten, neue und komplexere Fehlersituationen entstehen können. So ist z.B. auch der Fall zu betrachten, daß das Kommunikationsmedium unzuverlässig ist, so daß Nachrichten verloren gehen, dupliziert oder verstümmelt werden können. Die gestiegene Komplexität der Programmierung ruft außerdem neue Fehler hervor.

Eine spezielle Behandlung aller möglichen Fehler in diesem Umfeld würde zu einem nicht zu akzeptierenden Aufwand führen, und zwar weder für den Benutzer noch für den Entwickler verteilter Applikationen. Zudem werden höhere Erwartungen an verteilte Programme gestellt: Die Datensicherheit, d.h. die jederzeit korrekte Berechnung und Speicherung von Daten, die Verläßlichkeit, d.h. die Vertrauenswürdigkeit in bereitgestellte Dienstleistungen und die Transparenz der Mechanismen zur Erbringung der Fehlertoleranz, sollen gesteigert und jederzeit verfügbar sein.

Die aus dem Datenbankbereich stammenden Transaktionen haben sich als ein Schlüsselkonzept bei der Entwicklung verteilter fehlertoleranter Anwendungen erwiesen, insbesondere in Umgebungen, wo ein nebenläufiger Zugriff auf gemeinsam benutzbare und veränderbare Daten gefordert ist, da diese die Konsistenz der Daten trotz des Auftretens von Fehlern zusichern [KMSL90; Mull89; SPG91]. Ohne besondere Vorkehrungen kann insbesondere der nebenläufige Zugriff auf gemeinsame Daten zu weiteren fehlerhaften System- zuständen führen, die möglicherweise Inkonsistenzen der Daten zur Folge haben. Dabei ist zu beachten, daß die Konsistenz der Daten durch Fehler verletzt werden kann, die Aus- wirkungen auf noch aktive oder aber auf schon erfolgreich beendete Berechnungen haben können. Zur Lösung dieser Probleme wurden in PROFEMO und RelaX Konzepte entwickelt, die im wesentlichen auf geschachtelten und verteilten Transaktionen aufbauen und allgemeine Verfahren zur Fehlerbehandlung und Sicherung von konsistenten Systemzuständen darstellen [NGJK85; KMSL90]. Die einfache Handhabung der angesprochenen Probleme sowohl für den Programmierer als auch für den Benutzer verteilter Systeme, ist eine der Zielsetzungen von RelaX. Die Realisierung solcher Konzepte führt zu einem System, welches einen fehlerhaften (System-) Zustand entdeckt und diesen in einen früheren, schon einmal erreichten, konsistenten Zustand überführt (backward error recovery) [KMSL90]3. Ein mit solchen Eigenschaften ausgestattetes System gehört in dem oben beschriebenen Sinne zu der Klasse der fehlertoleranten Systeme.

Ein Ziel bezüglich nebenläufiger Aktionen auf gemeinsam benutzbaren Objekten ist es, die Konsistenz des Systemzustands durch atomare Aktionen zu sichern. Solche Aktionen, Transaktionen genannt, fassen eine Menge von logisch zusammengehörigen Operationsausführungen auf Objekten zu einer Einheit zusammen. Eine Transaktion wird allgemein durch die folgenden Eigenschaften charakterisiert, die in der Literatur auch als ACID-Eigenschaften bekannt sind [Mull89; Gray78; Blac90]:

- Entweder wird eine Transaktion vollständig oder gar nicht ausgeführt. Dieses Verhalten wird auch als Atomarit ä t im Fehlerfall (Atomicity) bezeichnet. Wird eine Transaktion abgebrochen (durch den Benutzer oder vom System), werden alle durch die ausgeführten Operationen resultierenden Modifikationen zurückgenommen.

- Sind mehrere Transaktionen nebenläufig auszuführen, so ist dies zulässig, solange deren Wirkung bezüglich veränderter Daten so ist, als würden die Transaktionen in einer seriellen Reihenfolge mit gleicher Wirkung durchgeführt werden. Diese Eigenschaft von Transaktionen wird auch als Serialisierbarkeit bezeichnet. Für den Anwender ergibt sich dadurch eine Synchronisationseigenschaft, da inkonsistente Zwischenzustände von außen nicht sichtbar sind. Die Sicherung der Atomarit ä t der Wirkung ist Aufgabe einer dedizierten Komponente des Systems, welche man ´concurrency control´ nennt. Eine zulässige Ausführung einer Menge von Transaktionen überführt also einen konsistenten Systemzustand in einen anderen konsistenten Systemzustand (Consistency). Die dieser Aussage zugrundeliegende Annahme ist die, daß Berechnungen innerhalb einer Transaktion immer nur zulässige Zustände bzgl. des verwendeten Datenmodells hervorrufen, also die Konsistenz bewahren (siehe Seite 7).

- Zwischenzustände von Transaktionen sind außerhalb der Transaktion nicht sichtbar, auch wenn die Transaktionen nebenläufig ausgeführt werden können (Isolation).

- Ist die Transaktion erfolgreich beendet worden, ist deren Wirkung unwiderruflich. Im Rahmen des angenommenen Fehlermodells wird zugesichert, daß die berechneten Ergebnisse erhalten bleiben. Dies wird auch als Permanenz der Wirkung (Durability) bezeichnet.

Eine Transaktion, die Operationen auf Objekten ausführt, die im System verteilt sind und sich dadurch auf mehrere Stellen ausbreitet, wird auch verteilte Transaktion genannt. Dabei kann eine Transaktion zu einem Zeitpunkt eine Menge von inneren Transaktionen besitzen und dadurch einen Transaktionsbaum aufspannen. Diese werden auch als Sub- bzw.

Sohn-Transaktionen bezeichnet und können selber nebenläufig ausgeführt werden. Geschachtelte Transaktionen ermöglichen eine erhöhte parallele Ausführung von Programmen (bzw. von Programmteilen), die Konstruktion von wiederverwendbaren Programmbausteinen und unabhängige Transaktionsabbrüche.

Eine Transaktion durchläuft in ihrem Leben mehrere Zustände. Der Anfangszustand einer Transaktion ist active, und solange sich die Transaktion in diesem Zustand befindet, können noch Operationen auf Objekten ausgeführt werden. Schlägt eine Transaktion fehl, so hinterläßt sie keine Wirkung auf den durch die Transaktion involvierten Objekten und geht in den Zustand aborted über. Der Zustand completed ist ein im RelaX-System zusätzlicher zugelassener Zwischenzustand, der besagt, daß sämtliche Operationen der Transaktion abgeschlossen sind, die Wirkung der Transaktion zu diesem Zeitpunkt aber noch nicht sicher abgespeichert, ein Übergang in den Zustand aborted jedoch noch möglich ist.

Sind alle durch die Transaktion bewirkten Zustandsänderungen sicher abgespeichert, so nimmt die Transaktion den Zustand committed an [KMSL90; NGJK85]. Abbildung 3 veranschaulicht die Phasen einer Transaktion mit den jeweils möglichen Zustandsübergängen:

Abbildung in dieser Leseprobe nicht enthalten

Abb. 3: Zustandsdiagramm von Transaktionen

Das Zwei-Phasen-Sperrprotokoll ist ein möglicher Mechanismus, mit dem der Zugriff von Transaktionen auf Ressourcen synchronisiert werden kann. Auf Ressourcen kann dabei nur zugegriffen werden, wenn für sie eine Sperre (lock) erworben wurde. Für die Art und die möglichen Zeitpunkte des Erwerbs von Sperren sind mehrere Varianten denkbar. Hier soll mit dem Zwei-Phasen Locking ein oft eingesetztes Protokoll diskutiert werden, dessen Ablauf in Abbildung 4 dargestellt ist.

Abbildung in dieser Leseprobe nicht enthalten

Abb. 4: Zwei-Phasen-Sperrprotokoll

In der ersten Phase sind für alle Ressourcen, die innerhalb einer Transaktion bearbeitet werden, Locks anzufordern. Beim strikten Zwei-Phasen Locking, der üblichen Variante des Protokolls, behält die Transaktion diese Locks bis zu ihrem Ende, wenn sie in den Zustand committed übergeht. Bei der nicht-strikten Variante, die im RelaX-System Verwendung findet, kann der Lockpunkt der Transaktion implizit oder explizit nach dem Anfordern aller Locks gesetzt werden. Dadurch ist die erste Phase des Protokolls beendet und die zweite Phase eingeleitet. Dies hat zur Folge, daß ab diesem Zeitpunkt für die aktuelle Transaktion keine weiteren Sperren mehr angefordert werden können. Die Freigabe der gehaltenen Locks kann im Verlauf der zweiten Phase erfolgen, falls im weiteren auf die dazugehörigen Ressourcen nicht mehr zugegriffen wird. Für diese Ressourcen können dann von anderen Transaktionen Sperren angefordert werden. Da die zugehörigen Daten aber unter Umständen noch nicht gesichert sind und die Transaktion, die die Modifikationen verursachte, noch nicht in den Zustand committed überging, macht man sich von den ungesicherten Daten bzw. von der entsprechenden Transaktion abhängig.

Wenn eine Transaktion abbricht, d.h. den Zustand aborted einnimmt, sind alle abhängigen Transaktionen ebenfalls abzubrechen, da auf die Daten, auf die zugegriffen wurde, durch den Abbruch invalidiert sind und ohne weiteres Wissen nur durch diese Art der Beendigung die Atomarität im Fehlerfall gewährleistet ist. Dies ist die übliche Vorgehensweise im RelaX-System. Eine Applikations-spezifische Behandlung, die nicht automatisch zum Abbruch führt, ist jedoch denkbar und möglicherweise wünschenswert. Ebenso muß bei der Überführung einer Transaktion in den Endzustand committed gewährleistet sein, daß sich alle modifizierten Daten in einem gesicherten Zustand befinden. Dies kann erreicht werden, indem man eine Transaktion erst dann in den Zustand committed überführt, wenn alle anderen Transaktionen, von denen sie abhängig ist, ebenfalls den Zustand committed erreicht haben oder dadurch, daß alle Transaktionen gemeinsam in den Zustand committed überführt werden.

Unter Verwendung des strikten Zwei-Phasen-Sperrprotokolls, bei dem die Sperren bis zu dem Zeitpunkt gehalten werden, wo die Transaktion in den Zustand committed übergeht, ist die Isolation der Transaktionen erfüllt, d.h. die eben geschilderten Abhängigkeiten können nicht auftreten.

Durch die Verwendung von Transaktionen als Hilfsmittel zur Strukturierung von Applikationen, kann vermieden werden, daß in jeder Anwendung von neuem die besprochenen Konsistenzbedingungen explizit kontrolliert und behandelt werden müssen. Dies soll vielmehr eine Aufgabe des Systems sein und entspricht damit der in Kapitel 1.1 angegebenen Zielsetzung verteilter Systeme, eine erhöhte Funktionalität bereitzustellen, ohne dabei aber die Komplexität der Anwendungen zu erhöhen.

Im RelaX-System wird ein allgemeines Verfahren zur Fehlerbehebung und Sicherung von konsistenten Systemzuständen bereitgestellt, welches nicht auf der Annahme isolierter Transaktionen basiert, sondern Mengen abhängiger Transaktionen betrachtet. Dadurch ist es im Gegensatz zu herkömmlichen transaktionsverarbeitenden Systemen möglich, die Serialisierbarkeit von Transaktionen durchzusetzen, ohne dabei aber die starre Forderung nach der Isolierung von Transaktionen bei der Fehlerbehebung und bei der Sicherung von Daten beibehalten zu müssen. Daher ist eine Synchronisation möglich, die neben der optional möglichen Isolation von Transaktionen auch nur die notwendigste Einschränkung vornehmen kann, um die Datenkonsistenz sicherzustellen.

1.3. Objektkonzept

Das objektorientierte Paradigma wird allgemein als ein Schlüsselkonzept für die Entwicklung bzw. den Betrieb von verteilten Betriebssystemen und Applikationen angesehen, da die zugrundeliegenden Konzepte wie Daten-Abstraktion und -Kapselung, Information Hiding, Polymorphie und Vererbung zu den allgemein anerkannten Vorteilen wie höherer Wiederverwendbarkeit, Erweiterbarkeit und Rapid Prototyping führen [Stro86; Espr87; Espr90]. Ausgehend von Programmiersprachen wie Simula [Stro86] und Smalltalk [GoRo83], werden objektorientierte Prinzipien heute auch in Bereichen wie Daten- banken und Betriebssystemen gefunden [CaDe86; BlZd87; ZSR86]. Dieses Paradigma findet sich sowohl in kommerziellen Systemen wie z.B. Clam [CaCo87; PeSt87] als auch in Forschungssystemen wie z.B. PROFEMO [NGJK85], COMANDOS [Espr90] und Avalon [WiHe87]. Auf Systeme der jüngeren Generation wird in Kapitel 4 noch näher eingegangen.

Die folgende Abbildung kann als eine Vererbungshierarchie angesehen werden, wobei unter Verwendung von objektorientierten Techniken objektbasierte Sprachen klassifiziert werden:

Abbildung in dieser Leseprobe nicht enthalten

Abb. 5: Hierarchie objektbasierter Sprachen

Der objektorientierte Ansatz baut auf bewährten Prinzipien der Softwaretechnik, nämlich prozedurale Abstraktion, Modularisierung und Datenkapselung auf, die unter dem Begriff der Objektbasiertheit zusammengefaßt werden können. Eine klassen-basierte Sprache ist objektbasiert und zeichnet sich zusätzlich dadurch aus, daß jedes Objekt zu einer Klasse gehören muß. Wird aber zusätzlich die Möglichkeit geboten, Gemeinsamkeiten ähnlicher Datentypen mittels des Konzeptes der Vererbung sichtbar zu machen und inkrementell Klassenhierarchien zu definieren, spricht man von Objektorientiertheit [Stro86; OMG90; Byte89].

Beim objektorientierten Modell wird die Funktionalität auf Objekte aufgeteilt. Der Schwerpunkt der Modellbildung ist nicht mehr die funktionale Zerlegung, sondern der Entwurf von eigenständigen Objekten, die Daten und Funktionen enthalten. Sowohl objektbasierte als auch objektorientierte Systeme zeichnen sich also dadurch aus, daß die Möglichkeit besteht, typisierte Einheiten, die Objekte genannt werden, aus einer abstrakten Spezifikation, der Typdefinition, zu erzeugen. Dieser Vorgang wird Instanziierung genannt. Ein Objekt ist also eine Inkarnation eines abstrakten Datentyps, bestehend aus einer Menge von Daten, auch Attribute genannt, und aus einer Anzahl von erlaubten Operationen, den Methoden, auf diesen Daten. Diese Operationen werden deshalb auch als typspezifisch bezeichnet. Ein Objekt kann daher auch als Informationsträger mit zeitlich veränderbarem Zustand bezeichnet werden, dessen Zustand durch den Wert seiner Attribute bestimmt wird. Methoden sind die einzige korrekte Möglichkeit, Daten des Objekts zu modifizieren bzw. zu bearbeiten. Das Verhalten eines Objektes ist durch die Typdefinition eindeutig festgelegt. Allgemein gesprochen und ohne auf eine bestimmte Sprache Bezug zu nehmen, interagiert ein Objekt mit seiner Umgebung, indem es Nachrichten sendet und empfängt. Eine Nachricht enthält dabei genug Informationen, z.B. Parameter, so daß ein Objekt geeignet reagieren kann. In der Regel wird durch das Senden einer Nachricht der Aufruf einer entsprechenden Methode und damit die Ausführung des entsprechenden Codes veranlaßt. Die Benutzung des Begriffs der Nachricht macht die lose Kopplung zwischen einem Objekt und dessen Benutzer deutlich.

Insbesondere wird die Frage offen gelassen, wie die Nachricht tatsächlich realisiert wird: Unterprogrammaufruf, System-Trap oder IPC.

In Sprachen, die das Konzept der Vererbung unterstützen, muß noch zwischen den Begriffen Typ und Klasse unterschieden werden. Eine Klasse stellt dabei die kleinste Einheit der Wiederverwendbarkeit dar. Ein Typ kann sich aus verschiedenen Klassen zusammen- setzen. Verschiedene Objekte können bzgl. verschiedener Typen erzeugt worden sein, dabei aber gleichzeitig derselben Klasse angehören. In diesem Fall können für die Objekte der verschiedenen Typen die Methoden der gemeinsamen Klasse ausgeführt werden.

Die Art und Weise, wie Objekte definiert werden, induziert unter anderem deren Wiederverwendbarkeit. Wird ein Objekt definiert, ist es üblich, daß Attribute und Verhalten von anderen, existierenden Objekten übernommen werden können. Dies spiegelt sich in den folgenden zwei orthogonalen Aspekten wieder:

1. Erwerben des Verhaltens

In der Literatur werden dazu die beiden Ansätze Vererbung und Delegierung angegeben. Bei der Vererbung, so wie dies in konventionellen objektorientierten Sprachen definiert ist (C++, Smalltalk), kann für ein Objekt ein neues Verhalten dadurch definiert werden, daß das Verhalten eines bestehenden Objektes durch Hinzunahme, Überlagerung oder Neudefinition von Attributen bzw. Methoden, geeignet verändert wird. Die genaue Vorgehensweise wird durch die Semantik der Sprache vorgegeben. Die Methoden arbeiten immer auf einem eindeutig durch das Programm bestimmten Objekt, welches als Instanziierung des zugehörigen Typs zu betrachten ist. Vererbung ist als ein statischer Ansatz anzusehen, der zur Übersetzungszeit angewendet wird. Dabei ist zwischen einfacher und mehrfacher Vererbung zu unterscheiden.

Bei der Variante, welche die Form der Delegierung benutzt, wird eine Nachricht, falls sie von einem Objekt nicht verarbeitet werden kann, an ein anderes Objekt delegiert. Jedes Objekt bestimmt dabei ein Delegierungs-Objekt. Bei diesem dynamischen Ansatz entsteht also eine Delegierungskette, die sich zur Laufzeit ändern kann.

2. Erwerben der Objektstruktur

Die Struktur von Objekten kann durch Typen oder Prototypen festgelegt werden. In Systemen, in denen Typen als Hilfsmittel zur Strukturierung dienen, sind diese als Objektvorlagen zu verstehen, durch welche Objekte erzeugt werden können. Ein Typ kann dabei selbst als ein Objekt betrachtet werden, welches instanziiert wird, um dadurch neue Objekte mit gleicher Struktur zu erzeugen. Diese werden dann als Instanzen des Typs bezeichnet. Weiterhin ist es so, daß ein Typ den Code für alle von ihm erzeugten Objekte bereitstellt. Dieser Ansatz zeichnet sich also dadurch aus, daß alle Objekte die gleiche Struktur aufweisen und den gleichen (Typ-) Code benutzen.

In Prototyp-Systemen kann jedes Objekt eine eigene, spezialisierte Struktur besitzen, so daß für ein gegebenes Objekt wenige Annahmen über den Aufbau getroffen werden können.

Abbildung 6 zeigt anhand einiger Beispiele von existierenden Sprachen die prinzipiellen Möglichkeiten zur Kombination beider Eigenschaften.

Abbildung in dieser Leseprobe nicht enthalten

Abb. 6: Beispiele zur Einordnung objektorientierter Sprachen

Die meisten traditionellen objektorientierten Sprachen sind Typ-basiert und unterstützen das Konzept der Vererbung. In diesen Systemen besitzt ein Objekt sowohl eine feste Struktur als auch ein vorgegebenes Verhalten, wobei beide Eigenschaften durch den Typ bestimmt sind, der das Objekt erzeugt. Delegierung wird selten und wenn, meistens in den Sprachen, die eine Form des Parallelismus unterstützen, angewandt. Nach [SoGu89] bietet die Methode der Vererbung einen deutlichen Vorteil gegenüber der Delegierung, da bei dieser Variante erheblich weniger Nachrichten zwischen den Objekten ausgetauscht werden müssen. Weiterhin bieten Typ-basierte Systeme in den meisten Situationen eine beträchtliche Platzersparnis gegenüber den Prototyp-basierten Systemen. Aus diesem Grund wird im folgenden nur noch von Typ-basierten Systemen ausgegangen.

Für Objekte als Gedächtnisträger ergeben sich zwei wichtige Aufgabenbereiche: So sind zum einen Möglichkeiten zur gemeinsamen Benutzung von Objekten zu schaffen und zum anderen sind diese im Rahmen des Fehlermodells abzuspeichern.

Die gemeinsame Benutzung von Objekten durch mehrere Prozesse ist notwendig, damit diese Prozesse Informationen austauschen können. Wollen mehrere Prozesse auf ein und dasselbe Objekt gleichzeitig zugreifen, entstehen zwischen den beteiligten Prozessen (indirekte) Abhängigkeiten. Zur geregelten Behandlung dieser Abhängigkeiten sind geeignete Strategien zur parallelen Benutzung von Objekten zu entwerfen. Dabei ist sicherzustellen, daß mehrere Prozesse, die sich um ein Objekt bewerben, dieses nacheinander benutzen, so daß zu jedem Zeitpunkt höchstens ein Prozeß das betroffene Objekt bearbeitet. Die entsprechenden Prozesse sind dann wechselseitig ausgeschlossen. Die dazu notwendigen Synchronisationsverfahren serialisieren also den parallelen Zugriff auf gemeinsam benutzbare Objekte durch mehrere Prozesse. Dabei soll die erreichbare Nebenläufigkeit so wenig wie möglich eingeschränkt werden. Dieser klassische Problembereich ist auch aus dem Bereich der Betriebssysteme bekannt [Tane90; SPG91]. Die dort entwickelten Methoden zur Synchronisation von Prozessen sind auch auf das Objektkonzept anwendbar. So könnte man z.B. pro Objekt ein Semaphor [SPG91] vorsehen, und mit Hilfe der p- und v-Operation jede Methode als kritischen Abschnitt modellieren. Ein auf höherem semantischen Niveau angesiedeltes Konzept stellen die von Hoare eingeführten Monitore [MOO87; SPG91] dar, welche dazu dienen, eingeschränkt parallel benutzbare Objekte zu konstruieren, so daß bei ihrer Benutzung Synchronisationsbedingungen eingehalten werden. Monitore sind in erster Linie geeignet zur Konstruktion von Objekten, für die alle Methoden wechselseitig ausgeschlossen auszuführen sind. Die beschriebenen Mechanismen können mehr oder weniger transparent auf der Sprachebene durchgesetzt werden, so daß dadurch synchronisierte Objekte entstehen. Der oben beschriebene wechselseitige Ausschluß entsteht bei einer reinen Read/Write-Semantik. Denkbar ist aber auch eine typspezifische Semantik die pro Typ bzw.

Methode geeignete Verfahren vorsieht, so daß zu einem Zeitpunkt auch mehr als ein Prozeß ein Objekt bearbeiten kann.

Für bestimmte Klassen von Anwendungen ist es sinnvoll, Daten über die Lebensdauer von Prozessen hinweg zu erhalten. In einem Finanzbuchhaltungssystem müssen z.B. die Daten, welche die Konten repräsentieren, auch über die Lebensdauer des Systems erhalten bleiben.

Wie oben erwähnt, sind bei einem objektorientierten Konzept die Objekte als Informationsträger anzusehen. Daher stellt sich die Aufgabe, genau die Objekte, welche zu längerfristigen Speicherung bestimmte Daten enthalten, zu speichern und bei Bedarf wieder zu aktivieren. Zur Speicherung der Objekte sind in der Literatur viele Strategien diskutiert worden [BlZd87; PeSt87; ZSR86]. So ist es z.B. denkbar, pro Objekt eine Datei anzulegen, in welcher die Attribute abgelegt sind. Durch die üblichen Zugriffsmechanismen der Dateiverwaltung sind Speicherung und Aktivierung leicht möglich. Zur Steigerung der Effizienz können die Attribute auch in Datenbanken gespeichert werden. Durch objektorientierte Datenbanken ist es sogar möglich, auf die sonst notwendige Abbildung der Attribute auf einen Datensatz zu verzichten. Objekte, deren Lebensdauer die einer Applikation übersteigt, werden im folgenden als langlebige, alle anderen als kurzlebige oder transiente Objekte bezeichnet. Wird durch das Sprachsystem ein transparenter Zugriff auf langlebige Objekte zugesichert, ohne daß dazu explizite E/A-Operationen und ein Linearisieren der Datenstrukturen nötig sind, spricht man von persistenten Objekten. Die Unterstützung der Langlebigkeit bzw. der Persistenz induziert allerdings nicht notwendigerweise auch die Existenz von Mechanismen zur Synchronisation oder zur Recoveryfähigkeit von Objekten. Zusammenfassend läßt sich also sagen, daß die Unterstützung von persistenten Objekten durch ein Sprachsystem im wesentlichen folgende Vorteile mit sich bringt:

- Wie oben erwähnt, stellen persistente Objekte eine elegante Möglichkeit dar, den Applikationszustand, also das Ergebnis einer Folge von Berechnungen, über die Lebensdauer des erzeugenden Prozesses hinweg zu sichern.
- Speicherung und Wiederherstellung langlebiger Objekte werden transparent durch das System vorgenommen, so daß der Programmierer von der Aufgabe befreit ist, explizite Ein/Ausgabe Operationen, wie z.B. "read"/"write" Aufrufe, in der Anwendung zu benutzen [Björ88; KPB88].
- Die Langlebigkeit ist in das objektorientierte Paradigma eingeführt und fügt sich so in die gewohnte Sprachumgebung ein, so daß der Programmierer zur Speicherung von Daten nicht mehr gleichzeitig verschiedene Konzepte, wie z.B. Objekt E/A und Objektzugriffe, in seiner Anwendung integrieren muß, sondern vielmehr nur noch mit einem einzigen, transparent vom System zur Verfügung gestellten Mechanismus, konfrontiert wird.

Das oben diskutierte Konzept der Persistenz von Objekten reicht aber nicht aus, um die Konsistenz der Objekte bzw. der Attribute auch im Fehlerfall zu garantieren. Das dafür nötig Charakteristikum ist die in diesem Abschnitt beschriebene Atomarität. Zusätzlich ist man aber auch an den oben erwähnten synchronisierten Objekten interessiert. Es liegt nun nahe, die Konzepte des objektorientierten Paradigmas mit einem verallgemeinerten Transaktionsmechanismus zu verbinden, um damit die Erstellung verläßlicher, verteilter Anwendungen zu vereinfachen. Gerade die Fähigkeit, Objekte als Einheit innerhalb von Transaktionen zu bearbeiten, hat robuste Systeme wie zum Beispiel Argus [LCJS87], Avalon [WiHe87], Arjuna [DPSW89] oder PROFEMO [NGJK85] hervorgebracht. Aus der Synthese der Eigenschaften von persistenten und synchronisierten Objekten mit Transktionen ergeben sich die sogenannten atomaren Objekte. Für diese Klasse von Objekten gelten die oben aufgezählten Eigenschaften von Transaktionen. Zusätzlich zur Persistenz sind außerdem Mechanismen zum synchronisierten gemeinsamen Zugriff vorhanden.

Die Gesamtheit aller im System vorkommenden Objekte bilden den globalen Objektraum.

Die Menge aller auf einer Stelle im System verfügbaren Objekte wird als der lokale Objektraum bezeichnet. Hierbei wird angenommen, daß ein Objekt immer vollständig auf einer Stelle vorhanden ist. Denkbar ist aber auch, daß das System fragmentierte Objekte zuläßt, so daß Teile eines Objektes zu einem Zeitpunkt in mehreren disjunkten Adreßräumen liegen können. Diese Sichtweise erschwert allerdings die Verwaltung von Objekten nicht unerheblich, insbesondere unter dem Gesichtspunkt der angesprochenen Konsistenzkriterien, weswegen dieser Ansatz hier nicht weiter verfolgt werden soll, obwohl er konzeptionell nicht ausgeschlossen wird [Shap89]. Ein Objektzustand wird häufig auch als Objektversion bezeichnet. Unter der Annahme einer zugrundeliegenden Transaktionsverwaltung werden die von einer Transaktion vorgefundenen Objektzustände als before images und die Objektzustände, die die Wirkung einer Transaktion widerspiegeln, als after images bezeichnet.

Die Konstruktion verteilter Anwendungen wird durch das Fehlen eines gemeinsamen, globalen Speichers erheblich erschwert. Der (nicht vorhandene) gemeinsame Speicher läßt sich als zwischen den Stellen fragmentiert betrachten. Jedes Fragment enthält einen Teil des gemeinsamen Zustands bzw. einen Teil des gemeinsamen Systemgedächtnisses. Der Fortschritt des Systems wird sich in Folgen von veränderten Objektversionen ausdrücken.

Um in einer solchen Umgebung Objekte verwalten zu können, werden geeignete Systeme konstruiert, die auch als Objektverwaltungssysteme bezeichnet werden. Diese ähneln Dateisystemen, die in konventionellen Systemen Verwendung finden, unterscheiden sich jedoch im wesentlichen in drei Punkten:

- In Dateisystemen sind die zu verwaltenden Einheiten Dateien. In Objektverwal- tungssystemen jedoch langlebige, typisierte Objekte.
- In Objektverwaltungssystemen sind die im Zusammenhang mit der Ausführung von Methoden auf langlebigen Objekten notwendigen Kopierarbeiten zwischen dem zur längerfristigen Speicherung von passiven Objekten dienenden Hintergrundspeicher und dem Haupt- bzw. virtuellen Speicher transparent für den jeweiligen Anwender. Es werden also von der Anwendung keine expliziten Ein/Ausgabe-Operationen verlangt.
- Aktive Objekte, die im Hauptspeicher eines Knoten liegen, sollen von anderen, parallel laufenden Prozessen mit disjunkten Adreßräumen gleichzeitig genutzt werden können.

Sichert das Objektverwaltungssystem Fehlertoleranz zu, ist damit immer ein Trade-off verbunden, da der Vorteil der Konsistenzerhaltung durch einen erhöhten Verwaltungsaufwand erkauft wird. Dies ist nicht für alle Anwendungsbereiche tolerierbar. Daher sollte das System so flexibel sein, daß verschiedene Objektarten zur Verfügung gestellt werden und der Pro- grammierer, je nach Bedarf, die für ihn optimale Variante wählen kann. Ein Objektverwaltungssystem sollte daher mindestens die folgenden Objektarten anbieten:

- Transiente Objekte: kurzlebige, prozeßlokale Objekte
- Persistente Objekte: langlebige, den erzeugenden Prozeß überlebende Objekte
- Atomare Objekte: Persistente, synchronisierte und recoveryfähige Objekte, die im Rahmen von Transaktionen manipuliert werden und für die das System die Gewährleistung der Konsistenz im Fall von Fehlern zusichert.

Um atomare Objekte auf Programmiersystemebene verwalten zu können, ist es notwendig, das Konzept der Transaktionen in die zugrundeliegende Sprache zu integrieren. Die oben beschriebenen Systeme (Argus, Arjuna) erreichen dies durch eine feste Bindung zu einer Sprache. In Arjuna wird z.B. jeder Methodenaufruf als eigene Transaktion angesehen. Diese starre Bindung hat sich als sehr unflexibel und für ein allgemeines Konzept als nicht geeignet herausgestellt. Das COMANDOS-Modell erlaubt dagegen eine wählbare Menge von Operationen als Transaktion auszuführen. Durch eine offene Systemarchitektur werden die Konzepte außerdem mehr als einer Sprache zur Verfügung gestellt.

Das RelaX-System macht keine Zusagen bzgl. der Konsistenz von nicht-atomaren Objekten. Zwar kann auch auf nicht-atomare Objekte innerhalb von Transaktionen zugegriffen werden, nur für atomare Objekte gilt aber die Zusicherung der Atomarität im Fehlerfall sowie der Atomarität der Wirkung. Außerhalb von Transaktionen kann nur lesend auf atomare Objekte zugegriffen werden, ohne dabei die Konsistenzkriterien zu verletzen.

Dem Grundkonzept jeder Stelle im RelaX-System (wie auch bei PROFEMO) liegt die in Abbildung 7 dargestellte Speicherstruktur zugrunde. Die Wechselwirkungen zwischen den einzelnen Speicherkomponenten werden anhand des Objektversionenflusses verdeutlicht.

Abbildung in dieser Leseprobe nicht enthalten

Abb. 7: Speicheraufbau und Fluß der Objektversionen

Im permanenten Speicher ist für jedes persistente Objekt eine Version abgespeichert, die aus einer erfolgreich abgeschlossenen Transaktion resultiert. Langlebige Objekte werden zum Zweck der Passivierung auf diesen Hintergrundspeicher transferiert (Passivieren). Der permanente Speicher ist so konstruiert, daß auftretende Fehler aus den Fehlerklassen, die durch das zugrundeliegende Fehlermodell definiert sind, seine Konsistenz nicht gefährden. Ein persistentes Objekt existiert solange, bis es explizit gelöscht wird. Transiente Objekte werden nach Definition spätestens bei Beendigung des erzeugenden Prozesses zerstört, evtl. aber auch früher.

Zur Ausführung von Operationen auf Objekten werden diese in den Hauptspeicher, auch aktiver Objektspeicher genannt, geladen (A ktivieren), da letztlich nur hier eine Abarbeitung möglich ist. Permanenter Speicher und aktiver Objektspeicher bilden zusammen den Objektspeicher. Durch die Teilung des Objektspeichers kann es vorkommen, daß Objekte zu einem Zeitpunkt zwei Repräsentationen besitzen, eine im aktiven und eine im permanenten Speicher. Ein langlebiges Objekt, welches im aktiven Speicher eine Repräsentation besitzt, bezeichnet man als aktives Objekt, alle anderen langlebigen Objekte als passive Objekte. Wird auf einem aktiven Objekt eine Operation ausgeführt, so wirken sich dabei eventuelle Änderungen nur auf die Objektrepräsentation im aktiven Speicher aus.

Aufgrund der unterschiedlichen Fehlertoleranzeigenschaften der beiden Speicherbereiche ist es daher sinnvoll, die Repräsentation auf dem permanenten Speicher zu bestimmten Zeitpunkten zu aktualisieren. Objekte aus dem aktiven Speicher können als Ergebnis von Entscheidungen der virtuellen Speicherverwaltung auf den Hintergrundspeicher ausgelagert werden. Dies geschieht in der Regel transparent für die Applikation. Dieser Vorgang ist jedoch, nicht zuletzt wegen der unterschiedlichen Fehlertoleranzeigenschaften der beiden Speicher, von der eigentlichen Passivierung eines Objektes wohl zu unterscheiden. Man nimmt weiterhin an, daß die im aktiven Speicher befindliche Information durch einen Stellenfehler verloren geht.

Der Recovery-Speicher enthält für jedes langlebige, aktive Objekt Informationen, die im Fall von Transaktionsfehlern benötigt werden. Das Ziel dieses Speichers ist es, in der Lage zu sein, im Falle eines Transaktionsfehlers die before-images wiederherzustellen. Um dies zu erreichen, wird, bevor eine Transaktion schreibend auf ein Objekt zugreift, der Objektzustand vor der Modifikation, das before-image, im Recovery-Speicher abgelegt (Save). Tritt nun der Fall ein, daß die Transaktion fehlschlägt, kann die ursprüngliche Objektversion zurückgewonnen werden (Restore). Im Gegensatz zu anderen Systemen, z.B. Datenbanken, ist der Recovery-Speicher in RelaX Teil des virtuellen Speichers. Es wird daher angenommen, daß der Inhalt dieses Speichers durch einen Stellenfehler verloren geht.

Der Log-Speicher enthält alle Informationen, die nötig sind, um nach einem Stellenfehler eine Restart-Operation abzuarbeiten, so daß das System dadurch wieder in einen konsistenten Zustand überführt werden kann (Neustart). Diese Informationen werden während der Abarbeitung der Protokolle, die zur Durchführung einer Transaktion nötig sind, auf den Log-Speicher geschrieben (Sicheres Speichern). Wie auch der permanente Speicher wird der Log-Speicher als ein stabiler Speicher angesehen, der Stellen- und Medienfehler in einem konsistenten Zustand überleben kann.

Um mit atomaren Objekten verteilte Anwendungen erstellen zu können, sind geeignete Konzepte zur Benutzung, zur Verwaltung und zur Speicherung von solchen Objekten zu entwerfen. Für die Benutzung von atomaren Objekten sind zum einen programmiersprachliche Aspekte zu behandeln. Neue Sprachen müssen entwickelt oder bestehende Sprachen um das Paradigma der Atomarität und der Persistenz erweitert werden, um dem Entwickler verteilter Anwendungen eine möglichst einfache und sichere Basis zur Bereitstellung der Fehlertoleranz bzw. der Langlebigkeit anbieten zu können. Zum anderen wiederholen sich die Probleme, die bei der Erstellung objektorientierter verteilter Anwendungen entstehen. Es bietet es sich daher an zur Lösung gleichartiger Probleme Softwareeinheiten zu schaffen, die Dienste erbringen, die es ermöglichen, atomare und persistente Objekte in einer sprachunabhängigen Weise darzustellen und zu verwenden. Außerdem ist es vorteilhaft Lösungsansätze für eine Mehrsprachenumgebung zu entwerfen, so daß Programme verschiedener Sprachen den selben Objektraum benutzen können. Dadurch wird einerseits eine möglichst breite Basis von potentiell verwendbaren Sprachen geschaffen, andererseits ist die Portabilität und die Austauschbarkeit der Dienste möglich, so wie dies für verteilte Systeme gefordert wird [Mull89].

Der in dieser Arbeit beschriebene Active Object Manager AOM erbringt als Teil des RelaX-Systems die eben beschriebene sprachunabhängige Verwaltung von atomaren Objekten des globalen Objektraums und ermöglicht, in Verbindung mit einer entsprechenden Sprachanbindung, die Erstellung von verläßlichen, verteilten Anwendungen.

1.4. Systemarchitektur

Zunächst soll diskutiert werden, wie eine systemseitige Unterstützung verläßlicher verteilter Applikationen in die Systemarchitektur eingebracht werden kann. Abbildung 8 zeigt die generische Struktur eines modernen verteilten Systems, welches aus n Stellen bestehen soll.

Abbildung in dieser Leseprobe nicht enthalten

Abb. 8: Architektur eines modernen verteilten Systems

Die Knoten sind durch ein geeignetes Kommunikationsmedium miteinander verbunden. Das m -Kern Betriebssystem, z.B. Mach [OSF89], Amoeba [Tane90] oder Chorus [SPG91], bietet über eine Schnittstelle zur Systemprogrammierung nur die Basisfunktionalität an, die zum minimalen Rechenbetrieb auf jeder Stelle vorhanden sein muß. Dies ist in der Regel die Speicherverwaltung, die E/A-Steuerung, die Interprozeßkommunikation und Teile der Prozeßverwaltung (Threads). Alle weiteren und zusätzlichen Funktionen des Betriebssystems werden durch sogenannte "Server Prozesse" realisiert, die als Anwenderprozesse laufen. Ein Server ist hier ein Subsystem, welches einen bestimmten Service an vorher unbekannte Benutzer anbietet. Ein Service ist dabei eine Funktion, die auf einer oder mehr Maschinen läuft. Ein Server ist also die Servicesoftware, die auf einer bestimmten Maschine ausgeführt wird [Gosc91]. Im folgenden werden die Begriffe "Server", "Manager" und "Verwalter" als Synonyme benutzt. Beispiele für einige mögliche Server sind File-Server, Print-Server und Name-Server. Server bilden die Basis für das Client-Server Modell, welches nach allgemeiner Meinung auf Betriebssystemebene das wichtigste Paradigma für Prozeß-Interaktionen in verteilten Umgebungen darstellt [Gosc91; Mull89]. Die vorhandenen Server bieten den Applikationen ihre Funktionalität mittels einer Schnittstelle zur Anwendungsprogrammierung an, die für den Benutzer die sichtbare Schnittstelle des Betriebssystem darstellt. Die in Kapitel 1.1 diskutierten Transparenzeigenschaften verteilter Systeme lassen sich einfach in Form von geeigneten Servern implementieren und erhöhen so die Erweiterbarkeit, Verifizierbarkeit und die Modifizierbarkeit des Betriebssystems.

Da moderne Speicherverwaltungstechniken Grundlage für die Realisierung des Objektmodells von RelaX sind, wird im folgenden das Konzept der virtuellen Speicherverwaltung des Mach 3.0 m-Kern Betriebssystems näher erläutert [RTY88].

Als aktive Einheit stellt eine Task eine Ausführungsumgebung dar, in der Ressourcen alloziiert werden können . Der Adreßraum einer Task besteht aus disjunkten Regionen, welche Folgen von virtuellen Adressen eines Prozesses repräsentieren und deren Länge ein Vielfaches der Seitengröße ist, die von der unterliegenden Architektur unterstützt wird. Für jede Region können Schutzattribute, wie Schreib-, Lese- und Ausführungsrechte, aber auch Vererbungsattribute vergeben werden. Alle Regionen eines Adreßraums werden durch eine Adreßabbildung (address map) beschrieben. Jeder Eintrag dieser Abbildung beschreibt die Bindung einer Region zu einem Speicherobjekt . Ein Speicherobjekt ist eine auslagerbare Einheit von Daten, bestehend aus einer Menge von Seiten, die an einen Hintergrundspeicher gebunden ist. Damit realisiert ein Speicherobjekt einen Cache für ein auf dem Hintergrundspeicher existierendes Objekt. Außerdem ist einem Speicherobjekt ein Pager zugeordnet, der für die Behandlung von Seitenfehlern und Anforderungen zur Auslagerung von Daten verantwortlich ist. Ein External Pager ist ein Pager, der als Serverprozeß außerhalb des Betriebssystemkerns läuft. External Pager, die auf verschiedenen Stellen in einem verteilten System implementiert sind, können durch ein geeignetes Protokoll kooperieren, um zusammen einen verteilten virtuellen Adreßraum bereitzustellen4 [RTY88].

Um den Erfordernissen eines auf Sharing basierenden Kooperationsmodelles zu genügen, wird von Mach und anderen m-Kern Betriebssystemen Memory Sharing, d.h. das gemeinsame Benutzen von Daten, für Prozesse unterstützt.

Unter Verwendung virtueller Speicherverwaltungstechniken neuerer UNIX ähnlicher Systeme, wie z.B. OSF/1 [OSF89], Chorus [SPG91] oder Amoeba [Tane90] wird in RelaX sowohl ein schneller Recoverymechanismus als auch eine effiziente Implementierung eines Commitprotokolls5 (2-Phase-Update) zur Verfügung gestellt. Beide Bereiche zusammen bilden dabei die Basis des benutzten Transaktionskonzeptes. Im folgenden sollen zwei

Komponenten von RelaX, der Transaktions-Manager (TM), sowie die sogenannten Ressource-Manager (RM) im allgemeinen und der Transactional Object Manager (TOM) im besonderen, vorgestellt und in Beziehung zum AOM gestellt werden. Das folgende Bild gibt einen Überblick über die Architektur einer einzelnen Stelle im RelaX-System.

Abbildung in dieser Leseprobe nicht enthalten

Abb. 9: RelaX-Architektur

Der Transaktionsmechanismus ist in einen Server ausgelagert, der mit den Ressource-Managern über eine standardisierte Schnittstelle kommuniziert und so in dem oben beschriebenen Sinne einen Transaktionsservice anbietet. Der Transaktions Manager bietet Funktionen, mit deren Hilfe ein verteiltes und sicheres Transaktionsmanagement ermöglicht wird, ohne daß interne Kenntnisse der zu bearbeitenden Ressourcen nötig sind. Die Verwaltung umfaßt sowohl die Zuordnung von Prozessen zu Transaktionen, um einen Prozeßfehler auf einen Transaktionsfehler abbilden zu können, als auch die Zuordnung von modifizierten Daten zu den entsprechenden Transaktionen. Pro Knoten ist nur ein Transaktions-Manager vorhanden, der alle vorhandenen Ressource-Manager einer Stelle bedienen kann. Die zwischen einem Ressource-Manager und dem Transaktionsverwalter realisierte allgemeine Schnittstelle ist sprachunabhängig und stellt eine Obermenge der im c /Open Modell beschriebenen XA-Schnittstelle [XA91] dar. Einzelheiten des Protokolls sind nicht Thema dieser Arbeit. Für genauere Informationen zu diesem Aufgabenkomplex ist daher auf [Hein93; KMSL90; X/Op91; Schu92] verwiesen. Alle Transaktions-Manager des Systems kommunizieren über ein Reliable Broadcast Protocol (RBP), damit sie die geschachtelten und verteilten Transaktionen geeignet verwalten können6. Insbesondere müssen die in eine verteilte Transaktion involvierten Transaktions-Manager einen gemeinsamen Konsens über den Ausgang der verteilten Transaktion finden. Weiterhin ist eine verteilte Datenstruktur zu verwalten, die die Abhängigkeiten von Transaktionen speichert, falls atomare Objekte vorzeitig freigegeben und weiter benutzt werden sowie dies durch das eingesetzte nicht-strikte Zwei-Phasen-Sperrprotokoll ermöglicht wird. Dies ist der sogenannte Recovery-Graph. Weitere und detaillierte Informationen zu diesem Thema finden sich in [KMSL90, Schu92].

Eine Applikation modelliert Transaktionen durch die Konstrukte Begin- Transaction und EndTransaction. Der vorzeitige Abbruch einer Transaktion wird durch das Konstrukt AbortTransaction angezeigt. Diese Operationen sind Bestandteil der TM-Schnittstelle. Das Erreichen des Lockpunktes innerhalb einer Transaktion kann dem Transaktions-Manager durch den Aufruf der Operation Set- LockPoint angezeigt werden. Der Transaktionsverwalter propagiert dieses Ereignis im Rahmen des TM-RM Protokolls an alle Ressource-Manager, die in die entsprechende Transaktion involviert sind.

Die Ressource-Manager verwalten beliebige globale Daten, die mittels Transaktionen verarbeitet werden. Damit realisiert jeder Ressourcenverwalter einen spezifischen Service, der durch eine geeignete Schnittstelle der Anwendungsprogrammierung zur Verfügung steht. Der Zugriff auf globale Daten eines oder mehrerer Ressourcenverwalter innerhalb von Transaktionen wird über die entsprechenden RM-Schnittstellen verwaltet. Ist eine Synchronisation von nebenläufigen Zugriffen auf gemeinsam benutzte Ressourcen notwendig, verwendet jeder Ressource-Manager ein geeignetes Protokoll. Typische Verwalter sind z.B. transaktionsorientierte Dateisysteme, Datenbanken oder Objektverwaltungssysteme, die atomare, persistente Objekte anbieten. Auf einem Knoten können gleichzeitig mehrere Ressource-Manager für unterschiedliche Aufgaben existieren, die aber nur durch einen einzigen Transaktionsverwalter koordiniert werden. Die beschriebene Struktur spiegelt die klare Trennung zwischen Transaktionsverwaltung und der Verwaltung von Daten, auf die Transaktionen zugreifen, wider und ist daher eine geeignete Basis zur Erzielung einer erweiterbaren Architektur.

Jeder Ressource-Manager, der die Spezifikation der Schnittstelle des Transaktions- managers einhält, kann in die oben beschriebene Struktur eingebettet werden. Zur Vereinfachung der Implementierung eines neuen Ressource-Managers werden im RelaX-System generische Software-Komponenten zur Verfügung gestellt [KMSL90; MKC92], deren Struktur in Abbildung 10 veranschaulicht wird.

Abbildung in dieser Leseprobe nicht enthalten

Abb. 10: Logische Struktur eines Ressource-Managers

Das den generischen Komponenten zugrundeliegende Schlüsselkonzept besteht in der Abstraktion vom eigentlichen Ressourcentyp und damit der Trennung, der für die Steuerung bzw. Verarbeitung von Transaktionen nötigen Operationen, von dem Inhalt bzw. der Verwaltung der Ressourcen. Ressourcen werden durch einen opaken Namen benannt, auf dem einige vordefinierte Operationen implementiert sein müssen, die von den anderen generischen Komponenten benutzt werden. Durch dieses Konzept entstehen wiederverwendbare Einheiten, die zur Konstruktion neuer Ressource-Manager geeignet sind.

Das Bild zeigt die Komponenten, die in generischer Form zur Verfügung stehen: Concurrency-Kontrolle, Recovery-Kontrolle, TM-RM Kontrolle und Generischer Log. In einem Ressource-Manager liegt ein hierarchischer Datenspeicher vor. Die untere Ebene enthält den Generischen Log [Wirz93] (siehe dazu auch Abb.7 auf Seite 21). Dieser ist ein stabiler Speicher und erhält seine Konsistenz daher auch beim Auftreten von Stellenfehlern. Der Log wird z.B. als Daten-Log verwendet, um die verwendeten Commit-Protokolle gegen Stellenausfälle abzusichern. Dazu müssen Protokollzustände und -daten sicher gespeichert werden. Wenn es zu einem Stellenausfall kommt, können dann bei einem Neustart die vorher noch nicht beendeten Protokolle zu Ende geführt werden. Die Durchsetzung der Transaktionseigenschaft macht dies erforderlich. Das TM-RM Modul [Hein93] implementiert die eigentliche Schnittstelle zwischen dem Transaktions-Manager und einem Ressource-Manager. Diese Schnittstelle ist für alle Ressourcen-Manager identisch. Die Concurrency-Kontrolle [Rade92] definiert eine Sperrenverwaltung für geschachtelte Transaktionen. Dazu wird die Vergabe von Sperren und ein Warteraum für die Prozesse, die auf die Vergabe von Sperren warten müssen, implementiert. Hierfür sind in der Literatur verschiedene Ansätze angegeben [MOO87; Mull89]. In RelaX wird standardmäßig ein nicht-striktes Zwei- Phasen-Sperrprotokoll verwendet, wobei eine Anpassung an andere Strategien vorgesehen ist. Weitere Einzelheiten dieses Konzeptes sind [KMSL90; MKC92; Zimm89] zu entnehmen.

Die lokale Recovery-Komponente [Rade92] verwaltet Recovery-Informationen für geschachtelte Transaktionen und unterstützt die Zustandsüberführung von Transaktionen in die Zustände committed und aborted. Zu diesem Zweck müssen zu jeder Transaktion die Recoverypunkte und die Abhängigkeiten zwischen den Transaktionen verwaltet werden, so daß im Falle eines Transaktionsfehlers das Before-Image wiedereingesetzt werden kann.

Außerdem müssen die After-Images von Transaktionen berechnet werden können, die bei einem Commit-Vorgang eingesetzt werden sollen.

Abbildung in dieser Leseprobe nicht enthalten

Abb. 11: Zugriffs- und Commit Folge

Abbildung 11 zeigt den Zustand einer Ressource, wenn Transaktionen darauf zugreifen und noch nicht committete Daten benutzen. Bei einem erstmaligen Zugriff auf eine Ressource wird der Zustand aus dem passiven Speicher gelesen. Der Zustand im passiven Speicher ist das Before-Image, während die Änderungen und damit das After-Image im aktiven Speicher stehen. Da das verallgemeinerte Transaktionskonzept von RelaX die vorzeitige Freigabe vorsieht, können nachfolgende Transaktionen auf den Zustand zugreifen, der bisher nur im virtuellen Speicher bekannt ist. Diese Daten sind gleichzeitig das After-Image der vorangegangenen Transaktion und dienen als Recoverypunkt für die nachfolgende Transaktion. Anders als in einigen Datenbanksystemen ist es nicht notwendig, die After- und Before-Images direkt auf den Log zu schreiben. Vielmehr stehen alle Modifikationen im aktiven Speicher, bis durch einen Commit-Vorgang der letzte aktuelle Zustand einer Transaktionsmenge, die in den Zustand committed überführt werden soll, im passiven Speicher eingesetzt wird.

Der in die RelaX-Architektur implementierte Transaktionsmechanismus wird auch im Rahmen des ESPRIT-Projekts COMANDOS verwendet [Espr90; KMSL90]. Mit RelaX wird ein modulares System zur Verfügung gestellt, welches die Erschließung anderer Anwendungsbereiche vereinfacht. Insbesondere sind die globale Transaktionsverwaltung und die Verwaltung von Ressourcen, die innerhalb von Transaktionen bearbeitet werden können, klar voneinander getrennt. Weitere wichtige Ziele für RelaX sind aber auch die (leichte) Erweiterbarkeit und die Portierbarkeit auf andere als Basis dienende Betriebssysteme. Die Architektur von RelaX wurde in Übereinstimmung mit dem c/Open Modell für verteilte Transaktionsverwaltung erstellt [X/Op91; XA91].

Die vorgestellten generischen Komponenten wurden im Rahmen von COMANDOS entwickelt und benutzt. Die COMANDOS Referenzplattform Amadeus [Amad92] wurde unter Benutzung dieser Komponenten mit dem RelaX-System zusammengeführt [MKC92].

Der Amadeus Objektverwalter fungierte dabei in jedem Knoten als Ressource-Manager.

Weiterhin konnte die Erweiterbarkeit und die Offenheit des RelaX-Systems dadurch demonstriert werden, daß parallel zu dem Amadeus Ressource-Manager das Informix RDBMS integriert wurde, und daß aus einem Programm heraus sowohl atomare Objekte als auch eine bestehende relationale Datenbasis transaktionsorientiert zu bearbeiten sind.

Im folgenden Unterkapitel wird der TOM als spezieller Objektverwalter des RelaXSystems vorgestellt und diskutiert. Dieser besitzt die in diesem Unterkapitel beschriebene Struktur und verwendet die generischen Komponenten.

1.5. Der RelaX Transactional Object Manager

Der RelaX Transactional Object Manager (TOM) ist ein spezieller Ressource-Manager, welcher gemeinsam benutzbare, atomare Objekte verwaltet und Applikationen bereitstellt. Er realisiert dabei ein transaktionsorientiertes Objektverwaltungssystem. Der TOM stellt einen systemweiten globalen Objektraum atomarer Objekte zur Verfügung und enthält Mechanismen zur Namensgebung, Objektlokalisierung und zum systemweiten Zugriff auf Objekte. Abbildung 12 zeigt die allgemeine Struktur des TOM im RelaX-System:

Abbildung in dieser Leseprobe nicht enthalten

Abb. 12: Struktur des RelaX Transactional Object Managers TOM

Im folgenden werden die Teilsysteme des TOM vorgestellt und in Beziehung zueinander gesetzt.

[...]


1 Dies wird auch als ´single point of failure´ oder auch als ´partial failure property´ bezeichnet.

2 Ein Beispiel eines verteilten Betriebssystems ist das V-System. Nach Mullender [Mull89] kann aber auch ein Ethernet mit Bridges als eine Art verteiltes System bezeichnet werden.

3 Die Wiederherstellung eines konsistenten Zustandes eines (verteilten) Systems nach einem Fehler wird als Recovery bezeichnet.

4 Dies ist auch als 'distributed virtual memory´ bekannt.

5 Ein Commitprotokoll ist ein Algorithmus für eine Menge von Prozessen auf verschiedenen Stellen, zur Herbeiführung von Entscheidungen, insbesondere über den Ausgang von Transaktionen.

6 Das RBP dient außerdem der Erkennung von Stellenfehlern und der Reintegration ausgefallener Stellen.

Ende der Leseprobe aus 181 Seiten

Details

Titel
Sprachunabhängige Verwaltung von atomaren Objekten des RelaX-Objektraums
Hochschule
Rheinische Friedrich-Wilhelms-Universität Bonn  (GMD Sankt Augustin)
Note
Sehr gut
Autor
Jahr
1993
Seiten
181
Katalognummer
V3552
ISBN (eBook)
9783638121941
Dateigröße
1524 KB
Sprache
Deutsch
Anmerkungen
Die vorliegende Diplomarbeit wurde im Rahmen des Projekts RelaX (Reliable distributed applications support on UNIX) der Gesellschaft für Mathematik und Datenverarbeitung mbH (GMD)in Sankt Augustin angefertigt. Inhalt des Projekts ist die Entwicklung von Konzepten, Prototypen und Evaluationswerkzeugen, die die Erstellung verläßlicher, verteilter Applikationen erleichtern und beim Auftreten von Hardware- und Kommunikationsfehlern sowie bei bestimmten logischen Fehlern flexibel reagieren. Als wesentliche Anwendungsgebiete von RelaX sind integrierte Informationssysteme in Bereichen wie CAD, Software Engineering, Bürosysteme und CIM anzusehen. Durch einen innovativen Ansatz werden Konzepte aus den Bereichen Betriebssysteme, Programmiersprachen und Datenbanken in RelaX vereint. Die Entwicklung neuer Anwendungen wird durch persistente Objekte unterstützt, die auf mehreren Stellen verteilt sein können und mittels Transaktionen bearbeitet werden, um gemeinsame Objektbenutzung und Fehlersituationen einfach und sicher handhaben zu können.
Schlagworte
Objektorientiert, Verteilte Betriebssysteme
Arbeit zitieren
Michael Wack (Autor:in), 1993, Sprachunabhängige Verwaltung von atomaren Objekten des RelaX-Objektraums, München, GRIN Verlag, https://www.grin.com/document/3552

Kommentare

  • Noch keine Kommentare.
Blick ins Buch
Titel: Sprachunabhängige Verwaltung von atomaren Objekten des RelaX-Objektraums



Ihre Arbeit hochladen

Ihre Hausarbeit / Abschlussarbeit:

- Publikation als eBook und Buch
- Hohes Honorar auf die Verkäufe
- Für Sie komplett kostenlos – mit ISBN
- Es dauert nur 5 Minuten
- Jede Arbeit findet Leser

Kostenlos Autor werden